SpringBoot自动化部署实战指南
一、整体部署架构设计
典型部署架构
二、基础部署方案
1. 快速启动脚本
#!/bin/bash
# deploy.sh
APP_NAME="my-springboot-app"
JAR_PATH="target/$APP_NAME.jar"
PROFILE="prod"
SERVER_IP="192.168.1.100"
DEPLOY_DIR="/opt/apps"
# 构建应用
mvn clean package -DskipTests
# 传输文件
scp $JAR_PATH $SERVER_IP:$DEPLOY_DIR
# 远程部署
ssh $SERVER_IP "sudo systemctl stop $APP_NAME || true"
ssh $SERVER_IP "cd $DEPLOY_DIR && nohup java -jar $APP_NAME.jar --spring.profiles.active=$PROFILE > app.log 2>&1 &"
2. Systemd服务配置
# /etc/systemd/system/my-springboot-app.service
[Unit]
Description=My SpringBoot Application
After=syslog.target network.target
[Service]
User=appuser
WorkingDirectory=/opt/apps
ExecStart=/usr/bin/java -jar /opt/apps/my-springboot-app.jar --spring.profiles.active=prod
SuccessExitStatus=143
Restart=always
RestartSec=30
Environment="JAVA_OPTS=-Xms512m -Xmx1024m -XX:MaxMetaspaceSize=256m"
[Install]
WantedBy=multi-user.target
三、Docker化部署方案
1. Dockerfile多阶段构建
# 构建阶段
FROM eclipse-temurin:17-jdk-jammy AS builder
WORKDIR /app
COPY . ./
RUN ./mvnw clean package -DskipTests
# 生产阶段
FROM eclipse-temurin:17-jre-jammy
VOLUME /tmp
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
# 安全增强
RUN addgroup --system spring && adduser --system --ingroup spring springuser
USER springuser
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/actuator/health || exit 1
EXPOSE 8080
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
2. Docker Compose部署
version: '3.8'
services:
app:
image: my-registry.com/spring-app:${TAG:-latest}
build:
context: .
target: builder # 仅用于开发环境
environment:
- SPRING_PROFILES_ACTIVE=prod
- SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/app_db
ports:
- "8080:8080"
depends_on:
- db
- redis
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: app_db
MYSQL_USER: appuser
MYSQL_PASSWORD: secret
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:6-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
volumes:
mysql_data:
四、CI/CD自动化流水线
GitHub Actions工作流
name: Build, Test & Deploy
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: 'maven'
- name: Build and Test
run: mvn clean verify
- name: Docker Build
uses: docker/build-push-action@v3
with:
context: .
push: false
tags: my-spring-app:pr-${{ github.sha }}
deploy-prod:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- name: Deploy to Kubernetes
uses: steebchen/kubectl@v2.0.0
with:
kubectl-version: v1.23.0
config: ${{ secrets.KUBECONFIG }}
command: apply -f k8s/deployment.yaml
Jenkins Pipeline脚本
pipeline {
agent any
environment {
DOCKER_REGISTRY = "my-registry.com"
KUBE_CONTEXT = "prod-cluster"
}
stages {
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
}
}
stage('Test') {
steps {
parallel(
"Unit Tests": { sh 'mvn test' },
"Integration Tests": { sh 'mvn verify -Pintegration' }
)
}
}
stage('Docker Build') {
steps {
script {
def imageName = "${DOCKER_REGISTRY}/spring-app:${env.BUILD_ID}"
docker.build(imageName).push()
}
}
}
stage('Deploy to Staging') {
steps {
withKubeConfig([credentialsId: 'k8s-prod-creds']) {
sh "kubectl config use-context ${KUBE_CONTEXT}"
sh "kubectl apply -f k8s/staging/deployment.yaml"
}
}
}
}
}
五、Kubernetes部署方案
1. Deployment配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: springboot-app
spec:
replicas: 3
revisionHistoryLimit: 3
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: springboot-app
template:
metadata:
labels:
app: springboot-app
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- springboot-app
topologyKey: "kubernetes.io/hostname"
containers:
- name: app
image: my-registry.com/spring-app:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: db-secrets
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1024Mi"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 45
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 5
2. 配置管理(ConfigMap + Secrets)
# ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
application.properties: |
server.port=8080
spring.datasource.url=jdbc:mysql://mysql-service:3306/app_db
spring.jpa.hibernate.ddl-auto=validate
spring.cache.type=redis
# Secrets
apiVersion: v1
kind: Secret
metadata:
name: db-secrets
type: Opaque
stringData:
spring.datasource.username: appuser
spring.datasource.password: "securepassword123"
六、高级部署策略
1. 蓝绿部署流程
# 部署新版本(绿色环境)
kubectl apply -f green-deployment.yaml
# 测试新版本
kubectl run test-container --image=curlimages/curl --rm -it -- \
curl http://green-service/actuator/health
# 切换流量
kubectl patch svc main-service -p \
'{"spec":{"selector":{"app":"springboot-app","version":"green"}}}'
# 清理旧版本
kubectl delete -f blue-deployment.yaml
2. 金丝雀发布自动化
# Argo Rollouts 配置
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: springboot-app
spec:
replicas: 5
strategy:
canary:
steps:
- setWeight: 10
- pause: {duration: 5m} # 监控指标
- setWeight: 25
- pause: {duration: 5m}
- setWeight: 50
- pause: {duration: 10m}
- setWeight: 100
selector:
matchLabels:
app: springboot-app
template:
# 与标准Deployment相同
七、监控与运维
Prometheus监控配置
# prometheus.yml
scrape_configs:
- job_name: 'springboot-app'
metrics_path: '/actuator/prometheus'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__address__]
action: replace
regex: ([^:]+)(?::\d+)?
replacement: $1:8080
target_label: __address__
- job_name: 'jvm'
static_configs:
- targets: ['jvm-exporter:9400']
Spring Boot Actuator配置
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
probes:
enabled: true
metrics:
enabled: true
metrics:
export:
prometheus:
enabled: true
tags:
application: ${spring.application.name}
distribution:
percentiles-histogram:
http.server.requests: true
八、安全加固措施
1. 安全基线配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // 仅用于API服务,前端应用需启用
.headers()
.contentSecurityPolicy("default-src 'self'")
.and()
.xssProtection().xssProtectionEnabled(true)
.and()
.httpStrictTransportSecurity()
.maxAgeInSeconds(31536000)
.includeSubDomains(true)
.and()
.frameOptions().deny();
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
2. 容器安全扫描
# 使用Trivy扫描镜像
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image my-registry.com/spring-app:latest
# 结果示例
+-------------------+------------------+----------+-------------------+---------+--------------------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED | TITLE |
+-------------------+------------------+----------+-------------------+---------+--------------------------------+
| apt | CVE-2023-XXXXX | HIGH | 2.4.8 | 2.4.9 | APT 安全漏洞 |
| openjdk-17-jre | CVE-2023-YYYYY | MEDIUM | 17.0.6 | 17.0.7 | OpenJDK 漏洞 |
+-------------------+------------------+----------+-------------------+---------+--------------------------------+
九、最佳实践总结
部署流程优化
- 自动化测试:集成单元测试、集成测试、安全扫描
- 不可变基础设施:每次部署创建新镜像而非更新现有实例
- 渐进式交付:结合蓝绿部署和金丝雀发布
- 回滚策略:保留最近3个版本,支持10秒内回滚
- 配置分离:敏感信息使用Secret管理,配置使用ConfigMap
性能优化
# JVM 优化参数
JAVA_TOOL_OPTIONS="-XX:+UseZGC \
-XX:MaxGCPauseMillis=200 \
-XX:ParallelGCThreads=4 \
-XX:ConcGCThreads=2 \
-Xmx1024m -Xms1024m"
监控指标黄金四律
- 延时:请求响应时间(P95 < 500ms)
- 流量:每秒请求数(RPS)
- 错误率:HTTP错误率(< 0.1%)
- 饱和度:CPU使用率(< 70%)、内存使用率(< 80%)
部署演进路线:手动部署 → 脚本自动化 → CI/CD流水线 → Kubernetes编排 → GitOps工作流 → 全自动渐进式交付
通过实施本指南,部署效率可提升5-10倍,停机时间减少90%,平均故障恢复时间(MTTR)降至5分钟以下。