【集群】K8S集群搭建记录——Prometheus持久化设置

【集群】K8S集群搭建记录——Prometheus持久化设置

Fre5h1nd Lv5

🐛 背景:Prometheus数据丢失

  • 近期项目验收,需要重新操作主动式伸缩云平台,却发现好多数据丢失、系统崩溃的问题,在修复 bug、备份数据的同时,顺便把 Prometheus 升级,配置持久化功能。

🚀 相关知识

转载声明:以下内容主要来自于文档[1][2]

1️⃣ k8s 之 Volume

  • 先来介绍docker里的volume[1]

    • 对于docker容器来说,由于镜像的只读性,难以进行数据持久化。
      • 镜像是分层构建的且每一层都是只读的,只读就意味着不能修改数据;
      • 只有当一个镜像运行为容器以后,在镜像的最顶端才会加上一个可写层。而一旦这个容器被删除,对应可写层上的数据也随之被删除,因此难以数据持久化。
    • 为了解决docker容器上的数据持久化的问题,docker使用了volume。
      • 在docker上volume有两种管理方式,
        • 第一种是用户手动指定把宿主机(对于宿主机上的目录可能是挂载存储系统上的某目录)上的某个目录挂载到容器某个目录,这种管理方式叫做绑定挂载卷;
        • 还有一种就是docker自身维护把某个目录挂载到容器某个目录,这种叫docker自己管理的卷。
      • 不管使用哪种方式管理的volume,它都是容器直接关联宿主机上的某个目录或文件。
      • docker中的volume解决了容器生命周期内产生的数据在容器终止后能够持久化保存的问题
  • 进一步考虑 k8s 的情况:

    • k8s也有同样的烦恼,不同的是k8s面对的是pod。
      • pod是k8s上最小调度单元,一个pod被删除以后,pod里运行的容器也随之被删除。因此pod里容器产生的数据也存在难以被持久化的问题。
    • 为了解决这个问题,我们先来看看pod的组成[1]
      pod的组成
      • 在k8s上pod里可以运行一个或多个容器,运行多个容器。
        • 其中一个容器我们叫主容器,其他的容器是用来辅助主容器,我们叫做sidecar。
      • 对于pod来说,不管里面运行多少个容器,在最底层都会运行一个pause容器,该容器最主要用来为pod提供基础架构支撑。并且位于同一个pod中的容器都共享pause容器的网络名称空间以及IPC和UTS。
    • 因此,如果我们要想给pod里的容器提供存储卷,首先要把存储卷关联到pause容器,然后在容器里挂载pause里的存储卷;如下图所示
      挂载示意图
      • 提示:
        • 对于pause容器来说,可以关联存储A,也可以关联存储B。对于pause关联的某个存储,其位于同一pod中的其他容器就也可以挂载pause里关联的存储目录或文件。
        • 对于k8s来说,存储本来就不属于k8s内部组件,而是一个外来系统。要想k8s使用外部存储系统,首先要求pause容器有适配其对应存储系统的驱动。如果同一宿主机上运行的多个容器共享同一内核上,即宿主机内核上,有对应存储系统的驱动,pause就可以使用对应的驱动去适配对应的存储。

