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ốnghostPath
– đâ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 và 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.