如何使用 Jenkins 将 Docker 容器从 Amazon ECR 自动部署到 Kubernetes

Posted

技术标签:

【中文标题】如何使用 Jenkins 将 Docker 容器从 Amazon ECR 自动部署到 Kubernetes【英文标题】:How to auto deploy Docker containers from Amazon ECR to Kubernetes using Jenkins 【发布时间】:2018-09-14 05:15:39 【问题描述】:

这是我们的环境:

    我有一个在 Amazon 上运行的 Kubernetes 集群。 在 Amazon 上运行的 Jenkins CI/CD 连接到私有 GitLab 并将我们的服务构建为 Docker 映像。 存储我们的 Docker 映像的 Amazon ECR。

我的问题:

    当 Jenkins 管道将新建的镜像推送到 ECR 后,如何将镜像从 ECR 自动部署到 Kubernetes(作为 pod)? 我可以在 Jenkins 管道中执行此操作吗?我已经阅读了很多资料,但我找不到应该怎么做。

还有像 Keel 这样的第 3 方工具,但它不支持 Amazon ECR(ECR 的 Webhook 问题)。

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

我有类似的工作流程,希望这可以帮助您找到方向。我正在为 CI 使用 bitbucket 管道,但我相信 Jenkins 也能正常工作。

这就是我在 CI 流程中所做的:

构建我的代码并安装依赖项 创建一个具有唯一标签 (commit-id) 的容器 > my-cntnr:12 推送到 ECR Curl Rancher API for my-pod > set(image:my-cntnr:12) Kubernates 更新 pod 并从 ECR 中拉取标签为 12 的容器

这是供参考的脚本:

      - composer install --no-interaction
      - docker build -t cms .
      - docker tag myrepo:latest 123456789.dkr.ecr.my-region.amazonaws.com/myrepo:$BITBUCKET_BUILD_NUMBER
      - aws ecr get-login --no-include-email --region my-region >> login.sh
      - sh login.sh
      - docker push 123456799.dkr.ecr.my-region.amazonaws.com/myrepo:$BITBUCKET_BUILD_NUMBER
      - sh .docker/workload-update.sh // my curl script calling rancher API

注意:由于我使用的是 Rancher,我可以使用 Rancher API 来更新 pod 和 他们的配置。


现在,对于 Kubernetes 的 ECR 凭证部分,您必须创建一个密钥(仅限 Kubernetes 实体),该密钥是使用您的 AWS ECR 详细信息创建的。然后你可以在你的 pod.yml 中使用这个秘密作为 image-pull-secret。这将告诉 k8 使用秘密并从 ECR 中提取图像

我有一个简单的脚本可以快速完成。

#
# RUN me where kubectl is available,& make sure to replace account,region etc
#
ACCOUNT=123456789
REGION=my-region
SECRET_NAME=$REGION-ecr-registry
EMAIL=email@email.com ( can be anything)

#
# Fetch token (which will expire in 12 hours)
#

TOKEN=`aws ecr --region=$REGION get-authorization-token --output text --query authorizationData[].authorizationToken | base64 -d | cut -d: -f2`

#
# Create or replace registry secret
#

kubectl delete secret --ignore-not-found $SECRET_NAME
kubectl create secret docker-registry $SECRET_NAME \
 --docker-server=https://$ACCOUNT.dkr.ecr.$REGION.amazonaws.com \
 --docker-username=AWS \
 --docker-password="$TOKEN" \
 --docker-email="$EMAIL"

这就是你如何在你的 pod.yml 中使用它

apiVersion: v1
kind: Pod                                            
metadata:
  name: my-app   
  labels:
    app: my-app                              
spec:                                                
  containers:
    - image: 123456789.dkr.ecr.my-region.amazonaws.com/my-repo
      name: -cntnr                            
      ports:
        - containerPort: 8080    
  imagePullSecrets:
  - name: my-secret-name ( this will be same as name of secret we created earlier)

我也写了一篇关于这个过程的详细文章。请找here。

