GitOps is used to automate the process of provisioning infrastructure. It consists of:

  • IaC
  • MRs
  • CI/CD

With these tools GitOps provides a set of best practices for automated deployment and management of infrastructure.

Infrastructure as code (IaC) is the process of managing and provisioning infrastructure. IaC allows versioned configuration of infrastructure which can be deployed to test, dev and prod environments. IaC enables reproducible and backed up infrastructure.

The IaC configuration can be deployed locally, through CICD processes or both. With GitOps we apply techniques to further improve the benefits of IaC granting faster deployments and enhance developer workflow.

With GitOps we use a Git repository as the single source of truth for infrastructure definitions. Merge Requests are used as the change process for updating infrastructure. The changes are applied through CICD pipelines.

Kubernetes application in GitHub with minikube and GitHub actions

In this project we will manage a simple webserver with GitOps principles. The webserver is configured in a Dockerfile and run in a container. The container is managed through a Kubernetes deployment. GitHub actions is responsible to deploy new changes and the code is stored in a git repository.

Webserver

Lighttdp is a high-performance open source Web server.

FROM alpine:3.13.6
RUN apk update \
    && apk add lighttpd \
    && rm -rf /var/cache/apk/*
COPY ./index.html /var/www/localhost/htdocs
CMD ["lighttpd","-D","-f","/etc/lighttpd/lighttpd.conf"]

index.html contains:

hello world

Kubernetes deployment

We deploy the webserver container and expose port 80.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webserver
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: webserver-api
          imagePullPolicy: Never
          image: lighttpd-webserver:0.1.0
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: webserver
spec:
  ports:
    - port: 80
      targetPort: 80

Minikube

Minikube is a utility you can use to run Kubernetes locally or with GitHub actions. This allows us to run the entire pipeline and deploy the application locally and in the GitHub environment.

โžœ minikube start
๐Ÿ˜„  minikube v1.15.1 on Darwin 11.6
    โ–ช MINIKUBE_ACTIVE_DOCKERD=minikube
โœจ  Using the hyperkit driver based on existing profile
๐Ÿ‘  Starting control plane node minikube in cluster minikube
๐Ÿ”„  Restarting existing hyperkit VM for "minikube" ...
๐Ÿณ  Preparing Kubernetes v1.19.4 on Docker 19.03.13 ...
๐Ÿ”Ž  Verifying Kubernetes components...
๐ŸŒŸ  Enabled addons: storage-provisioner, default-storageclass, dashboard
๐Ÿ„  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
โžœ kubectl apply -f deployment.yml
deployment.apps/webserver created
โžœ minikube service list                 
|----------------------|---------------------------|--------------|---------------------------|
|      NAMESPACE       |           NAME            | TARGET PORT  |            URL            |
|----------------------|---------------------------|--------------|---------------------------|
| default              | webserver                   |           80 | http://192.168.64.3:30295 |
| default              | kubernetes                | No node port |
| default              | redis-master              | No node port |
| default              | webserver                 | No node port |
| kube-system          | kube-dns                  | No node port |
| kubernetes-dashboard | dashboard-metrics-scraper | No node port |
| kubernetes-dashboard | kubernetes-dashboard      | No node port |
|----------------------|---------------------------|--------------|---------------------------|
โžœ curl $(minikube service webserver --url)
hello world

GitHub Actions

GitHub Actions makes it easy to automate software workflows. With GitHub Actions we can configure CI/CD pipelines to build, test, and deploy code.

We limit deployments on main branch to pull requests.

on:
  pull_request:
    branches: 
      - main
  types: [closed]

The deployment builds a new container image and deploys it to minikube. To verify the deployment, we check if the webserver is responding.

jobs:
  job1:
    runs-on: ubuntu-latest
    name: build webserver and deploy to minikube
    steps:
    - uses: actions/checkout@v2
    - name: Start minikube
      uses: medyagh/setup-minikube@master
    - name: Try the cluster !
      run: kubectl get pods -A
    - name: Build image
      run: |
        export SHELL=/bin/bash
        eval $(minikube -p minikube docker-env)
        docker build -f ./Dockerfile -t lighttpd-webserver:0.1.0 .
        echo -n "verifying images:"
        docker images        
    - name: Deploy to minikube
      run:
        kubectl apply -f deployment.yml
    - name: Test service URLs
      run: |
        minikube service list
        minikube service webserver --url
        echo "------------------opening the service------------------"
        curl $(minikube service webserver --url)        

Conclusion

In this project we have shown how GitOps principles can be used to automate management and deployment of an application.