1. 为什么选择Kubernetes部署Spring Boot应用
三年前我第一次尝试把公司电商系统迁移到Kubernetes集群时,凌晨三点还在处理Pod不断重启的问题。现在回想起来,那次痛苦的经历反而让我真正理解了容器化部署的价值。对于Java开发者而言,将Spring Boot应用部署到Kubernetes集群,就像是给跑车配备了智能导航系统——不仅保留了原有的高性能,还获得了自动扩缩容、故障自愈等现代化运维能力。
典型的单体Spring Boot应用在传统部署方式下,往往需要人工维护服务器环境、手动处理服务依赖。我见过太多团队在发版日集体加班,就为了处理war包部署时的端口冲突问题。而Kubernetes提供的声明式部署方式,配合Spring Boot的嵌入式容器特性,可以实现真正的"一次构建,随处运行"。
2. 环境准备与工具链搭建
2.1 本地开发环境配置
在MacBook Pro上我习惯使用以下工具组合:
bash复制# 基础工具
brew install kubectl helm docker minikube
# 验证安装
docker --version && kubectl version --client
这里有个容易踩的坑:Docker Desktop默认只分配2GB内存,对于需要启动MySQL+Redis+应用的开发环境远远不够。建议通过Preferences → Resources调整到至少4GB,否则在本地测试时会出现OOM错误。
2.2 集群环境选择策略
根据项目阶段我通常这样选择:
- 开发测试:Minikube(单节点)或Kind(多节点模拟)
- 预发布环境:EKS/AKS托管集群(按需付费)
- 生产环境:自建集群(至少3个Worker节点)
重要提示:minikube启动时务必添加--driver=docker参数,否则默认的虚拟机驱动会消耗过多资源。我常用的启动命令:
bash复制minikube start --driver=docker --memory=4096 --cpus=2
3. Spring Boot应用容器化改造
3.1 Dockerfile最佳实践
这是我优化过的多阶段构建Dockerfile模板:
dockerfile复制# 构建阶段
FROM maven:3.8.4-jdk-11 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# 运行时阶段
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","app.jar"]
关键优化点:
- 使用独立构建阶段减少最终镜像体积(从650MB降到120MB)
- 提前复制pom.xml下载依赖,利用Docker缓存加速构建
- 设置时区避免容器内时间戳问题
- 使用urandom加速SecureRandom初始化
3.2 镜像构建与推送
我习惯用这个alias简化操作:
bash复制alias dkb='docker build -t ${PWD##*/}:latest . && docker tag ${PWD##*/}:latest registry.example.com/${PWD##*/}:$(date +%Y%m%d)'
构建后推送到私有仓库:
bash复制docker push registry.example.com/order-service:20230615
4. Kubernetes部署清单详解
4.1 Deployment配置模板
yaml复制apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
labels:
app: order-service
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: registry.example.com/order-service:20230615
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1024Mi"
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
配置要点解析:
- 资源限制(resources)必须设置,否则单个Pod可能耗尽节点资源
- 健康检查(liveness/readiness)依赖Spring Boot Actuator
- 环境变量SPRING_PROFILES_ACTIVE切换配置环境
- 副本数(replicas)初始设为3保证高可用
4.2 Service暴露策略
NodePort示例(适合开发环境):
yaml复制apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
nodePort: 31000
selector:
app: order-service
Ingress配置(生产环境推荐):
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: order-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: orders.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80
5. 高级部署策略实战
5.1 蓝绿发布实施方案
- 准备v2版本Deployment(标签version=v2)
- 创建临时Service测试v2版本
- 切换主Service的selector到v2
- 保留v1版本作为回滚备份
bash复制# 查看发布状态
kubectl get pods -l app=order-service --show-labels
# 流量切换命令
kubectl patch svc order-service -p '{"spec":{"selector":{"version":"v2"}}}'
5.2 自动扩缩容配置
基于CPU指标的HPA配置:
yaml复制apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: order-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
经验之谈:HPA需要配合合理的resources.limits配置,我曾遇到因未设置limits导致CPU使用率计算不准的问题
6. 运维监控与日志收集
6.1 Prometheus监控集成
Spring Boot配置:
properties复制management.endpoints.web.exposure.include=*
management.metrics.tags.application=${spring.application.name}
Prometheus ServiceMonitor示例:
yaml复制apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: spring-boot-monitor
spec:
selector:
matchLabels:
app: order-service
endpoints:
- port: http
path: /actuator/prometheus
namespaceSelector:
any: true
6.2 日志收集方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| EFK(Elastic+Fluentd+Kibana) | 功能全面 | 资源消耗大 | 大型生产环境 |
| Loki+Promtail | 轻量级 | 查询功能较弱 | 中小规模集群 |
| 直接写入云日志服务 | 免运维 | 成本较高 | 云原生环境 |
我目前的推荐组合:
bash复制helm install loki grafana/loki-stack --set promtail.enabled=true
7. 常见故障排查手册
7.1 Pod启动失败排查流程
-
查看Pod状态:
bash复制
kubectl get pods -l app=order-service -
检查日志:
bash复制kubectl logs -f <pod-name> --tail=100 -
进入容器诊断:
bash复制kubectl exec -it <pod-name> -- /bin/sh -
查看事件记录:
bash复制
kubectl describe pod <pod-name>
7.2 典型问题解决方案
问题1:应用启动后立即退出
- 可能原因:JVM内存不足
- 解决方案:调整Docker内存限制和JVM参数
yaml复制env: - name: JAVA_OPTS value: "-Xms512m -Xmx512m"
问题2:健康检查失败
- 可能原因:Actuator端点未开放
- 解决方案:确认application.properties配置:
properties复制management.endpoint.health.show-details=always management.endpoints.web.exposure.include=health,info
8. 安全加固实践
8.1 最小权限原则实现
ServiceAccount配置示例:
yaml复制apiVersion: v1
kind: ServiceAccount
metadata:
name: order-service-account
automountServiceAccountToken: false
Pod中引用:
yaml复制spec:
serviceAccountName: order-service-account
containers:
- name: order-service
securityContext:
runAsNonRoot: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
8.2 网络策略配置
限制只允许来自ingress-controller的访问:
yaml复制apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: order-service-policy
spec:
podSelector:
matchLabels:
app: order-service
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 8080
9. 持续交付流水线设计
9.1 GitLab CI示例
.gitlab-ci.yml关键部分:
yaml复制stages:
- build
- test
- deploy
build-image:
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
deploy-dev:
stage: deploy
environment:
name: dev
script:
- kubectl set image deployment/order-service order-service=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -n dev
only:
- branches
9.2 Argo CD声明式部署
application.yaml示例:
yaml复制apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: order-service
spec:
destination:
server: https://kubernetes.default.svc
namespace: production
source:
repoURL: git@github.com:myorg/kubernetes-manifests.git
path: order-service/overlays/prod
targetRevision: HEAD
syncPolicy:
automated:
prune: true
selfHeal: true
10. 成本优化技巧
10.1 资源利用率提升方案
-
使用Vertical Pod Autoscaler自动调整requests/limits
bash复制
helm install vpa recommender --repo https://charts.fairwinds.com/stable -
配置Pod中断预算避免同时重启过多实例
yaml复制apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: order-service-pdb spec: minAvailable: 60% selector: matchLabels: app: order-service
10.2 Spot实例使用策略
适合无状态服务的节点配置:
yaml复制apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/lifecycle
operator: In
values:
- spot
tolerations:
- key: "kubernetes.io/lifecycle"
operator: "Equal"
value: "spot"
effect: "NoSchedule"