【云原生•监控】基于Prometheus的云原生集群监控(理论+实践)-01

news2024/12/28 19:00:31

【云原生•监控】基于Prometheus的云原生集群监控(理论+实践)-01

前言

「笔者已经在公有云上搭建了一套临时环境,可以先登录体验下:」

http://124.222.45.207:17000/login
账号:root/root.2020

云原生监控挑战

Prometheus 是用 Go 语言编写,从一开始就是开源的,到 2016 年 Prometheus 成为继 Kubernetes 之后,成为 CNCF 的第二个成员。近几年Prometheus的火热,和云原生日趋流行是密不可分的,并且现在已成为云原生生态中监控的事实标准。

传统的监控霸主Zabbix在面对云原生监控时,主要面临如下几个挑战:

  1. 监控对象数量增大:传统监控以单体应用为粒度,结合计算、存储、网络等基础设施监控进行运维保障。但在容器化微服务架构下,监控粒度细致到容器POD或微服务API级别,使得监控对象的数量相比单体应用呈指数级增长。

  2. 监控指标海量:

  • 资源对象类型多,如:Container、Pod、Service、Deployment、ReplicaSet、Endpoint、Ingress、PV、PVC等等;

  • 一个云原生集群可能有几万甚至几十万Pod;

  • 一个云原生集群可能有几千上万级别的Service、Endpoint、Deployment、Ingress等;

  • 海量的监控指标对数据写入、查询性能要求较高,以及存储空间占用优化等,才能承载海量的监控资源

对象动态变更较为频繁,资源对象的扩缩容、资源对象生命周期大大缩短,甚至有些对象朝生夕死等等,这就会带来两个问题:

  • 采集目标不能使用传统的静态配置方式,而是要基于服务发现机制能及时的感知到变化,并进行快速调整;

  • 资源对象扩缩容等导致的资源对象生命周期大大缩短是很容易导致指标数量的快速膨胀,久而久之会影响整个监控系统性能;

Zabbix出现得比较早,当时容器还没有诞生,自然对容器的支持比较差,而Prometheus的TSDB时序数据存储机制、丰富的服务发现机制等,基本就是为云原生量身定做的,Prometheus开始成为容器监控方面的标配,并且在未来可见的时间内会被广泛应用。

云原生监控方案

kubernetes云原生集群非常复杂,概况总结下我们主要关注的无外乎下面五大块指标:

  1. 容器基础资源指标:组件运行的外部环境相关性能指标,传统场景下组件运行的外部环境是主机,而云原生环境下组件的外部环境是容器,主机我们需要关注CPU、内存、存储、磁盘IO、网络IO等相关指标,同理容器基础资源指标也存在类似相关指标,如:Container的CPU使用率、内存使用率、存储空间、磁盘读写IO和网络IO等。

  2. k8s资源对象指标:容器是最底层的运行时组件,k8s作为强大的调度协调这些容器的平台,抽象定义出了很多资源对象,如Pod、Service、Deployment、ReplicaSet、DaemonSet、Ingress、StatefulSet、ConfigMap、ServiceAccount等等,资源对象指标就是对这些k8s定义的元数据信息进行监控。

  3. k8s服务组件指标:k8s作为一个复杂的集群,自身存在很多组件,如master节点上运行着:api-server组件、etcd组件、kube-scheduler组件、kube-controller-manager组件、coredns组件等,node节点上有kubelet组件、kube-proxy组件等,作为云原生集群的运维人员,肯定要关注这些核心组件的运行状况,避免某些组件性能瓶颈、异常奔溃导致整个云原生集群性能低下甚至不可用。

  4. k8s集群Node指标:云原生集群的各种组件、业务容器等最终都是运行在Node节点上,因此,Node节点的性能、异常情况等对整个云原生集群的影响也是非常大的,所以,我们也需要特别关注Node节点性能指标。

  5. 云原生上层业务指标:上面说的主要是云原生集群底层相关基础指标,云原生作为平台上面自然部署很多业务组件,比如PaaS中间件、业务应用服务等,这些组件运行在云原生上层本身也存在相关指标监控。

环境准备

为了监控上述云原生指标,首先,我们需要准备PrometheusGrafana环境。

Prometheus部署

