DEV Community

Cover image for πŸš€ Supercharge Your CI/CD Pipeline: GitHub Actions with Kubernetes Deployment
Md Imran
Md Imran

Posted on

πŸš€ Supercharge Your CI/CD Pipeline: GitHub Actions with Kubernetes Deployment

Ever tried deploying an application on a Friday evening, only to realize you've broken production? Fear not! With GitHub Actions and Kubernetes, you can automate your CI/CD pipeline and enjoy your weekends without unexpected pager duties.

Introduction

In today's fast-paced development world, Continuous Integration and Continuous Deployment (CI/CD) are essential practices that help teams ship code faster and more reliably. GitHub Actions, a powerful automation tool integrated right into your GitHub repository, can be combined with Kubernetes to streamline your deployment process.

In this article, we'll explore how to set up a CI/CD pipeline using GitHub Actions to deploy applications to a Kubernetes cluster. We'll walk through examples, share best practices, and maybe crack a joke or two along the way.

Why GitHub Actions and Kubernetes?

GitHub Actions: The Swiss Army Knife of Automation

GitHub Actions allows you to automate tasks within your software development lifecycle. Whether it's running tests, building code, or deploying applications, GitHub Actions can do it all without leaving your repository.

Benefits:

  • Integration: Directly integrated with GitHub repositories.
  • Customization: Write workflows using YAML syntax.
  • Community: Vast marketplace of pre-built actions.

Kubernetes: Orchestrate Like a Maestro

Kubernetes is an open-source platform designed to automate deploying, scaling, and operating application containers.

Benefits:

  • Scalability: Automatically scale applications based on load.
  • Self-Healing: Restarts containers that fail.
  • Rollouts and Rollbacks: Deploy new versions safely.

Together at Last

Combining GitHub Actions and Kubernetes provides a seamless pipeline from code commit to deployment, ensuring that your application is always up-to-date and running smoothly.

Prerequisites

Before we dive in, make sure you have the following:

  • GitHub Account: Where your repository will live.
  • Kubernetes Cluster: You can use Minikube for local development or a cloud provider like GKE, EKS, or AKS.
  • Docker Installed: For building container images.
  • kubectl: Kubernetes command-line tool.
  • Basic Understanding of YAML: Because what's life without YAML errors?

Setting Up a Sample Application

Let's create a simple Node.js application that says "Hello, Kubernetes!"β€”because who doesn't like being greeted by their orchestration tool?

1. Initialize a Node.js App:

mkdir hello-kubernetes
cd hello-kubernetes
npm init -y
Enter fullscreen mode Exit fullscreen mode

2. Install Express.js:

npm install express
Enter fullscreen mode Exit fullscreen mode

3. Create app.js:

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => res.send('Hello, Kubernetes!'));

app.listen(port, () => console.log(`App listening on port ${port}`));
Enter fullscreen mode Exit fullscreen mode

4. Test Locally:

node app.js
Enter fullscreen mode Exit fullscreen mode

Visit http://localhost:3000 to see the message.

Dockerizing the Application

Because containers are all the rage these days.

Create a Dockerfile:

FROM node:14

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 3000
CMD [ "node", "app.js" ]
Enter fullscreen mode Exit fullscreen mode

Build the Docker Image:

docker build -t your-dockerhub-username/hello-kubernetes:latest .
Enter fullscreen mode Exit fullscreen mode

Test the Docker Image Locally:

docker run -p 3000:3000 your-dockerhub-username/hello-kubernetes:latest
Enter fullscreen mode Exit fullscreen mode

Pushing the Image to Docker Hub

You can't deploy what you don't have in a registry!

1. Log In to Docker Hub:

docker login
Enter fullscreen mode Exit fullscreen mode

2. Push the Image:

docker push your-dockerhub-username/hello-kubernetes:latest
Enter fullscreen mode Exit fullscreen mode

Creating Kubernetes Manifests

Let's create deployment and service manifests for Kubernetes.

1. deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-kubernetes
  template:
    metadata:
      labels:
        app: hello-kubernetes
    spec:
      containers:
      - name: hello-kubernetes
        image: your-dockerhub-username/hello-kubernetes:latest
        ports:
        - containerPort: 3000
Enter fullscreen mode Exit fullscreen mode

