K8s的配置存储与实战

配置与存储:应用"吃喝"的保障

  • ConfigMap:存储配置文件

  • Secret:存放密码或密钥

  • PV/PVC:持久化存储的资源与资源绑定

K8s存储:临时存储与持久化存储

  • 临时存储

    • emptyDir:在同一个Pod内的不同容器间共享数据,和Pod生命周期相同,Pod创建时创建,Pod销毁时销毁,临时存储;

    • configMap:(配置映射)存储配置文件(如:my.cnf/redis.conf/nginx.conf);

    • secret:存储敏感数据(如密码、私钥、证书等);

    • downwardAPI:存储Pod与容器元数据(如名称、IP)。

|--------------------------|--------------|--------------|--------------|
| 存储类型 | 生命周期 | 共享范围 | 典型用途 |
| emptyDir | 与 Pod 一致 | 同一 Pod 内容器 | 临时数据共享 |
| configMap | 独立于 Pod | 跨 Pod 配置共享 | 配置文件挂载 |
| secret | 独立于 Pod | 跨 Pod 敏感信息 | 密码、证书挂载 |
| PersistentVolume | 独立于 Pod | 跨 Pod/命名空间 | 持久化数据(如数据库) |

  • 持久化存储:将数据存储到磁盘空间;

    • hostpath :让Pod中容器直接挂载当前Node节点的目录;

    • PV :持久化存储卷,用于关联存储介质(后台存储),相当于"硬盘";每个PV都有权限、容量;

    • PVC :在Pod中设置的持久化存储需求,启动Pod时,根据需求自动匹配相应的PV,从而实现数据目录的映射;在容器中的目录上挂载存储介质;

    • StorageClass :存储类,根据PVC的需求自动创建PV,使用时更加方便快捷。

|----------------|-----------------------------------------|---------------------------------------|
| 维度 | PV (Persistent Volume) | PVC (Persistent Volume Claim) |
| 角色定位 | 集群中的"物理硬盘" 存储资源本身 | 用户的"硬盘申请单" 存储资源请求 |
| 创建者 | 集群管理员创建 | 应用开发者/用户创建 |
| 作用范围 | 集群级别资源 跨Namespace可用 | Namespace级别资源 仅在当前Namespace有效 |
| 核心功能 | 定义具体存储属性: - 存储类型(NFS/本地等) - 容量大小 - 访问模式 | 声明存储需求: - 需要多大容量 - 读写权限要求 - 存储类选择 |
| 生命周期状态 | Available → Bound → Released → Failed | Pending → Bound → Deleted |
| 绑定关系 | 被PVC绑定使用 | 主动绑定到合适的PV |
| 使用方式 | Pod通过PVC间接使用PV | Pod直接引用PVC名称 |

工作流程简化:

管理员创建 PV → 用户创建 PVC → 系统自动绑定 → Pod 使用 PVC

  • 存储方式:

    • NFS

    • CEPH

    • MINIO

    • ......

存算分离:

  • 将存储与运算分离,集中存储,方便管理;

存储实战

emptyDir

# 示例一:基础共享(磁盘介质)

# 两个容器通过磁盘介质的emptyDir共享日志文件

vim 13-emptydir.yaml

apiVersion: v1

kind: Pod

metadata:

name: log-share-pod

spec:

volumes:

  • name: log-storage

emptyDir:

sizeLimit: 512Mi

containers:

  • name: app

image: busybox:latest

command: "/bin/sh", "-c", "mkdir -p /var/log/app \&\& while true; do echo \\"$(date) 访问日志: ...\\" \>\> /var/log/app/app.log; sleep 3; done"

volumeMounts:

  • name: log-storage

mountPath: /var/log/app

  • name: log-collector

image: busybox:latest

command: "/bin/sh", "-c", "tail -f /logs/app.log"

volumeMounts:

  • name: log-storage

mountPath: /logs

# 创建Pod,然后查看log-collector容器的日志输出

kubectl apply -f 13-emptydir.yaml

# 通过路径验证两个容器中的文件是否相同,如果两个MD5值相同证明文件相同

在app容器中检查文件

