阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Kubernetes集群监控方案详解

151次阅读
没有评论

共计 11504 个字符,预计需要花费 29 分钟才能阅读完成。

本文介绍在 k8s 集群中使用 node-exporter、prometheus、grafana 对集群进行监控。

其实现原理有点类似 ELK、EFK 组合。node-exporter 组件负责收集节点上的 metrics 监控数据,并将数据推送给 prometheus, prometheus 负责存储这些数据,grafana 将这些数据通过网页以图形的形式展现给用户。

在开始之前有必要了解下 Prometheus 是什么?
Prometheus(中文名:普罗米修斯)是由 SoundCloud 开发的开源监控报警系统和时序列数据库(TSDB). 自 2012 年起, 许多公司及组织已经采用 Prometheus, 并且该项目有着非常活跃的开发者和用户社区. 现在已经成为一个独立的开源项目。Prometheus 在 2016 加入 CNCF (Cloud Native Computing Foundation), 作为在 kubernetes 之后的第二个由基金会主持的项目。Prometheus 的实现参考了 Google 内部的监控实现,与源自 Google 的 Kubernetes 结合起来非常合适。另外相比 influxdb 的方案,性能更加突出,而且还内置了报警功能。它针对大规模的集群环境设计了拉取式的数据采集方式,只需要在应用里面实现一个 metrics 接口,然后把这个接口告诉 Prometheus 就可以完成数据采集了,下图为 prometheus 的架构图。
Kubernetes 集群监控方案详解
Prometheus 的特点:
1、多维数据模型(时序列数据由 metric 名和一组 key/value 组成)
2、在多维度上灵活的查询语言(PromQl)
3、不依赖分布式存储,单主节点工作.
4、通过基于 HTTP 的 pull 方式采集时序数据
5、可以通过中间网关进行时序列数据推送(pushing)
6、目标服务器可以通过发现服务或者静态配置实现
7、多种可视化和仪表盘支持

prometheus 相关组件,Prometheus 生态系统由多个组件组成,其中许多是可选的:
1、Prometheus 主服务, 用来抓取和存储时序数据
2、client library 用来构造应用或 exporter 代码 (go,Java,Python,ruby)
3、push 网关可用来支持短连接任务
4、可视化的 dashboard (两种选择,promdash 和 grafana. 目前主流选择是 grafana.)
4、一些特殊需求的数据出口(用于 HAProxy, StatsD, Graphite 等服务)
5、实验性的报警管理端(alartmanager, 单独进行报警汇总, 分发, 屏蔽等)

promethues 的各个组件基本都是用 golang 编写, 对编译和部署十分友好. 并且没有特殊依赖. 基本都是独立工作。
上述文字来自网络!

现在我们正式开始部署工作。
一、环境介绍
操作系统环境:CentOS linux 7.2 64bit
K8S 软件版本:1.9.0(采用 kubeadm 方式部署)
Master 节点 IP:192.168.115.5/24
Node 节点 IP:192.168.115.6/24

二、在 k8s 集群的所有节点上下载所需要的 image

# docker pull prom/node-exporter
# docker pull prom/prometheus:v2.0.0
# docker pull grafana/grafana:4.2.0

三、采用 daemonset 方式部署 node-exporter 组件

# cat node-exporter.yaml

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: kube-system
  labels:
    k8s-app: node-exporter
spec:
  template:
    metadata:
      labels:
        k8s-app: node-exporter
    spec:
      containers:
      – image: prom/node-exporter
        name: node-exporter
        ports:
        – containerPort: 9100
          protocol: TCP
          name: http

apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: node-exporter
  name: node-exporter
  namespace: kube-system
spec:
  ports:
  – name: http
    port: 9100
    nodePort: 31672
    protocol: TCP
  type: NodePort
  selector:
    k8s-app: node-exporter

通过上述文件创建 pod 和 service

# kubectl create -f  node-exporter.yaml

四、部署 prometheus 组件
1、rbac 文件

# cat rbac-setup.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
– apiGroups: [“”]
  resources:
  – nodes
  – nodes/proxy
  – services
  – endpoints
  – pods
  verbs: [“get”, “list”, “watch”]
– apiGroups:
  – extensions
  resources:
  – ingresses
  verbs: [“get”, “list”, “watch”]
– nonResourceURLs: [“/metrics”]
  verbs: [“get”]

apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: kube-system

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
– kind: ServiceAccount
  name: prometheus
  namespace: kube-system

