容器化与Kubernetes
介绍
容器化是一种轻量级的虚拟化技术,它允许将应用程序及其所有依赖项打包到一个标准化的单元中,称为容器。Kubernetes(K8s)是一个开源的容器编排平台,用于自动化容器化应用程序的部署、扩展和管理。容器化和Kubernetes已经成为现代云原生应用程序开发和部署的标准。
原理
容器化原理
- 隔离技术:使用Linux内核特性如cgroups(控制组)和namespaces(命名空间)实现资源隔离和进程隔离
- 镜像:包含应用程序及其依赖项的只读模板,使用分层文件系统
- 容器:镜像的运行实例,在镜像层之上添加可写层
- Docker:最流行的容器化平台,提供构建、运行和管理容器的工具
Kubernetes核心概念
- Pod:K8s最小部署单元,包含一个或多个容器
- Service:定义一组Pod的访问方式,提供负载均衡和服务发现
- Deployment:管理Pod的声明式定义,支持滚动更新和回滚
- StatefulSet:管理有状态应用的控制器
- ConfigMap/Secret:管理配置和敏感信息
- Namespace:将集群划分为多个逻辑隔离的环境
- Node:集群中的工作节点
- Control Plane:集群的控制平面,包含API Server、Scheduler、Controller Manager等组件
Kubernetes架构
- Master节点:控制平面,负责集群管理
- Worker节点:运行应用程序的工作节点
- API Server:集群的入口,处理REST API请求
- Scheduler:负责Pod调度
- Controller Manager:运行各种控制器,如Deployment控制器、StatefulSet控制器等
- etcd:分布式键值存储,保存集群状态
- kubelet:运行在每个节点上的代理,负责管理Pod
- kube-proxy:负责Service的网络代理
图示
容器化架构
┌─────────────────────────────────────────────────────────────────┐
│ 宿主机操作系统 │
├───────────────────┬───────────────────┬─────────────────────────┤
│ Docker引擎 │ 容器运行时 │ 其他容器运行时 │
├────────┬──────────┴────────┬──────────┴────────┬─────────────────┤
│ 容器1 │ 容器2 │ 容器3 │ 容器4 │
│ (应用A)│ (应用B) │ (应用C) │ (应用D) │
└────────┴───────────────────┴──────────────────┴─────────────────┘
Kubernetes架构
┌─────────────────────────────────────────────────────────────────┐
│ 控制平面 (Master节点) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────┐ │
│ │ API Server│ │ Scheduler │ │Controller │ │ etcd │ │
│ │ │ │ │ │ Manager │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────┘ │
└───────────────────────────┬─────────────────────────────────────┘
│
┌───────────────────────────▼─────────────────────────────────────┐
│ 数据平面 (Worker节点) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────┐ │
│ │ kubelet │ │ kube-proxy │ │ 容器运行时 │ │ Pods │ │
│ │ │ │ │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────────────┘
Kubernetes Pod和Service关系
┌─────────────────────────────────────────────────────────────────┐
│ Service (负载均衡) │
└───────────────────┬───────────────────┬─────────────────────────┘
│ │
┌───────────────────▼─────────┐ ┌───────▼───────────┐ ┌───────────▼─┐
│ Pod 1 │ │ Pod 2 │ │ Pod 3 │
│ ┌─────────────┐ ┌───────┐ │ │ ┌─────────────┐ │ │ │
│ │ 容器1 │ │容器2 │ │ │ │ 容器1 │ │ │ ┌─────────┐ │
│ └─────────────┘ └───────┘ │ │ └─────────────┘ │ │ │ 容器1 │ │
└─────────────────────────────┘ └───────────────────┘ └─────────────┘
实例
Dockerfile示例
# 基于Node.js 16镜像
FROM node:16-alpine
# 设置工作目录
WORKDIR /app
# 复制package.json和package-lock.json
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 3000
# 设置环境变量
ENV NODE_ENV=production
# 启动应用
CMD ["node", "server.js"]
Docker Compose示例
version: '3'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=db
- DB_PORT=5432
depends_on:
- db
restart: always
db:
image: postgres:13-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydb
volumes:
- pg-data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
pg-data:
Kubernetes Deployment示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodejs-app
labels:
app: nodejs-app
spec:
replicas: 3
selector:
matchLabels:
app: nodejs-app
template:
metadata:
labels:
app: nodejs-app
spec:
containers:
- name: nodejs-app
image: my-nodejs-app:latest
ports:
- containerPort: 3000
resources:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "200m"
memory: "256Mi"
env:
- name: NODE_ENV
value: "production"
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: db_host
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: db_password
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
Kubernetes Service示例
apiVersion: v1
kind: Service
metadata:
name: nodejs-app-service
spec:
selector:
app: nodejs-app
ports:
- port: 80
targetPort: 3000
type: LoadBalancer
Kubernetes ConfigMap和Secret示例
# ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
db_host: db-service
db_port: "5432"
db_user: user
app_log_level: info
# Secret
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
db_password: cGFzc3dvcmQ=
api_key: YXBpX2tleQ==
滚动更新示例
# 更新Deployment的镜像
kubectl set image deployment/nodejs-app nodejs-app=my-nodejs-app:v2
# 查看滚动更新状态
kubectl rollout status deployment/nodejs-app
# 如果出现问题,回滚到上一个版本
kubectl rollout undo deployment/nodejs-app
专业解决方案
容器化最佳实践
- 镜像优化:使用多阶段构建、选择轻量级基础镜像、最小化镜像层数
- 资源限制:为容器设置CPU和内存限制,避免资源争用
- 健康检查:实现liveness和readiness探针,确保容器健康
- 日志管理:将日志输出到标准输出和标准错误,便于收集
- 安全实践:避免以root用户运行容器、定期更新基础镜像、扫描镜像漏洞
- 构建缓存:利用Docker缓存机制加速构建过程
Kubernetes集群设计
- 单集群vs多集群:根据组织规模和隔离需求选择
- 控制平面高可用:部署多个Master节点,避免单点故障
- 节点池划分:根据应用类型和资源需求划分不同节点池
- 网络插件选择:根据性能和功能需求选择,如Calico、Flannel、Cilium
- 存储策略:根据应用数据需求选择合适的存储解决方案
- 集群 autoscaler:根据负载自动调整节点数量
部署策略
- 滚动更新:逐步替换旧版本Pod,零 downtime
- 金丝雀发布:将少量流量导向新版本,逐步增加
- 蓝绿部署:准备两套环境,切换流量
- A/B测试:基于用户特征将流量导向不同版本
- 灰度发布:基于权重分配流量
资源管理
- 请求与限制:合理设置CPU和内存的requests和limits
- 资源QoS:根据应用重要性设置不同的QoS级别
- 水平Pod自动扩缩容:基于指标自动调整Pod数量
- 垂直Pod自动扩缩容:自动调整Pod的资源请求
- 集群自动扩缩容:自动添加或删除节点
网络策略
- 入站/出站规则:控制Pod间通信
- 命名空间隔离:限制跨命名空间通信
- 服务网格:使用Istio、Linkerd等实现更细粒度的网络控制
- 负载均衡:选择合适的Service类型,如ClusterIP、NodePort、LoadBalancer
- Ingress:管理外部访问集群内服务的规则
存储管理
- 持久卷(PV)和持久卷声明(PVC):抽象存储资源
- 存储类(StorageClass):动态供应存储
- 状态管理:使用StatefulSet管理有状态应用
- 数据备份:定期备份重要数据
- 存储性能:根据应用需求选择合适的存储类型
监控与日志
- 资源监控:使用Prometheus监控集群资源使用情况
- 应用监控:埋点监控应用性能和健康状态
- 日志聚合:使用ELK Stack、Loki等聚合容器日志
- 分布式追踪:使用Jaeger、Zipkin等追踪请求流经的服务
- 告警系统:设置合理的告警规则,及时发现问题
安全
- Pod安全策略:限制Pod的权限和行为
- 网络安全:使用网络策略和TLS加密通信
- Secrets管理:安全存储和使用敏感信息
- 镜像安全:扫描镜像漏洞,只信任可靠镜像源
- RBAC:基于角色的访问控制,限制用户和服务的权限
- 审计日志:记录集群活动,便于追溯
工具推荐
- 容器化工具:Docker、Podman、Containerd
- 容器编排:Kubernetes、Docker Swarm
- Kubernetes管理工具:kubectl、k9s、Lens
- CI/CD:Jenkins、GitLab CI、GitHub Actions、Argo CD
- 监控:Prometheus、Grafana、Jaeger
- 日志:ELK Stack、Loki、Fluentd
- 存储:Rook、MinIO、Ceph
- 网络:Calico、Flannel、Cilium、Istio、Linkerd
- 安全:Trivy、Aqua Security、Falco
- 云服务:AWS EKS、Google GKE、Azure AKS、阿里云ACK