13

这是我们的环境:

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

我的问题:

  1. 一旦 Jenkins 管道将新建的镜像推送到 ECR,我如何将镜像从 ECR 自动部署到 Kubernetes(作为 pod)?
  2. 我可以在 Jenkins 管道中做到这一点吗?我已经阅读了很多材料,但我找不到应该怎么做。

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

任何帮助,将不胜感激。

4

4 回答 4

20

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

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

  • 构建我的代码并安装依赖项
  • 创建一个具有唯一标签 (commit-id) 的容器 >my-cntnr:12
  • 推送到 ECR
  • 用于 my-pod > set 的 Curl Rancher API(图片my-cntnr:12:)
  • Kubernetes 更新 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)

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

于 2018-05-24T06:13:15.480 回答
1

如果您想了解如何使用 GitOps 在 Kubernetes 上的多个环境中自动化 CI/CD,以便在环境之间进行升级,并在 Pull Requests 上预览环境,您可能想查看我最近在 DevOxx UK 上关于 Jenkins X 的演讲,我在那里进行了现场演示在 GKE 上。尽管 Jenkins X 也适用于AWS、AKS 和 GKE 以及其他 kubernetes 集群

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

于 2018-05-22T08:02:16.603 回答
1

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

*更新

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

于 2018-04-05T08:50:48.540 回答
0

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

例子:

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."
于 2020-02-12T19:07:27.677 回答