A Beginner's Guide to DevOps: Automating a CI/CD Pipeline with GitLab CI and Kubernetes

Introduction:

DevOps is all about automating processes to make development and operations more efficient. One of the most crucial aspects of DevOps is Continuous Integration and Continuous Deployment (CI/CD). In this guide, we'll walk you through setting up a simple CI/CD pipeline using GitLab CI and deploying your application to a Kubernetes cluster.

By the end of this tutorial, you'll know how to:

  • Set up a project in GitLab
  • Write a basic GitLab CI pipeline to automate testing and deployment
  • Deploy an application to a Kubernetes cluster using GitLab CI

Prerequisites:

Before starting, ensure you have the following:

  • A GitLab account (sign up for free at GitLab)
  • Basic knowledge of Git and Kubernetes
  • kubectl installed and configured to access a Kubernetes cluster (You can use Minikube for a local Kubernetes cluster)
  • A text editor like VSCode

Step 1: Set Up Your Project in GitLab

Objective: Create a new project in GitLab and initialize version control.

  1. Create a GitLab Account: If you don't have a GitLab account, sign up for one here.

  2. Create a New Repository:

  3. Go to your GitLab dashboard.
  4. Click the "New Project" button and create a new repository named ci-cd-k8s-app.
  5. Choose "Initialize repository with a README."

  6. Clone the Repository:  - Open your terminal and clone the repo to your local machine:

git clone https://gitlab.com/your-username/ci-cd-k8s-app.git
cd ci-cd-k8s-app

Step 2: Build a Simple Node.js Application

Objective: Create a simple Node.js application that will be deployed using your CI/CD pipeline.

  1. Initialize a Node.js Application:

  2. Inside your project directory, initialize a Node.js app:

npm init -y
  1. Install Express:

  2. Install the Express framework for creating a simple web server:

npm install express
  1. Create index.js:

  2. Create a file called index.js with the following content:

  3. Test the Application:

  4. Run the application locally to ensure it's working: node index.js

  5. Open your browser and go to http://localhost:3000.
  6. You should see "Hello, GitLab CI/CD with Kubernetes!"

  7. Add and Commit Your Code:

  8. Add your changes to the repository and push them to GitLab:

git add .
git commit -m "Initial Node.js app"
git push origin main

Step 3: Write a GitLab CI Pipeline

Objective: Automate the build, test, and deployment of your application using GitLab CI.

  1. Create a .gitlab-ci.yml File:
  2. In the root of your project, create a .gitlab-ci.yml file:
stages:
  - build
  - deploy

build:
  image: node:14
  stage: build
  script:
    - npm install
    - npm test

deploy:
  image: google/cloud-sdk
  stage: deploy
  script:
    - kubectl apply -f k8s/deployment.yaml
  only:
    - main
  • This pipeline has two stages: build and deploy. The build stage installs dependencies and runs tests, while the deploy stage applies a Kubernetes deployment configuration using kubectl.

  • Create a Kubernetes Deployment File:

  • Inside a new directory called k8s, create a deployment.yaml file:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nodejs-app
  template:
    metadata:
      labels:
        app: nodejs-app
    spec:
      containers:
        - name: nodejs-app
          image: node:14
          command: ["node", "index.js"]
          ports:
            - containerPort: 3000
`
  • This file defines a Kubernetes deployment with two replicas of your Node.js application.

  • Set Up Kubernetes Access:

  • Ensure that your GitLab CI runner has access to your Kubernetes cluster. You can either:

  • Set up a GitLab Kubernetes cluster (under your GitLab project settings, in the "Kubernetes" section), or
  • Provide access credentials via GitLab CI/CD variables (e.g., KUBECONFIG or KUBE_TOKEN).

  • Push Your Pipeline Configuration:

  • Add and commit your .gitlab-ci.yml and Kubernetes deployment file:
git add .
git commit -m "Add GitLab CI pipeline and Kubernetes deployment"
git push origin main
  1. Monitor the Pipeline:

  2. Go to the "CI/CD" section in your GitLab repository to see your pipeline running. The stages should execute in order, and if everything is set up correctly, your application will be deployed to your Kubernetes cluster.

Step 4: Expose Your Application

Objective: Create a Kubernetes service to expose your Node.js application to the internet.

  1. Create a Kubernetes Service File:

  2. In the k8s directory, create a service.yaml file:

apiVersion: v1
kind: Service
metadata:
  name: nodejs-app-service
spec:
  type: LoadBalancer
  selector:
    app: nodejs-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  • This service exposes your Node.js application on port 80, mapping it to the application's container port 3000.

  • Update Your Pipeline:

  • Modify your .gitlab-ci.yml to apply the service configuration:

deploy:
  image: google/cloud-sdk
  stage: deploy
  script:
    - kubectl apply -f k8s/deployment.yaml
    - kubectl apply -f k8s/service.yaml
  only:
    - main
  1. Push Your Updates:

  2. Push the updated service configuration to GitLab:

git add .
git commit -m "Add Kubernetes service configuration"
git push origin main
  1. Access Your Application:

  2. Once the pipeline runs successfully and the service is created, you'll get an external IP address assigned to your Kubernetes service. You can access your application via this IP address.

Conclusion:

Congratulations! You've just set up a full CI/CD pipeline using GitLab CI to automate the deployment of a Node.js application to a Kubernetes cluster. You learned how to automate testing, deployment, and service exposure using GitLab and Kubernetes. This project is a foundational DevOps workflow that can be expanded upon as you explore more advanced topics like monitoring, scaling, and security. Keep experimenting and building more complex pipelines as you grow your DevOps skills. Feel free to share your experience in the comments section. Happy DevOps-ing!