端到端微服务部署于 AWS EKS:使用 Jenkins、Docker、Kubernetes 与 Argo CD 的 CI/CD

发布: (2025年12月27日 GMT+8 08:12)
7 分钟阅读
原文: Dev.to

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

蓝绿部署(零停机)

  1. 创建一个 “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
  1. 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
  1. 通过在 Git 中更新选择器来切换流量
selector:
  app: user-service
  version: green
  1. 提交并推送 → Argo CD 同步 → 流量立即切换且无需重启 pod。
  2. 回滚: 还原选择器的更改(git revert),Argo CD 会恢复 blue 部署。

金丝雀部署(渐进式发布)

  1. 创建一个金丝雀部署,使用少量副本(例如 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
  1. Service 选择器同时包含 stable 和 canary pod(使用匹配两个版本的标签选择器)。
selector:
  app: user-service
  1. 通过在 Git 中编辑清单逐步增加金丝雀副本(例如 2 → 3 个 pod),让 Argo CD 应用更改。

  2. 提升为 stable: 当信心足够时,用新版本替换 stable 部署的镜像并删除金丝雀部署。

  3. 回滚: 将金丝雀规模缩至零(kubectl scale deployment user-service-canary --replicas=0)或还原引入金丝雀的 Git 提交。

Back to Blog

相关文章

阅读更多 »