October 10, 2023

Deploying to Kubernetes with Gitness

Table of Contents

Deploying applications to Kubernetes with Gitness involves setting up Gitness as a containerized app, configuring Kubernetes clusters, and creating deployment pipelines. This process leverages Gitness's continuous integration and deployment capabilities to streamline application management and ensure efficient, scalable deployments.

*Harness Open Source is the next evolution of Gitness and takes Gitness to the next level by offering an end-to-end software delivery platform that enhances productivity and accelerates software development cycles. Learn more here.


Gitness is an open-source Git solution designed with developers in mind. At its core, it offers a reliable space to host git repositories. However, its capabilities extend far beyond that. If you've been keeping up with recent news and announcements, you've likely come across its features for code hosting, collaboration, and continuous integration. In this blog, I'll demonstrate how you can leverage this platform to deploy to Kubernetes, thereby completing the full DevOps cycle of build and deploy.

If videos are more your style, we've got you covered:

Before you begin

You will be running Gitness as a containerized application, and during this process, you'll also deploy a sample application to a Kubernetes cluster. To get started, ensure you have the following:

  • Docker engine running.
  • A Kubernetes cluster (You can use k3d or a managed Kubernetes service).
  • kubectl installed and user is authenticated 
  • Your own Kubernetes manifest (this is optional).

A note: Ensure your user or service account on the Kubernetes cluster has the ability to create and list deployments, service accounts, roles, rolebindings, and more. It's typically advised to use a service account and its associated token instead of a user account token within a build/deploy system. Here's a manifest that includes definitions for a service account, role, role binding, and secret. By using this, you'll be able to leverage the gitness-sa service account to initiate deployments from Gitness.

Save the provided content as gitness-sa-manifest.yaml.

Let's use a dedicated namespace called gitness:

kubectl create namespace gitness

kubectl config set-context --current --namespace=gitness

Once done, execute the following command to create the necessary resources:

kubectl apply -f gitness-sa-manifest.yaml

Make a note of the gitness-sa-token. We’ll use it later:

TOKEN=$(kubectl get secret gitness-sa-token -n gitness -o=jsonpath='{.data.token}' | base64 --decode)

echo -e $TOKEN | tr -d '\n'

The echo command trims any newline character from within the token to avoid formatting errors when copying over.

Setup and configure Gitness

Setting up Gitness is straightforward and it's suitable for lightweight machines — yes, even on a $4 DigitalOcean VM. If you already have the Docker engine up and running, you can get started with Gitness with the following command:

Visit `localhost:3000` in your browser and sign up using a User ID, Email, and Password. Once you've successfully registered and are presented with the initial Gitness interface, you can choose to create a new project or import an existing one. A project in Gitness is similar to a group in GitLab or an organization in GitHub.

Let's initiate a project named gitness-cd. After it's set up, we will proceed to add two secrets that Gitness requires to orchestrate a deployment on your Kubernetes cluster. From the left navigation pane, select Secrets followed by + New Secret. You'll then create the following two secrets: k8s-server and gitness-sa-token.

For the k8s-server secret, use the output from the subsequent instructions as its value. To retrieve the URL of the Kubernetes API server:

kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'

We already made a note of gitness-sa-token in the previous section so use that value to create gitness-sa-token secret.

A Word on Gitness's Current Stage

Gitness is still in the early days and is going through rapid development. One of the known issues is that when using a script within a run step, the Gitness secrets are printed in the pipeline execution log in plain text. The Gitness community continues to report similar issues and this feedback will guide this platform's evolution. With your help, we aspire to set new industry standards for open-source code hosting & pipeline engine.

You might observe numerous shell script commands embedded within the CD pipeline and wonder, "Aren't we transitioning away from custom shell scripts?" Indeed, as Gitness matures, expect plugins and integrations that will streamline Kubernetes cluster configurations. This will eventually enable application deployments without reliance on shell scripting. For the time being, bear with the temporary solutions. The essence of this blog is to showcase the promising horizon awaiting Gitness.

Using Gitness for source code management

