🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 监控集群节点 要监控节点其实我们已经有很多非常成熟的方案了,比如 Nagios、zabbix,甚至我们自己来收集数据也可以,我们这里通过 Prometheus 来采集节点的监控指标数据,可以通过 [node_exporter](https://github.com/prometheus/node_exporter) 来获取,顾名思义,`node_exporter` 就是抓取用于采集服务器节点的各种运行指标,目前 `node_exporter` 支持几乎所有常见的监控点,比如 conntrack,cpu,diskstats,filesystem,loadavg,meminfo,netstat 等,详细的监控点列表可以参考其 [Github 仓库](https://github.com/prometheus/node_exporter)。 我们可以通过 DaemonSet 控制器来部署该服务,这样每一个节点都会自动运行一个这样的 Pod,如果我们从集群中删除或者添加节点后,也会进行自动扩展。 在部署 `node-exporter` 的时候有一些细节需要注意,如下资源清单文件:(prometheus-node-exporter.yaml) ```yaml cat <<'EOF' | kubectl apply -f - apiVersion: apps/v1 kind: DaemonSet metadata: name: node-exporter namespace: kube-system spec: selector: matchLabels: app.kubernetes.io/instance: node-exporter updateStrategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app.kubernetes.io/instance: node-exporter spec: securityContext: fsGroup: 65534 runAsGroup: 65534 runAsNonRoot: true runAsUser: 65534 containers: - name: node-exporter image: quay.io/prometheus/node-exporter:v1.7.0 imagePullPolicy: IfNotPresent args: - --path.procfs=/host/proc - --path.sysfs=/host/sys - --path.rootfs=/host/root - --collector.filesystem.fs-types-exclude=^(tmpfs|devtmpfs|cgroup2|overlay)$ securityContext: readOnlyRootFilesystem: true ports: - name: metrics containerPort: 9100 protocol: TCP livenessProbe: failureThreshold: 3 httpGet: httpHeaders: path: / port: 9100 scheme: HTTP initialDelaySeconds: 0 periodSeconds: 10 successThreshold: 1 readinessProbe: failureThreshold: 3 httpGet: httpHeaders: path: / port: 9100 scheme: HTTP initialDelaySeconds: 0 periodSeconds: 10 successThreshold: 1 volumeMounts: - name: proc mountPath: /host/proc readOnly: true - name: sys mountPath: /host/sys readOnly: true - name: root mountPath: /host/root mountPropagation: HostToContainer readOnly: true hostNetwork: true hostPID: true nodeSelector: kubernetes.io/os: linux tolerations: - operator: Exists volumes: - name: proc hostPath: path: /proc - name: sys hostPath: path: /sys - name: root hostPath: path: / EOF ``` 由于我们要获取到的数据是主机的监控指标数据,而我们的 `node-exporter` 是运行在容器中的,所以我们在 Pod 中需要配置一些 Pod 的安全策略,这里我们就添加了 `hostPID: true`、`hostIPC: true`、`hostNetwork: true` 3个策略,用来使用主机的 `PID namespace`、`IPC namespace` 以及主机网络,这些 namespace 就是用于容器隔离的关键技术,要注意这里的 namespace 和集群中的 namespace 是两个完全不相同的概念。 另外我们还将主机的 `/dev`、`/proc`、`/sys`这些目录挂载到容器中,这些因为我们采集的很多节点数据都是通过这些文件夹下面的文件来获取到的,比如我们在使用 `top` 命令可以查看当前 cpu 使用情况,数据就来源于文件 `/proc/stat`,使用 `free` 命令可以查看当前内存使用情况,其数据来源是来自 `/proc/meminfo` 文件。 ```shell $ kubectl apply -f node-exporter.yaml  daemonset.apps/node-exporter create $ kubectl get pods -n kube-mon -l app=node-exporter -o wide NAME                  READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES node-exporter-q42fg   1/1     Running   0          16m   172.20.0.14   k8s-master   <none>           <none> node-exporter-r54ds   1/1     Running   1          22h   172.20.0.13   k8s-node01   <none>           <none> node-exporter-tdwgt   1/1     Running   1          22h   172.20.0.9    k8s-node02   <none>           <none> ``` ## 验证 部署完成后,我们可以看到在3个节点上都运行了一个 Pod,由于我们指定了 `hostNetwork=true`,所以在每个节点上就会绑定一个端口 9100,我们可以通过这个端口去获取到监控指标数据: ```shell $ curl 172.20.0.14: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"} 0.098513621 go_gc_duration_seconds{quantile="0.25"} 0.098513621 go_gc_duration_seconds{quantile="0.5"} 0.098513621 go_gc_duration_seconds{quantile="0.75"} 0.098513621 go_gc_duration_seconds{quantile="1"} 0.098513621 go_gc_duration_seconds_sum 0.098513621 go_gc_duration_seconds_count 1 ``` ## 自定义指标 有些指标没有对应的exporter来收集,那么只能通过自定义指标来实现。`node_exporter` 可在启动时指定路径,并将该路径下的 `*.prom` 识别为监控数据文件。 **编写脚本** ```shell mkdir -p /opt/exports/{scripts,values} cat > /opt/exports/scripts/pids.sh <<-EOF #!/bin/bash echo \# Number of system pids. echo node_pids_kernel_use_number \$(ps -eLf | wc -l) echo node_pids_kernel_total_number \$(sysctl kernel.pid_max | awk -F= '{print \$2}') echo \# Number of user pids. echo node_pids_user_use_number \$(ps -eLf | egrep "^root" | wc -l) echo node_pids_user_total_number \$(ulimit -u) echo \# Number of Cgroups pids. echo node_pids_cgroup_use_number \$(cat /sys/fs/cgroup/pids/kubepods.slice/pids.current) echo node_pids_cgroup_total_number \$(cat /sys/fs/cgroup/pids/kubepods.slice/pids.max) EOF ``` **设置定时任务获取值** ```shell echo "* * * * * root bash /opt/exports/scripts/pids.sh > /opt/exports/values/pids.prom" >> /etc/crontab ``` **添加参数及挂载文件** ```shell kubectl -n kube-mon edit ds node-exporter # 在 secp.template.containers.args 下,新增一行 - --collector.textfile.directory=/opt/exports/values/ # 在 secp.template.containers.volumeMounts 下,新增两行 - name: custom-indicator mountPath: /opt/exports/values/ # 在 spec.template.volumes 下,新增三行 - name: custom-indicator hostPath: path: /opt/exports/values/ ``` ## 验证 curl -s 192.168.31.103:9100/metrics | grep pids | egrep -v "^#" ![](https://img.kancloud.cn/41/e8/41e8a54895aef9875dbf90a7c758bfe8_1133x194.png) node_pids_cgroup_total_number ![](https://img.kancloud.cn/d6/90/d690b83d25feb96e671d43573939b682_1920x643.png) ## Prometheus抓取数据 ```yaml - job_name: "node-exporters" kubernetes_sd_configs: - role: node relabel_configs: - source_labels: [__address__] action: replace regex: (.*):10250 target_label: __address__ replacement: $1:9100 metric_relabel_configs: - source_labels: [__address__] action: replace regex: (.*):10250 target_label: instance replacement: $1 ``` ## 附加iptables规则 ```shell iptables -t filter -I INPUT -p tcp --dport 9100 -m comment --comment "k8s node exporter ports" -j ACCEPT ```