Tìm hiểu sâu về Pod trong Kubernetes

Mỗi Pod có thể chứa một hoặc nhiều container. Các container này được chia thành hai loại:

  • Container chứa ứng dụng người dùng: Số lượng có thể thay đổi.
  • Container Pause: Đây là "container gốc" mà mọi Pod đều có. Nó có hai chức năng:
    • Đóng vai trò là cơ sở để đánh giá tình trạng sức khỏe tổng thể của Pod.
    • Thiết lập địa chỉ IP cho Pod (Pod IP), mà các container khác sẽ chia sẻ, để thực hiện giao tiếp mạng nội bộ Pod.

Giao tiếp giữa các Pod được thực hiện thông qua công nghệ mạng lớp 2 ảo hóa, trong môi trường này thường sử dụng Flannel.

Định nghĩa Pod

Dưới đây là cấu trúc tài nguyên của một Pod:


apiVersion: v1     # Bắt buộc: Phiên bản API, ví dụ: v1
kind: Pod       # Bắt buộc: Loại tài nguyên, ví dụ: Pod
metadata:       # Bắt buộc: Siêu dữ liệu
  name: string     # Bắt buộc: Tên Pod
  namespace: string  # Không gian tên của Pod, mặc định là "default"
  labels:       # Danh sách nhãn tùy chỉnh
    - name: string
spec:  # Bắt buộc: Mô tả chi tiết các container trong Pod
  containers:  # Bắt buộc: Danh sách các container trong Pod
  - name: string   # Bắt buộc: Tên container
    image: string  # Bắt buộc: Tên image của container
    imagePullPolicy: [ Always|Never|IfNotPresent ]  # Chính sách kéo ảnh
    command: [string]   # Lệnh khởi chạy container. Nếu không chỉ định, sử dụng lệnh mặc định khi đóng gói.
    args: [string]      # Các tham số cho lệnh khởi chạy container.
    workingDir: string  # Thư mục làm việc của container.
    volumeMounts:       # Cấu hình mount các volume chia sẻ vào container.
    - name: string      # Tên volume chia sẻ được định nghĩa trong phần `volumes[]`.
      mountPath: string # Đường dẫn tuyệt đối mount volume trong container.
      readOnly: boolean # Chỉ đọc hay không.
    ports: # Danh sách các cổng cần mở.
    - name: string        # Tên cổng.
      containerPort: int  # Số cổng mà container cần lắng nghe.
      hostPort: int       # Số cổng mà host cần lắng nghe. Mặc định giống `containerPort`.
      protocol: string    # Giao thức cổng (TCP/UDP). Mặc định là TCP.
    env:   # Danh sách các biến môi trường cần thiết lập trước khi container chạy.
    - name: string  # Tên biến môi trường.
      value: string # Giá trị biến môi trường.
    resources: # Cấu hình giới hạn và yêu cầu tài nguyên.
      limits:  # Giới hạn tài nguyên.
        cpu: string     # Giới hạn CPU (đơn vị core).
        memory: string  # Giới hạn bộ nhớ (đơn vị Mib/Gib).
      requests: # Yêu cầu tài nguyên.
        cpu: string    # Yêu cầu CPU ban đầu khi khởi động.
        memory: string # Yêu cầu bộ nhớ ban đầu khi khởi động.
    lifecycle: # Các hook vòng đời.
        postStart: # Hook chạy ngay sau khi container khởi tạo.
        preStop: # Hook chạy ngay trước khi container bị dừng.
    livenessProbe:  # Kiểm tra sức khỏe của container.
      exec:       # Kiểm tra bằng lệnh exec.
        command: [string]  # Lệnh hoặc script cần thực thi.
      httpGet:       # Kiểm tra bằng HTTP GET.
        path: string
        port: number
        scheme: string
      tcpSocket:     # Kiểm tra bằng TCP socket.
         port: number
       initialDelaySeconds: 0       # Thời gian chờ ban đầu sau khi container khởi động.
       timeoutSeconds: 0    # Thời gian chờ phản hồi cho mỗi lần kiểm tra.
       periodSeconds: 0     # Khoảng thời gian giữa các lần kiểm tra.
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged: false
  restartPolicy: [Always | Never | OnFailure]  # Chính sách khởi động lại Pod.
  nodeName: <string> # Chỉ định Node để lên lịch Pod.
  nodeSelector: object # Chọn Node dựa trên nhãn.
  imagePullSecrets: # Bí mật dùng để kéo ảnh.
  - name: string
  hostNetwork: false   # Sử dụng mạng của host hay không.
  volumes:   # Danh sách các volume chia sẻ trong Pod.
  - name: string    # Tên volume chia sẻ.
    emptyDir: {}       # Volume loại emptyDir, tồn tại trong vòng đời Pod.
    hostPath: string   # Volume loại hostPath, mount thư mục từ host.
      path: string      # Đường dẫn thư mục trên host.
    secret:       # Volume loại secret.
      secretName: string
      items:
      - key: string
        path: string
    configMap:         # Volume loại configMap.
      name: string
      items:
      - key: string
        path: string

