[DevOps Series] Kubernetes – Phần 2

6 min read

Giới thiệu

Đây là bài viết thứ hai trong loạt bài Kubernetes của mình và trong bài viết này, mình sẽ giới thiệu ngắn gọn cho bạn về K8s workloadshoặc các thành phần chính. Trong các bài viết sau, mình sẽ thảo luận chi tiết hơn về từng thành phần và cách chúng ta có thể áp dụng chúng trong dự án K8 của mình.

Pod

Không giống như Docker, trong Kubernetes, thuật ngữ “Pod” được sử dụng để xác định đơn vị nhỏ nhất. Về cơ bản, một pod có thể có một hoặc nhiều container. Nhưng thông lệ chung là có một ứng dụng cho mỗi pod.

Mỗi pod trong node có địa chỉ IP riêng được lấy từ phạm vi CIDR của node[CIDR – viết tắt của Classless Inter Domain Routing, là một IP addressing scheme (phương pháp định vị địa chỉ IP) giúp cải thiện việc phân bổ địa chỉ IP]. Ngoài ra, một podsẽ nhận được một địa chỉ IP mới sau mỗi lần tạo lại.

Dưới đây bạn có thể thấy ví dụ mà mình dùng để tạo pod. Sau hoàn thành các cấu hình của file này, bạn có thể sử dụng lệnh kubectl apply -f để áp dụng nó. Đảm bảo các file config này được viết bằng YAML.

file name: sample-pod.yml

apiVersion: v1
kind: Pod
metadata:
  name: myapp
  labels:
    name: myapp
spec:
  containers:
  - name: myapp
    image: <Image>
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
    ports:
      - containerPort: <Port>

Deployment

Deployment được gọi là bản thiết kế của pod. Khi bạn cần tạo nhiều pods, chúng ta có thể sử các file config K8s Deployment để tạo chúng.

Dưới đây bạn có thể thấy ví dụ mà mình sử dụng để tạo K8s deployment. Trong file config, bạn có thể thấy mình đã sử dụng thuật ngữ “deployment” thay vì “pod”. Trong file confih này, chúng ta có các phần riêng biệt dành cho thông số kỹ thuật của pod và container.

Ngoài ra, fiel config cho deployment, chúng ta xác định container port mà chạy ứng dụng chạy trên port đấy. containerPort này tương ứng với K8 services có liên quan và bạn sẽ tìm thấy nó trong phần sau của bài viết này.

file name: sample-deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: <Image>
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: <Port>

ConfigMap & Secret

Trong Kubernetes, ConfigMaps giúp chúng ta lưu trữ các config bên ngoài như database credential. Nói chung, chúng ta sẽ kết nối configMap với một pod.

Trong configMap, chúng ta lưu trữ dữ liệu dưới dạng key: value và bên dưới bạn có thể lấy đoạn mã mẫu của configMap.

file name: sample-configmap.yml

apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp
data:
  key: value

Khi nói đến secrets trong Kubernetes, chúng ta sử dụng chúng để lưu trữ thông tin bí mật như tên người dùng và mật khẩu. Nhưng điều bạn cần lưu ý là chúng ta không thêm chúng ở dạng văn bản thuần túy mà lưu trữ các giá trị ở định dạng được mã hóa base-64. Bạn có thể dễ dàng chuyển đổi một từ văn bản thuần túy sang định dạng được mã hoá bằng base-64 bằng terminal như sau:

$ echo -n <your-word> | base64
eg:
echo -n mypass | base64
bXlwYXNz

Với configMaps, chúng ta kết nối các secrets đến deployment/pod. Ngoài ra, trong Kubernetes, chúng ta có cơ hội định cấu hình các secrets hoặc configMaps bên trong quá trình triển khai dưới dạng các biến môi trường thay vì tạo chúng dưới dạng các tệp riêng biệt. Ở đây bạn có xem ví dụ về K8s secret.

file name: sample-secret.yml

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  password: <Password>

Volumes

K8s volumes được sử dụng để lưu trữ dữ liệu và giữ chúng liên tục cho các ứng dụng có trạng thái (stateful app). Dưới đây là một số ví dụ về volumes.

  • emptyDir – đây là một thư mục trống
  • hostPath – đây là một thư mục nằm trên chính node đó
  • nfs 
  • azureDisk

Services

Trong Kubernetes có 3 loại services chính:

  • ClusterIP
  • NodePort (range: 30000–32767)
  • LoadBalancer

Không giống như pod, K8s services có địa chỉ IP public và IP này giúp truy cập ứng dụng từ bên ngoài. Trong khi Kubernetes service ClusterIP là loại địa chỉ mặc định và chúng ta có thể thay đổi loại thành NodePort hoặc LoadBalancer khi cần thiết.

