GitHub Actions打包容器,推送 AWS ECR 并使 EKS 自动拉取以完成发版部署

以下是关于 EKS 直接拉取 ECR 镜像的解答,以及如何通过 GitHub Actions 将项目打包为容器、推送至 AWS ECR 并使 EKS 自动拉取以完成发版部署的详细步骤。当前时间为 2025 年 7 月 23 日下午 12:27 HKT,基于最新技术实践提供方案。


1. EKS 直接拉取 ECR 镜像吗?

  • 答案:是的,EKS 可以直接拉取 ECR 镜像,但需要满足以下条件:

    • IAM 权限 :EKS 集群的节点(Worker Nodes)需关联一个 IAM 角色,拥有 AmazonEC2ContainerRegistryReadOnly 权限,以便从 ECR 拉取镜像。
    • 配置正确 :在 Kubernetes Pod 的 spec.containers.image 字段中指定 ECR 镜像路径(例如 account-id.dkr.ecr.region.amazonaws.com/repository:tag)。
    • 网络访问:EKS 集群需能访问 ECR(通常通过 VPC 配置或公网访问)。
    • 默认行为:EKS 的 kubelet 会自动尝试拉取指定的镜像,无需额外工具,但拉取过程依赖节点的网络和权限设置。
  • 验证方法

    • 使用 kubectl describe pod <pod-name> 检查事件日志,确认拉取成功或失败(例如 "ImagePullBackOff" 表示权限或网络问题)。

2. 通过 GitHub Actions 打包容器、推送至 ECR 并部署到 EKS 的步骤

准备工作
  • AWS 配置
    • 创建 ECR 仓库(例如 my-app),记录仓库 URL(account-id.dkr.ecr.region.amazonaws.com/my-app)。
    • 设置 EKS 集群(例如 my-eks-cluster),并通过 aws eks update-kubeconfig --region region --name my-eks-cluster 获取 kubeconfig
    • 创建 IAM 角色并附加到 EKS 节点组,包含 AmazonEC2ContainerRegistryReadOnly 权限。
    • 在 GitHub 仓库的 Settings > Secrets and variables > Actions 中添加:
      • AWS_ACCESS_KEY_ID
      • AWS_SECRET_ACCESS_KEY
      • AWS_REGION(例如 us-east-1
      • ECR_REPOSITORY(例如 my-app
      • KUBE_CONFIG_DATA(将 kubeconfig 转为 Base64 编码,例如 cat ~/.kube/config | base64)。
  • 项目配置
    • 根目录下创建 Dockerfile(示例见下)。
    • 创建 Kubernetes 部署文件 deployment.yaml(示例见下)。
Dockerfile 示例
复制代码
# 使用官方 Node.js 镜像作为基础
FROM node:18-alpine

# 设置工作目录
WORKDIR /app

# 复制 package.json 和 package-lock.json
COPY package*.json ./

# 安装依赖
RUN npm install

# 复制项目文件
COPY . .

# 构建应用
RUN npm run build

# 暴露端口
EXPOSE 3000

# 启动命令
CMD ["node", "dist/index.js"]
Kubernetes 部署文件(deployment.yaml)
复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: <account-id>.dkr.ecr.<region>.amazonaws.com/my-app:latest
        ports:
        - containerPort: 3000
        resources:
          requests:
            memory: "256Mi"
            cpu: "200m"
          limits:
            memory: "512Mi"
            cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: LoadBalancer
GitHub Actions 工作流(.github/workflows/deploy.yml)
复制代码
name: Deploy to EKS

on:
  push:
    branches:
      - main

jobs:
  deploy:
    name: Build and Deploy
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

      - name: Update kubeconfig
        run: |
          echo "${{ secrets.KUBE_CONFIG_DATA }}" | base64 -d > kubeconfig
          export KUBECONFIG=kubeconfig

      - name: Deploy to EKS
        uses: kodermax/kubectl-aws-eks@main
        with:
          args: set image deployment/my-app my-app=${{ steps.build-image.outputs.image }} --record
        env:
          KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_DATA }}

      - name: Verify deployment
        uses: kodermax/kubectl-aws-eks@main
        with:
          args: rollout status deployment/my-app
        env:
          KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_DATA }}

      - name: Cleanup
        if: always()
        run: |
          rm -f kubeconfig
实现流程
  1. 触发工作流
    • 推送到 main 分支时,GitHub Actions 自动运行。
  2. 构建与推送
    • 配置 AWS 凭证,登录 ECR。
    • 使用 Docker Buildx 构建镜像,打上 Git 提交哈希标签(${``{ github.sha }}),推送到 ECR。
  3. 部署到 EKS
    • 解码 kubeconfig,更新 Deployment 中的镜像标签。
    • 使用 kubectl 应用更改,EKS 节点自动拉取新镜像。
  4. 验证与清理
    • 检查部署状态,确保 Pod 运行。
    • 清理临时文件。
