Acorn was created and launched by the previous founding team of Rancher on the 3rd of August 2022. I actually got to see the product, demo, and deep dive when it was a private project, big thanks to Darren. Acorn is a framework to make the deployment of applications to Kubernetes seamless and easy. In this article, I will share my first impressions, spin it up on Civo Kubernetes and see the benefits.
Easy Kubernetes Deployment to Civo Using Acorn
As part of our virtual booth, Saiyam Pathak gave three quick-fire talks. In his final session “Easy Kubernetes deployment to Civo using Acorn”, Saiyam spoke about deploying challenges and how tools like Acorn can make your life easier.
The problem statement
Have you felt frustrated while deploying a simple app? We all get that feeling when we are writing the YAML files for deployment, services, persistent volume and other K8s components to actually get a simple app deployed to Kubernetes. Now tools like K3s and services like Civo Kubernetes give you cluster with ease, but the frustration of building, deploying and getting the URL (with ingress or svc) is still a pain. This is where the team at Acorn Labs decided to create something to help solve this and make things simpler for the teams deploying applications to Kubernetes.
What is Acorn?
Acorn is a tool/CLI that you can use to simply deploy your application to Kubernetes for different environments (dev, staging, prod). Here you need to write an Acornfile which takes huge inspiration from Dockerfile and Docker Compose, its syntax is simple (derived from CUE) and there is an Acornfile reference as well in the docs so you don't need to learn CUE lang to write Acornfile.
Sample Acornfile
containers: {
web: {
build: "."
ports: publish: "8080/http"
}
}
This example shows how to create a container web and build from the current directory with the ports to be published. Acorn Images can actually have multiple Docker images and even the metadata. This artifact can be published to any OCI registry. I will show you a couple of Acornfile examples so that it becomes clear how simple it is to create and use them for application deployment, as well as customize them for your needs.
Acorn Architecture
There is a high-level architecture given in the docs so I will not reinvent the wheel by creating a new one. The below example is taken directly from the docs.
Now when you run acorn install
against the Kubernetes cluster, you can see that three components will be installed:
- acorn-api: this is the one that is used to perform all the actions. After the kubernetes
apiserver
authentication is checked and passed, it goes toacorn-apiserver
via the Kubernetes API aggregation layer. When the request comes,acorn-apiserver
will perform different operations like it will creates the CRDappinstances.internal.acorn.io
on app creation, build image using buildkit and push to external or internal registry depending on the passed arguments. - buildkit + Internal registry: it is a service used for image building and has 2 containers.
- acorn-controller: this is the one actually converting acorn apps to Kubernetes objects.
Cluster creation
As Civo is super fast with <2 minute launch time, I also added Acorn as a marketplace app for installing the server-side components as soon as the project was announced (a couple of hours later to be precise). This means that you need not run acorn install
.
I will be using Civo CLI to create the cluster, you can install the cli from here. You can create the cluster from the UI or from the Civo CLI. For this tutorial, let's create using the CLI.
civo k3s create acorn-civo --applications Acorn
The cluster acorn-civo (13188e49-a39c-4bcb-8c93-f3d001c3f361) has been created
The above example will create a 3 node cluster named acorn-civo. Once the cluster is up and running in a couple of minutes, we can proceed.
We will then need to get the Kubeconfig for the cluster and save to our desired location. If you do not specify a path, it will save it to the default location of ~/.kube/config.
civo k3s config acorn-civo --save --local-path /Users/saiyam/Downloads/acorn.config
Merged with main kubernetes config: /Users/saiyam/Downloads/acorn.config
Let's make sure that kubectl knows to use our cluster's configuration file:
export KUBECONFIG=/Users/saiyam/Downloads/acorn.config
kubectl get nodes
NAME STATUS ROLES AGE VERSION
k3s-acorn-civo-b77c-409c89-node-pool-d6a4-hnd5l Ready <none> 2m1s v1.22.11+k3s1
k3s-acorn-civo-b77c-409c89-node-pool-d6a4-hwku7 Ready <none> 2m25s v1.22.11+k3s1
k3s-acorn-civo-b77c-409c89-node-pool-d6a4-stiv6 Ready <none> 2m25s v1.22.11+k3s1
We can also check if the acorn components are installed
kubectl get all -n acorn-system
NAME READY STATUS RESTARTS AGE
pod/acorn-api-57db7cc74b-wm6tb 1/1 Running 0 2m21s
pod/acorn-controller-6c465fbf65-x2ct8 1/1 Running 0 2m21s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/acorn-api ClusterIP 10.43.241.163 <none> 7443/TCP 2m22s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/acorn-api 1/1 1 1 2m22s
deployment.apps/acorn-controller 1/1 1 1 2m22s
NAME DESIRED CURRENT READY AGE
replicaset.apps/acorn-api-57db7cc74b 1 1 1 2m22s
replicaset.apps/acorn-controller-6c465fbf65 1 1 1 2m22s
Acorn in Action
Now would be the time to install the acorn cli locally on your systems. You can do that by running curl https://get.acorn.io | sh
[INFO] Finding release for channel latest
[INFO] Using v0.1.0 as release
[INFO] Downloading hash https://github.com/acorn-io/acorn/releases/download/v0.1.0/checksums.txt
[INFO] Downloading archive https://github.com/acorn-io/acorn/releases/download/v0.1.0/acorn-v0.1.0-macOS-universal.tar.gz
[INFO] Verifying binary download
[INFO] Installing acorn to /usr/local/bin/acorn
acorn -v
acorn version v0.1.0+80d6e93d
After installing acorn successfully in your system, clone this repository and cd
into it.
git clone https://github.com/saiyam1814/acorn-demo.git
cd acorn-demo
Now, this has the source code and a Dockerfile to run a simple flask app and in the Acornfile we are telling it to run a web container and build the Dockerfile present in the current directory.
containers: {
web: {
build: "."
ports: publish: "8080/http"
}
}
Now we run the acorn build
acorn build .
acorn build .
Waiting for the builder to start... Ready
it creates the third pod buildkit
with two containers as explained in the architecture.
buildkitd-5f77fb596c-q86r5 2/2 Running 0 4m46s
Once its ready it starts building the image from the Dockerfile and pushes it to the internal registry.
acorn build .
[+] Building 2.3s (7/7) FINISHED
=> [internal] load .dockerignore 0.4s
=> => transferring context: 2B 0.3s
=> [internal] load build definition from Dockerfile 0.5s
=> => transferring dockerfile: 131B 0.5s
=> [internal] load metadata for docker.io/tiangolo/uwsgi-nginx-flask:latest 0.7s
=> [internal] load build context 0.7s
=> => transferring context: 39.41kB 0.7s
=> [1/2] FROM docker.io/tiangolo/uwsgi-nginx-flask:latest@sha256:d588b419b8c6922 0.0s
=> => resolve docker.io/tiangolo/uwsgi-nginx-flask:latest@sha256:d588b419b8c6922 0.0s
=> CACHED [2/2] COPY . ./ 0.0s
=> exporting to image 0.3s
=> => exporting layers 0.0s
=> => exporting manifest sha256:818583281395c9c16206151960414efee95ff6a6aea6fa99 0.0s
=> => exporting config sha256:06801160ae6868056b39b78d6e11b460b15fe92601a4d475e3 0.0s
=> => pushing layers 0.2s
=> => pushing manifest for 127.0.0.1:5000/acorn/acorn:latest@sha256:818583281395 0.0s
[+] Building 1.4s (5/5) FINISHED
=> [internal] load .dockerignore 0.5s
=> => transferring context: 64B 0.5s
=> [internal] load build definition from Dockerfile 0.5s
=> => transferring dockerfile: 58B 0.5s
=> [internal] load build context 0.5s
=> => transferring context: 262B 0.5s
=> CACHED [1/1] COPY . / 0.0s
=> exporting to image 0.1s
=> => exporting layers 0.0s
=> => exporting manifest sha256:891231607fff23bfdf6ddd1da12d8d32e8259e0fc0036004 0.0s
=> => exporting config sha256:8b606335d8ca7c36bafb77260bbbc3abe9cc8051c571533acf 0.0s
=> => pushing layers 0.0s
=> => pushing manifest for 127.0.0.1:5000/acorn/acorn:latest@sha256:891231607fff 0.0s
4425dd246abcc566dfaca7c81e29acb7aafb6838b67bc617680c2efa332cc272
Now let's run the app
acorn run 4425dd246abcc566dfaca7c81e29acb7aafb6838b67bc617680c2efa332cc272
small-cloud
acorn apps
NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE
small-cloud 4425dd246abc 1 1 21s ago http://<pending> => web:8080 OK
This should be populated with the ingress created (if not then you can check ing)
kubectl get ing -A
NAMESPACE NAME CLASS HOSTS ADDRESS PORTS AGE
small-cloud-b67bd297-fb3 web <none> web.small-cloud.13188e49-a39c-4bcb-8c93-f3d001c3f361.k8s.civo.com 80 9m26s
Now when you open the URL in the host, boom!!!...you will see your application running! How cool and fancy is that? You didn't have to create any Kubernetes resources and everything was created automatically for you.
Let us try another example, this time from a different Acornfile which is present in the same repo.
containers: {
frontend: {
image: "nginx"
ports: publish: "80/tcp"
dirs: {
"/var/www/html": "volume://web-content"
}
// ...
}
}
// ...
volumes: {
"web-content": {}
}
The above is basically to show that you can create persistent volume as well using Acornfile. Adding tcp instead of http will create a service type LoadBalancer
.
acorn run -f Acornfile2
[+] Building 5.8s (5/5) FINISHED
=> [internal] load build definition from acorn-dockerfile-302118934 0.6s
=> => transferring dockerfile: 64B 0.5s
=> [internal] load .dockerignore 0.4s
=> => transferring context: 2B 0.4s
=> [internal] load metadata for docker.io/library/nginx:latest 2.8s
=> [1/1] FROM docker.io/library/nginx@sha256:ecc068890de55a75f1a32cc8063e79f90f0b043d70c5fcf 1.6s
=> => resolve docker.io/library/nginx@sha256:ecc068890de55a75f1a32cc8063e79f90f0b043d70c5fcf 0.0s
=> => sha256:b1349eea8fc5b5eebb633c2cd79fc24a915fcb00279de24684bb07e349e8eab 1.39kB / 1.39kB 0.1s
=> => sha256:27e0d286aeab484653fdf0f736d5f7a2fbcc572e387ec8a1d6ccf0e74b6bfefc 664B / 664B 0.1s
=> => sha256:6a17c8e7063d97ef72e89f7d4673935ff9a2b7c179bea1726852399219118f65 891B / 891B 0.2s
=> => sha256:05396a986fd3f3739cc890e30a2ed78e377c6a2b24d9f0ebe99ff3349aedc603 603B / 603B 0.2s
=> => sha256:1efc276f4ff952c055dea726cfc96ec6a4fdb8b62d9eed816bd2b788f2860 31.37MB / 31.37MB 0.6s
=> => sha256:baf2da91597d101646b307b706d06b048862192b127f74b1079d374d902e3 25.35MB / 25.35MB 0.8s
=> exporting to image 1.9s
=> => exporting layers 0.0s
=> => exporting manifest sha256:77c9bb357067366f2629112b4af9e008bd9ff1ebcaa97f99420b2dfbc626 0.0s
=> => exporting config sha256:f53af215ede0ee11e25dcfdd813625fa1564d3053721493a1cc5553317c876 0.0s
=> => pushing layers 1.8s
=> => pushing manifest for 127.0.0.1:5000/acorn/acorn:latest@sha256:77c9bb357067366f2629112b 0.0s
[+] Building 1.7s (5/5) FINISHED
=> [internal] load build definition from Dockerfile 0.6s
=> => transferring dockerfile: 58B 0.5s
=> [internal] load .dockerignore 0.5s
=> => transferring context: 64B 0.5s
=> [internal] load build context 0.5s
=> => transferring context: 418B 0.5s
=> [1/1] COPY . / 0.1s
=> exporting to image 0.3s
=> => exporting layers 0.1s
=> => exporting manifest sha256:012dc34ea34ee765cb040392ffa1a15ac13dee9d09c4311c3026482b49aa 0.0s
=> => exporting config sha256:e3a86ddb9208a5d2b9868b7508490bbdb7293cc1f8a31c83b32d123e04ce9b 0.0s
=> => pushing layers 0.1s
=> => pushing manifest for 127.0.0.1:5000/acorn/acorn:latest@sha256:012dc34ea34ee765cb040392 0.0s
wandering-tree
acorn apps list
acorn apps
NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE
wandering-tree 3a6183bacf50 1 1 102s ago tcp://534320fc-56cf-4692-931d-cabcd9daa36b.lb.civo.com:80 => frontend:80 OK
You can see the PV/PVC created using civo-volume
storage class
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-a86abaa1-86cd-4893-b2fe-755703b9cec4 10Gi RWO Retain Bound wandering-tree-7d2bbad7-59d/web-content civo-volume 23m
kubectl get pvc -A
NAMESPACE NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
wandering-tree-7d2bbad7-59d web-content Bound pvc-a86abaa1-86cd-4893-b2fe-755703b9cec4 10Gi RWO civo-volume 23m
kubectl get svc -A | grep LoadBalancer
wandering-tree-7d2bbad7-59d frontend-publish-7d2bbad7-59d LoadBalancer 10.43.131.13 80:30072/TCP 6m59s
Again you can see how easy it is to deploy your application to the Kubernetes cluster.
Conclusion
Overall the first impressions are really good, where acorn is trying to solve the problem of deploying the apps across environments easily. Right now the apps do not do much and there are endpoint issues where sometimes it doesn't get populated, which I am sure is in the works already (I reported one issue on DNS as well). It would be good if acorn apps can fetch the logs, and can add a debug container in future. I would also like to see a GitOps approach, where you can connect to a repo and deploy directly from git. Something like an acorn monitor for the health of apps and then a fancy dashboard where I can monitor acorn, its components and apps. I will be keeping an eye on this project as I love the people behind it and will keep you all updated with the latest acorn features.
Since this review, we have added Acorn to our Marketplace: Launch a Civo Kubernetes cluster with Acorn.