1、为了方便管理,我们将监控相关的所有资源对象都安装在 monitoring 这个 namespace 下面,没有的话可以提前创建:

[root@k8s-01 prometheus]# kubectl create ns monitoring 
namespace/monitoring created

2、为了能够方便的管理配置文件,我们这里将 prometheus.yml 配置文件用 ConfigMap 的形式进行管理:

# prometheus-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: monitoring
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
      scrape_timeout: 15s
    scrape_configs:
    - job_name: 'prometheus'
      static_configs:
      - targets: ['localhost:9090']

我们这里暂时只配置了对 prometheus 本身的监控,直接创建该资源对象:

[root@k8s-01 prometheus]# kubectl apply -f prometheus-config.yaml 
configmap/prometheus-config created

配置文件创建完成了,以后如果我们有新的资源需要被监控,我们只需要将上面的 ConfigMap 对象更新即可。

3、现在我们来创建 prometheusPod 资源:

# prometheus-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus
  namespace: monitoring
  labels:
    app: prometheus
spec:
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      serviceAccountName: prometheus
      containers:
        - image: prom/prometheus:v2.31.1
          name: prometheus
          args:
            - "--config.file=/etc/prometheus/prometheus.yml"
            - "--storage.tsdb.path=/prometheus" # 指定tsdb数据路径
            - "--storage.tsdb.retention.time=24h"
            - "--web.enable-admin-api" # 控制对admin HTTP API的访问,其中包括删除时间序列等功能
            - "--web.enable-lifecycle" # 支持热更新,直接执行localhost:9090/-/reload立即生效
          ports:
            - containerPort: 9090
              name: http
          volumeMounts:
            - mountPath: "/etc/prometheus"
              name: config-volume
            - mountPath: "/prometheus"
              name: data
          resources:
            requests:
              cpu: 200m
              memory: 1024Mi
            limits:
              cpu: 200m
              memory: 1024Mi
        - image: jimmidyson/configmap-reload:v0.4.0  #prometheus配置动态加载
          name: prometheus-reload
          securityContext:
            runAsUser: 0
          args:
            - "--volume-dir=/etc/config"
            - "--webhook-url=http://localhost:9090/-/reload"
          volumeMounts:
            - mountPath: "/etc/config"
              name: config-volume
          resources:
            requests:
              cpu: 100m
              memory: 50Mi
            limits:
              cpu: 100m
              memory: 50Mi   
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: prometheus-data
        - configMap:
            name: prometheus-config
          name: config-volume

持久化

另外为了 prometheus 的性能和数据持久化我们这里是直接将通过一个 LocalPV 来进行数据持久化的,**注意一定不能使用 nfs 来持久化数据(TSDB时序库不支持nfs存储,会存在丢失数据风险)**,通过 --storage.tsdb.path=/prometheus 指定数据目录,创建如下所示的一个 PVC 资源对象,注意是一个 LocalPV,和 k8s-02 节点具有亲和性:

#prometheus-storage.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: prometheus-local
  labels:
    app: prometheus
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 20Gi
  storageClassName: local-storage
  local:
    path: /data/k8s/prometheus  #确保主机节点上存在该目录
  persistentVolumeReclaimPolicy: Retain
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - k8s-02
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: prometheus-data
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: prometheus
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
  storageClassName: local-storage

这里的volumeBindingMode: WaitForFirstConsumer意思就是延迟绑定,当有符合PVC要求的PV不立即绑定。因为POD关联PVC,而绑定之后,POD被调度到其他节点,显然其他节点很有可能没有那个PV所以POD就挂起了,另外就算该节点有合适的PV,而POD被设置成不能运行在该节点,这时候就没法了,延迟绑定的好处是,POD的调度要参考卷的分布。当开始调度POD的时候看看它要求的LPV在哪里,然后就调度到该节点,然后进行PVC的绑定,最后在挂载到POD中,这样就保证了POD所在的节点就一定是LPV所在的节点。所以让PVC延迟绑定,就是等到使用这个PVC的POD出现在调度器上之后(真正被调度之前),然后根据综合评估再来绑定这个PVC。

[root@k8s-01 prometheus]# kubectl get pvc -n monitoring
NAME              STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS    AGE
prometheus-data   Pending                                      local-storage   4m9s

RBAC权限

