文章目录
- [一、Kubernetes Volume 存储卷](#一、Kubernetes Volume 存储卷)
-
- [1. emptyDir 临时空目录卷](#1. emptyDir 临时空目录卷)
- [2. hostPath 主机路径卷](#2. hostPath 主机路径卷)
- [3. NFS 网络存储卷](#3. NFS 网络存储卷)
- [4. PV & PVC 持久存储架构](#4. PV & PVC 持久存储架构)
-
- [访问模式 accessModes](#访问模式 accessModes)
- [volumeMode 卷模式](#volumeMode 卷模式)
- [回收策略 PersistentVolumeReclaimPolicy](#回收策略 PersistentVolumeReclaimPolicy)
- [NFS 静态 PV 实验](#NFS 静态 PV 实验)
- [二、Kubernetes 配置管理 ConfigMap & Secret](#二、Kubernetes 配置管理 ConfigMap & Secret)
-
- [1. ConfigMap](#1. ConfigMap)
-
- [创建 ConfigMap 三种方式](#创建 ConfigMap 三种方式)
- [Pod 引用 ConfigMap 两种方式](#Pod 引用 ConfigMap 两种方式)
- [综合实验:haproxy + webapp 负载均衡案例](#综合实验:haproxy + webapp 负载均衡案例)
-
- [步骤 1 创建 webapp‑1](#步骤 1 创建 webapp‑1)
- [步骤 2 创建 webapp‑2](#步骤 2 创建 webapp‑2)
- [步骤 3 haproxy 配置与 pod](#步骤 3 haproxy 配置与 pod)
- [2. Secret](#2. Secret)
-
- [创建 secret](#创建 secret)
- [Pod 引用 Secret](#Pod 引用 Secret)
- 综合实验
- 环境清理
- 小结
前言
本篇记录 Kubernetes 存储卷与配置管理相关实验,包含临时卷emptyDir、节点卷hostPath、NFS 网络存储、PV/PVC 持久存储架构,以及 ConfigMap、Secret 配置管理对象。所有案例均为可直接复制运行的实操命令与 yaml。
复习实验
实验 1:Namespace and Contexts 综合实验
- yaml 方式创建命名空间
dev‑ns - 在
dev‑ns创建 nginx pod,镜像nginx:alpine - 使用
kubectl config修改当前上下文默认命名空间为dev‑ns,不使用‑n查看 pod - 安装
kubens切换回default命名空间,查看 dev‑ns 资源必须带‑n参数 - 编写 shell 脚本实现命名空间切换
- 删除
dev‑ns,ns 删除后内部 pod 会自动清除
验证点
kubectl get ns看到 dev‑ns- 不指定‑n 可以看到 nginx pod
- 切到 default 后直接
get pod看不到 dev‑ns 的 pod - 删除 ns,内部资源自动回收
实验 2:多容器 Pod 基础管理
-
创建命名空间
pod‑lab,设置上下文默认 ns 为pod‑lab -
yaml 创建多容器 pod
two‑container‑pod- 容器 web:
nginx:alpine - 容器 client:
busybox:1.36,command 执行sleep 3600保活
- 容器 web:
-
kubectl get pod ‑o wide确认状态2/2 Running,查看 PodIP -
在 client 容器内部
wget 127.0.0.1访问同 Pod 内 nginx -
将 master 节点
/etc/hosts复制到 pod web 容器/tmp/hosts -
查看 nginx 日志;进入 client 执行 hostname
-
删除 pod,观察 Terminating 状态
一、Kubernetes Volume 存储卷
参考官方文档:卷 | Kubernetes
环境准备
kubectl create ns storage
kubectl config set‑context --current --namespace storage
K8s 支持众多 Volume 类型: emptyDir、hostPath、nfs、iscsi、fc、glusterfs、rbd、gitRepo、secret、persistentVolumeClaim、downwardAPI 等。
1. emptyDir 临时空目录卷
特点:Pod 调度到节点时创建;Pod 从节点删除,emptyDir 数据永久丢失;同一 Pod 多个容器之间可以共享该卷。
pod‑with‑emptyDir.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
app: busybox
spec:
volumes:
- name: datavolume
emptyDir: {}
containers:
- name: busybox1
image: hub.laoma.cloud/library/busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
- name: busybox2
image: hub.laoma.cloud/library/busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
实操命令
kubectl apply -f pod-with-emptyDir.yaml
# 在busybox1写文件
kubectl exec busybox -c busybox1 -- touch /data/b1-f1
# busybox2读取共享目录
kubectl exec busybox -c busybox2 -- ls /data
# 登录对应node查看宿主机实际路径
# /var/lib/kubelet/pods/<pod‑uid>/volumes/kubernetes.io~empty‑dir/datavolume
# 删除pod验证数据销毁
kubectl delete pod busybox --force
# node上目录直接消失
用途:Pod 内部多容器临时数据共享、缓存;Pod 销毁数据就没,不能做持久存储。
2. hostPath 主机路径卷
特点:把Node 节点本地文件 / 目录直接挂载进 Pod ;Pod 删除,节点上数据依然保留。 ⚠️ 注意:多节点集群,pod 漂移到其他节点,就读不到旧节点数据;生产尽量少用。
pod‑with‑hostPath.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
app: busybox
spec:
volumes:
- name: datavolume
hostPath:
path: /busyboxdir
containers:
- name: busybox1
image: hub.laoma.cloud/library/busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
- name: busybox2
image: hub.laoma.cloud/library/busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
readOnly: false
kubectl apply -f pod-with-hostPath.yaml
# pod写文件,node节点查看;删除pod,node上文件依旧保留
kubectl exec busybox -c busybox1 -- touch /data/b1-f1
kubectl delete pod busybox --force
# node节点 /busyboxdir 数据还在
3. NFS 网络存储卷
NFS 属于网络共享存储,Pod 删除数据仍然保留,可以多 Pod 共享读写。
环境准备
master 安装 nfs 服务端
apt install -y nfs-kernel-server
mkdir -m 777 /nfsshares
echo hello laoma > /nfsshares/index.html
cat << EOF > /etc/exports
/nfsshares *(rw)
EOF
systemctl restart nfs-server.service
所有 worker 节点安装 nfs 客户端
apt install -y nfs-common
pod‑with‑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"
kubectl apply -f pod-with-nfs.yaml
kubectl get pod -o wide
curl <pod‑ip>
# 在pod内新建文件,master的/nfsshares可以看到;删除pod,nfs服务器数据不会丢失
kubectl delete pod nginx --force
4. PV & PVC 持久存储架构
PV(PersistentVolume):集群级别资源 ,代表后端真实存储,由集群管理员创建。 PVC(PersistentVolumeClaim):命名空间级别资源,用户存储申请;K8s 自动寻找匹配 PV 完成绑定。
访问模式 accessModes
| 模式 | 说明 | 缩写 |
|---|---|---|
| ReadWriteOnce | 卷可以被一个节点读写挂载,同节点多 pod 可以共用 | RWO |
| ReadOnlyMany | 多节点只读挂载 | ROX |
| ReadWriteMany | 多节点同时读写挂载 | RWX |
| ReadWriteOncePod | 仅单个 Pod 读写(1.22+) | RWOP |
NFS 同时支持 RWO/ROX/RWX;hostPath 仅支持 RWO。
volumeMode 卷模式
Filesystem默认,作为文件系统挂载到目录Block原始块设备,不做文件系统格式化,给应用直接使用块设备
回收策略 PersistentVolumeReclaimPolicy
- Retain(默认)保留 :删除 PVC 后,PV 状态变为 Released,保留数据;需要手动清理
claimRef才能重新绑定新 PVC。 - Recycle:已经废弃。
- Delete:删除 PVC 同时删除后端存储资产;NFS 不支持 Delete,会报错。
关键点:当 PV 为 Released 状态,里面还残留上一个 PVC 的 claimRef 引用,直接新建 PVC 无法绑定,需要 kubectl edit pv 删除 claimRef 字段。
NFS 静态 PV 实验
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
pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: webclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
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
操作命令
kubectl apply -f pv.yaml
kubectl apply -f pvc.yaml
# 查看状态,PVC状态Bound代表绑定成功
kubectl get pv,pvc
kubectl apply -f pod-with-pvc.yaml
kubectl get pod -o wide
curl <pod‑ip>
kubectl delete pod web --force
# 删除pod,NFS后端数据依旧保留
PV‑PVC 匹配规则:
- accessModes 要满足 PVC 最低要求
- 存储容量大于等于 PVC 申请大小
- StorageClassName 必须一致(如果设置)
环境清理
kubectl delete ns storage
二、Kubernetes 配置管理 ConfigMap & Secret
ConfigMap:存放普通非敏感配置,明文;上限 1MiB。 Secret:存放密码、密钥等敏感数据,内部 base64 编码,不是加密,只是简单编码。
环境准备
kubectl create ns configure
kubectl config set‑context --current --namespace configure
1. ConfigMap
创建 ConfigMap 三种方式
-
‑‑from‑literal键值对 -
‑‑from‑file文件 -
‑‑from‑file整个目录字面量键值对
kubectl create configmap mysql --from‑literal=password=redhat
文件方式
echo Hello World > index.html
kubectl create configmap web1 --from‑file=./index.html目录方式
mkdir web2
mv index.html error.html web2
kubectl create configmap web2 --from‑file=./web2
Pod 引用 ConfigMap 两种方式
-
环境变量 configMapKeyRef pod‑with‑env‑from‑configmap.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql
labels:
name: mysql
spec:
containers:- image: hub.laoma.cloud/library/mysql:latest
imagePullPolicy: IfNotPresent
name: mysql
ports:- containerPort: 3306
name: mysql
env: - name: MYSQL_ROOT_PASSWORD
valueFrom:
configMapKeyRef:
name: mysql
key: password
- containerPort: 3306
- image: hub.laoma.cloud/library/mysql:latest
-
Volume 挂载方式(最常用)
configMap 作为卷挂载:key = 文件名,value = 文件内容。支持整体挂载,也支持指定单个 key 挂载;configMap 更新,挂载卷内容会自动同步更新。
pod‑with‑volume‑from‑configmap.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: "/usr/share/nginx/html"
volumes:
- name: webcontent
configMap:
name: web2
单个 key 挂载两种写法:items 方式 /subPath 方式。注意:subPath 挂载的文件不会自动热更新 configmap。
综合实验:haproxy + webapp 负载均衡案例
需求
- haproxy pod,配置文件存放在 configmap,volume 挂载到
/usr/local/etc/haproxy/haproxy.cfg,转发流量到 webapp‑1、webapp‑2。 - webapp‑1、webapp‑2 为 nginx pod,使用 configmap 提供 index.html、error.html 页面内容。
步骤 1 创建 webapp‑1
kubectl create cm webapp‑1 --from‑literal=index.html="hello webapp‑1" --from‑literal=error.html="sorry, error."
pod‑webapp‑1.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: webapp‑1
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
kubectl apply -f pod-webapp-1.yaml
步骤 2 创建 webapp‑2
kubectl create cm webapp‑2 --from‑literal=index.html="hello webapp‑2" --from‑literal=error.html="sorry, error."
pod‑webapp‑2.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: webapp‑2
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
kubectl apply -f pod-webapp-2.yaml
步骤 3 haproxy 配置与 pod
获取 webapp‑1、webapp‑2 的 PodIP 填入 haproxy.cfg backend server 地址。
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.xx.xx:80 check
server app2 10.224.xx.xx:80 check
kubectl create cm haproxy.cfg --from‑file=haproxy.cfg=./haproxy.cfg
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
kubectl apply -f pod-haproxy.yaml
# 访问haproxy podIP:8080,轮询返回webapp‑1与webapp‑2页面
curl http://<haproxy‑pod‑ip>:8080
2. Secret
Secret 存储敏感信息,数据内部是 base64 编码,不是加密,仅简单编码,不能当做加密使用。
Secret 类型:
- generic (Opaque):通用键值、文件。
- docker‑registry:镜像仓库登录凭据。
- tls:存放证书私钥。
创建 secret
# 字面量generic
kubectl create secret generic mysecret1 --from‑literal=user=tom --from‑literal=password1=redhat
# 文件方式
kubectl create secret generic mysecret2 --from‑file=./user --from‑file=./password1
# docker‑registry镜像仓库凭据
kubectl create secret docker‑registry registry --docker‑username=laoma --docker‑password=redhat --docker‑email=admin@laoma.cloud --docker‑server=registry.laoma.cloud
# tls证书密钥secret
openssl genrsa -out www.key 2048
openssl req -new -key www.key -out www.csr -subj "/C=CN/ST=JS/L=NJ/O=LM/OU=DEVOPS/CN=www.laoma.cloud"
openssl x509 -req -days 3650 -in www.csr -signkey www.key -out www.crt
kubectl create secret tls www‑tls --cert=./www.crt --key=./www.key
Pod 引用 Secret
-
环境变量 secretKeyRef
env:
‑ name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret1
key: password1 -
Volume 挂载 secret 卷
volumes:
‑ name: webcontent
secret:
secretName: web
volumeMounts:
‑ name: webcontent
mountPath: "/usr/share/nginx/html"
secret 卷默认文件权限 644,可以通过
defaultMode设置全局权限;items 可以单独设置每个 key 文件 mode 权限。secret 卷挂载同样支持配置热更新。
综合实验
使用 mysql+wordpress 部署 blog:
- mysql 密码、站点证书存放在 secret;
- nginx 虚拟主机 vhost 配置文件由 configmap 提供。
环境清理
kubectl delete ns configure
小结
- 临时存储:
emptyDir,Pod 删除数据丢失,用于 Pod 内多容器共享临时数据。 - 节点本地存储:
hostPath,绑定节点目录,多节点环境 pod 漂移会出现数据不一致。 - 网络存储 NFS,实现跨节点持久共享。
- PV‑PVC 实现存储与业务解耦,管理员维护 PV,业务开发只申请 PVC。
- ConfigMap 管理普通配置,Secret 管理敏感信息(仅 base64 编码,不是加密)。
- ConfigMap/Secret 两种注入方式:环境变量、volume 挂载;subPath 挂载不支持热更新,直接 volume 整体挂载支持热更新。