如何使用 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 访问服务?