掌握多种存储类型的特点 并且能够在不同环境中选择合适的存储方案(有自己的见解)
一、ConfigMap
https://kubernetes.io/zh/docs/concepts/configuration/configmap/
1.2版本中引入,主要功能是为了解决应用程序会从配置文件、环境变量中获取配置信息,ConfigMap API为我们提供了向容器中注入配置信息的机制,ConfigMap可以被用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制对象。ConfigMap 是为了方便的处理不含铭感信息的字符串,你可以将它理解为Linux系统中的/etc目录,专门用来存储配置文件的目录
注意: ConfigMap不是属性配置文件的代替品,只是作为多个properties文件的引用。
一、创建configmap
1.创建目录和配置文件
# mkdir configmap
# cd configmap/
# cat <<EOF > cm.properties
user.name=liuli
user.password=12345
EOF
1.使用目录创建
#kubectl create configmap cm-config-path --from-file /root/configmap
2.使用文件创建
#kubectl create configmap cm-config-file --from-file /root/configmap/cm.properties
3.使用字面值创建 (--from-literal)
#kubectl create configmap cm-config-kv --from-literal=user.name=liuli --from-literal=user.password=12345
4.资源清单形式创建 【 --- 多个文件放到一起】
# vim vim configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.level: very
special.type: charm
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
查看
# kubectl get configmap
# kubectl get configmap cm-config-kv -o yaml
二、在Pod中使用 【# kubectl explain configmap.apiVersion 版本 v1】2种方式 (env /envFrom)
# vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: test-container
image: nginx
command: ["/bin/sh","-c","env"]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.level
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
envFrom:
- configMapRef:
name: env-config
restartPolicy: Never
# kubectl apply -f pod.yaml
服务启动会打印环境变量,查看日志,可以看到导入的环境变量
# kubectl logs configmap-pod
在命令行中引用 :
command: ["/bin/sh","-c","echo $(SPECIAL_TYPE_KEY)"]
通过数据卷插件使用ConfigMap
# vim valume-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: valume-configmap-pod
spec:
containers:
- name: test-container
image: nginx
command: ["/bin/sh","-c","sleep 6000s"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
restartPolicy: Never
# kubectl apply -f valume-pod.yaml
进入容器查看
# kubectl exec valume-configmap-pod -it -- /bin/bash
-- 进入挂载目录 打印数据
root@valume-configmap-pod:/etc/config# cd /etc/config
root@valume-configmap-pod:/etc/config# ls
special.level special.type
root@valume-configmap-pod:/etc/config# cat special.level
veryroot@valume-configmap-pod:/etc/config#
configMap热更新
修改configMap
kubectl edit configMap special-config
修改信息:
等一会( 大约10s 就看到环境变量 改变了)
veryroot@valume-configmap-pod:/etc/config# cat special.level
very-hotroot@valume-configmap-pod:/etc/config#
更新ConfigMap目前并不会触发相关pod的滚动更新,可以通过修改 pod annotaions 的方式强制触发滚动更新【TODO】
1.使用该ConfigMap挂载Env不会同步更新
2.使用该ConfigMap挂载的volume中的数据需要一段时间(大概10s)才能同步更新
二、Secret
https://kubernetes.io/zh/docs/concepts/configuration/secret/
解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴漏到镜像或者Pod Spec中。Secret可以以Vlolume或者环境变量的但是使用。
内置类型
kubernetes.io/service-account-token 服务账号令牌
kubernetes.io/dockercfg ~/.dockercfg 文件的序列化形式
kubernetes.io/dockerconfigjson ~/.docker/config.json 文件的序列化形式
kubernetes.io/basic-auth 用于基本身份认证的凭据
kubernetes.io/ssh-auth 用于 SSH 身份认证的凭据
kubernetes.io/tls 用于 TLS 客户端或者服务器端的数据
bootstrap.kubernetes.io/token 启动引导令牌数据
Service Account:用来访问k8s api,由系统自动创建,并且自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount目录中
Opaque: base64编码格式的secret,用来存储密码、密钥等 ;是一个map类型的数据,要求value是base64编码格式
# 获取base64编码
[root@k8s ~]# echo -n "admin" |base64
YWRtaW4=
[root@k8s ~]# echo -n "12345" |base64
MTIzNDU=
# vim secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MTIzNDU=
# kubectl apply -f secret.yaml
# kubectl get secret
1.将Secret挂载到volume中
# vim pod-secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: sercret-test
labels
name: sercret-test
spec:
volumes:
- name: secrets
secret:
secretName: mysecret
containers:
-image:nginx
name: db
volumeMounts:
- name: secrets
mountPath: ''
readOnly: true
# kubectl apply -f pod-secret.yaml
# kubectl get pod
# kubectl exec secret-test -it -- /bin/sh
查看效果 (使用时自己完成解密)
# cd /etc/secrets
# ls
password username
# cat password
12345# cat username
admin#
2.将secret导出到环境变量
# vim pd-pod-secrets.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-deploment
spec:
replicas: 2
selector:
matchLabels:
app: pod-deploment
template:
metadata:
labels:
app: pod-deploment
spec:
containers:
- name: myapp
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
env:
- name: TEST_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: TEST_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
#kubectl apply -f pd-pod-secrets.yaml
# 查看结果
[root@k8s secret]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-deploment-f69948d58-gqmlx 1/1 Running 0 6s
pod-deploment-f69948d58-vjfwh 1/1 Running 0 6s
[root@k8s secret]# kubectl exec pod-deploment-f69948d58-gqmlx -it -- bin/sh
# echo $TEST_USER
admin
kubernates.io/dockerconfigjson: 用来存储私有docker register 的认证信息
# kubectl create secret docker-registry myregistrykey \
--docker-server=DOCKER_REGISTER_SERVER \
--docker-username=DOCKER_USER \
--docker-password= DOCKER_PASSWORD \
--docker-email=DOCKER_EMAIL
在创建pod的时候使用,通过imagePullSecrets来引用创建的 ‘myregistrykey ’
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: foo
iamge: nginx
imagePullSecrets:
-name: myregistrykey
basic-auth 、basic-auth (参考服务发现 ingress-nginx 应用)
三、volume
https://kubernetes.io/zh/docs/concepts/storage/
Container 中的文件在磁盘上是临时存放的,这给 Container 中运行的较重要的应用 程序带来一些问题。问题之一是当容器崩溃时文件丢失。kubelet 会重新启动容器, 但容器会以干净的状态重启。 第二个问题会在同一 Pod 中运行多个容器并共享文件时出现。 Kubernetes 卷(Volume) 这一抽象概念能够解决这两个问题。
olume是k8s数据卷,常见的数据卷有4种类型:EmptyDir,HostDir,NFS,Secret,gitRepo。Kubernetes支持Volume类型有:
emptyDir
hostPath
gcePersistentDisk
awsElasticBlockStore
nfs
iscsi
fc (fibre channel)
flocker
glusterfs
rbd
cephfs
gitRepo
secret
persistentVolumeClaim
downwardAPI
projected
azureFileVolume
azureDisk
vsphereVolume
Quobyte
PortworxVolume
ScaleIO
StorageOS
local
emptyDir
使用emptyDir,当Pod分配到Node上时,将会创建emptyDir,并且只要Node上的Pod一直运行,Volume就会一直存。当Pod(不管任何原因)从Node上被删除时,emptyDir也同时会删除,存储的数据也将永久删除。注:删除容器不影响emptyDir。
使用场景:
- 暂存空间,例如用于基于磁盘的合并排序
- 用做长时间计算崩溃恢复时的检查点
- web服务器容器提供数据时,保存内容管理器容器提取的文件
hostPath
hostPath允许挂载Node上的文件系统到Pod里面去。如果Pod需要使用Node上的文件,可以使用hostPath。
- 空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
- DirectoryOrCreate 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
- Directory 在给定路径上必须存在的目录。
- FileOrCreate 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet
相同的组和所有权。 - File 在给定路径上必须存在的文件。
- Socket 在给定路径上必须存在的 UNIX 套接字。
- CharDevice 在给定路径上必须存在的字符设备。
- BlockDevice 在给定路径上必须存在的块设备。
当使用这种类型的卷时要小心,因为:
1.具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同 而在不同节点上有不同的行为。
2.下层主机上创建的文件或目录只能由 root 用户写入。你需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。
实验
# vim emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: nginx
name: myapp
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
# kubectl apply -f emptydir.yaml
## 一个空目录
# kubectl exec test-pd -it -- /bin/sh
# cd /cache
# vim hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod2
spec:
containers:
- image: nginx
name: myapp2
volumeMounts:
- mountPath: /home
name: mydir
- mountPath: /home/a.txt
name: myfile
volumes:
- name: mydir
hostPath:
path: /home
type: DirectoryOrCreate
- name: myfile
hostPath:
path: /home/a.txt
type: FileOrCreate
# kubectl apply -f hostpath.yaml
# kubectl exec test-pod2 -it -- /bin/sh
查看挂载的文件
# cd /home
# ls
四、PV/PVC (实际中使用的较少 ,没有深入研究)
https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/
**持久卷(PersistentVolume,PV)**是集群中的一块存储,可以由管理员事先供应,或者 使用存储类(Storage Class)来动态供应。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样,也是使用 卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。 此 API 对象中记述了存储的实现细节,无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。
**持久卷申领(PersistentVolumeClaim,PVC)**表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源(CPU 和内存);同样 PVC 申领也可以请求特定的大小和访问模式 (例如,可以要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载,参见访问模式)。
静态供应
集群管理员创建若干 PV 卷。这些卷对象带有真实存储的细节信息,并且对集群 用户可用(可见)。PV 卷对象存在于 Kubernetes API 中,可供用户消费(使用)。
动态供应 (实现比较繁琐,还不太有好)
如果管理员所创建的所有静态 PV 卷都无法与用户的 PersistentVolumeClaim 匹配, 集群可以尝试为该 PVC 申领动态供应一个存储卷。 这一供应操作是基于 StorageClass 来实现的:PVC 申领必须请求某个 存储类,同时集群管理员必须 已经创建并配置了该类,这样动态供应卷的动作才会发生。 如果 PVC 申领指定存储类为 “”,则相当于为自身禁止使用动态供应的卷。
绑定
PVC 申领与 PV 卷之间的绑定是一种一对一的映射
保护使用中的存储对象
确保仍被 Pod 使用的 PersistentVolumeClaim(PVC)对象及其所绑定的 PersistentVolume(PV)对象在系统中不会被删除,因为这样做可能会引起数据丢失。
访问模式
- ReadWriteOnce – 卷可以被一个节点以读写方式挂载;
- ReadOnlyMany – 卷可以被多个节点以只读方式挂载;
- ReadWriteMany – 卷可以被多个节点以读写方式挂载。
在命令行接口(CLI)中,访问模式也使用以下缩写形式:
- RWO - ReadWriteOnce
- ROX - ReadOnlyMany
- RWX - ReadWriteMany
重要提醒! 每个卷只能同一时刻只能以一种访问模式挂载,即使该卷能够支持 多种访问模式。
类
每个 PV 可以属于某个类(Class),通过将其 storageClassName 属性设置为某个 StorageClass 的名称来指定。 特定类的 PV 卷只能绑定到请求该类存储卷的 PVC 申领。 未设置 storageClassName 的 PV 卷没有类设定,只能绑定到那些没有指定特定 存储类的 PVC 申领。
早前,Kubernetes 使用注解 volume.beta.kubernetes.io/storage-class 而不是 storageClassName 属性。这一注解目前仍然起作用,不过在将来的 Kubernetes 发布版本中该注解会被彻底废弃。
回收策略
- Retain – 手动回收
- Recycle – 基本擦除 (rm -rf /thevolume/*) 【新版本已经废弃】
- Delete – 诸如 AWS EBS、GCE PD、Azure Disk 或 OpenStack Cinder 卷这类关联存储资产也被删除
目前,仅 NFS 和 HostPath 支持回收(Recycle)。 AWS EBS、GCE PD、Azure Disk 和 Cinder 卷都支持删除(Delete)。
阶段
每个卷会处于以下阶段(Phase)之一:
- Available(可用)-- 卷是一个空闲资源,尚未绑定到任何申领;
- Bound(已绑定)-- 该卷已经绑定到某申领;
- Released(已释放)-- 所绑定的申领已被删除,但是资源尚未被集群回收;
- Failed(失败)-- 卷的自动回收操作失败。
PVC(PersistentVolumeClaims)
每个 PVC 对象都有 spec 和 status 部分,分别对应申领的规约和状态,申领可以通过为 storageClassName 属性设置 StorageClass 的名称来请求特定的存储类。 只有所请求的类的 PV 卷,即 storageClassName 值与 PVC 设置相同的 PV 卷, 才能绑定到 PVC 申领。
1.在(192.168.44.134) 安装nfs服务器
# yum install -y nfs-common nfs-utils rpcbind
# mkdir /nfs
# chmod 777 /nfs/
# chown nfsnobody /nfs/
# vim /etc/exports
/nfs *(rw,no_root_squash,no_all_squash,sync)
# systemctl start rpcbind
# systemctl start nfs
# exportfs -rv //重新刷新共享(修改配置后找不到)
2.访问节点安装客户端(所有k8s节点)
# yum install -y nfs-utils rpcbind
# vim nfspv.yaml
测试挂载 ,验证后取消挂载
# mkdir /test
# showmount -e 192.168.44.134
Export list for 192.168.44.134:
/nfs *
# mount -t nfs 192.168.44.134:/nfs /test/
==== 可以测试文件访问+写入
# umount /test/
3.创建pv
# vim nfspv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp
server: 192.168.44.134
# kubectl apply -f nfspv.yaml
# kubectl get pv
4.创建PVC
# vim pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc001
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
storageClassName: slow
resources:
requests:
storage: 5Gi
创建
# kubectl apply -f pvc.yaml
查看
# kubectl get pv
# kubectl get pvc
5.使用申请PVC 【该实验没成功,有时间在研究 TODO】
# vim pod-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
name: pvc-pod
spec:
volumes:
- name: pvc-storage
persistentVolumeClaim:
claimName: pvc001
containers:
- name: pvc-container
image: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: /var/www/html
name: pvc-storage