2️⃣ k8s 之 PV、PVC、SC[2]

  • volume的基础使用中,需要我们手动向不同类型存储接口传递不同的参数,才能实现把外部存储映射到k8s上的一个volume对象,使得pod才能正常的挂载对应的存储卷,对应pod里的容器才能正常使用。

  • 这种使用方式的前提是用户必须了解对应的存储系统,了解对应类型的存储接口,以及相关参数。这使得用户在k8s上使用存储卷变得有些复杂。

  • 为了简化这一过程,在k8s上使用pv和pvc资源来把对应底层存储接口给隐藏了,用户使用存储卷不再关心底层存储系统接口,不管底层是那种类型的存储,用户只需面对一个pvc接口即可。

  • PV、PVC和K8s集群以及pod的关系

  • 补充:

    • NFS 是 Network File System 的缩写,即网络文件系统。功能是通过网络让不同的机器、不同的操作系统能够彼此分享文件。
    • Persistent Volume(PV) 是存储卷,它代表了实际存储空间。
      • 它主要作用是把后端存储中的某个逻辑单元,映射为k8s上的pv资源。
      • pv是集群级别的资源,任意名称空间都可以直接关联某一个pv,关联pv的过程我们叫做绑定pv。
    • Persistent Volume Claim (PVC) 是存储卷声明,它代表了对存储卷的请求。当容器被重新部署到其他节点时,PVC 会将数据挂载到该节点上,从而确保数据不会丢失。
      • pvc就是持久存储卷申请,在一个名称空间下创建一个pvc就是把对应名称空间同集群上的某一pv做绑定。
      • 一旦一个名称空间绑定了一个pv后,对应的pv就会从available状态转变成bond状态,其他名称空间将不能再使用,只有对应pv是available状态才能正常的被其他名称空间关联绑定。
    • 用户在创建pod时使用存储卷只需要关心对应名称空间的pvc对象,而对应pv由集群管理管理员定义,后端存储是专门的存储管理员负责管理。而对应名称空间关联某一pv需要使用pvc资源来定义。
      • 简单讲pvc和pv的关系是一一对应的,一个pv只能对应一个pvc;至于同一名称空间下的多个pod是否能够同时使用一个PVC取决pv是否允许多路读写,对应pv是否支持多路读写取决后端存储系统。
        • 不同类型的存储系统,对应访问模式也有所不同。访问模式有三种,单路读写(ReadWriteOnce简称RWO),多路读写(ReadWriteMany简称RWX),多路只读(ReadOnlyMany简称ROX);
  • 下面我们再来说一下sc资源。

    • SC 是 StorageClass的缩写,表示存储类。
      • 这种资源主要用来对pv资源的自动供给提供接口。
        • 所谓自动供给是指用户无需手动创建pv,而是在创建pvc时对应pv会由persistentVolume-controller自动创建并完成pv和pvc的绑定。
      • 使用sc资源的前提是对应后端存储必须支持restful类型接口的管理接口,并且pvc必须指定对应存储类名称来引用SC。
      • 简单讲SC资源就是用来为后端存储提供自动创建pv并关联对应pvc的接口。如下图
        • SC与 PV、PVC 关系
        • 使用sc动态创建pv,对应pvc必须也属于该sc。
        • 上图主要描述了用户在创建pvc时,引用对应的sc以后,sc会调用底层存储系统的管理接口,创建pv并关联至对应pvc。

🚢 配置过程

  • 根据相关文档,我们采用 NFS 创建 SC,再进一步开展 Prometheus 的持久化绑定。

1️⃣ 部署 NFS-Server[3]

  • 在 master 节点部署 NFS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 进入存储卷目录
$ cd /mnt/data/prometheus_data

# 部署 NFS-Server
$ yum install nfs-utils -y rpcbind

# 设置 nfs 存储目录
$ mkdir k8s-volume -p
$ chmod 755 k8s-volume

# 编辑 nfs 配置文件
$ vim /etc/exports
/mnt/data/prometheus_data/k8s-volume *(rw,no_root_squash,sync)
#存储目录,*允许所有人连接,rw读写权限,sync文件同时写入硬盘及内存,no_root_squash 使用者root用户自动修改为普通用户

# 启动 rpcbind
$ systemctl start rpcbind
$ systemctl enable rpcbind
$ systemctl status rpcbind
● rpcbind.service - RPC bind service
Loaded: loaded (/usr/lib/systemd/system/rpcbind.service; enabled; vendor preset: enabled)
Active: active (running) since 一 2022-08-22 21:31:14 CST; 11 months 0 days ago
Main PID: 1168 (rpcbind)
CGroup: /system.slice/rpcbind.service
└─1168 /sbin/rpcbind -w