Trong Kubernetes, hầu hết các tài nguyên đều có các thuộc tính cấp cao giống nhau:

  • apiVersion: Phiên bản API.
  • kind: Loại tài nguyên.
  • metadata: Siêu dữ liệu (tên, không gian tên, nhãn, v.v.).
  • spec: Cấu hình chi tiết của tài nguyên.
  • status: Trạng thái của tài nguyên (do Kubernetes tự động tạo).

Thuộc tính spec là trọng tâm nghiên cứu, với các thuộc tính con phổ biến như:

  • containers: Danh sách các container và thông tin chi tiết của chúng.
  • nodeName: Chỉ định Node cụ thể để lên lịch Pod.
  • nodeSelector: Chọn Node dựa trên các nhãn được định nghĩa.
  • hostNetwork: Sử dụng chế độ mạng của host.
  • volumes: Thông tin về các volume được gắn vào Pod.
  • restartPolicy: Chính sách khởi động lại Pod khi gặp sự cố.

Cấu hình Pod

Phần này tập trung vào thuộc tính pod.spec.containers.

Cấu hình cơ bản

Tạo file pod-base.yaml:


apiVersion: v1
kind: Pod
metadata:
  name: pod-base
  namespace: dev
  labels:
    user: heima
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
  - name: busybox
    image: busybox:1.30

Pod này có hai container: nginxbusybox. Container busybox có thể gặp sự cố vì nó là một tập hợp các lệnh tiện ích và tự động thoát khi Kubernetes khởi động xong.


# Tạo Pod
kubectl apply -f pod-base.yaml
# Quan sát trạng thái Pod (READY 1/2 cho thấy một container đang gặp sự cố)
kubectl get pod -n dev
# Xem chi tiết Pod
kubectl describe pod pod-base -n dev

Kéo ảnh (Image Pull)

Tạo file pod-imagepullpolicy.yaml:


apiVersion: v1
kind: Pod
metadata:
  name: pod-imagepullpolicy
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    imagePullPolicy: Never # Chính sách kéo ảnh
  - name: busybox
    image: busybox:1.30

Các chính sách kéo ảnh:

  • Always: Luôn kéo ảnh từ kho lưu trữ từ xa.
  • IfNotPresent: Sử dụng ảnh cục bộ nếu có, nếu không thì kéo từ kho lưu trữ từ xa.
  • Never: Chỉ sử dụng ảnh cục bộ, không bao giờ kéo từ kho lưu trữ từ xa.

Mặc định:

  • Nếu tag ảnh là một phiên bản cụ thể, chính sách mặc định là IfNotPresent.
  • Nếu tag ảnh là latest, chính sách mặc định là Always.

# Tạo Pod
kubectl create -f pod-imagepullpolicy.yaml
# Xem chi tiết Pod để thấy quá trình kéo ảnh
kubectl describe pod pod-imagepullpolicy -n dev

Lệnh khởi chạy (Command)

Để giải quyết vấn đề container busybox không chạy, chúng ta cần đảm bảo nó luôn hoạt động bằng cách sử dụng command.

Tạo file pod-command.yaml:


apiVersion: v1
kind: Pod
metadata:
  name: pod-command
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done;"]

Lệnh này tạo một file /tmp/hello.txt và ghi thời gian hiện tại vào đó mỗi 3 giây.


# Tạo Pod
kubectl create -f pod-command.yaml
# Xem trạng thái Pod (cả hai container đều chạy bình thường)
kubectl get pods pod-command -n dev
# Vào container busybox để xem nội dung file
kubectl exec pod-command -n dev -it -c busybox /bin/sh

Lưu ý về commandargs:

  • Nếu cả commandargs đều không được chỉ định, cấu hình ENTRYPOINT trong Dockerfile sẽ được sử dụng.
  • Nếu command được chỉ định nhưng args không, cấu hình mặc định của Dockerfile sẽ bị bỏ qua và command sẽ được thực thi.
  • Nếu command không được chỉ định nhưng args có, lệnh ENTRYPOINT trong Dockerfile sẽ được thực thi với các tham số từ args.
  • Nếu cả commandargs đều được chỉ định, cấu hình Dockerfile sẽ bị bỏ qua, command sẽ được thực thi và args sẽ được thêm vào làm tham số.

Biến môi trường (Environment Variables)

Tạo file pod-env.yaml:


