有什么好的网站推荐一下,58同城网站建设的不足,辽宁建设工程信息网官网首页,正规的手游代理平台#x1f482; 个人主页: Java程序鱼 #x1f4ac; 如果文章对你有帮助#xff0c;欢迎关注、点赞、收藏(一键三连)和订阅专栏
#x1f464; 微信号#xff1a;hzy1014211086#xff0c;想加入技术交流群的小伙伴可以加我好友#xff0c;群里会分享学习资料、学习方法… 个人主页: Java程序鱼 如果文章对你有帮助欢迎关注、点赞、收藏(一键三连)和订阅专栏 微信号hzy1014211086想加入技术交流群的小伙伴可以加我好友群里会分享学习资料、学习方法 存储卷的概念和类型
为了保证数据的持久性必须保证数据在外部存储在docker容器中为了实现数据的持久性存储在宿主机和容器内做映射可以保证在容器的生命周期结束数据依旧可以实现持久性存储。但是在k8s中由于pod分布在各个不同的节点之上并不能实现不同节点之间持久性数据的共享并且在节点故障时可能会导致数据的永久性丢失。为此k8s就引入了外部存储卷的功能。 k8s的存储卷类型
[rootk8s-master ~] kubectl explain pod.spec.volumes #查看k8s支持的存储类型
KIND: Pod
VERSION: v1常用分类 emptyDir临时目录:Pod删除数据也会被清除这种存储成为emptyDir用于数据的临时存储。 hostPath(宿主机目录映射): 本地的SAN(iSCSI,FC)、NAS(nfs,cifs,http)存储 分布式存储glusterfsrbdcephfs 云存储EBSAzure Disk
persistentVolumeClaim --PVC(存储卷创建申请) 当你需要创建一个存储卷时只需要进行申请对应的存储空间即可使用这就是PVC。其关联关系如图 上图解析在Pod上定义一个PVC该PVC要关联到当前名称空间的PVC资源该PVC只是一个申请PVC需要和PV进行关联。PV属于存储上的一部分存储空间。但是该方案存在的问题是我们无法知道用户是什么时候去创建Pod也不知道创建Pod时定义多大的PVC那么如何实现按需创建呢
不需要PV层把所有存储空间抽象出来这一个抽象层称为存储类当用户创建PVC需要用到PV时可以向存储类申请对应的存储空间存储类会按照需求创建对应的存储空间这就是PV的动态供给如图 那么PV的动态供给其重点是在存储类的定义其分类大概是对存储的性能进行分类的如图金存储类、银存储类、铜存储类等。
总结 k8s要使用存储卷需要2步
在pod定义volume并指明关联到哪个存储设备在容器使用volume mount进行挂载
emptyDir存储卷演示
一个emptyDir 第一次创建是在一个pod被指定到具体node的时候并且会一直存在在pod的生命周期当中正如它的名字一样它初始化是一个空的目录pod中的容器都可以读写这个目录这个目录可以被挂在到各个容器相同或者不相同的的路径下。当一个pod因为任何原因被移除的时候这些数据会被永久删除。注意一个容器崩溃了不会导致数据的丢失因为容器的崩溃并不移除pod.
emptyDir 磁盘的作用 1普通空间基于磁盘的数据存储 2作为从崩溃中恢复的备份点 3存储那些那些需要长久保存的数据例web服务中的数据
默认的emptyDir 磁盘会存储在主机所使用的媒介上可能是SSD或者网络硬盘这主要取决于你的环境。当然我们也可以将emptyDir.medium的值设置为Memory来告诉Kubernetes 来挂在一个基于内存的目录tmpfs因为 tmpfs速度会比硬盘块度了但是当主机重启的时候所有的数据都会丢失。
[rootk8s-master ~] kubectl explain pods.spec.volumes.emptyDir #查看emptyDir存储定义
[rootk8s-master ~] kubectl explain pods.spec.containers.volumeMounts #查看容器挂载方式
[rootk8s-master ~] cd mainfests mkdir volumes cd volumes
[rootk8s-master volumes] cp ../pod-demo.yaml ./
[rootk8s-master volumes] mv pod-demo.yaml pod-vol-demo.yaml
[rootk8s-master volumes] vim pod-vol-demo.yaml #创建emptyDir的清单
apiVersion: v1
kind: Pod
metadata:name: pod-demonamespace: defaultlabels:app: myapptier: frontendannotations:magedu.com/create-by:cluster admin
spec:containers:- name: myappimage: ikubernetes/myapp:v1imagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80volumeMounts: #在容器内定义挂载存储名称和挂载路径- name: htmlmountPath: /usr/share/nginx/html/- name: busyboximage: busybox:latestimagePullPolicy: IfNotPresentvolumeMounts:- name: htmlmountPath: /data/ #在容器内定义挂载存储名称和挂载路径command: [/bin/sh,-c,while true;do echo $(date) /data/index.html;sleep 2;done]volumes: #定义存储卷- name: html #定义存储卷名称 emptyDir: {} #定义存储卷类型
[rootk8s-master volumes] kubectl apply -f pod-vol-demo.yaml
pod/pod-vol-demo created
[rootk8s-master volumes] kubectl get pods
NAME READY STATUS RESTARTS AGE
pod-vol-demo 2/2 Running 0 27s
[rootk8s-master volumes] kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
......
pod-vol-demo 2/2 Running 0 16s 10.244.2.34 k8s-node02
......在上面我们定义了2个容器其中一个容器是输入日期到index.html中然后验证访问nginx的html是否可以获取日期。以验证两个容器之间挂载的emptyDir实现共享。如下访问验证:
[rootk8s-master volumes] curl 10.244.2.34 #访问验证
Tue Oct 9 03:56:53 UTC 2018
Tue Oct 9 03:56:55 UTC 2018
Tue Oct 9 03:56:57 UTC 2018
Tue Oct 9 03:56:59 UTC 2018
Tue Oct 9 03:57:01 UTC 2018
Tue Oct 9 03:57:03 UTC 2018
Tue Oct 9 03:57:05 UTC 2018
Tue Oct 9 03:57:07 UTC 2018
Tue Oct 9 03:57:09 UTC 2018
Tue Oct 9 03:57:11 UTC 2018
Tue Oct 9 03:57:13 UTC 2018
Tue Oct 9 03:57:15 UTC 2018hostPath存储卷演示
hostPath宿主机路径就是把pod所在的宿主机之上的脱离pod中的容器名称空间的之外的宿主机的文件系统的某一目录和pod建立关联关系在pod删除时存储数据不会丢失。
1查看hostPath存储类型定义
[rootk8s-master volumes] kubectl explain pods.spec.volumes.hostPath
KIND: Pod
VERSION: v1RESOURCE: hostPath ObjectDESCRIPTION:HostPath represents a pre-existing file or directory on the host machinethat is directly exposed to the container. This is generally used forsystem agents or other privileged things that are allowed to see the hostmachine. Most containers will NOT need this. More info:https://kubernetes.io/docs/concepts/storage/volumes#hostpathRepresents a host path mapped into a pod. Host path volumes do not supportownership management or SELinux relabeling.FIELDS:path string -required- #指定宿主机的路径Path of the directory on the host. If the path is a symlink, it will followthe link to the real path. More info:https://kubernetes.io/docs/concepts/storage/volumes#hostpathtype stringType for HostPath Volume Defaults to More info:https://kubernetes.io/docs/concepts/storage/volumes#hostpathtype
DirectoryOrCreate 宿主机上不存在创建此目录
Directory 必须存在挂载目录
FileOrCreate 宿主机上不存在挂载文件就创建
File 必须存在文件 2清单定义
[rootk8s-master volumes] vim pod-hostpath-vol.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-vol-hostpathnamespace: default
spec:containers:- name: myappimage: ikubernetes/myapp:v1volumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlhostPath:path: /data/pod/volume1type: DirectoryOrCreate3在node节点上创建挂载目录
[rootk8s-node01 ~] mkdir -p /data/pod/volume1
[rootk8s-node01 ~] vim /data/pod/volume1/index.html
node01.magedu.com
[rootk8s-node02 ~] mkdir -p /data/pod/volume1
[rootk8s-node02 ~] vim /data/pod/volume1/index.html
node02.magedu.com
[rootk8s-master volumes]# kubectl apply -f pod-hostpath-vol.yaml
pod/pod-vol-hostpath created4访问测试
[rootk8s-master volumes] kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
......
pod-vol-hostpath 1/1 Running 0 37s 10.244.2.35 k8s-node02
......
[rootk8s-master volumes] curl 10.244.2.35
node02.magedu.com
[rootk8s-master volumes]# kubectl delete -f pod-hostpath-vol.yaml #删除pod再重建验证是否依旧可以访问原来的内容
[rootk8s-master volumes] kubectl apply -f pod-hostpath-vol.yaml
pod/pod-vol-hostpath created
[rootk8s-master volumes] curl 10.244.2.37
node02.magedu.comhostPath可以实现持久存储但是在node节点故障时也会导致数据的丢失
nfs共享存储卷演示
nfs使的我们可以挂在已经存在的共享到的我们的Pod中和emptyDir不同的是emptyDir会被删除当我们的Pod被删除的时候但是nfs不会被删除仅仅是解除挂在状态而已这就意味着NFS能够允许我们提前对数据进行处理而且这些数据可以在Pod之间相互传递.并且nfs可以同时被多个pod挂在并进行读写。
注意必须先报纸NFS服务器正常运行在我们进行挂在nfs的时候
1在stor01节点上安装nfs并配置nfs服务
[rootstor01 ~] yum install -y nfs-utils 》192.168.56.14
[rootstor01 ~] mkdir /data/volumes -pv
[rootstor01 ~] vim /etc/exports
/data/volumes 192.168.56.0/24(rw,no_root_squash)
[rootstor01 ~] systemctl start nfs
[rootstor01 ~] showmount -e
Export list for stor01:
/data/volumes 192.168.56.0/242在node01和node02节点上安装nfs-utils并测试挂载
[rootk8s-node01 ~] yum install -y nfs-utils
[rootk8s-node02 ~] yum install -y nfs-utils
[rootk8s-node02 ~] mount -t nfs stor01:/data/volumes /mnt
[rootk8s-node02 ~] mount
......
stor01:/data/volumes on /mnt type nfs4 (rw,relatime,vers4.1,rsize131072,wsize131072,namlen255,hard,prototcp,port0,timeo600,retrans2,secsys,clientaddr192.168.56.13,local_locknone,addr192.168.56.14)
[rootk8s-node02 ~] umount /mnt/3创建nfs存储卷的使用清单
[rootk8s-master volumes] cp pod-hostpath-vol.yaml pod-nfs-vol.yaml
[rootk8s-master volumes] vim pod-nfs-vol.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-vol-nfsnamespace: default
spec:containers:- name: myappimage: ikubernetes/myapp:v1volumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlnfs:path: /data/volumesserver: stor01
[rootk8s-master volumes] kubectl apply -f pod-nfs-vol.yaml
pod/pod-vol-nfs created
[rootk8s-master volumes] kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
pod-vol-nfs 1/1 Running 0 21s 10.244.2.38 k8s-node023在nfs服务器上创建index.html
[rootstor01 ~] cd /data/volumes
[rootstor01 volumes ~] vim index.html
h1 nfs stor01/h1
[rootk8s-master volumes] curl 10.244.2.38
h1 nfs stor01/h1
[rootk8s-master volumes] kubectl delete -f pod-nfs-vol.yaml #删除nfs相关pod再重新创建可以得到数据的持久化存储
pod pod-vol-nfs deleted
[rootk8s-master volumes] kubectl apply -f pod-nfs-vol.yaml PVC和PV的概念
我们前面提到kubernetes提供那么多存储接口但是首先kubernetes的各个Node节点能管理这些存储但是各种存储参数也需要专业的存储工程师才能了解由此我们的kubernetes管理变的更加复杂的。由此kubernetes提出了PV和PVC的概念这样开发人员和使用者就不需要关注后端存储是什么使用什么参数等问题。如下图 PersistentVolumePV是集群中已由管理员配置的一段网络存储。 集群中的资源就像一个节点是一个集群资源。 PV是诸如卷之类的卷插件但是具有独立于使用PV的任何单个pod的生命周期。 该API对象捕获存储的实现细节即NFSiSCSI或云提供商特定的存储系统。 PersistentVolumeClaimPVC是用户存储的请求。PVC的使用逻辑在pod中定义一个存储卷该存储卷类型为PVC定义的时候直接指定大小pvc必须与对应的pv建立关系pvc会根据定义去pv申请而pv是由存储空间创建出来的。pv和pvc是kubernetes抽象出来的一种存储资源。
虽然PersistentVolumeClaims允许用户使用抽象存储资源但是常见的需求是用户需要根据不同的需求去创建PV用于不同的场景。而此时需要集群管理员提供不同需求的PV而不仅仅是PV的大小和访问模式但又不需要用户了解这些卷的实现细节。 对于这样的需求此时可以采用StorageClass资源。这个在前面就已经提到过此方案。
PV是集群中的资源。 PVC是对这些资源的请求也是对资源的索赔检查。 PV和PVC之间的相互作用遵循这个生命周期
Provisioning配置— Binding绑定—Using使用— Releasing释放 — Recycling回收
Provisioning
这里有两种PV的提供方式:静态或者动态
静态–直接固定存储空间 集群管理员创建一些 PV。它们携带可供集群用户使用的真实存储的详细信息。 它们存在于Kubernetes API中可用于消费。
动态–通过存储类进行动态创建存储空间 当管理员创建的静态 PV 都不匹配用户的 PVC 时集群可能会尝试动态地为 PVC 配置卷。此配置基于 StorageClassesPVC 必须请求存储类并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用动态配置。
Binding
在动态配置的情况下用户创建或已经创建了具有特定数量的存储请求和特定访问模式的PersistentVolumeClaim。 主机中的控制回路监视新的PVC找到匹配的PV如果可能并将 PVC 和 PV 绑定在一起。 如果为新的PVC动态配置PV则循环将始终将该PV绑定到PVC。 否则用户总是至少得到他们要求的内容但是卷可能超出了要求。 一旦绑定PersistentVolumeClaim绑定是排他的不管用于绑定它们的模式。
如果匹配的卷不存在PVC将保持无限期。 随着匹配卷变得可用PVC将被绑定。 例如提供许多50Gi PV的集群将不匹配要求100Gi的PVC。 当集群中添加100Gi PV时可以绑定PVC。
Using
Pod使用PVC作为卷。 集群检查声明以找到绑定的卷并挂载该卷的卷。 对于支持多种访问模式的卷用户在将其声明用作pod中的卷时指定所需的模式。
一旦用户有声明并且该声明被绑定绑定的PV属于用户只要他们需要它。 用户通过在其Pod的卷块中包含PersistentVolumeClaim来安排Pods并访问其声明的PV。
Releasing
当用户完成卷时他们可以从允许资源回收的API中删除PVC对象。 当声明被删除时卷被认为是“释放的”但是它还不能用于另一个声明。 以前的索赔人的数据仍然保留在必须根据政策处理的卷上.
Reclaiming
PersistentVolume的回收策略告诉集群在释放其声明后该卷应该如何处理。 目前卷可以是保留回收或删除。 保留可以手动回收资源。 对于那些支持它的卷插件删除将从Kubernetes中删除PersistentVolume对象以及删除外部基础架构如AWS EBSGCE PDAzure Disk或Cinder卷中关联的存储资产。 动态配置的卷始终被删除
Recycling
如果受适当的卷插件支持回收将对卷执行基本的擦除rm -rf / thevolume / *并使其再次可用于新的声明。
NFS使用PV和PVC
实验图如下 [rootk8s-master ~] kubectl explain pv #查看pv的定义方式
FIELDS:apiVersionkindmetadataspec
[rootk8s-master ~] kubectl explain pv.spec #查看pv定义的规格
spec:nfs定义存储类型path定义挂载卷路径server定义服务器名称accessModes定义访问模型有以下三种访问模型以列表的方式存在也就是说可以定义多个访问模式ReadWriteOnceRWO 单节点读写ReadOnlyManyROX 多节点只读ReadWriteManyRWX 多节点读写capacity定义PV空间的大小storage指定大小[rootk8s-master volumes] kubectl explain pvc #查看PVC的定义方式
KIND: PersistentVolumeClaim
VERSION: v1
FIELDS:apiVersion stringkind string metadata Objectspec Object
[rootk8s-master volumes] kubectl explain pvc.spec
spec:accessModes定义访问模式必须是PV的访问模式的子集resources定义申请资源的大小requests:storage: 配置nfs存储
[rootstor01 volumes] mkdir v{1,2,3,4,5}
[rootstor01 volumes] vim /etc/exports
/data/volumes/v1 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v2 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v3 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v4 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v5 192.168.56.0/24(rw,no_root_squash)
[rootstor01 volumes] exportfs -arv
exporting 192.168.56.0/24:/data/volumes/v5
exporting 192.168.56.0/24:/data/volumes/v4
exporting 192.168.56.0/24:/data/volumes/v3
exporting 192.168.56.0/24:/data/volumes/v2
exporting 192.168.56.0/24:/data/volumes/v1
[rootstor01 volumes] showmount -e
Export list for stor01:
/data/volumes/v5 192.168.56.0/24
/data/volumes/v4 192.168.56.0/24
/data/volumes/v3 192.168.56.0/24
/data/volumes/v2 192.168.56.0/24
/data/volumes/v1 192.168.56.0/24定义PV
这里定义5个PV并且定义挂载的路径以及访问模式还有PV划分的大小。
[rootk8s-master volumes] kubectl explain pv
[rootk8s-master volumes] kubectl explain pv.spec.nfs
[rootk8s-master volumes] vim pv-demo.yamlapiVersion: v1
kind: PersistentVolume
metadata:name: pv001labels:name: pv001
spec:nfs:path: /data/volumes/v1server: stor01accessModes: [ReadWriteMany,ReadWriteOnce]capacity:storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv002labels:name: pv002
spec:nfs:path: /data/volumes/v2server: stor01accessModes: [ReadWriteOnce]capacity:storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv003labels:name: pv003
spec:nfs:path: /data/volumes/v3server: stor01accessModes: [ReadWriteMany,ReadWriteOnce]capacity:storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv004labels:name: pv004
spec:nfs:path: /data/volumes/v4server: stor01accessModes: [ReadWriteMany,ReadWriteOnce]capacity:storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv005labels:name: pv005
spec:nfs:path: /data/volumes/v5server: stor01accessModes: [ReadWriteMany,ReadWriteOnce]capacity:storage: 5Gi[rootk8s-master volumes] kubectl apply -f pv-demo.yaml persistentvolume/pv001 created
persistentvolume/pv002 created
persistentvolume/pv003 created
persistentvolume/pv004 created
persistentvolume/pv005 created[rootk8s-master volumes] kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 1Gi RWO,RWX Retain Available 7s
pv002 2Gi RWO Retain Available 7s
pv003 2Gi RWO,RWX Retain Available 7s
pv004 4Gi RWO,RWX Retain Available 7s
pv005 5Gi RWO,RWX Retain Available 7s定义PVC
这里定义了pvc的访问模式为多路读写该访问模式必须在前面pv定义的访问模式之中。定义PVC申请的大小为2Gi此时PVC会自动去匹配多路读写且大小为2Gi的PV匹配成功获取PVC的状态即为Bound
[rootk8s-master volumes ~] vim pod-vol-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: mypvcnamespace: default
spec:accessModes: [ReadWriteMany]resources:requests:storage: 2Gi
---
apiVersion: v1
kind: Pod
metadata:name: pod-vol-pvcnamespace: default
spec:containers:- name: myappimage: ikubernetes/myapp:v1volumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlpersistentVolumeClaim:claimName: mypvc[rootk8s-master volumes] kubectl apply -f pod-vol-pvc.yaml
persistentvolumeclaim/mypvc created
pod/pod-vol-pvc created
[rootk8s-master volumes] kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 1Gi RWO,RWX Retain Available 19m
pv002 2Gi RWO Retain Available 19m
pv003 2Gi RWO,RWX Retain Bound default/mypvc 19m
pv004 4Gi RWO,RWX Retain Available 19m
pv005 5Gi RWO,RWX Retain Available 19m
[rootk8s-master volumes] kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Bound pv003 2Gi RWO,RWX 22s测试访问
在存储服务器上创建index.html并写入数据通过访问Pod进行查看可以获取到相应的页面。
[rootstor01 volumes] cd v3/
[rootstor01 v3]# echo welcome to use pv3 index.html
[rootk8s-master volumes] kubectl get pods -o wide
pod-vol-pvc 1/1 Running 0 3m 10.244.2.39 k8s-node02
[rootk8s-master volumes] curl 10.244.2.39
welcome to use pv3StorageClass
在pv和pvc使用过程中存在的问题在pvc申请存储空间时未必就有现成的pv符合pvc申请的需求上面nfs在做pvc可以成功的因素是因为我们做了指定的需求处理。那么当PVC申请的存储空间不一定有满足PVC要求的PV事又该如何处理呢为此Kubernetes为管理员提供了描述存储class类的方法StorageClass。举个例子在存储系统中划分一个1TB的存储空间提供给Kubernetes使用当用户需要一个10G的PVC时会立即通过restful发送请求从而让存储空间创建一个10G的image之后在我们的集群中定义成10G的PV供给给当前的PVC作为挂载使用。在此之前我们的存储系统必须支持restful接口比如ceph分布式存储而glusterfs则需要借助第三方接口完成这样的请求。如图 [rootk8s-master ~] kubectl explain storageclass #storageclass也是k8s上的资源
KIND: StorageClass
VERSION: storage.k8s.io/v1
FIELDS:allowVolumeExpansion boolean allowedTopologies []Object apiVersion string kind string metadata Object mountOptions []string #挂载选项parameters map[string]string #参数取决于分配器可以接受不同的参数。 例如参数 type 的值 io1 和参数 iopsPerGB 特定于 EBS PV。当参数被省略时会使用默认值。 provisioner string -required- #存储分配器用来决定使用哪个卷插件分配 PV。该字段必须指定。reclaimPolicy string #回收策略可以是 Delete 或者 Retain。如果 StorageClass 对象被创建时没有指定 reclaimPolicy 它将默认为 Delete。 volumeBindingMode string #卷的绑定模式StorageClass 中包含 provisioner、parameters 和 reclaimPolicy 字段当 class 需要动态分配 PersistentVolume 时会使用到。由于StorageClass需要一个独立的存储系统此处就不再演示。从其他资料查看定义StorageClass的方式如下
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:name: standard
provisioner: kubernetes.io/aws-ebs
parameters:type: gp2
reclaimPolicy: Retain
mountOptions:- debug配置容器应用
在日常单机甚至集群状态下我们需要对一个应用进行配置只需要修改其配置文件即可。那么在容器中又该如何提供配置 信息呢例如为Nginx配置一个指定的server_name或worker进程数为Tomcat的JVM配置其堆内存大小。传统的实践过程中通常有以下几种方式
启动容器时通过命令传递参数将定义好的配置文件通过镜像文件进行写入通过环境变量的方式传递配置数据挂载Docker卷传送配置文件
而在Kubernetes系统之中也存在这样的组件就是特殊的存储卷类型。其并不是提供pod存储空间而是给管理员或用户提供从集群外部向Pod内部的应用注入配置信息的方式。
这两种特殊类型的存储卷分别是configMap和secret
Secret用于向Pod传递敏感信息比如密码私钥证书文件等这些信息如果在容器中定义容易泄露Secret资源可以让用户将这些信息存储在急群众然后通过Pod进行挂载实现敏感数据和系统解耦的效果。ConfigMap主要用于向Pod注入非敏感数据使用时用户将数据直接存储在ConfigMap对象当中然后Pod通过使用ConfigMap卷进行引用实现容器的配置文件集中定义和管理。
[rootk8s-master volumes]# kubectl explain pods.spec.volumes
......configMap ObjectConfigMap represents a configMap that should populate this volumesecret ObjectSecret represents a secret that should populate this volume. More info:https://kubernetes.io/docs/concepts/storage/volumes#secretSecret解析
Secret对象存储数据的方式是以键值方式存储数据在Pod资源进行调用Secret的方式是通过环境变量或者存储卷的方式进行访问数据解决了密码、token、密钥等敏感数据的配置问题而不需要把这些敏感数据暴露到镜像或者Pod Spec中。另外Secret对象的数据存储和打印格式为Base64编码的字符串因此用户在创建Secret对象时也需要提供该类型的编码格式的数据。在容器中以环境变量或存储卷的方式访问时会自动解码为明文格式。需要注意的是如果是在Master节点上Secret对象以非加密的格式存储在etcd中所以需要对etcd的管理和权限进行严格控制。
Secret有4种类型
Service Account 用来访问Kubernetes API由Kubernetes自动创建并且会自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount目录中Opaque base64编码格式的Secret用来存储密码、密钥、信息、证书等类型标识符为generickubernetes.io/dockerconfigjson 用来存储私有docker registry的认证信息类型标识为docker-registry。kubernetes.io/tls用于为SSL通信模式存储证书和私钥文件命令式创建类型标识为tls。
创建 Secret的2种方式
命令式创建
通过 --from-literal
[rootk8s-master ~] kubectl create secret -h
Create a secret using specified subcommand.Available Commands:docker-registry Create a secret for use with a Docker registrygeneric Create a secret from a local file, directory or literal valuetls Create a TLS secretUsage:kubectl create secret [flags] [options]Use kubectl command --help for more information about a given command.
Use kubectl options for a list of global command-line options (applies to all commands).每个 --from-literal 对应一个信息条目。
[rootk8s-master ~] kubectl create secret generic mysecret --from-literalusernameadmin --from-literalpassword123456
secret/mysecret created
[rootk8s-master ~] kubectl get secret
NAME TYPE DATA AGE
mysecret Opaque 2 6s2通过 --from-file每个文件内容对应一个信息条目。
[rootk8s-master ~] echo -n admin ./username
[rootk8s-master ~] echo -n 123456 ./password
[rootk8s-master ~] kubectl create secret generic mysecret --from-file./username --from-file./password
secret/mysecret created
[rootk8s-master ~] kubectl get secret
NAME TYPE DATA AGE
mysecret Opaque 2 6s3通过 --from-env-file 文件 env.txt 中每行 KeyValue 对应一个信息条目。
[rootk8s-master ~] cat EOF env.txtusernameadminpassword123456EOF
[rootk8s-master ~]# kubectl create secret generic mysecret --from-env-fileenv.txt
secret/mysecret created
[rootk8s-master ~]# kubectl get secret
NAME TYPE DATA AGE
mysecret Opaque 2 10s清单式创建
通过 YAML 配置文件
#事先完成敏感数据的Base64编码
[rootk8s-master ~] echo -n admin |base64
YWRtaW4
[rootk8s-master ~] echo -n 123456 |base64
MTIzNDU2[rootk8s-master ~] vim secret.yaml
apiVersion: v1
kind: Secret
metadata:name: mysecret
data:username: YWRtaW4password: MTIzNDU2
[rootk8s-master ~] kubectl apply -f secret.yaml
secret/mysecret created
[rootk8s-master ~] kubectl get secret #查看存在的 secret显示有2条数据
NAME TYPE DATA AGE
mysecret Opaque 2 8s
[rootk8s-master ~] kubectl describe secret mysecret #查看数据的 Key
Name: mysecret
Namespace: default
Labels: none
Annotations:
Type: OpaqueDatausername: 5 bytes
password: 6 bytes
[rootk8s-master ~] kubectl edit secret mysecret #查看具体的value可以使用该命令
apiVersion: v1
data:password: MTIzNDU2username: YWRtaW4
kind: Secret
metadata:
......
[rootk8s-master ~] echo -n MTIzNDU2 |base64 --decode #通过 base64 将 Value 反编码
123456
[rootk8s-master ~] echo -n YWRtaW4 |base64 --decode
admin如何使用Secret
Pod 可以通过 Volume 或者环境变量的方式使用 Secret
[rootk8s-master volumes] vim pod-secret-demo.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-secret
spec:containers:- name: pod-secretimage: busyboxargs:- /bin/sh- -c- sleep 10;touch /tmp/healthy;sleep 30000volumeMounts: #将 foo mount 到容器路径 /etc/foo可指定读写权限为 readOnly。- name: foomountPath: /etc/fooreadOnly: truevolumes: #定义 volume foo来源为 secret mysecret。- name: foosecret:secretName: mysecret
[rootk8s-master volumes] kubectl apply -f pod-secret-demo.yaml
pod/pod-secret created
[rootk8s-master volumes] kubectl get pods
pod-secret 1/1 Running 0 1m
[rootk8s-master volumes] kubectl exec -it pod-secret sh
/ # ls /etc/foo/
password username
/ # cat /etc/foo/username
admin/ #
/ # cat /etc/foo/password
123456/ # 可以看到Kubernetes 会在指定的路径 /etc/foo 下为每条敏感数据创建一个文件文件名就是数据条目的 Key这里是 /etc/foo/username 和 /etc/foo/passwordValue 则以明文存放在文件中。
也可以自定义存放数据的文件名比如将配置文件改为
[rootk8s-master volumes] cat pod-secret-demo.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-secret
spec:containers:- name: pod-secretimage: busyboxargs:- /bin/sh- -c- sleep 10;touch /tmp/healthy;sleep 30000volumeMounts:- name: foomountPath: /etc/fooreadOnly: truevolumes:- name: foosecret:secretName: mysecretitems: #自定义存放数据的文件名- key: usernamepath: my-secret/my-username- key: passwordpath: my-secret/my-password
[rootk8s-master volumes] kubectl delete pods pod-secret
pod pod-secret deleted
[rootk8s-master volumes] kubectl apply -f pod-secret-demo.yaml
pod/pod-secret created
[rootk8s-master volumes] kubectl exec -it pod-secret sh
/ # cat /etc/foo/my-secret/my-username
admin
/ # cat /etc/foo/my-secret/my-password
123456这时数据将分别存放在 /etc/foo/my-secret/my-username 和 /etc/foo/my-secret/my-password 中。
以 Volume 方式使用的 Secret 支持动态更新Secret 更新后容器中的数据也会更新。
将 password 更新为 abcdefbase64 编码为 YWJjZGVm
[rootk8s-master ~] vim secret.yaml
apiVersion: v1
kind: Secret
metadata:name: mysecret
data:username: YWRtaW4password: YWJjZGVm
[rootk8s-master ~] kubectl apply -f secret.yaml
secret/mysecret configured
/ # cat /etc/foo/my-secret/my-password
abcdef通过 Volume 使用 Secret容器必须从文件读取数据会稍显麻烦Kubernetes 还支持通过环境变量使用 Secret。
[rootk8s-master volumes] cp pod-secret-demo.yaml pod-secret-env-demo.yaml
[rootk8s-master volumes] vim pod-secret-env-demo.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-secret-env
spec:containers:- name: pod-secret-envimage: busyboxargs:- /bin/sh- -c- sleep 10;touch /tmp/healthy;sleep 30000env:- name: SECRET_USERNAMEvalueFrom:secretKeyRef:name: mysecretkey: username- name: SECRET_PASSWORDvalueFrom:secretKeyRef:name: mysecretkey: password
[rootk8s-master volumes] kubectl apply -f pod-secret-env-demo.yaml
pod/pod-secret-env created[rootk8s-master volumes] kubectl exec -it pod-secret-env sh
/ # echo $SECRET_USERNAME
admin
/ # echo $SECRET_PASSWORD
abcdef通过环境变量 SECRET_USERNAME 和 SECRET_PASSWORD 成功读取到 Secret 的数据。
需要注意的是环境变量读取 Secret 很方便但无法支撑 Secret 动态更新。
Secret 可以为 Pod 提供密码、Token、私钥等敏感数据对于一些非敏感数据比如应用的配置信息则可以用 ConfigMap。
ConifgMap解析
configmap是让配置文件从镜像中解耦让镜像的可移植性和可复制性。许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。这些配置信息需要与docker image解耦你总不能每修改一个配置就重做一个image吧ConfigMap API给我们提供了向容器中注入配置信息的机制ConfigMap可以被用来保存单个属性也可以用来保存整个配置文件或者JSON二进制大对象。
ConfigMap API资源用来保存key-value pair配置数据这个数据可以在pods里使用或者被用来为像controller一样的系统组件存储配置数据。虽然ConfigMap跟Secrets类似但是ConfigMap更方便的处理不含敏感信息的字符串。 注意ConfigMaps不是属性配置文件的替代品。ConfigMaps只是作为多个properties文件的引用。可以把它理解为Linux系统中的/etc目录专门用来存储配置文件的目录。下面举个例子使用ConfigMap配置来创建Kuberntes VolumesConfigMap中的每个data项都会成为一个新文件。
[rootk8s-master volumes] kubectl explain cm
KIND: ConfigMap
VERSION: v1
FIELDS:apiVersion stringbinaryData map[string]stringdata map[string]stringkind stringmetadata ObjectConfigMap创建方式
与 Secret 一样ConfigMap 也支持四种创建方式
1通过 --from-literal每个 --from-literal 对应一个信息条目。 [rootk8s-master volumes] kubectl create configmap nginx-config --from-literalnginx_port80 --from-literalserver_namemyapp.magedu.com
configmap/nginx-config created
[rootk8s-master volumes] kubectl get cm
NAME DATA AGE
nginx-config 2 6s
[rootk8s-master volumes] kubectl describe cm nginx-config
Name: nginx-config
Namespace: default
Labels: none
Annotations: noneDataserver_name:
----
myapp.magedu.com
nginx_port:
----
80
Events: none2通过 --from-file每个文件内容对应一个信息条目。
[rootk8s-master mainfests] mkdir configmap cd configmap
[rootk8s-master configmap] vim www.conf
server {server_name myapp.magedu.com;listen 80;root /data/web/html;
}
[rootk8s-master configmap] kubectl create configmap nginx-www --from-file./www.conf
configmap/nginx-www created
[rootk8s-master configmap] kubectl get cm
NAME DATA AGE
nginx-config 2 3m
nginx-www 1 4s
[rootk8s-master configmap] kubectl get cm nginx-www -o yaml
apiVersion: v1
data:www.conf: server {\n\tserver_name myapp.magedu.com;\n\tlisten 80;\n\troot /data/web/html;\n}\n
kind: ConfigMap
metadata:creationTimestamp: 2018-10-10T08:50:06Zname: nginx-wwwnamespace: defaultresourceVersion: 389929selfLink: /api/v1/namespaces/default/configmaps/nginx-wwwuid: 7c3dfc35-cc69-11e8-801a-000c2972dc1f如何使用configMap
1环境变量方式注入到pod
[rootk8s-master configmap] vim pod-configmap.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-cm-1namespace: defaultlabels: app: myapptier: frontendannotations:magedu.com/created-by: cluster admin
spec:containers:- name: myappimage: ikubernetes/myapp:v1ports:- name: httpcontainerPort: 80 env:- name: NGINX_SERVER_PORTvalueFrom:configMapKeyRef:name: nginx-configkey: nginx_port- name: NGINX_SERVER_NAMEvalueFrom:configMapKeyRef:name: nginx-configkey: server_name
[rootk8s-master configmap] kubectl apply -f pod-configmap.yaml
pod/pod-cm-1 created
[rootk8s-master configmap] kubectl exec -it pod-cm-1 -- /bin/sh
/ # echo $NGINX_SERVER_PORT
80
/ # echo $NGINX_SERVER_NAME
myapp.magedu.com修改端口可以发现使用环境变化注入pod中的端口不会根据配置的更改而变化
[rootk8s-master volumes] kubectl edit cm nginx-config
configmap/nginx-config edited
/ # echo $NGINX_SERVER_PORT
802存储卷方式挂载configmapVolume 形式的 ConfigMap 也支持动态更新
[rootk8s-master configmap ~] vim pod-configmap-2.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-cm-2namespace: defaultlabels: app: myapptier: frontendannotations:magedu.com/created-by: cluster admin
spec:containers:- name: myappimage: ikubernetes/myapp:v1ports:- name: httpcontainerPort: 80 volumeMounts:- name: nginxconfmountPath: /etc/nginx/config.d/readOnly: truevolumes:- name: nginxconfconfigMap:name: nginx-config
[rootk8s-master configmap ~] kubectl apply -f pod-configmap-2.yaml
pod/pod-cm-2 created
[rootk8s-master configmap ~] kubectl get pods
[rootk8s-master configmap ~] kubectl exec -it pod-cm-2 -- /bin/sh
/ # cd /etc/nginx/config.d
/ # cat nginx_port
80
/ # cat server_name
myapp.magedu.com[rootk8s-master configmap ~] kubectl edit cm nginx-config #修改端口再在容器中查看端口是否变化。
apiVersion: v1
data:nginx_port: 800....../ # cat nginx_port
800
[rootk8s-master configmap ~] kubectl delete -f pod-configmap2.yaml3以nginx-www配置nginx [rootk8s-master configmap ~] vim pod-configmap3.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-cm-3namespace: defaultlabels: app: myapptier: frontendannotations:magedu.com/created-by: cluster admin
spec:containers:- name: myappimage: ikubernetes/myapp:v1ports:- name: httpcontainerPort: 80 volumeMounts:- name: nginxconfmountPath: /etc/nginx/conf.d/readOnly: truevolumes:- name: nginxconfconfigMap:name: nginx-www
[rootk8s-master configmap ~] kubectl apply -f pod-configmap3.yaml
pod/pod-cm-3 created
[rootk8s-master configmap ~] kubectl get pods
[rootk8s-master configmap] kubectl exec -it pod-cm-3 -- /bin/sh
/ # cd /etc/nginx/conf.d/
/etc/nginx/conf.d # ls
www.conf
/etc/nginx/conf.d # cat www.conf
server {server_name myapp.magedu.com;listen 80;root /data/web/html;
}
apiVersion: v1
data:nginx_port: 800....../ # cat nginx_port
800
[rootk8s-master configmap ~] kubectl delete -f pod-configmap2.yaml3以nginx-www配置nginx [rootk8s-master configmap ~] vim pod-configmap3.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-cm-3namespace: defaultlabels: app: myapptier: frontendannotations:magedu.com/created-by: cluster admin
spec:containers:- name: myappimage: ikubernetes/myapp:v1ports:- name: httpcontainerPort: 80 volumeMounts:- name: nginxconfmountPath: /etc/nginx/conf.d/readOnly: truevolumes:- name: nginxconfconfigMap:name: nginx-www
[rootk8s-master configmap ~] kubectl apply -f pod-configmap3.yaml
pod/pod-cm-3 created
[rootk8s-master configmap ~] kubectl get pods
[rootk8s-master configmap] kubectl exec -it pod-cm-3 -- /bin/sh
/ # cd /etc/nginx/conf.d/
/etc/nginx/conf.d # ls
www.conf
/etc/nginx/conf.d # cat www.conf
server {server_name myapp.magedu.com;listen 80;root /data/web/html;
}
文章转载自: http://www.morning.xzkgp.cn.gov.cn.xzkgp.cn http://www.morning.tbhf.cn.gov.cn.tbhf.cn http://www.morning.jrgxx.cn.gov.cn.jrgxx.cn http://www.morning.fpngg.cn.gov.cn.fpngg.cn http://www.morning.dhmll.cn.gov.cn.dhmll.cn http://www.morning.yysqz.cn.gov.cn.yysqz.cn http://www.morning.zbkwj.cn.gov.cn.zbkwj.cn http://www.morning.mtjwp.cn.gov.cn.mtjwp.cn http://www.morning.yjdql.cn.gov.cn.yjdql.cn http://www.morning.ckwrn.cn.gov.cn.ckwrn.cn http://www.morning.tbksk.cn.gov.cn.tbksk.cn http://www.morning.wdhlc.cn.gov.cn.wdhlc.cn http://www.morning.fjshyc.com.gov.cn.fjshyc.com http://www.morning.qpsxz.cn.gov.cn.qpsxz.cn http://www.morning.znqmh.cn.gov.cn.znqmh.cn http://www.morning.jbxd.cn.gov.cn.jbxd.cn http://www.morning.thjqk.cn.gov.cn.thjqk.cn http://www.morning.wkpfm.cn.gov.cn.wkpfm.cn http://www.morning.rkgyx.cn.gov.cn.rkgyx.cn http://www.morning.w58hje.cn.gov.cn.w58hje.cn http://www.morning.hqnsf.cn.gov.cn.hqnsf.cn http://www.morning.bxhch.cn.gov.cn.bxhch.cn http://www.morning.pwlxy.cn.gov.cn.pwlxy.cn http://www.morning.xsgxp.cn.gov.cn.xsgxp.cn http://www.morning.fkdts.cn.gov.cn.fkdts.cn http://www.morning.c-ae.cn.gov.cn.c-ae.cn http://www.morning.zcsyz.cn.gov.cn.zcsyz.cn http://www.morning.attorneysportorange.com.gov.cn.attorneysportorange.com http://www.morning.dpgdj.cn.gov.cn.dpgdj.cn http://www.morning.qrcsb.cn.gov.cn.qrcsb.cn http://www.morning.fpkpz.cn.gov.cn.fpkpz.cn http://www.morning.dhrbj.cn.gov.cn.dhrbj.cn http://www.morning.rgrz.cn.gov.cn.rgrz.cn http://www.morning.gnjkn.cn.gov.cn.gnjkn.cn http://www.morning.wlqbr.cn.gov.cn.wlqbr.cn http://www.morning.pqypt.cn.gov.cn.pqypt.cn http://www.morning.tslwz.cn.gov.cn.tslwz.cn http://www.morning.xrrjb.cn.gov.cn.xrrjb.cn http://www.morning.0small.cn.gov.cn.0small.cn http://www.morning.zwckz.cn.gov.cn.zwckz.cn http://www.morning.hrjrt.cn.gov.cn.hrjrt.cn http://www.morning.fcqlt.cn.gov.cn.fcqlt.cn http://www.morning.rjljb.cn.gov.cn.rjljb.cn http://www.morning.jypqx.cn.gov.cn.jypqx.cn http://www.morning.htbsk.cn.gov.cn.htbsk.cn http://www.morning.qynpw.cn.gov.cn.qynpw.cn http://www.morning.mtsck.cn.gov.cn.mtsck.cn http://www.morning.qzmnr.cn.gov.cn.qzmnr.cn http://www.morning.gyfwy.cn.gov.cn.gyfwy.cn http://www.morning.qkrgk.cn.gov.cn.qkrgk.cn http://www.morning.fylqz.cn.gov.cn.fylqz.cn http://www.morning.lnbyk.cn.gov.cn.lnbyk.cn http://www.morning.dmtwz.cn.gov.cn.dmtwz.cn http://www.morning.ytrbq.cn.gov.cn.ytrbq.cn http://www.morning.xqmd.cn.gov.cn.xqmd.cn http://www.morning.kqblk.cn.gov.cn.kqblk.cn http://www.morning.yxbrn.cn.gov.cn.yxbrn.cn http://www.morning.tymnr.cn.gov.cn.tymnr.cn http://www.morning.lqzhj.cn.gov.cn.lqzhj.cn http://www.morning.dlwzm.cn.gov.cn.dlwzm.cn http://www.morning.smfbw.cn.gov.cn.smfbw.cn http://www.morning.hdrrk.cn.gov.cn.hdrrk.cn http://www.morning.fqhbt.cn.gov.cn.fqhbt.cn http://www.morning.ktlfb.cn.gov.cn.ktlfb.cn http://www.morning.qgfy.cn.gov.cn.qgfy.cn http://www.morning.jzmqk.cn.gov.cn.jzmqk.cn http://www.morning.lhhkp.cn.gov.cn.lhhkp.cn http://www.morning.yrflh.cn.gov.cn.yrflh.cn http://www.morning.zrmxp.cn.gov.cn.zrmxp.cn http://www.morning.dpruuode.cn.gov.cn.dpruuode.cn http://www.morning.lgxzj.cn.gov.cn.lgxzj.cn http://www.morning.hkng.cn.gov.cn.hkng.cn http://www.morning.mdtfh.cn.gov.cn.mdtfh.cn http://www.morning.trzmb.cn.gov.cn.trzmb.cn http://www.morning.rcfwr.cn.gov.cn.rcfwr.cn http://www.morning.mhnrx.cn.gov.cn.mhnrx.cn http://www.morning.xjqrn.cn.gov.cn.xjqrn.cn http://www.morning.xnqwk.cn.gov.cn.xnqwk.cn http://www.morning.pgcmz.cn.gov.cn.pgcmz.cn http://www.morning.zhishizf.cn.gov.cn.zhishizf.cn