Sửa lỗi 'context deadline exceeded' khi Kubectl không thể kết nối với API Server

intermediate☸️ Kubernetes2026-07-28

Bối cảnh

Không có gì làm trì trệ việc triển khai hơn là một lệnh kubectl bị treo vô thời hạn. Gần đây tôi đã gặp phải vấn đề này khi quản lý một cụm production trong lúc lưu lượng truy cập tăng đột biến. Thay vì nhận được danh sách tài nguyên như mong đợi, tôi lại gặp lỗi: Unable to connect to the server: context deadline exceeded. Về cơ bản, đây là lỗi timeout; kubectl đã đợi API server phản hồi, nhưng thời gian chờ đã hết trước.

Điều này thường báo hiệu sự gián đoạn trong đường truyền liên lạc. Cho dù đó là control plane bị quá tải hay đơn giản là sai lệch cấu hình firewall, việc khắc phục đòi hỏi một cách tiếp cận có hệ thống. Đây là quy trình tôi sử dụng để xác định và giải quyết nút thắt cổ chai.

Quy trình gỡ lỗi

1. Tăng mức độ chi tiết (Verbosity)

Hãy bắt đầu bằng việc kiểm tra bên dưới hệ thống. Đầu ra tiêu chuẩn thường ẩn đi quá trình bắt tay (handshake) thực tế, vì vậy tôi sử dụng cờ -v để xem chi tiết yêu cầu thô.

kubectl get pods -v=9

Cấp độ 9 sẽ xuất ra yêu cầu tương đương với lệnh curl. Hãy chú ý kỹ đến địa chỉ IP. Nếu kubectl đang cố gắng kết nối với địa chỉ 10.x.x.x nội bộ trong khi VPN của bạn bị ngắt kết nối, nguồn gốc của lỗi sẽ hiện rõ ngay lập tức. Tôi cũng từng thấy trường hợp này xảy ra khi một file kubeconfig cũ trỏ đến tên DNS của một load balancer đã bị xóa.

2. Kiểm tra đường truyền mạng

Nếu địa chỉ IP chính xác, hãy xác minh xem cổng 6443 có thực sự có thể truy cập được từ máy cục bộ của bạn hay không. Tôi thích dùng nc (netcat) để kiểm tra nhanh:

nc -zv <api-server-ip> 6443

Kết nối thất bại ở đây cho thấy vấn đề nằm ở lớp mạng. Điều này thường do AWS Security Group thiếu IP hiện tại của bạn hoặc firewall của công ty chặn lưu lượng truy cập ra ngoài trên các cổng không tiêu chuẩn. Nếu bạn nhận được thông báo 'Connection Refused' ngay lập tức, nghĩa là server vẫn hoạt động nhưng từ chối bạn. Nếu nó bị treo, các gói tin đang bị loại bỏ hoàn toàn.

3. Kiểm tra sức khỏe của Control Plane

Khi bạn có quyền truy cập SSH vào các master node, hãy kiểm tra xem container kube-apiserver có thực sự khỏe mạnh hay không. Trên các cụm kubeadm, bạn có thể kiểm tra trực tiếp các static pod:

sudo crictl ps | grep kube-apiserver
sudo crictl logs <container-id> --tail 50

Tìm kiếm các mẫu cụ thể như "etcdserver: request timed out" hoặc các sự kiện OOMKilled. Nếu API server bị kẹt trong vòng lặp crash (crash loop), nó sẽ không có đủ tài nguyên để phản hồi các yêu cầu từ client.

Giải pháp

Giải pháp 1: Kiểm tra Proxy và các biến môi trường

Các biến môi trường cục bộ thường là nguyên nhân phổ biến. Trong môi trường doanh nghiệp, kubectl có thể nhầm lẫn khi điều hướng lưu lượng truy cập cụm nội bộ thông qua một web proxy. Điều này thường dẫn đến timeout vì proxy không thể kết nối tới mạng cụm nội bộ.

# Tạm thời xóa proxy để kiểm tra
unset http_proxy
unset https_proxy

# Hoặc đảm bảo IP API server của bạn được loại trừ
export no_proxy=$no_proxy,10.96.0.1,<cluster-api-ip>

Giải pháp 2: Khắc phục độ trễ của Etcd

API server chỉ nhanh khi etcd nhanh. Nếu etcd mất hơn 100ms để thực hiện một lệnh ghi, API server có khả năng cao sẽ làm timeout client. Hãy kiểm tra logs để tìm các cảnh báo "apply entries took too long".

Tôi đã từng giải quyết một vấn đề timeout dai dẳng bằng cách chuyển thư mục dữ liệu etcd sang ổ cứng NVMe SSD. Nếu bạn đang dùng AWS, hãy đảm bảo các volume EBS là loại gp3 với ít nhất 3.000 IOPS được cấp phát. Thời gian chờ đĩa cao là "kẻ giết người thầm lặng" đối với khả năng phản hồi của Kubernetes.

Giải pháp 3: Điều chỉnh Idle Timeout của Load Balancer

Nếu cụm của bạn nằm sau AWS ELB hoặc Nginx Ingress, load balancer có thể đang ngắt kết nối quá sớm. Điều này thường gặp với các lệnh chạy lâu như kubectl logs -f hoặc kubectl exec.

Hãy đặt idle timeout của Load Balancer thành 300 giây hoặc cao hơn. Đối với các thiết lập dựa trên Nginx, hãy thêm các annotation này vào cấu hình ingress của bạn:

nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"

Giải pháp 4: Xử lý tình trạng cạn kiệt tài nguyên

Một master node chạy ở mức 95% CPU cuối cùng sẽ loại bỏ các yêu cầu. Sử dụng top hoặc htop trên master node để kiểm tra sự tranh chấp tài nguyên. Trong một trường hợp, một logging agent bị lỗi đã tiêu tốn 4GB RAM, khiến kube-apiserver phải sử dụng bộ nhớ swap trên đĩa. Sau khi tôi giới hạn tài nguyên của agent đó, các lỗi context deadline exceeded đã biến mất ngay lập tức.

Xác minh

Sau khi áp dụng bản sửa lỗi, hãy chạy một lệnh nhẹ để xác nhận kết nối:

kubectl version

Khi lệnh đó thành công, hãy kiểm tra một thao tác nặng hơn để đảm bảo tính ổn định của kết nối:

kubectl get pods -A

Nếu danh sách hiển thị trong vòng một hoặc hai giây, API server của bạn đã hoạt động bình thường trở lại.

Bài học kinh nghiệm

  • Cô lập các lớp: Sử dụng -v=9 để xác định xem timeout xảy ra trước khi yêu cầu rời khỏi máy tính của bạn hay trong khi chờ phản hồi của server.
  • Theo dõi các chỉ số Etcd: Hãy theo dõi sát sao etcd_disk_wal_fsync_duration_seconds. Nếu chỉ số này tăng vọt, API server của bạn chắc chắn sẽ bị lag.
  • Kiểm tra VPN: Làm việc từ xa thường liên quan đến các đường truyền tunnel không ổn định. Nếu bạn thấy mất gói tin (packet loss) khi ping liên tục đến API server, mạng cục bộ của bạn có khả năng cao là nút thắt cổ chai.

Related Error Notes