Những khái niệm cốt lõi trong Kubernetes (Phần 1)
Bài đăng này đã không được cập nhật trong 4 năm
Chào các bạn, ở bài viết Cảm ngộ ban đầu về Kubernetes trước, chúng ta đã tìm hiểu sơ lược, tổng quan về Kubernetes cũng như có một chút thực hành với Kubernetes trên local. Hôm nay, ở bài viết này, chúng ta sẽ cùng tìm hiểu sâu hơn một chút về các khái niệm cốt lõi (Core concept) trong Kubernetes.
1. Pods: Nơi mà các container được chạy lên
Pods là thành phần cơ bản nhất trong một hệ thống Kubernetes. Pods nằm trong các woker nodes là nơi chứa các container (một hay nhiều). Mỗi pods giống như một logic machine riêng biệt (có IP, hostname, tiếng trình riêng).
Tại sao chúng ta lại cần Pods ?
Tại sao lại cần có Pods, sao không chạy trực tiếp các container trong worker nodes đi ?
Thực ra Pods là một cấp độ cao hơn của container, nó có thể chứa nhiều container cùng xử lý một loại công việc. Các container sẽ có chung một địa chỉ IP, chia sẻ cùng 1 volume.
Cấu hình một Pods đơn giản
Để tạo một pods đơn giản trên cluster Kubernetes, chúng ta sẽ cấu hình các thông số của pods với file yml
hoặc json
tùy thích. Hãy chắc chắn bạn đã có 1 cluster Kubernetes (Trên local sử dụng minikube, chi tiết có trong phần demo của bài trước)
kubia-manual.yaml
apiVersion: v1
kind: Pod
metadata:
name: kubia-manual
spec:
containers:
- image: luksa/kubia
name: kubia
ports:
- containerPort: 8080
protocol: TCP
- apiVersion: version của Kubernetes API
- kind: Chỉ định thành phần cần tạo (ở đây là Pod)
- metadata: Tên của Pod
- spec: Mô tả về các thông số kỹ thuật của Pod
- container: chưa tên image của container cần chạy trong pod
- name: Tên container
- containerPort: Cổng đầu ra ứng dụng của container
Để tạo pods, chúng ta dùng lệnh kubectl create
kubectl create -f kubia-manual.yaml
Thông báo sẽ hiện ra ngay sau khi chạy lệnh
pod "kubia-manual" created
Kiểm tra pods:
kubectl get pods
NAME READY STATUS RESTARTS AGE
kubia-manual 1/1 Running 0 32s
Tổ chức pods với labels
Ở các hệ thống trung bình đến lớn, số lượng Pods được triển khai trên cluster Kubernetes lên đến hàng chục, thậm chi hàng trăm... Nếu không có cơ chế, giải pháp tổ chức tốt các pods với số lượng lớn như thế, chúng sẽ thành mớ bòng bong, hỗn độn dẫn đến mất rất nhiều công sức để quản lý. Với Labels, chúng ta có thể các pods thành các nhóm nhỏ hơn, giúp phần nào giải quyết vấn đề nêu trên.
Lưu ý: Labels có thể được đánh cho các node, chứ không chỉ dành riêng cho các pods.
Với các pods ở hình trên, chúng ta có thể tổ chức với việc gán 2 nhãn (labels) cho mỗi pods:
- app: Để chỉ ra pods thuộc phần nào trong ứng dụng như UI hay Order Service, ...
- rel: Để chỉ ra pods được dùng cho phiên bản nào của ứng dụng (stable, beta hay là canary).
Cấu hình pods với labels
apiVersion: v1
kind: Pod
metadata:
name: kubia-manual-v2
labels:
app: ui
rel: stable
spec:
containers:
- image: luksa/kubia
name: kubia
ports:
- containerPort: 8080
protocol: TCP
Khác với file yml cấu hình pods ở phần trên một chút. Ở phần metadata
chúng ta đã thêm vào phần labels cho pods.
Sau khi create pods bằng lệnh kubectl create -f
, chúng ta dùng lệnh:
kubectl get po --show-labels
Console sẽ hiển thị các pods với label tương ứng.
2. ReplicationControllers
Trong thực tế, các Pods khi được chạy trên các cluster Kubernetes hoàn toàn có thể bị lỗi, chết ngoắc một cách bất ngờ bởi nhiều lý do khác nhau. Với ReplicationControllers, nó sẽ đảm bảo sẽ tạo lại Pods mới thay thế khi Pods cũ bị lỗi (hay các node bị lỗi). Một cách đầy đủ hơn, ReplicationControllers sẽ duy trì số Pods đang chạy với số lượng được chỉ định trước (ít hơn thì tạo thêm pods mới, thừa thì xóa bớt pods đi).
Cấu trúc của ReplicationControllers
- label selector: Xác định pods mà Controller quản lý (theo labels)
- replica count: Số lượng pods cần duy trì
- pod template: Được hiểu là khuôn mẫu của pods để Controller sử dụng để tạo Pods mới khi cần.
Tạo một ReplicationControllers
Vẫn là cách quen thuộc, viết file yml
(hoặc json
) để cấu hình.
kubia-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: kubia
spec:
replicas: 3
selector:
app: kubia
template:
metadata:
labels:
app: kubia
spec:
containers:
- name: kubia
image: luksa/kubia
ports:
- containerPort: 8080
- kind: là kiểu ReplicationController
- replicas: 3 là số lượng pods cần duy trì
- app: kubia có nghĩa là áp dụng cho các Pods có labels
app: kubia
- template: là phần pod template, mô tả tên images, port để có thể chạy container trong pods lên.
Cuối cùng tạo ReplicationController với lệnh
$ kubectl create -f kubia-rc.yaml
replicationcontroller "kubia" created
Ok, giờ chúng ta sẽ xóa 1 Pods với lệnh
kubectl delete pod [tên-pod]
Gần như ngay lập tức sẽ có 1 Pods mới được tạo thành thay thế Pods vừa bị xóa.
3. Service: Cầu nối để các thành phần trong hệ thống Kubernetes tương tác với nhau
Như chúng ta đã biết, cách Pods có IP, hostname riêng chứa các container của ứng dụng. Client có thể kết nối đến các Pods để tương tác bằng IP hay hostname tương ứng. Tuy nhiên, có một vấn đề là các Pods có thể bị crash hay lỗi bất ngờ, khi ReplicationController tạo lại Pods mới thay thế thì các thông số như địa chỉ IP, hostname cũng thay đổi. Hơn nữa, một ứng dụng triển khai trên Kubernetes có nhiều Pods chạy cùng một lúc, client không nên và cũng không cần thiết lưu trữ 1 tá các địa chỉ IP, hostname của các Pods.
Và đây là lúc chúng ta cần đến Service
Kubernetes Service là một tài nguyên cho phép tạo một điểm truy cập duy nhất đến các Pods cung cấp cùng một dịch vụ. Mỗi Service có địa chỉ IP và port không đổi. Client có thể mở các kết nối đến IP và port của service, sau đó chúng sẽ được điều hướng đến các Pods để xử lý.
Tạo Service bằng cách cấu hình file yml
File kubia-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
- kind: Service thể hiển rằng thành phần cần tạo là Service
- port: 80 thể hiện rằng cổng tương tác với Service là cổng 80
- targetPort: 8080 là cổng của các container trong pods mà service sẽ điều hướng kết nối đến
- app: kubia (thuộc phần selector) thể hiển rằng service tương tác với các pods có labels là
app=kubia
Ở phần spec
chúng ta có thể thêm 1 trường nữa là type
biểu thể kiểu service cần dùng (mặc định là ClusterIP). Các loại Service bao goomf:
- ClusterIP: Service chỉ có địa chỉ IP cục bộ và chỉ có thể truy cập được từ các thành phần trong cluster Kubernetes.
- NodePort: Service có thể tương tác qua Port của các worker nodes trong cluster (sẽ giải thích kỹ hơn ở phần sau)
- LoadBlancer: Service có địa chỉ IP public, có thể tương tác ở bất cứ đâu.
- ExternalName: Ánh xạ service với 1 DNS Name
Tạo Service
kubectl create -f kubia-svc.yaml
Kiểm tra các service với lệnh
$ kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.111.240.1 <none> 443/TCP 30d
kubia 10.111.249.153 <none> 80/TCP 6m
Chúng ta hoàn toàn có thể config cho Service nhiều hơn 1 cổng, ở file dưới chúng ta config cổng tương tác của service cho giao thức http và https ứng với 2 cổng 8080 và 8443 trong container.
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
ports:
- name: http
port: 80
targetPort: 8080
- name: https
port: 443
targetPort: 8443
selector:
app: kubia
Service NodePort
Như ở trên, sau khi tạo Service và dùng lệnh kubectl get svc
để kiểm tra service vừa tạo thì chúng ta thấy rõ ràng có 2 thống số IP là CLUSTER_IP
và EXTERNAL_IP
có giá trị <none>
.
- CLUSTER_IP: Là địa chỉ IP cục bộ trong Cluster Kubernetes, với địa chỉ IP này thì các
Pods
hayServices
có thể tương tác với nhau nhưng bên ngoài sẽ không thể tác tương tác vớiService
thông qua nó được. - EXTERNAL_IP: IP public, có thể dùng để client bên ngoài (hoặc bất cứ đâu) tương tác với Service.
Type NodePort giúp Service có thể tương tác được từ bên ngoài thông qua port của worker node.
Khởi tạo file config kubia-svc-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: kubia-nodeport
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
nodePort: 30123
selector:
app: kubia
- nodePort: số hiệu cổng của node worker được mở để bên ngoài tương tác với service
Kiểm tra thông tin service:
$ kubectl get svc kubia-nodeport
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubia-nodeport 10.111.254.223 <nodes> 80:30123/TCP 2m
Khi tương tác với service, client sẽ truy cập qua <Địa chỉ Ip public của Node>:Port
Service load balancer
Tạo một Service
kiểu Loadblancer
sẽ cung cấp thêm địa chỉ IP public để client bên ngoài có thể gửi request đến.
File kubia-svc-loadbalancer.yaml
apiVersion: v1
kind: Service
metadata:
name: kubia-loadbalancer
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
Tạo Service:
kubectl create -f kubia-svc-loadbalancer.yaml
Kết quả:
$ kubectl get svc kubia-loadbalancer
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubia-loadbalancer 10.111.241.153 130.211.53.173 80:32143/TCP 1m
Tài liệu tham khảo
All rights reserved