2、以 configmap 的形式管理 prometheus 组件的配置文件

# cat configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: kube-system
data:
  prometheus.yml: |
    global:
      scrape_interval:    15s
      evaluation_interval: 15s
    scrape_configs:

    – job_name: ‘kubernetes-apiservers’
      kubernetes_sd_configs:
      – role: endpoints
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_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

    – job_name: ‘kubernetes-nodes’
      kubernetes_sd_configs:
      – role: node
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
      – action: labelmap
        regex: __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

    – job_name: ‘kubernetes-cadvisor’
      kubernetes_sd_configs:
      – role: node
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
      – action: labelmap
        regex: __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/cadvisor

    – job_name: ‘kubernetes-service-endpoints’
      kubernetes_sd_configs:
      – role: endpoints
      relabel_configs:
      – source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      – source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
        action: replace
        target_label: __scheme__
        regex: (https?)
      – source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      – source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
        action: replace
        target_label: __address__
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
      – action: labelmap
        regex: __meta_kubernetes_service_label_(.+)
      – source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      – source_labels: [__meta_kubernetes_service_name]
        action: replace
        target_label: kubernetes_name

    – job_name: ‘kubernetes-services’
      kubernetes_sd_configs:
      – role: service
      metrics_path: /probe
      params:
        module: [http_2xx]
      relabel_configs:
      – source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe]
        action: keep
        regex: true
      – source_labels: [__address__]
        target_label: __param_target
      – target_label: __address__
        replacement: blackbox-exporter.example.com:9115
      – source_labels: [__param_target]
        target_label: instance
      – action: labelmap
        regex: __meta_kubernetes_service_label_(.+)
      – source_labels: [__meta_kubernetes_namespace]
        target_label: kubernetes_namespace
      – source_labels: [__meta_kubernetes_service_name]
        target_label: kubernetes_name

    – job_name: ‘kubernetes-ingresses’
      kubernetes_sd_configs:
      – role: ingress
      relabel_configs:
      – source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_probe]
        action: keep
        regex: true
      – source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
        regex: (.+);(.+);(.+)
        replacement: ${1}://${2}${3}
        target_label: __param_target
      – target_label: __address__
        replacement: blackbox-exporter.example.com:9115
      – source_labels: [__param_target]
        target_label: instance
      – action: labelmap
        regex: __meta_kubernetes_ingress_label_(.+)
      – source_labels: [__meta_kubernetes_namespace]
        target_label: kubernetes_namespace
      – source_labels: [__meta_kubernetes_ingress_name]
        target_label: kubernetes_name

    – job_name: ‘kubernetes-pods’
      kubernetes_sd_configs:
      – role: pod
      relabel_configs:
      – source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      – source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      – source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
        target_label: __address__
      – action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      – source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      – source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: kubernetes_pod_name3、Prometheus deployment 文件

# cat prometheus.deploy.yml

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  labels:
    name: prometheus-deployment
  name: prometheus
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      containers:
      – image: prom/prometheus:v2.0.0
        name: prometheus
        command:
        – “/bin/prometheus”
        args:
        – “–config.file=/etc/prometheus/prometheus.yml”
        – “–storage.tsdb.path=/prometheus”
        – “–storage.tsdb.retention=24h”
        ports:
        – containerPort: 9090
          protocol: TCP
        volumeMounts:
        – mountPath: “/prometheus”
          name: data
        – mountPath: “/etc/prometheus”
          name: config-volume
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
          limits:
            cpu: 500m
            memory: 2500Mi
      serviceAccountName: prometheus   
      volumes:
      – name: data
        emptyDir: {}
      – name: config-volume
        configMap:
          name: prometheus-config     

4、Prometheus service 文件

# cat prometheus.svc.yml

kind: Service
apiVersion: v1
metadata:
  labels:
    app: prometheus
  name: prometheus
  namespace: kube-system
spec:
  type: NodePort
  ports:
  – port: 9090
    targetPort: 9090
    nodePort: 30003
  selector:
app: prometheus

5、通过上述 yaml 文件创建相应的对象

# kubectl create -f  rbac-setup.yaml
# kubectl create -f  configmap.yaml
# kubectl create -f  prometheus.deploy.yml
# kubectl create -f  prometheus.svc.yml

