天天看點

如何監控Kubernetes APIServer,超詳細的文章

寫在前面

如果是用的公有雲托管的 Kubernetes 叢集,控制面的元件都交由雲廠商托管的,那作為客戶的我們就省事了,基本不用操心 APIServer 的運維。個人也推薦使用雲廠商這個服務,畢竟 Kubernetes 還是有點複雜的,更新也不好搞,我們自己來維護整個叢集,成本效益有點低。當然,如果因為各種原因最後我們還是要維護控制面這些元件,那就要好好看看本系列接下來的幾篇部落格了。

黑盒測試

APIServer 在 Kubernetes 架構中非常核心,是所有 API 的入口,APIServer 也暴露了 metrics 資料,我們嘗試擷取一下:

[[email protected] etcd]# ss -tlpn|grep apiserver
LISTEN 0      128                *:6443             *:*    users:(("kube-apiserver",pid=164445,fd=7))

[[email protected] etcd]# curl -s http://localhost:6443/metrics
Client sent an HTTP request to an HTTPS server.

[[email protected] etcd]# curl -s -k https://localhost:6443/metrics
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"/metrics\"",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}
           

解釋一下上面的指令和結果。首先我通過 ss 指令檢視 apiserver 子產品監聽在哪些端口,發現這個程序在 6443 端口有監聽。然後,使用 curl 指令請求 6443 的 metrics 接口,結果又說這是一個 HTTPS Server,不能用 HTTP 協定請求。好,那我用 HTTPS 協定請求,自簽證書,加了 -k 參數,傳回 Forbidden,說沒權限通路 

/metrics

 接口。OK,那看來是需要 Token 鑒權,我們建立一下相關的 ServiceAccount。

準備認證資訊

下面的内容可以儲存為 auth-server.yaml。

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: categraf
rules:
  - apiGroups: [""]
    resources:
      - nodes
      - nodes/metrics
      - nodes/stats
      - nodes/proxy
      - services
      - endpoints
      - pods
    verbs: ["get", "list", "watch"]
  - apiGroups:
      - extensions
      - networking.k8s.io
    resources:
      - ingresses
    verbs: ["get", "list", "watch"]
  - nonResourceURLs: ["/metrics", "/metrics/cadvisor"]
    verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: categraf
  namespace: flashcat
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: categraf
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: categraf
subjects:
- kind: ServiceAccount
  name: categraf
  namespace: flashcat
           

在上一節《Kubernetes監控手冊05-監控Kubelet》中,我們為 daemonset 建立過認證資訊,那個認證資訊主要是用于調用 kubelet 的接口。而這次我們要調用的是 apiserver 的接口,是以增加了一些權限點,當然,上例 yaml 中給出的權限點有點多,沒關系,反正都是隻讀的,後面再需要其他權限的時候,省的再建立新的 ServiceAccount 了。與上一講相比,這次 ServiceAccount 名字改成了 categraf,與上一講用到的 ServiceAccount 區分開。

通過下面的指令建立相關内容,然後檢視一下是否建立成功:

[[email protected] yamls]# kubectl apply -f auth-server.yaml -n flashcat
clusterrole.rbac.authorization.k8s.io/categraf unchanged
serviceaccount/categraf unchanged
clusterrolebinding.rbac.authorization.k8s.io/categraf unchanged

[[email protected] yamls]# kubectl get sa categraf -n flashcat
NAME       SECRETS   AGE
categraf   1         7h13m

[[email protected] yamls]# kubectl get sa categraf -n flashcat -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"categraf","namespace":"flashcat"}}
  creationTimestamp: "2022-11-28T05:00:17Z"
  name: categraf
  namespace: flashcat
  resourceVersion: "127151612"
  uid: 8b473b31-ce09-4abe-ae55-ea799160a9d5
secrets:
- name: categraf-token-6whbs

[[email protected] yamls]# kubectl get secret categraf-token-6whbs -n flashcat
NAME                   TYPE                                  DATA   AGE
categraf-token-6whbs   kubernetes.io/service-account-token   3      7h15m
           

上例中,因為我之前建立過了,是以顯示的是 unchanged,擷取 sa 的時候,可以看到 AGE 已經七個多小時了。通過 

