Skip to content

Kubernetes on edge for IoT: Akri (Microsoft) video demo & MicroK8s (Canonical) - Powered by GCE

License

Notifications You must be signed in to change notification settings

didier-durand/microk8s-akri

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

77 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Akri on MicroK8s

workflow badge License

Goal

This repository delivers a fully scripted workflow (install + run - based on microk8s-akri.yml and microk8s-akri.sh) on GitHub CI / CD of the end-to-end demo recently published by the Akri project: it illustrates the use of video cameras (mocked here by test video streams) in Kubernetes edge workloads. The badge above gives status of our last execution (see also section Execution Report for log excerpts) and details for all previous runs can be found in the Actions tab. Section Akri Helm Chart provides the fully expanded version of the K8s objects used in this showcase.

Akri by Microsoft follows the Greek-based naming tradition of the Kubernetes arena: "akri" means "edge" in Greek. Interestingly, the Akri acronym can also stand for "A Kubernetes Resource Interface". So, it's now clear that the project is all about edge computing and the Internet of Things (IoT) with its 30+ billions of connected objects to emerge in next five years: 4 connected objects per human being worldwide in 2025 as predicted by IoT Analytics.

The workflow is also automatically scheduled by cron (see microk8s-akri.yml) on GitHub on a recurrent basis to validate that it keeps working properly while its various components keep evolving: new versions of Akri, MicroK8s, Ubuntu, etc. MicroK8s defined as 'autonomous, production-grade Kubernetes, on cloud, clusters, workstations, Edge and IoT' is used here because its source code is extremely close to the upstream version of Kubernetes: this feature guarantees the widest possible range of use cases for those workloads making sophisticated use of the K8s features. We have already used it for same reasons in our scripted showcases for Kube Bench and Kata Containers.

Section Workflow Actions below details the sequence of actions needed to reach a working deployment starting from a fresh Ubuntu instance launched on Google Cloud Engine (GCE): we currently use a n1-standard-4 instance.

The workflow execution finally delivers the command(s) needed to obtain remote access on GCE to both the standard Kubernetes dashboard and the Akri demo application from the browser on your laptop: web pages similar to the ones below will be reached.

Feel free to fork and re-use! (Of course, if you like it, please, give it a star)

When you reach the end of workflow execution, you will be able to access, from your local browser two different applications produced by the pods of your MicroK8s cluster running on GCE. To allow port forwarding over ssh toward your laptop, you need to have gcloud SDK installed locally and to enter the following terminal command gcloud compute ssh microk8s-akri --zone=us-central1-c --project=$GCP_PROJECT --ssh-flag='-L 3443:localhost:3443 -L 12321:localhost:12321'. Then,

  1. http://localhost:12321 will get you to the Akri demo application. At the bottom, permament images (updated at 1 fps) of the 2 fake cameras: the first with a bouncing ball, the second one with a colour carrousel. The top image shifts from one camera to the other every few seconds.
  2. http://localhost:3443 will get you to the standard Kubernetes dashboard showing all details above the 11 active pods. You need to obtain the security token from the final lines of the execution log to authentify with the dashboard.

(click on pictures above to enlarge them)

Kubernetes On The Edge - Akri Architecture

Recent announcement by NIVIDIA demonstrates that Moore's Law remains in full force: installing a K8s microcluster on the edge is definitely possible now! The needed computing power with minimal form factor is available today and can serve even demanding edge ML / AI workloads.

One of the key differences between Kubernetes in the (public) cloud and Kubernetes on the edge is that, on the edge, workloads often require a variety of physical devices, like sensors, cameras and other leaf devices. Those leaf devices are single-purpose and limited: usually, no opportunity to load any additional software on them in order to make them multi-purpose or to become a member node of a Kubernetes cluster.

But the project team wanted those devices to remain easy to integrate with cloud-native workloads while keeping the resulting global system agile and flexible. So, they took the (smart) decision of treating the devices as resources and not compute nodes. Consequently, they designed some custom controllers and resources to dynamically discover the devices and expose them to applications as standard Kubernetes Custom Resources, easy to access and manipulate using the standard mechanisms and features of the platform.