由于 prometheus 可以访问 Kubernetes 的一些资源对象,所以需要配置 rbac 相关认证,这里我们使用了一个名为 prometheus 的 serviceAccount 对象:

# rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: monitoring
---
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
---
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: monitoring

由于我们要获取的资源信息,在每一个 namespace 下面都有可能存在,所以我们这里使用的是 ClusterRole 的资源对象,值得一提的是我们这里的权限规则声明中有一个 nonResourceURLs 的属性,是用来对非资源型 metrics 进行操作的权限声明,这个在以前我们很少遇到过,然后直接创建上面的资源对象即可:

[root@k8s-01 prometheus]# kubectl apply -f rbac.yaml 
serviceaccount/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
[root@k8s-01 prometheus]# kubectl get sa -n monitoring
NAME         SECRETS   AGE
default      1         30m
prometheus   1         21s

现在我们就可以添加 promethues 的资源对象了:

[root@k8s-01 prometheus]# kubectl apply -f prometheus-deploy.yaml
deployment.apps/prometheus created
[root@k8s-01 prometheus]# kubectl get pod -n monitoring                                
NAME                         READY   STATUS             RESTARTS   AGE
prometheus-5cdf864d9-z9bg4   0/1     CrashLoopBackOff   2          2m56s
[root@k8s-01 prometheus]# kubectl logs -f prometheus-5cdf864d9-z9bg4 -n monitoring
ts=2023-06-06T15:27:55.111Z caller=main.go:444 level=info msg="Starting Prometheus" version="(version=2.31.1, branch=HEAD, revision=411021ada9ab41095923b8d2df9365b632fd40c3)"
ts=2023-06-06T15:27:55.111Z caller=main.go:449 level=info build_context="(go=go1.17.3, user=root@9419c9c2d4e0, date=20211105-20:35:02)"
ts=2023-06-06T15:27:55.111Z caller=main.go:450 level=info host_details="(Linux 3.10.0-1127.10.1.el7.x86_64 #1 SMP Wed Jun 3 14:28:03 UTC 2020 x86_64 prometheus-5cdf864d9-z9bg4 (none))"
ts=2023-06-06T15:27:55.111Z caller=main.go:451 level=info fd_limits="(soft=1048576, hard=1048576)"
ts=2023-06-06T15:27:55.111Z caller=main.go:452 level=info vm_limits="(soft=unlimited, hard=unlimited)"
ts=2023-06-06T15:27:55.112Z caller=query_logger.go:87 level=error component=activeQueryTracker msg="Error opening query log file" file=/prometheus/queries.active err="open /prometheus/queries.active: permission denied"
panic: Unable to create mmap-ed active query log

goroutine 1 [running]:
github.com/prometheus/prometheus/promql.NewActiveQueryTracker({0x7ffc2fc58e01, 0xb}, 0x14, {0x34442c0, 0xc0001371d0})
        /app/promql/query_logger.go:117 +0x3d7
main.main()
        /app/cmd/prometheus/main.go:491 +0x6bbf
[root@k8s-01 prometheus]#

文件权限

创建 Pod 后,我们可以看到并没有成功运行,出现了 open /prometheus/queries.active: permission denied 这样的错误信息,这是因为我们的 prometheus 的镜像中是使用的 nobody 这个用户,然后现在我们通过 LocalPV 挂载到宿主机上面的目录的 ownership 却是 root

[root@k8s-02 k8s]# ls -alh
总用量 0
drwxr-xr-x  4 root root  39 6月  18 22:14 .
drwxr-xr-x. 5 root root  50 6月   6 23:23 ..
drwxr-xr-x  6 root root 138 6月  19 01:00 prometheus

所以当然会出现操作权限问题了,这个时候我们就可以通过 securityContext 来为 Pod 设置下 volumes 的权限,通过设置 runAsUser=0 指定运行的用户为 root:

containers:
  - image: prom/prometheus:v2.31.1
    name: prometheus
    securityContext:
      runAsUser: 0

也可以通过设置一个 initContainer 来修改数据目录权限:

......
initContainers:
- name: fix-permissions
  image: busybox
  command: [chown, -R, "nobody:nobody", /prometheus]
  volumeMounts:
  - name: data
    mountPath: /prometheus

这个时候我们重新更新下 prometheus:

