Using Nanobus to Replace Nginx

After I was able to Deploy a Nanobus Web Server, I thought about using Nanbous to replace Nginx. I’ve moved on a little from Deploying Nginx + PHP + git-sync on Kubernetes. I still run Nginx + git-sync on Kubernetes. I’ve removed the need for PHP in my Nginx web servers anymore. I thought, do I still really need to run a full blown Nginx anymore on some of my static servers? Let’s find out!

Setting Up The Repo

I’m not going to bore you with the details here because I’ve covered the bulk of setting up a repo in previous articles such as the one noted above. I will at least cover here what I’m putting into the repo. I’m going to first create a super simple index.html file

<html><body>
Testing Content
</body>
</html>

I’ve added this to a content directory in my repo. In the root of my repo, I’ll add in a bus.yaml for the Nanobus web server:

id: static-content-server
version: 0.0.1
transports:
  https:
    uses: nanobus.transport.http.server/v1
    with:
      address: ':8000'
      routers:
        - uses: nanobus.transport.http.static/v1
          with:
            paths:
              - file: /www/www/content/index.html
                path: /

One import concept here is to make sure your file value points to where you actually plan to mount this repo. More on that in the next section. The directory structure for the repo looks like this:

.
./bus.yaml
./content
./content/index.html

Setting Up The Kubernetes Deployment

Since my previous configuration was all deployed via Kubernetes, I want to do the same with this. I put together a super simple YAML that has a service and deployment:

apiVersion: v1
kind: Service
metadata:
  name: nano-web
  labels:
    tier: backend
spec:
  selector:
    app: nano-web
    tier: backend
  ports:  
  - name: http
    port: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nano-web
  labels:
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nano-web
      tier: backend
  template:
    metadata:
      labels:
        app: nano-web
        tier: backend
    spec:
      securityContext:
        fsGroup: 65533 # to make SSH key readable
      volumes:
      - name: dir
        emptyDir: {}
      - name: github-secret
        secret:
          secretName: github-creds
          defaultMode: 288
      containers:
      - env:
        - name: GIT_SYNC_REPO
          value: [email protected]:<my-user>/<my-static-repo>.git
        - name: GIT_SYNC_BRANCH
          value: master
        - name: GIT_SYNC_SSH
          value: "true"
        - name: GIT_SYNC_PERMISSIONS
          value: "0777"
        - name: GIT_SYNC_DEST
          value: www
        - name: GIT_SYNC_ROOT
          value: /git
        name: git-sync
        image: k8s.gcr.io/git-sync:v3.1.1
        securityContext:
          runAsUser: 65533 # git-sync user
        volumeMounts:
        - name: git-secret
          mountPath: /etc/git-secret
        - name: dir
          mountPath: /git
      - name: nano-web
        image: nanobus/nanobus
        args:
          - "run"
          - "/www/www/bus.yaml"
        ports:
        - containerPort: 8000
        volumeMounts:
        - name: dir
          mountPath: /www

It is also very important to again point out these items from the YAML:

...
        - name: GIT_SYNC_DEST
          value: www
...
        args:
          - "run"
          - "/www/www/bus.yaml"
...
        - name: dir
          mountPath: /www

The GIT_SYNC_DEST says that we’ll mount the git repo into the www directory. The mountPath says that we should mount the git sync to /www. This means that our repo’s root will be /www/www. This means that our bus.yaml will be located in /www/www/bus.yaml and the index.html file will be at /www/www/content/index.html.

Deploying and Testing

Now that I’ve got everything in place, let’s wave the magic kubectl wand:

 % kubectl apply -f ../static/nano-web.yaml                                
service/nano-web created
deployment.apps/nano-web created

We can check out the deployment:

% kubectl get pod                            
NAME                            READY   STATUS    RESTARTS          AGE
nano-web-899b74798-4n5jt        1/2     Error     0                 3s

% kubectl get pod                            
NAME                            READY   STATUS    RESTARTS          AGE
nano-web-899b74798-4n5jt        2/2     Running   2 (1m ago)       1m

