Adding Storage

Housekeeping

See the Getting Started documentation for installing and setting up:

  • microk8s

  • UCF tools

    • Accessing NGC

    • Setting up repositories

Introduction

In this tutorial, we will show how to add storage to UCF microservices and applications.

This will help you get familiar with the basics of:

  • Using a local-path-provisioner to create PersistentVolume (PVs) and PersistentVolumeClaim (PVCs), and

  • Defining and adding PVs and PVCs to microservices.

Local Path Provisioner

First, install the Local Path Provisioner by running the following command if not already done:

$ curl https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.23/deploy/local-path-storage.yaml | sed 's/^  name: local-path$/  name: mdx-local-path/g' | microk8s kubectl apply -f -

Now, we can use local storage in our microservices.

Defining and Adding PVs and PVCs to Microservices

Create a PVC by running:

$ curl https://raw.githubusercontent.com/rancher/local-path-provisioner/master/examples/pvc/pvc.yaml | \
      sed 's/storageClassName: local-path$/storageClassName: mdx-local-path/g' | microk8s kubectl apply -f -

Let’s update the microservice manifest of our HTTP server microservice http-server:

type: msapplication
specVersion: 2.0.0
name: ucf.svc.http-server
chartName: http-server
description: http server
version: 0.0.2
tags: []
keywords: []
publish: false
ingress-endpoints:
  - name: http
    description: REST API endpoint
    protocol: TCP
    scheme: http
    mandatory: False
    data-flow: in-out
---
spec:
  - name: http-server-deployment
    type: ucf.k8s.app.deployment
    parameters:
      apptype: stateless

  - name: http-server-container
    type: ucf.k8s.container
    parameters:
      image:
        repository: nvcr.io/nvidia/pytorch
        tag: 22.04-py3
      command: [sh, -c]
      args: [
            "cd /localvol && echo $PWD && touch somefile.txt && ls && python -m http.server 8080
            "]
      ports:
        - containerPort: 8080
          name: http
      volumeMounts:
        - name: localvol
          mountPath: /localvol

  - name: svc
    type: ucf.k8s.service
    parameters:
      ports:
      - port: 8080
        protocol: TCP
        name: http

  - name: localvol
    type: ucf.k8s.volume
    parameters:
      persistentVolumeClaim:
        claimName: local-path-pvc

There are two additions to our manifest file:

  • A keyword volumeMounts with parameters to the UCF Container Component

  • Another UCF Component of type ucf.k8s.volume that will logically connect tp the PVC

We won’t make any changes to client.

In the app.yaml file to the following:

specVersion: 2.0.0
version: 0.0.2
doc: README.md
name: server-client-app
description: Server Client Application

dependencies:
- ucf.svc.curl-client:0.0.1
- ucf.svc.http-server:0.0.2

components:
- name: client
  type: ucf.svc.curl-client
- name: http-server
  type: ucf.svc.http-server

connections:
    client/http: http-server/http

The version of the http-server and the app has been updated.

Building Microservices and Applications and Deploying them

Follow the steps mentioned below but remember to update the version of the http-server under dependencies section in app.yaml

Inspecting and Debugging Microservices and Application

Let’s verify that the application was deployed successfully:

$ microk8s kubectl get all
NAME                                                      READY   STATUS             RESTARTS      AGE
pod/http-server-http-server-deployment-575bd9c956-4zd2l   1/1     Running            0             3m27s
pod/curl-client-curl-client-deployment-64b485b4f7-zlqn8   1/1     Running            0             3m27s

NAME                                             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/kubernetes                               ClusterIP   10.152.183.1    <none>        443/TCP    82d
service/http-server-http-server-deployment-svc   ClusterIP   10.152.183.70   <none>        8080/TCP   3m27s

NAME                                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/http-server-http-server-deployment   1/1     1            1           3m27s
deployment.apps/curl-client-curl-client-deployment   1/1     1            1           3m27s

NAME                                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/http-server-http-server-deployment-575bd9c956   1         1         1       3m27s
replicaset.apps/curl-client-curl-client-deployment-64b485b4f7   1         1         1       3m27s

We can check the http-server container to see print the current working directory - in this case the /localvol folder. If we were using something like Triton Inference Server, we could add models here!

$ microk8s kubectl logs --tail -1 -l "app=http-server-http-server-deployment"
/localvol
somefile.txt

We can also get logs to verify if the file was created in the mounted vol:

$ microk8s kubectl logs --tail -1 -l "app=curl-client-curl-client-deployment"
    % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                  Dload  Upload   Total   Spent    Left  Speed
  100   346  100   346    0     0   112k      0 --:--:-- --:--:-- --:--:--  112k
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  <html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>Directory listing for /</title>
  </head>
  <body>
  <h1>Directory listing for /</h1>
  <hr>
  <ul>
  <li><a href="somefile.txt">somefile.txt</a></li>
  </ul>
  <hr>
  </body>
  </html>

As we can see somefile.txt shows up in the client, meaning that the file was indeed created in the mounted file path.

Stopping and Cleaning up Microservices and Applications

Finally, to stop and clean up the application we can run:

$ microk8s helm3 uninstall server-client