Akri's architecture is very well depicted by the diagram below coming from the project introductory blog post.

This post details the various components in full detail: a must-read! The recent presentation video and Edge conference slides bring additional interesting information.

This architecture doesn't impose any overhead at all on the devices themselves. But, more importantly, at least to our mind, it keeps all software components of the global application within Kubernetes.

The interests are multiple:

  1. It keeps application developers, familiar with Kubernetes, in known territory: for edge workloads. they keep developing with K8s concepts, objects & APIs that they know very well for cloud applications.
  2. It leverages the advantages of cloud-native architecture end to end: powerful abstraction of infrastructure, smallest possible lead time from dev to prod, automatic updates for new versions, etc. Operations remain fully homogeneous: the full edge stack can be managed by deployment and management mechanisms and tools (new container versions, compliance validation, etc.) already mastered for central workloads on cloud Kubernetes. So, no need to plan for additional processes and tools, specific to edge software that would reside outside of Kubernetes.
  3. The use of advanced but standard features like Custom Resources and associated Controllers makes Akri easily extensible by the community. The team already announces the support of additional device protocols in upcoming releases: currently, Open Network Video Interface Forum (ONVIF) for IP cameras and Linux udev (userspace /dev) to manage hotplug-capable devices are supported. Beyond community contributions, the respect of the K8s standards will maximize Akri's composability, hence the added value that it delivers.

Regarding existing protocols, detailed instructions to configure the Helm chart for both protocols are provided: udev configuration guide and ONVIF configuration guide. The structure of the Helm chart itself is explained in the Helm section of user guide with full details regarding parameter values in Helm variable declarations.

Workflow Actions

This workflow is strongly inspired by the description and directives of the end-to-end demo provided by project's Github repo. Please, refer to it for all details.

In our script, we add the automation around the canonical procedure to run it on a Google Cloud GCE. The workflow is driven by ssh commands executed from another Ubuntu machine provided by Github CI / CD. Thorough logging is also added to allow post-mortem analysis of the failing executions as the underlying environment changes: Github Actions, Ubuntu, Microk8s, Akri Helm chart and container images get installed at latest version on new runs.

This additional logging can be suppressed if you prefer less verbose executions in your own use case. Additionally, microk8s-akri.sh can be run directly on your laptop: we use it as-is in MacOS terminal to execute the workflow on GCE without Github.

[NB: both sides of the shell scripting, GitHub and GCE, are contained in one bash file - uploaded by itself to GCE via scp - to more easily move and use it in different places]

Essentially, the sequence of actions to reach a working Akri demo from a fresh Ubuntu instance on GCE is:

  1. Start, via gcloud SDK, the fresh GCE Ubuntu instance where Akri, GStreamer and MicroK8s will be installed.
  2. Update all Ubuntu packages to their very last version via apt.
  3. Upload the shell script to GCE for execution.
  4. Install crictl, the Container Runtime CLI used by Akri's Helm Chart.
  5. Install package for v4l2loopback, the kernel module to create virtual video devices. IMPORTANT: version must be at least 0.12.5-1 (or newer) else GStreamer won't work: only Ubuntu 20.10 or newer comes with it upfront.
  6. Load module v4l2loopback in the kernel and create the 2 fake camera devices.
  7. Install GStreamer.
  8. Trigger reboot if needed (some updated packages may require it) and wait for return of the instance.
  9. Disconnect / reconnect to be able to use the authorizations granted via attachment to group 'microk8s'.
  10. Reload v4l2loopback and recreate the 2 fake camera devices.
  11. Launch as background process a different test video stream on each of the 2 cameras via GStreamer.
  12. Activate the MicroK8s addons required by Akri: dns, rbac, dashboard and helm3.
  13. Install Akri on MicroK8s via its Helm chart, with proper parameters to activate udev and discover devices.
  14. Validate proper deployment of the chart by checking availability of the installed Kubernetes objects.
  15. Deploy the sample video application.
  16. Validate its proper operations.

When all those steps have successfully completed, both the standard Kubernetes dashboard and the Akri sample video application can be accessed remotely on GCE from your laptop via your favorite browser using the directives and values provided at end of execution log. The security token required for access to the dashboard and taken from the generated kubectl config is also provided.