kubectl exec log-share-pod -c app -- md5sum /var/log/app/app.log

在log-collector容器中检查文件

kubectl exec log-share-pod -c log-collector -- md5sum /logs/app.log

示例二:内存介质(tmpfs)+ 只读权限

vim 14-emptydir-tmpfs.yaml

apiVersion: v1

kind: Pod

metadata:

name: cache-share-pod

spec:

volumes:

  • name: cache-volume

emptyDir:

medium: Memory

sizeLimit: 256Mi

containers:

  • name: cache-generator

image: busybox:latest

command: "/bin/sh", "-c", "while true; do echo \\"缓存数据: $(date +%s)\\" \> /cache/data; sleep 5; done"

volumeMounts:

  • name: cache-volume

mountPath: /cache

  • name: cache-reader

image: busybox:latest

command: "/bin/sh", "-c", "while true; do echo \\"读取到: $(cat /read-only-cache/data)\\"; sleep 5; done"

volumeMounts:

  • name: cache-volume

mountPath: /read-only-cache

readOnly: true

# 创建Pod

kubectl apply -f 14-emptydir-tmpfs.yaml

# 查看Pod状态

kubectl get pod cache-share-pod

## 验证内存emptyDir功能

# 查看cache-generator容器的日志(写入端)(什么都不会出现是正常的,因为输出被重定向到了文件,可以通过检查文件内容来验证数据是否正确写入和共享)

kubectl logs cache-share-pod -c cache-generator -f

# 查看cache-reader容器的日志(读取端)

kubectl logs cache-share-pod -c cache-reader -f

## 验证只读权限

# 在cache-reader容器中尝试写入(应该失败)

kubectl exec -it cache-share-pod -c cache-reader -- sh -c "echo '测试写入' > /read-only-cache/test.txt"

# 在cache-generator容器中尝试写入(应该成功)

kubectl exec -it cache-share-pod -c cache-generator -- sh -c "echo '测试写入' > /cache/test.txt && echo '写入成功'"

Configmap

vim 15-emptydir-configmap.yaml

apiVersion: v1

kind: ConfigMap

metadata:

name: app-config01

data:

app.conf: |

# 应用基础配置

app.name=my-application

app.version=1.0.0

server.port=8080

debug.mode=false

logback.xml: |

<?xml version="1.0" encoding="UTF-8"?>

<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<pattern>%d{yyyy-MM-dd HH:mm:ss} - %msg%n</pattern>

</encoder>

</appender>

<root level="INFO">

<appender-ref ref="STDOUT" />

</root>

</configuration>

environment.properties: |

# 环境配置

database.url=jdbc:postgresql://localhost:5432/testdb

cache.enabled=true

feature.toggle.new-ui=true

# 应用ConfigMap

kubectl apply -f 15-emptydir-configmap.yaml

# 查看ConfigMap,或者可以用describe验证创建

kubectl get configmaps

# 创建Pod

vim 16-dapi-pod-configmap.yaml

apiVersion: v1

kind: Pod

metadata:

name: dapi-test-pod

spec:

containers:

  • name: test-container

image: busybox:latest

command: "/bin/sh", "-c", "sleep 3600"

volumeMounts:

  • name: app-config

mountPath: /etc/app-config/

volumes:

  • name: app-config

configMap:

name: app-config01

# 应用Pod

kubectl apply -f 16-dapi-pod-configmap.yaml

# 查看Pod状态

kubectl get pod

## 验证ConfigMap挂载

# 查看Pod日志

kubectl logs dapi-test-pod

# 进入Pod验证文件

root@master:~/yaml# kubectl exec -it dapi-test-pod -- /bin/sh

# 然后就变成

/ #

# 在容器内检查

ls /etc/app-config/

cat /etc/app-config/app.conf

cat /etc/app-config/logback.xml

cat /etc/app-config/environment.properties

# 退出容器

exit


Secret

++++++1. Service Account Secret(自动创建)++++++

vim 17-service-account-secret-pod.yaml

apiVersion: v1

kind: Pod

metadata:

name: sa-test-pod

spec:

automountServiceAccountToken: true #显式启用

