1. Nhận diện sự cố
Trong quá trình xây dựng cụm Kubernetes có tính sẵn sàng cao (High Availability) thông qua phương pháp triển khai binary, thành phần kube-controller-manager trên các node master đôi khi không đạt trạng thái ổn định. Khi kiểm tra trạng thái các thành phần điều khiển, hệ thống báo lỗi Unhealthy như sau:
# kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Unhealthy Get http://127.0.0.1:10252/healthz: net/http: HTTP/1.x transport connection broken: malformed HTTP response "\x15\x03\x01\x00\x02\x02"
etcd-0 Healthy {"health":"true"}
etcd-1 Healthy {"health":"true"}
etcd-2 Healthy {"health":"true"}
Thông báo lỗi malformed HTTP response kèm theo các ký tự hex đặc trưng cho thấy có sự không khớp về giao thức giữa client kiểm tra health và service đang lắng nghe.
2. Phân tích nhật ký hệ thống
Để tìm hiểu nguyên nhân sâu hơn, chúng ta kiểm tra trạng thái hoạt động của service thông qua systemd. Nhật ký ghi lại cho thấy các lỗi liên quan đến bắt tay TLS (TLS handshake):
# systemctl status kube-controller-manager -l
● kube-controller-manager.service - Kubernetes Controller Manager
Loaded: loaded (/etc/systemd/system/kube-controller-manager.service; enabled)
Active: active (running)
...
Dec 29 03:57:44 ceph-01 kube-controller-manager: http: TLS handshake error from 127.0.0.1:40918: tls: first record does not look like a TLS handshake
Dec 29 03:57:46 ceph-01 kube-controller-manager: http: TLS handshake error from 127.0.0.1:40948: tls: first record does not look like a TLS handshake
Lỗi tls: first record does not look like a TLS handshake xác nhận rằng service đang cố gắng giao tiếp qua HTTPS trên cổng được cấu hình, trong khi cơ chế health check mặc định lại gửi yêu cầu HTTP thuần túy, hoặc ngược lại, gây ra xung đột giao thức.
3. Nguyên nhân và phương án xử lý
Vấn đề nằm ở tệp cấu hình service của kube-controller-manager. Cụ thể, các tham số liên quan đến cổng lắng nghe đã được thiết lập cứng gây ra xung đột. Dưới đây là cấu hình gặp sự cố:
[Service]
ExecStart=/usr/local/bin/kube-controller-manager \
--port=0 \
--secure-port=10252 \
--bind-address=127.0.0.1 \
--kubeconfig=/etc/kubernetes/cert/kube-controller-manager.kubeconfig \
--authentication-kubeconfig=/etc/kubernetes/cert/kube-controller-manager.kubeconfig \
--service-cluster-ip-range=10.254.0.0/16 \
--cluster-name=kubernetes \
--cluster-signing-cert-file=/etc/kubernetes/cert/ca.pem \
--cluster-signing-key-file=/etc/kubernetes/cert/ca-key.pem \
--experimental-cluster-signing-duration=8760h \
--root-ca-file=/etc/kubernetes/cert/ca.pem \
--service-account-private-key-file=/etc/kubernetes/cert/ca-key.pem \
--leader-elect=true \
--feature-gates=RotateKubeletServerCertificate=true \
--controllers=*,bootstrapsigner,tokencleaner \
--horizontal-pod-autoscaler-use-rest-clients=true \
--horizontal-pod-autoscaler-sync-period=10s \
--tls-cert-file=/etc/kubernetes/cert/kube-controller-manager.pem \
--tls-private-key-file=/etc/kubernetes/cert/kube-controller-manager-key.pem \
--use-service-account-credentials=true \
--alsologtostderr=true \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=2
Các tham số --port=0, --secure-port=10252 và --bind-address=127.0.0.1 khi kết hợp có thể khiến cơ chế health check nội bộ không thể kết nối đúng cách do sự chênh lệch giữa HTTP và HTTPS. Để khắc phục, chúng ta cần loại bỏ các tham số cưỡng bức này để service sử dụng cấu hình mặc định phù hợp hơn với cơ chế kiểm tra sức khỏe của cụm.
Cấu hình đã điều chỉnh như sau:
[Service]
ExecStart=/usr/local/bin/kube-controller-manager \
--kubeconfig=/etc/kubernetes/cert/kube-controller-manager.kubeconfig \
--authentication-kubeconfig=/etc/kubernetes/cert/kube-controller-manager.kubeconfig \
--service-cluster-ip-range=10.254.0.0/16 \
--cluster-name=kubernetes \
--cluster-signing-cert-file=/etc/kubernetes/cert/ca.pem \
--cluster-signing-key-file=/etc/kubernetes/cert/ca-key.pem \
--experimental-cluster-signing-duration=8760h \
--root-ca-file=/etc/kubernetes/cert/ca.pem \
--service-account-private-key-file=/etc/kubernetes/cert/ca-key.pem \
--leader-elect=true \
--feature-gates=RotateKubeletServerCertificate=true \
--controllers=*,bootstrapsigner,tokencleaner \
--horizontal-pod-autoscaler-use-rest-clients=true \
--horizontal-pod-autoscaler-sync-period=10s \
--tls-cert-file=/etc/kubernetes/cert/kube-controller-manager.pem \
--tls-private-key-file=/etc/kubernetes/cert/kube-controller-manager-key.pem \
--use-service-account-credentials=true \
--alsologtostderr=true \
--logtostderr=false \
--log-dir=/var/log/kubernetes \
--v=2
Restart=on-failure
RestartSec=5
Sau khi cập nhật tệp cấu hình, thực hiện tải lại daemon và khởi động lại service:
# systemctl daemon-reload
# systemctl restart kube-controller-manager
4. Kiểm tra lại trạng thái cụm
Thực hiện lại lệnh kiểm tra thành phần cụm để xác nhận sự cố đã được giải quyết:
# kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy {"health":"true"}
etcd-1 Healthy {"health":"true"}
etcd-2 Healthy {"health":"true"}
Tất cả các thành phần chính bao gồm controller-manager, scheduler và etcd đều đã chuyển sang trạng thái Healthy, xác nhận cụm Kubernetes đã hoạt động ổn định.