[root@k8s-01 prometheus]# kubectl apply -f prometheus-deploy.yaml 
deployment.apps/prometheus created
[root@k8s-01 prometheus]# kubectl get pod -n monitoring
NAME                          READY   STATUS    RESTARTS   AGE
prometheus-675dd5dc5b-ks9k4   1/1     Running   0          9s
[root@k8s-01 prometheus]# kubectl logs -f prometheus-675dd5dc5b-ks9k4 -n monitoring
ts=2023-06-06T15:33:41.415Z caller=main.go:444 level=info msg="Starting Prometheus" version="(version=2.31.1, branch=HEAD, revision=411021ada9ab41095923b8d2df9365b632fd40c3)"
ts=2023-06-06T15:33:41.415Z caller=main.go:449 level=info build_context="(go=go1.17.3, user=root@9419c9c2d4e0, date=20211105-20:35:02)"
ts=2023-06-06T15:33:41.418Z caller=web.go:542 level=info component=web msg="Start listening for connections" address=0.0.0.0:9090
ts=2023-06-06T15:33:41.500Z caller=main.go:839 level=info msg="Starting TSDB ..."
ts=2023-06-06T15:33:41.505Z caller=main.go:869 level=info msg="TSDB started"
ts=2023-06-06T15:33:41.505Z caller=main.go:996 level=info msg="Loading configuration file" filename=/etc/prometheus/prometheus.yml
ts=2023-06-06T15:33:41.506Z caller=main.go:1033 level=info msg="Completed loading of configuration file" filename=/etc/prometheus/prometheus.yml totalDuration=592.24µs db_storage=1.487µs remote_storage=6.209µs web_handler=900ns query_engine=1.736µs scrape=288.029µs scrape_sd=26.451µs notify=1.151µs notify_sd=1.487µs rules=3.679µs
ts=2023-06-06T15:33:41.506Z caller=main.go:811 level=info msg="Server is ready to receive web requests."

Pod 创建成功后,为了能够在外部访问到 prometheus 的 Web UI 服务,我们还需要创建一个 Service 对象:

# prometheus-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: prometheus
  namespace: monitoring
  labels:
    app: prometheus
spec:
  selector:
    app: prometheus
  type: NodePort
  ports:
    - name: web
      port: 9090
      targetPort: http

为了方便测试,我们这里创建一个 NodePort 类型的服务,当然我们可以创建一个 Ingress对象,通过域名来进行访问:

[root@k8s-01 prometheus]# kubectl apply -f prometheus-svc.yaml 
service/prometheus created
[root@k8s-01 prometheus]# kubectl get svc -n monitoring  -owide 
NAME         TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE   SELECTOR
prometheus   NodePort   10.96.219.107   <none>        9090:32478/TCP   20s   app=prometheus

现在我们就可以通过 http://任意节点IP:32478 访问 prometheus 的 webui 服务了:

0c44e792dae2ebf2a6889496f62f529e.png

这个抓取job是用于抓取 prometheus 本身的一些监控数据了,比如我们这里就选择 process_resident_memory_bytes 这个指标,然后点击 Execute,就可以看到类似于下面的图表数据了:

64f6d00edbd9a0f4e991e9a3a59d1c8a.png

Grafana部署

Prometheus 采集了 Kubernetes 集群中的一些监控数据指标,我们也尝试使用 promQL 语句查询出了一些数据,并且在 Prometheus 的 Dashboard 中进行了展示,但是明显可以感觉到 Prometheus 的图表功能相对较弱,所以一般情况下我们还是会使用 Grafana 来进行展示,所以我们可以将 Grafana 安装到集群中来。

1、创建编排文件:

# grafana-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: grafana
  template:
    metadata:
      labels:
        app: grafana
    spec:
      volumes:
        - name: storage
          persistentVolumeClaim:
            claimName: grafana-data
      containers:
        - name: grafana
          image: grafana/grafana:8.3.3
          imagePullPolicy: IfNotPresent
          securityContext:
            runAsUser: 0
          ports:
            - containerPort: 3000
              name: grafana
          env:
            - name: GF_SECURITY_ADMIN_USER
              value: admin
            - name: GF_SECURITY_ADMIN_PASSWORD
              value: admin
          readinessProbe:
            failureThreshold: 10
            httpGet:
              path: /api/health
              port: 3000
              scheme: HTTP
            initialDelaySeconds: 60
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 30
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /api/health
              port: 3000
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1
          resources:
            limits:
              cpu: 400m
              memory: 1024Mi
            requests:
              cpu: 200m
              memory: 512Mi
          volumeMounts:
            - mountPath: /var/lib/grafana
              name: storage
