In this guide, you will deploy Akri end-to-end, all the way from discovering local video cameras to the footage being streamed on a Web application. You will explore how Akri can dynamically discover devices, deploy brokers pods to perform some action on a device (in this case grabbing video frames and serving them over gRPC), and deploy broker services for obtaining the results of that action.
-
Acquire an Ubuntu 20.04 LTS, 18.04 LTS or 16.04 LTS environment to run the commands. If you would like to deploy the demo to a cloud-based VM, see the instructions for DigitalOcean or Google Compute Engine (and you can skip the rest of the steps in this document).
-
To make dummy video4linux devices, install the v4l2loopback kernel module and its prerequisites. Learn more about v4l2 loopback here
sudo apt update sudo apt -y install linux-modules-extra-$(uname -r) sudo apt -y install dkms curl http://deb.debian.org/debian/pool/main/v/v4l2loopback/v4l2loopback-dkms_0.12.5-1_all.deb -o v4l2loopback-dkms_0.12.5-1_all.deb sudo dpkg -i v4l2loopback-dkms_0.12.5-1_all.deb
When running on Ubuntu 20.04 LTS, 18.04 LTS or 16.04 LTS, do NOT install v4l2loopback through
sudo apt install -y v4l2loopback-dkms
, you will get an older version (0.12.3). 0.12.5-1 is required for gstreamer to work properly. -
Insert the kernel module, creating /dev/video1 and /dev/video2 devnodes. To create different number video devices modify the
video_nr
argument.sudo modprobe v4l2loopback exclusive_caps=1 video_nr=1,2
-
Install Gstreamer main packages
sudo apt-get install -y \ libgstreamer1.0-0 gstreamer1.0-tools gstreamer1.0-plugins-base \ gstreamer1.0-plugins-good gstreamer1.0-libav
-
Open two new terminals (one for each fake video device), and in each terminal ssh into your ubuntu server that your cluster is running on.
-
In one terminal, stream a test video of a white ball moving around a black background from the first fake video device.
sudo gst-launch-1.0 -v videotestsrc pattern=ball ! "video/x-raw,width=640,height=480,framerate=10/1" ! avenc_mjpeg ! v4l2sink device=/dev/video1
If this generates an error, be sure that there are no existing video streams targeting /dev/video1 (you can query with commands like this:
ps -aux | grep gst-launch-1.0 | grep "/dev/video1"
). -
In the other terminal, stream a test video of SMPTE 100%% color bars moving horizontally from the second fake video device.
sudo gst-launch-1.0 -v videotestsrc pattern=smpte horizontal-speed=1 ! "video/x-raw,width=640,height=480,framerate=10/1" ! avenc_mjpeg ! v4l2sink device=/dev/video2
If this generates an error, be sure that there are no existing video streams targeting /dev/video2 (you can query with commands like this:
ps -aux | grep gst-launch-1.0 | grep "/dev/video2"
).
Note: Feel free to deploy on any Kubernetes distribution. Here, find instructions for K3s and MicroK8s. Select and carry out one or the other (or adapt to your distribution), then continue on with the rest of the steps.
- Install K3s v1.18.9+k3s1.
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.18.9+k3s1 sh -
- Grant admin privilege to access kubeconfig.
sudo addgroup k3s-admin sudo adduser $USER k3s-admin sudo usermod -a -G k3s-admin $USER sudo chgrp k3s-admin /etc/rancher/k3s/k3s.yaml sudo chmod g+r /etc/rancher/k3s/k3s.yaml su - $USER
- Check K3s status.
kubectl get node
- Install Helm.
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml sudo apt install -y curl curl -L https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
- K3s uses its own embedded crictl, so we need to configure the Akri Helm chart with the k3s crictl path and socket.
export AKRI_HELM_CRICTL_CONFIGURATION="--set agent.host.crictl=/usr/local/bin/crictl --set agent.host.dockerShimSock=/run/k3s/containerd/containerd.sock"
- Install MicroK8s.
sudo snap install microk8s --classic --channel=1.18/stable
- Grant admin privilege for running MicroK8s commands.
sudo usermod -a -G microk8s $USER sudo chown -f -R $USER ~/.kube su - $USER
- Check MicroK8s status.
microk8s status --wait-ready
- Enable CoreDNS, Helm and RBAC for MicroK8s.
microk8s enable dns helm3 rbac
- If you don't have an existing
kubectl
andhelm
installations, add aliases. If you do not want to set an alias, addmicrok8s
in front of allkubectl
andhelm
commands.alias kubectl='microk8s kubectl' alias helm='microk8s helm3'
- For the sake of this demo, the udev video broker pods run privileged to easily grant them access to video devices, so
enable privileged pods and restart MicroK8s. More explicit device access could have been configured by setting the
appropriate security context in the broker PodSpec
in the Configuration.
echo "--allow-privileged=true" >> /var/snap/microk8s/current/args/kube-apiserver microk8s.stop microk8s.start
- Akri depends on crictl to track some Pod information. MicroK8s does not install crictl locally, so crictl must be installed and the Akri Helm chart needs to be configured with the crictl path and MicroK8s containerd socket.
# Note that we aren't aware of any version restrictions VERSION="v1.17.0" curl -L https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-${VERSION}-linux-amd64.tar.gz --output crictl-${VERSION}-linux-amd64.tar.gz sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin rm -f crictl-$VERSION-linux-amd64.tar.gz export AKRI_HELM_CRICTL_CONFIGURATION="--set agent.host.crictl=/usr/local/bin/crictl --set agent.host.dockerShimSock=/var/snap/microk8s/common/run/containerd.sock"
-
Use Helm to install Akri and create a Configuration to discover local video devices. Create your Configuration by setting values in your install command. Enable the udev Configuration which will search the Linux device filesystem as specified by a udev rule and give it a name. Since we want to find only video devices on the node, specify a udev rule of
KERNEL=="video[0-9]*"
. Also, specify the broker image you want to be deployed to discovered devices. In this case we will use Akri's sample frame server. Since the /dev/video1 and /dev/video2 devices are running on this node, the Akri Agent will discover them and create an Instance for each camera. Watch two broker pods spin up, one for each camera.helm repo add akri-helm-charts https://deislabs.github.io/akri/ helm install akri akri-helm-charts/akri \ $AKRI_HELM_CRICTL_CONFIGURATION \ --set useLatestContainers=true \ --set udev.enabled=true \ --set udev.name=akri-udev-video \ --set udev.udevRules[0]='KERNEL=="video[0-9]*"' \ --set udev.brokerPod.image.repository="ghcr.io/deislabs/akri/udev-video-broker:latest-dev"
For MicroK8s
watch microk8s kubectl get pods,akric,akrii -o wide
For K3s and vanilla Kubernetes
watch kubectl get pods,akric,akrii -o wide
Run
kubectl get crd
, and you should see the crds listed. Runkubectl get pods -o wide
, and you should see the Akri pods. Runkubectl get akric
, and you should seeakri-udev-video
. If IP cameras were discovered and pods spun up, the instances can be seen by runningkubectl get akrii
and further inspected by runingkubectl get akrii akri-udev-video-<ID> -o yaml
More information about the Akri Helm charts can be found in the user guide. -
Inspect the two instances, seeing the correct devnodes in the metadata and that one of the usage slots for each instance was reserved for this node.
kubectl get akrii -o yaml
-
Deploy the streaming web application and watch a pod spin up for the app.
kubectl apply -f https://raw.githubusercontent.com/deislabs/akri/main/deployment/samples/akri-video-streaming-app.yaml
For MicroK8s
watch microk8s kubectl get pods -o wide
For K3s and vanilla Kubernetes
watch kubectl get pods -o wide
-
Determine which port the service is running on.
kubectl get services
Something like the following will be displayed. The ids of the camera services (
udev-camera-<id>-svc
) will likely be different as they are determined by hostname.NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.XXX.XXX.X <none> 443/TCP 2d5h streaming NodePort 10.XXX.XXX.XX <none> 80:31143/TCP 41m udev-camera-901a7b-svc ClusterIP 10.XXX.XXX.XX <none> 80/TCP 42m udev-camera-e2548e-svc ClusterIP 10.XXX.XXX.XX <none> 80/TCP 42m udev-camera-svc ClusterIP 10.XXX.XXX.XXX <none> 80/TCP 42m
-
Navigate in your browser to http://ip-address:31143/ where ip-address is the IP address of your ubuntu VM and the port number is from the output of
kubectl get services
. You should see three videos. The top video streams frames from all udev cameras (from the overarchingudev-camera-svc
service), while each of the bottom videos displays the streams from each of the individual camera services (udev-camera-901a7b-svc
andudev-camera-e2548e-svc
). Note: the streaming web application displays at a rate of 1 fps.
- Bring down the streaming service.
For MicroK8s
kubectl delete service akri-video-streaming-app kubectl delete deployment akri-video-streaming-app
For K3s and vanilla Kuberneteswatch microk8s kubectl get pods
watch kubectl get pods
- Delete the configuration and watch the instances, pods, and services be deleted.
For MicroK8s
kubectl delete akric akri-udev-video
For K3s and vanilla Kuberneteswatch microk8s kubectl get pods,services,akric,akrii -o wide
watch kubectl get pods,services,akric,akrii -o wide
- Bring down the Akri Agent, Controller, and CRDs.
helm delete akri kubectl delete crd instances.akri.sh kubectl delete crd configurations.akri.sh
- Stop video streaming on dummy devices and remove kernel module.
# If terminal has timed out, search for process to kill. # ps ax | grep gst-launch-1.0 # sudo kill <PID> sudo modprobe -r v4l2loopback
- Plug in real cameras! You can pass environment variables to the frame server broker to specify the format, resolution width/height, and frames per second of your cameras.
- Apply the onvif-camera configuration and make the streaming app display footage from both the local video devices and onvif cameras. To do this, modify the video streaming yaml as described in the inline comments in order to create a larger service that aggregates the output from both the
udev-camera-svc
service andonvif-camera-svc
service. - Add more nodes to the cluster.
- Modify the udev rule to find a more specific subset of cameras.
- Discover other udev devices by creating a new udev configuration and broker. Learn more about the udev protocol here.