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: nginx và busybox. 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ề command và args:
- Nếu cả
commandvàargsđều không được chỉ định, cấu hìnhENTRYPOINTtrong Dockerfile sẽ được sử dụng. - Nếu
commandđược chỉ định nhưngargskhông, cấu hình mặc định của Dockerfile sẽ bị bỏ qua vàcommandsẽ được thực thi. - Nếu
commandkhông được chỉ định nhưngargscó, lệnhENTRYPOINTtrong Dockerfile sẽ được thực thi với các tham số từargs. - Nếu cả
commandvàargsđều được chỉ định, cấu hình Dockerfile sẽ bị bỏ qua,commandsẽ được thực thi vàargssẽ đượ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
postStartvàpreStop. - Kiểm tra
livenessProbevàreadinessProbe.
- Hook
- 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:
- Người dùng gửi thông tin Pod đến API Server.
- API Server tạo đối tượng Pod và lưu vào etcd.
- Các thành phần khác theo dõi thay đổi trên API Server.
- Scheduler tìm Pod mới và phân bổ Node, cập nhật thông tin lên API Server.
- Kubelet trên Node nhận Pod, cố gắng khởi chạy container và gửi kết quả về API Server.
- API Server lưu trạng thái Pod vào etcd.
Quá trình kết thúc Pod:
- Người dùng gửi lệnh xóa Pod đến API Server.
- Pod được đánh dấu là
terminatingtrong thời gian chờ (mặc định 30 giây). - Kubelet bắt đầu quá trình đóng Pod.
- Endpoint controller gỡ bỏ Pod khỏi danh sách endpoints của Service tương ứng.
- Nếu có hook
preStop, nó sẽ được thực thi. - Các tiến trình container nhận tín hiệu dừng.
- 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.
- 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.