这里我们介绍动态PV第一个案例,部署3个副本的nginx服务。主要学习 volumeClaimTemplate 属性。
statefulset组成
statefulSet的三个组成部分:
1)Headless Service :名为nginx,用来定义Pod网络标识( DNS domain)。
2)StatefulSet :定义具体应用,名为Nginx,有三个Pod副本,并为每个Pod定义了一个域名。
3)volumeClaimTemplates : 存储卷申请模板,创建PVC,指定pvc名称大小,将自动创建pvc,且pvc必须由存储类供应。
为什么需要 headless service 无头服务?
在用Deployment时,每一个Pod名称是没有顺序的,是随机字符串,因此是Pod名称是无序的,但是在statefulset中要求必须是有序 ,每一个pod不能被随意取代,pod重建后pod名称还是一样的。而pod IP是变化的,所以是以Pod名称来识别。pod名称是pod唯一性的标识符,必须持久稳定有效。这时候要用到无头服务,它可以给每个Pod一个唯一的名称 。
为什么需要volumeClaimTemplate?
对于有状态的副本集都会用到持久存储,对于分布式系统来讲,它的最大特点是数据是不一样的,所以各个节点不能使用同一存储卷,每个节点有自已的专用存储,但是如果在Deployment中的Pod template里定义的存储卷,是所有副本集共用一个存储卷,数据是相同的,因为是基于模板来的 ,而statefulset中每个Pod都要自已的专有存储卷,所以statefulset的存储卷就不能再用Pod模板来创建了,于是statefulSet使用volumeClaimTemplate,称为卷申请模板,它会为每个Pod生成不同的pvc,并绑定pv, 从而实现各pod有专用存储。这就是为什么要用volumeClaimTemplate的原因。
nfs服务
rbac
nfsnginx/nfsrbac.yml。与前文保持一致。
kind: ServiceAccount
apiVersion: v1
metadata:
name: nfs-client-provisioner
---
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
namespace: default #替换成要部署NFS Provisioner的namespace
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
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
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: default #替换成要部署NFS Provisioner的namespace
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
storageClass
nfsnginx/nfsnginxstorage.yml。与前文介绍类似,注意修改storageClass的名称
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
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
#由于quay.io仓库部分镜像国内无法下载,所以替换为其他镜像地址
image: vbouchaud/nfs-client-provisioner:v3.1.1
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: nfs-client-nginx #nfs-provisioner的名称,以后设置的storageclass要和这个保持一致
- name: NFS_SERVER
value: 192.168.198.156 #NFS服务器地址,与volumes.nfs.servers 保持一致
- name: NFS_PATH
value: /nginx #NFS服务共享目录地址,与volumes.nfs.path保持一致。使用NFS4版本进行多级目录挂载
volumes:
- name: nfs-client-root
nfs:
server: 192.168.198.156 #NFS服务器地址,与spec.containers.env.value保持一致
path: /nginx #NFS服务器目录,与 spec.containers.env.value保持一致。使用NFS4版本进行多级目录挂载
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage-nginx
annotations: storageclass.kubernetes.io/is-default-class: "true" #设置为默认的storageclass
#动态卷分配者名称,必须和创建的"provisioner"变量中设置的name一致
provisioner: nfs-client-nginx
parameters:
archiveOnDelete: "true" #设置为"false"时删除PVC不会保留数据,"true"则保留数据
mountOptions:
- hard #指定为硬挂载方式
- nfsvers=4 #指定NFS版本,这个需要 根据NFS Server 版本号设置
nginx服务
如果定义多个副本。必须使用volumeClaimTemplate属性。如果定义1个副本。可以使用pod+pvc方式。
nfsnginx/nginxstatefulset.yml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginxdeployment
labels:
app: nginxdeployment
spec:
replicas: 3
serviceName: nginxsvc
template:
metadata:
name: nginxdeployment
labels:
app: nginxdeployment
spec:
containers:
- name: nginxdeployment
image: nginx:1.17.10-alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- mountPath: /usr/share/nginx/html/
name: nginxvolume
restartPolicy: Always
volumeClaimTemplates:
- metadata:
name: nginxvolume
annotations:
volume.beta.kubernetes.io/storage-class: "nfs-storage-nginx"
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
selector:
matchLabels:
app: nginxdeployment
---
apiVersion: v1
kind: Service
metadata:
name: nginxsvc
spec:
selector:
app: nginxdeployment
ports:
- port: 8080
clusterIP: None
部署nginx服务
kubectl apply -f .
kubectl get pods -o wide
kubectl get pv
kubectl get pvc
网友评论