Kubernetes
将配置从镜像中解耦,让同一镜像在不同环境使用不同配置。ConfigMap存储非敏感配置。
# 创建ConfigMap ✅
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
# 键值对
NODE_ENV: "production"
LOG_LEVEL: "info"
APP_PORT: "3000"
# 完整配置文件
nginx.conf: |
server {
listen 80;
location / {
proxy_pass http://api-service:8000;
}
}
# 在Pod中使用ConfigMap ✅
spec:
containers:
- name: app
envFrom:
- configMapRef:
name: app-config # 所有键作为环境变量
# 或选择特定键
env:
- name: NODE_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: NODE_ENV
# 挂载为文件
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d
volumes:
- name: config
configMap:
name: app-config
# 创建Secret ✅
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
# Base64编码
username: YWRtaW4= # echo -n 'admin' | base64
password: c2VjcmV0MTIz # echo -n 'secret123' | base64
stringData:
# 明文(创建时自动编码)
database-url: "postgres://admin:secret123@db:5432/myapp"
# 命令行创建 ✅
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password=secret123
# 从文件创建
kubectl create secret generic tls-secret \
--from-file=tls.crt=./cert.pem \
--from-file=tls.key=./key.pem
# 在Pod中使用Secret ✅
spec:
containers:
- name: app
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
# 挂载为文件
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-secret
# 1. 启用EncryptionConfiguration加密etcd中的Secret ✅
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <BASE64_ENCODED_SECRET>
- identity: {}
# 2. 使用RBAC限制Secret访问 ✅
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["db-secret"]
verbs: ["get"]
# 3. 使用外部密钥管理 ✅
# External Secrets Operator → AWS Secrets Manager / HashiCorp Vault
# 4. 禁止Secret写入etcd(使用CSI驱动)
# Secrets Store CSI Driver
❓ ConfigMap更新后Pod会自动刷新吗?环境变量方式:不会自动刷新,需要重启Pod。挂载文件方式:Kubelet会定期刷新(默认Period=300s),但应用需要自己监听文件变化。推荐:使用滚动更新
kubectl rollout restart deployment确保所有Pod获取新配置。❓ Secret的Base64编码是加密吗?不是!Base64是编码,任何人都能解码。它只是让二进制数据可以用YAML存储。要真正保护Secret:①启用etcd加密 ②使用RBAC限制访问 ③使用外部密钥管理系统 ④开启审计日志。
| 要点 | 说明 | 最佳实践 |
|---|---|---|
| 资源规划 | 根据业务负载合理分配CPU/内存 | 先压测再上线,设置requests和limits |
| 监控告警 | 设置关键指标阈值和告警规则 | Prometheus + AlertManager,5分钟P99延迟告警 |
| 备份策略 | 定期备份关键数据和配置 | 自动化备份脚本 + 异地存储 + 定期恢复演练 |
| 灰度发布 | 新版本逐步放量降低风险 | 金丝雀发布5%→20%→50%→100% |
| 回滚预案 | 部署前确认回滚方案和步骤 | 保留前一版本镜像,数据库迁移向前兼容 |
| 文档更新 | 配置变更必须同步更新文档 | GitOps管理配置,变更即文档 |
| 安全基线 | 遵循CIS Docker Benchmark | 非root运行、只读FS、最小能力 |
| 日志规范 | 结构化日志,统一格式 | JSON格式日志,包含traceId |
# 容器生命周期
docker create/start/stop/restart/rm/pause/unpause
docker logs/top/stats/inspect/exec diff
# 镜像构建
docker build/pull/push/tag/rmi/images/history
docker save/load/import/manifest
# 网络与存储
docker network create/ls/inspect/connect/disconnect/rm/prune
docker volume create/ls/inspect/rm/prune
# Docker Compose
docker compose up/down/ps/logs/build/exec
docker compose config/stop/start/scale/top/cp
# 系统维护
docker system df/prune/info
docker builder prune
docker container/prune/image prune
# K8s常用命令
kubectl get/describe/logs/exec/apply/delete
kubectl rollout status/undo/history
kubectl scale/autoscale/set
| 特性 | Docker Compose | Kubernetes |
|---|---|---|
| 规模 | 单主机 | 多主机集群 |
| 自愈 | restart策略 | 自动重启/替换Pod |
| 扩缩容 | 手动--scale | HPA自动扩缩容 |
| 滚动更新 | 手动操作 | 自动RollingUpdate |
| 服务发现 | 服务名DNS | Service + CoreDNS |
| 配置管理 | .env文件 | ConfigMap + Secret |
| 存储 | Volume/Bind Mount | PV/PVC/StorageClass |
| 密钥管理 | 环境变量 | Secret(加密存储) |
| 网络策略 | 网络隔离 | NetworkPolicy |
| 适用场景 | 开发/小规模 | 生产/大规模 |
# Step 1: 检查容器状态
docker ps -a # 查看所有容器
docker inspect <container> # 查看详细配置
# Step 2: 查看日志
docker logs --tail 100 <container> # 最近100行日志
docker logs --since 1h <container> # 最近1小时
# Step 3: 进入容器排查
docker exec -it <container> sh # 进入容器shell
# Step 4: 检查资源
docker stats --no-stream # 资源使用概览
docker system df # 磁盘使用
# Step 5: 网络排查
docker network ls # 网络列表
docker exec <c> ping <target> # 网络连通性
docker exec <c> nslookup <svc> # DNS解析
# Step 6: 检查健康状态
docker inspect --format '{{.State.Health}}' <c>
docker inspect --format '{{.State.ExitCode}}' <c>
docker inspect --format '{{.State.OOMKilled}}' <c>
# 通用最佳实践模板
FROM alpine:3.19 AS builder
# ... 构建步骤 ...
FROM alpine:3.19
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=builder /app/output .
USER appuser
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:8080/health || exit 1
EXPOSE 8080
CMD ["./app"]
services:
app:
build: .
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1'
memory: 512M