How to auto deploy Docker containers from Amazon ECR to Kubernetes using Jenkins

MasoudSat picture MasoudSat · Apr 4, 2018 · Viewed 13.9k times · Source

This is our environment:

  1. I have a Kubernetes cluster running on Amazon.
  2. Jenkins CI/CD running on Amazon that connects to a private GitLab and builds our services as Docker images.
  3. Amazon ECR that stores our Docker images.

My questions:

  1. How can I auto deploy images from ECR to Kubernetes (as pods) once the Jenkins pipeline pushes newly built images to ECR?
  2. Can I do that within Jenkins pipeline? I've read lots of material but I couldn't find how should it be done.

There is also a 3rd party tool like Keel but it doesn't support Amazon ECR (Webhook problem with ECR).

Any help would be appreciated.

Answer

damitj07 picture damitj07 · May 24, 2018

I have a similar workflow and I hope this helps you get some direction. I am using bitbucket pipeline for CI, but I am sure Jenkins will work fine as well.

This is what I do in my CI flow :

  • Build my code and install dependencies
  • Create a container with a unique tag ( commit-id ) > my-cntnr:12
  • Push to ECR
  • Curl Rancher API for my-pod > set(image:my-cntnr:12)
  • Kubernates updates the pod and pulls the container with tag 12 from ECR

Here is the script for reference :

      - 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

note: Since I am using Rancher, I can use Rancher API to update pods and their configuration.


Now for the ECR credentials part for Kubernetes, you have to create a secret ( a Kubernetes only entity), this secret is created using your AWS ECR details. Then you can use this secret in your pod.yml as image-pull-secret. This will tell k8 to use the secret and pull the image from ECR

I have a simple script to quickly do that.

#
# RUN me where kubectl is available,& make sure to replace account,region etc
#
ACCOUNT=123456789
REGION=my-region
SECRET_NAME=${REGION}-ecr-registry
[email protected] ( 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}"

And this is how you can use it in your 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)

I've written a detailed article about the process as well. Please find it here.