apiVersion: v1
kind: Pod
metadata:
  name: pod-env
  namespace: dev
spec:
  containers:
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","while true;do /bin/echo $(date +%T);sleep 60; done;"]
    env: # Danh sách biến môi trường
    - name: "username"
      value: "admin"
    - name: "password"
      value: "123456"

# Tạo Pod
kubectl create -f pod-env.yaml
# Vào container và kiểm tra biến môi trường
kubectl exec pod-env -n dev -c busybox -it /bin/sh

Lưu ý: Cách này không được khuyến khích, nên lưu cấu hình trong file riêng.

Giới hạn tài nguyên (Resource Quotas)

Sử dụng thuộc tính resources để giới hạn CPU và bộ nhớ cho container.

  • limits: Giới hạn tối đa tài nguyên mà container có thể sử dụng. Nếu vượt quá, container sẽ bị chấm dứt và khởi động lại.
  • requests: Yêu cầu tối thiểu tài nguyên cần thiết để khởi động container. Nếu không đủ tài nguyên, container sẽ không thể khởi động.

Tạo file pod-resources.yaml:


apiVersion: v1
kind: Pod
metadata:
  name: pod-resources
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    resources: # Phân bổ tài nguyên
      limits:  # Giới hạn (tối đa)
        cpu: "2" # Giới hạn CPU (core)
        memory: "10Gi" # Giới hạn bộ nhớ
      requests: # Yêu cầu (tối thiểu)
        cpu: "1"  # Yêu cầu CPU (core)
        memory: "10Mi"  # Yêu cầu bộ nhớ
  • CPU: Đơn vị là core, có thể là số nguyên hoặc thập phân.
  • Memory: Đơn vị có thể là Gi, Mi, G, M, v.v.

# Chạy Pod
kubectl create -f pod-resources.yaml
# Xem Pod
kubectl get pod pod-resources -n dev
# Xóa Pod
kubectl delete -f pod-resources.yaml
# Sửa đổi pod-resources.yaml để requests.memory thành 10Gi
# Chạy lại Pod
kubectl create -f pod-resources.yaml
# Xem trạng thái Pod (sẽ bị Pending do thiếu bộ nhớ)
kubectl get pod pod-resources -n dev -o wide
# Xem chi tiết Pod để thấy lý do lỗi
kubectl describe pod pod-resources -n dev

Vòng đời Pod

Vòng đời Pod bao gồm các giai đoạn từ khi tạo đến khi kết thúc, bao gồm:

  • Quá trình tạo Pod.
  • Chạy container khởi tạo (init container).
  • Chạy container chính (main container):
    • Hook postStartpreStop.
    • Kiểm tra livenessProbereadinessProbe.
  • Quá trình kết thúc Pod.

Pod có 5 trạng thái (pha):

  • Pending: Pod đã được tạo nhưng chưa được lên lịch hoặc đang tải ảnh.
  • Running: Pod đã được lên lịch trên một Node và tất cả các container đã được tạo.
  • Succeeded: Tất cả các container trong Pod đã kết thúc thành công và sẽ không được khởi động lại.
  • Failed: Tất cả các container đã kết thúc, nhưng ít nhất một container đã kết thúc không thành công (trả về mã lỗi khác 0).
  • Unknown: Không thể lấy trạng thái Pod, thường do lỗi mạng.

Tạo và Kết thúc

Quá trình tạo Pod:

  1. Người dùng gửi thông tin Pod đến API Server.
  2. API Server tạo đối tượng Pod và lưu vào etcd.
  3. Các thành phần khác theo dõi thay đổi trên API Server.
  4. Scheduler tìm Pod mới và phân bổ Node, cập nhật thông tin lên API Server.
  5. Kubelet trên Node nhận Pod, cố gắng khởi chạy container và gửi kết quả về API Server.
  6. API Server lưu trạng thái Pod vào etcd.

Quá trình kết thúc Pod:

  1. Người dùng gửi lệnh xóa Pod đến API Server.
  2. Pod được đánh dấu là terminating trong thời gian chờ (mặc định 30 giây).
  3. Kubelet bắt đầu quá trình đóng Pod.
  4. Endpoint controller gỡ bỏ Pod khỏi danh sách endpoints của Service tương ứng.
  5. Nếu có hook preStop, nó sẽ được thực thi.
  6. Các tiến trình container nhận tín hiệu dừng.
  7. Sau thời gian chờ, nếu Pod vẫn còn tiến trình chạy, nó sẽ bị chấm dứt ngay lập tức.
  8. Kubelet yêu cầu API Server đặt thời gian chờ về 0 để hoàn tất xóa. Pod không còn hiển thị với người dùng.

Thẻ: Kubernetes Pod container docker yaml

Đăng vào ngày 30 tháng 7 lúc 15:06