k8s持久存储StorageClass
//
# Centos安装nfs服务
- 存储挂载服务器,安装nfs (IP:192.168.108.10)
#aster节点安装nfs
yum -y install nfs-utils rpcbind
#创建nfs目录
mkdir -p /data/sharedir
#编辑export文件,这个文件就是nfs默认的配置文件
cat >>/etc/exports<<'EOF'
/data/sharedir *(rw,no_root_squash,no_all_squash,sync,anonuid=2233,anongid=2233)
EOF
#配置生效
exportfs -r #在以后新加挂载,也用这个命令重新挂载配置
#查看生效
exportfs
#启动rpcbind、nfs服务
systemctl restart rpcbind #必须先启动rpcbind,再启动nfs
systemctl restart nfs
systemctl enable nfs rpcbind
#查看 RPC 服务的注册状况
rpcinfo -p localhost
#showmount测试
showmount -e localhost # showmount -e IP
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
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
- 所有计算节点(node)安装nfs
yum -y install nfs-utils
检查挂载
[root@hdss-21 ~]# showmount -e 192.168.108.10 Export list for 192.168.108.10: /data/sharedir * /data/k8ssharedir *
# 静态绑定pv,pvc
参数说明
参数 | 说明 |
---|---|
capacity | 指定 PV 的容量 |
accessModes | 指定访问模式 |
persistentVolumeReclaimPolicy | PV 的回收策略 |
storageClassName | 指定PV的class类型,比如k8s默认支持的nfs |
nfs | pv 挂载nfs服务的信息 |
accessModes
ReadWriteOnce pv以 read-write 模式 mount 到单个节点。
ReadOnlyMany pv以 read-only 模式 mount 到多个节点。
ReadWriteMany pv以 read-write 模式 mount 到多个节点。
persistentVolumeReclaimPolicy
Retain – 需要管理员手工回收。
Recycle – 清除 PV 中的数据,效果相当于执行 rm -rf /data/sharedir/nginx-test/*。
Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、AzureDisk、OpenStack 等。
# 创建PV
vi nginx-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-web01
labels:
nfspv: nginx-web01
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nginxnfs
nfs:
path: "/data/sharedir/nginx-test"
server: 192.168.108.10
readOnly: false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建PVC
提示:pvc绑定到对应pv通过labels标签方式实现,也可以不指定,将随机绑定到pv。如果pvc指定labels标签等名称,就要对应pv里面的名称,否则绑定不上。
PV和PVC的 accessModes要一致,当没有设置storageClassName时,pv与pvc绑定不是通过名字来绑定,而是通过(访问模式,类型,大小)来匹配
vi nginx-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-web01
namespace: default
labels:
app: nginx-web01
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
storageClassName: nginxnfs
selector:
matchLabels:
nfspv: nginx-web01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 执行yml,绑定
mkdir -p /data/sharedir/nginx-test #创建挂载目录
kubectl apply -f nginx-pv.yml
kubectl apply -f nginx-pvc.yml
#查看
kubectl get pv
kubectl get pvc
1
2
3
4
5
6
7
2
3
4
5
6
7
# 创建pod测试
vi nginx-pod.yml
kind: Pod
apiVersion: v1
metadata:
name: nginx-web
namespace: default
spec:
containers:
- name: nginx-web
image: nginx:1.21.1
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: nginx-web
volumes:
- name: nginx-web
persistentVolumeClaim:
claimName: nginx-web01 #对应pvc名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
创建pod:kubectl apply -f nginx-pod.yml
# 动态绑定之StatefulSet
Github nfs借鉴 (opens new window)
介绍
StatefulSet 是用来管理有状态应用的工作负载 API 对象。 StatefulSet 用来管理某 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。 和 Deployment 类似, StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同的是, StatefulSet 为它们的每个 Pod 维护了一个有粘性的 ID。 这些 Pod 是基于相同的规约来创建的, 但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。 如果希望使用存储卷为工作负载提供持久存储,可以使用 StatefulSet 作为解决方案的一部分。 尽管 StatefulSet 中的单个 Pod 仍可能出现故障, 但持久的 Pod 标识符使得将现有卷与替换已失败 Pod 的新 Pod 相匹配变得更加容易。
特性
Pod一致性:包含次序(启动、停止次序)、网络一致性。此一致性与Pod相关,与被调度到哪个node节点无关; 稳定的次序:对于N个副本的StatefulSet,每个Pod都在[0,N)的范围内分配一个数字序号,且是唯一的; 稳定的网络:Pod的hostname模式为( StatefulSet名称)−(statefulset名称)-(statefulset名称)−(序号); 稳定的存储:通过VolumeClaimTemplate为每个Pod创建一个PV。删除、减少副本,不会删除相关的卷。
限制
给定 Pod 的存储必须由 PersistentVolume 驱动 基于所请求的 storage class 来提供,或者由管理员预先提供。 删除或者收缩 StatefulSet 并不会删除它关联的存储卷。 这样做是为了保证数据安全,它通常比自动清除 StatefulSet 所有相关的资源更有价值。 StatefulSet 当前需要无头服务 来负责 Pod 的网络标识。你需要负责创建此服务。 当删除 StatefulSets 时,StatefulSet 不提供任何终止 Pod 的保证。 为了实现 StatefulSet 中的 Pod 可以有序地且体面地终止,可以在删除之前将 StatefulSet 缩放为 0。 在默认 Pod 管理策略(OrderedReady) 时使用 滚动更新,可能进入需要人工干预 才能修复的损坏状态。 注意:删除PVC,会删除相应的pv,同时还是删除对应的挂载(ID序号)目录
为什么需要volumeClaimTemplate?
对于有状态的副本集都会用到持久存储,对于分布式系统来讲,它的最大特点是数据是不一样的,所以各个节点不能使用同一存储卷,每个节点有自已的专用存储 但是如果在Deployment中的Pod template里定义的存储卷,是所有副本集共用一个存储卷,数据是相同的,因为是基于模板来的 , 而statefulset中每个Pod都要自已的专有存储卷,所以statefulset的存储卷就不能再用Pod模板来创建了,于是statefulSet使用volumeClaimTemplate,称为卷申请模板, 它会为每个Pod生成不同的pvc,并绑定pv,从而实现各pod有专用存储。这就是为什么要用volumeClaimTemplate的原因。
# 部署nfs-client-provisioner
nfs-client-provisioner: 是一个Kubernetes的简易NFS的外部provisioner,本身不提供NFS,需要现有的NFS服务器提供存储
# 配置deplopyment.yml文件
vi deplopyment-nfs-client-provisioner.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
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: 192.168.108.10
- name: NFS_PATH
value: /data/k8ssharedir
volumes:
- name: nfs-client-root
nfs:
server: 192.168.108.10
path: /data/k8ssharedir
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
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
# 配置StorageClass.yml文件
provisioner
provisioner属性要等于驱动所传入的环境变量PROVISIONER_NAME的值。否则,驱动不知道知道如何绑定storage class。
如果修改provisioner的名字,需要与上面的deployment的PROVISIONER_NAME名字一致。
vi StorageClass-nfs.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
archiveOnDelete: "false"
1
2
3
4
5
6
7
2
3
4
5
6
7
# 配置rbac-nfs.yml文件
配置RBAC授权provisioner (k8s1.6+默认开启)
vi rbac-nfs.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
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: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
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
63
64
65
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
63
64
65
# 配置statefulset.yml文件
vi statefulset-nginx-web.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30001
name: web
selector:
app: nfs-web
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nfs-web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nfs-web # has to match .spec.template.metadata.labels
template:
metadata:
labels:
app: nfs-web
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: nginx:1.21.1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
annotations:
volume.beta.kubernetes.io/storage-class: managed-nfs-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Gi
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
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
# 创建服务client-provisioner
kubectl apply -f rbac-nfs.yml
kubectl apply -f deplopyment-nfs-client-provisioner.yml
kubectl apply -f StorageClass-nfs.yml
#检查服务
kubectl get roles.rbac.authorization.k8s.io
kubectl get deployments.apps
kubectl get pod
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 创建服务statefulset
kubectl apply -f statefulset-nginx-web.yaml
#检查服务
kubectl get pod
1
2
3
4
2
3
4
注意的是:新增 scale会自动新加pvc,减少不会自动删除pvc,pv,在手动删除pvc 的时候,会删除pv和挂载的随机id目录
//
如果此文章对您有帮助,点击 -->> 请博主喝咖啡 (opens new window)
上次更新: 2022/12/29, 16:26:13