---
apiVersion: v1
kind: Service
metadata:
  name: grafana
  namespace: monitoring
spec:
  type: NodePort
  ports:
    - port: 3000
  selector:
    app: grafana
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: grafana-local
  labels:
    app: grafana
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 1Gi
  storageClassName: local-storage
  local:
    path: /data/k8s/grafana #保证节点上创建好该目录
  persistentVolumeReclaimPolicy: Retain
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - k8s-02
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: grafana-data
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: grafana
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: local-storage

两个比较重要的环境变量GF_SECURITY_ADMIN_USERGF_SECURITY_ADMIN_PASSWORD,用来配置 grafana 的管理员用户和密码的,由于 grafana 将 dashboard、插件这些数据保存在 /var/lib/grafana 这个目录下面的,所以我们这里如果需要做数据持久化的话,就需要针对这个目录进行 volume 挂载声明。

2、创建并验证Pod启动正常:

[root@k8s-01 prometheus]# kubectl apply -f grafana-deploy.yaml
[root@k8s-01 prometheus]# kubectl get pod -n monitoring
NAME                          READY   STATUS    RESTARTS   AGE
grafana-7cfd74ccf5-crcnz      1/1     Running   0          3m57s
prometheus-675dd5dc5b-ks9k4   1/1     Running   0          11d
[root@k8s-01 prometheus]# kubectl get svc -n monitoring
NAME         TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
grafana      NodePort   10.96.57.144    <none>        3000:32052/TCP   13m
prometheus   NodePort   10.96.219.107   <none>        9090:32478/TCP   11d

3、访问 grafana:http://192.168.31.160:32052

2b357a3803b7ca245a3137fa329546a6.png

4、添加Prometheus数据源:

5f4139a17b139110e9a9392dbafa365d.png

容器基础资源指标

说到容器监控我们自然会想到 cAdvisor,之前分享过如何部署cAdvisor组件监控Docker容器,cAdvisor(Container Advisor)Google 开源的一个容器监控工具,可用于对容器资源的使用情况和性能进行监控。它以守护进程方式运行,用于收集、聚合、处理和导出正在运行容器的有关信息。具体来说,该组件对每个容器都会记录其资源隔离参数、历史资源使用情况、完整历史资源使用情况的直方图和网络统计信息。

cAdvisor 是用于监控容器引擎的,由于其监控的实用性,Kubernetes 已经默认将其内置到 kubelet 组件中,所以我们无需再单独部署 cAdvisor 组件,直接使用 kubelet 组件提供的指标采集地址即可。

cAdvisor 的数据路径为 /api/v1/nodes/<node>/proxy/metrics,但是我们不推荐使用这种方式,因为这种方式是通过 api-server 去代理访问的,对于大规模的集群会对 api-server造成很大的压力,所以我们可以直接通过访问 kubelet/metrics/cadvisor 这个端点来获取 cAdvisor 的数据。

cAdvisor接入

我们这里使用 node 的服务发现模式,因为每一个节点下面都有 kubelet,自然都有 cAdvisor 采集到的数据指标,配置如下:

- job_name: "cadvisor"
  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_(.+)
      replacement: $1
    - replacement: /metrics/cadvisor # <nodeip>/metrics -> <nodeip>/metrics/cadvisor
      target_label: __metrics_path__
  # 下面的方式不推荐使用
  # - target_label: __address__
  #   replacement: kubernetes.default.svc:443
  # - target_label: __metrics_path__
  #   replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor

cadvisor监控接入成功如下图:

44b321b29c17c7b1a974e5830d940ffc.png

k8s节点node指标

节点性能关键指标

1、主机基本信息

node_uname_info:主机基本信息,包括架构、主机名、操作系统类型等

2、CPU使用率:

(1 - avg(rate(node_cpu_seconds_total{mode="idle"}[$interval])) by (instance)) * 100

