1. 核心理念
容器不是简单的“打包可运行环境”,而是一个 架构边界单位。面向容器的设计,就是把应用拆分为独立的、可部署的、隔离的运行单元,并让容器本身成为交付、运行、扩展的核心最小单元。
一句话:先想容器边界,再想代码结构。
2. 设计流程
(1) 确定容器粒度
- 微服务化:每个业务能力一个容器(订单、支付、库存)
- 功能模块化:可共用的功能(缓存、消息队列、API 网关)单独容器化
- 经验法则:容器越小,灵活性越高,但部署和运维复杂度也高
(2) 接口优先设计
- 容器间通信使用标准接口(HTTP/gRPC/消息队列)
- 明确输入/输出协议,减少跨容器强依赖
- 接口与实现解耦,保证容器内部技术栈可自由更换
(3) 环境与依赖内置化
- 应用运行所需依赖全部打包进容器镜像
- 配置外置(ConfigMap、Secrets),避免在镜像中写死
- 保证容器可在任何节点“一键运行”,不依赖宿主机环境
(4) 状态管理
- 无状态优先:容器重启不影响业务
- 有状态服务(数据库、文件存储)拆出去,用持久卷(PV)或云存储
(5) 生命周期管理
- 容器启动、健康检查、退出信号处理(SIGTERM)
- 版本化镜像(不可变镜像策略)
- 灰度发布与回滚(通过镜像 tag + orchestration 工具)
3. 面向容器的架构特征
特征 | 说明 | 好处 |
---|---|---|
轻量隔离 | 各容器进程、依赖隔离 | 避免冲突,易迁移 |
可移植性 | 镜像可运行在不同平台 | 从开发到生产一致 |
可伸缩性 | 按容器水平扩展 | 高并发应对灵活 |
可观测性 | 每个容器独立监控 | 问题定位精准 |
自动化 | 构建、测试、部署流水线化 | 降低运维成本 |
4. 设计时的陷阱
- 容器粒度过细 → 接口调用过多,性能下降
- 将数据库直接放在短生命周期容器中 → 数据丢失
- 容器镜像过大 → 启动和更新慢
- 忽略网络延迟和跨容器带宽消耗
5. 一个简单的例子
比如一个电商系统:
api-gateway
容器(Nginx + Lua 或 Kong)user-service
容器(Go + MySQL)order-service
容器(Java + Kafka)payment-service
容器(Node.js + 支付SDK)- 公用
redis
容器(缓存) - 公用
mq
容器(RabbitMQ 或 Kafka)
所有容器的运行、扩容、监控都交给 Kubernetes 或 Docker Compose 进行编排。
ConfigMap vs docker-compose
environment 区别
1. 定义
项目 | ConfigMap | docker-compose environment |
---|---|---|
归属平台 | Kubernetes | Docker / Docker Compose |
本质 | Kubernetes 的一种资源对象,用来存储非机密的配置信息(key-value) | 在 Compose 文件(docker-compose.yml )中,为容器运行时注入环境变量的方式 |
作用范围 | K8s 集群层面,多个 Pod/容器可共享 | 当前 Compose 项目或单个容器 |
存储位置 | 存在 etcd(K8s 控制面) | 写在 Compose 文件里或外部 .env 文件 |
用途 | 统一、集中管理配置,容器可挂载或注入 | 在启动容器时设置环境变量 |
2. 使用方式
ConfigMap(K8s)
1 | # 创建 ConfigMap |
引用方式:
- 作为环境变量:
1 | envFrom: |
- 挂载成文件:
1 | volumeMounts: |
docker-compose environment
1 | services: |
或者使用外部 .env
文件:
1 | # .env |
然后在 docker-compose.yml
:
1 | services: |
3. 关键区别
对比点 | ConfigMap | docker-compose environment |
---|---|---|
平台 | 运行在 Kubernetes | 运行在 Docker / Compose |
管理方式 | 集群 API 统一管理,可独立于镜像和 Pod 生命周期 | 由 docker-compose.yml 直接定义,和容器生命周期绑定 |
更新方式 | 更新 ConfigMap → 重启 Pod(或触发滚动更新) | 改 docker-compose.yml 或 .env → 重新 docker-compose up -d |
适合场景 | 多容器/多服务共享配置,动态调整 | 单项目或单容器快速设置环境变量 |
存储安全 | 仅适合非敏感数据(敏感数据用 Secret) | 同样不适合存敏感数据(最好用 Docker Secret) |
4. 一句总结
- ConfigMap = K8s 的“集群级配置中心”(适合动态、集中管理配置)
- docker-compose environment = 本地/单机容器的环境变量注入(适合小规模部署或开发环境)
容器中的敏感数据
在Kubernetes中,敏感数据不应该存储在ConfigMap中,因为ConfigMap并不提供加密或保护数据的功能。对于敏感数据,Kubernetes提供了Secret对象来专门处理这类信息。Secret可以用来存储如密码、OAuth令牌和SSH密钥等敏感信息,并且可以在创建时选择是否启用加密。Secret可以通过类似ConfigMap的方式注入到容器中,作为环境变量或挂载为文件。
以下是在Kubernetes中使用Secret的一些基本操作:
创建Secret:
可以通过命令行或者YAML文件创建Secret。例如,从文件创建一个包含用户名和密码的Secret:1
kubectl create secret generic mysecret --from-file=username=./username.txt --from-file=password=./password.txt
在Pod中使用Secret:
- 作为环境变量:
1
2
3
4
5
6env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username - 作为挂载的卷:
1
2
3
4
5
6
7volumeMounts:
- name: secret-volume
mountPath: /etc/secret
volumes:
- name: secret-volume
secret:
secretName: mysecret
- 作为环境变量:
在Docker Compose中,没有直接等同于Kubernetes Secret的对象,但你可以通过环境变量或者挂载文件的方式来安全地传递敏感信息。
使用环境变量:
你可以在docker-compose.yml
文件中定义环境变量,并在运行docker-compose up
之前通过.env
文件或者命令行参数来设置这些值。1
2
3
4
5services:
myservice:
image: myimage
environment:
- SECRET_KEY=${SECRET_KEY}挂载敏感文件:
你可以将包含敏感信息的文件挂载到容器中。确保这些文件在主机系统上有适当的权限设置,并且不与版本控制系统共享(例如通过.gitignore
)。1
2
3
4
5services:
myservice:
image: myimage
volumes:
- ./secrets:/run/secretsDocker Secrets(仅适用于Swarm模式):
如果你在使用Docker Swarm模式,可以利用Docker Secrets功能来管理敏感数据,这提供了更高级的安全措施,比如自动加密。
无论是在Kubernetes还是Docker Compose中,处理敏感数据时都应该采取适当的安全措施,比如限制访问权限、使用加密以及避免将敏感信息硬编码到配置文件中。
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