在 Kubernetes 下,Promethues 通過與 Kubernetes API 集成,主要支持5中服務發現模式,分別是:Node
、Service
、Pod
、Endpoints
、Ingress
。
我們通過 kubectl 命令可以很方便的獲取到當前集群中的所有節點信息:
[root@master1 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
master1 Ready master 40d v1.19.3
node1 Ready <none> 40d v1.19.3
node2 Ready <none> 40d v1.19.3
但是要讓 Prometheus 也能夠獲取到當前集群中的所有節點信息的話,我們就需要利用 Node 的服務發現模式,同樣的,在 prometheus.yml
文件中配置如下的 job 任務即可:
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
# 然后apply這個cm
其實現在到頁面上查看會報錯,查看Promethues 日志:
orbidden: User \"system:serviceaccount:kube-mon:default\" cannot list resource \"nodes\" in API group \"\" at the cluster scope"
level=error ts=2021-02-12T14:15:17.104Z caller=klog.go:94 component=k8s_client_runtime func=ErrorDepth msg="/app/discovery/kubernetes/kubernetes.go:335: Failed to list *v1.Node: nodes is forbidden: User \"system:serviceaccount:kube-mon:default\" cannot list resource \"nodes\" in API group \"\" at the cluster scope"
level=error ts=2021-02-12T14:15:18.108Z caller=klog.go:94 component=k8s_client_runtime func=ErrorDepth msg="/app/discovery/kubernetes/kubernetes.go:335: Failed to list *v1.Node: nodes is forbidden: User \"system:serviceaccount:kube-mon:default\" cannot list resource \"nodes\" in API group \"\" at the cluster scope"
level=error ts=2021-02-12T14:15:19.112Z caller=klog.go:94 component=k8s_client_runtime func=ErrorDepth msg="/app/discovery/kubernetes/kubernetes.go:335: Failed to list *v1.Node: nodes is forbidden: User \"system:serviceaccount:kube-mon:default\" cannot list resource \"nodes\" in API group \"\" at the cluster scope"
實際上就是沒權限,所以我們得給他加權限
# 默認的sa是沒有權限的
[root@master1 prometheus]# kubectl get sa default -n kube-mon
NAME SECRETS AGE
default 1 6h37m
步驟一
在創建Prometheus的deployment中加上
# 位置:Deployment.spec.template.spec下面
serviceAccountName: prometheus # 指定自己創建的sa
"""
template:
metadata:
labels:
app: prometheus # 這個labels要跟selector的一致,才能匹配上
spec:
serviceAccountName: prometheus # 指定自己創建的sa
volumes: # 真正掛載,這里需要用到底下聲明掛載的name
- name: config # 這里需要跟底下聲明掛載的name(config)保持一致
configMap:
name: prometheus-config # configmap name
"""
步驟二
創建SA,創建文件prometheus-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus # 名字要跟deployment中的那個serviceAccountName保持一直
namespace: kube-mon
步驟三
創建集群角色,且做好綁定。文件prometheus-rbac.yaml
# 先創建一個集群角色,給定以下一堆權限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- apiGroups:
- ""
resources:
- nodes
- services
- endpoints
- pods
- nodes/proxy
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
- nodes/metrics
verbs:
- get
- nonResourceURLs:
- /metrics
verbs:
- get
---
# 然后做集群角色綁定,把集群角色跟SA綁定在一起即可
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: prometheus
roleRef:
apiGroup: rbac.authorization.k8s.io # 使用這個API
kind: ClusterRole # 指定綁定的ClusterRole名字是prometheus
name: prometheus
subjects: # 指定綁定的kind為ServiceAccount,name is prometheus,namespace is kube-mon
- kind: ServiceAccount
name: prometheus
namespace: kube-mon
# 所以現在這個namespace下的Pod就有以上權限了
步驟四
然后重新apply這幾個文件
[root@master1 prometheus]# ll
total 24
-rw-r--r-- 1 root root 1926 Feb 12 21:54 prome-node-exporter.yaml
-rw-r--r-- 1 root root 968 Feb 12 20:37 prome-redis.yaml
-rw-r--r-- 1 root root 574 Feb 12 22:11 prometheus-cm.yaml
-rw-r--r-- 1 root root 2247 Feb 12 22:52 prometheus-deploy.yaml
-rw-r--r-- 1 root root 861 Feb 12 17:30 prometheus-rbac.yaml
-rw-r--r-- 1 root root 451 Feb 12 16:28 prometheus-svc.yaml
[root@master1 prometheus]# kubectl apply -f .
步驟五、
現在頁面查看還是有問題的
我們可以看到上面的 kubernetes-nodes
這個 job 任務已經自動發現了我們5個 node 節點,但是在獲取數據的時候失敗了,出現了類似於下面的錯誤信息:
server returned HTTP status 400 Bad Request
這個是因為 prometheus 去發現 Node 模式的服務的時候,訪問的端口默認是10250,而默認是需要認證的 https 協議才有權訪問的,但實際上我們並不是希望讓去訪問10250端口的 /metrics
接口,而是 node-exporter
綁定到節點的 9100 端口,所以我們應該將這里的 10250
替換成 9100
,但是應該怎樣替換呢?
這里我們就需要使用到 Prometheus 提供的 relabel_configs
中的 replace
能力了,relabel
可以在 Prometheus 采集數據之前,通過 Target 實例的 Metadata
信息,動態重新寫入 Label 的值。除此之外,我們還能根據 Target 實例的 Metadata
信息選擇是否采集或者忽略該 Target 實例。比如我們這里就可以去匹配 __address__
這個 Label 標簽,然后替換掉其中的端口,如果你不知道有哪些 Label 標簽可以操作的話,可以將鼠標🎒移動到 Targets 的標簽區域,其中顯示的 Before relabeling
區域都是我們可以操作的標簽:
現在我們來替換掉端口,修改 ConfigMap:(此處忽略,用下面的最終版本)
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
action: replace
這里就是一個正則表達式,去匹配 __address__
這個標簽,然后將 host 部分保留下來,port 替換成了 9100,現在我們重新更新配置文件,執行 reload 操作,然后再去看 Prometheus 的 Dashboard 的 Targets 路徑下面 kubernetes-nodes 這個 job 任務是否正常了:
我們可以看到現在已經正常了,但是還有一個問題就是我們采集的指標數據 Label 標簽就只有一個節點的 hostname,這對於我們在進行監控分組分類查詢的時候帶來了很多不方便的地方,要是我們能夠將集群中 Node 節點的 Label 標簽也能獲取到就很好了。這里我們可以通過 labelmap
這個屬性來將 Kubernetes 的 Label 標簽添加為 Prometheus 的指標數據的標簽:
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
action: replace
- action: labelmap # 這個
regex: __meta_kubernetes_node_label_(.+)
# 熱更新,ip是prometheusPod的Ip
[root@master1 ~]# curl -X POST "http://10.244.1.139:9090/-/reload"
另外由於 kubelet 也自帶了一些監控指標數據,就上面我們提到的 10250 端口,所以我們這里也把 kubelet 的監控任務也一並配置上:
- job_name: 'kubernetes-kubelet'
kubernetes_sd_configs:
- role: node
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
但是這里需要特別注意的是這里必須使用 https
協議訪問,這樣就必然需要提供證書,我們這里是通過配置 insecure_skip_verify: true
來跳過了證書校驗,但是除此之外,要訪問集群的資源,還必須要有對應的權限才可以,也就是對應的 ServiceAccount 棒的 權限允許才可以,我們這里部署的 prometheus 關聯的 ServiceAccount 對象前面我們已經提到過了,這里我們只需要將 Pod 中自動注入的 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
和 /var/run/secrets/kubernetes.io/serviceaccount/token
文件配置上,就可以獲取到對應的權限了。
現在我們再去更新下配置文件,執行 reload 操作,讓配置生效,然后訪問 Prometheus 的 Dashboard 查看 Targets 路徑:
到這里我們就把 Kubernetes 集群節點使用 Prometheus 監控起來了,接下來我們再來和大家學習下怎樣監控 Pod 或者 Service 之類的資源對象。
apiVersion: v1
kind: Service
metadata:
annotations:
prometheus.io/port: "9153" # metrics 接口的端口
prometheus.io/scrape: "true" # 這個注解可以讓prometheus自動發現