Giới thiệu về phương pháp triển khai Kubernetes HA
Việc cài đặt một cụm Kubernetes có khả năng chịu lỗi cao (High Availability - HA) thường đi kèm với độ phức tạp đáng kể, đòi hỏi nhiều công cụ và cấu hình phụ thuộc. Phương pháp được trình bày ở đây mang đến một cách tiếp cận đơn giản và hiệu quả để xây dựng cụm K8s HA mà không cần đến các thành phần truyền thống như HAProxy hay Keepalived, cũng không yêu cầu Ansible.
Giải pháp này khai thác sức mạnh của ipvs trong nhân Linux để cân bằng tải cho các máy chủ API của Kubernetes, đồng thời tích hợp cơ chế kiểm tra tình trạng (health check) cho các apiserver. Kiến trúc tổng thể tập trung vào sự tinh gọn, ổn định và dễ quản lý, với mục tiêu cung cấp một công cụ cài đặt Kubernetes đáng tin cậy và linh hoạt.
Đặc điểm và ưu điểm nổi bật
Giải pháp này được xây dựng dựa trên các nguyên tắc thiết kế nhằm tối ưu hóa sự đơn giản và hiệu quả:
- Cài đặt ngoại tuyến: Hỗ trợ cài đặt hoàn toàn ngoại tuyến, với việc tách biệt công cụ và gói tài nguyên (nhị phân, tệp cấu hình, ảnh container, tệp YAML). Điều này giúp dễ dàng thay thế các phiên bản Kubernetes khác nhau chỉ bằng cách cập nhật gói ngoại tuyến tương ứng.
- Gia hạn chứng chỉ tự động: Tích hợp khả năng gia hạn chứng chỉ, giảm bớt gánh nặng quản lý chứng chỉ thủ công cho người dùng.
- Dễ sử dụng: Quy trình triển khai được đơn giản hóa đến mức tối đa.
- Cấu hình linh hoạt: Cho phép người dùng tùy chỉnh các tệp cấu hình theo nhu cầu cụm của mình.
- Tải cân bằng cấp độ Kernel: Sử dụng
ipvscủa nhân Linux để cân bằng tải, mang lại độ ổn định cao và dễ dàng khắc phục sự cố nhờ kiến trúc đơn giản.
Vì sao không sử dụng Ansible?
Trong các phiên bản đầu, việc triển khai đã từng sử dụng Ansible. Tuy nhiên, điều này đòi hỏi người dùng phải cài đặt Ansible, Python và các thư viện phụ thuộc khác, làm tăng độ phức tạp ban đầu. Để đơn giản hóa hơn nữa, Ansible sau đó được đưa vào container. Tuy nhiên, ngay cả khi sử dụng SSH với tên người dùng/mật khẩu, vẫn cần đến ssh-pass, điều này không đáp ứng được mục tiêu về sự tối giản.
Để khắc phục những hạn chế này, giải pháp hiện tại tập trung vào một công cụ dạng nhị phân duy nhất, không có bất kỳ phụ thuộc nào. Việc phân phối tệp và thực thi lệnh từ xa đều được triển khai thông qua SDK tùy chỉnh, loại bỏ mọi phụ thuộc bên ngoài.
Vì sao không sử dụng Keepalived và HAProxy?
Việc triển khai HAProxy dưới dạng static pod có thể chấp nhận được và tương đối dễ quản lý. Tuy nhiên, Keepalived thường được cài đặt thông qua các trình quản lý gói như yum hoặc apt, dẫn đến nhiều vấn đề khó kiểm soát:
- Không đồng nhất phiên bản: Sự khác biệt về nguồn gói có thể dẫn đến các phiên bản không tương thích, thậm chí thay đổi cấu hình. Việc debug các sự cố đôi khi rất khó khăn do sự khác biệt phiên bản.
- Lỗi cài đặt: Các vấn đề về thư viện phụ thuộc hoặc môi trường hệ thống có thể ngăn cản việc cài đặt Keepalived.
- Kiểm tra sức khỏe không chính xác: Nhiều script kiểm tra sức khỏe chỉ đơn thuần kiểm tra quá trình của HAProxy, thay vì kiểm tra trạng thái
healthzthực sự củaapiserver. Nếuapiservergặp sự cố nhưng HAProxy vẫn đang chạy, cụm sẽ rơi vào trạng thái HA giả mạo. - Khó quản lý: Việc giám sát Keepalived chạy dưới dạng systemd phức tạp hơn so với các static pod có thể được giám sát trực tiếp qua Prometheus. Việc khởi động lại hoặc quản lý cần các thao tác riêng biệt, không nhất quán với việc quản lý tập trung thông qua Kubelet.
- Sự cố hiệu suất: Đã từng ghi nhận trường hợp Keepalived chiếm dụng toàn bộ CPU, gây ảnh hưởng nghiêm trọng đến hiệu suất cụm.
Để giải quyết những vấn đề này, Keepalived đã từng được thử nghiệm chạy trong container (mặc dù các image cộng đồng thường không hoạt động ổn định). Tuy nhiên, những khó khăn này đã thúc đẩy việc tìm kiếm một giải pháp thay thế đơn giản và đáng tin cậy hơn, cuối cùng dẫn đến việc loại bỏ hoàn toàn HAProxy và Keepalived.
Vì sao không sử dụng Envoy hoặc Nginx cho tải cân bằng cục bộ?
Trong kiến trúc tải cân bằng cục bộ (mỗi node đều chạy một bộ cân bằng tải cho các master), việc sử dụng các proxy ở không gian người dùng như Envoy hoặc Nginx sẽ đòi hỏi mỗi node phải chạy thêm một tiến trình, tiêu tốn tài nguyên và tăng độ phức tạp. Mặc dù IPVS cũng cần một tiến trình lvscare (tương tự như kube-proxy), tiến trình này chỉ chịu trách nhiệm quản lý các quy tắc IPVS. Luồng traffic thực sự vẫn được xử lý trực tiếp bởi nhân Linux, mang lại sự ổn định cao và hiệu suất vượt trội do không phải chuyển gói dữ liệu giữa không gian kernel và không gian người dùng.
Một vấn đề khác với Envoy hoặc Nginx là trong quá trình join node, nếu bộ cân bằng tải chưa được thiết lập, kubelet sẽ không thể khởi động. Điều này có nghĩa là bạn không thể quản lý các bộ cân bằng tải này dưới dạng static pod (do chúng phụ thuộc vào kubelet), dẫn đến một vòng lặp phụ thuộc (dependency deadlock). Ngược lại, với IPVS, các quy tắc có thể được thiết lập trước khi kubelet thực hiện thao tác join, sau đó một daemon sẽ giám sát và duy trì các quy tắc này. Nếu một apiserver trở nên không khả dụng, các quy tắc IPVS tương ứng trên tất cả các node sẽ tự động bị xóa và được thêm lại khi master phục hồi.
Vì sao cần tùy chỉnh Kubeadm?
Kubeadm được tùy chỉnh vì hai lý do chính:
- Gia hạn chứng chỉ: Thời hạn chứng chỉ mặc định của Kubeadm bị giới hạn. Việc tùy chỉnh mã nguồn cho phép kéo dài thời hạn này (ví dụ: lên 99 năm), tránh sự phụ thuộc vào các công cụ ký chứng chỉ bên ngoài.
- Tích hợp tải cân bằng cục bộ: Việc thay đổi mã nguồn Kubeadm là cách thuận tiện nhất để tích hợp cơ chế tải cân bằng cục bộ. Trong quá trình
join, cần thực hiện hai bước: thiết lập các quy tắc IPVS trước khijoinvà tạo static pod cholvscare. Nếu không tùy chỉnh Kubeadm, việc này có thể gây ra lỗistatic pod directory already exists. Hơn nữa, Kubeadm cung cấp các SDK hữu ích để hỗ trợ việc triển khai tính năng này một cách sạch sẽ.
Bằng cách tích hợp các tính năng cốt lõi này vào Kubeadm, công cụ triển khai trở nên nhẹ hơn, chỉ còn tập trung vào việc phân phối và thực thi các lệnh cấp cao. Điều này cũng cho phép sử dụng trực tiếp Kubeadm để thêm node.
Hướng dẫn sử dụng
Chuẩn bị
- Cài đặt và khởi động Docker.
- Tải gói cài đặt Kubernetes ngoại tuyến.
- Tải phiên bản công cụ triển khai mới nhất.
- Hỗ trợ Kubernetes phiên bản 1.14.0 trở lên.
Cài đặt
Để triển khai cụm Kubernetes HA với nhiều master, chỉ cần thực hiện lệnh sau:
$ myk8sctl init --master 192.168.1.10 \
--master 192.168.1.11 \
--master 192.168.1.12 \
--node 192.168.1.20 \
--user adminuser \
--password 'your-secure-password' \
--version v1.14.1 \
--package-path /root/kube-offline-1.14.1.tar.gz
Cụm Kubernetes HA của bạn đã được thiết lập một cách nhanh chóng và đơn giản.
Để cài đặt một cụm với một master và nhiều node:
$ myk8sctl init --master 192.168.1.10 \
--node 192.168.1.20 \
--node 192.168.1.21 \
--user adminuser \
--password 'your-secure-password' \
--version v1.14.1 \
--package-path /root/kube-offline-1.14.1.tar.gz
Sử dụng SSH key hoặc cặp khóa thay vì mật khẩu:
$ myk8sctl init --master 172.16.10.10 \
--node 172.16.10.20 \
--package-path https://example.com/kube-1.15.0.tar.gz \
--private-key /root/my_kubernetes_key.pem \
--version v1.15.0
Giải thích các tham số
--master: Danh sách địa chỉ IP của các máy chủ master.--node: Danh sách địa chỉ IP của các máy chủ worker node.--user: Tên người dùng SSH để truy cập các máy chủ.--password: Mật khẩu SSH của người dùng.--package-path: Đường dẫn đến gói cài đặt ngoại tuyến. Có thể là đường dẫn cục bộ hoặc URL HTTP (công cụ sẽwgetvề máy chủ mục tiêu).--version: Phiên bản Kubernetes cần cài đặt.--private-key: Đường dẫn đến tệp khóa riêng SSH. Mặc định là/root/.ssh/id_rsanếu không được chỉ định.
Các tham số khác:
--kubeadm-config string: Đường dẫn đến tệp cấu hình Kubeadm tùy chỉnh (ví dụ:kubeadm-config.yaml).--virtual-ip string: Địa chỉ IP ảo (VIP) cho tải cân bằng cục bộ (mặc định là10.103.97.2). Không khuyến nghị thay đổi, và VIP này không thể truy cập từ bên ngoài cụm.
Kiểm tra trạng thái cài đặt
$ kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master-01 Ready master 2m25s v1.14.1
k8s-master-02 Ready master 119s v1.14.1
k8s-master-03 Ready master 63s v1.14.1
k8s-worker-01 Ready <none> 38s v1.14.1
$ kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-5cbcccc885-9n2p8 1/1 Running 0 3m1s
kube-system calico-node-656zn 1/1 Running 0 93s
kube-system calico-node-bv5hn 1/1 Running 0 2m54s
kube-system calico-node-f2vmd 1/1 Running 0 3m1s
kube-system calico-node-tbd5l 1/1 Running 0 118s
kube-system coredns-fb8b8dccf-8bnkv 1/1 Running 0 3m1s
kube-system coredns-fb8b8dccf-spq7r 1/1 Running 0 3m1s
kube-system etcd-k8s-master-01 1/1 Running 0 2m25s
kube-system etcd-k8s-master-02 1/1 Running 0 2m53s
kube-system etcd-k8s-master-03 1/1 Running 0 118s
kube-system kube-apiserver-k8s-master-01 1/1 Running 0 2m15s
kube-system kube-apiserver-k8s-master-02 1/1 Running 0 2m54s
kube-system kube-apiserver-k8s-master-03 1/1 Running 1 47s
kube-system kube-controller-manager-k8s-master-01 1/1 Running 1 2m43s
kube-system kube-controller-manager-k8s-master-02 1/1 Running 0 2m54s
kube-system kube-controller-manager-k8s-master-03 1/1 Running 0 63s
kube-system kube-proxy-b9b9z 1/1 Running 0 2m54s
kube-system kube-proxy-nf66n 1/1 Running 0 3m1s
kube-system kube-proxy-q2bqp 1/1 Running 0 118s
kube-system kube-proxy-s5g2k 1/1 Running 0 93s
kube-system kube-scheduler-k8s-master-01 1/1 Running 1 2m43s
kube-system kube-scheduler-k8s-master-02 1/1 Running 0 2m54s
kube-system kube-scheduler-k8s-master-03 1/1 Running 0 61s
kube-system k8s-lvscare-controller-k8s-worker-01 1/1 Running 0 86s
Thêm node mới
Để thêm node vào cụm, bạn có thể sử dụng lệnh myk8sctl join:
$ myk8sctl join --master 192.168.1.10 \
--master 192.168.1.11 \
--master 192.168.1.12 \
--virtual-ip 10.103.97.2 \
--node 192.168.1.25 \
--user adminuser \
--password 'your-secure-password' \
--package-path /root/kube-offline-1.15.0.tar.gz
Sử dụng cấu hình Kubeadm tùy chỉnh
Trong một số trường hợp, bạn có thể cần tùy chỉnh tệp cấu hình Kubeadm, ví dụ như thêm một tên miền vào danh sách certSANs cho chứng chỉ API server.
Đầu tiên, tạo tệp cấu hình mẫu:
$ myk8sctl config --template kubeadm >> custom-kubeadm-config.yaml.tmpl
Sau đó, chỉnh sửa tệp custom-kubeadm-config.yaml.tmpl, ví dụ, thêm tên miền mycompany.com:
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: {{.Version}}
controlPlaneEndpoint: "api.mycluster.local:6443"
networking:
podSubnet: 100.64.0.0/10
apiServer:
certSANs:
- mycompany.com # Tên miền mới được thêm
- 127.0.0.1
- api.mycluster.local
{{range .Masters -}}
- {{.}}
{{end -}}
- {{.VIP}}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
excludeCIDRs:
- "{{.VIP}}/32"
Lưu ý: Các phần khác của tệp không cần thay đổi, công cụ sẽ tự động điền nội dung vào các template.
Cuối cùng, khi triển khai, sử dụng tham số --kubeadm-config để chỉ định tệp cấu hình mẫu tùy chỉnh:
$ myk8sctl init --kubeadm-config custom-kubeadm-config.yaml.tmpl \
--master 192.168.1.10 \
--master 192.168.1.11 \
--master 192.168.1.12 \
--node 192.168.1.20 \
--user adminuser \
--password 'your-secure-password' \
--version v1.14.1 \
--package-path /root/kube-offline-1.14.1.tar.gz
Nâng cấp phiên bản
Quy trình nâng cấp phiên bản Kubernetes từ 1.14 lên 1.15 được mô tả dưới đây. Nguyên tắc tương tự áp dụng cho các phiên bản khác, với các chi tiết cụ thể có thể tham khảo tài liệu chính thức.
Quy trình nâng cấp
- Cập nhật các gói nhị phân và ảnh container mới trên tất cả các node.
- Nâng cấp master đầu tiên (control plane chính).
- Nâng cấp kubelet trên master đầu tiên.
- Nâng cấp các master còn lại.
- Nâng cấp các node worker.
- Xác minh trạng thái cụm.
Các bước thực hiện
1. Cập nhật Kubeadm và các công cụ khác:
Sao chép gói ngoại tuyến phiên bản mới lên tất cả các node. Sau đó, chạy script khởi tạo đi kèm gói để cập nhật các tệp nhị phân của kubeadm, kubectl, kubelet và nhập các ảnh container mới.
# Trên tất cả các node
cd /path/to/new/kube/package/shell && sh setup_tools.sh
2. Nâng cấp Control Plane (master đầu tiên):
$ kubeadm upgrade plan
$ kubeadm upgrade apply v1.15.0
Khởi động lại kubelet:
$ systemctl restart kubelet
Việc nâng cấp kubelet đơn giản là thay thế tệp nhị phân kubelet trong /usr/bin bằng phiên bản mới và khởi động lại dịch vụ kubelet. Tệp nhị phân kubelet mới thường nằm trong thư mục conf/bin của gói cài đặt.
3. Nâng cấp các Master khác:
$ kubeadm upgrade apply
4. Nâng cấp Node Worker:
Tạm dừng lịch trình trên node (tùy chọn):
$ kubectl drain <TEN_NODE> --ignore-daemonsets
Cập nhật cấu hình kubelet:
$ kubeadm upgrade node config --kubelet-version v1.15.0
Thay thế tệp nhị phân kubelet và khởi động lại dịch vụ:
# Sao chép tệp nhị phân kubelet mới vào /usr/bin
$ systemctl restart kubelet
Kích hoạt lại lịch trình trên node:
$ kubectl uncordon <TEN_NODE>
Xác minh
Kiểm tra trạng thái các node sau khi nâng cấp:
$ kubectl get nodes
Nếu thông tin phiên bản hiển thị chính xác, quá trình nâng cấp đã thành công.
Kubeadm upgrade apply hoạt động như thế nào?
Lệnh kubeadm upgrade apply thực hiện các bước sau:
- Kiểm tra tính khả dụng của việc nâng cấp cụm.
- Thực hiện chính sách nâng cấp phiên bản (kiểm tra các phiên bản tương thích).
- Xác nhận sự tồn tại của các ảnh container cần thiết.
- Nâng cấp các thành phần control plane (apiserver, controller manager, scheduler). Nếu thất bại, quá trình sẽ được rollback.
- Nâng cấp Kube-DNS và Kube-Proxy.
- Tạo các tệp chứng chỉ mới và sao lưu các tệp cũ nếu chúng đã quá hạn 180 ngày.
Biên dịch từ mã nguồn
Do sử dụng thư viện netlink, khuyến nghị biên dịch trong môi trường container. Bạn có thể thực hiện với một lệnh duy nhất:
$ docker run --rm -v $(pwd):/go/src/myk8s.io/myk8sctl -w /go/src/myk8s.io/myk8sctl -it golang:1.12.7 go build -o myk8sctl
Nếu bạn đang sử dụng Go Modules, cần chỉ định biên dịch thông qua thư mục vendor:
$ go build -mod vendor -o myk8sctl
Gỡ cài đặt
Để gỡ cài đặt cụm Kubernetes, sử dụng lệnh myk8sctl clean:
$ myk8sctl clean \
--master 192.168.1.10 \
--master 192.168.1.11 \
--master 192.168.1.12 \
--node 192.168.1.20 \
--user adminuser \
--password 'your-secure-password'
Nguyên lý hoạt động
Quy trình thực thi
- Sao chép gói cài đặt ngoại tuyến đến các máy chủ mục tiêu (master và node) thông qua SFTP hoặc Wget.
- Thực hiện
kubeadm inittrên master đầu tiên (master0). - Trên các master còn lại, thực hiện
kubeadm joinvới vai trò control plane. Quá trình này sẽ khởi độngetcdtrên các master này, tạo thành một cụm vớietcdcủa master0, và khởi động các thành phần control plane (apiserver, controller, v.v.). - Các node worker sẽ được
joinvào cụm. Trên mỗi node này, các quy tắc IPVS sẽ được cấu hình, và tệp/etc/hostssẽ được cập nhật để phân giải địa chỉ.
Tất cả các yêu cầu đến apiserver đều được thực hiện thông qua một tên miền. Bởi vì mỗi node cần kết nối với nhiều master thông qua một IP ảo, và kubelet cùng kube-proxy trên mỗi node có thể truy cập IP ảo của apiserver khác nhau (mặc dù Kubeadm chỉ cho phép chỉ định một địa chỉ trong cấu hình). Vì vậy, một tên miền duy nhất được sử dụng, nhưng địa chỉ IP mà mỗi node phân giải cho tên miền đó sẽ khác nhau. Khi địa chỉ IP thay đổi, chỉ cần sửa đổi cấu hình phân giải địa chỉ.
Tải cân bằng Kernel cục bộ
Cơ chế này triển khai tải cân bằng cục bộ trên mỗi node, cho phép các node truy cập vào các master thông qua một instance IPVS được quản lý bởi nhân Linux:
+----------+ +---------------+ Server ảo: 127.0.0.1:6443
| Master A |<----------------------| IPVS trên | Servers thực:
+----------+ |+---------------+ 10.103.97.200:6443
| 10.103.97.201:6443
+----------+ | 10.103.97.202:6443
| Master B |<---------------------+
+----------+ |
|
+----------+ |
| Master C |<---------------------+
+----------+
Một static pod có tên lvscare-controller được triển khai trên mỗi node để giám sát và duy trì các quy tắc IPVS này. Nếu một apiserver trở nên không khả dụng, lvscare-controller sẽ tự động xóa các quy tắc IPVS tương ứng trên tất cả các node. Khi master đó phục hồi, các quy tắc sẽ được thêm lại.
Trên mỗi node worker, bạn có thể quan sát thấy ba thay đổi chính:
/etc/kubernetes/manifests: Chứa tệp cấu hình static pod cholvscare-controller.ipvsadm -Ln: Hiển thị các quy tắc IPVS đã được tạo./etc/hosts: Bao gồm địa chỉ phân giải cho IP ảo của cụm.
Tùy chỉnh Kubeadm chi tiết
Công cụ này thực hiện các thay đổi rất nhỏ đối với Kubeadm, chủ yếu là kéo dài thời hạn chứng chỉ và mở rộng lệnh join. Dưới đây là mô tả chi tiết về việc tùy chỉnh lệnh join.
Đầu tiên, tham số --master được thêm vào lệnh join để chỉ định danh sách các địa chỉ master:
flagSet.StringSliceVar(
&localLBConfig.LVSCare.Masters, "master", []string{},
"A list of HA master IPs, e.g., --master 192.168.0.2:6443",
)
Điều này cho phép thu thập danh sách các địa chỉ master để thiết lập tải cân bằng IPVS.
Nếu node không phải là control plane và cụm có nhiều hơn một master, chỉ một quy tắc IPVS duy nhất sẽ được tạo. Các node control plane không cần tạo quy tắc này vì chúng kết nối trực tiếp với apiserver của chính mình:
if joinData.Config.ControlPlane == nil {
fmt.Println("This node is not a control plane.")
if len(localLBConfig.LVSCare.Masters) != 0 {
localLBConfig.CreateLocalLB(args[0])
}
}
Tiếp theo, static pod lvscare-controller được tạo để giám sát IPVS:
if len(localLBConfig.LVSCare.Masters) != 0 {
localLBConfig.LVSCareStaticPodToDisk("/etc/kubernetes/manifests")
}
Do đó, bạn vẫn có thể sử dụng phiên bản Kubeadm đã tùy chỉnh này để triển khai cụm mà không cần công cụ bên ngoài, mặc dù sẽ phức tạp hơn. Dưới đây là các bước cài đặt thủ công.
Tệp cấu hình Kubeadm (ví dụ):
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.14.0
controlPlaneEndpoint: "k8s-api.local:6443" # Tên DNS cho apiserver
apiServer:
certSANs:
- 127.0.0.1
- k8s-api.local
- 172.20.241.205
- 172.20.241.206
- 172.20.241.207
- 172.20.241.208
- 10.103.97.10 # IP ảo
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
excludeCIDRs:
- "10.103.97.10/32" # Quan trọng: Nếu không có dòng này, kube-proxy có thể xóa các quy tắc IPVS của bạn
Trên master0 (giả sử VIP là 10.103.97.100):
$ echo "10.103.97.100 k8s-api.local" >> /etc/hosts # Phân giải thành địa chỉ của master0
$ kubeadm init --config=kubeadm-config.yaml --experimental-upload-certs
$ mkdir -p $HOME/.kube && cp /etc/kubernetes/admin.conf $HOME/.kube/config
$ kubectl apply -f https://docs.projectcalico.org/v3.6/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
Trên master1 (giả sử VIP là 10.103.97.101):
$ echo "10.103.97.100 k8s-api.local" >> /etc/hosts # Phân giải thành địa chỉ của master0 để join
$ kubeadm join 10.103.97.100:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890 \
--experimental-control-plane \
--certificate-key 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
$ sed "s/10.103.97.100/10.103.97.101/g" -i /etc/hosts # Sau khi join, chuyển phân giải sang địa chỉ của chính nó
Trên master2 (giả sử VIP là 10.103.97.102):
$ echo "10.103.97.100 k8s-api.local" >> /etc/hosts
$ kubeadm join 10.103.97.100:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890 \
--experimental-control-plane \
--certificate-key 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
$ sed "s/10.103.97.100/10.103.97.102/g" -i /etc/hosts
Trên node worker, khi join, thêm tham số --master để chỉ định danh sách các địa chỉ master:
$ echo "10.103.97.10 k8s-api.local" >> /etc/hosts # Cần phân giải thành IP ảo
$ kubeadm join 10.103.97.10:6443 --token abcdef.0123456789abcdef \
--master 10.103.97.100:6443 \
--master 10.103.97.101:6443 \
--master 10.103.97.102:6443 \
--discovery-token-ca-cert-hash sha256:a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890
Phân tích cấu trúc gói ngoại tuyến
Cấu trúc của gói cài đặt ngoại tuyến được tổ chức như sau:
.
├── binaries # Tệp nhị phân của phiên bản Kubernetes cụ thể (kubeadm, kubectl, kubelet)
│ ├── kubeadm
│ ├── kubectl
│ └── kubelet
├── configs # Tệp cấu hình
│ ├── 10-kubeadm.conf # (ít dùng trong phiên bản mới, được tạo trực tiếp bởi script để kiểm tra cgroup driver)
│ ├── dashboard # Cấu hình Kubernetes Dashboard
│ │ ├── dashboard-admin.yaml
│ │ └── kubernetes-dashboard.yaml
│ ├── monitoring # Cấu hình cho Prometheus và Grafana (ví dụ)
│ │ ├── grafana.yaml
│ │ ├── prometheus.yaml
│ │ └── rbac
│ │ └── monitoring-rbac.yaml
│ ├── kubeadm.yaml # Tệp cấu hình chính của kubeadm
│ ├── kubelet.service # Tệp cấu hình systemd cho kubelet
│ ├── cni # Cấu hình cho plugin mạng (ví dụ: Calico)
│ │ └── calico.yaml
├── images # Tất cả các ảnh container cần thiết
│ └── images.tar
└── scripts
├── init_cluster.sh # Script khởi tạo cụm
└── master_config.sh # Script cấu hình master
- Script
init_cluster.shsao chép các tệp nhị phân từ thư mụcbinariesvào$PATH, cấu hình systemd, tắt swap và tường lửa, sau đó nhập các ảnh container cần thiết. - Script
master_config.shchủ yếu thực hiện lệnhkubeadm init. - Thư mục
configschứa các tệp cấu hình Kubeadm, tệp YAML cho Calico và các thành phần khác.
Công cụ cài đặt sẽ gọi các script trên, đảm bảo tính tương thích. Các phiên bản Kubernetes khác nhau có thể được hỗ trợ thông qua việc điều chỉnh nhỏ trong các script này.