
Nếu bạn dùng K8S hằng ngày, chắc chắn pod và service là hai resource bạn bắt gặp nhiều nhất. Trong bài viết này, chúng ta cùng nhau tìm hiểu cách thức pod và service hoạt động.
Khi tạo một Service, có hai thông tin bắt buộc phải được định nghĩa
selector, để chỉ ra service này sẽ trỏ đến pod nào
targetPort, là port của pod dùng để nhận traffic
Dưới đây là một ví dụ về cách define service:
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- port: 80
targetPort: 3000
selector:
name: app
Khi chạy lệnh “kubectl apply -f service.yaml”, K8S sẽ tìm tất cả các pod có label trùng với selector của service (name:app), và thu thập tất cả IP Address của các pod đó.
Tiếp đến, với mỗi IP Address thu thập được, K8S sẽ tạo ra một endpoint tương ứng.
IP address + port = endpoint
---------------------------------
10.0.0.3 + 3000 = 10.0.0.3:3000
Như vậy có bao nhiêu pod có label match selector, thì có bấy nhiêu endpoint được tạo. Đến đây, tôi mới đặt câu hỏi, tại sao lại cần phải có endpoint? Rõ ràng nếu endpoint chỉ là tổ hợp của IP Address và Port, thì rõ ràng là chỉ cần Service và Pod là đã đủ rồi.
Hoá ra mối quan hệ giữa service và pod không phải là 1-n như tôi nghĩ, mà là quan hệ n-n. Tức một service có thể gắn với nhiều pod, và ngược lại, một pod có thể gắn với nhiều service. Do đó cần phải có một resource trung gian, đó chính là endpoint.
Endpoint được dùng vào những việc gì
Endpoint được dùng trong một số thành phần của k8s như
kube-proxy
ingress-controller
network policy
Kube-proxy là thành phần dùng để mapping Service IP Address sang Pod IP Address. Việc mapping từ IP này sang IP khác như vậy người ta gọi là NAT. Cụ thể hơn trong kube-proxy, việc đổi IP Address của destination, được gọi là DNAT.
Để thực hiện việc mapping, kube-proxy sử dụng iptables của Linux. Chạy câu lệnh dưới để xem những resources liên quan đến kube-proxy.
kubectl get all -n kube-system | grep proxy
Khi thực hiện xoá pod. Luồng logic sẽ như sau:
Chạy câu lệnh “kubectl delete pod A”
Request được gửi đến API server
API Server forward request đến Endpoint Controller
Endpoint Controller báo lại cho API server rằng cần remove endpoint của pod A ra khỏi list
API Server remove endpoint của pod A ra khỏi etcd
API Server báo cho kubelet ở node mà có pod vừa mới bị xoá endpoint
kubelet báo cho kube-proxy, CoreDNS, Ingress Controller, vv rằng endpoint của pod A đã bị xoá
kube-proxy nhận được thông báo, liền xoá các mapping của service với pod A ra khỏi iptables
Đến bước này bất kể request nào đến service được với pod A đều sẽ fail, vì không tìm thấy trong iptables nữa. Tuy nhiên, đến đây tôi mới đặt câu hỏi: Nếu Service trỏ đến nhiều pod, và mỗi pod lại nằm ở những node khác nhau thì có chuyện gì xảy ra hay không?
Điều gì xảy ra khi thực hiện một request đến một K8S service
Thực ra K8S service không hề tồn tại. Thứ mà bạn thấy Service IP Address cũng chỉ là virtual IP, tức không có bất kì một process nào listen trên IP và port của Service.
Giả sử có 2 pod A và B, được deploy trên 2 node khác nhau nodeA, nodeB. Cả 2 pods được trỏ vào bởi 1 service duy nhất, gọi là S. Giờ đứng ở một pod nào đó trong nodeC, thực hiện một request đến service S, chuyện gì sẽ xảy ra?
Client thực hiện một DNS query đến kube-dns
kube-dns trả về virtual IP của Service
client thực hiện request đến virtual IP của Service
kube-proxy ở source node thực hiện DNAT (ServiceIP → Destination PodIP)
kube-proxy forward request đến Pod IP
Pod nhận request và trả về response
kube-proxy ở source node thực hiện SNAT (Destination PodIP → ServiceIP)
Response trả về cho client
Nếu suy ngẫm một chút ở bước 4, ta sẽ có thể đặt một câu hỏi là: Vậy phải chăng kube-proxy ở mỗi node sẽ phải lưu toàn bộ thông tin của tất cả các Pod? Để trả lời câu hỏi này, tôi vào trong pod kube-proxy và log ra toàn bộ các action trên iptables
kubectl exec -it kube-proxy-pod-name -- sh -c "iptables-save"
Trong phần log được in ra, có thể thấy cả những update của các endpoint, hoặc service gắn với pod nằm trên node khác.
Ở giữa bước 5 và bước 6, tôi có thắc mắc là việc giao tiếp giữa 2 node khác nhau được thực hiện ra sao, câu trả lời là đó là phần việc của CNI.