Fork & Run

To start, you need a Google Cloud account including a project where the GCE APIs have been enabled. Obtain the id of your project from GCP dashboard. Additionally, you need to create in this project a service account (SA) and give it proper GCE credentials: right to create, administer and delete GCE images & instances (if your cannot make the SA a "Project Owner" to simplify the security aspects...). Save the private key of the SA in json format.

Then, fork our repository and define the required Github Secrets in your fork:

  1. your GCP project id will be {{ secrets.GCP_PROJECT }}
  2. The private key of your service account in json format will be ${{ secrets.GCP_SA_KEY }}

To easily use the workflow from Github, you can launch it with the manual dispatch feature of Github that you can see as a launch button (the green one in the picture below) in the Action tab of your fork.

The workflow will execute all the steps described above and keep the instance up and running for further exploration. Up to you to delete it via Google Cloud console when it's no longer needed. When scheduled automatically, it will terminate gracefully after all validation tests described are completed: it will then delete the GCE instance.

Execution Report

### execution date: Thu Nov 26 14:59:37 UTC 2020
 
### microk8s snap version:
microk8s          v1.19.3    1791   1.19/stable      canonical*         classic
 
### gstreamer version:
gst-launch-1.0 version 1.16.2
GStreamer 1.16.2
https://launchpad.net/distros/ubuntu/+source/gstreamer1.0
 
### ubuntu version:
Linux microk8s-akri 5.4.0-1029-gcp #31-Ubuntu SMP Wed Oct 21 19:38:01 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.1 LTS
Release:	20.04
Codename:	focal
 

### build kernel module v4l2loopback: 
Selecting previously unselected package v4l2loopback-dkms.
(Reading database ... 73918 files and directories currently installed.)
Preparing to unpack v4l2loopback-dkms_0.12.5-1_all.deb ...
Unpacking v4l2loopback-dkms (0.12.5-1) ...
Setting up v4l2loopback-dkms (0.12.5-1) ...

### load kernel module v4l2loopback: 

### check required kernel modules: 
videodev              225280  1 v4l2loopback
mc                     53248  1 videodev
v4l2loopback           40960  0
videodev              225280  1 v4l2loopback
vermagic:       5.4.0-1029-gcp SMP mod_unload 

### check devices: 
crw------- 1 root root 81, 0 Nov 26 14:49 /dev/video1
crw------- 1 root root 81, 1 Nov 26 14:49 /dev/video2

