端到端微服务部署于 AWS EKS:使用 Jenkins、Docker、Kubernetes 与 Argo CD 的 CI/CD
Source: Dev.to
(请提供需要翻译的正文内容,我才能为您完成简体中文翻译。)
用户‑订单微服务应用
架构概览
一个由 User Service(用户服务)和 Order Service(订单服务)组成的简易两服务系统。两个服务均使用 Spring Boot 构建,打包为 Docker 镜像,并部署到 Amazon EKS 集群中。
项目结构(学习用单仓库)
microservices-project/
├─ user-service/
│ ├─ src/
│ └─ Dockerfile
├─ order-service/
│ ├─ src/
│ └─ Dockerfile
└─ k8s/
├─ db-deployment.yaml
├─ user-deployment.yaml
├─ order-deployment.yaml
└─ ingress.yaml
Spring Boot 示例代码片段
@Entity
public class User {
@Id @GeneratedValue
private Long id;
// …
}
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping
public ResponseEntity create(@RequestBody User user) { … }
@GetMapping("/{id}")
public ResponseEntity get(@PathVariable Long id) { … }
@GetMapping("/health")
public String health() { return "OK"; }
}
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@PostMapping
public ResponseEntity create(@RequestBody Order order) {
// 调用用户服务
String url = "http://user-service:8080/users/" + order.getUserId();
restTemplate.getForObject(url, User.class);
// …
}
}
构建 – 为两个服务制作 Docker 镜像
# user-service/Dockerfile
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/user-service.jar app.jar
ENTRYPOINT ["java","-jar","/app/app.jar"]
# order-service/Dockerfile
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/order-service.jar app.jar
ENTRYPOINT ["java","-jar","/app/app.jar"]
# Build and tag images
mvn clean package -f user-service/pom.xml
docker build -t user-service:1.0 ./user-service
mvn clean package -f order-service/pom.xml
docker build -t order-service:1.0 ./order-service
Kubernetes – 数据库部署
# k8s/db-deployment.yaml
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
ports:
- port: 5432
selector:
app: postgres
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:13
env:
- name: POSTGRES_DB
value: microservices
- name: POSTGRES_USER
value: admin
- name: POSTGRES_PASSWORD
value: secret
ports:
- containerPort: 5432
Kubernetes – 用户服务部署
# k8s/user-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 2
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:1.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service
ports:
- port: 8080
targetPort: 8080
Kubernetes – 订单服务部署
# k8s/order-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 2
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: order-service:1.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
selector:
app: order-service
ports:
- port: 8080
targetPort: 8080
Ingress – 单入口点
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: microservices-ingress
spec:
rules:
- http:
paths:
- path: /users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
- path: /orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 8080
部署所有内容
kubectl apply -f k8s/
功能验证(关键测试)
curl -X POST http:///orders \
-H "Content-Type: application/json" \
-d '{"userId":1,"productId":42,"quantity":2}'
回滚场景
# Revert to previous Git commit that contains the older manifests
git revert
# Argo CD (or kubectl) will apply the reverted state automatically
生产级改进
- 添加健康检查和就绪探针。
- 启用资源限制和请求。
- 使用 sidecar 进行日志/指标收集(例如,Prometheus 导出器)。
- 将机密存储在 AWS Secrets Manager 或使用 KMS 加密的 Kubernetes Secrets 中。
- 实施蓝绿或金丝雀部署(见下文)。
第 2 部分 – 完整 CI 流水线(Jenkins)
pipeline {
agent any
environment {
REGISTRY = 'your-registry.io'
IMAGE_TAG = "${env.BUILD_NUMBER}"
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'https://github.com/your-org/microservices-project.git'
}
}
stage('Build User Service') {
steps {
dir('user-service') {
sh 'mvn clean package'
}
}
}
stage('Build Order Service') {
steps {
dir('order-service') {
sh 'mvn clean package'
}
}
}
stage('Docker Build') {
steps {
sh '''
docker build -t $REGISTRY/user-service:$IMAGE_TAG user-service/
docker build -t $REGISTRY/order-service:$IMAGE_TAG order-service/
'''
}
}
stage('Docker Push') {
steps {
withDockerRegistry([credentialsId: 'dockerhub-creds', url: '']) {
sh '''
docker push $REGISTRY/user-service:$IMAGE_TAG
docker push $REGISTRY/order-service:$IMAGE_TAG
'''
}
}
}
stage('Update K8s Manifests Repo') {
steps {
sh '''
git clone https://github.com/your-org/k8s-manifests.git
cd k8s-manifests
sed -i "s|image:.*user-service.*|image: $REGISTRY/user-service:$IMAGE_TAG|" user-deployment.yaml
sed -i "s|image:.*order-service.*|image: $REGISTRY/order-service:$IMAGE_TAG|" order-deployment.yaml
git commit -am "Update images to $IMAGE_TAG"
git push
'''
}
}
}
}
该流水线遵循经典流程: **Trigger → Checkout → Build → Test(此处省略) → Docker Build → Docker Push → Update Git → 通过 Argo CD 进行 CD。
Source: …
第 3 部分 – Argo CD(GitOps 部署)
安装 Argo CD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl port-forward svc/argocd-server -n argocd 8080:443
获取初始管理员密码:
kubectl get secret argocd-initial-admin-secret -n argocd -o jsonpath="{.data.password}" | base64 -d
将 Argo CD 连接到清单仓库
# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: microservices-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/k8s-manifests.git
targetRevision: HEAD
path: .
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
应用该 Application:
kubectl apply -f application.yaml
Argo CD 将持续将实际集群状态与 Git 中的清单进行对比,并自动处理发布、回滚和健康检查。
自动化操作
- 同步(Sync):
kubectl apply -f k8s/→ Argo CD 检测到漂移后自动同步。 - 回滚(Rollback):
git revert→ Argo CD 将集群恢复到之前的状态。 - 状态(Status):
kubectl get pods或使用 Argo CD UI 查看。
蓝绿部署与金丝雀部署使用 Argo CD
蓝绿部署(零停机)
- 创建一个 “green” 部署(新版本)与现有的 “blue” 部署并存。
# user-service-green.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service-green
spec:
replicas: 2
selector:
matchLabels:
app: user-service
version: green
template:
metadata:
labels:
app: user-service
version: green
spec:
containers:
- name: user-service
image: your-registry.io/user-service:2.0
ports:
- containerPort: 8080
- Service 选择器最初指向 blue 版本。
# user-service-service.yaml
apiVersion: v1
metadata:
name: user-service
spec:
selector:
app: user-service
version: blue # change to "green" to switch traffic
ports:
- port: 8080
targetPort: 8080
- 通过在 Git 中更新选择器来切换流量:
selector:
app: user-service
version: green
- 提交并推送 → Argo CD 同步 → 流量立即切换且无需重启 pod。
- 回滚: 还原选择器的更改(
git revert),Argo CD 会恢复 blue 部署。
金丝雀部署(渐进式发布)
- 创建一个金丝雀部署,使用少量副本(例如 1 个 pod ≈ 10 % 流量)。
# user-service-canary.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service-canary
spec:
replicas: 1
selector:
matchLabels:
app: user-service
version: canary
template:
metadata:
labels:
app: user-service
version: canary
spec:
containers:
- name: user-service
image: your-registry.io/user-service:2.0
ports:
- containerPort: 8080
- Service 选择器同时包含 stable 和 canary pod(使用匹配两个版本的标签选择器)。
selector:
app: user-service
-
通过在 Git 中编辑清单逐步增加金丝雀副本(例如 2 → 3 个 pod),让 Argo CD 应用更改。
-
提升为 stable: 当信心足够时,用新版本替换 stable 部署的镜像并删除金丝雀部署。
-
回滚: 将金丝雀规模缩至零(
kubectl scale deployment user-service-canary --replicas=0)或还原引入金丝雀的 Git 提交。