You will want to check the pod a few times because it will start in an Error state until the git sync finishes and makes the volume available. After we’ve got a Running status, let’s check the logs:

 % kubectl logs -f nano-web-899b74798-4n5jt -c nano-web
2023-02-15T21:54:21.745Z	INFO	Initializing codec	{"name": "cloudevents+json", "type": "cloudevents+json"}
2023-02-15T21:54:21.745Z	INFO	Initializing codec	{"name": "text/plain", "type": "text/plain"}
2023-02-15T21:54:21.745Z	INFO	Initializing codec	{"name": "text/html", "type": "text/html"}
2023-02-15T21:54:21.745Z	INFO	Initializing codec	{"name": "bytes", "type": "bytes"}
2023-02-15T21:54:21.745Z	INFO	Initializing codec	{"name": "json", "type": "json"}
2023-02-15T21:54:21.745Z	INFO	Initializing codec	{"name": "msgpack", "type": "msgpack"}
2023-02-15T21:54:21.745Z	INFO	Initializing codec	{"name": "cloudevents+avro", "type": "cloudevents+avro"}
2023-02-15T21:54:21.746Z	INFO	Initializing transport	{"name": "http"}
2023-02-15T21:54:21.746Z	INFO	Serving static files	{"path": "/", "dir": null, "file": "/www/www/content/index.html", "strip": null}
2023-02-15T21:54:21.753Z	INFO	HTTP server listening	{"address": ":8000"}

This all looks good so let’s do the final test by checking it with our web browser. I haven’t exposed this yet outside of my cluster so we’ll port forward with a little kubectl port-forward svc/nano-web 8000:8000 and check the browser.

web browser screenshot showing Testing Content
Testing Content Page

Sure enough! That’s what we expected.

The Battle Continues

As I was writing this article, I noticed that my reference files from Deploying Nginx + PHP + git-sync on Kubernetes

were broken :facepalm:. This is a great opportunity to fix them! I updated my bus.yaml file to include the blog_posts directory:

id: static-content-server
version: 0.0.1
transports:
  https:
    uses: nanobus.transport.http.server/v1
    with:
      address: ':8000'
      routers:
        - uses: nanobus.transport.http.static/v1
          with:
            paths:
              - file: /www/www/content/index.html
                path: /
              - dir: /www/www/content/my_blog_post_files/20191229
                path: /my_blog_post_files/20191229
                strip: /my_blog_post_files/20191229

Redeploying and checking the browser yields success! The YAML was returned.

This is a great next question. I had to redeploy to get this to work because it needed a new bus.yaml file. The whole point of this is to be able to update my web content by simply updating a git repo.

Testing For Success

I’ll start by first testing for something that does not exist

% curl https://localhost:8000/my_blog_post_files/20191229/does_not_exist.txt
404 page not found

This error is ok because it was totally expected. This file does not exist, yet. I’ll quickly create that file in my repo:

% echo "testing 1 2 3" > my_blog_post_files/20191229/does_not_exist.txt

Next, I do my git commit and git push to update the repo. After waiting a few seconds for the repo to sync, I’ll run another curl:

% curl https://localhost:8000/my_blog_post_files/20191229/does_not_exist.txt
testing 1 2 3

Success! Let’s see if I change the file and commit will it still update?

% echo "4 5 6 7 8" >> my_blog_post_files/20191229/does_not_exist.txt

% git commit -a
[master 4637b99] Altering test file
 1 file changed, 1 insertion(+)

% git push origin master                                            
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Delta compression using up to 8 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (7/7), 593 bytes | 593.00 KiB/s, done.
Total 7 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To github.com:<some_user>/<some_repo>.git
   9f5d696..4637b99  master -> master

 % curl https://localhost:8000/my_blog_post_files/20191229/does_not_exist.txt
testing 1 2 3
4 5 6 7 8

I don’t just serve text documents with this nginx server so let’s see if we can also serve up images. I copied over a quick logo file and tested this:

Still Successful!!! My little experiment using Nanobus to replace Nginx is declared a success. It looks like it is time to switch out all of my other static Nginx servers for Nanobus now.