### start video streams (in background): 
Setting pipeline to PAUSED ...
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0.GstPad:src: caps = video/x-raw, format=(string)I420, width=(int)640, height=(int)480, framerate=(fraction)10/1, multiview-mode=(string)mono, colorimetry=(string)2:4:7:1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = video/x-raw, format=(string)I420, width=(int)640, height=(int)480, framerate=(fraction)10/1, multiview-mode=(string)mono, colorimetry=(string)2:4:7:1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive
/GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0.GstPad:src: caps = video/x-raw, format=(string)I420, width=(int)640, height=(int)480, framerate=(fraction)10/1, multiview-mode=(string)mono, colorimetry=(string)2:4:7:1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = video/x-raw, format=(string)I420, width=(int)640, height=(int)480, framerate=(fraction)10/1, multiview-mode=(string)mono, colorimetry=(string)2:4:7:1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive
/GstPipeline:pipeline0/avenc_mjpeg:avenc_mjpeg0.GstPad:sink: caps = video/x-raw, format=(string)I420, width=(int)640, height=(int)480, framerate=(fraction)10/1, multiview-mode=(string)mono, colorimetry=(string)2:4:7:1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:sink: caps = video/x-raw, format=(string)I420, width=(int)640, height=(int)480, framerate=(fraction)10/1, multiview-mode=(string)mono, colorimetry=(string)2:4:7:1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive
/GstPipeline:pipeline0/avenc_mjpeg:avenc_mjpeg0.GstPad:sink: caps = video/x-raw, format=(string)I420, width=(int)640, height=(int)480, framerate=(fraction)10/1, multiview-mode=(string)mono, colorimetry=(string)2:4:7:1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:sink: caps = video/x-raw, format=(string)I420, width=(int)640, height=(int)480, framerate=(fraction)10/1, multiview-mode=(string)mono, colorimetry=(string)2:4:7:1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive
/GstPipeline:pipeline0/avenc_mjpeg:avenc_mjpeg0.GstPad:src: caps = image/jpeg, parsed=(boolean)true, width=(int)640, height=(int)480, colorimetry=(string)2:4:7:1, framerate=(fraction)10/1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, multiview-mode=(string)mono, multiview-flags=(GstVideoMultiviewFlagsSet)0:ffffffff:/right-view-first/left-flipped/left-flopped/right-flipped/right-flopped/half-aspect/mixed-mono
/GstPipeline:pipeline0/avenc_mjpeg:avenc_mjpeg0.GstPad:src: caps = image/jpeg, parsed=(boolean)true, width=(int)640, height=(int)480, colorimetry=(string)2:4:7:1, framerate=(fraction)10/1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, multiview-mode=(string)mono, multiview-flags=(GstVideoMultiviewFlagsSet)0:ffffffff:/right-view-first/left-flipped/left-flopped/right-flipped/right-flopped/half-aspect/mixed-mono
/GstPipeline:pipeline0/GstV4l2Sink:v4l2sink0.GstPad:sink: caps = image/jpeg, parsed=(boolean)true, width=(int)640, height=(int)480, colorimetry=(string)2:4:7:1, framerate=(fraction)10/1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, multiview-mode=(string)mono, multiview-flags=(GstVideoMultiviewFlagsSet)0:ffffffff:/right-view-first/left-flipped/left-flopped/right-flipped/right-flopped/half-aspect/mixed-mono
/GstPipeline:pipeline0/GstV4l2Sink:v4l2sink0.GstPad:sink: caps = image/jpeg, parsed=(boolean)true, width=(int)640, height=(int)480, colorimetry=(string)2:4:7:1, framerate=(fraction)10/1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, multiview-mode=(string)mono, multiview-flags=(GstVideoMultiviewFlagsSet)0:ffffffff:/right-view-first/left-flipped/left-flopped/right-flipped/right-flopped/half-aspect/mixed-mono
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock

### enabling microk8s addons: 
Enabling DNS
Applying manifest
serviceaccount/coredns created
configmap/coredns created
deployment.apps/coredns created
service/kube-dns created
clusterrole.rbac.authorization.k8s.io/coredns created
clusterrolebinding.rbac.authorization.k8s.io/coredns created
Restarting kubelet
DNS is enabled
Enabling Helm 3
Fetching helm version v3.0.2.
Helm 3 is enabled
Enabling RBAC
Reconfiguring apiserver
RBAC is enabled
Enabling Kubernetes Dashboard
Enabling Metrics-Server
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
serviceaccount/metrics-server created
deployment.apps/metrics-server created
service/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
clusterrolebinding.rbac.authorization.k8s.io/microk8s-admin created
Metrics-Server is enabled
Applying manifest
serviceaccount/kubernetes-dashboard created
service/kubernetes-dashboard created
secret/kubernetes-dashboard-certs created
secret/kubernetes-dashboard-csrf created
secret/kubernetes-dashboard-key-holder created
configmap/kubernetes-dashboard-settings created
role.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
deployment.apps/kubernetes-dashboard created
service/dashboard-metrics-scraper created
deployment.apps/dashboard-metrics-scraper created

If RBAC is not enabled access the dashboard using the default token retrieved with:

token=$(microk8s kubectl -n kube-system get secret | grep default-token | cut -d " " -f1)
microk8s kubectl -n kube-system describe secret $token

In an RBAC enabled setup (microk8s enable RBAC) you need to create a user with restricted
permissions as shown in:
https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md


### install akri chart: 
"akri-helm-charts" has been added to your repositories
NAME: akri
LAST DEPLOYED: Thu Nov 26 14:58:13 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the Akri Controller:
  kubectl get -o wide pods | grep controller
2. Get the Akri Agent(s):
  kubectl get -o wide pods | grep agent
3. Get the Akri Configuration(s):
  kubectl get -o wide akric

