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

相关推荐
i***39582 小时前
ShardingSphere-jdbc 5.5.0 + spring boot 基础配置 - 实战篇
java·spring boot·后端
E***q5392 小时前
后端服务限流实现,Spring Cloud Alibaba Sentinel
java·开发语言·sentinel
k***21602 小时前
从零到上线:Node.js 项目的完整部署流程(包含 Docker 和 CICD)
docker·容器·node.js
Jeremy爱编码2 小时前
手写LRU 缓存
java·spring·缓存
期待のcode2 小时前
springboot的热部署和静态资源映射规则
java·spring boot·后端
橘子海全栈攻城狮2 小时前
【源码+文档+调试讲解】实验室耗材管理系统springboot 094
java·开发语言·spring boot·后端·spring
东东__net2 小时前
java项目管理工具Maven
java·maven
范纹杉想快点毕业2 小时前
《嵌入式硬件从入门到精通:电源 / 模电 / 数电 / 通信核心全解析》
java·开发语言·数据库·单片机·嵌入式硬件