{"id":513,"date":"2024-06-03T00:29:36","date_gmt":"2024-06-02T23:29:36","guid":{"rendered":"https:\/\/www.alanknipmeyer.phd\/?p=513"},"modified":"2024-06-03T00:30:19","modified_gmt":"2024-06-02T23:30:19","slug":"an-easy-way-to-build-kubernetes-with-gpu-support","status":"publish","type":"post","link":"https:\/\/www.alanknipmeyer.phd\/index.php\/2024\/06\/03\/an-easy-way-to-build-kubernetes-with-gpu-support\/","title":{"rendered":"An easy way to build Kubernetes with GPU Support ?"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">So its been a busy couple of weeks, with writing up and collating information for my first Post Graduate Review (PGR) and actually being going to Bangor for training seminars, but more on that in a few weeks or so when all the sessions are completed !<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Today I&#8217;d like to focus on a <em>new to me<\/em> method of running and install Kubernetes on Ubuntu. Many starting with Kubernetes will use, and stick to <a href=\"https:\/\/microk8s.io\/\">microk8s<\/a> and it has the ability to use <a href=\"https:\/\/microk8s.io\/docs\/nvidia-dgx\">GPU via a single command<\/a>, however I am always keen to try out something new and this week I will focus on <a href=\"https:\/\/kind.sigs.k8s.io\/\">kind<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What is kind and why use it over microk8s \/others ?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">MicroK8s is excellent, but it can get quite technical, whilst that is not objectionable to me, I like to focus on actually building distributed container images that can work Kubernetes easily, i.e. CI\/CD and MLOps methodologies. What I &#8216;lose&#8217; on building a &#8216;production like&#8217; Kubernetes environment, I recoup in time focused on Machine Learning and the ability to use GPU&#8217;s easily. For a deeper comparison, I can recommend the page put together by Alperen on &#8216;<a href=\"https:\/\/alperenbayramoglu2.medium.com\/simple-comparison-of-lightweight-k8s-implementations-7c07c4e6e95f\">Simple Comparison of Lightweight K8S Implementations<\/a>&#8216;. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Getting started with Kind <\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I stated out with a vanilla install of Ubuntu Server 22.04 and installed the NVIDIA Drivers via the apt repository method. This did put me on a slight older version of CUDA, but sufficient enough to install Docker with GPU support. Documentation for this step is on NVIDIA&#8217;s website <a href=\"https:\/\/docs.nvidia.com\/ai-enterprise\/deployment-guide-vmware\/0.1.0\/docker.html\">here<\/a>, I didn&#8217;t encounter any issues following the steps provided.<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>sudo docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi\nSun Jun  2 22:49:42 2024       \n+-----------------------------------------------------------------------------+\n| NVIDIA-SMI 470.239.06   Driver Version: 470.239.06   CUDA Version: 11.4     |\n|-------------------------------+----------------------+----------------------+\n| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |\n| Fan  Temp  Perf  Pwr:Usage\/Cap|         Memory-Usage | GPU-Util  Compute M. |\n|                               |                      |               MIG M. |\n|===============================+======================+======================|\n|   0  NVIDIA GeForce ...  Off  | 00000000:01:00.0 Off |                  N\/A |\n|  0%   48C    P8    14W \/ 184W |      0MiB \/ 12021MiB |      0%      Default |\n|                               |                      |                  N\/A |\n+-------------------------------+----------------------+----------------------+\n                                                                               \n+-----------------------------------------------------------------------------+\n| Processes:                                                                  |\n|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |\n|        ID   ID                                                   Usage      |\n|=============================================================================|\n|  No running processes found                                                 |\n+-----------------------------------------------------------------------------+<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The prerequisite to install Kind is to have Go-lang installed, this was easily done using the Ubuntu package management apt, <a href=\"https:\/\/www.cherryservers.com\/blog\/install-go-ubuntu\">this page<\/a> was sufficient to install go and without any other dependencies.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As I was just wanting to get this up and running, I used root for now and will update modify later, but the steps should be the same for a regular user account. Install Kind was as easy os typing a single command, its worth checking to see on the <a href=\"https:\/\/github.com\/kubernetes-sigs\/kind\">kind repository<\/a> what is the latest version, as of writing its 0.23.0<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PATH=\/root\/go\/bin:$PATH\ngo install sigs.k8s.io\/kind@v0.23.0\nkind create cluster\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On the &#8216;dev&#8217; machine I have here it only took a few moments for kind to build all the necessary components to build a fully functioning Kubernetes system.  I tested this out with the standard &#8216;hello world&#8217; docker containers. Next I wanted to build with GPU support with the NVIDIA runtime support, on a regular Kubernetes cluster, this is quite an involved process, as documented <a href=\"https:\/\/docs.nvidia.com\/ai-enterprise\/deployment-guide-bare-metal\/0.1.0\/kubernetes.html\">here<\/a>. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once I had tested that a &#8216;standard&#8217; kind Kubernetes install worked correctly, I set about getting the GPU support working. This was far easier than the lengthy process in setting up a Kubernetes cluster on bare-metal with GPU support, I required to install &#8216;helm&#8217; to load the charts for the GPU. The full installation instructions are provided <a href=\"https:\/\/www.substratus.ai\/blog\/kind-with-gpus\">here<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kind create cluster --name substratus --config - &lt;&lt;EOF\napiVersion: kind.x-k8s.io\/v1alpha4\nkind: Cluster\nnodes:\n- role: control-plane\n  image: kindest\/node:v1.27.3@sha256:3966ac761ae0136263ffdb6cfd4db23ef8a83cba8a463690e98317add2c9ba72\n  # required for GPU workaround\n  extraMounts:\n    - hostPath: \/dev\/null\n      containerPath: \/var\/run\/nvidia-container-devices\/all\nEOF\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This process took a few moments and I did run into some issues with &#8220;Too Many Open Files&#8221;. This was quickly resolved by following the <a href=\"https:\/\/www.howtogeek.com\/805629\/too-many-open-files-linux\/\">Ubuntu<\/a> and <a href=\"https:\/\/lucaberton.medium.com\/troubleshooting-too-many-open-files-error-in-kubernetes-kube-proxy-16d5c7e7a691\">Kubernetes<\/a> fixes for these errors. With a reboot my Kubernetes node was running with GPU support !<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One of my favorite tools I have been introduced to in the last year is k9s, whilst I wont do a deep dive on all the functions it has, I can strongly recommend installing it. I used the &#8216;snap&#8217; package manager to install k9s<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>snap refresh k9s --channel=latest\/stable<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">It was then super easy to startup k9s and navigate my installation.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"286\" src=\"https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-1024x286.png\" alt=\"\" class=\"wp-image-514\" style=\"width:1092px;height:auto\" srcset=\"https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-1024x286.png 1024w, https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-300x84.png 300w, https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-768x215.png 768w, https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-1536x430.png 1536w, https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-2048x573.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">K9s running on KIND GPU Node<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Testing GPU Support within Kubernetes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Whilst my version of CUDA is slightly older, I was able to run a previous version of vectoradd<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl apply -f - &lt;&lt; EOF\napiVersion: v1\nkind: Pod\nmetadata:\n  name: cuda-vectoradd\nspec:\n  restartPolicy: OnFailure\n  containers:\n  - name: cuda-vectoradd\n    image: \"nvcr.io\/nvidia\/k8s\/cuda-sample:vectoradd-cuda11.2.1-ubuntu18.04\"\n    resources:\n      limits:\n        nvidia.com\/gpu: 1\nEOF<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"299\" src=\"https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-1-1024x299.png\" alt=\"\" class=\"wp-image-515\" srcset=\"https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-1-1024x299.png 1024w, https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-1-300x88.png 300w, https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-1-768x224.png 768w, https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-1-1536x449.png 1536w, https:\/\/www.alanknipmeyer.phd\/wp-content\/uploads\/2024\/06\/image-1.png 1814w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Vector-Add pod running and logs from k9s<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This was by far the easiest way I have experienced of running Kubernetes with GPU support on Ubuntu, whilst I&#8217;m not sure I would use this on a production environment, it works for me as a MLOps\/DevOps engineer that wants to focus on developing Cryptanalysis containers to run Kubernetes, therefore if you want such an environment, I can really recommend it !<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe title=\"Kind + GPU: A Local K8s cluster that can run GPU pods\" width=\"800\" height=\"450\" src=\"https:\/\/www.youtube.com\/embed\/O1683vzaJVE?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><figcaption class=\"wp-element-caption\">Excellent video from Samos expalning how to build k8s cluster with GPU support.<\/figcaption><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>So its been a busy couple of weeks, with writing up and collating information for my first Post Graduate Review (PGR) and actually being going to Bangor for training seminars, but more on that in a few weeks or so when all the sessions are completed ! Today I&#8217;d like to focus on a new [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26,17],"tags":[],"class_list":["post-513","post","type-post","status-publish","format-standard","hentry","category-kubernetes","category-lab"],"_links":{"self":[{"href":"https:\/\/www.alanknipmeyer.phd\/index.php\/wp-json\/wp\/v2\/posts\/513","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.alanknipmeyer.phd\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.alanknipmeyer.phd\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.alanknipmeyer.phd\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.alanknipmeyer.phd\/index.php\/wp-json\/wp\/v2\/comments?post=513"}],"version-history":[{"count":2,"href":"https:\/\/www.alanknipmeyer.phd\/index.php\/wp-json\/wp\/v2\/posts\/513\/revisions"}],"predecessor-version":[{"id":517,"href":"https:\/\/www.alanknipmeyer.phd\/index.php\/wp-json\/wp\/v2\/posts\/513\/revisions\/517"}],"wp:attachment":[{"href":"https:\/\/www.alanknipmeyer.phd\/index.php\/wp-json\/wp\/v2\/media?parent=513"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.alanknipmeyer.phd\/index.php\/wp-json\/wp\/v2\/categories?post=513"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.alanknipmeyer.phd\/index.php\/wp-json\/wp\/v2\/tags?post=513"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}