# 启动 NFS
$ systemctl restart nfs
$ systemctl enable nfs
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
$ systemctl status nfs
● nfs-server.service - NFS server and services
Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; vendor preset: disabled)
Drop-In: /run/systemd/generator/nfs-server.service.d
└─order-with-mounts.conf
Active: active (exited) since 日 2023-07-23 23:22:56 CST; 15s ago
Main PID: 14007 (code=exited, status=0/SUCCESS)
Tasks: 0
Memory: 0B
CGroup: /system.slice/nfs-server.service

7月 23 23:22:55 k8s-node2 systemd[1]: Starting NFS server and services...
7月 23 23:22:56 k8s-node2 systemd[1]: Started NFS server and services.


#检查 rpcbind 及 nfs 是否正常
$ rpcinfo | grep nfs
100003 3 tcp 0.0.0.0.8.1 nfs superuser
100003 4 tcp 0.0.0.0.8.1 nfs superuser
100227 3 tcp 0.0.0.0.8.1 nfs_acl superuser
100003 3 udp 0.0.0.0.8.1 nfs superuser
100227 3 udp 0.0.0.0.8.1 nfs_acl superuser
100003 3 tcp6 ::.8.1 nfs superuser
100003 4 tcp6 ::.8.1 nfs superuser
100227 3 tcp6 ::.8.1 nfs_acl superuser
100003 3 udp6 ::.8.1 nfs superuser
100227 3 udp6 ::.8.1 nfs_acl superuser

# 查看nfs目录挂载权限
$ cat /var/lib/nfs/etab
/mnt/data/prometheus_data/k8s-volume *(rw,sync,wdelay,hide,nocrossmnt,secure,no_root_squash,no_all_squash,no_subtree_check,secure_locks,acl,no_pnfs,anonuid=65534,anongid=65534,sec=sys,rw,secure,no_root_squash,no_all_squash)
  • 在所有需要 NFS 挂在的集群节点安装
1
2
3
4
5
6
$ yum install -y nfs-utils rpcbind
$ systemctl start rpcbind
$ systemctl enable rpcbind
$ systemctl start nfs
$ systemctl enable nfs
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.

2️⃣ 创建 SC[3]

  • 进入存储卷目录
1
2
3
$ cd /mnt/data/prometheus_data
$ mkdir nfs_yaml/
$ cd nfs_yaml
  • 创建 NFS-Client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# nfs-client.yaml
# 为 prometheus pod 提供支持,避免无法Running
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-client-provisioner
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: nfs-client-provisioner
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER
value: k8s-node2 #nfs server 地址
- name: NFS_PATH
value: /mnt/data/prometheus_data/k8s-volume #nfs共享目录
volumes:
- name: nfs-client-root
nfs:
server: k8s-node2 #nfs server 地址
path: /mnt/data/prometheus_data/k8s-volume #nfs共享目录
  • 创建 nfs-client rbac 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# nfs-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
