Metrics, Traces và API Priority and Fairness

K
Kai··5 min read

Bài 65 lo log — sự kiện rời rạc. Quan sát còn cần số liệu liên tục: bao nhiêu request đang chạy, độ trễ ra sao, có pod nào restart. Kubernetes phơi những thứ đó qua endpoint /metrics. Bài này xem metrics ấy, rồi đào sâu một cơ chế vừa là observability vừa là tự vệ: API Priority and Fairness, thứ ta đã thoáng thấy trong log apiserver ở Bài 65.

Endpoint /metrics

apiserver và kubelet đều phơi /metrics ở định dạng Prometheus — text thuần, mỗi dòng một số đo kèm nhãn:

kubectl get --raw /metrics | grep -E "apiserver_current_inflight_requests|apiserver_request_total" | head
apiserver_current_inflight_requests{request_kind="mutating"} 0
apiserver_current_inflight_requests{request_kind="readOnly"} 1
apiserver_request_total{code="0",resource="pods",subresource="exec",verb="CONNECT",version="v1"} 18

apiserver_current_inflight_requests đếm request đang xử lý theo loại, apiserver_request_total là bộ đếm tích lũy chia theo resource/verb/mã trả về. kubelet có bộ riêng:

kubectl get --raw /api/v1/nodes/worker-0/proxy/metrics | grep kubelet_running_containers
kubelet_running_containers{container_state="created"} 1
kubelet_running_containers{container_state="exited"}  6
kubelet_running_containers{container_state="running"} 14

Đây là dữ liệu thô; Prometheus (hoặc tương đương) cào định kỳ rồi lưu chuỗi thời gian để vẽ biểu đồ và cảnh báo. Bản thân Kubernetes không lưu metrics — như log, nó chỉ phơi ra, phần thu thập là hệ thống ngoài. (metrics-server ở Bài 39 là chuyện khác: nó cào một tập nhỏ để phục vụ HPA, không phải kho metrics đầy đủ.)

API Priority and Fairness

apiserver có ngân sách request giới hạn. Nếu một controller lỗi quay vòng gọi API dồn dập, nó có thể chiếm hết ngân sách và làm leader-election, node heartbeat đói theo — cụm mất ổn định. APF (ổn định từ 1.29) chống điều đó: phân loại request vào nhiều mức ưu tiên, mỗi mức có hạn đồng thời riêng, để một luồng hỗn không bóp nghẹt luồng khác.

Hai loại object điều khiển nó. PriorityLevelConfiguration định nghĩa các mức và phần băng thông mỗi mức:

kubectl get prioritylevelconfigurations
NAME              TYPE      NOMINALCONCURRENCYSHARES   QUEUES   HANDSIZE   QUEUELENGTHLIMIT
catch-all         Limited   5                          <none>   <none>     <none>
exempt            Exempt    <none>                     <none>   <none>     <none>
leader-election   Limited   10                         16       4          50
node-high         Limited   40                         64       6          50
system            Limited   30                         64       6          50
workload-high     Limited   40                         128      6          50
workload-low      Limited   100                        128      6          50

FlowSchema quyết request nào vào mức nào, theo người gửi/resource, và tách thành các luồng (theo user hoặc namespace):

kubectl get flowschemas
NAME                      PRIORITYLEVEL     MATCHINGPRECEDENCE   DISTINGUISHERMETHOD
exempt                    exempt            1                    <none>
probes                    exempt            2                    <none>
system-leader-election    leader-election   100                  ByUser
system-nodes              system            500                  ByUser
kube-controller-manager   workload-high     800                  ByNamespace
kube-scheduler            workload-high     800                  ByNamespace

Đọc một dòng: request leader-election khớp FlowSchema system-leader-election (precedence 100, ưu tiên hơn precedence cao), vào mức leader-election, tách luồng ByUser. Mức exempt đặc biệt, bỏ qua mọi giới hạn, dành cho health check và request sống còn (probes, exempt). Cụm không cần cấu hình gì: bộ FlowSchema và PriorityLevelConfiguration này dựng sẵn.

Trạng thái sống của APF

apiserver phơi trạng thái APF qua một endpoint debug — thấy ngay mức nào đang bận, có request nào bị từ chối:

kubectl get --raw /debug/api_priority_and_fairness/dump_priority_levels
PriorityLevelName, ..., ExecutingRequests, DispatchedRequests, RejectedRequests, ...
catch-all,         ..., 0,                 7,                  0,
exempt,            ..., 1,                 15451,              0,
leader-election,   ..., 0,                 39746,              0,
node-high,         ..., 0,                 2479,               0,

DispatchedRequests cho thấy phân bổ tải thật: leader-election đã xử lý 39746 request, exempt 15451 (health check liên tục). Cột đáng canh là RejectedRequests, đang 0 ở mọi mức, nghĩa là cụm chưa quá tải. Khi một mức bão hòa và hàng đợi đầy, request mới nhận 429 Too Many Requests và số này tăng ở đúng mức đó — chỉ ra ngay luồng nào đang gây áp lực, thay vì để cả apiserver chậm đều. Đây là chỗ APF vừa bảo vệ vừa quan sát được: không chỉ chặn quá tải mà còn nói cho biết quá tải ở đâu.

Traces

Mảnh thứ ba của observability là tracing — theo một request qua các thành phần để tìm chỗ chậm. apiserver và kubelet hỗ trợ xuất trace theo OpenTelemetry, bật qua --tracing-config-file. Cụm này không bật:

ssh controller-0 'grep -c tracing-config-file /etc/systemd/system/kube-apiserver.service'
0

Khi bật, apiserver gửi span tới một OTel collector, và ta thấy được, ví dụ, một request CREATE pod tốn thời gian ở admission webhook (Bài 58) hay ở etcd. Trace bù cho metrics: metrics nói chậm, trace nói chậm ở đâu. Cụm tự dựng để mặc định tắt vì nó cần một collector ngoài; bật là thêm --tracing-config-file trỏ tới collector đó.

🧹 Dọn dẹp

Bài này chỉ đọc endpoint /metrics, object APF dựng sẵn, và endpoint debug — không tạo gì. Không có gì để dọn. Lệnh dùng trong bài ở github.com/nghiadaulau/kubernetes-from-scratch, thư mục 66-metrics-apf.

Tổng kết

Observability của Kubernetes ba mảnh. Metrics: apiserver và kubelet phơi /metrics định dạng Prometheus (apiserver_request_total, kubelet_running_containers...), bản thân cụm không lưu — Prometheus ngoài cào và giữ chuỗi thời gian. API Priority and Fairness vừa bảo vệ apiserver vừa quan sát được: PriorityLevelConfiguration chia ngân sách request thành các mức (system, leader-election, workload-high/low, catch-all, exempt), FlowSchema phân request vào mức theo người gửi/resource và tách luồng, và endpoint /debug/api_priority_and_fairness cho thấy DispatchedRequests/RejectedRequests từng mức — 429 ở một mức chỉ thẳng luồng gây tải. Traces (OTel, --tracing-config-file) theo request qua các thành phần để chỉ chỗ chậm, mặc định tắt vì cần collector ngoài. Cả ba đều phơi-tại-cụm, thu-ở-ngoài — đúng triết lý của Kubernetes về observability.

Bài 67 khép Part XIII bằng các cơ chế vận hành còn lại: leader election giữ cho controller-manager và scheduler chỉ có một bản chủ động trong HA, cách quản addon, và node autoscaling — cụm tự thêm/bớt node theo tải.

Related Posts