Win $20,000. Help build the future of education. Answer the call. Learn more

IBM Developer Blog

Follow the latest happenings with IBM Developer and stay in the know.

Learn more about using a GitHub Action to deploy to IBM Cloud Kubernetes Service.

GitHub Actions are a relatively new feature that enable continuous integration and continuous delivery (CI/CD) for a particular repository. I decided to write my own GitHub Action to deploy to IBM Cloud Kubernetes Service, which was largely inspired by the one written for GKE.

In this blog, I first discuss the GitHub Action file itself, then show some fun output, and finally talk about setting up the bits on IBM Cloud. Please note that all of the source code I refer to is available on

Before I get started, I have to thank JJ Asghar and Paul Czarkowski for helping me clean this up.

Update 05/27/2020

Our deploy to IKS action was accepted by the GitHub Action community and appears as a tile when a new action is created! Woo hoo!

IKS tile

The GitHub Action YAML file

Let’s look at this file in chunks. Note that you can see the file in its entirety in the repo.

The following example shows the simplest block:

name: Build and Deploy to IKS

on: [push]

You simply give your action a name and choose to deploy on push or on release. Push is easier to debug, so that’s what I’m using. Also, shout out to the ACT tool for enabling local support for GitHub Actions.

This next part defines a few of the variables that the script calls. Some of these are “secrets”, which are saved in your repo settings and obfuscating in the logs while others are defined in the YAML. The only one that needs to be a secret is the API key for IBM Cloud. You can easily get a new IBM Cloud API key from the IAM settings.

The IMAGE_NAME, DEPLOYMENT_NAME, and PORT vary based on what your application is doing. The REGISTRY_HOSTNAME and IBM_CLOUD_REGION vary based on where your cluster is hosted. The IKS_CLUSTER can be the name or ID of the IBM Cloud Kubernetes Service cluster you’re using.

Two secrets, IBM Cloud Registry name, and IBM Cloud API key

# Environment variables available to all jobs and steps in this workflow
  GITHUB_SHA: ${{ github.sha }}
  IBM_CLOUD_REGION: us-south
  IMAGE_NAME: hello-python
  IKS_CLUSTER: bq1sm2gd0sjtps7ajoa0 # name or id of cluster
  DEPLOYMENT_NAME: hello-python
  PORT: 5001

This next part defines all the jobs and steps. You only have one job since you want the steps to run sequentially on the same container. If you break this up then you’ll have to start sharing context and other things. Maybe this can be solved later.

The gist of this is checking out the codebase (this is a GitHub supported action) and then installing and authenticating with the IBM Cloud command-line interface (CLI). You also install the plugins required to communicate with Kubernetes clusters. The login step is where you use your IBM_CLOUD_API_KEY secret.


    name: Setup, Build, Publish, and Deploy
    runs-on: ubuntu-latest

    - name: Checkout
      uses: actions/checkout@v2

    # Download and Install IBM Cloud CLI
    - name: Install IBM Cloud CLI
      run: |
        curl -fsSL | sh
        ibmcloud --version
        ibmcloud config --check-version=false
        ibmcloud plugin install -f kubernetes-service
        ibmcloud plugin install -f container-registry

    # Authenticate with IBM Cloud CLI
    - name: Authenticate with IBM Cloud CLI
      run: |
        ibmcloud login --apikey "${IBM_CLOUD_API_KEY}" -r "${IBM_CLOUD_REGION}" -g default
        ibmcloud cr region-set "${IBM_CLOUD_REGION}"
        ibmcloud cr login

The next two steps are pretty vanilla; you build the image and then push it. The neat part about this is that you tag that version with the git SHA and the image is pushed to the IBM Container Registry.

    # Build the Docker image
    - name: Build with Docker
      run: |
          --build-arg GITHUB_SHA="$GITHUB_SHA" \
          --build-arg GITHUB_REF="$GITHUB_REF" .

    # Push the image to IBM Container Registry
    - name: Push the image to ICR
      run: |

The next part is where you actually deploy your application. I got a little cheeky here and re-generated the deploy and service CRDs. I applied them on every deployment, so it also works in a scenario where you don’t have the app deployed yet.

    # Deploy the Docker image to the IKS cluster
    - name: Deploy to IKS
      run: |
        ibmcloud ks cluster config --cluster $IKS_CLUSTER
        kubectl config current-context
        kubectl create deployment $DEPLOYMENT_NAME --image=$REGISTRY_HOSTNAME/$ICR_NAMESPACE/$IMAGE_NAME:$GITHUB_SHA --dry-run -o yaml > deployment.yaml
        kubectl apply -f deployment.yaml
        kubectl rollout status deployment/$DEPLOYMENT_NAME
        kubectl create service loadbalancer $DEPLOYMENT_NAME --tcp=80:$PORT --dry-run -o yaml > service.yaml
        kubectl apply -f service.yaml
        kubectl get services -o wide

An impressive UI

The GitHub Action user interface (UI) is very nice and intuitive. You can see all the steps plainly and click on each one for expanded logs. You can also see where your app is being hosted and if it was rolled out correctly.

GitHub Action output

The application itself is simple (it just shows environment variables in a pretty table).

GitHub Action table

IBM Cloud bits

First, you need an IBM Cloud Kubernetes Service cluster (any size will do). I highlighted the cluster name and ID and either of these will work as the IKS_CLUSTER variable.

IBM Cloud Kubernetes Service cluster

Then, you need a namespace in the IBM Container Registry. Mine is stevemar2. You can access your list here.

IBM Container Registry namespaces

The last step is an IBM Cloud API key, which is available through the IAM settings.

API key


And that’s it! Overall, my first real experience with GitHub Actions went well. Feel free to re-use any of this content or code. It should work, provided your application isn’t too complex.