1.10 Integrating GitLab with Kubernetes for Continuous Deployment

Level Up Your Deployment Game: GitLab & Kubernetes – A Beginner’s Guide to Continuous Deployment

So, you’re rocking Kubernetes, using GitLab for version control, and you’re ready to take your deployment process to the next level? Great! This post will walk you through integrating GitLab with Kubernetes for Continuous Deployment (CD). We’ll break it down into easy-to-understand steps, so even if you’re relatively new to these technologies, you’ll be deploying like a pro in no time.

Why GitLab & Kubernetes?

Think of GitLab as the command center for your code and Kubernetes as the engine that powers your applications. Together, they offer a powerful combination for:

  • Automated Deployments: Whenever you push changes to your repository, Kubernetes automatically deploys the updated version. No more manual steps!
  • Faster Release Cycles: Automated deployments mean quicker feedback loops and faster releases of new features and bug fixes.
  • Improved Consistency: Deployments become predictable and repeatable, reducing the risk of errors.
  • Simplified Rollbacks: Easily revert to previous versions if something goes wrong, minimizing downtime.

What You’ll Need:

  • A GitLab Account: If you don’t have one, sign up at gitlab.com.
  • A Kubernetes Cluster: This could be a local cluster (like Minikube or Kind), a managed service (like GKE, AKS, or EKS), or a self-managed cluster.
  • kubectl Installed: The command-line tool for interacting with your Kubernetes cluster. Make sure it’s configured to connect to your cluster.
  • A Docker Image: Your application packaged as a Docker image, pushed to a container registry (like Docker Hub or GitLab Container Registry).

Let’s Get Started: The Integration Process

Here’s the basic process we’ll follow:

  1. Create a Kubernetes Service Account: This account will give GitLab the permissions it needs to deploy to your cluster.
  2. Connect GitLab to Your Kubernetes Cluster: We’ll use the Service Account’s credentials to establish the connection.
  3. Create a .gitlab-ci.yml File: This file defines your Continuous Integration/Continuous Deployment (CI/CD) pipeline. It’s the brains of the operation!
  4. Define Your Deployment Strategy: Decide how you want to deploy your application (e.g., rolling update, canary deployment).

Step 1: Create a Kubernetes Service Account

We need to create a Service Account and give it the necessary permissions to deploy applications to your Kubernetes cluster. Here’s how:

  1. Create a Namespace (Optional but Recommended): If you want to isolate your application, create a dedicated namespace:
    kubectl create namespace my-gitlab-app
    
  2. Create a Service Account:
    kubectl create serviceaccount gitlab-deploy -n my-gitlab-app
    
  3. Create a ClusterRoleBinding: This gives the Service Account permissions to deploy resources within the namespace.
    kubectl create clusterrolebinding gitlab-deploy-role --clusterrole=cluster-admin --serviceaccount=my-gitlab-app:gitlab-deploy
    

    Important Note: Granting cluster-admin privileges is often discouraged in production environments. Consider using more granular roles that only grant the necessary permissions. Consult Kubernetes documentation for details on Role-Based Access Control (RBAC).

  4. Get the Service Account Token and CA Certificate: We’ll need these to configure GitLab.
    TOKEN=$(kubectl get secret $(kubectl get serviceaccount gitlab-deploy -n my-gitlab-app -o jsonpath='{.secrets[0].name}') -n my-gitlab-app -o jsonpath='{.data.token}' | base64 --decode)
    CA=$(kubectl get secret $(kubectl get serviceaccount gitlab-deploy -n my-gitlab-app -o jsonpath='{.secrets[0].name}') -n my-gitlab-app -o jsonpath='{.data.ca\.crt}' | base64 --decode)
    
    echo "Token: $TOKEN"
    echo "CA Certificate: $CA"
    

    Note: Save these values securely!

Step 2: Connect GitLab to Your Kubernetes Cluster

Now, let’s connect GitLab to your Kubernetes cluster using the credentials we just gathered:

  1. Go to your GitLab project: Navigate to the project in GitLab where your application code resides.
  2. Navigate to Settings -> CI/CD: Find the CI/CD settings for your project.
  3. Expand “Variables”: We’ll store the sensitive information as CI/CD variables.
    • Add a variable named KUBE_NAMESPACE with the value my-gitlab-app (or your chosen namespace).
    • Add a variable named KUBE_CONTEXT with the value of your cluster’s context name (you can find this using kubectl config current-context). If you’re unsure or want to use the Ingress endpoint, proceed as below.
  4. Navigate to Infrastructure -> Kubernetes: (if you don’t see this, enable “Operations” under your project’s Settings -> General -> Visibility, project features)
  5. Click “Add Kubernetes Cluster” -> “Connect existing cluster”.
  6. Fill in the form:
    • Cluster Name: Choose a descriptive name (e.g., my-k8s-cluster).
    • API URL: This is the address of your Kubernetes API server. You can usually find this in your cloud provider’s documentation (e.g., GKE, AKS, EKS). Alternatively, if your cluster is using an Ingress, use the external IP or hostname of your Ingress controller.
    • CA Certificate: Paste the CA Certificate you obtained in Step 1.
    • Token: Paste the Token you obtained in Step 1.
    • Project Namespace (optional): Leave this blank. We’ll use CI/CD variables instead.
  7. Click “Add Kubernetes cluster”.

Step 3: Create a .gitlab-ci.yml File

