Deployment to Kubernetes

Using the Codefresh GUI to deploy to a Kubernetes cluster

In this tutorial we will see how you can use Codefresh to deploy a Docker image to a Kubernetes cluster and also how to setup an automated pipeline to automatically redeploy it when the source code changes.

Even though, in this tutorial we use Codefresh to deploy docker images directly to the Kubernetes cluster, in production we suggest you use Helm instead. Helm is a package manager for Kubernetes that allows you to deploy multiple applications at once as a single entity (Helm Charts) and also perform rollbacks to previous versions. Like Kubernetes, Codefresh has native support for Helm deployments including a release dashboard.

Notice that for this tutorial we will use the GUI provided by Codefresh to both create the Kubernetes service inside the cluster and also to create the CI/CD pipeline that keeps it up to date. In a real world scenario it is best if you use Codefresh YAML which is much more powerful and flexible.

Codefresh also offers several alternative ways of deploying to Kubernetes.

Overview

At the end of this tutorial we will have a pipeline that:

  1. Checks out code from GitHub and creates a Docker image
  2. Stores it in the internal Codefresh Docker registry
  3. Notifies the K8s cluster that a new version of the application is present. Kubernetes will pull the new image and deploy it

Deployment overview

A complete CI/CD pipeline

For simplicity reasons, we will use the built-in Docker registry that is available to all Codefresh accounts. For your own application you can also integrate with any other external Docker registry.

Prerequisites

It is assumed that:

Notice that for this tutorial you don’t need a Kubernetes deployment file. Codefresh will create one for you via its friendly GUI. If you already have an existing deployment file for your own application, consult the main K8s documentation on how to use it.

Giving the Kubernetes cluster read access to the internal Codefresh registry

A Kubernetes cluster deploys applications by pulling images from a Docker registry. In most cases your Docker image will be on a private Docker registry. Therefore, you need to grant rights to the cluster so that it has read access to the images that are pushed on the Docker registry by Codefresh.

Each Codefresh account comes with its own built-in Docker registry, but by default this is not accessible externally. To make this registry “external” we need to declare it first as an integration.

Creating an API key for the Codefresh internal registry

Click User settings on the left sidebar. At the bottom of the User settings screen, click the button Generate at the Codefresh Registry section.

Generating an API key for Codefresh registry

Generating an API key for Codefresh registry (click image to enlarge)

In the dialog that appears, enter a name for your key (this name doesn’t affect anything, it is just for you to remember the purpose of the key) and click the Create button. Your key will be generated. You can click the “eye” button inside the text field to view its full form.

Copying the Codefresh Registry Key

Copying the Codefresh Registry Key (click image to enlarge)

Write down this token as it will never be visible again apart from this screen.

Making the internal Codefresh Registry available to your Kubernetes cluster

After you have the API key, go to your Account Configuration, by clicking on Account Settings on the left sidebar. On the first section called Integrations click the Configure button next to Docker Registry.

Codefresh Registry Integration

Codefresh Registry Integration (click image to enlarge)

Then click the Add Registry button and select the Codefresh registry from the top down menu. Enter your Codefresh username in the respective field and enter the token that we created in the previous section.

Adding the internal Registry

Adding the internal Registry (click image to enlarge)

Finally click the Test button to make sure that everything works ok, and then the Save button to apply your changes. The Codefresh Internal registry is now ready to be used by your Kubernetes cluster.

Deploying a Docker image to Kubernetes manually

Codefresh offers a dedicated GUI that allows you to deploy any Docker image to your cluster without writing any configuration files at all.

Click the Kubernetes button from the left side bar. The screen that appears is the Codefresh overview of your Kubernetes cluster that shows all your deployments (pods and namespaces)

Codefresh K8s Dashboard

Codefresh K8s Dashboard (click image to enlarge)

Click the Add Service button on the top right. The screen that appears is a friendly UI that allows you to create a Kubernetes deployment (and associated service). You can also toggle the top right button to define a Kubernetes YAML yourself, but for the purposes of this tutorial we will only use the GUI.

Codefresh K8s add service

Codefresh K8s add service (click image to enlarge)

The fields in this screen are:

  • Cluster - elect your cluster if you have more than one.
  • Namespace - select the namespace where the application will be deployed to (default will work just fine).
  • Service Name - enter any arbitrary name for your service.
  • Replicas - how many replicas you want for resiliency. This affects pricing, so 1 is a good value for a demo.
  • Expose Port - check it so that your application is available outside the cluster .
  • Image - enter the fully qualified name of your Docker image.
  • Image Pull Request - select the Codefresh registry and create a pull secret for it.
  • Internal Ports - which port is exposed from your application. The example Python app we deploy, exposes 5000.