namespace: monitoring
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
namespace: monitoring
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get","list","watch","create","delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get","list","watch","update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get","list","watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list","watch","create","update","patch"]
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["create","delete","get","list","watch","patch","update"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
namespace: monitoring
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: monitoring
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
  • 执行文件,创建对象
1
2
3
$ kubectl apply -f nfs-rbac.yaml
$ kubectl apply -f nfs-client.yaml
$ kubectl get pod -n tongji-cluster
  • 创建StorageClass对象
1
2
3
4
5
6
7
# prometheus-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: prometheus-data-db
namespace: monitoring
provisioner: fuseim.pri/ifs
  • 声明Storageclass对象,其中provisioner=fuseim.pri/ifs,对应的是本集群中使用NFS作为后端存储
1
$ kubectl apply -f prometheus-storageclass.yaml

3️⃣ Prometheus 持久化绑定

  • 前提:本文所用集群使用 Prometheus Operator 方式部署监控相关组件。[4]
1
2
3
4
# 进入 Prometheus 文件目录
$ cd /etc/kubernetes/prom_yaml/
# 修改文件
$ vim prometheus/prometheus-prometheus.yaml
  • 添加如下配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
# prometheus/prometheus-prometheus.yaml
...
spec:
storage:
volumeClaimTemplate:
spec:
storageClassName: prometheus-data-db
resources:
requests:
storage: 100Gi
....

#只需要在sepc:中添加对应的信息,storageClassName为刚刚创建的名称,storage为资源对象大小
1
2
# 执行修改
$ kubectl apply -f prometheus/prometheus-prometheus.yaml

4️⃣ 查看结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ kubectl get pod -n monitoring
NAME READY STATUS RESTARTS AGE
grafana-6f7b49c756-br788 1/1 Running 4 344d
kube-state-metrics-78c9d96848-n5748 3/3 Running 6 439d
nfs-client-provisioner-96dc64d6d-lk9m4 1/1 Running 0 4m38s
node-exporter-2mjlt 2/2 Running 0 439d
node-exporter-fs7nf 2/2 Running 0 313d
node-exporter-x26l8 2/2 Running 4 439d
prometheus-k8s-0 2/2 Running 1 64s
prometheus-k8s-1 2/2 Running 1 64s
prometheus-operator-547c9cf9fd-cs4kv 2/2 Running 0 154d


$ kubectl get pv -n monitoring | grep prom
pvc-e786b1a8-d2ef-453d-9f5d-b1cb4b2b5574 100Gi RWO Delete Bound monitoring/prometheus-k8s-db-prometheus-k8s-1 prometheus-data-db 3m5s
pvc-fd9f1223-8131-4b0f-b070-661a2bcfd782 100Gi RWO Delete Bound monitoring/prometheus-k8s-db-prometheus-k8s-0 prometheus-data-db 3m5s

$ kubectl get pvc -n monitoring
prometheus-k8s-db-prometheus-k8s-0 Bound pvc-fd9f1223-8131-4b0f-b070-661a2bcfd782 100Gi RWO prometheus-data-db 3m20s
prometheus-k8s-db-prometheus-k8s-1 Bound pvc-e786b1a8-d2ef-453d-9f5d-b1cb4b2b5574 100Gi RWO prometheus-data-db 3m20s
  • 可以测试一下把 pod 删掉数据是否还保存
    1
    $ kubectl delete pods -n monitoring prometheus-k8s-0

🤔 反思

  • 以目标为导向可以大大提高效率。
    • 本次实现过程中,
      • 先查询“Prometheus 持久化”发现了些教程,但意识到大部分名词看不懂;
      • 于是转向查询相关名词。
        • 看相关名词的过程中,头脑逐渐迷糊,渐渐忘记主线,开始陷入细节中。
        • 上了个厕所,复盘发现自己效率有点低,于是立马警醒自己。
      • 接下来回顾最初查到的教程,以看懂教程为目标,缩小名词排查范围,只关注“PV、PVC、SC”等概念,效率回升。
  • 就我个人而言,很容易陷入细节里。原因就是干着干着会忘记主线,只想把文档里的每个字都看懂,从而积累小小成就感。从大局看,有点捡了芝麻丢了西瓜,还是得时刻问自己“我现在在干什么?”,同时记录工作过程方便自己理清思路。

  • 希望通过分享我配置k8s持久化的经历,可以帮助你在类似的问题上更加迅速和高效地解决困扰你的问题。
  • 希望这篇博客对你有帮助!如果你有任何问题或需要进一步的帮助,请随时提问。
  • 如果你喜欢这篇文章,欢迎动动小手 给我一个follow或star。

🗺参考文献

[1] 容器编排系统K8s之Volume的基础使用

[2] 容器编排系统K8s之PV、PVC、SC资源

[3] Prometheus Operator 持久化存储

[4] 使用kube-prometheus部署k8s监控(最新版)

  • 标题: 【集群】K8S集群搭建记录——Prometheus持久化设置
  • 作者: Fre5h1nd
  • 创建于 : 2023-07-23 21:44:59
  • 更新于 : 2024-03-08 15:36:55
  • 链接: https://freshwlnd.github.io/2023/07/23/k8s/k8s-persistence/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论