You can import an existing GitHub or GitLab repository but for this blog, let’s create a new repository in Gitness. From the left navigation bar, select Repository and click on New Repository. Give this repository a name, for example, demo-repo and click Create Repository. You can keep all other options as default. 

Once the repository is created, you’ll see an option to add a new file. You can generate git credentials, clone the repository, and work from a terminal. Since we’ll be adding one file, let’s use the Gitness UI to add that file. Click on +New File, give the file a name nginx-deployment.yaml, and paste the following code:

Alright, let's just commit those changes straight to the main branch. By the way, if you've got a Kubernetes app and some manifests lying around, feel free to use yours. Otherwise, our sample nginx-deployment.yaml has got you covered.

Create a deployment pipeline in Gitness

The pipeline concept in Gitness is a child concept under the Repository entity. You can create one or more pipelines for a given repository. For this blog, assume that you have a continuous integration pipeline that can build your code, run tests, and push an image to an image registry. In this section, we’ll create a deployment pipeline that can deploy that image to your Kubernetes cluster. Let’s use nginx:latest as an example but you can swap this with your choice of a container image. 

Getting started is straightforward:

  1. Navigate to RepositoryPipelines and then click + New Pipeline.
  2. Name it something relevant like k8s-deploy.
  3. The branch, by default, should be set to main, and the YAML path will indicate where Gitness archives the pipeline in a code format.
  4. Once you hit Create, a template pipeline will be at your disposal.

Replace the sample pipeline with the following pipeline definition:

Click Save and Run from the top-right corner and watch your deployment pipeline logs to ensure that Gitness deployed an nginx application on your Kubernetes cluster. A successful pipeline execution will look something like this:

Pipeline execution logs for both CI and CD stages

Unfolding the cdstep will reveal the smooth sailing of the nginx-deployment pods. You're probably brimming with questions about this pipeline definition, right? No worries – we're diving deep into those in the next section.

Breaking down the pipeline definition

Let's delve a bit deeper into the Gitness pipeline structure. A pipeline in Gitness can have one or multiple stages. In our example, we have two defined stages: cistage and cdstage.

Both of these stages utilize the alpine/k8s:1.26.9 container image, which includes the kubectl tool. The cistage is more of a placeholder right now, simply executing an echo command.

The cdstage, however, does the heavy lifting. It initiates the deployment through a series of shell commands. First, it establishes a connection to the Kubernetes cluster, leveraging two secrets provided by Gitness during runtime. Next, it triggers a deployment using the nginx-deployment file from our Gitness demo-repo. To round things off, it checks to confirm the successful launch of the pods.

It's worth noting that these commands are executed within the Gitness run step, and they operate from the root directory of your git repository.

Challenges with deployment from a Continuous Integration (CI) tool

While Continuous Integration (CI) tools are indispensable for maintaining code quality, they aren't always suitable for deployment tasks. Here's why:

  1. Nature of CI Tools: CI tools are essentially designed to run workloads sequentially. Deploying to dynamic environments requires a level of adaptability that CI tools might not offer.
  1. Deployment Strategies: Advanced deployment methods, like blue-green or canary releases, can be challenging to execute with standard CI platforms.
  1. Statelessness of CI: CI processes generally don't retain state. This can lead to deployment inconsistencies or errors due to the lack of contextual awareness.
  1. Security Concerns: Deployments often need high-level permissions. Using CI tools for such tasks can expose systems to security vulnerabilities. Now, you might be thinking, "Why did we let Gitness into our Kubernetes cluster then?" Think of Gitness less like a regular CI tool and more like a complete software delivery platform.
  1. Scalability Challenges: As a business grows, it might deploy to multiple regions or across environments. CI tools can struggle to keep pace with such expanding requirements.

If you’re looking for an advanced continuous delivery platform, give Harness Continuous Delivery (CD) a try! From deploying multiple services across multiple environments to comprehensive GitOps support, Harness CD can deploy any app, anywhere without any scripting involved.

Open Source
Continuous Delivery & GitOps