### waiting for installed chart to get ready: 
deployment.apps/akri-controller-deployment condition met

### get akri configuration: 
NAME              CAPACITY   AGE
akri-udev-video   1          60s

### install video streaming app: 
deployment.apps/akri-video-streaming-app created
service/akri-video-streaming-app created
deployment.apps/akri-video-streaming-app condition met

### get pods --all-namespaces: 
NAMESPACE     NAME                                          READY   STATUS    RESTARTS   AGE     IP            NODE            NOMINATED NODE   READINESS GATES
kube-system   calico-kube-controllers-847c8c99d-x8t4w       1/1     Running   1          4m49s   10.1.54.71    microk8s-akri   <none>           <none>
kube-system   kubernetes-dashboard-7ffd448895-2svqv         1/1     Running   0          2m26s   10.1.54.67    microk8s-akri   <none>           <none>
kube-system   calico-node-d9trc                             1/1     Running   2          4m49s   10.128.0.43   microk8s-akri   <none>           <none>
kube-system   dashboard-metrics-scraper-6c4568dc68-22xq2    1/1     Running   0          2m26s   10.1.54.69    microk8s-akri   <none>           <none>
kube-system   metrics-server-8bbfb4bdb-qfzqg                1/1     Running   0          2m26s   10.1.54.70    microk8s-akri   <none>           <none>
kube-system   coredns-86f78bb79c-dxp8x                      1/1     Running   0          2m48s   10.1.54.68    microk8s-akri   <none>           <none>
default       akri-agent-daemonset-zcmqs                    1/1     Running   0          82s     10.128.0.43   microk8s-akri   <none>           <none>
default       akri-controller-deployment-5b4bb5cbb5-gxzml   1/1     Running   0          82s     10.1.54.72    microk8s-akri   <none>           <none>
default       akri-udev-video-aa247f-pod                    1/1     Running   0          73s     10.1.54.74    microk8s-akri   <none>           <none>
default       akri-udev-video-018417-pod                    1/1     Running   0          73s     10.1.54.73    microk8s-akri   <none>           <none>
default       akri-video-streaming-app-fd5f4cb7d-dv499      1/1     Running   0          21s     10.1.54.75    microk8s-akri   <none>           <none>

### get daemonsets --all-namespaces: 
NAMESPACE     NAME                   DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE     CONTAINERS    IMAGES                                   SELECTOR
kube-system   calico-node            1         1         1       1            1           kubernetes.io/os=linux   4m59s   calico-node   calico/node:v3.13.2                      k8s-app=calico-node
default       akri-agent-daemonset   1         1         1       1            1           kubernetes.io/os=linux   82s     akri-agent    ghcr.io/deislabs/akri/agent:latest-dev   name=akri-agent

