In today’s world, containers are transforming the way applications are deployed at the edge. The ease of portability, size, and efficiency makes containers an ideal candidate to run applications on low powered edge devices. These edge devices are located at the edge of a network and closer to the end user. Because of the proximity of these devices it is often a requirement to develop applications at the edge that provides low operational overhead, minimize latency issues and decentralized services.
Developing applications at the edge has a different perspective than traditional practices when it comes to code collaboration and deployment efforts. CI/CD (Continuous Integration, Continuous Deployment) at the edge provides risk mitigation to applications by supporting small, incremental changes and an eventual rollout of the application. The issues in the code can be rapidly detected and mitigated without a huge operational overhead.
To resolve these challenges using cloud-native development on edge devices, Project Cassini is the open, collaborative, standards-based initiative to deliver a cloud-native software experience across a secure Arm edge ecosystem. In this blueprint, we showcase how applications can be developed using Rancher K3s and GitLab CI/CD at the edge.
Rancher K3s is a lightweight production-grade Kubernetes distribution from Rancher. It has been designed for developers and operators who need to deploy applications quickly and reliably to resource-constrained environments like edge computing, CI use cases. It has a small footprint (~40MB) and has been designed to run on low memory devices. This has been achieved by removing over 1Million lines of code from the upstream Kubernetes distribution from CNCF and is optimized for Arm architecture.
GitLab is a web-based DevOps platform that provides a git-based repository and has support for building cloud native applications at the edge. GitLab has a large footprint in the self-hosted git market. GitLab supports self-hosted runners on Arm platform and also has added GitLab server (64-bit) packages for Arm-based platforms.
Here, we host self-contained CI/CD system at the edge location. To achieve this, we have deployed the GitLab server on Raspberry Pi4. We also have Arm based Gitlab runners deployed on K3s cluster running on Raspberry Pi. There are three stages associated with our CI/CD workflow:
Figure 1 shows the high-level architecture of the use case:
Figure 1. Developing a containerized application at the edge with GitLab and Rancher K3s.
The following video explains the entire CI/CD workflow with application deployment:
Following are the pre-requisites for building the use case:
Deploy the GitLab server instance on a Raspberry Pi and configure the SSH keys. Follow the steps here to install K3s cluster on Raspberry Pi.
We are now going to install docker and the GitLab runner on one of the raspberry Pis.
sudo curl -sSL https://get.docker.com | sh
Verify that docker daemon is running and you are able to push and pull images from docker hub. Use the following command to download the arm64 binary for GitLab runner on Raspberry Pi:
curl -LJO https://gitlab-runner-downloads.s3.amazonaws.com/latest/deb/gitlab-runner_arm64.deb
Install the gitlab runner using the following command:
dpkg -i gitlab-runner_arm64.deb
After the GitLab runner is installed we need to register it with our GitLab server to use it in our pipeline. Grab the registration token from the GitLab server. Go to Admin area > Runners and locate the token.
Figure 2. Gitlab Arm runner configuration
After successful registration, the runner should be in a connected state.
Create an empty project on the GitLab server and make sure that the newly created runner is associated with this project. Create a sample application code and put it in “main.go” file. The source code is located in the GitHub repo here.
Create a new file named Dockerfile with the following content:
FROM golang:1.11-alpine as builder WORKDIR /usr/build ADD main.go . RUN go build -o app . FROM alpine:latest WORKDIR /usr/src COPY --from=builder /usr/build/app . EXPOSE 8080 CMD ["/usr/src/app"]
Create a Kubernetes deployment spec yaml file with the content located here.
Create the .gitlab-ci.yml file with the following content:
image: docker:latest services: - docker:dind stages: - build - deploy variables: DOCKER_TLS_CERTDIR: "" CONTAINER_IMAGE: pbakre/go-demo-app:${CI_COMMIT_SHORT_SHA} build: stage: build script: - docker login -u ${DOCKER_USER} -p ${DOCKER_PASSWORD} - docker build -t ${CONTAINER_IMAGE} . - docker tag ${CONTAINER_IMAGE} ${CONTAINER_IMAGE} - docker tag ${CONTAINER_IMAGE} pbakre/go-k8s-world:latest - docker push ${CONTAINER_IMAGE} deploy: stage: deploy image: pbakre/kubectl-arm:latest script: - kubectl config set-cluster k8s --server="${SERVER}" - kubectl config set clusters.k8s.certificate-authority-data ${CERTIFICATE_AUTHORITY_DATA} - kubectl config set-credentials gitlab --token="${USER_TOKEN}" - kubectl config set-context default --cluster=k8s --user=gitlab - kubectl config use-context default - sed -i "s/<VERSION>/${CI_COMMIT_SHORT_SHA}/g" deployment.yaml - kubectl apply -f deployment.yaml
In the above file, we have defined multiple stages for our CI process. In the build stage, we are creating a container image for our sample application and pushing to a docker repo. In the ‘deploy’ stage, we use a small docker image that has kubectl installed which will be used to interact with the K3s cluster.
Now, we commit a code change in our project repository and if everything is configured correctly, we should see a pipeline being triggered automatically with two jobs – build and deploy
Figure 3. CI/CD pipeline stages
Once completed, we should see our application being deployed on the K3s cluster and accessible via a kubernetes service.
Figure 4. Sample application pods running on K3s cluster
We can now access the application via the NodePort service IP.
Developing a cloud native application at the edge with GitLab CI/CD and Rancher K3s simplifies the DevOps processes in such resource constrained environments. There are multiple additional edge use cases highlighted by Rancher here at Arm DevSummit. Reach us here with questions or comments.