目录
- 更新集群中的配置文件,只需要使用配置文件注册中心即可,触发每一个进程的修改以及运行
1、configMap
如图,configMap中存储的nginx.conf的配置信息,当pod被创建时,配置信息会被自动注入,当修改了nginx.conf的文件时,pod的配置信息也会被自动的更新
创建的方式是以键值对的方式进行创建
创建configMap指令
#创建第一个文件
echo enemies=aliens$'\n'\
lives=3$'\n'\
enemies.cheat=true$'\n'\
enemies.code.lives=30 > game-test
#创建第二个文件
echo color.good=purple$'\n'\
color.bad=yello$'\n'\
allow.textmode=true$'\n'\
how.nice.to.look=veryNice > ui-test
----------------------------------------
#创建文件夹下的cm
kubectl create configmap config别名 --from-file=指定一个目录,这个目录下文件都会被创建
kubectl get cm yourCMname #查看configmap
kubectl get cm yourCMname -o yaml #查看configmap配置信息
kubectl decribe cm yourCMname # 查看configmap配置信息
相当于自动给创建了一个yaml文件
- 首先创建configmap的yaml文件,下图创建了两个configmap:special config和env-config
- 1、使用ConfigMap代替环境变量
apiVersion: v1
kind: ConfigMap
metadata:
name: test-cm #po名字
namespace: default
labels:
app: cm-test #设置标签
data:
test.how: howhow
test.why: whywhy
--- #三个横线表示分别创建
apiVersion: v1
kind: ConfigMap
metadata:
name: test2-cm2 #po名字
namespace: default
labels:
app: cm-test #设置标签
data:
log_level: INFO
2、将配置信息注入到pod中
apiVersion: v1
kind: Pod
metadata:
name: cmtest-pod #po名字
labels:
app: cmtest-pod #设置pod标签
spec:
containers:
- name: cmtest-pod #容器的名字
image: busybox #容器使用的镜像
command: ["/bin/sh", "-c","env", "sleep 6000s"] #启动容器执行指令使之在前台运行,打印env的内容
env:
- name: SPECIAL_LEVER_KEY #设置一个变量
valueFrom:
configMapKeyRef:
name: test-cm # 从名字为test-cm的configmap里面进行取值
key: test.how #通过键取值,赋值给上面的变量
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: test-cm
key: test.why
envFrom:
- configMapRef:
name: test2-cm2
restartPolicy: Never
可以看到打印了env的内容,并且变量也被赋值(取值)
- 除此之外还可以通过configmap设置命令行参数
apiVersion: v1
kind: Pod
metadata:
name: cmtest-pod #po名字
labels:
app: cmtest-pod #设置pod标签
spec:
containers:
- name: cmtest-pod #容器的名字
image: busybox #容器使用的镜像
command: ["/bin/sh", "echo $(SPECIAL_LEVER_KEY) $(SPECIAL_TYPE_KEY)"] #启动容器执行指令使之在前台运行
env:
- name: SPECIAL_LEVER_KEY #设置一个变量
valueFrom:
configMapKeyRef:
name: test-cm # 从名字为test-cm的configmap里面进行取值
key: test.how #通过键取值,赋值给上面的变量
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: test-cm
key: test.why
envFrom:
- configMapRef:
name: test2-cm2
restartPolicy: Never
唯一的区别就是使用了"echo $(SPECIAL_LEVER_KEY) $(SPECIAL_TYPE_KEY)"
进行取变量的值
- 除此之外还可以通过数据卷插件使用configmap
在数据卷里面使用这个ConfigMap,有不同的选项,最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容。
apiVersion: v1
kind: Pod
metadata:
name: test-pod6 #po名字
spec:
containers:
- name: with-node-affinity #容器的名字
image: busybox #容器使用的镜像
command: ["/bin/sh","-c", "sleep 3600"] #启动容器执行指令使之在前台运行
volumeMounts: #挂载和使用卷
- name: config-volume
mountPath: /etc/config #挂载的路径
volumes: #创建卷
- name: config-volume
configMap: #选择挂载到哪个cm上,这里选择test-cm
name: test-cm
restartPolicy: Never
可以看到这个卷已经成功挂载到容器的/etc/config目录下,并且可以可以看到cm中的两个键值对test.how和test.why。
注意:挂载到这个pod中的容器上以后,除非进到容器里面,否则不能在command命令行那里进行可读和可写操作(例如echo `data` > index.html),否则会报错:readonly。
configmap的热更新
还以上面的test-cm这个configmap为例,通过指令kubectl edit configmap test-cm
来编辑yaml文件,修改了test.how:deBug, test.why:error。切换到刚才通过test-cmt创建的pod容器中,可以看到值立即就更改了。实现了热更新的效果。
动态的修改配置信息可以通过edit指令去完成
kubectl create -f cm.yaml #生成cm
kubectl edit configmap log-config # 动态修改cm配置信息
当然这种动态的更新方式,也是基于pod annotations的方式有关,可以通过设置pod annotations来实现滚动更新,即热更新
kubectl patch deployment yourDeploymentName --patch '{"spec": {"template": {"metadata": {"annotations": {"version/config": "20200722"}}}}}'
注意:更新configmap后,使用该configmap挂载的Env不会同步更新,使用configmap挂载的Volume中的数据需要一段时间(10s)才能同步更新
通过git进行卷挂载(gitRepo存储卷)
2、Secret
configmap保存的时一些明文信息,但是如果要保存密码密钥等信息,就需要加密保存,使用Secret
Servce Account(不常用)
Opaque Secret
base64表面加密作用,实际上通过base64 -d就可以解密了它使用的场景是对极其复杂的密码或者符号甚至是文件内容进行加密,加密后就变成短短的一串字母了
- 创建secret.yaml文件,将Secret挂载到Volume中
apiVersion: v1
kind: Pod #deploymentd的类型
metadata:
labels:
name: secret-test
name: secret-test #Pod的名字
namespace: default #pod使用的命名空间
spec:
volume: #申请卷,卷名为secrets
- name: secrets
secret: # secret使用方案
secretName: mysecret # 名称为mysecret
containers: #容器
- image: centos #容器使用的镜像
name: db #容器名称
volumeMounts: #挂载的是上面的secrets
- name: secrets
mountPath: "/etc/secrets" #挂载到/etc/secrets目录下
readOnly: true # 只读
Opaque Secret,在创建的时候虽然对字段加密了,但是在创建了secret以后,调用这个字段时会自动完成解密
- 2、将Secert导出到环境中
apiVersion: extensions/v1bata1 #分组/版本号
kind: Deployment #类型
metadata:
name: Pod05 #po名字
labels:
app: Pod05 #设置pod标签
spec:
replicas: 3
template: #创建模板,一旦副本数不满足期望值就根据模板进行创建pod,保证副本的数量保持为3
metadata:
labels:
app: myapp5
spec:
nodeSelector: #标签键名的匹配选择,必须匹配键名和键值,即进行节点的匹配
key: value #能匹配上的标签就行,比如disk: ssd 就必须是ssd硬盘才行,使用kubectl label node yourNodename disk=ssd进行打标签
containers:
- name: pod05 #容器的名字
image: busybox #容器使用的镜像
command: ["/bin/sh", "-c", "sleep 6000s"] #启动容器执行指令使之在前台运行
ports:
-containerPort: 80
env:
-name: TEST_USER
valueFrom:
secertKeyRef:
name: mysecert
key: passwd
上面将username的值赋给TEST_USER,将passwd的值赋给TEST_PASSWORD。在创建这个deployment之后,通过访问创建的pod,进入pod就可以得到TEST_USER,和TEST_PASSWORD这两个关键字段对应的字符。
kubectl exec podname -it -- /bin/sh #进入pod中
echo $TEST_USER
echo $TEST_PASSWORD#输出变量对应的字符
harbor使用
当镜像仓库的私有的时候就需要加密认证,使用docker登录私有仓库,然后执行push指令
docker login your域名
输入用户名和密码
docker push your私有仓库链接
就是说每次pull镜像,都需要先登录私有仓库,再进行镜像的拉取
可以用下面Kubernetes.io/dockerconfigjson的方法来解决
Kubernetes.io/dockerconfigjson
在本机执行上面的指令,首先进行myregistrykey 的信息认证,然后在yaml文件中加入imagePullSecret: {“name”:myregistrykey},既可以实现不需要重复的输入账户密码的免认证登录效果
通过上面的myregistrykey方式进行私有仓库的认证回非常的方便
3、volume
emptyDir
当pod被分配给节点时,首先创建emptyDir卷,并且只要该pod在该节点上运行,该卷就会存在,正如卷的名字所述,它最初时空的。pod中的容器可以读取和写入emptydir卷中的相同的文件,矩管该卷可以挂载到每个容器中的相同或不同的路径上,当出于任何原因从节点上删除pod时,empty中的数据将被永久删除。
注意:容器崩溃不会从节点中移除pod,因此 emptydir
卷中的数据将会被永久删除
用法:
- 1、暂存空间,例如用于基于磁盘的合并排序
- 2、作用长时间计算崩溃恢复时的检查点
- 3、web服务器容器提供数据时,保存内容管理器容器提取的文件
apiVersion: v1
kind: Pod #deploymentd的类型
metadata:
name: test-pd
spec:
containers: #容器
- image: centos #容器使用的镜像
name: test-container #容器名称
command: ["/bin/sh", "-c", "sleep 6000s"]
volumeMounts: #挂载卷,把下面的volume的cache-volume挂载过来
- name: cache-volume
mountPath: /cache #挂载到/cache目录下
volumes: #申请卷,卷名为cache-volume
- name: cache-volume
emptyDir: {}
或者在一个pod中直接创建两个容器
apiVersion: v1
kind: Pod #deploymentd的类型
metadata:
name: test-pd
spec:
containers: #容器
- image: centos #容器使用的镜像
name: test-container #容器名称
command: ["/bin/sh", "-c", "sleep 6000s"]
volumeMounts: #挂载卷,把下面的volume的cache-volume挂载过来
- mountPath: /test01 #挂载到/test01目录下
name: cache-volume
- name: liveness-exec-container
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "sleep 6000s"]
volumeMounts:
- mountPath: /test02
name: cache-volume
volumes: #申请卷,卷名为cache-volume
- name: cache-volume
emptyDir: {
kubectl apply -f yourname.yaml#创建pod
kubectl describe pod test-pd #查看创建的pod中容器的详细信息,即得到容器名
kubectl exec podname -c containername -it -- /bin/sh #指定pod名下的容器名,切换到sh下执行
切换到容器liveness-exec-container下可以看到挂载的test文件夹,并且可以正常的写入数据
切换到容器test-container下可以看到挂载的cache文件夹,并且可以正常的写入数据
hostPath
hostPath卷将主机节点的文件系统中的文件或目录挂载到集群中
用途如下:
- 1、运行需要访问Docker内部的容器,使用/var/lib/docker的hostPath
- 2、在容器中运行cAdvisor,使用/dev/cgroups的hostpath
除了所需的path属性之外,用户还可以为hostpath卷指定type
使用hostPath卷时请注意:
- 由于每个节点的文件都不同,具有相同的配置(例如通过podTemplate创建的)的pod在不同的节点上的行为可能会有所不同
- 当kubernetes按照计划添加资源感知调度时,将无法考虑hostPath使用的资源
- 在底层主机上创建的文件或者目录只能由root写入,需要在特权容器中以root身份运行进程,或者修改主机上的文件权限以便写入hostpath卷
apiVersion: v1
kind: Pod #deploymentd的类型
metadata:
name: test-pod #创建pod,名字为testpod
spec:
containers: #容器
- image: busybox #容器使用的镜像
imagePullPolicy: IfNotPresent #镜像拉取策略
name: test-container #容器名称
command: ["/bin/sh", "-c", "sleep 6000s"] #让容器前台运行
volumeMounts: #挂载卷,把下面的volume的test-volume挂载过来
- name: test-volume
mountPath: /test01 #将test-volume这个卷挂载到/test01目录下
volumes: #申请卷,卷名为test-volume
- name: test-volume
hostPath:
path: /dataa
type: Directory
运行的效果:在master节点上创建pod之后,在master节点上更改hostPath路径下的文件数据或者创建文件,在node节点上访问这个路径可以看到更改和创建文件后的详细信息
4、Persistentvolume
- Persistent volume(PV)
是由管理员设置的存储,他是集群的一部分,就像节点是集群中的资源一样,PV也是集群中的资源,PV是Volume之类的卷插件,但是有独立于使用PV的pod生命周期,此API对象包含存储实现的细节,即NFS、ISCSI或特定于云供应商的存储系统 - PersistentvolumeClaim(PVC)
是用户存储的请求,它与Pod相似,Pod消耗节点资源,PVC消耗PV资源,Pod可以请求特定级别的资源(CPU和内存),声明可以请求特定的大小和访问模式(例如,可以以读/写一次,或者只读多次模式挂载)
解释了为什么当pod被删除时,数据不会丢失,就是因为进行了PVC持久化的保护存储
apiVersion: v1
kind: PersistentVolume #deploymentd的类型
metadata:
name: test-pv #创建pod,名字为testpod
spec:
capacity:
storage: 5Gi #容器
volumeMode: Filesystem #容器使用的镜像
accessModes: #设定访问控制
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle #设定回收策略
storageClassName: slow #存储的模式是分等级的,比如机械硬盘和ssd,这里要选择等级,从符合等级的存储中做选择
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp #选择挂载路径
server: 172.17.0.2 #挂到哪个服务器下
PV访问模式
注意:一个卷一次只能使用一种访问模式挂载,即使它支持很多访问模式,例如GCEPersistentDisk可以由单个节点作为ReadWriteOnce模式挂载,或由多个节点以ReadWriteMany模式挂载,但是不能同时挂载
回收策略+状态
实战化展示
- 1、创建storeageclass,具体解释见官网
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner #这里需要重点关注一下,使用provisioner可以实现动态的存储,由于展示的是本地磁盘空间,所以不使用动态存储no-provisioner
volumeBindingMode: WaitForFirstConsumer
- 2、创建本地磁盘pv
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-local
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage #指定storeageclass
local:
path: /data/k8s/localpv # vm10-0-10-202节点上的目录
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- vm10-0-10-202
- 3、创建pvc
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-local
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: local-storage #指定存储类
此时查看一下创建的情况
[root@vm10-0-10-202 test]# k get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-local Pending local-storage 5s
[root@vm10-0-10-202 test]# k get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-local 5Gi RWO Delete Available local-storage 9s
注意:此时PVC不会立马绑定到PV,其等待Pod被调度时才会绑定到PV上,当前PVC状态为Pending,实际上是因为
延迟绑定
。通过这个延迟绑定机制,原本实时发生的 PVC 和 PV 的绑定过程,就被延迟到了 Pod 第一次调度的时候在调度器中进行,从而保证了这个绑定结果不会影响 Pod 的正常调度。
- 4、创建pod
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: local-volume-test
name: local-volume-test
spec:
replicas: 1
selector:
matchLabels:
app: local-volume-test
template:
metadata:
labels:
app: local-volume-test
spec:
containers:
- image: busybox
name: local-volume-test
imagePullPolicy: IfNotPresent
command: [ "/bin/sh", "-c", "while true; do sleep 2; echo $(date) $(hostname)>> /mnt/test/test.log; done" ]
volumeMounts:
- name: local-data
mountPath: /mnt/test
volumes:
- name: local-data
persistentVolumeClaim:
claimName: pvc-local
再查看创建情况
[root@vm10-0-10-202 test]# k get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-local Bound pv-local 5Gi RWO local-storage 16m
[root@vm10-0-10-202 test]# k get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-local 5Gi RWO Delete Bound default/pvc-local local-storage 16m
[root@vm10-0-10-202 test]# k get pod
NAME READY STATUS RESTARTS AGE
local-volume-test-6f6cf47b79-j5g8h 0/1 ContainerCreating 0 26s
可以看到pv处于绑定状态,此外pvc也处于绑定状态
StatefulSet
持久化演示NFS
一旦PVC绑定了pv以后就可以实现数据的持久化存储,即使是pod被删除了,依旧会自动创建同名的pod(pod的ip可能会更改),并且pod中的数据依然和以前的数据一样,实现了数据的持久化保存。
如果真的像删除pod中的数据,可直接删除pv来进行数据的清除
kubectl delete -f yourPVname.yaml
kubectl delete pvc --all #删除了pvc相当是释放了pv,pv并没有删除
kubectl edit pv yourPVname#进入pv实例中,删除claimRef这部分,就可以完全的释放pv资源
总结
上面这张图可以非常好的诠释整个pv,pvc,statefulset的过程
- pv1-pv4申请了NFS存储资源
- pvc与pv进行绑定,控制着pv与pod中的资源存储的持久化
- statefulset管理着pvc