Prometheus监控kubernetes
Prometheus監控 kubernetes
咱們的目標通過Prometheus監控Kubernetes集群。
1.使用ConfigMaps管理Prometheus的配置文件
創建prometheus-config.yml文件,并寫入以下內容
apiVersion: v1 kind: ConfigMap metadata:name: prometheus-config data:prometheus.yml: |global:scrape_interval: 15sevaluation_interval: 15sscrape_configs:- job_name: 'prometheus'static_configs:- targets: ['localhost:9090']使用kubectl命令行工具,在命名空間default創建ConfigMap資源:
kubectl create -f prometheus-config.yml configmap "prometheus-config" created2.使用Deployment部署Prometheus
當ConfigMap資源創建成功后,我們就可以通過Volume掛載的方式,將Prometheus的配置文件掛載到容器中。 這里我們通過Deployment部署Prometheus Server實例,創建prometheus-deployment.yml文件,并寫入以下內容:
apiVersion: v1 kind: "Service" metadata:name: prometheuslabels:name: prometheus spec:ports:- name: prometheusprotocol: TCPport: 9090targetPort: 9090selector:app: prometheustype: NodePort --- apiVersion: apps/v1 kind: Deployment metadata:labels:name: prometheusname: prometheus spec:replicas: 1selector:matchLabels:app: prometheustemplate:metadata:labels:app: prometheusspec:containers:- name: prometheusimage: prom/prometheus:v2.2.1command:- "/bin/prometheus"args:- "--config.file=/etc/prometheus/prometheus.yml"ports:- containerPort: 9090protocol: TCPvolumeMounts:- mountPath: "/etc/prometheus"name: prometheus-configvolumes:- name: prometheus-configconfigMap:name: prometheus-config該文件中分別定義了Service和Deployment,Service類型為NodePort,這樣我們可以通過虛擬機IP和端口訪問到Prometheus實例。為了能夠讓Prometheus實例使用ConfigMap中管理的配置文件,這里通過volumes聲明了一個磁盤卷。并且通過volumeMounts將該磁盤卷掛載到了Prometheus實例的/etc/prometheus目錄下。
使用以下命令創建資源,并查看資源的創建情況:
[root@master-1 prometheus]# kubectl create -f prometheus-deployment.yml service "prometheus" created deployment "prometheus" created[root@master-1 prometheus]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-deploy-fb74b55d4-gz6cz 1/1 Running 2 (2d3h ago) 3d prometheus-b487b9dfc-n74nv 1/1 Running 0 2d1h [root@master-1 prometheus]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d1h nginx-svc NodePort 10.104.88.55 <none> 80:30523/TCP 3d prometheus NodePort 10.100.208.234 <none> 9090:32053/TCP 2d2h我們可以通過worker虛擬機的IP地址和端口32053訪問http://192.168.5.21:32053到Prometheus的服務。
但是這里只有Prometheus 9000的監控。接下來,我們配置Prometheus的config 和 rbac開始監控k8s.
3.kubernetes的服務發現
3.1kubernetes的訪問授權
為了能夠讓Prometheus能夠訪問收到認證保護的Kubernetes API,我們首先需要做的是,對Prometheus進行訪問授權。在Kubernetes中主要使用基于角色的訪問控制模型(Role-Based Access Control),用于管理Kubernetes下資源訪問權限。首先我們需要在Kubernetes下定義角色(ClusterRole),并且為該角色賦予相應的訪問權限。同時創建Prometheus所使用的賬號(ServiceAccount),最后則是將該賬號與角色進行綁定(ClusterRoleBinding)。這些所有的操作在Kubernetes同樣被視為是一系列的資源,可以通過YAML文件進行描述并創建,這里創建prometheus-rbac-setup.yml文件,并寫入以下內容:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata:name: prometheus rules: - apiGroups: [""]resources:- nodes- nodes/proxy- services- endpoints- podsverbs: ["get", "list", "watch"] - apiGroups:- extensionsresources:- ingressesverbs: ["get", "list", "watch"] - nonResourceURLs: ["/metrics"]verbs: ["get"] --- apiVersion: v1 kind: ServiceAccount metadata:name: prometheusnamespace: default --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata:name: prometheus roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: prometheus subjects: - kind: ServiceAccountname: prometheusnamespace: default其中需要注意的是ClusterRole是全局的,不需要指定命名空間。而ServiceAccount是屬于特定命名空間的資源。通過kubectl命令創建RBAC對應的各個資源:
$ kubectl create -f prometheus-rbac-setup.yml clusterrole "prometheus" created serviceaccount "prometheus" created clusterrolebinding "prometheus" created在完成角色權限以及用戶的綁定之后,就可以指定Prometheus使用特定的ServiceAccount創建Pod實例。修改prometheus-deployment.yml文件,并添加serviceAccountName和serviceAccount定義:
apiVersion: v1 kind: "Service" metadata:name: prometheuslabels:name: prometheus spec:ports:- name: prometheusprotocol: TCPport: 9090targetPort: 9090selector:app: prometheustype: NodePort --- apiVersion: apps/v1 kind: Deployment metadata:labels:name: prometheusname: prometheus spec:replicas: 1selector:matchLabels:app: prometheustemplate:metadata:labels:app: prometheusspec:serviceAccountName: prometheus # 添加ServiceAccountName containers:- name: prometheusimage: prom/prometheus:v2.2.1command:- "/bin/prometheus"args:- "--config.file=/etc/prometheus/prometheus.yml"ports:- containerPort: 9090protocol: TCPvolumeMounts:- mountPath: "/etc/prometheus"name: prometheus-configvolumes:- name: prometheus-configconfigMap:name: prometheus-config通過kubectl apply對Deployment進行變更升級:
$ kubectl apply -f prometheus-deployment.yml service "prometheus" configured deployment "prometheus" configured[root@master-1 prometheus]# kubectl get pod NAME READY STATUS RESTARTS AGE prometheus-b487b9dfc-n73dv 0/1 Terminating 0 3d prometheus-b487b9dfc-n74nv 1/1 Running 0 2d1h指定ServiceAccount創建的Pod實例中,會自動將用于訪問Kubernetes API的CA證書以及當前賬戶對應的訪問令牌文件掛載到Pod實例的/var/run/secrets/kubernetes.io/serviceaccount/目錄下,可以通過以下命令進行查看:
[root@master-1 prometheus]# kubectl exec -it prometheus-b487b9dfc-n74nv -- ls /var/run/secrets/kubernetes.io/serviceaccount/ ca.crt namespace token3.2服務發現
在Kubernetes下,Promethues通過與Kubernetes API集成目前主要支持5種服務發現模式,分別是:Node、Service、Pod、Endpoints、Ingress。
通過kubectl命令行,可以方便的獲取到當前集群中的所有節點信息:
[root@master-1 prometheus]# kubectl get node -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME master-1 Ready control-plane,master 3d1h v1.22.1 192.168.5.11 <none> CentOS Linux 7 (Core) 3.10.0-1160.49.1.el7.x86_64 docker://20.10.12 master-2 Ready control-plane,master 3d1h v1.22.1 192.168.5.12 <none> CentOS Linux 7 (Core) 3.10.0-1160.49.1.el7.x86_64 docker://20.10.12 master-3 Ready control-plane,master 3d1h v1.22.1 192.168.5.13 <none> CentOS Linux 7 (Core) 3.10.0-1160.49.1.el7.x86_64 docker://20.10.12 worker-1 Ready <none> 3d1h v1.22.1 192.168.5.21 <none> CentOS Linux 7 (Core) 3.10.0-1160.49.1.el7.x86_64 docker://20.10.12為了能夠讓Prometheus能夠獲取到當前集群中所有節點的信息,在Promtheus的配置文件中,我們添加如下Job配置:
- job_name: 'kubernetes-nodes'tls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: node通過指定kubernetes_sd_config的模式為node,Prometheus會自動從Kubernetes中發現到所有的node節點并作為當前Job監控的Target實例。如下所示,這里需要指定用于訪問Kubernetes API的ca以及token文件路徑。
對于Ingress,Service,Endpoints, Pod的使用方式也是類似的,下面給出了一個完整Prometheus配置的示例:
apiVersion: v1 data:prometheus.yml: |-global:scrape_interval: 15s evaluation_interval: 15sscrape_configs:- job_name: 'kubernetes-nodes'tls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: node- job_name: 'kubernetes-service'tls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: service- job_name: 'kubernetes-endpoints'tls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: endpoints- job_name: 'kubernetes-ingress'tls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: ingress- job_name: 'kubernetes-pods'tls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: podkind: ConfigMap metadata:name: prometheus-config更新Prometheus配置文件,并重建Prometheus實例:
$ kubectl apply -f prometheus-config.yml configmap "prometheus-config" configured[root@master-1 prometheus]# kubectl get pod NAME READY STATUS RESTARTS AGE prometheus-b487b9dfc-n74nv 1/1 Running 0 2d1h[root@master-1 prometheus]# kubectl delete pod prometheus-b487b9dfc-n74nv pod "prometheus-b487b9dfc-n74nv" deleted[root@master-1 prometheus]# kubectl get pod NAME READY STATUS RESTARTS AGE prometheus-b487b9dfc-s2rrr 1/1 Running 0 5sPrometheus使用新的配置文件重建之后,打開Prometheus UI,通過Service Discovery頁面可以查看到當前Prometheus通過Kubernetes發現的所有資源對象了:
同時Prometheus會自動將該資源的所有信息,并通過標簽的形式體現在Target對象上。如下所示,是Promthues獲取到的Node節點的標簽信息:
__address__="192.168.5.13:10250" __meta_kubernetes_node_address_Hostname="master-3" __meta_kubernetes_node_address_InternalIP="192.168.5.13" __meta_kubernetes_node_annotation_flannel_alpha_coreos_com_backend_data="{"VNI":1,"VtepMAC":"56:87:0f:ed:d7:eb"}" __meta_kubernetes_node_annotation_flannel_alpha_coreos_com_backend_type="vxlan" __meta_kubernetes_node_annotation_flannel_alpha_coreos_com_kube_subnet_manager="true" __meta_kubernetes_node_annotation_flannel_alpha_coreos_com_public_ip="192.168.5.13" __meta_kubernetes_node_annotation_kubeadm_alpha_kubernetes_io_cri_socket="/var/run/dockershim.sock" __meta_kubernetes_node_annotation_node_alpha_kubernetes_io_ttl="0" __meta_kubernetes_node_annotation_volumes_kubernetes_io_controller_managed_attach_detach="true" __meta_kubernetes_node_label_beta_kubernetes_io_arch="amd64" __meta_kubernetes_node_label_beta_kubernetes_io_os="linux" __meta_kubernetes_node_label_kubernetes_io_arch="amd64" __meta_kubernetes_node_label_kubernetes_io_hostname="master-3" __meta_kubernetes_node_label_kubernetes_io_os="linux" __meta_kubernetes_node_label_node_kubernetes_io_exclude_from_external_load_balancers="" __meta_kubernetes_node_label_node_role_kubernetes_io_control_plane="" __meta_kubernetes_node_label_node_role_kubernetes_io_master="" __meta_kubernetes_node_name="master-3" __metrics_path__="/metrics" __scheme__="http" instance="master-3" job="kubernetes-nodes"目前為止,我們已經能夠通過Prometheus自動發現Kubernetes集群中的各類資源以及其基本信息。不過,如果現在查看Promtheus的Target狀態頁面,結果可能會讓人不太滿意:
雖然Prometheus能夠自動發現所有的資源對象,并且將其作為Target對象進行數據采集。 但并不是所有的資源對象都是支持Promethues的,并且不同類型資源對象的采集方式可能是不同的。因此,在實際的操作中,我們需要有明確的監控目標,并且針對不同類型的監控目標設置不同的數據采集方式。
接下來,我們將利用Promtheus的服務發現能力,實現對Kubernetes集群的全面監控。
4.監控kubernetes集群
我們介紹了Promtheus在Kubernetes下的服務發現能力,并且通過kubernetes_sd_config實現了對Kubernetes下各類資源的自動發現。在本小節中,我們將帶領讀者利用Promethues提供的服務發現能力,實現對Kubernetes集群以及其中部署的各類資源的自動化監控。
下表中,梳理了監控Kubernetes集群監控的各個維度以及策略:
| 從集群各節點kubelet組件中獲取節點kubelet的基本運行狀態的監控指標 | node | 白盒監控 | kubelet |
| 從集群各節點kubelet內置的cAdvisor中獲取,節點中運行的容器的監控指標 | node | 白盒監控 | kubelet |
| 從部署到各個節點的Node Exporter中采集主機資源相關的運行資源 | node | 白盒監控 | node exporter |
| 對于內置了Promthues支持的應用,需要從Pod實例中采集其自定義監控指標 | pod | 白盒監控 | custom pod |
| 獲取API Server組件的訪問地址,并從中獲取Kubernetes集群相關的運行監控指標 | endpoints | 白盒監控 | api server |
| 獲取集群中Service的訪問地址,并通過Blackbox Exporter獲取網絡探測指標 | service | 黑盒監控 | blackbox exporter |
| 獲取集群中Ingress的訪問信息,并通過Blackbox Exporter獲取網絡探測指標 | ingress | 黑盒監控 | blackbox exporter |
4.1從Kubelet獲取節點運行狀態
Kubelet組件運行在Kubernetes集群的各個節點中,其負責維護和管理節點上Pod的運行狀態。kubelet組件的正常運行直接關系到該節點是否能夠正常的被Kubernetes集群正常使用。
基于Node模式,Prometheus會自動發現Kubernetes中所有Node節點的信息并作為監控的目標Target。 而這些Target的訪問地址實際上就是Kubelet的訪問地址,并且Kubelet實際上直接內置了對Promtheus的支持。
修改prometheus.yml配置文件,并添加以下采集任務配置:
- job_name: 'kubernetes-kubelet'scheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: noderelabel_configs:- action: labelmapregex: __meta_kubernetes_node_label_(.+)這里使用Node模式自動發現集群中所有Kubelet作為監控的數據采集目標,同時通過labelmap步驟,將Node節點上的標簽,作為樣本的標簽保存到時間序列當中。
重新加載promethues配置文件,并重建Promthues的Pod實例后,查看kubernetes-kubelet任務采集狀態,我們會看到以下錯誤提示信息:
Get https://192.168.99.100:10250/metrics: x509: cannot validate certificate for 192.168.99.100 because it doesn't contain any IP SANs這是由于當前使用的ca證書中,并不包含192.168.99.100的地址信息。為了解決該問題,第一種方法是直接跳過ca證書校驗過程,通過在tls_config中設置 insecure_skip_verify為true即可。 這樣Promthues在采集樣本數據時,將會自動跳過ca證書的校驗過程,從而從kubelet采集到監控數據:
- job_name: 'kubernetes-kubelet'scheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtinsecure_skip_verify: truebearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: noderelabel_configs:- action: labelmapregex: __meta_kubernetes_node_label_(.+)第二種方式,不直接通過kubelet的metrics服務采集監控數據,而通過Kubernetes的api-server提供的代理API訪問各個節點中kubelet的metrics服務,如下所示:
- job_name: 'kubernetes-kubelet'scheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: noderelabel_configs:- action: labelmapregex: __meta_kubernetes_node_label_(.+)- target_label: __address__replacement: kubernetes.default.svc:443- source_labels: [__meta_kubernetes_node_name]regex: (.+)target_label: __metrics_path__replacement: /api/v1/nodes/${1}/proxy/metrics通過relabeling,將從Kubernetes獲取到的默認地址__address__替換為kubernetes.default.svc:443。同時將__metrics_path__替換為api-server的代理地址/api/v1/nodes/${1}/proxy/metrics。
通過獲取各個節點中kubelet的監控指標,用戶可以評估集群中各節點的性能表現。例如,通過指標kubelet_pod_start_duration_seconds_count可以獲得當前節點中Pod啟動的數量。
4.2從Kubelet獲取節點容器資源使用情況
各節點的kubelet組件中除了包含自身的監控指標信息以外,kubelet組件還內置了對cAdvisor的支持。cAdvisor能夠獲取當前節點上運行的所有容器的資源使用情況,通過訪問kubelet的/metrics/cadvisor地址可以獲取到cadvisor的監控指標,因此和獲取kubelet監控指標類似,這里同樣通過node模式自動發現所有的kubelet信息,并通過適當的relabel過程,修改監控采集任務的配置。 與采集kubelet自身監控指標相似,這里也有兩種方式采集cadvisor中的監控指標:
方式一:直接訪問kubelet的/metrics/cadvisor地址,需要跳過ca證書認證:
- job_name: 'kubernetes-cadvisor'scheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtinsecure_skip_verify: truebearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: noderelabel_configs:- source_labels: [__meta_kubernetes_node_name]regex: (.+)target_label: __metrics_path__replacement: metrics/cadvisor- action: labelmapregex: __meta_kubernetes_node_label_(.+)方式二:通過api-server提供的代理地址訪問kubelet的/metrics/cadvisor地址:
- job_name: 'kubernetes-cadvisor'scheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: noderelabel_configs:- target_label: __address__replacement: kubernetes.default.svc:443- source_labels: [__meta_kubernetes_node_name]regex: (.+)target_label: __metrics_path__replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor- action: labelmapregex: __meta_kubernetes_node_label_(.+)4.3使用NodeExporter監控集群資源使用情況
為了能夠采集集群中各個節點的資源使用情況,我們需要在各節點中部署一個Node Exporter實例。在本章的“部署Prometheus”小節,我們使用了Kubernetes內置的控制器之一Deployment。Deployment能夠確保Prometheus的Pod能夠按照預期的狀態在集群中運行,而Pod實例可能隨機運行在任意節點上。而與Prometheus的部署不同的是,對于Node Exporter而言每個節點只需要運行一個唯一的實例,此時,就需要使用Kubernetes的另外一種控制器Daemonset。顧名思義,Daemonset的管理方式類似于操作系統中的守護進程。Daemonset會確保在集群中所有(也可以指定)節點上運行一個唯一的Pod實例。
創建node-exporter-daemonset.yml文件,并寫入以下內容:
apiVersion: apps/v1 kind: DaemonSet metadata:name: node-exporter spec:selector:matchLabels:app: node-exportertemplate:metadata:annotations:prometheus.io/scrape: 'true'prometheus.io/port: '9100'prometheus.io/path: 'metrics'labels:app: node-exportername: node-exporterspec:containers:- image: prom/node-exporterimagePullPolicy: IfNotPresentname: node-exporterports:- containerPort: 9100hostPort: 9100name: scrapehostNetwork: truehostPID: true由于Node Exporter需要能夠訪問宿主機,因此這里指定了hostNetwork和hostPID,讓Pod實例能夠以主機網絡以及系統進程的形式運行。同時YAML文件中也創建了NodeExporter相應的Service。這樣通過Service就可以訪問到對應的NodeExporter實例。
[root@master-1 prometheus]# kubectl create -f node-exporter-daemonset.yml daemonset.apps/node-exporter created查看Daemonset以及Pod的運行狀態
[root@master-1 prometheus]# kubectl get daemonsets NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE node-exporter 1 1 1 1 1 <none> 74s[root@master-1 prometheus]# kubectl get pods NAME READY STATUS RESTARTS AGE node-exporter-brh9d 1/1 Running 0 79s prometheus-b487b9dfc-4xf65 1/1 Running 0 9m28s由于Node Exporter是以主機網絡的形式運行,因此直接訪問MiniKube的虛擬機IP加上Pod的端口即可訪問當前節點上運行的Node Exporter實例:
[root@master-1 ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES node-exporter-brh9d 1/1 Running 0 104m 192.168.5.21 worker-1 <none> <none> prometheus-b487b9dfc-4xf65 1/1 Running 0 113m 10.244.3.50 worker-1 <none> <none>[root@master-1 ~]# curl http://192.168.5.21:9100/metrics # HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles. # TYPE go_gc_duration_seconds summary go_gc_duration_seconds{quantile="0"} 3.3862e-05 go_gc_duration_seconds{quantile="0.25"} 4.1737e-05 go_gc_duration_seconds{quantile="0.5"} 4.5937e-05 go_gc_duration_seconds{quantile="0.75"} 5.1647e-05 go_gc_duration_seconds{quantile="1"} 0.003094938 go_gc_duration_seconds_sum 0.020962164 go_gc_duration_seconds_count 353目前為止,通過Daemonset的形式將Node Exporter部署到了集群中的各個節點中。接下來,我們只需要通過Prometheus的pod服務發現模式,找到當前集群中部署的Node Exporter實例即可。 需要注意的是,由于Kubernetes中并非所有的Pod都提供了對Prometheus的支持,有些可能只是一些簡單的用戶應用,為了區分哪些Pod實例是可以供Prometheus進行采集的,這里我們為Node Exporter添加了注解:
prometheus.io/scrape: 'true'由于Kubernetes中Pod可能會包含多個容器,還需要用戶通過注解指定用戶提供監控指標的采集端口:
prometheus.io/port: '9100'而有些情況下,Pod中的容器可能并沒有使用默認的/metrics作為監控采集路徑,因此還需要支持用戶指定采集路徑:
prometheus.io/path: 'metrics'為Prometheus創建監控采集任務kubernetes-pods,如下所示:
- job_name: 'kubernetes-pods'kubernetes_sd_configs:- role: podrelabel_configs:- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]action: keepregex: true- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]action: replacetarget_label: __metrics_path__regex: (.+)- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]action: replaceregex: ([^:]+)(?::\d+)?;(\d+)replacement: $1:$2target_label: __address__- action: labelmapregex: __meta_kubernetes_pod_label_(.+)- source_labels: [__meta_kubernetes_namespace]action: replacetarget_label: kubernetes_namespace- source_labels: [__meta_kubernetes_pod_name]action: replacetarget_label: kubernetes_pod_name通過以上relabel過程實現對Pod實例的過濾,以及采集任務地址替換,從而實現對特定Pod實例監控指標的采集。需要說明的是kubernetes-pods并不是只針對Node Exporter而言,對于用戶任意部署的Pod實例,只要其提供了對Prometheus的支持,用戶都可以通過為Pod添加注解的形式為其添加監控指標采集的支持。
4.4從kube-apiserver獲取集群運行監控指標
在開始正式內容之前,我們需要先了解一下Kubernetes中Service是如何實現負載均衡的,如下圖所示,一般來說Service有兩個主要的使用場景:
代理對集群內部應用Pod實例的請求:當創建Service時如果指定了標簽選擇器,Kubernetes會監聽集群中所有的Pod變化情況,通過Endpoints自動維護滿足標簽選擇器的Pod實例的訪問信息;
代理對集群外部服務的請求:當創建Service時如果不指定任何的標簽選擇器,此時需要用戶手動創建Service對應的Endpoint資源。例如,一般來說,為了確保數據的安全,我們通常講數據庫服務部署到集群外。 這是為了避免集群內的應用硬編碼數據庫的訪問信息,這是就可以通過在集群內創建Service,并指向外部的數據庫服務實例。
kube-apiserver扮演了整個Kubernetes集群管理的入口的角色,負責對外暴露Kubernetes API。kube-apiserver組件一般是獨立部署在集群外的,為了能夠讓部署在集群內的應用(kubernetes插件或者用戶應用)能夠與kube-apiserver交互,Kubernetes會默認在命名空間下創建一個名為kubernetes的服務,如下所示:
[root@master-1 prometheus]# kubectl get svc kubernetes -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d4h <none>而該kubernetes服務代理的后端實際地址通過endpoints進行維護,如下所示:
[root@master-1 prometheus]# kubectl get endpoints kubernetes NAME ENDPOINTS AGE kubernetes 192.168.5.11:6443,192.168.5.12:6443,192.168.5.13:6443 3d4h通過這種方式集群內的應用或者系統主機就可以通過集群內部的DNS域名kubernetes.default.svc訪問到部署外部的kube-apiserver實例。
因此,如果我們想要監控kube-apiserver相關的指標,只需要通過endpoints資源找到kubernetes對應的所有后端地址即可。
如下所示,創建監控任務kubernetes-apiservers,這里指定了服務發現模式為endpoints。Promtheus會查找當前集群中所有的endpoints配置,并通過relabel進行判斷是否為apiserver對應的訪問地址:
- job_name: 'kubernetes-apiservers'kubernetes_sd_configs:- role: endpointsscheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenrelabel_configs:- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]action: keepregex: default;kubernetes;https- target_label: __address__replacement: kubernetes.default.svc:443在relabel_configs配置中第一步用于判斷當前endpoints是否為kube-apiserver對用的地址。第二步,替換監控采集地址到kubernetes.default.svc:443即可。重新加載配置文件,重建Promthues實例,得到以下結果。
5.Kubernetes 中部署 Grafana
grafana 是一個可視化面板,有著非常漂亮的圖表和布局展示,功能齊全的度量儀表盤和圖形編輯器,支持 Graphite、zabbix、InfluxDB、Prometheus、OpenTSDB、Elasticsearch 等作為數據源,比 Prometheus 自帶的圖表展示功能強大太多,更加靈活,有豐富的插件,功能更加強大。
通過Deployment部署grafana 創建grafana-deployment-5.0.0.yml文件,并寫入以下內容:
apiVersion: apps/v1 kind: Deployment metadata:name: grafana-corelabels:app: grafanacomponent: core spec:replicas: 1selector:matchLabels:app: grafanatemplate:metadata:labels:app: grafanaspec:containers:- image: grafana/grafana:5.0.0name: grafana-coreimagePullPolicy: IfNotPresentresources:limits:cpu: 100mmemory: 100Mirequests:cpu: 100mmemory: 100Mienv:- name: GF_AUTH_BASIC_ENABLEDvalue: "true"- name: GF_AUTH_ANONYMOUS_ENABLEDvalue: "false"readinessProbe:httpGet:path: /loginport: 3000volumeMounts:- name: grafana-persistent-storagemountPath: /varvolumes:- name: grafana-persistent-storageemptyDir: {}--- apiVersion: v1 kind: Service metadata:name: grafanalabels:app: grafana spec:type: NodePortports:- port: 3000selector:app: grafana部署grafana
[root@master-1 prometheus]# kubectl apply -f grafana-deployment-5.0.0.yml deployment.apps/grafana-core created注意:
如果是用的grafana 5.0.0以上版本, 會報錯 GF_PATHS_DATA='/var/lib/grafana' is not writable. You may have issues with file permissions, more information here: http://docs.grafana.org/installation/docker/#migration-from-a-previous-version-of-the-docker-container-to-5-1-or-later mkdir: cannot create directory '/var/lib/grafana/plugins': No such file or directory解決辦法:securityContext:fsGroup: 472runAsUser: 472完整的grafana-deployment-5.3.4.yml文件如下: apiVersion: apps/v1 kind: Deployment metadata:name: grafananamespace: kube-opslabels:app: grafana spec:revisionHistoryLimit: 10selector:matchLabels:app: grafanatemplate:metadata:labels:app: grafanaspec:containers:- name: grafanaimage: grafana/grafana:5.3.4imagePullPolicy: IfNotPresentports:- containerPort: 3000name: grafanaenv:- name: GF_SECURITY_ADMIN_USERvalue: admin- name: GF_SECURITY_ADMIN_PASSWORDvalue: admin321readinessProbe:failureThreshold: 10httpGet:path: /api/healthport: 3000scheme: HTTPinitialDelaySeconds: 60periodSeconds: 10successThreshold: 1timeoutSeconds: 30livenessProbe:failureThreshold: 3httpGet:path: /api/healthport: 3000scheme: HTTPperiodSeconds: 10successThreshold: 1timeoutSeconds: 1resources:limits:cpu: 100mmemory: 256Mirequests:cpu: 100mmemory: 256MivolumeMounts:- mountPath: /var/lib/grafanasubPath: grafananame: storagesecurityContext:fsGroup: 472runAsUser: 472volumes:- name: storageemptyDir: {} --- apiVersion: v1 kind: Service metadata:name: grafanalabels:app: grafana spec:type: NodePortports:- port: 3000selector:app: grafana查看pod svc 狀態
[root@master-1 prometheus]# kubectl get pod,svc NAME READY STATUS RESTARTS AGE pod/grafana-569d774b85-8244q 1/1 Running 0 7m20s pod/node-exporter-brh9d 1/1 Running 0 21h pod/prometheus-b487b9dfc-gvkd4 1/1 Running 0 17hNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/blackbox-exporter ClusterIP 10.106.168.178 <none> 9115/TCP 18h service/grafana NodePort 10.100.91.140 <none> 3000:30674/TCP 7m20s service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d23h service/nginx-svc NodePort 10.104.88.55 <none> 80:30523/TCP 3d23h service/prometheus NodePort 10.100.208.234 <none> 9090:32053/TCP 3d這里,grafana的部署就完成了,接下來我們訪問grafana并配置Prometheus數據源。
Grafana配置
訪問grafana所在節點的的地址 http://192.168.5.21:30674/
grafana 默認用戶名 admin 密碼 admin
如果是grafana-deployment-5.3.4.yml生成的, 密碼是 admin321
添加數據源
顯示下面截圖,說明數據源可用。
導入模板
grafana 的官方網站https://grafana.com/grafana/dashboards/上還有很多公共的 Dashboard 可以供我們使用,我們這里可以使用Kubernetes cluster monitoring (via Prometheus)(dashboard id 為162)這個 Dashboard 來展示 Kubernetes 集群的監控信息。
就會顯示下面的界面,表示grafana配置成功。
仔細看看,這個dashboard是監控pod的,發現pod的數據有,但是cluster的數據沒有。這時候我們就需要去檢查一下https://grafana.com/grafana/dashboards/162 相關的配置是不是有漏掉的。
經過對grafana模板的監控字段進行修改,dashboard已經是下面這個樣子
比如,cluster memory usage 點擊edit, 修改metrics 為
(sum(node_memory_MemTotal_bytes) - sum(node_memory_MemFree_bytes+node_memory_Buffers_bytes+node_memory_Cached_bytes) ) / sum(node_memory_MemTotal_bytes) * 100
然后點擊Save,可以添加備注。
cluster_cpu_usage改為
sum(sum by (name)( rate(container_cpu_usage_seconds_total{image!=“”}[1m] ) )) / count(node_cpu_seconds_total{mode=“system”}) * 100
cluster_file_system改為
(sum(node_filesystem_size_bytes{device=“/dev/mapper/centos_centos7-root”}) - sum(node_filesystem_free_bytes{device=“/dev/mapper/centos_centos7-root”}) ) / sum(node_filesystem_size_bytes{device=“/dev/mapper/centos_centos7-root”}) * 100
其中{device=“xxx”}過濾條件,根據os的FS類型來決定。
附錄:
我已將需要的yml文件上傳至GitHub ,有需要的可以直接下載。
https://github.com/JasonYLong/prometheus-on-kubernetes.git
參考該文章,我只是做了新版本的修改,并加上了grafana的部分。
https://yunlzheng.gitbook.io/prometheus-book/part-iii-prometheus-shi-zhan/readmd
總結
以上是生活随笔為你收集整理的Prometheus监控kubernetes的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大数据CDC技术
- 下一篇: 自动更新之安装apk