Kubernetes 下的服务发现

目前为止,我们已经能够在 Kubernetes 下部署一个简单的 Prometheus 实例,不过当前来说它并不能发挥其监控系统的作用,除了 Prometheus,暂时没有任何的监控采集目标。在第7章中,我们介绍了 Prometheus 的服务发现能力,它能够与通过与 “中间代理人“ 的交互,从而动态的获取需要监控的目标实例。而在 Kubernetes 下 Prometheus 就是需要与 Kubernetes 的 API 进行交互,从而能够动态的发现 Kubernetes 中部署的所有可监控的目标资源。

Kubernetes 的访问授权

为了能够让 Prometheus 能够访问收到认证保护的 Kubernetes API,我们首先需要做的是,对 Prometheus 进行访问授权。在 Kubernetes 中主要使用基于角色的访问控制模型 (Role-Based Access Control),用于管理Kubernetes 下资源访问权限。首先我们需要在 Kubernetes 下定义角色(ClusterRole),并且为该角色赋予响应的访问权限。同时创建 Prometheus 所使用的账号(ServiceAccount),最后则是将该账号与角色进行绑定(ClusterRoleBinding)。这些所有的操作在 Kubernetes 同样被视为是一系列的资源,可以通过YAML文件进行描述并创建,这里创建 prometheus-rbac-setup.yml 文件,并写入以下内容:

  1. apiVersion: rbac.authorization.k8s.io/v1beta1
  2. kind: ClusterRole
  3. metadata:
  4. name: prometheus
  5. rules:
  6. - apiGroups: [""]
  7. resources:
  8. - nodes
  9. - nodes/proxy
  10. - services
  11. - endpoints
  12. - pods
  13. verbs: ["get", "list", "watch"]
  14. - apiGroups:
  15. - extensions
  16. resources:
  17. - ingresses
  18. verbs: ["get", "list", "watch"]
  19. - nonResourceURLs: ["/metrics"]
  20. verbs: ["get"]
  21. ---
  22. apiVersion: v1
  23. kind: ServiceAccount
  24. metadata:
  25. name: prometheus
  26. namespace: default
  27. ---
  28. apiVersion: rbac.authorization.k8s.io/v1beta1
  29. kind: ClusterRoleBinding
  30. metadata:
  31. name: prometheus
  32. roleRef:
  33. apiGroup: rbac.authorization.k8s.io
  34. kind: ClusterRole
  35. name: prometheus
  36. subjects:
  37. - kind: ServiceAccount
  38. name: prometheus
  39. namespace: default

其中需要注意的是ClusterRole是全局的,不需要指定命名空间。而ServiceAccount是属于特定命名空间的资源。通过kubectl命令创建RBAC对应的各个资源:

  1. $ kubectl create -f prometheus-rbac-setup.yml
  2. clusterrole "prometheus" created
  3. serviceaccount "prometheus" created
  4. clusterrolebinding "prometheus" created

在完成角色权限以及用户的绑定之后,就可以指定Prometheus使用特定的ServiceAccount创建Pod实例。修改prometheus-deployment.yml文件,并添加serviceAccountName和serviceAccount定义:

  1. spec:
  2. replicas: 1
  3. template:
  4. metadata:
  5. labels:
  6. app: prometheus
  7. spec:
  8. serviceAccountName: prometheus
  9. serviceAccount: prometheus

通过kubectl apply对Deployment进行变更升级:

  1. $ kubectl apply -f prometheus-deployment.yml
  2. service "prometheus" configured
  3. deployment "prometheus" configured
  4. $ kubectl get pods
  5. NAME READY STATUS RESTARTS AGE
  6. prometheus-55f655696d-wjqcl 0/1 Terminating 0 38m
  7. prometheus-69f9ddb588-czn2c 1/1 Running 0 6s

指定 ServiceAccount 创建的 Pod 实例中,会自动将用于访问 Kubernetes API 的 CA 证书以及当前账户对应的访问令牌文件挂载到 Pod 实例的 /var/run/secrets/kubernetes.io/serviceaccount/ 目录下,可以通过以下命令进行查看:

  1. kubectl exec -it prometheus-69f9ddb588-czn2c ls /var/run/secrets/kubernetes.io/serviceaccount/
  2. ca.crt namespace token

服务发现

在Kubernetes下,Promethues通过与Kubernetes API集成目前主要支持5种服务发现模式,分别是:Node、Service、Pod、Endpoints、Ingress。

通过kubectl命令行,可以方便的获取到当前集群中的所有节点信息:

  1. $ kubectl get nodes -o wide
  2. NAME STATUS ROLES AGE VERSION EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
  3. minikube Ready <none> 164d v1.8.0 <none> Buildroot 2017.02 4.9.13 docker://Unknown