3、CPU负载:

node_load1:1分钟负载
node_load5:5分钟负载
node_load15:15分钟负载

4、内存使用率:

100 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100

5、磁盘指标:

node_filesystem_size_bytes:磁盘总量
node_filesystem_avail_bytes:磁盘可用量

6、磁盘IO:

sum(rate(node_disk_read_bytes_total[1m]))     # 磁盘每秒读取量
sum(rate(node_disk_written_bytes_total[1m]))  # 磁盘每秒写入量

7、网络IO:

sum(rate(node_network_receive_bytes_total[1m]))     # 网卡IO(进)
sum(rate(node_network_transmit_bytes_total[1m]))  # 网卡IO(出)

节点监控部署

物理节点性能监控一般是通过node_exporter来获取,要监控云原生集群节点同样我们这里使用 node_exporter,由于每个节点都需要获取到监控指标数据,所以我们可以通过 DaemonSet 控制器来部署该服务,这样每一个节点都会自动运行一个 node-exporter 的 Pod,如果我们从集群中删除或者添加节点后,也会进行自动扩展。

1、创建 DaemonSet 控制器的编排文件node-exporter-daemonset.yaml:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: kube-system
  labels:
    app: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostPID: true
      hostIPC: true
      hostNetwork: true
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: node-exporter
          image: prom/node-exporter:v1.3.1
          args:
            - --web.listen-address=$(HOSTIP):9100
            - --path.procfs=/host/proc
            - --path.sysfs=/host/sys
            - --path.rootfs=/host/root
            - --no-collector.hwmon # 禁用不需要的一些采集器
            - --no-collector.nfs
            - --no-collector.nfsd
            - --no-collector.nvme
            - --no-collector.dmi
            - --no-collector.arp
            - --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/containerd/.+|/var/lib/docker/.+|var/lib/kubelet/pods/.+)($|/)
            - --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$
          ports:
            - containerPort: 9100
          env:
            - name: HOSTIP
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
          resources:
            requests:
              cpu: 150m
              memory: 200Mi
            limits:
              cpu: 300m
              memory: 400Mi
          securityContext:
            runAsNonRoot: true
            runAsUser: 65534
          volumeMounts:
            - name: proc
              mountPath: /host/proc
            - name: sys
              mountPath: /host/sys
            - name: root
              mountPath: /host/root
              mountPropagation: HostToContainer
              readOnly: true
      tolerations: # 添加容忍
        - operator: "Exists"
      volumes:
        - name: proc
          hostPath:
            path: /proc
        - name: dev
          hostPath:
            path: /dev
        - name: sys
          hostPath:
            path: /sys
        - name: root
          hostPath:
            path: /

由于我们要获取到的数据是主机的监控指标数据,而我们的 node-exporter 是运行在容器中的,所以我们在 Pod 中需要配置一些 Pod 的安全策略,这里我们就添加了 hostPID: truehostIPC: truehostNetwork: true 3 个策略,用来使用主机的 PID namespaceIPC namespace 以及Network namespace,这些 namespace 就是用于容器隔离的关键技术。

另外使用hostPath存储卷技术将主机的 /dev/proc/sys这些目录挂载到容器中,这些因为我们采集的很多节点数据都是通过这些文件夹下面的文件来获取到的,比如我们在使用 top 命令可以查看当前 cpu 使用情况,数据就来源于文件 /proc/stat,使用 free 命令可以查看当前内存使用情况,其数据来源是来自 /proc/meminfo 文件。

2、通过DaemonSet控制器创建Pod:

kubectl apply -f  node-exporter-daemonset.yaml

3、查看Pod是否运行正常:

[root@k8s-01 prometheus]# kubectl get pod -n kube-system -l app=node-exporter -owide
NAME                  READY   STATUS    RESTARTS   AGE     IP               NODE     NOMINATED NODE   READINESS GATES
node-exporter-5brqt   1/1     Running   0          3m35s   192.168.31.162   k8s-03   <none>           <none>
node-exporter-hqzbp   1/1     Running   0          3m35s   192.168.31.161   k8s-02   <none>           <none>
node-exporter-tlc7r   1/1     Running   0          3m35s   192.168.31.160   k8s-01   <none>           <none>