### get services --all-namespaces: 
NAMESPACE     NAME                         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE     SELECTOR
default       kubernetes                   ClusterIP   10.152.183.1     <none>        443/TCP                  4m59s   <none>
kube-system   kube-dns                     ClusterIP   10.152.183.10    <none>        53/UDP,53/TCP,9153/TCP   2m48s   k8s-app=kube-dns
kube-system   metrics-server               ClusterIP   10.152.183.104   <none>        443/TCP                  2m28s   k8s-app=metrics-server
kube-system   kubernetes-dashboard         ClusterIP   10.152.183.159   <none>        443/TCP                  2m27s   k8s-app=kubernetes-dashboard
kube-system   dashboard-metrics-scraper    ClusterIP   10.152.183.123   <none>        8000/TCP                 2m27s   k8s-app=dashboard-metrics-scraper
default       akri-udev-video-aa247f-svc   ClusterIP   10.152.183.241   <none>        80/TCP                   63s     akri.sh/instance=akri-udev-video-aa247f,controller=akri.sh
default       akri-udev-video-svc          ClusterIP   10.152.183.142   <none>        80/TCP                   63s     akri.sh/configuration=akri-udev-video,controller=akri.sh
default       akri-udev-video-018417-svc   ClusterIP   10.152.183.59    <none>        80/TCP                   63s     akri.sh/instance=akri-udev-video-018417,controller=akri.sh
default       akri-video-streaming-app     NodePort    10.152.183.21    <none>        80:32293/TCP             21s     app=akri-video-streaming-app
Akri dashboard ports - gce:  80 - local: 12321 
K8s dashboard ports - gce:  443 - local: 3443 
Forwarding from 127.0.0.1:12321 -> 5000
Forwarding from [::1]:12321 -> 5000
Forwarding from 127.0.0.1:3443 -> 8443
Forwarding from [::1]:3443 -> 8443
default microk8s token:
ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNkluVnBlaTFwYW1vdGJqZHdhR1ZDUjI1MmNFcG9NMHBvTFVwMFRGbGpSR2hoWjNoVlRGbG9ka3N3TUc4aWZRLmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUpyZFdKbExYTjVjM1JsYlNJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZqY21WMExtNWhiV1VpT2lKa1pXWmhkV3gwTFhSdmEyVnVMWEE1YTJ0MElpd2lhM1ZpWlhKdVpYUmxjeTVwYnk5elpYSjJhV05sWVdOamIzVnVkQzl6WlhKMmFXTmxMV0ZqWTI5MWJuUXVibUZ0WlNJNkltUmxabUYxYkhRaUxDSnJkV0psY201bGRHVnpMbWx2TDNObGNuWnBZMlZoWTJOdmRXNTBMM05sY25acFkyVXRZV05qYjNWdWRDNTFhV1FpT2lJek1qZGhaamczTXkwNVpHSTRMVFJsT1RFdFlUUm1NQzFoTnpjeU56azFaRFExTURRaUxDSnpkV0lpT2lKemVYTjBaVzA2YzJWeWRtbGpaV0ZqWTI5MWJuUTZhM1ZpWlMxemVYTjBaVzA2WkdWbVlYVnNkQ0o5LmE2R0dCdV83N1RZSUVOOHg3NDR1aVR4bHZkS3dpSWtkc0dWeFF5YmY2WDBYVmhseG50ZDFuTnJzS280NEFsVmhVLWJNbkp4REZvOWVIUjBwVW8xaHhScldUU2pzTjFmNmtJaGJKd1UzSUxFSExrR1JBWmZhVThfMXhrSldmNGY4TGFsNmFxSXpsZVdOaU9PMFBYOUxyV2FmUjROeFhzbkczZkhxckRNN18xR1pSQ3NmWFZOUHUwbUNaMVpYZWJITldYUFlYdGlXX05mWHNheTJWWnhLTVhwVG9XRE43Y0dnMFNhaGFOeEx4QnRVNlpZS2hGV2cxTUUyQ08weVFsRmZmWE9iYkd4WjhXYjI5SkF6bWJGNTlQeUdZSzVHbE9NcWdHOHBsZ2pqS0pvcHdGLVpTekdrZWJwckRSN2JTbXg1TkdBX2dkbnBLTExRa3JJc2N3eVVPZw==
Handling connection for 12321
<html>
  <head>
    <title>Akri Demo</title>
  </head>
  <body>
    <div style="max-width: 800px;  margin: auto;text-align:center">
      <h1>Akri Demo</h1>
      <div style="display: inline-block;clear:both;margin-bottom:30px">
        <img src="/camera_frame_feed/0" style="width:480px">
      </div>
      <ul style="display: block;list-style-type: none;padding:0;">
        
        <li style="display: inline-block; padding: 0 25">
          <img src="/camera_frame_feed/1" style="width:200px">
        </li>
        
        <li style="display: inline-block; padding: 0 25">
          <img src="/camera_frame_feed/2" style="width:200px">
        </li>
        
      </ul>
    </div>
  </body>
</html>Handling connection for 12321
Handling connection for 12321
 
gcloud command for port-forwarding of K8s & Akri dashboards:  gcloud compute ssh microk8s-akri --zone=us-central1-c  --project=$GCP_PROJECT  --ssh-flag='-L 3443:localhost:3443 -L 12321:localhost:12321'
 
K8s authentication token: WkZSYllqYkZTRnlkR0dxZXAvWlk5QXZhWUJra2hlSHlJbCtSb2Q1OWNlUT0K
K8s dashboard: https://localhost:3443
Akri dashboard:  http://localhost:12321

