【K8s 小白必懂】ConfigMap 到底是个啥?从概念到 MySQL 实战。
目录
方式 2:用 --from-literal 命令行创建(适合简单键值对)
方式 3:用 --from-file 从文件创建(适合直接导入配置文件)
方式 1:Volume 挂载(把 ConfigMap 变成容器内的文件)
实战示例:把 index.html 挂载到 httpd 容器
方式 2:环境变量注入(把 ConfigMap 变成容器内的环境变量)
五、实战:用 ConfigMap 给 MySQL 做初始化(你的项目场景)
步骤 2:编写 MySQL Deployment,挂载 ConfigMap
一、先搞懂:ConfigMap 到底是个什么东西?
1. 核心概念(一句话说清)
ConfigMap 是 Kubernetes 中用来「存储配置信息」的核心资源,它的本质是一个「键值对(key-value)存储」,专门用来把应用的配置和容器镜像解耦,让同一个镜像可以在不同环境(开发 / 测试 / 生产)中复用不同配置。
2. 为什么需要 ConfigMap?
如果没有 ConfigMap,你会遇到这些痛点:
- 把配置硬编码在镜像里:改个配置就要重新打包镜像、重新部署,效率极低
- 配置和代码混在一起:不同环境(开发 / 生产)的数据库地址、端口不一样,要维护多套镜像
- 敏感信息泄露:把密码、密钥写死在代码里,安全风险极高
ConfigMap 完美解决了这些问题:配置和镜像彻底分离,配置统一由 K8s 管理,容器运行时动态注入配置。
3. 核心特性
- 存储格式:支持纯文本、JSON、YAML、配置文件等任意格式,本质都是键值对
- 大小限制:单个 ConfigMap 最大 1MiB,不适合存大量数据(大文件用存储卷)
- 作用范围:默认属于某个命名空间,只能在同命名空间的 Pod 中使用
- 使用方式:两种核心用法 ——挂载为文件到容器内、注入为环境变量
- 非加密存储:ConfigMap 不加密,敏感信息(密码、密钥)必须用 Secret,不能用 ConfigMap
二、ConfigMap 能干什么?(核心使用场景)
ConfigMap 几乎覆盖了容器化应用的所有配置需求,最常用的 3 个场景:
- 存储应用配置文件:比如 Nginx 的
nginx.conf、MySQL 的初始化 SQL、SpringBoot 的application.yml,把配置文件存进 ConfigMap,挂载到容器内直接生效 - 注入环境变量:把配置项作为环境变量注入容器,应用启动时直接读取,比如数据库地址、端口、日志级别
- 容器启动命令参数:把配置作为容器启动命令的参数,动态调整容器行为
三、ConfigMap 3 种创建方式(小白也能上手)
方式 1:用 YAML 文件创建(最常用,适合复杂配置)
这是生产环境最推荐的方式,适合存储多行配置、配置文件等复杂内容。
# 1. 编写 ConfigMap YAML 文件
cat > game-demo.yaml <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
name: game-demo # ConfigMap 名称,后续 Pod 要引用这个名字
data:
# 键值对 1:单行配置
player_initial_lives: "3"
# 键值对 2:单行配置
ui_properties_file_name: "tomcat"
# 键值对 3:多行配置(用 | 符号,保留换行格式)
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
EOF
# 2. 应用 YAML 创建 ConfigMap
kubectl create -f game-demo.yaml
# 3. 验证创建成功
kubectl get configmaps
kubectl describe configmaps game-demo
执行结果说明:
kubectl get configmaps会看到名为game-demo的 ConfigMap,DATA列显示有 3 个键kubectl describe可以查看 ConfigMap 里的所有键值对详情
方式 2:用 --from-literal 命令行创建(适合简单键值对)
适合快速创建少量简单配置,直接在命令行写键值对,不用写 YAML。
# 创建名为 player 的 ConfigMap,包含 2 个键值对
kubectl create configmap player \
--from-literal=username=player \
--from-literal=age=18
# 验证
kubectl describe configmaps player
特点:简单快捷,适合临时创建、少量配置,不适合多行内容。
方式 3:用 --from-file 从文件创建(适合直接导入配置文件)
适合把本地已有的配置文件直接导入 ConfigMap,不用手动复制粘贴内容。
# 1. 先创建一个本地文件 index.html
echo "hello world!" > index.html
# 2. 从文件创建 ConfigMap,键名默认就是文件名
kubectl create configmap indexcontent --from-file=index.html
# 3. 验证(可以看到键名是 index.html,值是文件内容)
kubectl describe configmaps indexcontent
进阶用法:指定自定义键名
kubectl create configmap indexcontent --from-file=custom-index=index.html
四、ConfigMap 2 种核心使用方式(实战必学)
方式 1:Volume 挂载(把 ConfigMap 变成容器内的文件)
这是最常用的方式,适合把配置文件、脚本等内容挂载到容器指定目录,容器直接读取文件。
实战示例:把 index.html 挂载到 httpd 容器
# 1. 先创建包含 index.html 的 ConfigMap(前面已经创建过 indexcontent)
# 2. 编写 Pod YAML,挂载 ConfigMap
cat > cmvolume.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: configmapvolume
labels:
app: configmaptest
spec:
containers:
- name: test
image: httpd
imagePullPolicy: IfNotPresent
# 容器内挂载点
volumeMounts:
- name: index # 必须和下面 volumes 里的 name 一致
mountPath: /usr/local/apache2/htdocs # httpd 默认网页根目录
# 定义存储卷,关联 ConfigMap
volumes:
- name: index # 自定义卷名,和 volumeMounts 对应
configMap:
name: indexcontent # 要挂载的 ConfigMap 名称
EOF
# 3. 应用 Pod
kubectl create -f cmvolume.yaml
# 4. 验证:进入容器查看文件
kubectl exec -it configmapvolume -- cat /usr/local/apache2/htdocs/index.html
执行结果:容器内 /usr/local/apache2/htdocs/ 目录下会生成 index.html 文件,内容就是 ConfigMap 里的 hello world!,httpd 启动后直接访问就能看到内容。
核心原理:
volumes段:把 ConfigMap 定义为一个存储卷,给卷起一个名字(比如index)volumeMounts段:把这个卷挂载到容器的指定目录,容器内就会生成对应的文件- 键名就是文件名,键值就是文件内容
方式 2:环境变量注入(把 ConfigMap 变成容器内的环境变量)
适合把配置项作为环境变量注入容器,应用启动时通过环境变量读取配置,比如数据库密码、端口等。
实战示例:给 MySQL 容器注入 root 密码
# 1. 创建包含密码的 ConfigMap
kubectl create configmap mysqlpw \
--from-literal=password=ABCabc123
# 2. 编写 Pod YAML,注入环境变量
cat > cmenv.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: mysql
spec:
containers:
- name: mysqlname
image: mysql
imagePullPolicy: IfNotPresent
env:
# 定义环境变量 MYSQL_ROOT_PASSWORD
- name: MYSQL_ROOT_PASSWORD
valueFrom:
configMapKeyRef:
name: mysqlpw # 引用的 ConfigMap 名称
key: password # 引用 ConfigMap 中的哪个键
EOF
# 3. 应用 Pod
kubectl create -f cmenv.yaml
# 4. 验证:进入容器查看环境变量
kubectl exec -it mysql -- env | grep MYSQL_ROOT_PASSWORD
执行结果:容器内会生成 MYSQL_ROOT_PASSWORD=ABCabc123 环境变量,MySQL 镜像会自动读取这个环境变量作为 root 密码,启动后直接用这个密码登录即可。
五、实战:用 ConfigMap 给 MySQL 做初始化(你的项目场景)
这是我的项目中实际用到的场景,我把完整流程拆解清楚,让你彻底明白每一步的作用。
需求背景
我们要在 K8s 中部署 MySQL 8.0,要求:
- 第一次启动时自动创建
hr_db数据库 - 自动创建
departments(部门表)和employees(员工表) - 自动插入测试数据
- 配置和镜像分离,不用重新打包镜像
核心原理
MySQL 官方镜像有一个特性:容器第一次启动时,会自动执行 /docker-entrypoint-initdb.d/ 目录下的所有 .sql、.sh 文件。我们只需要把初始化 SQL 存进 ConfigMap,然后把 ConfigMap 挂载到这个目录,MySQL 就会自动执行。
步骤 1:编写 ConfigMap(存储初始化 SQL)
yaml
# apps/mysql/mysql-deployment.yaml 中的 ConfigMap 部分
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-init-scripts # ConfigMap 名称,后续要引用
namespace: ai-services
data:
# 键名 init.sql,值是完整的初始化 SQL(用 | 保留换行)
init.sql: |
CREATE DATABASE IF NOT EXISTS hr_db;
USE hr_db;
-- 创建部门表
CREATE TABLE IF NOT EXISTS departments (
dept_id INT PRIMARY KEY,
dept_name VARCHAR(50) NOT NULL,
location VARCHAR(50)
);
-- 创建员工表
CREATE TABLE IF NOT EXISTS employees (
emp_id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
role VARCHAR(50),
salary DECIMAL(10, 2),
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES departments(dept_id)
);
-- 插入测试数据
INSERT INTO departments VALUES (1, 'Engineering', 'Building A'), (2, 'Sales', 'Building B'), (3, 'HR', 'Building A');
INSERT INTO employees VALUES
(101, 'Alice', 'Engineer', 90000, 1),
(102, 'Bob', 'Manager', 120000, 1),
(103, 'Charlie', 'Salesperson', 70000, 2),
(104, 'David', 'Recruiter', 60000, 3),
(105, 'Eve', 'Engineer', 95000, 1);
说明:
- 这里的
init.sql就是键名,后续挂载到容器后,会生成/docker-entrypoint-initdb.d/init.sql文件 - 把 SQL 写在 ConfigMap 里,而不是硬编码在镜像里,后续改 SQL 只需要改 ConfigMap,不用重新部署 MySQL
步骤 2:编写 MySQL Deployment,挂载 ConfigMap
# apps/mysql/mysql-deployment.yaml 中的 Deployment 部分
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: ai-services
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: "native"
- name: MYSQL_DATABASE
value: "hr_db"
ports:
- containerPort: 3306
volumeMounts:
# 1. 挂载数据存储卷(持久化 MySQL 数据)
- name: mysql-storage
mountPath: /var/lib/mysql
# 2. 挂载 ConfigMap 卷,到 MySQL 初始化目录
- name: init-scripts
mountPath: /docker-entrypoint-initdb.d
volumes:
# 1. 数据存储卷(PVC,持久化数据)
- name: mysql-storage
persistentVolumeClaim:
claimName: mysql-pvc
# 2. ConfigMap 卷,关联我们创建的 mysql-init-scripts
- name: init-scripts
configMap:
name: mysql-init-scripts
核心挂载链路拆解(你之前困惑的点):
- ConfigMap 定义:
metadata.name: mysql-init-scripts(给 ConfigMap 起名字) - volumes 段:
- name: init-scripts+configMap.name: mysql-init-scripts(把 ConfigMap 定义为一个存储卷,卷名init-scripts) - volumeMounts 段:
- name: init-scripts+mountPath: /docker-entrypoint-initdb.d(把这个卷挂载到容器的/docker-entrypoint-initdb.d目录) - 最终效果:容器内
/docker-entrypoint-initdb.d/目录下生成init.sql文件,MySQL 第一次启动自动执行这个 SQL,完成建库、建表、插数据
步骤 3:通过 Argo CD 部署(GitOps 方式)
把配置提交到 Git 仓库,Argo CD 自动同步到 K8s 集群:
bash
运行
cd ~/sre-agent-gitops
git add apps/mysql/
git commit -m "feat: Add MySQL deployment with HR schema"
git push origin main
# 创建 Argo CD Application,让 Argo 接管 MySQL
cat > ~/mysql-argocd.yaml <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: mysql-hr
namespace: argocd
spec:
project: default
source:
repoURL: 'https://github.com/Wang2978266434/sre-agent-gitops'
targetRevision: HEAD
path: apps/mysql
destination:
server: 'https://kubernetes.default.svc'
namespace: ai-services
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
EOF
kubectl apply -f ~/mysql-argocd.yaml
步骤 4:验证部署结果
# 1. 查看 MySQL Pod 是否正常运行
kubectl get pods -n ai-services
# 2. 进入 MySQL 容器,验证数据是否创建成功
kubectl exec -it <mysql-pod-name> -n ai-services -- mysql -uroot -pnative hr_db
# 3. 执行查询,验证表和数据
SELECT * FROM employees;
执行结果:会看到 5 条员工数据,说明 ConfigMap 挂载成功,SQL 自动执行完成。
六、ConfigMap 常见坑 & 最佳实践
1. 常见坑
- 坑 1:ConfigMap 更新后,容器内不会自动热更新ConfigMap 更新后,已经运行的容器不会自动同步,需要重启 Pod 才能生效(K8s 1.16+ 支持部分热更新,但生产环境建议重启)
- 坑 2:敏感信息用 ConfigMap 存储ConfigMap 是明文存储,密码、密钥等敏感信息必须用 Secret,绝对不能用 ConfigMap
- 坑 3:ConfigMap 大小超过 1MiB单个 ConfigMap 最大 1MiB,大文件(比如日志、备份文件)用存储卷,不要用 ConfigMap
- 坑 4:跨命名空间引用 ConfigMapConfigMap 属于命名空间资源,只能在同命名空间的 Pod 中使用,跨命名空间需要创建同名 ConfigMap
2. 最佳实践
- 配置和镜像分离:所有配置都用 ConfigMap 管理,镜像只放业务代码,不写任何配置
- 按环境区分 ConfigMap:开发、测试、生产环境用不同的 ConfigMap,同一个镜像复用
- 用 Git 管理 ConfigMap:把 ConfigMap YAML 提交到 Git,通过 GitOps(Argo CD)管理,可追溯、可回滚
- ConfigMap 命名规范:用
应用名-用途命名,比如mysql-init-scripts、nginx-config,见名知意 - 避免过度使用:简单配置用环境变量,复杂配置用文件挂载,不要把所有配置都塞进 ConfigMap
七、总结
ConfigMap 是 K8s 中配置管理的核心工具,它的核心价值就是 **「解耦」**:把应用配置和容器镜像彻底分开,让容器化应用真正具备可移植性、可维护性。
- 本质:键值对存储,用来存配置
- 核心用法:挂载为文件、注入为环境变量
- 实战价值:你的项目中用它给 MySQL 做初始化,就是最典型的生产级用法
- 注意事项:敏感信息用 Secret,不要用 ConfigMap
更多推荐




所有评论(0)