EKS 自动拉取镜像
  • EKS 的 kubelet 会在 Pod 启动时自动拉取 deployment.yaml 中指定的镜像(例如 account-id.dkr.ecr.us-east-1.amazonaws.com/my-app:sha256...)。
  • 如果镜像未找到或权限不足,Pod 状态将显示 ImagePullBackOff,需检查 IAM 角色和网络配置。
注意事项
  • IAM 角色:确保 EKS 节点组的 IAM 角色有 ECR 读取权限。
  • 镜像标签 :使用动态标签(${``{ github.sha }})避免缓存问题,生产环境可加环境标识(如 prod-${``{ github.sha }})。
  • 网络:若 EKS 在私有 VPC,配置 VPC Endpoint 或 NAT Gateway 访问 ECR。
  • 安全:使用 GitHub OIDC 替代长期凭证,提升安全性。
  • 测试 :初次部署后,使用 kubectl get podskubectl logs 验证。
验证部署
  • 推代码后,检查 GitHub Actions 日志。
  • 使用 kubectl get deployments 确认 my-app 更新。
  • 通过 Service 的外部 IP(kubectl get svc my-app-service)访问应用。

此方案实现了从代码提交到 EKS 自动部署的全流程,适合中小型项目。如需多环境或回滚支持,可扩展工作流逻辑。

优化改进版action.yml

bash 复制代码
name: Deploy to EKS

on:
  push:
    branches:
      - main
      - dev

jobs:
  deploy:
    name: Build and Deploy
    runs-on: ubuntu-latest
    env:
      ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
      IMAGE_TAG: ${{ github.ref == 'refs/heads/main' && format('prod-{0}', github.sha) || format('dev-{0}', github.sha) }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

      - name: Update kubeconfig
        run: |
          echo "${{ secrets.KUBE_CONFIG_DATA }}" | base64 -d > kubeconfig
          export KUBECONFIG=kubeconfig

      - name: Deploy to EKS
        uses: kodermax/kubectl-aws-eks@main
        with:
          args: set image deployment/my-app my-app=${{ steps.build-image.outputs.image }} --record
        env:
          KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_DATA }}

      - name: Verify deployment
        run: |
          kubectl rollout status deployment/my-app --timeout=5m
        env:
          KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_DATA }}
        timeout-minutes: 5

      - name: Rollback on failure
        if: failure()
        run: |
          kubectl rollout undo deployment/my-app
        env:
          KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_DATA }}

      - name: Cleanup
        if: always()
        run: |
          rm -f kubeconfig

      - name: Notify deployment status
        if: always()
        run: |
          echo "Deployment to ${ENVIRONMENT} completed with status ${{ job.status }}"
          # 可选:集成 Slack 或邮件通知
          # curl -X POST -H 'Content-type: application/json' --data '{"text":"Deployment to ${ENVIRONMENT} ${{ job.status }}"}' https://hooks.slack.com/services/xxx
相关推荐
TG_yunshuguoji8 小时前
亚马逊云渠道商:AWS实例自动替换策略在哪里设置?
运维·服务器·云计算·aws
TG:@yunlaoda360 云老大10 小时前
阿里云国际站GPU:阿里云GPU怎么释放实例?
服务器·阿里云·云计算
TG:@yunlaoda360 云老大10 小时前
阿里云国际站GPU:怎么通过控制台自助排查功能诊断GPU?
服务器·阿里云·云计算
runepic10 小时前
阿里云 CentOS 磁盘扩容记录:resize2fs 版本过低导致无法扩容的解决方案
服务器·阿里云·centos·云计算·1024程序员节
TG:@yunlaoda360 云老大12 小时前
腾讯云国际站代理商:腾讯云负载均衡的健康探测源IP,我该如何诊断和配置?
服务器·云计算·腾讯云
TG:@yunlaoda360 云老大15 小时前
腾讯云国际站WAF:如何在腾讯云WAF上设置CC攻击防护,以保障业务数据免被恶意爬取?
服务器·云计算·腾讯云
KevinPedri15 小时前
测试:uk8s创建监控和告警同步飞书等渠道
docker·kubernetes·云计算·1024程序员节
搞科研的小刘选手15 小时前
【云计算专题会议】第二届云计算与大数据国际学术会议(ICCBD 2025)
大数据·人工智能·物联网·5g·云计算·6g·智能通信
电话交换机IPPBX-3CX17 小时前
电话交换机 3CX 数据存储在 AWS S3 的配置文档
aws·亚马逊·ippbx·电话交换机
wanhengidc19 小时前
服务器硬件设备都有哪些?
运维·服务器·网络·游戏·智能手机·架构·云计算