与 K8s 部署衔接:Deployment、Service、Ingress
随着容器化应用的普及,Kubernetes(K8s)已成为容器编排的事实标准。Docker 容器作为 K8s 的基本部署单元,需要与 K8s 的核心概念如 Deployment、Service 和 Ingress 紧密衔接。本篇文章将深入探讨如何将 Docker 容器与 K8s 部署进行有效整合,实现生产级的容器化应用部署。
一、Kubernetes 核心概念
在深入具体配置之前,我们需要理解 K8s 的几个核心概念:
1. Pod
Pod 是 K8s 中最小的部署单元,可以包含一个或多个容器:
# 简单的 Pod 配置
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: myapp:latest
ports:
- containerPort: 30002. Deployment
Deployment 管理 Pod 的部署和更新,提供声明式的更新能力:
# Deployment 配置示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 30003. Service
Service 为 Pod 提供稳定的网络访问入口:
# Service 配置示例
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: ClusterIP4. Ingress
Ingress 管理外部访问集群服务的 HTTP 和 HTTPS 路由:
# Ingress 配置示例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80二、从 Docker 到 K8s 的迁移
将 Docker 容器部署迁移到 K8s 需要考虑多个方面:
1. 镜像准备
确保 Docker 镜像符合 K8s 的要求:
# 优化的 Dockerfile 用于 K8s 部署
FROM node:18-alpine
# 创建非 root 用户
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
# 复制应用代码
COPY . .
# 更改文件所有权
RUN chown -R nextjs:nodejs /app
USER nextjs
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
EXPOSE 3000
CMD ["node", "server.js"]2. Deployment 配置
创建适合生产环境的 Deployment 配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
version: v1.0.0
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
version: v1.0.0
spec:
containers:
- name: myapp
image: myapp:latest
imagePullPolicy: Always
ports:
- containerPort: 3000
name: http
env:
- name: NODE_ENV
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: myapp-secrets
key: database-url
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 60
periodSeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 30
periodSeconds: 103. Service 配置
创建 Service 以暴露应用:
apiVersion: v1
kind: Service
metadata:
name: myapp-service
labels:
app: myapp
spec:
selector:
app: myapp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 3000
type: ClusterIP三、高级 K8s 配置
1. ConfigMap 和 Secret
外部化配置和敏感信息:
# ConfigMap 示例
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
data:
NODE_ENV: "production"
LOG_LEVEL: "info"
API_TIMEOUT: "5000"
---
# Secret 示例
apiVersion: v1
kind: Secret
metadata:
name: myapp-secrets
type: Opaque
data:
database-url: <base64-encoded-database-url>
api-key: <base64-encoded-api-key>在 Deployment 中使用 ConfigMap 和 Secret:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
template:
spec:
containers:
- name: myapp
# ... 其他配置
envFrom:
- configMapRef:
name: myapp-config
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: myapp-secrets
key: database-url2. PersistentVolume 和 PersistentVolumeClaim
处理持久化存储:
# PersistentVolume 示例
apiVersion: v1
kind: PersistentVolume
metadata:
name: myapp-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
hostPath:
path: /data/myapp
---
# PersistentVolumeClaim 示例
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myapp-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: manual在 Deployment 中使用 PVC:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
template:
spec:
containers:
- name: myapp
# ... 其他配置
volumeMounts:
- name: data
mountPath: /app/data
volumes:
- name: data
persistentVolumeClaim:
claimName: myapp-pvc四、Ingress 配置和路由
1. 基本 Ingress 配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 802. 多路径路由
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: Prefix
backend:
service:
name: myapp-api-service
port:
number: 80
- path: /admin(/|$)(.*)
pathType: Prefix
backend:
service:
name: myapp-admin-service
port:
number: 80
- path: /(.*)
pathType: Prefix
backend:
service:
name: myapp-frontend-service
port:
number: 80五、监控和日志
1. 健康检查配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
template:
spec:
containers:
- name: myapp
# ... 其他配置
livenessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 60
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 32. 资源限制和请求
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
template:
spec:
containers:
- name: myapp
# ... 其他配置
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"六、完整的部署示例
以下是一个完整的 K8s 部署示例:
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: myapp
---
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
namespace: myapp
data:
NODE_ENV: "production"
LOG_LEVEL: "info"
---
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: myapp-secrets
namespace: myapp
type: Opaque
data:
database-url: <base64-encoded-value>
---
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
namespace: myapp
labels:
app: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 3000
envFrom:
- configMapRef:
name: myapp-config
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: myapp-secrets
key: database-url
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 60
periodSeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
---
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: myapp
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 3000
type: ClusterIP
---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
namespace: myapp
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80一句话总结
将 Docker 容器与 Kubernetes 部署衔接需要理解 K8s 的核心概念如 Deployment、Service 和 Ingress,并通过合理的资源配置、健康检查、存储管理和网络策略来实现生产级的容器化应用部署。
通过这种方式,我们可以充分利用 Docker 的容器化优势和 K8s 的编排能力,构建高可用、可扩展的现代化应用架构。在实际部署中,还需要考虑监控、日志、安全和备份等运维方面的要求。