-o yaml

 可以看到 sa 對應的 secret 的名字,最下面那一行,可以看到 secret 名字是 categraf-token-6whbs。然後我們用這個 secret 中的 token 來調用一下 APIServer 試試:

[[email protected] yamls]# token=`kubectl get secret categraf-token-6whbs -n flashcat -o jsonpath={.data.token} | base64 -d`
[[email protected] yamls]# curl -s -k -H "Authorization: Bearer $token" https://localhost:6443/metrics > metrics
[[email protected] yamls]# head -n 6 metrics
# HELP aggregator_openapi_v2_regeneration_count [ALPHA] Counter of OpenAPI v2 spec regeneration count broken down by causing APIService name and reason.
# TYPE aggregator_openapi_v2_regeneration_count counter
aggregator_openapi_v2_regeneration_count{apiservice="*",reason="startup"} 0
aggregator_openapi_v2_regeneration_count{apiservice="k8s_internal_local_delegation_chain_0000000002",reason="update"} 0
aggregator_openapi_v2_regeneration_count{apiservice="v1beta1.metrics.k8s.io",reason="add"} 0
aggregator_openapi_v2_regeneration_count{apiservice="v1beta1.metrics.k8s.io",reason="update"} 0
           

OK,這個新的 Token 是可以擷取到資料的了,權限認證通過。

采集原理

既然 Token 已經有了,采集器抓取 APIServer 的資料的時候,隻要在 Header 裡傳入這個 Token 理論上就可以拿到資料了。如果 APIServer 是二進制方式部署,咱們就直接通過 Categraf 的 Prometheus 插件來抓取就可以了。如果 APIServer 是部署在 Kubernetes 的容器裡,咱們最好是使用服務發現機制來做。

支援 Kubernetes 服務發現的 agent 有不少,但是要說最原汁原味的還是 Prometheus 自身,Prometheus 新版本(v2.32.0)支援了 agent mode 模式,即把 Prometheus 程序當做采集器 agent,采集了資料之後通過 remote write 方式傳給中心(這裡使用早就準備好的 Nightingale 作為資料接收服務端)。那這裡我就使用 Prometheus 的 agent mode 方式來采集 APIServer。

部署 agent mode prometheus

首先準備一下 Prometheus agent 需要的配置檔案,我們做成一個 ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-agent-conf
  labels:
    name: prometheus-agent-conf
  namespace: flashcat
data:
  prometheus.yml: |-
    global:
      scrape_interval: 15s
      evaluation_interval: 15s
    scrape_configs:
      - job_name: 'apiserver'
        kubernetes_sd_configs:
        - role: endpoints
        scheme: https
        tls_config:
          insecure_skip_verify: true
        authorization:
          credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
        relabel_configs:
        - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
          action: keep
          regex: default;kubernetes;https
    remote_write:
    - url: 'http://10.206.0.16:19000/prometheus/v1/write'    
           

可以把上面的内容儲存為 prometheus-agent-configmap.yaml,然後 

kubectl -f prometheus-agent-configmap.yaml

 建立一下即可。

有了配置了,下面我們就可以部署 Prometheus 了,要把 Prometheus 程序當做 agent 來用,需要啟用這個 feature,通過指令行參數 

--enable-feature=agent

 即可輕松啟用了,我們把 agent mode 模式的 Prometheus 部署成一個 Deployment,單副本。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus-agent
  namespace: flashcat
  labels:
    app: prometheus-agent
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus-agent
  template:
    metadata:
      labels:
        app: prometheus-agent
    spec:
      serviceAccountName: categraf
      containers:
        - name: prometheus
          image: prom/prometheus
          args:
            - "--config.file=/etc/prometheus/prometheus.yml"
            - "--web.enable-lifecycle"
            - "--enable-feature=agent"
          ports:
            - containerPort: 9090
          resources:
            requests:
              cpu: 500m
              memory: 500M
            limits:
              cpu: 1
              memory: 1Gi
          volumeMounts:
            - name: prometheus-config-volume
              mountPath: /etc/prometheus/
            - name: prometheus-storage-volume
              mountPath: /prometheus/
      volumes:
        - name: prometheus-config-volume
          configMap:
            defaultMode: 420
            name: prometheus-agent-conf
        - name: prometheus-storage-volume
          emptyDir: {}
           