From the same screen you can also define environment variables and cpu/mem limits.

You can see the full name of the Docker image, in the Images tab of the Codefresh GUI of your build.

Finding the full name of a Docker image

Finding the full name of a Docker image (click image to enlarge)

By default, Codefresh appends the branch name of a git commit to the resulting Docker image. This is why in the Image field we used the branch name as tag

Do not use latest for your deployments. This doesn’t help you to understand which version is deployed. Use either branch names or even better git hashes so that you know exactly what is deployed on your Kubernetes cluster. Notice also that the YML Codefresh is creating has an image pull policy of always, so the cluster will always redeploy the latest image even if it has the same name as the previous one.

Finally click the deploy button. Codefresh will create a Kubernetes YAML file behind the scenes and apply it to your Kubernetes cluster. The cluster will contact the Codefresh registry and pull the image. The cluster will then create all the needed resources (service, deployments, pods) in order to make the application available.

You can watch the status of the deployment right from the Codefresh UI.

Codefresh K8s deployment

Codefresh K8s deployment (click image to enlarge)

Once the deployment is complete, you will also see the public URL of the application. You can visit it in the browser and see the application running.

Example Python Application

Example Python Application (click image to enlarge)

This concludes the manual deployment. We deployed a Docker image from Codefresh to a Kubernetes cluster without writing any YAML files at all! The next step is to automate this process so that every time a commit happens in git, the application will be redeployed.

Automating deployments to Kubernetes

The application is now running successfully in the Kubernetes cluster. We will setup a pipeline in Codefresh so that any commits that happen in GitHub, are automatically redeploying the application, giving us a true CI/CD pipeline.

To do this, we will add two extra steps in the basic pipeline created in the previous tutorial.

Here is the complete pipeline:

codefresh.yml

version: '1.0'
stages:
  - checkout
  - package
  - test 
  - upload
  - deploy
steps:
  main_clone:
    title: Cloning main repository...
    type: git-clone
    repo: '${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}'
    revision: '${{CF_REVISION}}'
    stage: checkout
  MyAppDockerImage:
    title: Building Docker Image
    type: build
    stage: package
    image_name: my-app-image
    working_directory: ./
    tag: '${{CF_BRANCH}}'
    dockerfile: Dockerfile
  MyUnitTests:
    title: Running Unit tests
    image: '${{MyAppDockerImage}}'
    stage: test 
    commands:
      - python setup.py test    
  MyPushStep:
    title: Pushing to DockerHub Registry
    type: push
    stage: upload
    tag: '${{CF_BRANCH}}'
    candidate: '${{MyAppDockerImage}}'
    image_name: kkapelon/pythonflasksampleapp #Change kkapelon to your dockerhub username
    registry: dockerhub # Name of your integration as was defined in the Registry screen
  DeployToMyCluster:
    title: deploying to cluster
    type: deploy
    stage: deploy
    kind: kubernetes  
    ## cluster name as the shown in account's integration page
    cluster:  my-demo-k8s-cluster
    # desired namespace
    namespace: default
    service: python-demo
    candidate:
      # The image that will replace the original deployment image 
      # The image that been build using Build step
      image: kkapelon/pythonflasksampleapp:${{CF_BRANCH}}
      # The registry that the user's Kubernetes cluster can pull the image from
      # Codefresh will generate (if not found) secret and add it to the deployment so the Kubernetes master can pull it
      registry: dockerhub   
      

You can see that we have added a new deploy step at the end of the pipeline. Deploy steps allow you to deploy Kubernetes applications in a declarative manner. Codefresh offers many more ways for Kubernetes deployments.

The deploy step will update an existing Kubernetes deployment and will optionally create a pull secret for the image if needed, but it will not create any Kubernetes services (which is ok in our case as we created it manually in the previous section).

Once all the details are filled in the pipeline editor, click the Save button.

Now we will change the application in the production branch and commit/push the change to Git.

Git change

Git change (click image to enlarge)

Codefresh will pick the change automatically and trigger a new build that deploys the new version:

Codefresh K8s deployment

Codefresh K8s deployment (click image to enlarge)

Once the build is complete, if you visit again the URL you will see your change applied.

Example Python Application after change

Example Python Application after change (click image to enlarge)

You now have a complete CI/CD pipeline in Codefresh for fully automated builds to Kubernetes!