部署完成后,我们可以看到在 3 个节点上都运行了一个 node-exporter的Pod,且状态Running,可以通过PodIP:9100方式访问获取节点指标:

curl http://192.168.31.160:9100/metrics
curl http://192.168.31.161:9100/metrics
curl http://192.168.31.162:9100/metrics

由于我们指定了 hostNetwork=true,所以PodIP实际上就是节点IP,指定的container port: 9100也会在每个节点上就会绑定一个端口 9100:

[root@k8s-01 ~]# netstat -antp|grep 9100
tcp        0      0 192.168.31.160:9100     0.0.0.0:*               LISTEN      39239/node_exporter

4、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_(.+)

成功接入后,在prometheus target页面可以看到采集正常:

353ffe98d1da3c881b793f118dc80b1a.png

5、导入8919 dashboardKubernetes云原生集群节点性能监控指标就展示到模板上,如下图:

724e5fc0860217a9e4f968dfbf6f9c45.png

5fc11c9e08913f68cec6d13e84688437.gif

[更多云原生监控运维,请关注微信公众号:云原生生态实验室]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/668574.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FreeRTOS实时操作系统(四)中断任务管理

系列文章目录 文章目录 系列文章目录前言中断优先级FreeRTOS中的中断管理一系列中断管理寄存器中断配置寄存器中断屏蔽寄存器 中断管理实战 前言 跟着正点原子学习一下中断管理&#xff0c;正好之间没有总结过&#xff0c;还有些地方不清楚。 中断优先级 中断的工作方式就不介…

Oracle的DCL、DDL、DML语言学习使用——oracle入门学习(一)

Oracle的DCL、DDL、DML语言学习使用 前言1.SQL Plus1.1 命令行SQL PLUS使用sqlplus /nologsqlplus / as sysdba 1.2 oracle自带SQL PLUS使用1.3 sys和system用户的区别 2. Oracle的体系结构3.DCL语言什么是DCL语言3.1 查看数据文件位置和表空间3.2 创建表空间3.3 删除表空间3.4…

鉴源实验室丨TBOX通讯模组AT指令测试

作者 | 李伟 上海控安安全测评部总监 来源 | 鉴源实验室 引言&#xff1a;上一篇文章我们讲了整车的OTA升级测试(详解车载设备FOTA测试&#xff09;&#xff0c;本篇我们介绍在车载零配件上比较少见却很实用的测试&#xff1a;通讯模组的AT&#xff08;Attention&#xff09;指…

总结Nginx的安装、配置与设置开机自启

在Ubuntu下安装Nginx有以下方法&#xff0c;但是如果想要安装最新版本的就必须下载源码包编译安装。 一、Nginx安装 1、基于APT源安装 sudo apt-get install nginx 安装好的文件位置&#xff1a; /usr/sbin/nginx&#xff1a;主程序 /etc/nginx&#xff1a;存放配置文件 /us…

高压放大器可以驱动电机吗

高压放大器可以驱动电机。事实上&#xff0c;高压放大器在许多应用中都是电机控制的核心部件之一。高压放大器可以将输入信号转换为高电压和高电流&#xff0c;从而驱动电动机。 一、高压放大器的原理 高压放大器是一种电子设备&#xff0c;用于将低功率信号转换为高功率信号。…

云原生之深入解析如何在Kubernetes下快速构建企业级云原生日志系统

一、概述 ELK 是三个开源软件的缩写&#xff0c;分别表示 Elasticsearch , Logstash, Kibana , 它们都是开源软件。新增了一个 FileBeat&#xff0c;它是一个轻量级的日志收集处理工具 (Agent)&#xff0c;Filebeat 占用资源少&#xff0c;适合于在各个服务器上搜集日志后传输…

Lombok你不知道的用法

Lombok是大家经常用的一款工具&#xff0c;它可以帮我们减少很多重复代码的书写&#xff0c;但是我们对它的使用&#xff0c;可能更多局限于实体类的编写&#xff0c;比如说通过Data注解实现减少getter/setter/toString等方法的编写&#xff0c;其实它还有更多的注解功能&#…

美依礼芽破圈!小红书数据解读,如何拨动二次元心弦?