要特别注意 

serviceAccountName: categraf

 這一行内容别忘記了,以上 yaml 内容儲存為 prometheus-agent-deployment.yaml,然後 apply 一下:

[[email protected] yamls]$ kubectl apply -f prometheus-agent-deployment.yaml
deployment.apps/prometheus-agent created
           

可以通過 

kubectl logs <podname> -n flashcat

 檢視剛才建立的 prometheus-agent-xx 那個 Pod 的日志,如果沒有報錯,理論上就問題不大了。

檢視監控資料

在即時查詢裡查一下 

apiserver_request_total

 這個名額,如果可以查到,就說明資料上報是正常的。孔飛老師之前整理過夜莺的 Kubernetes / Apiserver 監控大盤,可以導入測試,位址在這裡。效果如下:

如何監控Kubernetes APIServer,超詳細的文章

另外,Apiserver 的關鍵名額的含義,孔飛老師也做了整理,我也給摘過來了:

# HELP apiserver_request_duration_seconds [STABLE] Response latency distribution in seconds for each verb, dry run value, group, version, resource, subresource, scope and component.
# TYPE apiserver_request_duration_seconds histogram
apiserver響應的時間分布,按照url 和 verb 分類
一般按照instance和verb+時間 彙聚

# HELP apiserver_request_total [STABLE] Counter of apiserver requests broken out for each verb, dry run value, group, version, resource, scope, component, and HTTP response code.
# TYPE apiserver_request_total counter
apiserver的請求總數,按照verb、 version、 group、resource、scope、component、 http傳回碼分類統計

# HELP apiserver_current_inflight_requests [STABLE] Maximal number of currently used inflight request limit of this apiserver per request kind in last second.
# TYPE apiserver_current_inflight_requests gauge
最大并發請求數, 按mutating(非get list watch的請求)和readOnly(get list watch)分别限制
超過max-requests-inflight(預設值400)和max-mutating-requests-inflight(預設200)的請求會被限流
apiserver變更時要注意觀察,也是回報叢集容量的一個重要名額

# HELP apiserver_response_sizes [STABLE] Response size distribution in bytes for each group, version, verb, resource, subresource, scope and component.
# TYPE apiserver_response_sizes histogram
apiserver 響應大小,機關byte, 按照verb、 version、 group、resource、scope、component分類統計

# HELP watch_cache_capacity [ALPHA] Total capacity of watch cache broken by resource type.
# TYPE watch_cache_capacity gauge
按照資源類型統計的watch緩存大小

# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
每秒鐘使用者态和系統态cpu消耗時間, 計算apiserver程序的cpu的使用率

# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
apiserver的記憶體使用量(機關:Byte)

# HELP workqueue_adds_total [ALPHA] Total number of adds handled by workqueue
# TYPE workqueue_adds_total counter
apiserver中包含的controller的工作隊列,已處理的任務總數

# HELP workqueue_depth [ALPHA] Current depth of workqueue
# TYPE workqueue_depth gauge
apiserver中包含的controller的工作隊列深度,表示目前隊列中要處理的任務的數量,數值越小越好 
例如APIServiceRegistrationController admission_quota_controller
           

相關文章

  • Kubernetes監控手冊01-體系介紹
  • Kubernetes監控手冊02-宿主監控概述
  • Kubernetes監控手冊03-宿主監控實操
  • Kubernetes監控手冊04-監控Kube-Proxy
  • Kubernetes監控手冊05-監控Kubelet

關于作者

本文作者秦曉輝,Flashcat合夥人,文章内容是Flashcat技術團隊共同沉澱的結晶,作者做了編輯整理,我們會持續輸出監控、穩定性保障相關的技術文章,文章可轉載,轉載請注明出處,尊重技術人員的成果。

如果對 Nightingale、Categraf、Prometheus 等技術感興趣,歡迎加入我們的微信群組,聯系我(picobyte)拉入部落,和社群同仁一起探讨監控技術。

繼續閱讀