Kubernetes 集群监控方案详解
Kubernetes 集群监控方案详解
Node-exporter 对应的 nodeport 端口为 31672,通过访问 http://192.168.115.5:31672/metrics 可以看到对应的 metrics
Kubernetes 集群监控方案详解
prometheus 对应的 nodeport 端口为 30003,通过访问 http://192.168.115.5:30003/target 可以看到 prometheus 已经成功连接上了 k8s 的 apiserver
Kubernetes 集群监控方案详解
可以在 prometheus 的 WEB 界面上提供了基本的查询 K8S 集群中每个 POD 的 CPU 使用情况,查询条件如下:

sum by (pod_name)(rate(container_cpu_usage_seconds_total{image!="", pod_name!=""}[1m] ) )

Kubernetes 集群监控方案详解
上述的查询有出现数据,说明 node-exporter 往 prometheus 中写入数据正常,接下来我们就可以部署 grafana 组件,实现更友好的 webui 展示数据了。

五、部署 grafana 组件

1、grafana deployment 配置文件

# cat grafana-deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: grafana-core
  namespace: kube-system
  labels:
    app: grafana
    component: core
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: grafana
        component: core
    spec:
      containers:
      – image: grafana/grafana:4.2.0
        name: grafana-core
        imagePullPolicy: IfNotPresent
        # env:
        resources:
          # keep request = limit to keep this container in guaranteed class
          limits:
            cpu: 100m
            memory: 100Mi
          requests:
            cpu: 100m
            memory: 100Mi
        env:
          # The following env variables set up basic auth twith the default admin user and admin password.
          – name: GF_AUTH_BASIC_ENABLED
            value: “true”
          – name: GF_AUTH_ANONYMOUS_ENABLED
            value: “false”
          # – name: GF_AUTH_ANONYMOUS_ORG_ROLE
          #  value: Admin
          # does not really work, because of template variables in exported dashboards:
          # – name: GF_DASHBOARDS_JSON_ENABLED
          #  value: “true”
        readinessProbe:
          httpGet:
            path: /login
            port: 3000
          # initialDelaySeconds: 30
          # timeoutSeconds: 1
        volumeMounts:
        – name: grafana-persistent-storage
          mountPath: /var
      volumes:
      – name: grafana-persistent-storage
        emptyDir: {}

2、grafana service 配置文件

# cat grafana-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: grafana
  namespace: kube-system
  labels:
    app: grafana
    component: core
spec:
  type: NodePort
  ports:
    – port: 3000
  selector:
    app: grafana
component: core

3、grafana ingress 配置文件
# cat grafana-ing.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: grafana
  namespace: kube-system
spec:
  rules:
  – host: k8s.grafana
    http:
      paths:
      – path: /
        backend:
          serviceName: grafana
          servicePort: 3000

通过访问 traefik 的 webui 可以看到 k8s.grafana 服务发布成功
Kubernetes 集群监控方案详解
修改 hosts 解析,访问测试
Kubernetes 集群监控方案详解
Kubernetes 集群监控方案详解
也可以直接访问 nodeport 端口
Kubernetes 集群监控方案详解
默认用户名和密码都是 admin
Kubernetes 集群监控方案详解
配置数据源为 prometheus
Kubernetes 集群监控方案详解
导入面板,可以直接输入模板编号 315 在线导入,或者下载好对应的 json 模板文件本地导入,面板模板下载地址 https://grafana.com/dashboards/315
Kubernetes 集群监控方案详解
导入面板之后就可以看到对应的监控数据了。
Kubernetes 集群监控方案详解
Kubernetes 集群监控方案详解
Kubernetes 集群监控方案详解
这里要说明一下,在测试过程中,导入编号为 162 的模板,发现只有部分数据,且 pod 的名称显示不友好。模板地址 https://grafana.com/dashboards/162,详见下图。
Kubernetes 集群监控方案详解

六、后记
这里存在一些问题后续要继续研究解决。
1、prometheus 的数据存储采用 emptydir。如果 Pod 被删除,或者 Pod 发生迁移,emptyDir 也会被删除,并且永久丢失。后续可以在 K8S 集群外部再配置一个 Prometheus 系统来永久保存监控数据,两个 prometheus 系统之间通过配置 job 自动进行数据拉取。
2、Grafana 的配置数据存储采用 emptydir。如果 Pod 被删除,或者 Pod 发生迁移,emptyDir 也会被删除,并且永久丢失。我们也可以选择将 grafana 配置在 k8s 外部,数据源选择 K8S 集群外部的 prometheus 即可。
3、关于监控项的报警(alertmanager)尚未配置。

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计11504字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中