Ngoài ra, chúng ta sử dụng K8s ingress để lấy lưu lượng truy cập từ bên ngoài trước rồi gửi đến service. Dưới đây, bạn có thể xem ví dụ về K8s service.

file name: sample-service.yml

apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  selector:
    app: myapp
  ports:
  - port: <Port>
    targetPort: <Target Port>

ReplicaSet

Chúng ta sử dụng ReplicaSets để đảm bảo số lượng pods mong muốn sẽ chạy bên trong node. Chúng ta có thể sử dụng trường deployment replicas để xác định số lượng pods mà chúng ta cần.

DaemonSet

Kubernetes DaemonSet ược sử dụng để tạo một pod trong mỗi node bên trong cluster. Dưới đây bạn có thể xem một số trường hợp điển hình khi chúng ta sử dụng Daemonset.

  • Chạy một logs collection daemon trên mỗi node, chẳng hạn như Fluentd hoặc logstash.
  • Chạy một trình nền lưu trữ cluster(cluster storage daemon), chẳng hạn như glusterd ceph trên mỗi node.
  • Chạy một node monitoring daemon trên mỗi node, chẳng hạn như Prometheus Node Exporter, collectd, Datadog agent, New Relic agent, hoặc Ganglia

StatefulSet

StatefulSet tạo các pods đặc biệt mà chúng ta có thể gán tên thứ tự duy nhất cho mỗi node. Trong trường hợp chung, pod có một giá trị ngẫu nhiên ở cuối tên và giá trị này thay đổi trong mỗi lần tái tạo node. Vì vậy, thật khó để đoán pod nhóm hoàn chỉnh.

Trong những tình huống như vậy, chúng ta có thể sử dụng StatefulSet của K8s và nó giúp chỉ định một tên pod duy nhất , pod mới sẽ có cùng tên với pod trước đó. Định dạng tên pod là <statefulset-name>-<ordinal-index>.

Nếu chúng ta xác định 3 replicas trong file config deployment và khi chạy lệnh apply nó, cả 3 pod sẽ được tạo một lần. Nhưng khi bạn sử dụng StatefulSet, nó sẽ lần lượt tạo ra 3 pods đó.

StatefulSets về cơ bản được sử dụng để lưu trữ liên tục để khi pod xuất hiện sau khi gặp sự cố, nó có khả năng tự động kết nối với trạng thái trước đó.

Một số trường hợp sử dụng StatefulSets là:

  • Triển khai một clustered resource (ví dụ: Cassandra, Elaticsearch)
  • Các ứng dụng bằng cách nào đó phụ thuộc lẫn nhau

Sau đây là ví dụ về StatefulSet

file name: sample-statefulset.yml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mystatefulset
spec:
  selector:
    matchLabels:
      app: myapp
  serviceName: <ServiceName>
  replicas: 2
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: registry.k8s.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

Job

Các K8s Jobs được sử dụng để chạy đúng một task nhất định để hoàn thành. Khi bạn có nhiều jobs, tất cả chúng có thể được sắp xếp để chạy song song bằng cách sử dụng parallelism. Không giống như pod, một job không chạy mãi mãi, nó chạy cho đến khi hoàn thành nhiệm vụ và sau khi hoàn thành, nó sẽ dừng quá trình của mình.

Baạn có thể xem ví dụ của Kubernetes Job.

file name: sample-job.yml

apiVersion: batch/v1
kind: Job
metadata:
  name: myjob
spec:
  ttlSecondsAfterFinished: 100
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never

CronJob

Chúng ta sử dụng K8s CronJobs để lên lịch 1 job và hoàn thành nó theo lịch trình nhất định. Ví dụ: chúng ta có thể lên lịch cho k8s job chạy hàng ngày, mỗi tháng một lần, v.v.

Trong bài tiếp theo, mình sẽ nói thêm về các lệnh Kubernetes cơ bản và tạo ứng dụng K8s đầu tiên.

Avatar photo

Clean Code: Nguyên tắc viết hàm trong lập trình…

Trong quá trình phát triển phần mềm, việc viết mã nguồn dễ đọc, dễ hiểu là yếu tố then chốt để đảm bảo code...
Avatar photo Dat Tran Thanh
3 min read

Clean Code: Nguyên tắc comment trong lập trình

Trong lập trình, code không chỉ là một tập hợp các câu lệnh để máy tính thực thi, mà còn là một hình thức...
Avatar photo Dat Tran Thanh
3 min read

Clean Code: Nguyên tắc xử lý lỗi (Error Handling)

Trong quá trình phát triển phần mềm, việc xử lý lỗi không chỉ là một phần quan trọng mà còn ảnh hưởng trực tiếp...
Avatar photo Dat Tran Thanh
4 min read

Leave a Reply

Your email address will not be published. Required fields are marked *