为什么需要数据卷?
容器中的文件在磁盘上是临时存放的,这给容器中运行比较重要的应用程序带来一些问题
问题1:当容器升级或者崩溃时,kubelet会重建容器,容器内文件会丢失
问题2:一个Pod中运行多个容器并需要共享文件
kubenetes卷(Volume)这一抽象概念能够解决这两个问题
常用的数据卷
• 节点本地(hostPath, emptyDir)
• 网络(NFS, Ceph, GlusterFS)
• 公有云(AWS EBS)
• K8S资源(configmap, secret)
emptyDir卷
是一个临时存储卷,与Pod生命周期绑定一起,如果Pod删除了卷也会被删除。
应用场景: Pod中容器之间数据共享
案例
apiVersion: v1
kind: Pod
metadata:
name: pod-emptydir
spec:
containers:
- image: centos
command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"]
name: write
volumeMounts:
- mountPath: /data
name: cache-volume
- image: centos
command: ["bash","-c","tail -f /data/hello"]
name: read
volumeMounts:
- mountPath: /data
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
节点数据卷: hostPath
hostPath卷: 挂载Node文件系统(Pod所在节点)上文件或者目录到Pod中的容器。
应用场景: Pod中容器需要访问宿主机文件
案例:
apiVersion: v1
kind: Pod
metadata:
name: pod-emptydir
spec:
containers:
- image: centos
command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"]
name: write
volumeMounts:
- mountPath: /data
name: cache-volume
- image: centos
command: ["bash","-c","tail -f /data/hello"]
name: read
volumeMounts:
- mountPath: /data
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
网络数据卷: NFS
NFS卷: 提供对NFS挂载支持,可以自动将NFS共享路径
挂载到Pod中
NFS: 是一个主流的文件共享服务器。
# yum install nfs-utils
#设置用于同步数据的目录读写权限
# vi /etc/exports
/ifs/kubernetes *(rw,no_root_squash)
# mkdir -p /ifs/kubernetes
# systemctl start nfs
# systemctl enable nfs
注:每个Node上都要安装nfs-utils包,因为会使用到某些依赖。
示例:将Nginx网站程序根目录持久化到
NFS存储,为多个Pod提供网站程序文件
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web-nfs
spec:
replicas: 3
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
labels:
app: web
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumes:
- name: data
nfs:
server: 192.168.40.132
path: /ifs/kubernetes
持久数据卷概述
PersistentVolume(PV): 对存储资源创建和使用的抽象,使得存储作为集群中的资源管理
PersistentVolumeClaim(PVC): 让用户不需要关心具体的Volume实现细节
pvc:申请容量
pv:提供存储
1、pvc与pv的匹配策略
pvc匹配最接近的大于自己申请容量的pv,如果满足不了,pod处于pending
Pod申请PVC作为卷来使用, Kubernetes通过PVC查找绑定的PV,并Mount给Pod。
PV与PVC使用流程
PV生命周期
AccessModes(访问模式):
AccessModes是用来对PV进行访问模式的设置,用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:
•ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载•ReadOnlyMany(ROX):只读权限,可以被多个节点挂载•ReadWriteMany(RWX):读写权限,可以被多个节点挂载
RECLAIM POLICY(回收策略):
目前PV支持的策略有三种:
•Retain(保留):保留数据,需要管理员手工清理数据•Recycle(回收):清除PV中的数据,效果相当于执行rm-rf /ifs/kuberneres/*•Delete(删除):与PV相连的后端存储同时删除
STATUS(状态):
一个PV的生命周期中,可能会处于4中不同的阶段:
•Available(可用):表示可用状态,还未被任何PVC绑定•Bound(已绑定):表示PV已经被PVC绑定•Released(已释放):PVC被删除,但是资源还未被集群重新声明•Failed(失败):表示该PV的自动回收失败
目前PV使用方式称为静态供给,需要K8s运维工程师提前创建一堆PV,供开发者使用。
PV 动态供给(StorageClass)
PV静态供给明显的缺点是维护成本太高了!因此, K8s开始支持PV动态供给,使用StorageClass对象实现。
K8s默认不支持NFS动态供给,需要单独部署社区开发的插件。
项目地址:
GitHub - kubernetes-sigs/nfs-subdir-external-provisioner: Dynamic sub-dir volume provisioner on a remote NFS server.
部署
cd deploy
kubectl apply -f rbac.yaml # 授权访问apiserver
kubectl apply -f deployment.yaml # 部署插件,需修改里面NFS服务器地址与共享目录
kubectl apply -f class.yaml # 创建存储类
kubectl get sc # 查看存储类
StorageClass测试案例:在创建pvc时指定存储类名称
基于NFS实现PV动态供给流程图
StatefulSet 控制器介绍
无状态与有状态:
Deployment控制器设计原则:
管理的所有Pod一模一样,提供同一个服务,也不考虑在哪台Node运
行,可随意扩容和缩容。这种应用称为“
无状态”,例如Web服务
在实际的场景中,这并不能满足所有应用,尤其是分布式应用,会部署多个实例,
这些实例之间往往有依赖关系,例如主从关系、主备关系,这种应用称为“有状态”,例如MySQL主从、 Etcd集群
StatefulSet控制器用于部署有状态应用,满足一些有状态应用的需求:
• Pod有序的部署、扩容、删除和停止
• Pod分配一个稳定的且唯一的网络标识
• Pod分配一个独享的存储
StatefulSet 部署应用实践
• 稳定的网络ID(域名)
使用Headless Service(相比普通Service只是将spec.clusterIP定义为None)来维护Pod网络身份。并且添加serviceName: “nginx” 字段指定StatefulSet控制器要使用这个Headless Service。DNS解析名称: <statefulsetName-index>.<service-name> .<namespace-name>.svc.cluster.local
• 稳定的存储
StatefulSet的存储卷使用VolumeClaimTemplate创建,称为卷申请模板,当StatefulSet使用VolumeClaimTemplate创建一个PersistentVolume时,同样也会为每个Pod分配并创建一个编号的PVC。
StatefulSet与Deployment区别:
有身份的!
身份三要素:
• 域名• 主机名• 存储(PVC)
应用程序数据存储
• ConfigMap:存储配置文件
• Secret:存储敏感数据
ConfigMap 存储应用配置
创建ConfigMap后,数据实际会存储在K8s中Etcd,然后通过创建Pod时引用该数据。
应用场景:应用程序配置
Pod使用configmap数据有两种方式:
• 变量注入
• 数据卷挂载
ConfigMap 存储应用配置
Secret 存储敏感信息
与ConfigMap类似,区别在于Secret主要存储敏感数据,所有的数据要经过base64编码。
应用场景:凭据
kubectl create secret 支持三种数据类型:
• docker-registry:存储镜像仓库认证信息• generic:存储用户名、密码• tls:存储证书
Secret 存储敏感信息案例
当创建容器时出现Pending状态,可以通过以下命令查看
kubectl describe pod pod名称
1、pvc与pv匹配条件
主要参考存储容量和访问模式
2、pvc与pv的关系
一对一
3、存储容量能限制嘛?
目前不能,主要用于匹配,限制主要取决于后端存储。
存储类型:
1、共享存储,例如NFS,直接能多台机器挂载
2、块存储,例如硬盘、Ceph,只能挂载到单个机器上,并且需要先格式化
3、对象存储,例如阿里云OSS,通过API访问
每个pod不等对,怎么体现的不对等(角色)?
配置文件(节点标识、IP唯一、数据存储)
部署一个etcd,3个pod,肯定是一个镜像。
如何区分3个pod的角色?
启动容器时候,启动不同的配置文件,并且这一步是自动化的。
自动化如何去做?如何自适应k8s机制?
主要是连接另一个pod的域名、决定自身角色的条件
怎么决定自身角色?
可以根据pod主机名决定(编号)。
假设当前起的第一个pod,编号肯定是0,容器启动时执行自动化脚本,脚本就可以根据编号角色启动的配置。