Deploy Atmo Wasm microservices to K3S on Civo.com
I already wrote about Civo and Atmo (from Suborbital), but never at the same time. Today I will explain how to deploy Atmo services on a Civo Kubernetes cluster.
All the source codes are on a "gitpodified" project: https://gitlab.com/k33g_org/discovering-atmo/deploy-atmo-on-civo
Requirements
To create a K3s cluster on Civo you'll need the Civo CLI:
brew tap civo/tools
brew install civo
🖐 You need to be registered on Civo and get a "Civo Key" to be able to use the Civo CLI
To connect to the cluster you'll need the kubectl
CLI, and, it's not mandatory, but K9s is a very convenient tool to manage a Kubernetes cluster:
brew install derailed/k9s/k9s
brew install kubernetes-cli
To create and build Atmo services, you'll need the subo
CLI:
brew tap suborbital/subo
brew install subo
Create a K3s cluster on Civo
We're going to create a small cluster and store the KUBECONFIG file to ./config/k3s.yaml
CLUSTER_NAME="tinypanda"
CLUSTER_SIZE="g3.k3s.xsmall"
CLUSTER_NODES=1
CLUSTER_REGION=NYC1
export KUBECONFIG=$PWD/config/k3s.yaml
Store the value of the Civo key in a variable (CIVO_API_KEY
) and run the below command to create a K3s cluster in less than a minute:
civo apikey add civo-key ${CIVO_API_KEY}
civo apikey current civo-key
civo kubernetes create ${CLUSTER_NAME} --size=${CLUSTER_SIZE} --nodes=${CLUSTER_NODES} --region=${CLUSTER_REGION} --wait
Get the KUBECONFIG file and save it `./config/k3s.yaml``
civo --region=${CLUSTER_REGION} kubernetes config ${CLUSTER_NAME} > ./config/k3s.yaml
Check if you can connect
Type the below commands:
export KUBECONFIG=$PWD/config/k3s.yaml
kubectl get pods --all-namespaces
You should get something like that:
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system helm-install-traefik-2f64k 0/1 Completed 0 14m
kube-system svclb-traefik-pr85p 2/2 Running 0 14m
kube-system traefik-6f9cbd9bd4-vjxjb 1/1 Running 0 14m
kube-system coredns-854c77959c-579kv 1/1 Running 0 14m
kube-system local-path-provisioner-7c458769fb-72frb 1/1 Running 0 14m
kube-system civo-csi-controller-0 3/3 Running 0 14m
kube-system metrics-server-86cbb8457f-lfljp 1/1 Running 0 14m
kube-system civo-csi-node-mnlrx 2/2 Running 0 14m
Or, even better, use K9s:
export KUBECONFIG=$PWD/config/k3s.yaml
k9s --all-namespaces
Create and test an Atmo project and add a wasm service
Creating an Atmo project is very easy:
subo create project services
cd services
rm -rf .git # we're already in a git repository
A demo "helloworld" service (aka "runnable") is automatically generated in the project. The code is simple, and it's enough for our experiments:
👀 /services/helloworld/src/lib.rs
use suborbital::runnable::*;
struct HelloWorld{}
impl Runnable for HelloWorld {
fn run(&self, input: Vec<u8>) -> Result<Vec<u8>, RunErr> {
let in_string = String::from_utf8(input).unwrap();
Ok(String::from(format!("hello {}", in_string)).as_bytes().to_vec())
}
}
🖐 the route to reach the service is defined in/services/Directive.yaml
handlers:
- type: request
resource: /hello
method: POST
steps:
- fn: helloworld
Build and serve (in developer mode)
Build and package the wasm service:
subo build .
This will produce a bundle named
runnables.wasm.zip
that contains your wasm services (just only one in your case)
Run a development Atmo server to serve the bundle:
subo dev
Call the service:
curl localhost:8080/hello -d 'Jane'
Embed the bundle in a container (and push to a container registry)
You can find a Dockerfile in the services
directory. So, we're going to use it to embed the "runnables" bundle in a container.
🖐 I'm using the GitLab container registry, but it works with any registry of course.
Login to the registry
docker login registry.gitlab.com -u k33g -p ${GITLAB_TOKEN_ADMIN}
# k33g is my GitLab handle
# I use a personal web token to authenticate to the registry
# and I store it in `GITLAB_TOKEN_ADMIN`
Build and push the image
cd services
docker build -t atmo-services . # (🖐 don't forget the `.` at the end of the command)
docker tag atmo-services registry.gitlab.com/k33g_org/discovering-atmo/deploy-atmo-on-civo/atmo-services:0.0.0
docker push registry.gitlab.com/k33g_org/discovering-atmo/deploy-atmo-on-civo/atmo-services:0.0.0
You can read more about the GitLab container registry here: https://docs.gitlab.com/ee/user/packages/container_registry/
Serve it with Docker
Now, we can serve the service with Docker:
docker run -e ATMO_HTTP_PORT=8080 -p 8080:8080 registry.gitlab.com/k33g_org/discovering-atmo/deploy-atmo-on-civo/atmo-services:0.0.0
And we can test again the service:
curl localhost:8080/hello -d 'Jane'
And if we can run Atmo services in Docker, we can deploy Atmo services on Kubernetes, and then on Civo
Deploy the "helloworld" service on Civo
DNS Name
We need the DNS name of the cluster. Then type the below command:
civo kubernetes show tinypanda
# 🖐 `tinypanda` is the name of my cluster
You should get something like this:
ID : 93da0af0-b3ed-4a2c-86e7-4cb4089c00f7
Name : tinypanda
Region : NYC1
Nodes : 1
Size : g3.k3s.xsmall
Status : ACTIVE
Version : 1.20.0-k3s1
API Endpoint : https://212.2.244.216:6443
External IP : 212.2.244.216
DNS A record : 93da0af0-b3ed-4a2c-86e7-4cb4089c00f7.k8s.civo.com
So, the DNS name is 93da0af0-b3ed-4a2c-86e7-4cb4089c00f7.k8s.civo.com
Deployment manifest
I created a template of yaml manifest to deploy my service on the cluster: ./kubernetes/deploy.template.yaml
, and I will use the UNIX tool envsubst
to substitute the value of the variables:
---
# Service
apiVersion: v1
kind: Service
metadata:
name: ${APPLICATION_NAME}
spec:
selector:
app: ${APPLICATION_NAME}
ports:
- port: 8080
targetPort: 8080
---
# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${APPLICATION_NAME}
spec:
replicas: 1
selector:
matchLabels:
app: ${APPLICATION_NAME}
template:
metadata:
labels:
app: ${APPLICATION_NAME}
spec:
containers:
- name: ${APPLICATION_NAME}
image: ${REGISTRY}:${TAG}
command: ["atmo"]
ports:
- containerPort: 8080
imagePullPolicy: Always
env:
- name: ATMO_HTTP_PORT
value: "8080"
---
# Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ${APPLICATION_NAME}
spec:
rules:
- host: ${APPLICATION_NAME}.${DNS}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ${APPLICATION_NAME}
port:
number: 8080
I used this to install
envsubst
:sudo apt-get install gettext -y
🚀
Deploy Now, we can deploy the service:
export KUBECONFIG=$PWD/config/k3s.yaml
# Create a demo namespace
export KUBE_NAMESPACE="demo"
kubectl create namespace ${KUBE_NAMESPACE} --dry-run=client -o yaml | kubectl apply -f -
export APPLICATION_NAME="atmo-hello"
export REGISTRY="registry.gitlab.com/k33g_org/discovering-atmo/deploy-atmo-on-civo/atmo-services"
export DNS="93da0af0-b3ed-4a2c-86e7-4cb4089c00f7.k8s.civo.com"
export TAG="0.0.0"
envsubst < kubernetes/deploy.template.yaml > kubernetes/tmp/deploy.${TAG}.yaml
kubectl apply -f kubernetes/tmp/deploy.${TAG}.yaml -n ${KUBE_NAMESPACE}
You should get this:
service/atmo-hello created
deployment.apps/atmo-hello created
ingress.networking.k8s.io/atmo-hello created
The service is deployed:
And you can test it:
curl http://atmo-hello.${DNS}/hello -d 'Jane Doe'
Some useful commands
If you want to scale your service:
REPLICAS=3
kubectl scale --replicas=${REPLICAS} deploy ${APPLICATION_NAME} -n ${KUBE_NAMESPACE}
If you want to remove your service:
kubectl delete -f ./kube/deploy.${TAG}.yaml -n ${KUBE_NAMESPACE}
If you want to delete your cluster:
CLUSTER_NAME="tinypanda"
CLUSTER_REGION=NYC1
export KUBECONFIG=$PWD/config/k3s.yaml
civo apikey add civo-key ${CIVO_API_KEY}
civo apikey current civo-key
civo kubernetes remove ${CLUSTER_NAME} --region=${CLUSTER_REGION} --yes
That's all folks
The next blog post will be about the same topic but with Knative.
👋
- If you loved this "post" (or not), don't forget to use the emojis reactions
- Don't hesitate to add comments and/or ask questions
- You can subscribe to the Rss feed