这是我参与更文挑战的第9天,活动详情查看: 更文挑战
k8s环境中,不管是deployment还是daemonset还是其他控制器对象,最终启动的容器还是pod,pod在运行中会产生临时数据,如果pod重启,数据会丢失。对于无状态应用,是可以接受的,但有状态pod就不行了,会导致大故障,所以持久化存储至关重要,那k8s中的存储又是怎么样的了
主要概念
k8s中有4个重要概念: Volume(卷)、PersistentVolume(持久卷)、PersistentVolumeClaim(PVC)、StorageClass(存储类)
架构图
Volume
volume是最基础的使用方式,其底层可以是不同类型的存储方案,默认支持列表(不断增加中)
awsElasticBlockStoreazureDiskazureFilecephfscinderconfigMapdownwardAPIemptyDirfc (fibre channel)flocker (deprecated)gcePersistentDiskgitRepo (deprecated)glusterfshostPathiscsilocalnfs
PV持久卷
持久卷是集群中的一块存储,可以提前配置,或使用storageclass 动态创建,pv独立于pod生命周期,pod重启,pv可继续存在
回收策略:
Retain(保留) --手动回收
Delete (删除) --关联的存储资产 如 AWS EBS、GCE PD、Azure Disk和OpenStack Cinder卷将被删除
当前只有NFS和HostPath支持回收策略。 AWS EBS、GCE PD 、Azure Disk 和Cinder卷支持删除策略
状态:
卷可以处于以下的某种状态:
Available(可用)——一块空闲资源还没有被任何声明绑定
Bound(已绑定)——卷已经被声明绑定
Released(已释放)——声明被删除,但是资源还未被集群重新声明
Failed(失败)——该卷的自动回收失败
PVC持久卷认领
消费PV,从PV处申请卷,PV上的存储单元
例子:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv004
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs1
nfs:
path: /nfsdata1
server: 192.168.78.136
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc004
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: nfs1
StorageClass存储类
storage class相当于为提供了一组接口,可以按策略配置,来动态创建PV和服务各种底层存储,如GlusterFS
每个 StorageClass 都包含 provisioner
、parameters
和 reclaimPolicy
字段, 这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到
官方参考: kubernetes.io/docs/concep…
例子:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: glusterfs-storageclass
namespace: default
parameters:
resturl: "http://ip:8080"
clusterid: "xxxxxxxxxx"
restauthenabled: "true" #若heketi开启认证此处也必须开启auth认证
restuser: "admin"
secretName: "glusterfs-secret" #name/namespace与secret资源中定义一致
secretNamespace: "default"
volumetype: "replicate:2"
provisioner: kubernetes.io/glusterfs
reclaimPolicy: Delete
allowVolumeExpansion: true
实战部署
nfs安装
在centos7上
yum install nfs-utils rpcbind -y
配置
mkdir -p /data/nfs
chmod 755 /data/nfs
vi /etc/exports
-
/data/nfs *(rw,sync,no_root_squash,no_all_squash)
-
systemctl enable rpcbind
systemctl enable nfs-server
systemctl start rpcbind
systemctl start nfs-server
#查看nfs信息
showmount -e localhost
配置释义
ro 只读访问
rw 读写访问sync 所有数据在请求时写入共享
async nfs 在写入数据前可以响应请求
secure nfs 通过1024以下的安全TCP/IP端口发送
insecure nfs 通过1024以上的端口发送
wdelay 如果多个用户要写入nfs目录,则归组写入(默认)
no_wdelay 如果多个用户要写入nfs目录,则立即写入,当使用async时,无需此设置。
hide 在nfs共享目录中不共享其子目录
no_hide 共享nfs目录的子目录
subtree_check 如果共享/usr/bin之类的子目录时,强制nfs检查父目录的权限(默认)
no_subtree_check 和上面相对,不检查父目录权限
all_squash 共享文件的UID和GID映射匿名用户anonymous,适合公用目录。
no_all_squash 保留共享文件的UID和GID(默认)
root_squash root用户的所有请求映射成如anonymous用户一样的权限(默认)
no_root_squas root用户具有根目录的完全管理访问权限
anonuid=xxx 指定nfs服务器/etc/passwd文件中匿名用户的UID
anongid=xxx 指定nfs服务器/etc/passwd文件中匿名用户的GID
以nfs为底层实际存储,来部署一个zookeeper集群
创建PVPVC
PV 作为存储资源,主要包括存储能力、访问模式、回收策略、存储类型
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv1
labels:
app: nfs
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
nfs:
path: /data/nfs/pv1
server: ip
参数说明:
- capacity:持久卷资源和容量的描述,存储大小是唯一可设置或请求的资源。
- accessMode:访问模式,有ReadWriteOnce,ReadOnlyMany,ReadWriteMany。其中: ReadWriteOnce:表示具有读写权限,但是只能被一个node挂载一次 ReadOnlyMany:表示具有只读权限,可以被多个node多次挂载 ReadWriteMany:表示具有读写权限,可以被多个node多次挂载
- persistentVolumeReclaimPolicy: 回收策略,也就是释放持久化卷时的策略,其有以下几种: Retain:保留数据,如果要清理需要手动清理数据,默认的策略; Delete:删除,将从Kubernetes中删除PV对象,以及外部基础设施中相关的存储资产,比如AWS EBS, GCE PD, Azure Disk, 或Cinder volume; Recycle:回收,清楚PV中的所有数据,相当于执行rm -rf /pv-volume/*;
- NFS 存储类型,还支持众多,比如常用的Ceph和GlusterFS
*注 目前只有 NFS 和 HostPath 两种类型支持回收策略。持久化应用基本配Retain
创建PV
pv.yaml
PV的状态说明:
-
Available(可用):表示可用状态,还未被任何 PVC 绑定
-
Bound(已绑定):表示 PVC 已经被 PVC 绑定
-
Released(已释放):PVC 被删除,但是资源还未被集群重新声明
-
Failed(失败): 表示该 PV 的自动回收失败
PVC挂载PV,实际PV的申请者,也有访问模式,资源请求,挂载类型等
PVC创建时会自动绑定到PV,但是一个PVC只能绑定一个PV(因为我们访问模式定义的ReadWriteOnce),且容量不能大于PV,如果是只读只写的PV可以被多个PVC挂载,但是访问模式要和PV一样
如果有默认的存储类,PVC会自动绑定到存储类,这时需要selector来选择labels
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc1
spec:
selector:
matchLabels:
app: nfs
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
参数说明:
-
accessModes:主要定义卷所应该拥有的访问模式
-
resources:主要定义卷应该拥有的最小资源
-
selector:定义绑定卷的标签查询
-
dataSource:定义如果提供者具有卷快照功能,就会创建卷,并将数据恢复到卷中,反之不创建
-
storageClassName:定义的storageClass的名字(如果PV有定义或SC有定义的)
-
volumeMode:定义卷的类型
-
volumeName:需要绑定的PV的名称链接
创建PVC
kubectl apply -f pvc.yaml
kubectl get pv,pvc
pvpvc总结:
- Pod声明了PVC,K8S会找一个PV配对,如果没有PV,就去找对应的StorageClass,帮它创建一个PV,然后和PVC完成绑定,就是Bound,如果都没有,就是PENGDING
创建StorageClass
官方sigs组织有一个repo专门来提供配置以及教程: github.com/kubernetes-…
其中覆盖比较全面,且没有排序,想正确安装使用也得爬爬坑,当然github也有repo整理排序的,但是这个SC是根据host来创建,也可以参考一下: github.com/adonaicosta…
接下来开始部署sc
k8s所有节点安装nfs客户端(其他存储服务差不多,如果直接挂载的基本都要在k8s 节点安装客户端)
yum -y install nfs-utils
创建rbac
apiVersion: v1
kind: Namespace
metadata:
name: dmp-storage-class
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
namespace: dmp-storage-class
---
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: dmp-storage-class
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
namespace: dmp-storage-class
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
namespace: dmp-storage-class
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: dmp-storage-class
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
创建nfs-client
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
namespace: dmp-storage-class
spec:
replicas: 1
selector:
matchLabels:
app: nfs-client-provisioner
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
imagePullPolicy: IfNotPresent
#请替换成quay.io/external_storage/nfs-client-provisioner:latest
image: harbor-test.libaogo.cn/dev/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes/
env:
- name: PROVISIONER_NAME
value: go.libaigo.com/nfs - name: NFS_SERVER
value: ip
- name: NFS_PATH
value: /data/nfs/pv4
volumes:
- name: nfs-client-root
nfs:
server: ip
path: /data/nfs/pv4
创建SC
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: dmp-nfs-storage annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: go.libaigo.com/nfs # or choose another name, must match deployment's env PROVISIONER_NAME'
reclaimPolicy: Retain
parameters:
archiveOnDelete: "false"
创建PVC
匹配对应存储类,会自动创建PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: sc-test
labels:
app: sc-test
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: dmp-nfs-storage
resources:
requests:
storage: "5Gi"
执行以下命令或在目录执行 kubectl apply -f ./
kubectl apply -f rbac.yaml
kubectl apply -f deployment-nfs-client.yaml
kubectl apply -f StorageClass-nfs-yaml
kubectl apply -f pvc.yaml
查看结果
以deployment方式部署的nfs-client
在rancher存储类的中的PV
总结:
-
StorageClass 支持众多存储类型
-
StorageClass 根据Type 可以实现动态PV,实现动态扩容
-
StorageClass 非常灵活,根据不同Type 实现不同功能
-
StorageClass 根据Type 实现数据高可用,高冗余