containers:

  • name: test-container

image: busybox:latest

command: "/bin/sh", "-c", "echo '检查Service Account目录...'; sleep 3; find /run -name '\*serviceaccount\*' 2\>/dev/null \|\| find /var -name '\*serviceaccount\*' 2\>/dev/null \|\| echo '未找到serviceaccount目录'; sleep 3600"

# 创建Pod并等待Pod运行起来

kubectl apply -f 17-service-account-secret-pod.yaml

kubectl get pod

# 进入Pod里验证

kubectl exec -it sa-test-pod -- /bin/sh

/ # find / -name "*serviceaccount*" 2>/dev/null

显示 /var/run/secrets/kubernetes.io/serviceaccount

/ # ls /var/run/secrets/kubernetes.io/serviceaccount

显示 ca.crt namespace token

/ # cat /var/run/secrets/kubernetes.io/serviceaccount/namespace

显示 default/ # 然后输入 exit 退出即可

++++++2. Opaque Secret(存储密码密钥)++++++

## 创建Opaque Secret

# 通过命令行创建 Secret

kubectl create secret generic app-secrets \

--from-literal=username=admin \

--from-literal=password=secret123 \

--from-literal=database-url="db://admin:secret@db.example.com/app"

# 验证Secret内容

kubectl get secret app-secrets -o jsonpath='{.data}' | base64 -d

显示 base64: invalid input

# # 创建使用Opaque Secret的Pod

cat > 19-opaque-test-pod.yaml << 'EOF'

apiVersion: v1

kind: Pod

metadata:

name: opaque-test-pod

spec:

containers:

  • name: test-container

image: busybox:latest

command: "/bin/sh", "-c", "sleep 3600"

env:

  • name: USERNAME

valueFrom:

secretKeyRef:

name: app-secrets

key: username

  • name: PASSWORD

valueFrom:

secretKeyRef:

name: app-secrets

key: password

volumeMounts:

  • name: secret-volume

mountPath: /etc/secrets

readOnly: true

volumes:

  • name: secret-volume

secret:

secretName: app-secrets

EOF

kubectl apply -f 19-opaque-test-pod.yaml

++++++3. Docker Registry Secret(私有仓库认证++++** ++++)(kubernetes.io/dockerconfigjson 类型++++ ++++)++++++**

## 创建Docker Registry Secret

# 创建用于私有Docker仓库的secret

kubectl create secret docker-registry my-registry-key \

--docker-server=192.168.57.200:8099 \

--docker-username=admin \

--docker-password=password123 \

--docker-email=admin@example.com

# 查看创建的secret 详情

kubectl get secret my-registry-key -o yaml

# 或者查看类型

kubectl get secret my-registry-key -o jsonpath='{.type}'

# 输出会是: kubernetes.io/dockerconfigjson

## 创建使用Registry Secret的Pod

cat > 18-registry-test-pod.yaml << EOF

apiVersion: v1

kind: Pod

metadata:

name: registry-test-pod

spec:

containers:

  • name: test-container

image: busybox:latest

command: "/bin/sh", "-c", "echo '这个Pod使用了Docker Registry Secret'; sleep 3600"

imagePullSecrets:

  • name: my-registry-key

EOF

# 创建Pod

kubectl apply -f 18-registry-test-pod.yaml

## 验证

# 查看所有secret

kubectl get secrets

# 查看各个Pod状态

kubectl get pods

# 进入Pod查看详细内容

kubectl exec -it opaque-test-pod -- /bin/sh

# 在容器内查看:

env | grep USERNAME

env | grep PASSWORD

ls -la /etc/secrets/

cat /etc/secrets/database-url

exit

### 清理资源

# 删除所有测试资源

kubectl delete pod sa-test-pod opaque-test-pod registry-test-pod

kubectl delete secret app-secrets my-registry-key


K8s存储之volume

