Kubernetes - Custom Resources

0 0 0

Người đăng: Kiệt Tuấn

Theo Viblo Asia

Kubernetes Custom Resource là gì?

Dựa theo documents của hãng https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/

Thì chúng ta có thể hiểu 1 cách đơn giản : Custom resource là 1 phần mở rộng của Kubernetes API.

(Cần nắm rõ về K8S API, vì đây là component rất quan trọng của K8S)

Custom resource cho phép administrator định nghĩa và quản lý các loại resource mới không có sẵn trong mặc định Kubernetes.

Custom Resource giúp Kubernetes có thể mở rộng và tùy chỉnh theo nhu cầu cụ thể của ứng dụng hoặc hệ thống.

Mình có 1 bài toán nhỏ như này để giúp mọi người có 1 cái nhìn khách quan hơn vể Custom Resource.

Ví dụ : Chúng ta có khoảng 10 deployment, và mỗi 1 deployment này sẽ có 1 configmap tương ứng. Khi chúng ta thay đổi giá trị trong configmap, để deployment ăn được new config thì cần phải restart lại các pods trong dlp đó.

Số lượng dlp ít thì không sao, làm tay cũng được. Nhưng trong trường hợp vài chục dlp đi kèm cài chục configmap thì hơi oải.

Ok, vậy mình sẽ viết custom resource để nó sẽ thay mình check các thay đổi trong configmap và restart pods tương ứng.

  1. Tạo 1 configmap đơn giản :
apiVersion: v1
kind: ConfigMap
metadata: name: my-configmap namespace: default
data: app-config: "Hello, this is version 1"

image.png

  1. Tạo deployment :
apiVersion: apps/v1
kind: Deployment
metadata: name: app-deployment namespace: default
spec: replicas: 20 selector: matchLabels: app: app-configmap template: metadata: labels: app: app-configmap spec: containers: - name: app-container image: nginx:latest volumeMounts: - name: config-volume mountPath: /usr/share/nginx/html/index.html subPath: app-config volumes: - name: config-volume configMap: name: my-configmap

image.png

Mục đích là sẽ gán giá trị trong configmap my-configmap tạo ở trên vào /usr/share/nginx/html/index.html bên trong pod. Sau khi deploy thì ta check content trong index.html

image.png

  1. Bây giờ ta sẽ tạo CustomResourceDefinition (CRD)
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata: name: configmaprestarters.example.com
spec: group: example.com versions: - name: v1 served: true storage: true schema: openAPIV3Schema: type: object properties: spec: type: object properties: configMapName: type: string namespace: type: string scope: Namespaced names: plural: configmaprestarters singular: configmaprestarter kind: ConfigMapRestarter shortNames: - cmr

image.png

Define 1 chút về CRD trên nhé : Trong spec sẽ có những trường sau :

  • group: example.com -> Group sẽ được tạo trong API resource
  • name: v1 -> version của API
  • served: true storage: true -> API có được sử dụng không, có được lưu trữ không.
  • schema -> cấu trúc của CR với type là Object, và properties là configmapName và namespace.
  • scope: Namespaced -> CRD sẽ áp dụng trong namespace

Sau đó apply CRD này :

image.png

Check crd:

image.png

Có thể describe crd này để xem kỹ hơn :

image.png

Và chúng ta có thể check trong API resource :

image.png

  1. Tạo custom resource:
apiVersion: example.co/v1
kind: ConfigMapRestarter
metadata: name: restart-pod-on-config-change namespace: default
spec: configMapName: my-configmap namespace: default

image.png

Và apply nó thôi.

image.png

image.png

Như vậy là CR đã được map đến CRD ở trên.

  1. Viết 1 script check thay đổi configmap, ở đây mình dùng python:
from kubernetes import client, config, watch config.load_kube_config() v1 = client.CoreV1Api()
custom_api = client.CustomObjectsApi()
namespace = "default"
configmap_name = "my-configmap" def restart_pods(namespace, configmap_name): print(f"Restarting pods that use ConfigMap: {configmap_name}") pods = v1.list_namespaced_pod(namespace) for pod in pods.items: for volume in pod.spec.volumes: if volume.config_map and volume.config_map.name == configmap_name: print(f"Deleting pod: {pod.metadata.name}") v1.delete_namespaced_pod(pod.metadata.name, namespace) #Watch for changes in ConfigMap
def watch_configmap(namespace, configmap_name): w = watch.Watch() for event in w.stream(v1.list_namespaced_config_map, namespace=namespace): cm = event['object'] if cm.metadata.name == configmap_name: print(f"ConfigMap {configmap_name} has changed. Event: {event['type']}") restart_pods(namespace, configmap_name) if __name__ == "__main__": print(f"Watching ConfigMap: {configmap_name} in namespace: {namespace}") watch_configmap(namespace, configmap_name)

image.png

Cài đặt kubernetes library cho python :

pip install kubernetes

image.png

Run code :

image.png

Ok, bây giờ ta mở thêm 1 tab mới, và thực hiện thay đổi giá trị của configmap từ 1 -> 2

image.png

image.png

image.png

image.png

Và check file index.html trong các pod

image.png

OK, vậy là CR, CRD, scripts chạy ngon rồi.

Tiếp theo, ta sẽ đóng gói script này lại, và tạo 1 deployment để nó sẽ chạy giúp chúng ta.

  1. Build image và push lên dockerhub