【讨论】:

非常简单的解决方案。谢谢 很好的答案和博客。谢谢!【参考方案2】:

是的,这是可能的。您可以将 Amazon ECR 用于您的 Kubernetes 集群,但您需要 create a secret with credentials。您可以为 Jenkins 开发一个管道,它将自动将更新部署到您的 Kubernetes 集群。为此,您需要配置触发器,例如成功完成构建图像的先前管道。您可以使用 kubernetes-plugin 来开发您的管道,或者您可以使用新的图像标签调用 kubectl update。您可以使用默认的部署更新或第 3 方工具更新您的集群,例如 helm。

*更新

有一个很好的文档:Using AWS EC2 Container Registry. 对于 Jenkins 和 Kubernetes,我建议您使用 kube2iam,它有助于避免授权令牌过期。 为 Kubernetes 节点和 Jenkins 创建自定义角色,也不要忘记为 kube2iam 添加分配角色的权限。

【讨论】:

感谢您的回复。 Kubernetes 文档针对 AWS 写的不是很好,大部分材料默认是针对 GKE 的。 AWS ECR 的身份验证机制完全不同。在将映像推送到 AWS ECR 之前,您应该运行以下 shell 命令进行身份验证:$(aws ecr get-login --region us-east-2 --no-include-email) 我刚刚用其他信息更新了答案【参考方案3】:

如果您想了解如何使用 GitOps 在 Kubernetes 上的多个环境中实现 CI/CD 自动化,以便在环境之间进行升级,并在 Pull Requests 上预览环境,您可能想查看my recent talk on Jenkins X at DevOxx UK,我在 GKE 上对此进行了现场演示。虽然 Jenkins X 在 AWS, AKS and GKE and other kubernetes clusters too 上工作。

当您将更改合并到主分支时,Jenkins X 会为您的应用创建一个新的语义版本化分发(pom.xml、jar、docker 映像、helm 图表)。然后,管道会自动生成拉取请求,以通过 GitOps 在所有环境中推广您的应用程序。然后,您可以决定在应用发布管道完成后回滚版本(因为还有一个环境管道)。

【讨论】:

【参考方案4】:

非常有帮助 - 谢谢。一个快速补充:如果您使用命名空间,则需要将 -n <namespace> 添加到每个 kubectl 命令才能使其工作。我在您的 Medium 文章中的 cron 作业脚本中添加了一个 NAMESPACE 环境变量来处理这个问题。

例子:

ACCOUNT=123456789876
REGION=your-region
NAMESPACE=your-namespace
SECRET_NAME=$REGION-ecr-registry
EMAIL=dummy.email@email.com
TOKEN=`aws ecr get-login --region $REGION --registry-ids $ACCOUNT | cut -d' ' -f6`
echo "ENV variables setup done."
kubectl delete secret --ignore-not-found $SECRET_NAME -n $NAMESPACE
kubectl create secret docker-registry $SECRET_NAME -n $NAMESPACE \
--docker-server=https://$ACCOUNT.dkr.ecr.$REGION.amazonaws.com \
--docker-username=AWS \
--docker-password="$TOKEN" \
--docker-email="$EMAIL"
echo "Secret created by name. $SECRET_NAME"
kubectl patch serviceaccount default -p '"imagePullSecrets":["name":"'$SECRET_NAME'"]' -n $NAMESPACE
echo "All done."

【讨论】:

以上是关于如何使用 Jenkins 将 Docker 容器从 Amazon ECR 自动部署到 Kubernetes的主要内容,如果未能解决你的问题,请参考以下文章

如何使用未部署在 swarm 中的 docker 容器从 docker swarm 访问服务?

如何从 Docker 容器克隆 Git 存储库

从jenkins docker ecs容器中访问ecr图像

使用阿里云容器服务Jenkins实现持续集成和Docker镜像构建

在容器中运行 Jenkins pipeline 任务

如何通过 Jenkins 更新 ECS 容器/TASK?