为了能够让Prometheus能够获取到当前集群中所有节点的信息,在Promtheus的配置文件中,我们添加如下Job配置:

  1. - job_name: 'kubernetes-nodes'
  2. tls_config:
  3. ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  4. bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  5. kubernetes_sd_configs:
  6. - role: node

通过指定kubernetes_sd_config的模式为 node,Prometheus 会自动从 Kubernetes 中发现到所有的 node 节点并作为当前 Job 监控的 Target 实例。如下所示,这里需要指定用于访问 Kubernetes API 的 ca 以及 token 文件路径。

对于 Ingress,Service,Endpoints, Pod 的使用方式也是类似的,下面给出了一个完整 Prometheus 配置的示例:

  1. apiVersion: v1
  2. data:
  3. prometheus.yml: |-
  4. global:
  5. scrape_interval: 15s
  6. evaluation_interval: 15s
  7. scrape_configs:
  8. - job_name: 'kubernetes-nodes'
  9. tls_config:
  10. ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  11. bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  12. kubernetes_sd_configs:
  13. - role: node
  14. - job_name: 'kubernetes-service'
  15. tls_config:
  16. ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  17. bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  18. kubernetes_sd_configs:
  19. - role: service
  20. - job_name: 'kubernetes-endpoints'
  21. tls_config:
  22. ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  23. bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  24. kubernetes_sd_configs:
  25. - role: endpoints
  26. - job_name: 'kubernetes-ingress'
  27. tls_config:
  28. ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  29. bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  30. kubernetes_sd_configs:
  31. - role: ingress
  32. - job_name: 'kubernetes-pods'
  33. tls_config:
  34. ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  35. bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  36. kubernetes_sd_configs:
  37. - role: pod
  38. kind: ConfigMap
  39. metadata:
  40. name: prometheus-config

更新Prometheus配置文件,并重建Prometheus实例:

  1. $ kubectl apply -f prometheus-config.yml
  2. configmap "prometheus-config" configured
  3. $ kubectl get pods
  4. prometheus-69f9ddb588-rbrs2 1/1 Running 0 4m
  5. $ kubectl delete pods prometheus-69f9ddb588-rbrs2
  6. pod "prometheus-69f9ddb588-rbrs2" deleted
  7. $ kubectl get pods
  8. prometheus-69f9ddb588-rbrs2 0/1 Terminating 0 4m
  9. prometheus-69f9ddb588-wtlsn 1/1 Running 0 14s

Prometheus使用新的配置文件重建之后,打开Prometheus UI,通过Service Discovery页面可以查看到当前Prometheus通过Kubernetes发现的所有资源对象了:

Service Discovery发现的实例

Service Discovery发现的实例

同时Prometheus会自动将该资源的所有信息,并通过标签的形式体现在Target对象上。如下所示,是Promthues获取到的Node节点的标签信息:

  1. __address__="192.168.99.100:10250"
  2. __meta_kubernetes_node_address_Hostname="minikube"
  3. __meta_kubernetes_node_address_InternalIP="192.168.99.100"
  4. __meta_kubernetes_node_annotation_alpha_kubernetes_io_provided_node_ip="192.168.99.100"
  5. __meta_kubernetes_node_annotation_node_alpha_kubernetes_io_ttl="0"
  6. __meta_kubernetes_node_annotation_volumes_kubernetes_io_controller_managed_attach_detach="true"
  7. __meta_kubernetes_node_label_beta_kubernetes_io_arch="amd64"
  8. __meta_kubernetes_node_label_beta_kubernetes_io_os="linux"
  9. __meta_kubernetes_node_label_kubernetes_io_hostname="minikube"
  10. __meta_kubernetes_node_name="minikube"
  11. __metrics_path__="/metrics"
  12. __scheme__="https"
  13. instance="minikube"
  14. job="kubernetes-nodes"

目前为止,我们已经能够通过Prometheus自动发现Kubernetes集群中的各类资源以及其基本信息。不过,如果现在查看Promtheus的Target状态页面,结果可能会让人不太满意:

Target页面状态

Target 页面状态

虽然 Prometheus 能够自动发现所有的资源对象,并且将其作为Target对象进行数据采集。 但并不是所有的资源对象都是支持 Promethues 的,并且不同类型资源对象的采集方式可能是不同的。因此,在实际的操作中,我们需要有明确的监控目标,并且针对不同类型的监控目标设置不同的数据采集方式。

接下来,我们将利用 Promtheus 的服务发现能力,实现对 Kubernetes 集群的全面监控。