FROM python:3.10-slim WORKDIR /app COPY check_cm_controller.py /app/check_cm_controller.py RUN pip install kubernetes CMD ["python", "check_cm_controller.py"]

image.png

image.png

image.png

  1. Tạo 1 deployment để chạy images này nào :
apiVersion: apps/v1
kind: Deployment
metadata: name: restart-controller namespace: default
spec: replicas: 1 selector: matchLabels: app: restart-controller template: metadata: labels: app: restart-controller spec: containers: - name: restart-controller image: kiettran164/crds:cm-controller imagePullPolicy: Always

image.png

và apply nó thôi. Rồi, lỗi rồi:

image.png

image.png

Và logs báo như sau : Traceback (most recent call last):

│ File "/app/check_cm_controller.py", line 4, in <module> │ config.load_kube_config() │ File "/usr/local/lib/python3.10/site-packages/kubernetes/config/kube_config.py", line 819, in load_kube_config │ loader = _get_kube_config_loader( │ File "/usr/local/lib/python3.10/site-packages/kubernetes/config/kube_config.py", line 776, in _get_kube_config_loader │ raise ConfigException( │ kubernetes.config.config_exception.ConfigException: Invalid kube-config file. No configuration found.

image.png

Nguyên nhân : Lỗi này xảy ra do controller đang chạy trong Pod, và kubeconfig (thường dùng cho kết nối local) không khả dụng bên trong container.

Chúng ta sẽ cần phải sửa lại code trong python.

image.png

Sửa thành : config.load_incluster_config()

image.png

Mục đích : cho phép script Python kết nối với Kubernetes API Server từ bên trong.

Xong build lại và push image lên Docker Hub again.

image.png

Từ đoạn này mình phải chuyển sang 1 cụm khác, vì proxy của cụm hiện tại đang lỗi.

  1. Cấp cho các con pod bên trong deployment check cm có quyền để đọc và xóa Pod, cũng như theo dõi ConfigMap. Để làm được điều này, ta cần tạo serviceaccount, role và role binding serviceaccount.yml
apiVersion: v1
kind: ServiceAccount
metadata: name: restart-controller-sa namespace: default

image.png

rbac-role.yml

apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: restart-controller-role namespace: default rules: - apiGroups: [""] resources: ["pods", "configmaps"] verbs: ["get", "list", "watch", "delete"] ---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata: name: restart-controller-rolebinding namespace: default
subjects: - kind: ServiceAccount name: restart-controller-sa namespace: default
roleRef: kind: Role name: restart-controller-role apiGroup: rbac.authorization.k8s.io

image.png

Apply thôi.

image.png

image.png

image.png

Rồi, h tạo deployment cho thằng check configmap thôi :

apiVersion: apps/v1 kind: Deployment metadata: name: restart-controller namespace: default spec: replicas: 1 selector: matchLabels: app: restart-controller template: metadata: labels: app: restart-controller spec: serviceAccountName: restart-controller-sa containers: - name: restart-controller image: kiettran164/crds:cm-controller-v2 imagePullPolicy: IfNotPresent

image.png

Apply nó, và cùng test nào.

image.png

Hiện tại mình có 20 con pod, và 1 pod sẽ làm nhiệm vụ check configmap. Đây là configmap hiện tại.

image.png H mình thực hiện thay đổi configmap này.

image.png image.png Và chờ xem thằng check config có chạy k nhé :

image.png Ten ten, đang xóa đi và tạo lại 1 loạt pods.

image.png Giờ check content trong index.html xem sao :

image.png

wasadm@masternode:~/crds/cm-controller$ kubectl exec -it app-deployment-79f7cfc658-26658 -- cat /usr/share/nginx/html/index.html

Hello, this is version 20

Vậy là thành công. Phần sau mình sẽ viết 1 Operator để kết hợp với thằng này. Chúc mọi người lab thành công.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Deploying A Containerized Web Application On Kubernetes

1. Overview. Kubernetes is an open source project (available on kubernetes.io) which can run on many different environments, from laptops to high-availability multi-node clusters; from public clouds to on-premise deployments; from virtual machines to bare metal.

0 0 55

- vừa được xem lúc

Kubernetes - Học cách sử dụng Kubernetes Namespace cơ bản

Namespace trong Kubernetes là gì. Tại sao nên sử dụng namespace.

0 0 113

- vừa được xem lúc

[Kubernetes] Kubectl và các command cơ bản

Mở đầu. Kubectl là công cụ quản trị Kubernetes thông qua giao diện dòng lệnh, cho phép bạn thực thi các câu lệnh trong Kubernetes cluster.

0 0 59

- vừa được xem lúc

Triển khai EFK Stack trên Kubernetes

EFK stack on K8S. Giới thiệu. Một hệ thống có thể chạy nhiều dịch vụ hoặc ứng dụng khác nhau, vì vậy việc. theo dõi hệ thống là vô cùng cần thiết.

0 0 72

- vừa được xem lúc

Thực hành Kubernetes (K8S) bằng cách sử dụng lệnh Command

Bài hướng dẫn hôm nay sẽ hướng dẫn sử dụng K8S bằng cách sử dụng câu lệnh thay vì UI trên web. Có 2 lựa chọn để thực hiện:. . Sử dụng Cloud Shell.

0 0 56

- vừa được xem lúc

Kubernetes best practices - Liveness và Readiness Health checks

Mở đầu. Kubernetes cung cấp cho bạn một framework để chạy các hệ phân tán một cách mạnh mẽ.

0 0 49