2. service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes-service
spec:
  type: LoadBalancer
  selector:
    app: hello-kubernetes
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
Enter fullscreen mode Exit fullscreen mode

Deploying Manually (Just Once, We Promise)

Apply the manifests to ensure everything works before automating.

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
Enter fullscreen mode Exit fullscreen mode

Check the status:

kubectl get pods
kubectl get services
Enter fullscreen mode Exit fullscreen mode

Visit the external IP to see your application running.

Setting Up GitHub Actions for CI/CD

Time to automate and make our future selves proud.

1. Create a .github/workflows Directory

In your repository, create the directory:

mkdir -p .github/workflows
Enter fullscreen mode Exit fullscreen mode

2. Create ci-cd.yaml

This YAML file will define our workflow.

name: CI/CD Pipeline

on:
  push:
    branches:
      - master

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Code
        uses: actions/checkout@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Log in to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and Push Docker Image
        uses: docker/build-push-action@v4
        with:
          push: true
          tags: your-dockerhub-username/hello-kubernetes:latest

      - name: Set up Kubectl
        uses: azure/k8s-set-context@v1
        with:
          kubeconfig: ${{ secrets.KUBE_CONFIG_DATA }}

      - name: Deploy
        run: |
          kubectl apply -f deployment.yaml
          kubectl apply -f service.yaml

Enter fullscreen mode Exit fullscreen mode

3. Configure GitHub Secrets

Go to your repository settings and add the following secrets:

  • DOCKERHUB_USERNAME: Your Docker Hub username.
  • DOCKERHUB_TOKEN: Docker Hub access token or password.
  • KUBE_CONFIG_DATA: Base64 encoded kubeconfig file.

Tip: To encode your kubeconfig:

cat $HOME/.kube/config | base64 | pbcopy  # For macOS
Enter fullscreen mode Exit fullscreen mode

4. Commit and Push

git add .
git commit -m "Set up CI/CD pipeline"
git push origin main
Enter fullscreen mode Exit fullscreen mode

Testing the Pipeline

Every time you push to the main branch, GitHub Actions will:

  1. Build the Docker image.
  2. Push it to Docker Hub.
  3. Apply the Kubernetes manifests, updating the deployment.

Funny Anecdote: If only we could automate making coffee as easily as deploying applications!

Rolling Updates

Kubernetes handles rolling updates smoothly. When the deployment detects a new image tag (since we're always using latest), it updates the pods one by one.

Adding Some Humor with Slack Notifications

Why not get notified with a funny message when your deployment succeeds or fails?

1. Set Up a Slack App:

  • Create a new Slack App and add it to your workspace.
  • Enable Incoming Webhooks.
  • Create a webhook URL.

2. Add Slack Secret:

  • Add SLACK_WEBHOOK_URL to your GitHub secrets.

3. Update ci-cd.yaml:

Add the following step at the end:

    - name: Notify Slack
      if: always()
      uses: 8398a7/action-slack@v3
      with:
        status: ${{ job.status }}
        fields: repo,message,commit,author,ref
        custom_payload: |
          {
            "text": "${{ job.status }}: The deployment to Kubernetes has completed. Time to celebrate! :tada:"
          }
      env:
        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Enter fullscreen mode Exit fullscreen mode

Now, every time the workflow runs, you'll get a Slack message. If it fails, maybe include a funny GIF to lighten the mood!

Best Practices

  • Use Specific Tags: Instead of latest, tag your images with commit SHAs or version numbers.
  • Namespace Isolation: Deploy to specific namespaces to avoid clashing with other services.
  • Resource Limits: Define resource requests and limits in your deployment to optimize cluster usage.
  • Security: Regularly rotate your secrets and use least privilege principles.

Certainly! Here are the two lines you can include in your article to reference your GitHub repository:

πŸ”— GitHub Repository

You can find all the code and configuration files for this project in my GitHub repository: github-actions-kubernetes. Feel free to clone or fork the repo to set up your own CI/CD pipeline!


Conclusion

By leveraging GitHub Actions and Kubernetes, we've automated our CI/CD pipeline, reducing manual intervention and the risk of errors. Now, deployments are smoother than a freshly buttered slide.

Final Joke: Why did the developer go broke? Because they used up all their cache!

Additional Resources


Thanks for reading! Feel free to leave a comment or share your own funny deployment stories.

Top comments (0)