kubernetes volume和configure
Kubernetes Volume
环境准备
[root@master30 ~ 09:46:38]# kubectl create namespace storage
namespace/storage created
[root@master30 ~ 10:07:02]# kubectl config set-context --current --namespace storage
Context "kubernetes-admin@kubernetes" modified.
[root@master30 ~ 10:07:32]# mkdir storage
emptyDir
默认情况下,当Pod分配到Node上时,将会创建emptyDir,只要Node上的Pod一直运行,Volume就会一直存。当Pod(不管任何原因)从Node上被删除时,emptyDir也同时会删除,存储的数据也将永久删除。
准备一个包含2个容器的pod,使用emptyDir。
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
app: busybox
spec:
volumes:
- name: datavolume
emptyDir: {}
containers:
- name: busybox1
image: docker.io/library/busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
- name: busybox2
image: docker.io/library/busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
[root@master30 ~ 10:07:46]# cd storage/
[root@master30 storage 10:07:57]# vim pod-emptyDir.yaml ##文件如上
[root@master30 storage 10:08:34]# kubectl apply -f pod-emptyDir.yaml
pod/busybox created
##查看在那个主机
[root@master30 storage 10:08:59]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 2/2 Running 0 25s 10.224.137.5 worker31 <none> <none>
# 创建数据
[root@master30 storage 10:11:42]# kubectl exec -it busybox -c busybox2 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # ls /data/
/ # exit
[root@master30 storage 10:12:10]# kubectl exec -it busybox -c busybox1 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # ls /data/
/ # cd /data/
/data # touch f1-from-b1
/data # exit
[root@master30 storage 10:16:01]# kubectl exec -it busybox -c busybox2 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # ls /data/
f1-from-b1
/ # cd /data/
/data # touch f2-from-b2
/data # exit
##发现俩个容器之间都会有相同的文件,因为都是挂载同一个目录
##查看文件来源于宿主机的哪里
##获取容器id
[root@worker31 ~ 10:10:15]# crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD
f35e75dc69581 c6348fa86ba0f 10 minutes ago Running busybox2 0 927073f4d41f1 busybox
1005d7803e287 c6348fa86ba0f 10 minutes ago Running busybox1 0 927073f4d41f1 busybox
418ed90fc8fed 637146d27f660 48 minutes ago Running calico-node 3 fe3424c654b77 calico-node-gcz8k
4cafdf0a7dbd7 53c535741fb44 48 minutes ago Running kube-proxy 3 ed3ab523c794c kube-proxy-7z8tj
##查看目录
[root@worker31 ~ 10:20:25]# crictl inspect 1005d7803e287 | grep data
"metadata": {
"containerPath": "/data",
"hostPath": "/var/lib/kubelet/pods/cfbeedc4-f63e-4f6c-a6e2-44289931bf8b/volumes/kubernetes.io~empty-dir/datavolume",
"metadata": {
"container_path": "/data",
"host_path": "/var/lib/kubelet/pods/cfbeedc4-f63e-4f6c-a6e2-44289931bf8b/volumes/kubernetes.io~empty-dir/datavolume"
"destination": "/data",
"source": "/var/lib/kubelet/pods/cfbeedc4-f63e-4f6c-a6e2-44289931bf8b/volumes/kubernetes.io~empty-dir/datavolume",
##宿主机的这个目录下面存在这容器创建的文件
[root@worker31 ~ 10:20:51]# ls /var/lib/kubelet/pods/cfbeedc4-f63e-4f6c-a6e2-44289931bf8b/volumes/kubernetes.io~empty-dir/datavolume
f1-from-b1 f2-from-b2
# 删除pod,验证emptyDir
[root@master30 storage 10:22:34]# kubectl delete pod busybox --force
Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "busybox" force deleted
[root@worker31 ~ 10:22:56]# ls /var/lib/kubelet/pods/cfbeedc4-f63e-4f6c-a6e2-44289931bf8b/volumes/kubernetes.io~empty-dir/datavolume
ls: cannot access '/var/lib/kubelet/pods/cfbeedc4-f63e-4f6c-a6e2-44289931bf8b/volumes/kubernetes.io~empty-dir/datavolume': No such file or directory
[root@worker31 ~ 10:23:28]# ls /var/lib/kubelet/pods/cfbeedc4-f63e-4f6c-a6e2-44289931bf8b/
ls: cannot access '/var/lib/kubelet/pods/cfbeedc4-f63e-4f6c-a6e2-44289931bf8b/': No such file or directory
##发现podid已经没有了
hostPath
hostPath允许Pod将Node的文件系统中某个目录挂载到Pod内部。pod删除后,hostPath卷数据保留。
准备一个pod,使用hostPath。
[root@master30 storage 10:32:35]# vim pod-hostPath.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
app: busybox
spec:
volumes:
- name: datavolume
hostPath:
path: /busyboxdir
containers:
- name: busybox1
image: docker.io/library/busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
- name: busybox2
image: docker.io/library/busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
# 设置readOnly,控制读写,默认值是false,也就是读写访问。
readOnly: true
#创建pod
[root@master30 storage 10:38:56]# kubectl apply -f pod-hostPath.yaml
pod/busybox created
##获取容器所在节点
[root@master30 storage 10:39:07]# kubectl get pod busybox -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 2/2 Running 0 27s 10.224.137.6 worker31 <none> <none>
##获取容器id,查看目录
[root@worker31 ~ 10:39:52]# crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD
165a2171d17ee c6348fa86ba0f 57 seconds ago Running busybox2 0 bf4bf16ffe0cd busybox
1ff42035ca413 c6348fa86ba0f 57 seconds ago Running busybox1 0 bf4bf16ffe0cd busybox
418ed90fc8fed 637146d27f660 About an hour ago Running calico-node 3 fe3424c654b77 calico-node-gcz8k
4cafdf0a7dbd7 53c535741fb44 About an hour ago Running kube-proxy 3 ed3ab523c794c kube-proxy-7z8tj
[root@worker31 ~ 10:40:06]# crictl inspect 1ff42035ca413 | grep busyboxdir
"hostPath": "/busyboxdir",
"host_path": "/busyboxdir"
"source": "/busyboxdir",
##测试
[root@master30 storage 10:40:44]# kubectl exec -it busybox -c busybox1 -- sh
/ # touch /data/b1-f1
/ # exit
[root@master30 storage 10:41:33]# kubectl exec -it busybox -c busybox2 -- sh
/ # ls /data/
b1-f1
/ # touch /data/b2-f2
touch: /data/b2-f2: Read-only file system
/ #
##发现busybox2只读不可创建 验证了 yaml文件的 readOnly: true
##节点确实存在目录且有先前创建的文件
[root@worker31 ~ 10:40:34]# ls /busyboxdir/
b1-f1
##删除pod容器用来验证hostpath
[root@master30 storage 10:45:31]# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox 2/2 Running 0 7m56s
[root@master30 storage 10:47:03]# kubectl delete pod busybox --force
Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "busybox" force deleted
# pod删除后,hostPath卷数据保留。
[root@worker31 ~ 10:49:26]# ls /busyboxdir/
b1-f1
##过了几分钟目录还存在
NFS 存储
NFS卷,将数据存储在NFS共享中。
准备NFS共享
# 安装 NFS server
[root@master30 storage 11:15:31]# apt install -y nfs-kernel-server
# 安创建NFS目录 修改创建文件夹的权限
[root@master30 storage 11:16:01]# mkdir -m 777 /nfsshares
[root@master30 storage 11:16:10]# echo hello > /nfsshares/index.html
# 配置共享,允许所有客户端访问
[root@master30 storage 11:16:20]# cat << EOF > /etc/exports
/nfsshares *(rw)
EOF
# 重启 nfs server
[root@master30 storage 11:16:29]# systemctl restart nfs-server.service
# 客户端安装
[root@worker31 ~ 10:50:04]# apt install -y nfs-kernel-server
[root@worker31 ~ 11:16:13]# showmount -e master30
Export list for master30:
/nfsshares *
[root@worker31 ~ 11:16:54]# mount master30:/nfsshares /mnt
[root@worker31 ~ 11:17:30]# ls /mnt
index.html
[root@worker31 ~ 11:17:37]# cat /mnt/index.html
hello
准备 pod
[root@master30 storage 11:17:56]# vim pod-nfs.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx
name: nginx
spec:
volumes:
- name: nfs
nfs:
server: 10.1.8.30
path: "/nfsshares"
containers:
- image: hub.laoma.cloud/library/nginx
name: nginx
volumeMounts:
- name: nfs
mountPath: "/usr/share/nginx/html"
#创建容器
[root@master30 storage 11:18:31]# kubectl apply -f pod-nfs.yaml
pod/nginx created
#查看容器ip
[root@master30 storage 11:18:42]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 10s 10.224.45.6 worker32 <none> <none>
[root@master30 storage 11:18:52]# curl 10.224.45.6
hello
持久性存储
Kubernetes 使用 persistent volume(PV)架构为集群提供永久存储。
PV 和 PVC 架构
开发人员不知道特定云环境的细节的情况下,只需要使用persistentVolumeClaim(PVC)请求PV资源,实现持久化存储。
- Persistent Volume,由PersistentVolume API对象定义,代表集群中现有存储。PV的生命周期与使用其的pod无关。Persistent Volume 是集群级别资源。
- Persistent Volume Claim,由PersistentVolumeClaim API对象定义,代表开发人员请求PV。Persistent Volume Claim 是 namespace 级别资源。
创建 PV 和 PVC
创建 PV
集群管理员可以创建任意数量PV,取决于后端存储。
[root@master30 storage 11:19:17]# vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: web
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
nfs:
path: /nfsshares
server: 10.1.8.30
[root@master30 storage 11:42:45]# kubectl apply -f pv.yaml
persistentvolume/web created
[root@master30 storage 11:43:31]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
web 5Gi RWO Retain Available <unset> 15s
创建 PVC
用户创建PVC,pod使用PVC申请特定容量、特定modes和特定存储类别的存储。master监控PVCs,查找匹配的PV或者等待后端存储创建相应PV,然后绑定PV和PVC。
[root@master30 storage 11:44:41]# vim pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: webclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
[root@master30 storage 11:45:35]# kubectl apply -f pvc.yaml
persistentvolumeclaim/webclaim created
[root@master30 storage 11:46:20]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
webclaim Bound web 5Gi RWO <unset> 12s
创建Pod使用PV
[root@master30 storage 11:46:32]# vim pod-with-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
name: web
spec:
containers:
- image: hub.laoma.cloud/library/nginx
name: web
ports:
- containerPort: 80
name: web-port
volumeMounts:
- name: web-persistent-storage
mountPath: /usr/share/nginx/html
volumes:
- name: web-persistent-storage
persistentVolumeClaim:
claimName: webclaim
##创建
[root@master30 storage 11:47:37]# kubectl apply -f pod-with-pvc.yaml
pod/web created
##查看ip
[root@master30 storage 11:48:16]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web 1/1 Running 0 11s 10.224.45.7 worker32 <none> <none>
ce'shi
[root@master30 storage 11:48:27]# curl 10.224.45.7
hello
PV accessModes
PersistentVolume 卷访问模式有:
- ReadWriteOnce,卷可以被一个节点以读写方式挂载,也允许同一节点上的多个 Pod 读写访问卷。
- ReadOnlyMany,卷可以被多个节点以只读方式挂载。
- ReadWriteMany,卷可以被多个节点以读写方式挂载。
- ReadWriteOncePod,卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用 ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本。
在命令行接口(CLI)中,访问模式也使用以下缩写形式:
- RWO - ReadWriteOnce
- ROX - ReadOnlyMany
- RWX - ReadWriteMany
- RWOP - ReadWriteOncePod
不同存储后端支持不同的模式:
| 卷插件 | ReadWriteOnce | ReadOnlyMany | ReadWriteMany | ReadWriteOncePod |
|---|---|---|---|---|
| AzureFile | ✓ | ✓ | ✓ | - |
| CephFS | ✓ | ✓ | ✓ | - |
| CSI | 取决于驱动 | 取决于驱动 | 取决于驱动 | 取决于驱动 |
| FC | ✓ | ✓ | - | - |
| FlexVolume | ✓ | ✓ | 取决于驱动 | - |
| GCEPersistentDisk | ✓ | ✓ | - | - |
| Glusterfs | ✓ | ✓ | ✓ | - |
| HostPath | ✓ | - | - | - |
| iSCSI | ✓ | ✓ | - | - |
| NFS | ✓ | ✓ | ✓ | - |
| RBD | ✓ | ✓ | - | - |
| VsphereVolume | ✓ | - | -(Pod 运行于同一节点上时可行) | - |
| PortworxVolume | ✓ | - | ✓ | - |
重要: 每个卷同一时刻只能以一种访问模式挂载,即使该卷能够支持多种访问模式。 例如,一个 GCEPersistentDisk 卷可以被某节点以 ReadWriteOnce 模式挂载,或者被多个节点以 ReadOnlyMany 模式挂载,但不可以同时以两种模式挂载。
常见的NAS存储都支持三种存储模式:ReadWriteOnce、ReadOnlyMany、ReadWriteMany。
PV volumeModes
特性状态: Kubernetes v1.18 [stable]
针对 PV 持久卷,Kubernetes 支持两种卷模式(volumeModes):Filesystem(文件系统) 和 Block(块)。 volumeMode 是一个可选的 API 参数。 如果该参数被省略,默认的卷模式是 Filesystem。
- Filesystem 卷,会被 Pod 挂载(Mount) 到某个目录。 如果卷的存储来自某块设备而该设备目前为空,Kuberneretes 会在第一次挂载卷之前在设备上创建文件系统。
- Block 卷,会被作为原始块设备来使用。 这类卷以块设备的方式交给 Pod 使用,其上没有任何文件系统。 这种模式对于为 Pod 提供一种使用最快可能方式来访问卷而言很有帮助, Pod 和卷之间不存在文件系统层。另外,Pod 中运行的应用必须知道如何处理原始块设备。 关于如何在 Pod 中使用
volumeMode: Block的卷, 可参阅原始块卷支持。
PVC与PV匹配规则
- PV的mode必须高于PVC申请的最低要求:mode 优先级,可简单理解为ROX<RWO<RWX。例如,用户请求RWO模式PV,但是目前只有NFS PV(RWO+ROX+RWX),PVC将匹配NFS。
- 容量满足最低要求:具有相同modes卷会被分组,然后根据size分类(由小到大)。
- pv storage classes:用于对pv进行分类,pvc可以根据storageClassName参数申请特定类型pv。如果pv设置了storageClassName,那么 pvc 申请资源的时候也要指定storageClassName。例如,storageClassName指定为 ns1-storage,ns1中pvc申请也指定storageClassName为ns1-storage。
PV 回收策略
当用户不再使用其存储卷时,他们可以从 API 中将 PVC 对象删除, 从而允许该资源被回收再利用。PersistentVolume 对象的回收策略告诉集群, 当其被从申领中释放时如何处理该数据卷。
PersistentVolume 回收策略支持:Retain(保留)、Recycle(回收)、Delete(删除)。
Retain(保留)
回收策略 Retain 使得用户可以手动回收资源。当 PersistentVolumeClaim 对象被删除时,PersistentVolume 卷仍然存在,对应的数据卷被视为"已释放(released)"。 由于卷上仍然保留上一次关联的pvc信息,清理掉上一次关联的pvc信息才可分配给其他pvc。Retain(保留)策略是默认策略。
示例:
[root@master30 storage 13:49:52]# vim pv-pvc-Retain.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: web
spec:
capacity:
storage: 5Gi
#persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
nfs:
path: /nfsshares
server: 10.1.8.30
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: webclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
[root@master30 storage 13:55:45]# kubectl apply -f pv-pvc-Retain.yaml
persistentvolume/web unchanged
persistentvolumeclaim/webclaim unchanged
[root@master30 storage 13:56:25]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
web 5Gi RWO Retain Bound storage/webclaim <unset> 133m
[root@master30 storage 13:56:36]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
webclaim Bound web 5Gi RWO <unset> 130m
删除 pvc 验证
[root@master30 storage 13:57:30]# kubectl delete pvc webclaim
persistentvolumeclaim "webclaim" deleted
##显示一直在删除,不回显示
[root@master30 ~ 13:57:59]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
web 5Gi RWO Retain Bound storage/webclaim <unset> 134m
[root@master30 ~ 13:58:17]# vim pvc-db.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dbclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
[root@master30 ~ 13:59:49]# kubectl apply -f pvc-db.yaml
persistentvolumeclaim/dbclaim created
##无法绑定
[root@master30 ~ 14:00:02]# kubectl get pvc dbclaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
dbclaim Pending <unset> 13s
# 手动清理卷上claimRef信息,删除claimRef部分
[root@master30 ~]# kubectl edit pv web
# 删除claimRef部分
# claimRef:
# apiVersion: v1
# kind: PersistentVolumeClaim
# name: webclaim
# namespace: test
# resourceVersion: "112157"
# uid: 0839cdc1-81bb-11e9-9ca8-52540000fa0a
# 删除claimRef部分
# dbclaim 绑定成功
[root@master30 ~]# kubectl get pvc dbclaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
dbclaim Bound web 5Gi RWO 3m49s
**注意:**删除pv,并不会删除后端存储中数据。
Recycle(回收)
**警告:**回收策略 Recycle 已被废弃。取而代之的建议方案是使用动态制备。
Recycle(回收)策略的效果与 Retaine(保留)一致。
Delete(删除)
对于支持 Delete 回收策略的卷插件,删除动作会将 PersistentVolume 对象从 Kubernetes 中移除,同时也会从外部基础设施(如 AWS EBS 或 GCE PD 卷)中移除所关联的存储资产。
Kubernetes Configure
环境准备
[root@master30 ~ 14:11:47]# kubectl create ns configure
namespace/configure created
[root@master30 ~ 14:15:00]# kubectl config set-context --current --namespace configure
Context "kubernetes-admin@kubernetes" modified.
ConfigMap
ConfigMap 介绍
ConfigMap 是一个存储其他对象所需要使用的配置的 API 对象。 ConfigMap 使用 data 和 binaryData 字段,保存键值对数据。
data字段,用来保存 UTF-8 字符串。binaryData字段,用来保存二进制数据(base64 编码的字串) 。
ConfigMap 的名字必须是一个合法的 DNS 子域名。data 或 binaryData 字段下面的每个键的名称都必须由字母、数字或者 -、_ 或 . 组成。在 data 下保存的键名不可以与在 binaryData 下出现的键名有重叠。
从 v1.19 开始,你可以添加一个 immutable 字段到 ConfigMap 定义中, 创建不可变更的 ConfigMap
ConfigMap 使用建议
- 使用 ConfigMap 存储配置数据,不存数据 / 文件,上限 = 1 MiB。
- **ConfigMap 在设计上不是用来保存大量数据的。**如果你需要保存大量数据,考虑使用挂载存储卷或者使用独立的数据库或者文件服务。
ConfigMap 创建
键值对类型
[root@master30 ~ 14:27:55]# kubectl create configmap mysql --from-literal=password=redhat
configmap/mysql created
[root@master30 ~ 14:28:12]# kubectl get configmaps mysql -o yaml
apiVersion: v1
data:
password: redhat <<<<<
kind: ConfigMap
metadata:
creationTimestamp: "2026-06-25T06:28:12Z"
name: mysql
namespace: configure
resourceVersion: "21786"
uid: db5484bb-29a0-4295-91e5-00daddab68ad
文件类型
[root@master30 ~ 14:28:27]# echo hello > index.html
[root@master30 ~ 14:29:10]# kubectl create configmap web1 --from-file=./index.html
configmap/web1 created
[root@master30 ~ 14:30:24]# kubectl get configmaps web1 -o yaml
apiVersion: v1
data:
index.html: |
hello <<<<<<<<
kind: ConfigMap
metadata:
creationTimestamp: "2026-06-25T06:29:32Z"
name: web1
namespace: configure
resourceVersion: "21905"
uid: 5e9e9171-388d-4bde-b3bb-a59d778d138a
目录类型
[root@master30 ~ 14:30:28]# echo error > error.html
[root@master30 ~ 14:31:28]# mkdir web2
[root@master30 ~ 14:31:32]# mv error.html index.html web2
[root@master30 ~ 14:31:46]# kubectl create configmap web2 --from-file=./web2
configmap/web2 created
[root@master30 ~ 14:32:07]# kubectl get configmaps web2 -o yaml
apiVersion: v1
data:
error.html: |
error <<<<<<<<<
index.html: |
hello <<<<<<<<<<
kind: ConfigMap
metadata:
creationTimestamp: "2026-06-25T06:32:07Z"
name: web2
namespace: configure
resourceVersion: "22138"
uid: b89f5f62-9df1-4d34-b8b0-23ef97df0d74
ConfigMap 引用
环境变量方式引用
**注意:**环境变量属于特定容器级别。
[root@master30 ~ 14:39:02]# vim pod-cm-env.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql
labels:
name: mysql
spec:
containers:
- image: docker.io/library/mysql:latest
imagePullPolicy: IfNotPresent
name: mysql
ports:
- containerPort: 3306
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
# 原先通过value设置环境变量值
valueFrom:
configMapKeyRef:
name: mysql
key: password
[root@master30 ~ 14:39:58]# kubectl apply -f pod-cm-env.yaml
pod/mysql created
[root@master30 ~ 14:41:03]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql 1/1 Running 0 15s 10.224.137.1 worker31 <none> <none>
[root@master30 ~ 14:41:18]# kubectl exec -it mysql -- bash -c 'echo $MYSQL_ROOT_PASSWORD'
redhat
[root@master30 ~ 14:41:58]# apt install -y mysql-client
[root@master30 ~ 14:46:38]# mysql -uroot -predhat -h 10.224.137.1
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 9.6.0 MySQL Community Server - GPL
Copyright (c) 2000, 2026, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql> quit
Bye
[root@master30 ~ 14:47:17]# kubectl exec -it mysql -- bash
bash-5.1# echo $MYSQL_ROOT_PASSWORD
redhat
bash-5.1#
以 volume 方式引用
**注意:**volumes属于pod级别,通过volumeMounts挂载。
引用整体
[root@master30 ~ 14:48:59]# vim pod-cm-volume-all.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: web
name: web
spec:
containers:
- image: hub.laoma.cloud/library/nginx:latest
imagePullPolicy: IfNotPresent
name: web
volumeMounts:
- name: webcontent
# mountPath值是一个挂载点,将secrete中所有键值对挂载过来
mountPath: "/usr/share/nginx/html"
volumes:
- name: webcontent
configMap:
name: web2
[root@master30 ~ 15:08:50]# kubectl apply -f pod-cm-volume-all.yaml
pod/web created
[root@master30 ~ 15:08:59]# kubectl get pod web -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web 1/1 Running 0 17s 10.224.45.1 worker32 <none> <none>
[root@master30 ~ 15:10:00]# cat ./web2/error.html
error
[root@master30 ~ 15:10:37]# cat ./web2/index.html
hello
[root@master30 ~ 15:10:41]# curl 10.224.45.1
hello
[root@master30 ~ 15:10:51]# curl 10.224.45.1/error.html
error
综合案例:haproxy+web
- 创建一个名称为 haproxy 的pod,使用镜像 haproxy,pod haproxy 的配置文件保存在 configmap 中,通过 volume 方式挂载到 /usr/local/etc/haproxy/haproxy.cfg。将流量转发到pod webapp-1 和 webapp-2。
创建第一个pod,名称为webapp-1,使用镜像nginx。为该pod创建一个cm,名称为webapp-1,该cm保存两个值
[root@master30 ~ 15:14:05]# kubectl create cm webapp-1 --from-literal=index.html="hello webapp-1" --from-literal=error.html="sorry,error"
configmap/webapp-1 created
[root@master30 ~ 15:19:03]# vim pod-webapp-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: webapp-1
spec:
containers:
- name: nginx
image: hub.laoma.cloud/library/nginx:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: config
mountPath: "/usr/share/nginx/html"
readOnly: true
volumes:
- name: config
configMap:
name: webapp-1
[root@master30 ~ 15:19:33]# kubectl apply -f pod-webapp-1.yaml
pod/webapp-1 created
创建第二个pod,名称为webapp-2,使用镜像nginx。为该pod创建一个cm,名称为webapp-2,该cm保存两个值
[root@master30 ~ 15:19:44]# kubectl create cm webapp-2 --from-literal=index.html="hello webapp-2" --from-literal=error.html="sorry,error"
configmap/webapp-2 created
[root@master30 ~ 15:20:07]# vim pod-webapp-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: webapp-2
spec:
containers:
- name: nginx
image: hub.laoma.cloud/library/nginx:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: config
mountPath: "/usr/share/nginx/html"
readOnly: true
volumes:
- name: config
configMap:
name: webapp-2
[root@master30 ~ 15:20:27]# kubectl apply -f pod-webapp-2.yaml
pod/webapp-2 created
创建haproxy配置文件
[root@master30 ~ 15:21:12]# vim haproxy.cfg
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:8080
default_backend servers
backend servers
server app1 10.224.137.2:80 check
server app2 10.224.45.2:80 check
[root@master30 ~ 15:22:09]# kubectl create cm haproxy.cfg --from-file=haproxy.cfg=./haproxy.cfg
configmap/haproxy.cfg created
#创建 HAProxy Pod
[root@master30 ~ 15:22:42]# vim pod-haproxy.yaml
apiVersion: v1
kind: Pod
metadata:
name: haproxy
spec:
containers:
- name: haproxy
image: hub.laoma.cloud/library/haproxy
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: true
volumeMounts:
- name: config
mountPath: "/usr/local/etc/haproxy"
readOnly: true
volumes:
- name: config
configMap:
name: haproxy.cfg
[root@master30 ~ 15:23:29]# kubectl apply -f pod-haproxy.yaml
pod/haproxy created
#查看IP
[root@master30 ~ 15:23:45]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
haproxy 1/1 Running 0 11s 10.224.45.3 worker32 <none> <none>
webapp-1 1/1 Running 0 4m12s 10.224.137.2 worker31 <none> <none>
webapp-2 1/1 Running 0 3m16s 10.224.45.2 worker32 <none> <none>
##轮询访问测试
[root@master30 ~ 15:23:56]# curl 10.224.45.3:8080
hello webapp-1[root@master30 ~ 15:24:07]# curl 10.224.45.3:8080
hello webapp-1[root@master30 ~ 15:24:09]# curl 10.224.45.3:8080
hello webapp-2[root@master30 ~ 15:24:10]#
Secret
Secret 介绍
Secret 是一种包含少量敏感信息的对象,例如密码、令牌或密钥。 这样的信息可能会被放在 Pod 规约中或者镜像中。 使用 Secret 意味着你不需要在应用程序代码中包含机密数据。
创建 Secret 可以独立于使用它们的 Pod, 减少在创建、查看和编辑 Pod 的工作流程中暴露 Secret(及其数据)的风险。 Kubernetes 和在集群中运行的应用程序也可以对 Secret 采取额外的预防措施, 例如避免将敏感数据写入非易失性存储。
Secret 类似于 ConfigMap 但专门用于保存机密数据。
Secret 与ConfigMap的区别在于:Secret对数据编码,ConfigMap不对数据编码。
Secret 类型
- generic:定义键值对,对变量值加密,类型为Opaque。
- docker-registry:用于访问registry仓库的凭据,类型kubernetes.io/dockerconfigjson。
- tls:保存TLS公钥和私钥,类型为Opaque。
Secret 创建
基于键值对
一般用于传递变量值。
[root@master30 ~ 15:44:36]# kubectl create secret generic mysecret1 --from-literal=user=tom --from-literal=password1=redhat --from-literal=password2=redhat
secret/mysecret1 created
[root@master30 ~ 16:37:16]# kubectl get secret
NAME TYPE DATA AGE
mysecret1 Opaque 3 11s
[root@master30 ~ 16:37:27]# kubectl get secret mysecret1 -o yaml
apiVersion: v1
data:
password1: cmVkaGF0
password2: cmVkaGF0
user: dG9t
kind: Secret
metadata:
creationTimestamp: "2026-06-25T08:37:16Z"
name: mysecret1
namespace: configure
resourceVersion: "33563"
uid: fccc93e3-d20b-49b7-a8b2-a3cf691d6ebc
type: Opaque
[root@master30 ~ 16:37:52]# echo -n tom | base64
dG9t
[root@master30 ~ 16:39:33]# echo -n redhat | base64
cmVkaGF0
[root@master30 ~ 16:40:02]# echo -n cmVkaGF0 | base64 -d
redhat
基于普通文件
一般用于传递配置文件。
[root@master30 ~ 16:41:16]# echo -n tom > user
[root@master30 ~ 16:41:33]# echo -n redhat > password1
[root@master30 ~ 16:41:45]# echo -n redhat > password2
[root@master30 ~ 16:41:47]# kubectl create secret generic mysecret2 --from-file=./user --from-file=./password1 --from-file=./password2
secret/mysecret2 created
[root@master30 ~ 16:43:05]# kubectl get secret mysecret2 -o yaml
apiVersion: v1
data:
password1: cmVkaGF0
password2: cmVkaGF0
user: dG9t
kind: Secret
metadata:
creationTimestamp: "2026-06-25T08:43:05Z"
name: mysecret2
namespace: configure
resourceVersion: "34089"
uid: aaf6b4bc-a8c8-4dd8-9df2-38b13fb465d8
type: Opaque
基于键值对内容的文件
[root@master30 ~ 16:48:16]# echo 'user=tom
password1=redhat
password2=redhat' > env.txt
[root@master30 ~ 16:48:33]# kubectl create secret generic mysecret1 --from-env-file=./env.txt
secret/mysecret1 created
[root@master30 ~ 16:49:07]# kubectl get secret mysecret1 -o yaml
apiVersion: v1
data:
password1: cmVkaGF0
password2: cmVkaGF0
user: dG9t
kind: Secret
metadata:
creationTimestamp: "2026-06-25T08:49:07Z"
name: mysecret1
namespace: configure
resourceVersion: "34641"
uid: a5402999-c2b1-4e06-a051-5e454059aa7d
type: Opaque
基于目录
文件名用作key名,文件内容用作value。
[root@master30 ~]# kubectl create secret generic mysecret5 --from-file=./config
secret/my-secret5 created
[root@master30 ~]# kubectl get secrets mysecret5 -o yaml
apiVersion: v1
data:
password1: cmVkaGF0
password2: cmVkaGF0
user: dG9t
kind: Secret
metadata:
......
name: mysecret5
namespace: laoma
resourceVersion: "26687"
selfLink: /api/v1/namespaces/laoma/secrets/mysecret4
uid: 04eccd8b-8686-4856-82c3-0ac697d75746
type: Opaque
基于 yaml 文件
apiVersion: v1
kind: Secret
metadata:
name: mysecret6
type: Opaque
data:
user: dG9t
password1: cmVkaGF0
password2: cmVkaGF0
yaml格式中变量值使用转换后的值。
更多推荐

所有评论(0)