一、ConfigMap
1,介绍
ConfigMap 功能在 Kuberbetes 1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者 json 二进制大对象。
2,创建方式
a)使用目录创建
vim file1.properties name=zhansan age=24 gender=man vim file2.properties color=yellow num=20
#/usr/local/demo/configmap为存储file1.properties和file2.properties的路径 kubectl create configmap cm-by-dir --from-file=/usr/local/demo/configmap kubectl get cm #查看cm的描述 kubectl describe cm cm-by-dir 查看cm的yaml文件内容 kubectl get cm cm-by-dir -o yaml
由此可得出:目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对,键就是文件的名字,值就是文件的内容。
b)使用文件创建
#继续使用a)中的文件 kubectl create configmap cm-by-file --from-file=/usr/local/demo/configmap/file1.properties kubectl get cm
c)使用字面值创建
#使用 --from-literal 参数传递配置信息 kubectl create configmap cm-by-literal --from-literal=name=zhangsan --from-literal=age=18 kubectl get cm
d)使用yaml创建(special.yaml)
apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: special.how: very special.type: charm
kubectl apply -f special.yaml
3,Pod中使用ConfigMap
special-config.yaml:
apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: special.how: very special.type: charm
log-level-config.yaml:
apiVersion: v1 kind: ConfigMap metadata: name: log-level-config namespace: default data: log_level: INFO
编写 Pod 资源清单(cm-env-pod.yaml):
apiVersion: v1 kind: Pod metadata: name: cm-env-pod namespace: default spec: restartPolicy: Never containers: - name: nginx-container image: hub.xcc.com/my-xcc/my-nginx:v1 command: ['sh', '-c', 'env'] #输出容器的环境变量 envFrom: #指定configMap,并使用configMap的key和value作为环境变量的key和value - configMapRef: name: log-level-config #引用的configMap名称 env: - name: SPECIAL_HOW_STR #环境变量key valueFrom: configMapKeyRef: name: special-config #引用的configMap名称 key: special.how #环境变量值为special-config中的special.how的值 - name: SPECIAL_TYPE_STR valueFrom: configMapKeyRef: name: special-config key: special.type
执行命令
kubectl apply -f log-level-config.yaml kubectl apply -f special-config.yaml kubectl apply -f cm-env-pod.yaml kubectl get pod #查看环境变量输出 kubectl log cm-env-pod
4,数据卷挂载
apiVersion: v1 kind: Pod metadata: name: volume-config-pod namespace: default spec: restartPolicy: Never containers: - name: nginx-container image: hub.xcc.com/my-xcc/my-nginx:v1 command: ['sh', '-c', 'sleep 3600'] volumeMounts: - name: config-volume #数据卷名称 mountPath: /etc/config #数据卷容器内的路径 volumes: - name: config-volume #数据卷关联的configMap名称 configMap: name: special-config
执行命令
[root@k8s-master01 ~]# kubectl apply -f volume-config-pod.yaml pod/volume-config-pod created [root@master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE volume-config-pod 1/1 Running 0 3s [root@master01 ~]# kubectl exec volume-config-pod -it /bin/bash root@volume-config-pod:/# cd /etc/config root@volume-config-pod:/etc/config# ls special.how special.type root@volume-config-pod:/etc/config# cat special.how very root@volume-config-pod:/etc/config# cat special.type charm
在挂载数据卷后,容器内部将 configMap 的 key 作为文件名,value 作为文件内容,创建成一个个的文件。
二、Secret
Secret 是一种包含少量敏感信息例如密码、token 或 key 的对象。这样的信息可能会被放在 Pod spec 中或者镜像中;将其放在一个 secret 对象中可以更好地控制它的用途,并降低意外暴露的风险。
Pod可以通过三种方式使用Secret:作为 volume 中的文件被挂载到 pod 中的一个或者多个容器里;作为环境变量注入;或者当 kubelet 为 pod 拉取镜像时使用。
1,secret的分类
-
kubernetes.io/service-account-token
:这是 Service Account 使用 API 凭证自动创建和附加 secret。Kubernetes 自动创建包含访问 API 凭据的 secret,并自动修改您的 pod 以使用此类型的 secret。如果需要,可以禁用或覆盖自动创建和使用API凭据。但是,如果您需要的只是安全地访问 apiserver,我们推荐这样的工作流程。
-
kubernetes.io/dockerconfigjson
:用来存储私有 docker registry 的认证信息。使用imagePullSecrets
策略指定 Secret。 -
Opaque
:base64 编码格式的 Secret,用来存储密码、密钥等;但数据也可以通过 base64 –decode 解码得到原始数据,所有加密性很弱。
2,Opaque Secret
假设有些 pod 需要访问数据库。这些 pod 需要使用的用户名和密码在您本地机器的 ./username.txt
和 ./password.txt
文件里。
a)使用文件创建
echo -n 'admin' > ./username.txt echo -n '123456' > ./password.txt kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt kubectl get secret kubectl get secret db-user-pass -o yaml
b)使用yaml清单创建
echo -n "admin" | base64 # YWRtaW4= echo -n "123456" | base64 # MTIzNDU2
创建mysecret.yaml
apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: YWRtaW4= password: MTIzNDU2
执行命令
kubectl apply -f mysecret.yaml kubectl get secret #查看 Secret 依然是 base64 编码格式保存的内容 kubectl get secret mysecret -o yaml
c)解码
[root@master01 secret]# kubectl get secret NAME TYPE DATA AGE ... [root@k8s-master01 secret]# kubectl get secret mysecret -o yaml apiVersion: v1 data: password: MTIzNDU2 username: YWRtaW4= ...... [root@master01 secret]# echo -n "MTIzNDU2" | base64 -d 123456 [root@master01 secret]# echo -n "YWRtaW4=" | base64 -d admin
d)编辑Secret
kubectl edit secrets mysecret
e)使用Secret
作为volume使用:
Secret可以作为数据卷被挂载,或作为环境变量暴露出来以供Pod中的容器使用。
- 创建一个 secret 或者使用已有的 secret。多个 pod 可以引用同一个 secret。
- 修改 pod 的定义在
spec.volumes[]
下增加一个 volume。可以给这个 volume 随意命名,它的spec.volumes[].secret.secretName
必须等于 secret 对象的名字。 - 将
spec.containers[].volumeMounts[]
加到需要用到该 secret 的容器中。指定spec.containers[].volumeMounts[].readOnly = true
和spec.containers[].volumeMounts[].mountPath
为您想要该 secret 出现的尚未使用的目录。 - 修改您的镜像并且/或者命令行让程序从该目录下寻找文件。Secret 的
data
映射中的每一个键都成为了mountPath
下的一个文件名。
示例:
apiVersion: v1 kind: Pod metadata: name: mypod spec: volumes: - name: foo secret: secretName: mysecret containers: - name: mypod image: hub.xcc.com/my-xcc/my-nginx:v1 volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true
向特此那个路径映射secret::
apiVersion: v1 kind: Pod metadata: name: mypod spec: volumes: - name: foo secret: secretName: mysecret items: - key: username path: my-group/my-username #secret存储的路径为/etc/foo/my-group/my-username containers: - name: mypod image: hub.xcc.com/my-xcc/my-nginx:v1 volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true
作为环境变量使用
将 secret 作为 pod 中的环境变量使用:
- 创建一个 secret 或者使用一个已存在的 secret。多个 pod 可以引用同一个 secret。
- 修改 Pod 定义,为每个要使用 secret 的容器添加对应 secret key 的环境变量。消费 secret key 的环境变量应填充 secret 的名称,并键入
env[x].valueFrom.secretKeyRef
。 - 修改镜像并/或者命令行,以便程序在指定的环境变量中查找值。
示例:
apiVersion: v1 kind: Pod metadata: name: secret-env-pod spec: containers: - name: mycontainer image: hub.xcc.com/my-xcc/my-nginx:v1 env: - name: SECRET_USERNAME valueFrom: secretKeyRef: name: mysecret key: username - name: SECRET_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password restartPolicy: Never
执行命令:
kubectl apply -f secret-env.yaml kubectl get pod kubectl exec secret-env-pod -it /bin/sh echo $SECRET_USERNAME echo $SECRET_PASSWORD
3,ImagePullSecret
假如我们创建 Pod 时,Pod 里面所使用的镜像是私有的,需要进行身份认证才能够拉取,那么我们可以创建一个具有该私有仓库认证信息的 Secret,然后使用 ImagePullSecrets 指定。
下面我们使用 harbor 私有仓库进行举例。在 harbor 中创建一个私有项目 tom,并向该项目中 push 一个镜像 hub.xcc.com/my/nginx:v1
。然后将集群中的所有节点都退出 harbor 的登录,并删除所有节点中的 hub.xcc.com/my/nginx:v1 镜像。
#镜像拉取错误 rpc error: code = Unknown desc = Error response from daemon: pull access denied for hub.xcc.com/my/nginx, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
解决步骤:
创建认证信息Secret
kubectl create secret docker-registry my-registry-secret --docker-server=hub.xcc.com --docker-username=admin --docker-password=Harbor12345 --docker-email=[email protected]
my-registry-secret:被创建的secret名称
yaml文件
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: nginx-container image: hub.xcc.com/my/nginx:v1 imagePullSecrets: - name: my-registry-secret
三、Volume
1,介绍
容器中的文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题。 首先,当容器崩溃时,kubelet 将重新启动容器,容器中的文件将会丢失——因为容器会以干净的状态重建(这和 docker 容器的重启不一样,docker 容器重启不会丢失数据)。其次,当在一个 Pod 中同时运行多个容器时,常常需要在这些容器之间共享文件。 Kubernetes 抽象出 Volume
对象来解决这两个问题。
2,分类
- awsElasticBlockStore
- azureDisk
- azureFile
- cephfs
- cinder
- configMap
- csi
- downwardAPI
- emptyDir
- fc (fibre channel)
- flexVolume
- flocker
- gcePersistentDisk
- gitRepo (deprecated)
- glusterfs
- hostPath
- iscsi
- local
- nfs
- persistentVolumeClaim
- projected
- portworxVolume
- quobyte
- rbd
- scaleIO
- secret
- storageos
- vsphereVolume
3,emptyDir
当 Pod 指定到某个节点上时,首先创建的是一个 emptyDir
卷,并且只要 Pod 在该节点上运行,卷就一直存在。 就像它的名称表示的那样,卷最初是空的。 尽管 Pod 中的容器挂载 emptyDir
卷的路径可能相同也可能不同,但是这些容器都可以读写 emptyDir
卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir
卷中的数据也会永久删除。
说明: 容器崩溃并不会导致 Pod 被从节点上移除,因此容器崩溃时emptyDir
卷中的数据是安全的。
emptyDir
的一些用途:
- 缓存空间,例如基于磁盘的归并排序。
- 为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
- 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。
默认情况下, emptyDir
卷存储在支持该节点所使用的介质上;这里的介质可以是磁盘或 SSD 或网络存储,这取决于您的环境。 但是,您可以将 emptyDir.medium
字段设置为 "Memory"
,以告诉 Kubernetes 为您安装 tmpfs(基于 RAM 的文件系统)。 虽然 tmpfs 速度非常快,但是要注意它与磁盘不同。 tmpfs 在节点重启时会被清除,并且您所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束。
创建volume-emptydir-pod.yaml
apiVersion: v1 kind: Pod metadata: name: volume-emptydir-pod spec: containers: - name: nginx-container #initc容器1 image: hub.xcc.com/my-xcc/my-nginx:v1 volumeMounts: #nginx-container 容器将 volume 挂载到了容器中的 /nginx-cache 目录下 - mountPath: /nginx-cache name: cache-volume #使用volume - name: busybox-container image: hub.xcc.com/my-xcc/my-busybox:v1 command: ['sh', '-c', 'sleep 3600s'] volumeMounts: #busybox-container 容器将 volume 挂载到了容器中的 /busybox-cache 目录下 - mountPath: /busybox-cache name: cache-volume volumes: #定义volume - name: cache-volume emptyDir: {}
执行命令
kubectl apply -f volume-emptydir-pod.yaml kubectl get pod #进入initc容器nginx-container kubectl exec volume-emptydir-pod -c nginx-container -it -- bin/bash ls /nginx-cache #进入initc容器busybox-container kubectl exec volume-emptydir-pod -c busybox-container -it -- bin/bash ls /busybox-cache #在nginx-container中 echo "this's nginx-container add content" > /nginx-cache/a.txt #在busybox-container中 cat /busybox-cache/a.txt
4,hostPath
hostPath
卷能将主机节点文件系统上的文件或目录挂载到您的 Pod 中。 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。
例如,hostPath
的一些用法有:
- 运行一个需要访问 Docker 引擎内部机制的容器;请使用
hostPath
挂载/var/lib/docker
路径。 - 在容器中运行 cAdvisor 时,以
hostPath
方式挂载/sys
。 - 允许 Pod 指定给定的
hostPath
在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。
除了必需的 path
属性之外,用户可以选择性地为 hostPath
卷指定 type
。
支持的 type
值如下:
取值 | 行为 |
---|---|
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。 | |
DirectoryOrCreate |
如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 Kubelet 相同的组和所有权。 |
Directory |
在给定路径上必须存在的目录。 |
FileOrCreate |
如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 Kubelet 相同的组和所有权。 |
File |
在给定路径上必须存在的文件。 |
Socket |
在给定路径上必须存在的 UNIX 套接字。 |
CharDevice |
在给定路径上必须存在的字符设备。 |
BlockDevice |
在给定路径上必须存在的块设备。 |
当使用这种类型的卷时要小心,因为:
- 具有相同配置(例如从 podTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。
- 当 Kubernetes 按照计划添加资源感知的调度时,这类调度机制将无法考虑由
hostPath
使用的资源。 - 基础主机上创建的文件或目录只能由 root 用户写入。您需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入
hostPath
卷。
Pod 示例
apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: k8s.gcr.io/test-webserver name: test-container volumeMounts: - mountPath: /test-pd name: test-volume volumes: - name: test-volume hostPath: # directory location on host path: /data # this field is optional type: Directory
注意: 应当注意,FileOrCreate
类型不会负责创建文件的父目录。 如果挂载挂载文件的父目录不存在,pod 启动会失败。 为了确保这种type
能够工作,可以尝试把文件和它对应的目录分开挂载,如下所示:
FileOrCreate pod 示例
apiVersion: v1 kind: Pod metadata: name: test-webserver spec: containers: - name: test-webserver image: k8s.gcr.io/test-webserver:latest volumeMounts: - mountPath: /var/local/aaa name: mydir - mountPath: /var/local/aaa/1.txt name: myfile volumes: - name: mydir hostPath: # 确保文件所在目录成功创建。 path: /var/local/aaa type: DirectoryOrCreate - name: myfile hostPath: path: /var/local/aaa/1.txt type: FileOrCreate
四、PV和PVC
1,概念
持久卷(PersistentVolume,PV)是集群中的一块存储,可以由管理员事先供应,或者 使用存储类(Storage Class)来动态供应。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样,也是使用 卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。 此 API 对象中记述了存储的实现细节,无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。
持久卷申领(PersistentVolumeClaim,PVC)表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源(CPU 和内存);同样 PVC 申领也可以请求特定的大小和访问模式 (例如,可以要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载,参见访问模式)。
2,生命周期
参考官网
3,PV类型
-
GCEPersistentDisk
、AWSElasticBlockStore
、AzureFile
、AzureDisk
、CSI
、FC (Fibre Channel)
-
FlexVolume
、Flocker
、NFS
、iSCSI
、RBD (Ceph Block Device)
、CephFS
、Cinder (OpenStack block storage)
-
Glusterfs
、VsphereVolume
、Quobyte Volumes
、Portworx Volumes
、ScaleIO Volumes
、StorageOS
-
HostPath (Single node testing only – local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)
4,PV示例
apiVersion: v1 kind: PersistentVolume metadata: name: pv0003 spec: capacity: storage: 500Mb #指定PV容量大小 volumeMode: Filesystem #文件系统类型,有两种类型:Filesystem(在创建 Pod 时会将挂载的卷嵌入到 Pod 的文件目录中) 和 Block(Pod 和卷之间没有任何文件系统层)。这是一个可选的参数,默认为 Filesystem。 accessModes: - ReadWriteOnce #ReadWriteOnce – 只能在一个节点中挂载,能够读写;ReadOnlyMany – 能够在多个节点挂载,只能读;ReadWriteMany – 能够在多个节点挂载,能够读写。 persistentVolumeReclaimPolicy: Recycle #回收策略。Retain(保留。手动回收);Recycle(回收,基本擦除rm -rf /thevolume/*);Delete(删除。关联的存储资产,如:AWS EBS、GCE PD等也将被删除)。 storageClassName: slow #为PV生命一个类名。PVC 的 storageClassName 必须和这个一致。但是 PV 和 PVC 都可以不设置这个值而使用默认的类名。Recycle:回收。不推荐使用此策略。相反,推荐的方法是使用动态配置。 mountOptions: - hard - nfsvers=4.1 nfs: path: /tmp server: 172.17.0.2
5,PVC示例
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: myclaim spec: accessModes: - ReadWriteOnce #必须和PV的accessModes一样或者是PV的子集 volumeMode: Filesystem #必须和PV的volumeMode一样 resources: #声明(如Pod)可以请求的资源大小。PVC会自动去寻找合适大小的PV匹配 requests: storage: 800Mb storageClassName: slow #与PV一致 selector: #通过指定标签进一步过滤PV。 matchLabels: #matchLabels PV中必须带有这个标签和值; release: "stable" matchExpressions: #matchExpressions 通过指定运算符:In,NotIn,Exists和DoesNotExist等
- {key: environment, operator: In, values: [dev]}
6,NFS示例
a)安装NFS
# 在harbor上192.168.232.90 #安装 nfs 服务及相关工具 yum install -y nfs-common nfs-utils rpcbind # 创建4个共享文件夹 mkdir /nfs1 /nfs2 /nfs3 /nfs4 chmod 777 /nfs1 /nfs2 /nfs3 /nfs4 chown nfsnobody /nfs1 /nfs2 /nfs3 /nfs4 #添加exports vim /etc/exports /nfs1 *(rw,no_root_squash,no_all_squash,sync) /nfs2 *(rw,no_root_squash,no_all_squash,sync) /nfs3 *(rw,no_root_squash,no_all_squash,sync) /nfs4 *(rw,no_root_squash,no_all_squash,sync) #重启绑定和nfs systemctl start rpcbind && systemctl start nfs #在集群中所有节点安装 yum install -y nfs-utils rpcbind
在集群任一节点测试挂载 nfs 文件系统:
# 测试连接 nfs,结果显示了 nfs 服务器的可挂载目录 [root@master01 testnfs]# showmount -e 192.168.232.90 Export list for 192.168.232.90: /nfs4 * /nfs3 * /nfs2 * /nfs1 * [root@master01 ~]# pwd /root [root@master01 ~]# mkdir nfs2 # 将本地 /root/nfs2/ 目录挂载到 nfs2 服务器目录 [root@master01 nfs2]# mount -t nfs 192.168.232.90:/nfs2 /root/nfs2/
[root@master01 ~]# cd nfs2/ [root@master01 nfs2]# touch test.txt
[root@master01 nfs2]# ls
test.txt # 此时 192.168.232.90 机器上的 /nfs2 目录可以看到 test.txt 这个文件 # 退出连接 [root@k8s-master01 testnfs]# umount -l /root/nfs2/
错误排查:如果执行命令 showmount -e 192.168.232.90
提示: clnt_create: RPC: Port mapper failure - Unable to receive: errno 113 (No route to host),可以关掉 nfs 服务器的防火墙(systemctl status firewalld),或者开启某些端口(自行网上搜索下)。
b)创建PV
nfs1-pv.yaml
apiVersion: v1 kind: PersistentVolume metadata: name: nfs1-pv spec: capacity: storage: 100Mb accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: "nfs" nfs: path: /nfs1 server: 192.168.232.90
nfs2-pv.yaml
apiVersion: v1 kind: PersistentVolume metadata: name: nfs2-pv spec: capacity: storage: 400Mb accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: "nfs" nfs: path: /nfs2 server: 192.168.232.90
nfs3-pv.yaml
apiVersion: v1 kind: PersistentVolume metadata: name: nfs3-pv spec: capacity: storage: 700Mb accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: "nfs" nfs: path: /nfs3 server: 192.168.232.90
nfs4-pv.yaml
apiVersion: v1 kind: PersistentVolume metadata: name: nfs4-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: "nfs" nfs: path: /nfs4 server: 192.168.232.90
执行命令
kubectl apply -f nfs1-pv.yaml kubectl apply -f nfs2-pv.yaml kubectl apply -f nfs3-pv.yaml kubectl apply -f nfs4-pv.yaml #可看到 VOLUMEMODE 是 Filesystem 其中PV 都是 Available 的,即未绑定状态 kubectl get pv -o wide
c)创建PVC和Pod
nfs-pvc-pod.yaml
apiVersion: v1 kind: Service metadata: name: nginx-svc labels: app: nginx-app spec: ports: - port: 80 name: web clusterIP: "None" selector: app: nginx-app --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: replicas: 1 serviceName: "nginx-app" selector: matchLabels: app: nginx-app template: metadata: labels: app: nginx-app spec: containers: - name: nginx-container image: hub.xcc.com/my-xcc/my-nginx:v1 ports: - containerPort: 80 name: web volumeMounts: - name: pvc-volume mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: pvc-volume spec: accessModes: ["ReadWriteOnce"] storageClassName: "nfs" resources: requests: storage: 600Mb
执行命令
kubectl apply -f nfs-pvc-pod.yaml kubectl get pvc #查看绑定情况 kubectl get pv kubectl get pod #我们将 statefulSet 扩容到 2 个 Pod,然后查看 pvc 的绑定情况 kubectl scale statefulSet web --replicas 2 kubectl get statefulSet kubectl get pod kubectl get pvc kubectl get pv