前言
DevOps 是开发与运维的协作实践,通过自动化工具实现持续集成和持续部署。Spring Boot 项目可以通过 Jenkins、GitHub Actions、GitLab CI 等工具实现 DevOps 流程。本文将介绍 Spring Boot DevOps 的完整方案。
CI/CD 流程
1. 典型流程
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Code │────▶│ Build │────▶│ Test │────▶│ Package │────▶│ Deploy │
│ Push │ │ Maven │ │ Unit │ │ Docker │ │ K8s │
└─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘
2. 阶段说明
| 阶段 | 说明 | 工具 |
|---|---|---|
| Code | 代码提交 | Git |
| Build | 编译构建 | Maven |
| Test | 单元测试 | JUnit |
| Package | 打包镜像 | Docker |
| Deploy | 部署应用 | K8s/Helm |
GitHub Actions
1. 基础 CI
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Build with Maven
run: mvn -B clean package -DskipTests
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: demo-jar
path: target/*.jar
2. 完整流水线
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
tags: ['v*']
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Run tests
run: mvn -B test
- name: Upload coverage
uses: codecov/codecov-action@v3
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
deploy-dev:
needs: build
runs-on: ubuntu-latest
environment: development
steps:
- name: Deploy to K8s
run: |
kubectl set image deployment/demo demo=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} -n dev
deploy-prod:
needs: deploy-dev
runs-on: ubuntu-latest
environment: production
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Deploy with Helm
run: |
helm upgrade demo ./helm/demo --set image.tag=${{ github.ref_name }}
3. 密钥管理
# 在 GitHub Settings → Secrets 中配置
# Secrets:
# - KUBE_CONFIG: K8s 配置文件
# - DOCKER_PASSWORD: Docker 密码
# - SONAR_TOKEN: SonarQube Token
Jenkins
1. Jenkinsfile
// Jenkinsfile
pipeline {
agent any
tools {
maven 'Maven 3.9'
jdk 'JDK 21'
}
environment {
REGISTRY = 'registry.example.com'
IMAGE_NAME = 'demo'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Test') {
steps {
sh 'mvn test'
junit 'target/surefire-reports/*.xml'
}
}
stage('Build Docker Image') {
steps {
script {
docker.build("${REGISTRY}/${IMAGE_NAME}:${env.BUILD_ID}")
}
}
}
stage('Push Docker Image') {
steps {
script {
docker.withRegistry("https://${REGISTRY}", 'docker-credentials') {
docker.image("${REGISTRY}/${IMAGE_NAME}:${env.BUILD_ID}").push()
}
}
}
}
stage('Deploy to Dev') {
when {
branch 'develop'
}
steps {
sh 'kubectl set image deployment/demo demo=${REGISTRY}/${IMAGE_NAME}:${BUILD_ID} -n dev'
}
}
stage('Deploy to Prod') {
when {
branch 'main'
}
steps {
input message: 'Deploy to production?', ok: 'Deploy'
sh 'kubectl set image deployment/demo demo=${REGISTRY}/${IMAGE_NAME}:${BUILD_ID} -n prod'
}
}
}
}
2. 多分支流水线
// Jenkinsfile
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Deploy') {
steps {
script {
if (env.BRANCH_NAME == 'main') {
deploy('prod')
} else if (env.BRANCH_NAME == 'develop') {
deploy('dev')
}
}
}
}
}
}
def deploy(String env) {
// 部署逻辑
}
GitLab CI
1. 基础配置
# .gitlab-ci.yml
stages:
- build
- test
- package
- deploy
variables:
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
cache:
paths:
- .m2/repository/
build:
stage: build
image: maven:3.9-eclipse-temurin-21
script:
- mvn clean package -DskipTests
artifacts:
paths:
- target/*.jar
test:
stage: test
image: maven:3.9-eclipse-temurin-21
script:
- mvn test
package:
stage: package
image: docker:24
services:
- docker:24-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
only:
- main
deploy-dev:
stage: deploy
image: bitnami/kubectl
script:
- kubectl set image deployment/demo demo=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -n dev
environment:
name: development
only:
- develop
deploy-prod:
stage: deploy
image: bitnami/kubectl
script:
- kubectl set image deployment/demo demo=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -n prod
environment:
name: production
when: manual
only:
- main
2. GitLab Runner
# 安装 Runner
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | bash
apt-get install gitlab-runner
# 注册 Runner
gitlab-runner register \
--url https://gitlab.com/ \
--registration-token YOUR_TOKEN \
--executor docker
ArgoCD GitOps
1. 安装 ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
2. 创建应用
# argocd-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: demo
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/demo-k8s.git
targetRevision: HEAD
path: k8s/prod
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
3. GitOps 流程
Code → CI → Git Ops Repo → ArgoCD → K8s
自动化部署
1. 蓝绿部署
# k8s/blue-green.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-blue
spec:
replicas: 3
template:
spec:
containers:
- name: demo
image: demo:1.0.0
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-green
spec:
replicas: 3
template:
spec:
containers:
- name: demo
image: demo:1.1.0
---
apiVersion: v1
kind: Service
metadata:
name: demo
spec:
selector:
version: blue # 切换到 green
ports:
- port: 80
targetPort: 8080
2. 金丝雀发布
# k8s/canary.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: demo
spec:
hosts:
- demo
http:
- route:
- destination:
host: demo
subset: stable
weight: 90
- destination:
host: demo
subset: canary
weight: 10
3. 滚动更新
# k8s/rolling-update.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
spec:
containers:
- name: demo
image: demo:1.1.0
监控与告警
1. Prometheus 监控
# prometheus-rule.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: demo-alerts
spec:
groups:
- name: demo
rules:
- alert: ServiceDown
expr: up{job="demo"} == 0
for: 1m
annotations:
summary: "Service is down"
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
for: 5m
annotations:
summary: "High error rate"
2. 告警通知
# alertmanager.yaml
route:
receiver: 'slack-notifications'
receivers:
- name: 'slack-notifications'
slack_configs:
- api_url: https://hooks.slack.com/services/xxx
channel: '#alerts'
最佳实践
1. 流水线优化
# ✅ 推荐
# 并行执行
jobs:
test:
security-scan:
lint:
# 缓存依赖
cache:
paths:
- .m2/repository/
# ❌ 不推荐
# 串行执行
# 不缓存
2. 安全配置
# ✅ 推荐
# 使用密钥管理
secrets:
- KUBE_CONFIG
- DOCKER_PASSWORD
# 镜像扫描
- name: Scan image
uses: aquasecurity/trivy-action@master
# ❌ 不推荐
# 硬编码密钥
3. 版本管理
# 语义化版本
tags:
- 'v1.0.0'
- 'v1.0.1'
- 'v1.1.0'
# Git 标签
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
4. 回滚策略
# 自动回滚
spec:
syncPolicy:
automated:
prune: true
selfHeal: true
# 手动回滚
helm rollback demo 1
kubectl rollout undo deployment/demo
总结
DevOps 要点:
- ✅ GitHub Actions - 原生集成
- ✅ Jenkins - 灵活强大
- ✅ GitLab CI - 一体化
- ✅ ArgoCD - GitOps
- ✅ 最佳实践 - 并行、安全、版本
DevOps 是现代软件交付的核心实践。