存储类型
- configMap
- Secret
- volume
- Persistent Volume
存储-ConfigMap
ConfigMap功能在k8s1.2引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API提供了向容器注入配置信息的机制。
ConfigMap可以用来保存单个属性,也可以用来保存整个配置文件或json二进制大对象。
ConfigMap的创建
1. 使用目录创建
$ ls /path/to/configmap/files/
game.properties
ui.properties
$ vim game.properties
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
$ vim ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=failyNice
$ kubectl create configmap game-config --from-file=/path/to/configmap/files
--from-file
指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对 ,键的名字就是文件名,值就是文件的内容。
2. 使用文件创建
只要指定为一个文件就可以从单个文件中创建ConfigMap。
$ kubectl create configmap game-config-2 --from-file=/path/to/configmap/files/game.properties
# 查看配置信息
$ kubectl get configmaps game-config-2 -o yaml
--from-file
这个参数可以使用多次,你可以使用两次分别指定上个实例中的那两个配置文件,效果和指定整个目录是一样的。
3. 使用字面值创建
使用文字值创建,利用 --from-literal
参数传递配置信息,该参数可以使用多次,格式如下:
$ kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
$ kubectl get configmaps special-config -o yaml
Pod中使用 ConfigMap
1. 使用 ConfigMap 替代环境变量
special-config:
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
env-config:
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
eg:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: hub.adaixuezhang.cn/library/myapp:v1
command: ["/bin/sh", "-c", "env"]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
envFrom:
- configMapRef:
name: env-config
restartPolicy: Never
2. 用 ConfigMap 设置命令行参数
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
pod:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: hub.adaixuezhang.cn/library/myapp:v1
command: ["/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)"]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
envFrom:
- configMapRef:
name: env-config
restartPolicy: Never
3. 通过数据卷插件使用ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
在数据卷里面使用这个 ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容。
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: hub.adaixuezhang.cn/library/myapp:v1
command: ["/bin/sh", "-c", "cat /etc/config/special.how"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
restartPolicy: Never
ConfigMap的热更新
apiVersion: v1
kind: ConfigMap
metadata:
name: log-config
namespace: default
data:
log_level: INFO
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: hub.adaixuezhang.cn/library/myapp:v1
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: log-config
检查:
$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` cat /etc/config/log_level
修改ConfigMap:
$ kubectl edit configmap log-config
特别注意:ConfigMap 如果以 ENV 的方式挂载至容器,修改ConfigMap并不会实现热更新!
ConfigMap更新后滚动更新Pod
更新ConfigMap目前并不会触发相关Pod的滚动更新,可以通过修改 Pod annotations 的方式强制触发滚动更新:
$ kubectl patch deployment my-nginx --patch '{"spec": {"template": {"metadata": {"annotations": {"version/config": "20200924"}}}}}'
如上在 .spec.template.metadata.annotations
中添加 version/config
,每次通过修改 version/config
来触发滚动更新。
更新 ConfigMap 后:
- 使用该 ConfigMap 挂载的Env不会同步更新;
- 使用该 ConfigMap 挂载的Volume中的数据需要一段时间(实测大概60s)才能同步更新。
存储-Secret
Secret解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者Pod Spec中。Secret可以以volume或者环境变量的方式使用。
Secret有三种类型:
- service account:用来访问k8s API,由k8s自动创建,并且会自动挂载到Pod的
/run/secrets/kubernetes.io/serviceaccount
目录中; - Opaque:base64编码格式的Secret,用来存储密码、密钥等;
- kubernetes.io/dockerconfigjson:用来存储私有 docker registry 的认证信息。
Service Account
$ kubectl run nginx --image nginx
$ kubectl get pods
$ kubectl exec nginx-pod-id ls /run/secrets/kubernetes.io/serviceaccount
Opaque Secret
1. 创建说明
Opaque 类型的数据是一个 map 类型,要求 value 是 base64 编码格式:
$ echo -n "admin" |base64
YWRtaW4=
$ echo -n "12lkwghs873" |base64
MTJsa3dnaHM4NzM=
secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: MTJsa3dnaHM4NzM=
username: YWRtaW4=
2. 使用方式
-
将Secret挂载到Volume中
apiVersion: v1 kind: Pod metadata: labels: name: mysecret name: secret-test spec: volumes: - name: secrets secret: secretName: mysecret containers: - image: hub.adaixuezhang.cn/library/myapp:v1 name: db volumeMounts: - name: secrets mountPath: "/etc/secrets" readOnly: true
进入容器查看
/etc/secrets
目录。 -
将Secret导出到环境变量中
apiVersion: apps/v1 kind: Deployment metadata: name: pod-deployment spec: replicas: 2 selector: matchLabels: app: pod-deployment template: metadata: labels: app: pod-deployment spec: containers: - name: pod-1 image: hub.adaixuezhang.cn/library/myapp:v1 ports: - containerPort: 80 env: - name: TEST_USER valueFrom: secretKeyRef: name: mysecret key: username - name: TEST_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password
进入容器,查看环境变量
echo $TEST_USER $TEST_PASSWORD
。
kubernetes.io/dockerconfigjson
使用kubectl 创建 docker registry认证的Secret
$ kubectl create secret docker-registry myregistry --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
secret "myregistrykey" created.
在创建Pod时,通过 imagePullSecrets
来引用刚创建的 myregistrykey
:
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: foo
image: hub.adaixuezhang.cn/test/myapp:v2
imagePullSecrets:
- name: myregistrykey
存储-volume
容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)重新启动;其次,在Pod中同时运行多个容器时,这些容器之间通常需要共享文件。k8s中Volume 抽象就很好的解决了这些问题。
卷的类型
k8s支持一下类型的卷:
emptyDir
当 Pod 被分配给节点时,首先创建 emptyDir
卷,并且只要该Pod在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod中的容器可以读取和写入 emptyDir
卷中相同的文件,该卷可以挂载到每个容器中的相同或不同路径上。当处于任何原因从节点中删除Pod时,emptyDir
中的数据将被永久删除。
注意:容器崩溃不会从节点中移除Pod,因此 emptyDir
卷中的数据在容器崩溃时是安全的。
emptyDir
的用法有:
- 暂存空间,例如用于基于磁盘的合并排序;
- 用作长时间计算崩溃恢复时的检查点;
- web服务器容器提供数据时,保存内容管理器容器提取的文件。
eg:
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- name: test-container
image: hub.adaixuezhang.cn/library/myapp:v1
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
hostPath
hostPath
卷将主机节点的文件系统中的文件或目录挂载到集群中。
hostPath用途如下:
- 运行需要访问Docker内部的容器:使用
/var/lib/docker
的hostPath
; - 在容器中运行 CAdvisor:使用
/dev/cgroups
的hostPath
;
除了所需的 path 属性之外,用户还可以为 hostPath 卷指定 type:
值 | 含义 |
---|---|
空字符串(默认)用于向后兼容,这意味着在挂载hostPath卷之前不会执行任何检查 | |
DirectoryOrCreate | 如果在给定的路径上没有任何东西存在,那么将根据需要在那里创建一个空目录,权限设置为0755,与kubelet具有相同的组合所有权 |
Directory | 给定的路径下必须存在目录 |
FileOrCreate | 如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为0644,与kubelet具有相同的组合所有权 |
File | 给定的路径下必须存在文件 |
Socket | 给定的路径下必须存在 UNIX 套接字 |
CharDevice | 给定的路径下必须存在字符设备 |
BlockDevice | 给定的路径下必须存在块设备 |
使用这种类型时需要注意:
- 由于每个节点上的文件都不同,具有相同配置(如从podTemplate创建的)的pod在不同节点上的行为可能会有所不同;
- 当k8s安装计划添加资源感知调度时,将无法考虑 hostPath 使用的资源;
- 在底层主机上创建的文件或目录只能由 root 写入。需要在特权容器中以root运行进程,或修改主机上的文件权限以便写入 hostPath 卷。
eg:
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- name: test-container
image: hub.adaixuezhang.cn/test/myapp:v2
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory
存储-PV-PVC
PV(PersistentVolume)
是由管理员设置的存储,它是集群的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。PV 是Volume之类的卷插件,但具有独立于使用PV的Pod的生命周期。此API对象包含存储实现的细节,即NFS、iSCSI或特定云供应商的存储系统。
PVC(PersistentVolumeClaim)
是用户存储的请求。它与pod相似。pod消耗节点资源,PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(例如,可以以读/写一次或只读多次模式挂载)
静态PV
集群管理员创建一些PV,它们带有可供集群用户使用的实际存储的细节。它们存在于k8s API中,可用于消费。
动态PV:
当管理员创建的静态PV都不匹配用户的 PVC 时,集群可能会尝试动态的为PVC创建卷。此配置基于 StrongClasses
:PVC 必须请求【存储类】,并且管理员必须创建并配置该类才能进行动态创建。声明该类为 ""
可以有效地禁用其他动态配置。
要启用基于存储级别的动态存储配置,集群管理员需要启用 API Server 上的 DefaultStorageClass
【准入控制器】。例如,通过确保 DefaultStorageClass
位于 API Server 组件的 --admission-control
标志,使用逗号 分割的有序值列表中,可以完成此操作。
绑定
master中的控制环路监视新的PVC,寻找匹配的PV(如果可能),并将它们绑定在一起。如果为新的PVC动态调配PV,则该环路将始终将该PV绑定到PVC。否则,用户总会得到它们所请求的存储,但是容量可能会超出要求的数量。一旦PV和PVC绑定后,PVC绑定是排他性的,不管它们是如何绑定的。PVC和PV是一对一的映射。
持久化卷声明的保护
持久化卷类型
eg:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0003
spec:
capacity:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp
server: 172.16.180.132
PV 访问模式
Volume插件支持的访问模式:
回收策略
新版本k8s中 Recycle机制已废弃!详见官方文档!!!
状态
eg:
安装NFS服务器
Server端:
$ yum install -y nfs-common nfs-utils rpcbind
$ mkdir /nfs
$ chmod 777 /nfs
$ vim /etc/exports
/nfs *(rw,no_root_squash,no_all_squash,sync)
$ systemctl enable --now rpcbind
$ systemctl enable --now nfs
client端:
$ yum install -y nfs-utils rpcbind
# 测试挂载-确保nfs服务可用
$ showmount -e 172.16.180.132
$ mkdir /share
$ mount -t nfs 172.16.180.132:/nfs /share
部署PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfspv1
spec:
capatcity:
storage: 100M
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfs
server: 172.16.180.132
创建服务并使用PVC
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: hub.adaixuezhang.cn/library/myapp:v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "nfs"
resources:
requests:
storage: 50M
关于StatefulSet
StatefulSet的启停顺序:
StatefulSet使用场景: