由于在该环境中Kubernetes的版本是 1.20.2,我们不使用最新版 kube-prometheus-stack,而采用兼容 1.20 的 Prometheus Operator + Grafana 部署方案,避免兼容性问题。对于 Kubernetes 1.20,官方兼容矩阵建议使用较早的 kube-prometheus release(如 release-0.8)。
15.1 准备环境
15.1.1 确认节点全部正常
在 ECS 上执行:
kubectl get nodes
应该类似:
NAME STATUS ROLES
ecs-prod Ready control-plane
k8s-node1 Ready
k8s-node2 Ready
如果不是全部 Ready,就先不要继续。
kubectl get pods -A
确保:
CoreDNS
Calico
Ingress
全部 Running。
15.1.2 确认资源充足
执行:
kubectl top nodes
如果没有安装 metrics-server,不要紧,会提示:
Metrics API not available
后续我们也可以补装。
15.1.3 创建监控命名空间
kubectl create namespace monitoring
查看:
kubectl get ns
应该出现:
monitoring
15.2 拉取node-exporter:v1.3.1镜像并推送Harbor
15.2.1 devops机器拉取镜像
你的 devops:
192.168.10.10
执行:
docker pull prom/node-exporter:v1.3.1
如果速度慢,可以使用镜像加速。
15.2.2 登录 Harbor
devops:
docker login 192.168.10.20
输入 Harbor 用户密码。
15.2.3 修改镜像名称
docker tag \
prom/node-exporter:v1.3.1 \
192.168.10.20/hybridblog/node-exporter:v1.3.1
检查:
docker images | grep node-exporter
应该:
192.168.10.20/hybridblog/node-exporter:v1.3.1
15.2.4 推送 Harbor
docker push \
192.168.10.20/hybridblog/node-exporter:v1.3.1
成功:
digest: sha256:xxxx
15.3 准备命名空间并部署node-exporter
15.3.1 创建 monitoring 命名空间
建议和你的:
hybridblog
kube-system
ingress-nginx
分开。
在 ECS master:
mkdir -p /data/k8s/monitoring
cd /data/k8s/monitoring
创建:
vim namespace.yaml
内容:
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
执行:
kubectl apply -f namespace.yaml
检查:
kubectl get ns
应该:
monitoring Active
15.3.2 创建 Harbor 拉取密钥
因为你的镜像:
192.168.10.20/hybridblog/node-exporter:v1.3.1
不是公网镜像。
所以 Kubernetes 需要 Harbor 登录信息。
执行:
kubectl create secret docker-registry harbor-secret \
--docker-server=192.168.10.20 \
--docker-username=你的Harbor用户名 \
--docker-password=你的密码 \
-n monitoring
查看:
kubectl get secret -n monitoring
应该:
NAME TYPE
harbor-secret kubernetes.io/dockerconfigjson
15.3.3 部署 node-exporter
作用:
采集 Linux 主机指标:
例如:
- CPU
- 内存
- 磁盘
- 网络
Prometheus 不直接读取节点信息。
结构:
Linux节点
↓
node-exporter
↓
Prometheus
创建:
vim node-exporter.yaml
内容:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitoring
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
imagePullSecrets:
- name: harbor-secret
containers:
- name: node-exporter
image:
192.168.10.20/hybridblog/node-exporter:v1.3.1
ports:
- containerPort: 9100
name: metrics
args:
- "--path.rootfs=/host"
volumeMounts:
- name: root
mountPath: /host
readOnly: true
volumes:
- name: root
hostPath:
path: /
建议增加:
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
避免以后监控组件占资源。
部署:
kubectl apply -f node-exporter.yaml
查看:
kubectl get pod -n monitoring -o wide
应该类似:
node-exporter-xxxxx Running k8s-node1
node-exporter-yyyyy Running k8s-node2
因为 DaemonSet 会:
每个 Node 自动创建一个 Pod
15.3.4 创建 node-exporter Service
Prometheus 需要访问 node-exporter。
创建:
vim node-exporter-service.yaml
内容:
apiVersion: v1
kind: Service
metadata:
name: node-exporter
namespace: monitoring
spec:
selector:
app: node-exporter
ports:
- port: 9100
targetPort: 9100
type: ClusterIP
执行:
kubectl apply -f node-exporter-service.yaml
查看:
kubectl get svc -n monitoring
应该:
node-exporter ClusterIP 10.xx.xx.xx 9100/TCP
15.3.5 验证 node-exporter
进入任意节点:
或者 ECS:
kubectl run test \
--image=busybox \
-n monitoring \
-it --rm \
-- sh
测试:
wget -qO- http://node-exporter:9100/metrics
如果看到:
# HELP node_cpu_seconds_total
node_cpu_seconds_total...
说明成功。
到这里完成第一层监控:
Kubernetes
Node1
|
node-exporter
|
Node2
|
node-exporter
↓
Prometheus
15.4 部署Prometheus
15.4.1 准备Prometheus镜像
在devops节点:
进入:
cd /root
拉取官方镜像:
docker pull prom/prometheus:v2.53.0
查看:
docker images | grep prometheus
打tag:
docker tag \
prom/prometheus:v2.53.0 \
192.168.10.20/hybridblog/prometheus:v2.53.0
登录Harbor:
docker login 192.168.10.20
推送:
docker push \
192.168.10.20/hybridblog/prometheus:v2.53.0
15.4.2 创建monitoring目录
在ecs-prod:
mkdir -p /root/monitoring/prometheus
cd /root/monitoring/prometheus
创建:
prometheus/
├── prometheus.yml
├── prometheus-deployment.yaml
├── prometheus-rbac.yaml
└── prometheus-service.yaml
15.4.3 创建 prometheus RBAC
进入:
cd /root/monitoring/prometheus
创建:
vim prometheus-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:
- pods
- nodes
- services
verbs:
- get
- list
- watch
---
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
应用:
kubectl apply -f prometheus-rbac.yaml
15.4.4 创建Prometheus配置文件
创建:
vim prometheus.yml
内容:
global:
scrape_interval: 20s
scrape_configs:
- job_name: node-exporter
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels:
- __meta_kubernetes_pod_label_app
action: keep
regex: node-exporter
- source_labels:
- __meta_kubernetes_pod_ip
regex: (.+)
target_label: __address__
replacement: $1:9100
- source_labels:
- __meta_kubernetes_pod_node_name
target_label: node
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
15.4.5 创建ConfigMap
kubectl create configmap prometheus-config \
-n monitoring \
--from-file=prometheus.yml
检查:
kubectl get configmap -n monitoring
应该:
prometheus-config
15.4.6 部署Prometheus Deployment
创建:
vim prometheus-deployment.yaml
内容:
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
nodeSelector:
kubernetes.io/hostname: k8s-node1
imagePullSecrets:
- name: harbor-secret
serviceAccountName: prometheus
containers:
- name: prometheus
image: 192.168.10.20/hybridblog/prometheus:v2.53.0
args:
- "--config.file=/etc/prometheus/prometheus.yml"
ports:
- containerPort: 9090
volumeMounts:
- name: config
mountPath: /etc/prometheus
volumes:
- name: config
configMap:
name: prometheus-config
15.4.7 创建Service
vim prometheus-service.yaml
内容:
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: monitoring
spec:
selector:
app: prometheus
ports:
- port: 9090
targetPort:9090
type: NodePort
部署:
kubectl apply -f prometheus-deployment.yaml
kubectl apply -f prometheus-service.yaml
查看:
kubectl get pod -n monitoring
应该:
NAME
node-exporter-xxxxx
node-exporter-yyyyy
prometheus-xxxxx
15.4.8 确认Prometheus采集成功
查看service:
kubectl get svc -n monitoring
例如:
prometheus NodePort
9090:30090
访问:
http://192.168.10.40:30090
进入:
Status
↓
Targets
应该看到:
node-exporter
UP
10.244.xx.xx:9100
10.244.xx.xx:9100
完成这里之后,再部署:
Prometheus
|
|
v
Grafana
|
|
Dashboard
|
|
CPU
Memory
Disk
Network
你的最终监控架构:
Grafana
|
|
Prometheus
|
------------------------------
| |
node-exporter node-exporter
| |
k8s-node1 k8s-node2
镜像来源:
Harbor
|
|
Prometheus镜像
Node-exporter镜像
15.5 部署 Grafana
15.5.1 Grafana 部署目标
最终:
浏览器
|
|
Grafana
|
|
Prometheus
|
|
node-exporter
|
|
k8s-node1
k8s-node2
15.5.2 准备 Grafana 镜像
因为你的网络结构:
ecs-prod
|
VPN
|
k8s-node1
k8s-node2
|
Harbor
所以继续使用 Harbor。
在 devops 节点:
docker pull grafana/grafana:11.1.0
查看:
docker images | grep grafana
应该:
grafana/grafana 11.1.0
打标签:
docker tag \
grafana/grafana:11.1.0 \
192.168.10.20/hybridblog/grafana:11.1.0
登录:
docker login 192.168.10.20
推送:
docker push \
192.168.10.20/hybridblog/grafana:11.1.0
确认 Harbor:
应该看到:
hybridblog
└── grafana
└── 11.1.0
15.5.4 创建 Grafana namespace
你的 Prometheus 已经在:
monitoring
所以继续:
kubectl get ns
如果存在:
monitoring
不用创建。
15.5.5 创建持久化环境
在ecs-prod:
kubectl label node k8s-node1 grafana=true
登录 k8s-node1:
ssh k8s-node1
创建目录:
mkdir -p /data/grafana
修改权限:
Grafana 官方镜像默认 uid 为 472
chown -R 472:472 /data/grafana
chmod -R 755 /data/grafana
15.5.5 创建 Grafana Deployment
创建目录:
mkdir -p /root/monitoring/grafana
cd /root/monitoring/grafana
创建:
vim grafana-deployment.yaml
内容:
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
nodeSelector:
grafana: "true"
imagePullSecrets:
- name: harbor-secret
containers:
- name: grafana
image: 192.168.10.20/hybridblog/grafana:11.1.0
ports:
- containerPort: 3000
env:
- name: GF_SECURITY_ADMIN_USER
value: "admin"
- name: GF_SECURITY_ADMIN_PASSWORD
value: "admin"
volumeMounts:
- name: grafana-storage
mountPath: /var/lib/grafana
volumes:
- name: grafana-storage
hostPath:
path: /data/grafana
type: DirectoryOrCreate
部署:
kubectl apply -f grafana-deployment.yaml
查看:
kubectl get pod -n monitoring -o wide
预计:
grafana-xxxxx Running
15.5.6 创建 Grafana Service
创建:
vim grafana-service.yaml
内容:
apiVersion: v1
kind: Service
metadata:
name: grafana
namespace: monitoring
spec:
selector:
app: grafana
ports:
- port: 3000
targetPort: 3000
nodePort: 30030
type: NodePort
应用:
kubectl apply -f grafana-service.yaml
查看:
kubectl get svc -n monitoring
例如:
grafana NodePort 10.96.xx.xx 3000:30030/TCP
访问:
http://k8s-node1_IP:30030
登录:
用户名:
admin
密码:
admin
15.5.7 添加 Prometheus 数据源
进入 Grafana 首页:
左侧菜单:
Connections
↓
Data sources
点击:
Add data source
选择:
Prometheus
配置 Prometheus URL
重点是这里。
你的 Prometheus 在:
monitoring namespace
Service 名字:
应该是:
kubectl get svc -n monitoring
类似:
NAME TYPE
prometheus ClusterIP
grafana NodePort
假设:
prometheus
那么 Kubernetes DNS:
prometheus.monitoring.svc.cluster.local
端口:
9090
所以 URL 填:
http://prometheus.monitoring.svc.cluster.local:9090
如下:
URL:
http://prometheus.monitoring.svc.cluster.local:9090
其他保持默认:
Access:
Server
不要选择 Browser。
点击:
Save & Test
成功应该显示:
Successfully queried the Prometheus API.
15.5.8 导入 Node Exporter Full Dashboard
左侧:
Dashboards
↓
New
↓
Import
看到:
Import dashboard
输入:
1860
也就是:
Node Exporter Full
点击:
Load
15.5.9选择数据源
下一页会让你选择:
Prometheus
选择刚才创建的数据源:
例如:
Prometheus
然后:
Import