The .gitlab-ci.yml file is the heart of your CI/CD pipeline. It tells GitLab how to build, test, and deploy your application. Here’s a simple example that deploys a Docker image to Kubernetes:

stages:
  - build
  - deploy

variables:
  DOCKER_IMAGE: your-docker-username/your-image-name # Replace with your Docker image

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
    - docker build -t $DOCKER_IMAGE:$CI_COMMIT_SHA .
    - docker push $DOCKER_IMAGE:$CI_COMMIT_SHA
  tags:
    - docker

deploy:
  stage: deploy
  image:
    name: bitnami/kubectl:latest
    entrypoint: [""]
  script:
    - kubectl config use-context $KUBE_CONTEXT # Use the context if using cluster-specific deployment
    - kubectl apply -n $KUBE_NAMESPACE -f k8s/deployment.yaml
    - kubectl apply -n $KUBE_NAMESPACE -f k8s/service.yaml
  tags:
    - kubernetes
  only:
    - main  # Only deploy on commits to the 'main' branch

Explanation:

  • stages: Defines the stages in your pipeline (build and deploy).
  • variables: Defines variables used throughout the pipeline. Replace your-docker-username/your-image-name with your actual Docker image name.
  • build: This stage builds and pushes your Docker image to your container registry.
    • image: docker:latest: Uses the Docker image to perform Docker operations.
    • services: - docker:dind: Uses Docker-in-Docker to build the image.
    • script: The commands to execute:
      • Logs into the container registry.
      • Builds the Docker image with a tag based on the commit SHA.
      • Pushes the image to the registry.
  • deploy: This stage deploys your application to Kubernetes.
    • image: bitnami/kubectl:latest: Uses an image with kubectl installed.
    • script: The commands to execute:
      • kubectl config use-context $KUBE_CONTEXT: Sets the Kubernetes context. (Optional, if using cluster endpoint)
      • kubectl apply -n $KUBE_NAMESPACE -f k8s/deployment.yaml: Applies the Kubernetes deployment manifest.
      • kubectl apply -n $KUBE_NAMESPACE -f k8s/service.yaml: Applies the Kubernetes service manifest.
  • tags: Specifies which GitLab Runner should execute the job. You’ll need a runner configured with Docker and Kubernetes access.
  • only: - main: This ensures that the deployment only happens when changes are pushed to the main branch (or your desired branch).

Step 4: Define Your Deployment Strategy (Kubernetes Manifests)

The .gitlab-ci.yml file references k8s/deployment.yaml and k8s/service.yaml. These files contain the Kubernetes manifests that define how your application will be deployed. Create a k8s directory in your project and create these files within it.

Example k8s/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-deployment
spec:
  replicas: 3 # Adjust the number of replicas
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: your-docker-username/your-image-name:$CI_COMMIT_SHA  # Use the image built in the CI pipeline
        ports:
        - containerPort: 8080  # Adjust the port your application uses

Example k8s/service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080 #  Adjust the port your application uses
  type: LoadBalancer # Or NodePort, ClusterIP, depending on your cluster and needs

Important Notes for the Kubernetes Manifests:

  • Image Tag: Notice that the image in the deployment.yaml uses the $CI_COMMIT_SHA variable. This ensures that each deployment uses the specific Docker image built in the CI pipeline.
  • Ports: Make sure the containerPort and targetPort values match the port your application is listening on.
  • Service Type: Choose the appropriate type for your service. LoadBalancer is common for cloud providers, while NodePort or ClusterIP are often used for local clusters.

Testing Your Deployment

  1. Commit and Push Your Changes: Commit the .gitlab-ci.yml, k8s/deployment.yaml, and k8s/service.yaml files to your GitLab repository and push them to the main branch.
  2. Monitor the Pipeline: Go to the “CI/CD” section of your GitLab project and watch the pipeline run.
  3. Verify the Deployment: Once the pipeline completes successfully, use kubectl to check if your application is running in your Kubernetes cluster:
    kubectl get deployments -n my-gitlab-app
    kubectl get services -n my-gitlab-app
    kubectl get pods -n my-gitlab-app
    

    You should see your deployment and service listed, and the pods associated with your deployment should be running.

Troubleshooting Tips:

  • Check Pipeline Logs: If the pipeline fails, carefully examine the logs for errors.
  • Verify Kubernetes Credentials: Double-check that the token and CA certificate you provided to GitLab are correct.
  • Review Kubernetes Manifests: Ensure that your deployment.yaml and service.yaml files are correctly configured.
  • Check Kubernetes Events: Use kubectl describe pod <pod-name> -n my-gitlab-app to check for events related to your pods that might indicate problems.

Beyond the Basics:

This guide provides a basic foundation for integrating GitLab with Kubernetes. Here are some areas to explore further:

  • Helm: Use Helm to package and manage your Kubernetes applications.
  • Advanced Deployment Strategies: Implement strategies like canary deployments, blue-green deployments, or rolling updates with health checks.
  • Auto Scaling: Configure Kubernetes to automatically scale your application based on traffic.
  • GitOps: Manage your Kubernetes infrastructure and applications using Git as the single source of truth.

Conclusion

Integrating GitLab with Kubernetes is a powerful way to automate your deployment process, improve your release velocity, and reduce errors. By following the steps outlined in this guide, you can get started with Continuous Deployment and take your application development workflow to the next level! Happy deploying!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top