卷的类型:

  • emptyDir:与pod的生命周期是一致的,它的最实际实用是提供Pod内多容器的volume数据共享;

    • 用法有:

    • 1、暂存空间,例如用于基于磁盘的合并排序

    • 2、用作长时间计算崩溃恢复时的检查点

    • 3、Web服务器容器提供数据时,保存内容管理器容器提取的文件

  • hostPath:将主机文件系统上的某个目录挂载到 Pod 中,可以使用本地节点的磁盘资源;

    • 具有持久化能力,但仅限固定节点。

    • 适合需要在特定节点上存储数据的场景,daemonset控制器。

    • 存储卷只能在节点本地使用,无法跨节点共享(缺点)。

    • hostPath 卷的使用需要谨慎,因为它会与节点的文件系统直接交互,可能引发数据一致性和安全性问题。

  • PersistentVolume(PV) & PersistentVolumeClaim(PVC)

  • StorageClass

emptyDir

## 验证两个容器如何通过共享卷来交换数据(容器间的数据共享和通信)

vim 20-volume-pod.yaml

apiVersion: v1

kind: Pod

metadata:

name: test-volume

spec:

containers:

  • name: volume-pod-1

image: 192.168.57.200:8099/library/nginx:latest

imagePullPolicy: IfNotPresent

volumeMounts:

  • mountPath: /test-1

name: volume

  • name: volume-pod-2

image: 192.168.57.200:8099/library/busybox:latest

imagePullPolicy: IfNotPresent

command: "/bin/sh", "-c", "sleep 600"

volumeMounts:

  • mountPath: /test-2

name: volume

volumes:

  • name: volume

emptyDir: {} # 必须指定卷类型

kubectl apply -f 20-volume-pod.yaml

# 进入busybox容器验证共享卷

kubectl exec -it test-volume -c volume-pod-2 -- /bin/sh

# 在busybox容器中创建文件 → 测试写入功能:

/ # ls -la /test-2/

total 8

drwxrwxrwx 2 root root 4096 Nov 14 03:26 .

drwxr-xr-x 1 root root 4096 Nov 14 03:26 ..

/ # echo "hello from pod-2" > /test-2/shared-file.txt

/ # exit

# 进入nginx容器验证

kubectl exec -it test-volume -c volume-pod-1 -- /bin/bash

# 在nginx容器中读取文件 → 验证共享是否成功:

root@test-volume:/# ls -la /test-1/

total 12

drwxrwxrwx 2 root root 4096 Nov 14 03:28 .

drwxr-xr-x 1 root root 4096 Nov 14 03:26 ..

-rw-r--r-- 1 root root 17 Nov 14 03:28 shared-file.txt

root@test-volume:/# cat /test-1/shared-file.txt

应该能看到 hello from pod-2

root@test-volume:/# exit

后续实验与之前相似就不做了。


补充hostPath

# 创建Pod YAML文件

vim 21-hostpath-pod.yaml

apiVersion: v1

kind: Pod

metadata:

name: hostpath

spec:

containers:

  • name: test-container

image: 192.168.57.200:8099/library/busybox:latest

command: "/bin/sh", "-c", "sleep 3600"

volumeMounts:

  • mountPath: /host-logs

name: host-volume

volumes:

  • name: host-volume

hostPath:

path: /tmp/hostpath-test

type: DirectoryOrCreate

kubectl apply -f 21-hostpath-pod.yaml

# 查看Pod状态

kubectl get pods

# 查看Pod是在哪个节点上执行的,方便一会儿验证

kubectl get pod hostpath -o wide

# 进入容器

kubectl exec -it hostpath -- /bin/sh

# 在容器内操作

ls -la /host-logs/

echo "Hello from container!" > /host-logs/test-file.txt

cat /host-logs/test-file.txt

exit

# 在主机上验证(在node节点上执行)

ls -la /tmp/hostpath-test/

cat /tmp/hostpath-test/test-file.txt

相关推荐
咩咩啃树皮10 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
鱟鲥鳚10 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
大模型码小白11 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司12 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地13 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun31415913 小时前
TCP超时重传机制是为了解决什么问题?
java
莫逸风16 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
生活爱好者!16 小时前
我把NAS当作下载机,docker一键部署qb
运维·docker·容器
z1234567898616 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
yaoxin52112317 小时前
470. Java 反射 - Member 接口与 AccessFlag
java·开发语言·python