今年&#xff0c;二次元存在感爆棚。新世代下二次元群体愈发壮大&#xff0c;不少博主发布二次元内容、品牌也试图融入二次元圈。那么&#xff0c;如何与之打成一片呢&#xff1f;今天&#xff0c;通过小红书数据&#xff0c;我们来解读二次元的内容方向。 点赞破8亿&#xff0…

【每日一题】1595. 连通两组点的最小成本

【每日一题】1595. 连通两组点的最小成本 1595. 连通两组点的最小成本题目描述解题思路 1595. 连通两组点的最小成本 题目描述 给你两组点&#xff0c;其中第一组中有 size1 个点&#xff0c;第二组中有 size2 个点&#xff0c;且 size1 > size2 。 任意两点间的连接成本…

对象的构造

问题 对象中成员变量的初始值是多少&#xff1f; 成员变量的初始值 #include <stdio.h>class Test { private:int i;int j; public:int getI() { return i; }int getJ() { return j; } };Test gt;int main() {printf("gt.i %d\n", gt.getI());printf("…

UE中使用Editor Utility Widget创建编辑器工具

在UE中可以使用EditorUtilityWidget创建编辑器面板工具&#xff0c;方便平时的开发。在UE4中使用编辑器UI需要开启对应插件&#xff0c;而UE5中则默认启用&#xff0c;下面就来学习一下。 1.UI创建 1.1.在Content Browser中右键&#xff0c;找到Editor Utilities即可创建编辑…

[MySQL]不允许你不会SQL语句之查询语句

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集&#xff01; &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指…

分享几个AI绘图的学习网址

AI绘图是一种使用人工智能技术来创建图形和图像的技术。 从技术角度来看&#xff0c;AI绘图是一个非常有趣和不断发展的领域。随着人工智能技术的不断进步&#xff0c;AI绘图也在不断地发展和创新&#xff0c;现在已经成为数字艺术领域中的一个重要分支。 AI绘图的出现也为许多…

2023年的深度学习入门指南(17) - 深度学习的硬件加速技术

2023年的深度学习入门指南(17) - 深度学习的硬件加速技术 有了前面的知识之后&#xff0c;想必大家对于算力需求的理解已经越来越深刻了。 除了使用CPU&#xff0c;GPU这样的通用器件之外&#xff0c;采用专用的硬件来进行加速是一个大家都能想到的选择。 其中的代表器件就是…

Docke是什么,一文带你了解

Docker的优势、与虚拟机技术的区别、三个重要概念和架构及工作原理详细讲解 随着云计算和容器化技术的发展&#xff0c;Docker作为一种轻量级的容器化技术&#xff0c;受到了越来越多的关注和应用。本文将详细介绍Docker的优势、与虚拟机技术的区别、三个重要概念和架构及工作…

memcpy 和 memmove的模拟实现

文章目录 1.函数的介绍 2.模拟实现 文章内容 1.函数的介绍 memcpy指的是C和C使用的内存拷贝函数&#xff0c;函数原型为void *memcpy(void*dest,void*src, size_t count)&#xff1b;函数的功能是从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中&#xff0c;即从…

内网穿透(NAT 穿透)原理+工具(部分无需管理员权限)

内网穿透&#xff0c;即 NAT&#xff08;Network Address Translation&#xff09; 穿透 内网穿透的实质是内网映射&#xff0c;内网地址转换成外网地址的实现。实现过程要有端对端数据传输&#xff0c;也有端口转发原理。内网映射方式&#xff0c;可以解决无公网IP问题&#…

Android问题笔记-Android studio 出现Failed to compile values file.错误

点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&…

docker compose 容器编排工具

目录 docker compose是什么&#xff1f; 官网网站&#xff1a;Docker Compose overview | Docker Documentation 安装使用compose&#xff1a; 步骤&#xff1a; 1、下载并安装compose的命令行插件 2、安装完成后授予权限&#xff0c;测试compose是否可以使用 3、实例测试…

AI大模型迈入应用时代,每日互动推动“可控大模型”落地

垂直行业更需要可控大模型 当下&#xff0c;大模型正在不断精进&#xff0c;以GPT-4、文心一言为代表的大模型&#xff08;LLM&#xff09;表现出了强大的逻辑推理能力&#xff0c;并能够很好地处理复杂任务&#xff0c;使得社会生产力得到了飞跃式提升。 面对大模型热度的持…