![]()
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:
- Create a Kubernetes Service Account: This account will give GitLab the permissions it needs to deploy to your cluster.
- Connect GitLab to Your Kubernetes Cluster: We’ll use the Service Account’s credentials to establish the connection.
- Create a
.gitlab-ci.ymlFile: This file defines your Continuous Integration/Continuous Deployment (CI/CD) pipeline. It’s the brains of the operation! - 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:
- Create a Namespace (Optional but Recommended): If you want to isolate your application, create a dedicated namespace:
kubectl create namespace my-gitlab-app - Create a Service Account:
kubectl create serviceaccount gitlab-deploy -n my-gitlab-app - 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-deployImportant Note: Granting
cluster-adminprivileges 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). - 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:
- Go to your GitLab project: Navigate to the project in GitLab where your application code resides.
- Navigate to Settings -> CI/CD: Find the CI/CD settings for your project.
- Expand “Variables”: We’ll store the sensitive information as CI/CD variables.
- Add a variable named
KUBE_NAMESPACEwith the valuemy-gitlab-app(or your chosen namespace). - Add a variable named
KUBE_CONTEXTwith the value of your cluster’s context name (you can find this usingkubectl config current-context). If you’re unsure or want to use the Ingress endpoint, proceed as below.
- Add a variable named
- Navigate to Infrastructure -> Kubernetes: (if you don’t see this, enable “Operations” under your project’s Settings -> General -> Visibility, project features)
- Click “Add Kubernetes Cluster” -> “Connect existing cluster”.
- 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 Certificateyou obtained in Step 1. - Token: Paste the
Tokenyou obtained in Step 1. - Project Namespace (optional): Leave this blank. We’ll use CI/CD variables instead.
- Cluster Name: Choose a descriptive name (e.g.,
- 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. Replaceyour-docker-username/your-image-namewith 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 withkubectlinstalled.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 themainbranch (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
imagein thedeployment.yamluses the$CI_COMMIT_SHAvariable. This ensures that each deployment uses the specific Docker image built in the CI pipeline. - Ports: Make sure the
containerPortandtargetPortvalues match the port your application is listening on. - Service Type: Choose the appropriate
typefor your service.LoadBalanceris common for cloud providers, whileNodePortorClusterIPare often used for local clusters.
Testing Your Deployment
- Commit and Push Your Changes: Commit the
.gitlab-ci.yml,k8s/deployment.yaml, andk8s/service.yamlfiles to your GitLab repository and push them to themainbranch. - Monitor the Pipeline: Go to the “CI/CD” section of your GitLab project and watch the pipeline run.
- Verify the Deployment: Once the pipeline completes successfully, use
kubectlto 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-appYou 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.yamlandservice.yamlfiles are correctly configured. - Check Kubernetes Events: Use
kubectl describe pod <pod-name> -n my-gitlab-appto 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!