Akri Helm Chart

### generation date: Thu Nov 26 14:59:46 UTC 2020
 
version.BuildInfo{Version:"v3.4.1", GitCommit:"c4e74854886b2efe3321e185578e6db9be0a6e29", GitTreeState:"clean", GoVersion:"go1.14.11"}
---
# Source: akri-dev/templates/rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: akri-controller-sa
---
# Source: akri-dev/templates/rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: akri-agent-sa
---
# Source: akri-dev/templates/rbac.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: "akri-controller-role"
rules:
- apiGroups: [""]
  resources: ["pods", "services"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["akri.sh"]
  resources: ["instances"]
  verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: ["akri.sh"]
  resources: ["configurations"]
  verbs: ["get", "list", "watch"]
---
# Source: akri-dev/templates/rbac.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: "akri-agent-role"
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["akri.sh"]
  resources: ["instances"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["akri.sh"]
  resources: ["configurations"]
  verbs: ["get", "list", "watch"]
---
# Source: akri-dev/templates/rbac.yaml
apiVersion: 'rbac.authorization.k8s.io/v1'
kind: 'ClusterRoleBinding'
metadata:
  name: 'akri-controller-binding'
  namespace: default
roleRef:
  apiGroup: ''
  kind: 'ClusterRole'
  name: 'akri-controller-role'
subjects:
  - kind: 'ServiceAccount'
    name: 'akri-controller-sa'
    namespace: default
---
# Source: akri-dev/templates/rbac.yaml
apiVersion: 'rbac.authorization.k8s.io/v1'
kind: 'ClusterRoleBinding'
metadata:
  name: 'akri-agent-binding'
  namespace: default
roleRef:
  apiGroup: ''
  kind: 'ClusterRole'
  name: 'akri-agent-role'
subjects:
  - kind: 'ServiceAccount'
    name: 'akri-agent-sa'
    namespace: default
---
# Source: akri-dev/templates/agent.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: akri-agent-daemonset
spec:
  selector:
    matchLabels:
      name: akri-agent
  template:
    metadata:
      labels:
        name: akri-agent
    spec:
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet
      nodeSelector:
        "kubernetes.io/os": linux
      serviceAccountName: 'akri-agent-sa'
      containers:
      - name: akri-agent
        image: "ghcr.io/deislabs/akri/agent:v0.0.43-dev"
        imagePullPolicy: Always
        env:
          - name: HOST_CRICTL_PATH
            value: /host/usr/bin/crictl
          - name: HOST_RUNTIME_ENDPOINT
            value: unix:///host/var/run/dockershim.sock
          - name: HOST_IMAGE_ENDPOINT
            value: unix:///host/var/run/dockershim.sock
          - name: AGENT_NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
        volumeMounts:
          - name: device-plugin
            mountPath: /var/lib/kubelet/device-plugins
          - name: usr-bin-crictl
            mountPath: /host/usr/bin/crictl
          - name: var-run-dockershim
            mountPath: /host/var/run/dockershim.sock
          - name: devices
            mountPath: /run/udev
        securityContext:
          privileged: true
      volumes:
      - name: device-plugin
        hostPath:
          path: "/var/lib/kubelet/device-plugins"
      - name: usr-bin-crictl
        hostPath:
          path: "/usr/bin/crictl"
      - name: var-run-dockershim
        hostPath:
          path: "/var/run/dockershim.sock"
      - name: devices
        hostPath:
          path: "/run/udev"
---
# Source: akri-dev/templates/controller.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: akri-controller-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: akri-controller
  template:
    metadata:
      labels:
        app: akri-controller
    spec:
      serviceAccountName: 'akri-controller-sa'
      containers:
      - name: akri-controller
        image: "ghcr.io/deislabs/akri/controller:v0.0.43-dev"
        imagePullPolicy: Always
      tolerations:
        # Allow this pod to run on the master.
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
      nodeSelector:
        "kubernetes.io/os": linux

About

Kubernetes on edge for IoT: Akri (Microsoft) video demo & MicroK8s (Canonical) - Powered by GCE

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages