八、Kubernetes资源对象之数据卷存储
Pod本身有生命周期,其应用容器及生成的数据自身均无法独立于该生命周期之外持久存在,并且同一Pod中的容器可共享PID、Network、IPC和UTS名称空间,但Mount和USER名称空间却各自独立,因而跨容器的进程彼此间默认无法基于共享的存储空间交换文件或数据。因而,借助特定的存储机制甚至是独立于Pod生命周期的存储设备完成数据持久化也是必然之需。
1、储存卷的概述
每个工作节点基于本地内存或目录向Pod提供存储空间,也能够使用借助驱动程序挂载的网络文件系统或附加的块设备,例如使用挂载至本地某路径上的NFS文件系统等。Kubernetes系统具体支持的存储卷类型要取决于存储卷插件的内置定义,如图所示,不过Kubernetes也支持管理员基于扩展接口配置使用第三方存储。另外,Kubernetes甚至还支持一些有着特殊功用的存储卷,例如将外部信息投射至Pod之中的ConfigMap、Secret和Downward API等。
1)临时存储卷:emptyDir。
2)本地存储卷:hostPath和local。
▪云存储——awsElasticBlockStore、gcePersistentDisk、azureDisk和azureFile。
▪网络文件系统——NFS、GlusterFS、CephFS和Cinder。
▪网络块设备——iscsi、FC、RBD和vSphereVolume。
▪网络存储平台——Quobyte、PortworxVolume、StorageOS和ScaleIO。
2、配置Pod存储卷
spec: volumes: - name: <string> #存数卷名称,仅可使用DNS标签格式的字符,在当前Pod中必须唯一 VOL_TYPE <Object> #存储卷插件及具体的目标存储系统的相关配置 containers: - name: ... image: ... volumeMount: - name: <string> #要挂载的存储卷的名称,必须匹配存储卷列表中某项的定义 mountPath: <string> #容器文件系统跟上的挂载点路劲 readOnly: <boolean> #是否挂载为只读模式,默认为"否" subPath: <string> #挂载存储卷上的一个子目录至指定的挂载点 subPathExpr: <string> #挂载由指定模式匹配到的存储卷的文件或目录至挂载点 mountPropagation: <string> #挂载卷的传播模式
▪None:该挂载卷不支持传播机制,当前容器不向其他容器或Pod传播自己的挂载操作,也不会感知主机后续在该挂载卷或其任何子目录上执行的挂载变动;此为默认值。
▪HostToContainer:主机向容器的单向传播,即当前容器能感知主机后续对该挂载卷或其任何子目录上执行的挂载变动。
▪Bidirectional:主机和容器间的双向传播,当前容器创建的存储卷挂载操作会传播给主机及使用了同一存储卷的所有Pod的所有容器,也能感知主机上后续对该挂载卷或其任何子目录上执行的挂载变动;该行为存在破坏主机操作系统的危险,因而仅可用于特权模式下的容器中。
除了配置参数的不同,各类型存储卷的大体使用格式基本相似。
emptyDir存储卷的生命周期与其所属的Pod对象相同,它无法脱离Pod对象的生命周期提供数据存储功能,因此通常仅用于数据缓存或临时存储。不过,基于emptyDir构建的gitRepo存储卷可以在Pod对象的生命周期起始时,从相应的Git仓库中克隆相应的数据文件到底层的emptyDir中,也就使得它具有了一定意义上的持久性。
1、emptyDir存储卷
emptyDir存储卷可以理解为Pod对象上的一个临时目录,类似于Docker上的“Docker挂载卷”,在Pod对象启动时即被创建,而在Pod对象被移除时一并被删除。因此,emptyDir存储卷只能用于某些特殊场景中,例如同一Pod内的多个容器间的文件共享,或作为容器数据的临时存储目录用于数据缓存系统等。 emptyDir存储卷嵌套定义在.spec.volumes.emptyDir字段中,可用字段主要有两个。
▪medium:此目录所在的存储介质的类型,可用值为default或Memory,默认为default,表示使用节点的默认存储介质;Memory表示使用基于RAM的临时文件系统tmpfs,总体可用空间受限于内存,但性能非常好,通常用于为容器中的应用提供缓存存储。
▪sizeLimit:当前存储卷的空间限额,默认值为nil,表示不限制;不过,在medium字段值为Memory时,建议务必定义此限额。
下面是一个使用了emptyDir存储卷的简单示例,它保存在volumes-emptydir-demo.yaml配置文件中。
apiVersion: v1 kind: Pod metadata: name: volumes-emptydir-demo namespace: default spec: initContainers: - name: config-file-downloader #image: ikubernetes/admin-box image: harbor.ywx.net/k8s-baseimages/admin-box imagePullPolicy: IfNotPresent command: ['/bin/sh','-c','wget -O /data/envoy.yaml http://ilinux.io/envoy.yaml'] volumeMounts: - name: config-file-store1 mountPath: /data containers: - name: envoy #image: envoyproxy/envoy-alpine:v1.14.1 image: harbor.ywx.net/k8s-baseimages/envoy-alpine:v1.14.1 imagePullPolicy: IfNotPresent command: ['/bin/sh','-c'] args: ['envoy -c /etc/envoy/envoy.yaml'] volumeMounts: - name: config-file-store mountPath: /etc/envoy readOnly: true - name: config-file-store2 mountPath: /app/data volumes: #定义config-file-store1使用内存作为存储 - name: config-file-store emptyDir: medium: Memory sizeLimit: 16Mi #定义config-file-store2使用本地节点作为存储 - name: config-file-store2 emptyDir: {}
在该示例清单中,为Pod对象定义了一个名为config-file-store的、基于emptyDir存储插件的存储卷。初始化容器将该存储卷挂载至/data目录后,下载envoy.yaml配置文件并保存于该挂载点目录下。主容器将该存储卷挂载至/etc/envoy目录,再通过自定义命令让容器应用在启动时加载的配置文件/etc/envoy/envoy.yaml上,如图所示。
Pod资源的详细信息中会显示存储卷的相关状态,包括其是否创建成功(Events字段中输出)、相关的类型及参数(Volumes字段中输出),以及容器中的挂载状态等信息(Containers字段中输出)。如下面的命令结果所示。
root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl apply -f volumes-emptydir-demo.yaml pod/volumes-emptydir-demo created root@k8s-master01:~# kubectl describe pod volumes-emptydir-demo Name: volumes-emptydir-demo Namespace: default Priority: 0 Node: 172.168.33.211/172.168.33.211 Start Time: Sun, 03 Oct 2021 15:20:24 +0800 Labels: <none> Annotations: <none> Status: Running IP: 172.20.58.214 IPs: IP: 172.20.58.214 #Init Containers执行的下载文件任务 Init Containers: config-file-downloader: Container ID: docker://faab615972f8b62758ea37e2d8c52f58362297eb695843664401c591348a05f8 Image: harbor.ywx.net/k8s-baseimages/admin-box Image ID: docker-pullable://harbor.ywx.net/k8s-baseimages/admin-box@sha256:56e2413d2bcc279c6667d36fa7dfc7202062a933d0f69cd8a1769b68e2155bbf Port: <none> Host Port: <none> #init containers下载envoy.yaml文件并存放在/data中 Command: /bin/sh -c wget -O /data/envoy.yaml http://ilinux.io/envoy.yaml State: Terminated Reason: Completed Exit Code: 0 Started: Sun, 03 Oct 2021 15:20:24 +0800 Finished: Sun, 03 Oct 2021 15:20:25 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: #把config-file-store目录挂载init containers的/data目录中用于保存下载的envoy.yaml文件 #envoy.yaml文件实际是存放在config-file-store目录中,便于主容器到config-file-store中调用envoy.yaml文件 /data from config-file-store (rw) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-d2zdv (ro) #主容器 Containers: envoy: Container ID: docker://572830ca035b817229d690ff3fe778da0110846a559a140cd47dc37a27f8c98a Image: harbor.ywx.net/k8s-baseimages/envoy-alpine:v1.14.1 Image ID: docker-pullable://harbor.ywx.net/k8s-baseimages/envoy-alpine@sha256:3a7001058482f86ad4069017d96435a80540f4a0534b8dbb045f1870b7e2eab6 Port: <none> Host Port: <none> Command: /bin/sh -c Args: envoy -c /etc/envoy/envoy.yaml State: Running Started: Sun, 03 Oct 2021 15:20:26 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: #把config-file-store2目录挂载到主容器的/app/data目录 /app/data from config-file-store2 (rw) #读取/etc/envoy文件,该文件是init containers时下载到config-file-store目录 /etc/envoy from config-file-store (ro) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-d2zdv (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: config-file-store: Type: EmptyDir (a temporary directory that shares a pod's lifetime) Medium: Memory SizeLimit: 16Mi config-file-store2: Type: EmptyDir (a temporary directory that shares a pod's lifetime) Medium: SizeLimit: <unset> kube-api-access-d2zdv: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 21s default-scheduler Successfully assigned default/volumes-emptydir-demo to 172.168.33.211 Normal Pulled 21s kubelet Container image "harbor.ywx.net/k8s-baseimages/admin-box" already present on machine Normal Created 21s kubelet Created container config-file-downloader Normal Started 21s kubelet Started container config-file-downloader Normal Pulled 20s kubelet Container image "harbor.ywx.net/k8s-baseimages/envoy-alpine:v1.14.1" already present on machine Normal Created 20s kubelet Created container envoy Normal Started 19s kubelet Started container envoy
为Envoy下载的配置文件中定义了一个监听所有可用IP地址上TCP 80端口的Ingress侦听器,以及一个监听所有可用IP地址上TCP的9901端口的Admin接口,这与Envoy镜像中默认配置文件中的定义均有不同。下面命令的结果显示它吻合自定义配置文件的内容。
root@k8s-master01:~# kubectl exec volumes-emptydir-demo -- netstat -tnl Defaulted container "envoy" out of: envoy, config-file-downloader (init) Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:9901 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN root@k8s-master01:~# podIP=$(kubectl get pods volumes-emptydir-demo -o jsonpath={.status.podIP}) root@k8s-master01:~# curl $podIP:9901/listeners listener_0::0.0.0.0:80
另外还直接在挂载了一个config-file-store2在主容器的/app/data中
root@k8s-master01:~# kubectl exec -it volumes-emptydir-demo -- /bin/sh Defaulted container "envoy" out of: envoy, config-file-downloader (init) / # echo 123 > /app/data/ywx.log / # ls /app/data/ywx.log /app/data/ywx.log / # root@k8s-master01:~# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES volumes-emptydir-demo 1/1 Running 0 15m 172.20.58.214 172.168.33.211 <none> <none> #在k8s-node02的宿主机上查找 root@k8s-node02:~# find /var/lib/kubelet/pods -name ywx.log /var/lib/kubelet/pods/2d7ac625-f69d-464b-9eb0-e1a23eba5ec1/volumes/kubernetes.io~empty-dir/config-file-store2/ywx.log root@k8s-node02:~# cat /var/lib/kubelet/pods/2d7ac625-f69d-464b-9eb0-e1a23eba5ec1/volumes/kubernetes.io~empty-dir/config-file-store2/ywx.log 123 #为了更好的验证,我们宿主机中创建一个kaka.log,在去容器中查看 root@k8s-node02:~# echo 456 >> /var/lib/kubelet/pods/2d7ac625-f69d-464b-9eb0-e1a23eba5ec1/volumes/kubernetes.io~empty-dir/config-file-store2/kaka.log #在容器中查看 root@k8s-master01:~# kubectl exec -it volumes-emptydir-demo -- ls /apps/data Defaulted container "envoy" out of: envoy, config-file-downloader (init) ls: /apps/data: No such file or directory command terminated with exit code 1 root@k8s-master01:~# kubectl exec -it volumes-emptydir-demo -- /bin/sh Defaulted container "envoy" out of: envoy, config-file-downloader (init) / # ls /app/data/ kaka.log ywx.log / # cat /app/data/kaka.log 456 / #
emptyDir卷简单易用,但仅能用于临时存储。如果Pod被删除,emptyDir卷会被一起删除,数据会丢失。
root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl delete -f volumes-emptydir-demo.yaml pod "volumes-emptydir-demo" deleted #在k8s-node02上确认 root@k8s-node02:~# find /var/lib/kubelet/pods -name ywx.log root@k8s-node02:~#
2、gitRepo存储卷
repository <string>:Git仓库的URL,必选字段。 ▪directory <string>:目标目录名称,但名称中不能包含“..”字符;“.”表示将仓库中的数据直接克隆至存储卷映射的目录中,其他字符则表示将数据克隆至存储卷上以用户指定的字符串为名称的子目录中。 ▪revision <string>:特定revision的提交哈希码。
使用gitRepo存储卷的Pod资源运行的工作节点上必须安装有Git程序,否则克隆仓库的操作将无法完成。
apiVersion: v1 kind: Pod metadata: name: volumes-gitrepo-demo namespace: default spec: containers: - name: nginx image: nginx:1.16.0 imagePullPolicy: IfNotPresent volumeMounts: - name: nginx-html mountPath: /usr/share/nginx/html volumes: - name: nginx-html gitRepo: repository: https://github.com/iKubernetes/Kubernetes_Advanced_Practical_2rd.git directory: . revision: "master" #注意:nginx:1.16.0镜像中需要安装git命令
三、hostPath存储卷
hostPath存储卷插件是将工作节点上某文件系统的目录或文件关联到Pod上的一种存储卷类型,其数据具有同工作节点生命周期一样的持久性。hostPath存储卷使用的是工作节点本地的存储空间,所以仅适用于特定情况下的存储卷使用需求,例如将工作节点上的文件系统关联为Pod的存储卷,从而让容器访问节点文件系统上的数据,或者排布分布式存储系统的存储设备等。hostPath存储卷在运行有管理任务的系统级Pod资源,以及Pod资源需要访问节点上的文件时尤为有用。 配置hostPath存储卷的嵌套字段有两个:一个用于指定工作节点上的目录路径的必选字段path;另一个用于指定节点之上存储类型的type。hostPath支持使用的节点存储类型有如下几种。
▪DirectoryOrCreate:指定的路径不存在时,自动将其创建为0755权限的空目录,属主和属组均为kubelet。 ▪Directory:事先必须存在的目录路径。 ▪FileOrCreate:指定的路径不存在时,自动将其创建为0644权限的空文件,属主和属组均为kubelet。 ▪File:事先必须存在的文件路径。 ▪Socket:事先必须存在的Socket文件路径。 ▪CharDevice:事先必须存在的字符设备文件路径。 ▪BlockDevice:事先必须存在的块设备文件路径。 ▪"":空字符串,默认配置,在关联hostPath存储卷之前不进行任何检查。
下面是定义在配置清单volumes-hostpath-demo.yaml中的Pod对象,容器中的filebeat进程负责收集工作节点及容器相关的日志信息并发往Redis服务器,它使用了3个hostPath类型的存储卷,第一个指向了宿主机的日志文件目录/var/logs,后面两个则与宿主机上的Docker运行时环境有关。
apiVersion: v1 kind: Pod metadata: name: vol-hostpath-pod namespace: default spec: containers: - name: filebeat image: ikubernetes/filebeat:5.6.7-alpine imagePullPolicy: IfNotPresent env: - name: REDIS_HOST value: redis.ilinux.io:6379 - name: LOG_LEVEL value: info volumeMounts: - name: varlog mountPath: /var/log - name: socket mountPath: /var/run/docker.sock - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers - name: socket hostPath: path: /var/run/docker.sock
上面配置清单中Pod对象的正确运行要依赖于REDIS_HOST和LOG_LEVEL环境变量,它们分别用于定义日志缓冲队列服务和日志级别。如果有可用的Redis服务器,我们就可通过环境变量REDIS_HOST将其对应的主机名或IP地址传递给Pod对象,待Pod对象准备好之后即可通过Redis服务器查看到由该Pod发送的日志信息。测试时,我们仅需要给REDIS_HOST环境变量传递一个任意值(例如清单中的redis.ilinux.io)便可直接创建Pod对象,只不过该Pod中容器的日志会报出无法解析指定主机名的错误,但这并不影响存储卷的配置和使用。
提示
在Filebeat的应用架构中,这些日志信息可能会由Logstash收集后发往集中式日志存储系统Elasticsearch,并通过Kibana进行展示。
一个简单的hostpath案例vol-hostpath-html.yaml
apiVersion: v1 kind: Pod metadata: name: vol-hostpath-html namespace: default spec: containers: - name: nginx image: nginx:1.16.0 imagePullPolicy: IfNotPresent volumeMounts: - name: vol-html mountPath: /usr/share/nginx/html volumes: - name: vol-html hostPath: path: /data/html
执行清单
root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl apply -f vol-hostpath-html.yaml pod/vol-hostpath-html created root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES vol-hostpath-html 1/1 Running 0 38s 172.20.58.215 172.168.33.211 <none> <none> #在pod在k8s-node02上创建,在k8s-node02的/data/html目录创建一个index.html文件 root@k8s-node02:~# echo vol-hostpaht-html > /data/html/index.html #访问pod root@k8s-master01:/apps/k8s-yaml/volume-case# curl 172.20.58.215 vol-hostpaht-html
四、网络存储卷
1、NFS存储卷
NFS即网络文件系统(Network File System),它是一种分布式文件系统协议,最初是由Sun Microsystems公司开发的类UNIX操作系统之上的经典网络存储方案,其功能旨在允许客户端主机可以像访问本地存储一样通过网络访问服务器端文件。作为一种由内核原生支持的网络文件系统,具有Linux系统使用经验的读者多数都应该有NFS使用经验。 Kubernetes的NFS存储卷用于关联某事先存在的NFS服务器上导出的存储空间到Pod对象中以供容器使用,该类型的存储卷在Pod对象终止后仅是被卸载而非被删除。而且,NFS是文件系统级共享服务,它支持同时存在的多路挂载请求,可由多个Pod对象同时关联使用。定义NFS存储卷时支持嵌套使用以下几个字段。
server <string>:NFS服务器的IP地址或主机名,必选字段。 ▪path <string>:NFS服务器导出(共享)的文件系统路径,必选字段。 ▪readOnly <boolean>:是否以只读方式挂载,默认为false。
下面的配置清单示例中以Redis为例来说明NFS存储卷的功能与用法。Redis是一个著名的高性能键值存储系统,应用非常广泛。它基于内存存储运行,数据持久化存储的需求通过周期性地将数据同步到主机磁盘之上完成,因此将Redis抽象为Pod对象部署运行于Kubernetes系统之上时,需要考虑节点级或网络级的持久化存储卷的支持,本示例就是以NFS存储卷为例,为Redis进程提供跨Pod对象生命周期的数据持久化功能。
apiVersion: v1 kind: Pod metadata: name: volume-nfs-demo labels: app: redis spec: containers: - name: redis image: redis:alpine imagePullPolicy: IfNotPresent ports: - containerPort: 6379 name: redisport securityContext: runAsUser: 1000 volumeMounts: - mountPath: /data name: redisdata volumes: - name: redisdata nfs: #NFS存储卷插件 server: 172.168.33.201 #nfs服务器的地址 path: /data/redis_data #nfs共享目录 readOnly: false #是否以只读方式挂载,默认为false。
上面的示例定义在名为volumes-nfs-demo.yaml资源清单文件中,容器镜像文件redis:alpine默认会以redis用户(UID是1000)运行redis-server进程,并将数据持久保存在容器文件系统上的/data目录中,因而需要确保UID为1000的用户有权限读写该目录。与此对应,NFS服务器上用于该Pod对象的存储卷的导出目录(本示例中为/data/redis目录)也需要确保让UID为1000的用户拥有读写权限,因而需要在172.168.33.201服务器上创建该用户,将该用户设置为/data/redis目录的属主,或通过facl设置该用户拥有读写权限。
1)安装NFS Server程序包,Ubuntu 20.04上的程序包名为nfs-kernel-server ~#apt install nfs-kernel-server 2)设定基础环境,包括用户、数据目录及相应授权。 ~# mkdir /data/redis_data ~# groupadd -r -g 1000 redis && useradd -r -m -s /bin/bash -u 1000 -g 1000 redis ~# chown redis.redis /data/redis_data 3)编辑/etc/exports配置文件,填入类似如下内容: /data/redis_data *(rw,no_root_squash) 4)启动NFS服务器: ~# systemctl start nfs-server 5)在各工作节点安装NFS服务客户端程序包,ubuntu20.04上的程序包名为nfs-common。 ~# apt install -y nfs-common
待上述步骤执行完成后,切换回Kubernetes集群可运行kubectl命令的主机之上,运行命令创建配置清单中的Pod对象:
root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl apply -f volume-nfs-demo.yaml pod/volume-nfs-demo created
资源创建完成后,可通过其命令客户端redis-cli创建测试数据,并手动触发其与存储系统同步,下面为要执行的Redis命令。
root@k8s-master01:~# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES volume-nfs-demo 1/1 Running 0 4m13s 172.20.135.175 172.168.33.212 <none> <none> [root@k8s-master01:~# kubectl exec -it volume-nfs-demo -- redis-cli 127.0.0.1:6379> set key1 "hello world" OK 127.0.0.1:6379> get key1 "hello world" 127.0.0.1:6379> BGSAVE Background saving started 127.0.0.1:6379> exit root@k8s-master01:~#
为了测试其数据持久化效果,下面先删除此前创建的Pod对象volume-nfs-demo.yaml ,而后待重建该Pod对象后检测数据是否依然能够访问。
root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl delete -f volume-nfs-demo.yaml pod "volume-nfs-demo" deleted root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl get pod -n default No resources found in default namespace. root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl apply -f volume-nfs-demo.yaml pod/volume-nfs-demo created root@k8s-master01:~# kubectl get pod -n default -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES volume-nfs-demo 1/1 Running 0 30s 172.20.58.216 172.168.33.211 <none> <none>
待其重建完成后,通过再次创建的Pod资源的详细描述信息可以观察到它挂载使用NFS存储卷的相关状态,也可通过下面的命令来检查redis-server中是否还保存有此前存储的数据。
root@k8s-master01:~# kubectl exec -it volume-nfs-demo -- redis-cli 127.0.0.1:6379> get key1 "hello world" 127.0.0.1:6379>
上面的命令结果显示出此前创建的键mykey及其数据在Pod对象删除并重建后依然存在,这表明删除Pod对象后,其关联的外部存储设备及数据并不会被一同删除,因而才具有了跨Pod生命周期的数据持久性。若需要在删除Pod后清除具有持久存储功能的存储设备上的数据,则需要用户或管理员通过存储系统的管理接口手动进行。
ceph集群的安装部署
https://www.cnblogs.com/yaokaka/p/15156785.html
Ceph是一个专注于分布式的、弹性可扩展的、高可靠的、性能优异的存储系统平台,同时支持提供块设备、文件系统和对象存储3种存储接口。它是个高度可配置的系统,并提供了一个命令行界面用于监视和控制其存储集群。Kubernetes支持通过RBD卷插件和CephFS卷插件,基于Ceph存储系统为Pod提供存储卷。要配置Pod对象使用RBD存储卷,需要事先满足以下前提条件。
▪存在某可用的Ceph RBD存储集群,否则需要创建一个。
▪在Ceph RBD集群中创建一个能满足Pod资源数据存储需要的存储映像。
▪在Kubernetes集群内的各节点上安装Ceph客户端程序包(ceph-common)。
定义RBD类型的存储卷时需要指定要连接的目标服务器和认证信息等配置,它们依赖如下几个可用的嵌套字段。
▪monitors <[]string>:Ceph存储监视器,逗号分隔的字符串列表;必选字段。 ▪image <string>:rados image(映像)的名称,必选字段。 ▪pool <string>:Ceph存储池名称,默认为rbd。 ▪user <string>:Ceph用户名,默认为admin。 ▪keyring <string>:用户认证到Ceph集群时使用的keyring文件路径,默认为/etc/ceph/keyring。 ▪secretRef <Object>:用户认证到Ceph集群时使用的保存有相应认证信息的Secret资源对象,该字段会覆盖由keyring字段提供的密钥信息。 ▪readOnly <boolean>:是否以只读方式访问。 ▪fsType:要挂载的存储卷的文件系统类型,至少应该是节点操作系统支持的文件系统,例如Ext4、xfs、NTFS等,默认为Ext4。
下面提供的RBD存储卷插件使用示例定义在volumes-rbd-demo.yaml配置清单文件中,它使用admin(ceph默认账户)用户认证到Ceph集群中,并关联RDB存储池k8spool中的存储映像k8srbd为Pod对象volumes-rbd-demo的存储卷,由容器进程挂载至/data目录进行数据存取。
apiVersion: v1 kind: Pod metadata: name: volumes-rbd-demo spec: containers: - name: redis image: redis:alpine ports: - containerPort: 6379 name: redisport volumeMounts: - mountPath: /data name: redis-rbd-vol volumes: - name: redis-rbd-vol rbd: monitors: - '172.168.32.201:6789,172.168.32.202:6789,172.168.32.201:6789' #ceph-mon地址:6789,多mon之间用逗号隔开 pool: k8spool #ceph的存储池 image: k8srbd #rados image(映射)名称 fsType: xfs #挂载卷的类型 readOnly: false #是否为只读 user: admin #ceph的用户名 #user: k8s #使用k8s用户来挂载,需要在ceph中创建k8s用户并授权 keyring: /etc/ceph/ceph.client.admin.keyring #用户认证到Ceph集群时使用的keyring文件路径 #keyring: /etc/ceph/ceph.client.k8s.keyring #k8s的keyring
RBD存储卷插件依赖Ceph存储集群作为存储系统,这里假设其监视器(MON)的地址为172.168.32.201,172.168.32.202,172.168.32.203,集群上的存储池k8spool中需要有事先创建好的存储映像k8srbd。客户端访问集群时要事先认证到Ceph集群并获得相应授权才能进行后续的访问操作,该示例使用了用户的keyring文件。该示例实现的逻辑架构如图所示。
为了完成示例中定义的资源的测试,需要事先完成如下几个步骤。
1)在Ceph集群上的k8spool存储池 root@ceph01:~# ceph osd pool create k8spool 128 128 pool 'k8spool' created root@ceph01:~# ceph osd pool ls device_health_metrics k8spool 2)给创建的pool开启rbd功能 root@ceph01:~# ceph osd pool application enable k8spool rbd enabled application 'rbd' on pool 'k8spool' 3)在k8spool中创建大小为1G的RBD映像文件 #因为挂载rbd的宿主机因内核版本原因不支持rbd的所有特性,只开启部分特性 root@ceph01:~# rbd create k8srbd --size 1G --pool k8spool --image-format 2 --image-feature layering #开启全部特性。注意挂载宿主机的内核版本是否支持rbd的特性功能 #root@ceph01:~# rbd create k8srbd --size 1G --pool k8spool #查看pool中所存在的img root@ceph01:~# rbd ls --pool k8spool k8srbd 4)在Kubernetes集群的所有节点安装ceph客户端(ceph-common) ①把ceph-01上的ceph.repo拷贝到Kubernetes的所有node节点 #master节点 root@ceph01:~# scp /etc/apt/sources.list 172.168.33.207:/etc/apt/sources.list root@ceph01:~# scp /etc/apt/sources.list 172.168.33.208:/etc/apt/sources.list root@ceph01:~# scp /etc/apt/sources.list 172.168.33.209:/etc/apt/sources.list #node节点 root@ceph01:~# scp /etc/apt/sources.list 172.168.33.210:/etc/apt/sources.list root@ceph01:~# scp /etc/apt/sources.list 172.168.33.211:/etc/apt/sources.list root@ceph01:~# scp /etc/apt/sources.list 172.168.33.212:/etc/apt/sources.list ②kubernetes各个node节点安装ceph-common客户端 root@k8s-master01:~# apt update && apt install -y ceph-common root@k8s-master02:~# apt update && apt install -y ceph-common root@k8s-master03:~# apt update && apt install -y ceph-common root@k8s-node01:~# apt update && apt install -y ceph-common root@k8s-node02:~# apt update && apt install -y ceph-common root@k8s-node03:~# apt update && apt install -y ceph-common 5)把ceph中admin的账号密码文件和ceph.conf拷贝到kubernetes的所有node节点上 kubernetes所有的node节点 root@k8s-master01:~# mkdir /etc/ceph root@k8s-master02:~# mkdir /etc/ceph root@k8s-master03:~# mkdir /etc/ceph root@k8s-node01:~# mkdir /etc/ceph root@k8s-node02:~# mkdir /etc/ceph root@k8s-node03:~# mkdir /etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.207:/etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.208:/etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.209:/etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.210:/etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.211:/etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.212:/etc/ceph 6)在k8s节点上可以查询ceph集群的状态 root@k8s-master01:~# ceph -s cluster: id: b6a53e40-2661-4754-8684-7fccb328c274 health: HEALTH_OK services: mon: 3 daemons, quorum ceph01,ceph02,ceph03 (age 8d) mgr: ceph01(active, since 8d), standbys: ceph02, ceph03 osd: 6 osds: 6 up (since 8d), 6 in (since 8d) data: pools: 2 pools, 640 pgs objects: 5 objects, 34 B usage: 70 MiB used, 120 GiB / 120 GiB avail pgs: 640 active+clean
使用普通的k8s用户来挂载
#如果使用普通用户挂载rbd #1)给pool=k8spool创建一个client的k8s用户,对mon有r权限,对k8spool地址池有rwx权限 root@ceph01:~# ceph auth add client.k8s mon 'allow r' osd 'allow rwx pool=k8spool' added key for client.k8s root@ceph01:~# ceph auth get client.k8s [client.k8s] key = AQAHWGRh/d+JNxAAHrzplwi8WWjwXc/NGdJeAw== caps mon = "allow r" caps osd = "allow rwx pool=k8spool" exported keyring for client.k8s #2)创建一个名为ceph.client.k8s.keyring的空的密钥环文件 root@ceph01:~# ceph-authtool --create-keyring ceph.client.k8s.keyring creating ceph.client.k8s.keyring #3)导出client.k8s信息之指定的keyring文件 root@ceph01:~# ceph auth get client.k8s -o ceph.client.k8s.keyring exported keyring for client.k8s root@ceph01:~# cat ceph.client.k8s.keyring [client.k8s] key = AQAHWGRh/d+JNxAAHrzplwi8WWjwXc/NGdJeAw== caps mon = "allow r" caps osd = "allow rwx pool=k8spool" #4)把ceph.client.k8s.keyring 拷贝到所有的k8s节点 root@ceph01:~# scp -r /etc/ceph/ceph.client.k8s.keyring 172.168.33.207:/etc/ceph root@ceph01:~# scp -r /etc/ceph/ceph.client.k8s.keyring 172.168.33.208:/etc/ceph root@ceph01:~# scp -r /etc/ceph/ceph.client.k8s.keyring 172.168.33.209:/etc/ceph root@ceph01:~# scp -r /etc/ceph/ceph.client.k8s.keyring 172.168.33.210:/etc/ceph root@ceph01:~# scp -r /etc/ceph/ceph.client.k8s.keyring 172.168.33.211:/etc/ceph root@ceph01:~# scp -r /etc/ceph/ceph.client.k8s.keyring 172.168.33.212:/etc/ceph #5)在k8s上使用k8s用户可以查询ceph集群的状态 root@k8s-master01:~# ceph -s --user k8s cluster: id: b6a53e40-2661-4754-8684-7fccb328c274 health: HEALTH_OK services: mon: 3 daemons, quorum ceph01,ceph02,ceph03 (age 8d) mgr: ceph01(active, since 8d), standbys: ceph02, ceph03 osd: 6 osds: 6 up (since 8d), 6 in (since 8d) data: pools: 2 pools, 640 pgs objects: 5 objects, 34 B usage: 70 MiB used, 120 GiB / 120 GiB avail pgs: 640 active+clean
使用ceph的admin账户来挂载
root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl apply -f volumes-rbd.yaml pod/volumes-rbd-demo created root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES volumes-rbd-demo 1/1 Running 0 2m32s 172.20.135.176 172.168.33.212 <none> <none>
随后从集群上的Pod对象volumes-rbd-demo的详细描述中获取存储的相关状态信息,确保其创建操作得以成功执行。下面是相关的存储卷信息示例。
root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl describe pod volumes-rbd-demo -n default ...... VVolumes: redis-rbd-vol: Type: RBD (a Rados Block Device mount on the host that shares a pod's lifetime) CephMonitors: [172.168.32.201:6789,172.168.32.202:6789,172.168.32.201:6789] RBDImage: k8srbd FSType: xfs RBDPool: k8spool RadosUser: admin Keyring: /etc/ceph/ceph.client.admin.keyring SecretRef: nil ReadOnly: false ......
使用ceph的k8s普通账户来挂载
1)删除pod root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl delete -f volumes-rbd.yaml pod "volumes-rbd-demo" deleted 2)修改volumes-rbd.yaml 文件,替换admin用户及keyring cat > volumes-rbd.yaml << EOF apiVersion: v1 kind: Pod metadata: name: volumes-rbd-demo spec: containers: - name: redis image: redis:alpine ports: - containerPort: 6379 name: redisport volumeMounts: - mountPath: /data name: redis-rbd-vol volumes: - name: redis-rbd-vol rbd: monitors: - '172.168.32.201:6789,172.168.32.202:6789,172.168.32.201:6789' #ceph-mon地址:6789,多mon之间用逗号隔开 pool: k8spool #ceph的存储池 image: k8srbd #rados image(映射)名称 fsType: xfs #挂载卷的类型 readOnly: false #是否为只读 #user: admin #ceph的用户名 user: k8s #使用k8s用户来挂载,需要在ceph中创建k8s用户并授权 #keyring: /etc/ceph/ceph.client.admin.keyring #用户认证到Ceph集群时使用的keyring文件路径 keyring: /etc/ceph/ceph.client.k8s.keyring #k8s的keyring EOF 3)再次运行volumes-rbd.yaml 清单 root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl apply -f volumes-rbd.yaml pod/volumes-rbd-demo created root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl get pod -n default NAME READY STATUS RESTARTS AGE volumes-rbd-demo 1/1 Running 0 29s 4)查看pod中的volume信息 root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl describe pod volumes-rbd-demo ...... Volumes: redis-rbd-vol: Type: RBD (a Rados Block Device mount on the host that shares a pod's lifetime) CephMonitors: [172.168.32.201:6789,172.168.32.202:6789,172.168.32.201:6789] RBDImage: k8srbd FSType: xfs RBDPool: k8spool RadosUser: k8s Keyring: /etc/ceph/ceph.client.k8s.keyring SecretRef: nil ReadOnly: false ......
2.2 使用secretRef字段来挂载rbd
应该把认证到Ceph集群上的用户的认证信息存储为Kubernetes集群上的Secret资源,并通过secretRef字段进行指定,而非直接使用keyring字段引用相应用户的keyring文件。
使用secretRef的方式来挂载,则不需要keyring文件
使用clinet.k8s用户来实验该方法
1)删除pod root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl delete -f volumes-rbd.yaml pod "volumes-rbd-demo" deleted 2)在ceph上获取client.ks8的key并进行64位编码 #获取client.k8s的key值 root@ceph01:~# ceph auth get client.k8s [client.k8s] key = AQAHWGRh/d+JNxAAHrzplwi8WWjwXc/NGdJeAw== caps mon = "allow r" caps osd = "allow rwx pool=k8spool" exported keyring for client.k8s #对key值做base64编码 root@ceph01:~# echo AQAHWGRh/d+JNxAAHrzplwi8WWjwXc/NGdJeAw== | base64 QVFBSFdHUmgvZCtKTnhBQUhyenBsd2k4V1dqd1hjL05HZEplQXc9PQo= 3)创建client-k8s-rbd-secret.yml apiVersion: v1 kind: Secret metadata: name: client-k8s-rbd-secret data: #Please note this value is client.k8s base64 encoded. # ceph auth get client.k8s | base64 key: QVFBSFdHUmgvZCtKTnhBQUhyenBsd2k4V1dqd1hjL05HZEplQXc9PQo= #client.k8s的key值的base64编码 4)修改volumes-rbd.yaml清单 cat > volumes-rbd.yaml <<EOF apiVersion: v1 kind: Pod metadata: name: volumes-rbd-demo spec: containers: - name: redis image: redis:alpine ports: - containerPort: 6379 name: redisport volumeMounts: - mountPath: /data name: redis-rbd-vol volumes: - name: redis-rbd-vol rbd: monitors: - 172.168.32.201:6789 - 172.168.32.202:6789 - 172.168.32.203:6789 pool: k8spool image: k8srbd user: k8s secretRef: name: client-k8s-rbd-secret #调用上面secret(client-k8s-rbd-secret) fsType: xfs readOnly: false EOF 4)运行client-k8s-rbd-secret.yaml和修改后的volumes-rbd.yaml 清单 root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl apply -f client-k8s-rbd-secret.yml secret/client-k8s-rbd-secret created root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl apply -f volumes-rbd.yaml pod/volumes-rbd-demo created root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl get pod NAME READY STATUS RESTARTS AGE volumes-rbd-demo 1/1 Running 0 7s 5)查看volume信息 root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl describe pod volumes-rbd-demo ...... olumes: redis-rbd-vol: Type: RBD (a Rados Block Device mount on the host that shares a pod's lifetime) CephMonitors: [172.168.32.201:6789 172.168.32.202:6789 172.168.32.201:6789] RBDImage: k8srbd FSType: xfs RBDPool: k8spool RadosUser: k8s Keyring: /etc/ceph/keyring SecretRef: &LocalObjectReference{Name:client-k8s-rbd-secret,} ReadOnly: false ......
3、CephFS存储卷
CephFS存储卷插件嵌套定义于Pod资源的spec.volumes.cephfs字段中,它支持通过如下字段的定义接入到存储预配服务中。
▪monitors <[]string>:Ceph存储监视器,为逗号分隔的字符串列表;必选字段。 ▪user <string>:Ceph集群用户名,默认为admin。 ▪secretFile <string>:用户认证到Ceph集群时使用的Base64格式的密钥文件(非keyring文件),默认为/etc/ceph/user.secret。 ▪secretRef <Object>:用户认证到Ceph集群过程中加载其密钥时使用的Kubernetes Secret资源对象。 ▪path <string>:挂载的文件系统路径,默认为CephFS文件系统的根(/),可以使用CephFS文件系统上的子路径,例如/kube/namespaces/default/redis1等。 ▪readOnly <boolean>:是否挂载为只读模式,默认为false。
下面提供的CephFS存储卷插件使用示例定义在volumes-cephfs-demo.yaml配置清单文件中,它使用admin用户认证到Ceph集群中,并关联CephFS上的子路径/kube/namespaces/default/redis1,作为Pod对象volumes-cephfs-demo的存储卷,并由容器进程挂载至/data目录进行数据存取。
apiVersion: v1 kind: Pod metadata: name: volumes-cephfs-demo namespace: default spec: containers: - name: redis image: redis:alpine imagePullPolicy: IfNotPresent volumeMounts: - name: redis-cephfs-vol mountPath: "/data" volumes: - name: redis-cephfs-vol cephfs: monitors: - 172.168.32.201:6789 - 172.168.32.202:6789 - 172.168.32.203:6789 path: /kube/namespaces/default/redis1 user: admin secretFile: /etc/ceph/admin.secret readOnly: false
Kubernetes集群上需要启用了CephFS,并提供了满足条件的用户账号及授权才能使用CephFS存储卷插件。客户端访问集群时需要事先认证到Ceph集群并获得相应授权才能进行后续的访问操作,该示例使用了保存在/etc/ceph/fsclient.key文件中的CephFS专用用户认证信息。要完成示例清单中定义的资源的测试,需要事先完成如下几个步骤。
1)创建cephfs-metadata root@ceph01:~/cephcluster# ceph osd pool create cephfs-metadata 32 32 pool 'cephfs-metadata' created 2)创建cephfs-data root@ceph01:~/cephcluster# ceph osd pool create cephfs-data 64 64 pool 'cephfs-data' created 3)创建一个叫mycephfs的cephFS root@ceph01:~/cephcluster# ceph fs new mycephfs cephfs-metadata cephfs-data new fs with metadata pool 3 and data pool 4 4)验证cephfs root@ceph01:~/cephcluster# ceph fs status mycephfs mycephfs - 0 clients ======== RANK STATE MDS ACTIVITY DNS INOS DIRS CAPS 0 active ceph03 Reqs: 0 /s 10 13 12 0 POOL TYPE USED AVAIL cephfs-metadata metadata 32.0k 113G cephfs-data data 0 113G STANDBY MDS ceph02 ceph01 MDS version: ceph version 16.2.6 (ee28fb57e47e9f88813e24bbf4c14496ca299d31) pacific (stable) 5)在Kubernetes集群的所有节点安装ceph客户端(ceph-common) ①把ceph-01上的ceph.repo拷贝到Kubernetes的所有node节点 #master节点 root@ceph01:~# scp /etc/apt/sources.list 172.168.33.207:/etc/apt/sources.list root@ceph01:~# scp /etc/apt/sources.list 172.168.33.208:/etc/apt/sources.list root@ceph01:~# scp /etc/apt/sources.list 172.168.33.209:/etc/apt/sources.list #node节点 root@ceph01:~# scp /etc/apt/sources.list 172.168.33.210:/etc/apt/sources.list root@ceph01:~# scp /etc/apt/sources.list 172.168.33.211:/etc/apt/sources.list root@ceph01:~# scp /etc/apt/sources.list 172.168.33.212:/etc/apt/sources.list ②kubernetes各个node节点安装ceph-common客户端 root@k8s-master01:~# apt update && apt install -y ceph-common root@k8s-master02:~# apt update && apt install -y ceph-common root@k8s-master03:~# apt update && apt install -y ceph-common root@k8s-node01:~# apt update && apt install -y ceph-common root@k8s-node02:~# apt update && apt install -y ceph-common root@k8s-node03:~# apt update && apt install -y ceph-common 5)把ceph中admin的账号密码文件和ceph.conf拷贝到kubernetes的所有node节点上 kubernetes所有的node节点 root@k8s-master01:~# mkdir /etc/ceph root@k8s-master02:~# mkdir /etc/ceph root@k8s-master03:~# mkdir /etc/ceph root@k8s-node01:~# mkdir /etc/ceph root@k8s-node02:~# mkdir /etc/ceph root@k8s-node03:~# mkdir /etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.207:/etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.208:/etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.209:/etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.210:/etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.211:/etc/ceph root@ceph01:~# scp -r /etc/ceph/{ceph.client.admin.keyring,ceph.conf} 172.168.33.212:/etc/ceph 6)在kubernetes的所有节点中将/etc/ceph/ceph.client.admin.keyring中的密钥导入到/etc/ceph/admin.secret cat /etc/ceph/ceph.client.admin.keyring root@k8s-master01:~# cat /etc/ceph/ceph.client.admin.keyring [client.admin] key = AQCNxVlhDfpPBBAALJ1Bn6KOGXKug1GIaBXYVA== caps mds = "allow *" caps mgr = "allow *" caps mon = "allow *" caps osd = "allow *" root@k8s-master01:~# cat /etc/ceph/admin.secret AQCNxVlhDfpPBBAALJ1Bn6KOGXKug1GIaBXYVA== root@k8s-master02:~# cat /etc/ceph/admin.secret AQCNxVlhDfpPBBAALJ1Bn6KOGXKug1GIaBXYVA== root@k8s-master03:~# cat /etc/ceph/admin.secret AQCNxVlhDfpPBBAALJ1Bn6KOGXKug1GIaBXYVA== root@k8s-node01:~# cat /etc/ceph/admin.secret AQCNxVlhDfpPBBAALJ1Bn6KOGXKug1GIaBXYVA== root@k8s-node02:~# cat /etc/ceph/admin.secret AQCNxVlhDfpPBBAALJ1Bn6KOGXKug1GIaBXYVA== root@k8s-node03:~# cat /etc/ceph/admin.secret AQCNxVlhDfpPBBAALJ1Bn6KOGXKug1GIaBXYVA==
在Kubernetes的某工作节点上手动挂载CephFS,以创建由Pod对象使用的数据目录。
在kubernetes的任意一台k8s节点k8s-master01上操作,挂载cephfs,并再挂载的cephfs中创建子目录,用于在pod中挂载 root@k8s-master01:~# mount -t ceph -o name=admin,secretfile=/etc/ceph/admin.secret 172.168.32.201:6789:/ /mnt root@k8s-master01:~# df -Th | grep mnt 172.168.32.201:6789:/ ceph 114G 0 114G 0% /mnt root@k8s-master01:~# mkdir -p /mnt/kube/namespaces/default/redis1
上述准备步骤执行完成后即可运行如下命令创建清单volumes-cephfs-demo.yaml中定义的Pod资源,并进行测试:
root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl apply -f volumes-cephfs-demo.yaml pod/volumes-cephfs-demo created root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl get pod NAME READY STATUS RESTARTS AGE volumes-cephfs-demo 1/1 Running 0 3s
随后通过Pod对象volumes-cephfs-demo的详细描述了解其创建及运行状态,若一切无误,则相应的存储卷会显示出类似如下的描述信息:
root@k8s-master01:~# kubectl describe pod volumes-cephfs-demo ...... Volumes: redis-cephfs-vol: Type: CephFS (a CephFS mount on the host that shares a pod's lifetime) Monitors: [172.168.32.201:6789 172.168.32.202:6789 172.168.32.203:6789] Path: /kube/namespaces/default/redis1 User: admin SecretFile: /etc/ceph/admin.secret SecretRef: nil ReadOnly: false ......
3.2 使用secretRef字段来挂载cephfs
在实践中,应该把认证到CephFS文件系统上的用户的认证信息存储为Kubernetes集群上的Secret资源,并通过secretRef字段进行指定,而非像该示例中那样,直接使用secretFile字段引用相应用户密钥信息文件。
1)删除pod root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl delete -f volumes-cephfs-demo.yaml pod "volumes-cephfs-demo" deleted 2)在ceph上获取client.admin的key并进行64位编码 #获取client.k8s的key值 root@ceph01:~# cat /etc/ceph/ceph.client.admin.keyring [client.admin] key = AQCNxVlhDfpPBBAALJ1Bn6KOGXKug1GIaBXYVA== caps mds = "allow *" caps mgr = "allow *" caps mon = "allow *" caps osd = "allow *" #对key值做base64编码 root@ceph01:~# echo AQCNxVlhDfpPBBAALJ1Bn6KOGXKug1GIaBXYVA== | base64 QVFDTnhWbGhEZnBQQkJBQUxKMUJuNktPR1hLdWcxR0lhQlhZVkE9PQo= 3)创建client-admin-cephfs-secret.yaml apiVersion: v1 kind: Secret metadata: name: client-admin-cephfs-secret data: #Please note this value is client.k8s base64 encoded. # ceph auth get client.k8s | base64 key: QVFDTnhWbGhEZnBQQkJBQUxKMUJuNktPR1hLdWcxR0lhQlhZVkE9PQo= #client.admin的key值的base64编码 4)修改volumes-cephfs-demo.yaml清单 cat > volumes-cephfs-demo.yaml <<EOF apiVersion: v1 kind: Pod metadata: name: volumes-cephfs-demo namespace: default spec: containers: - name: redis image: redis:alpine imagePullPolicy: IfNotPresent volumeMounts: - name: redis-cephfs-vol mountPath: "/data" volumes: - name: redis-cephfs-vol cephfs: monitors: - 172.168.32.201:6789 - 172.168.32.202:6789 - 172.168.32.203:6789 path: /kube/namespaces/default/redis1 user: admin secretRef: name: client-admin-cephfs-secret readOnly: false EOF 4)运行client-k8s-cephfs-secret.yaml和修改后的volumes-cephfs-demo.yaml 清单 root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl apply -f client-admin-cephfs-secret.yaml secret/client-admin-cephfs-secret created root@k8s-master01:/apps/k8s-yaml/volume-case# kubectl apply -f volumes-cephfs-demo.yaml pod/volumes-cephfs-demo created root@k8s-master01:~# kubectl get pod NAME READY STATUS RESTARTS AGE volumes-cephfs-demo 1/1 Running 0 116s 5)查看volume信息 root@k8s-master01:~# kubectl describe pod volumes-cephfs-demo ...... Volumes: redis-cephfs-vol: Type: CephFS (a CephFS mount on the host that shares a pod's lifetime) Monitors: [172.168.32.201:6789 172.168.32.202:6789 172.168.32.203:6789] Path: /kube/namespaces/default/redis1 User: admin SecretFile: SecretRef: &LocalObjectReference{Name:client-admin-cephfs-secret,} ReadOnly: false ......