<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yash Panchal</title>
    <description>The latest articles on DEV Community by Yash Panchal (@panchalhimself).</description>
    <link>https://dev.to/panchalhimself</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F269371%2F2f3f3b78-a8ba-4173-93ae-9a5a7db77850.png</url>
      <title>DEV Community: Yash Panchal</title>
      <link>https://dev.to/panchalhimself</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/panchalhimself"/>
    <language>en</language>
    <item>
      <title>Understanding the significance of the CPU in the age of GPU</title>
      <dc:creator>Yash Panchal</dc:creator>
      <pubDate>Tue, 03 Mar 2026 15:15:47 +0000</pubDate>
      <link>https://dev.to/panchalhimself/understanding-the-significance-of-the-cpu-in-the-age-of-gpu-5ah5</link>
      <guid>https://dev.to/panchalhimself/understanding-the-significance-of-the-cpu-in-the-age-of-gpu-5ah5</guid>
      <description>&lt;h2&gt;
  
  
  Why does CPU matter ?
&lt;/h2&gt;

&lt;p&gt;With the exponential growth of AI models the &lt;strong&gt;primary compute component that is being focused&lt;/strong&gt; right now is &lt;strong&gt;GPU&lt;/strong&gt;. Most of the people are out there gauging for the latest GPU benchmarks and talking about how to use GPUs. However the significance of CPU is being undermined due to this hype.&lt;/p&gt;

&lt;p&gt;Most new folks (students and new engineers) are emphasising more on the GPU benchmarks than understanding the system as a whole. &lt;/p&gt;

&lt;p&gt;While GPU capacity matters a alot, we are reaching a point where &lt;strong&gt;Compute is cheap while the loading and unloading of the data is becoming expensive in terms of time&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  CPUs are still critical component
&lt;/h3&gt;

&lt;p&gt;Let us understand why CPU is essential to any AI workload.&lt;/p&gt;

&lt;p&gt;Understanding the flow of an opensource model inference:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Downloading model from the internet (Gets stored in the Harddrive)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Running AI workload :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The stored model is moved from Harddrive to the &lt;strong&gt;CPU&lt;/strong&gt; memory first&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPU&lt;/strong&gt; then moves this stored model from &lt;strong&gt;CPU&lt;/strong&gt; memory to GPU memory&lt;/li&gt;
&lt;li&gt;Model needs input parameters these are transferred from &lt;strong&gt;CPU&lt;/strong&gt; memory to the GPU memory.&lt;/li&gt;
&lt;li&gt;Execution of the workload (&lt;strong&gt;CPU&lt;/strong&gt; tells the GPU to use the stored model and start execution)&lt;/li&gt;
&lt;li&gt;Post execution of the workload the output resides in the GPU memory.&lt;/li&gt;
&lt;li&gt;This stored output is moved from GPU memory to &lt;strong&gt;CPU&lt;/strong&gt; memory.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;The steps 1. and 2. are a one time steps, but the steps 3 to 6 happen during each inference request.&lt;/p&gt;

&lt;p&gt;In the entire flow above the shots are called by &lt;strong&gt;CPU&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>machinelearning</category>
      <category>performance</category>
    </item>
    <item>
      <title>Beyond nvidia-smi part — 1</title>
      <dc:creator>Yash Panchal</dc:creator>
      <pubDate>Thu, 19 Feb 2026 18:02:43 +0000</pubDate>
      <link>https://dev.to/panchalhimself/beyond-nvidia-smi-part-1-26le</link>
      <guid>https://dev.to/panchalhimself/beyond-nvidia-smi-part-1-26le</guid>
      <description>&lt;h2&gt;
  
  
  Common pitfalls and methods to measure GPU efficiency.
&lt;/h2&gt;

&lt;p&gt;This will be a two part series regarding monitoring a GPU&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GPUs are much simple compared to CPUs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Bunch of simple compute intensive hardware but in a massive proportion relative to memory and other decoder components within the same chipset.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GPU = Compute (Massive portion of the chip) + Memory + Decoders&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Compute is commonly refered to Streaming Multiprocessors (SM) in case of NVIDIA GPUs&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring normal servers vs GPUs:
&lt;/h3&gt;

&lt;p&gt;One can monitor normal linux server using utilities like htop/top or using exporters like node-exporter to get basic usage idea like CPU% RAM no of VCPUs, etc.&lt;/p&gt;

&lt;p&gt;However GPUs are not that staightforward to monitor.&lt;/p&gt;

&lt;p&gt;Common bad habit that one might encounter is to use nvidia-smi utility just like we use htop/top.&lt;/p&gt;

&lt;p&gt;Though it will work for identifying if GPU is doing any work at all, it won't give you any idea regarding efficiency of your GPU.&lt;/p&gt;

&lt;h3&gt;
  
  
  So what are these common mistakes ?
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Relying solely on nvidia-smi
&lt;/h4&gt;

&lt;p&gt;nvidia-smi is a nice utility, however when it comes to monitoring your GPU metrics it is myopic.&lt;/p&gt;

&lt;p&gt;The GPU-Util % that you see using nvidia-smi tells you if any CUDA kernel is active at a point in time, It will not help you in identifying efficiency of your GPU.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furtblva5m8y8a8iaq0od.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furtblva5m8y8a8iaq0od.png" alt="nvidia-smi showing 100%" width="800" height="318"&gt;&lt;/a&gt;&lt;br&gt;
Figure A taken from my FOSDEM 26 talk: Beyond nvidia-smi: Tools for Real GPU Performance Metrics &lt;a href="https://fosdem.org/2026/schedule/event/BBYZLU-gpu-performance-monitoring/" rel="noopener noreferrer"&gt;https://fosdem.org/2026/schedule/event/BBYZLU-gpu-performance-monitoring/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even if you would be doing a simple matrix multiplication on an H100 GPU you will still see GPU-Util to be at 100%.&lt;/p&gt;

&lt;p&gt;This is something that might lead a newbie to conclude that the GPU is being fully used.&lt;/p&gt;

&lt;p&gt;One such example is trying to run a Wan2.2 TI2V 5B parameter video generation model on an 80GB H100 GPU, You might see 23GB VRAM usage but 100% GPU-Util using nvidia-smi will make you question the efficiency of your GPU compute.&lt;/p&gt;

&lt;p&gt;Case of FP16 vs FP32 performance:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmonnmj31ydacpbrsmg2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmonnmj31ydacpbrsmg2j.png" alt="nvidia-smi @ 100% for fp32 vs fp16" width="800" height="455"&gt;&lt;/a&gt;&lt;br&gt;
Figure B &amp;amp; C taken from my FOSDEM 26 talk: Beyond nvidia-smi: Tools for Real GPU Performance Metrics &lt;a href="https://fosdem.org/2026/schedule/event/BBYZLU-gpu-performance-monitoring/In" rel="noopener noreferrer"&gt;https://fosdem.org/2026/schedule/event/BBYZLU-gpu-performance-monitoring/In&lt;/a&gt; the Figure B and C both show 100% GPU-Util for simple FP16 and FP32 matrix multiplication python scripts.&lt;/p&gt;

&lt;p&gt;Both are showing 100% but wait ! What exactly is being used by our GPU ?&lt;/p&gt;




&lt;h4&gt;
  
  
  2. Not identifying workload relevant metrics to monitor
&lt;/h4&gt;

&lt;p&gt;Identifying what workload is supported by your GPU is essential to speeding up your inference workload.&lt;/p&gt;

&lt;p&gt;If you are aware that your GPU supports Tensor Cores and your workload can be modified to utilize these Tensor Cores it can significantly speedup your inference.&lt;/p&gt;

&lt;p&gt;Before we get into the details of the identification of relevant metrics to monitor, we first need to understand what is actually being supported by our GPU.&lt;/p&gt;

&lt;p&gt;Basic performance specs of the GPU are generally available in the whitepaper by the provider.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9m9oul08q6ywavlngh46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9m9oul08q6ywavlngh46.png" alt="H100 GTC22 Whitepaper" width="800" height="480"&gt;&lt;/a&gt;&lt;br&gt;
Table 1 taken from H100 gtc22 whitepaper&lt;/p&gt;

&lt;p&gt;As we can see from Table 1 for our H100,&lt;br&gt;
There are two divisions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tensor Cores Performance (Explicitly mentioned as Tensor Core)&lt;/li&gt;
&lt;li&gt;CUDA Cores Performance&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tensor Cores are significantly faster ~8–10x than CUDA Cores.&lt;/p&gt;

&lt;p&gt;So ideally whenever possible we should be using Tensor Cores that will significantly improve your inference performance.&lt;/p&gt;

&lt;p&gt;In our case we ran FP16 workload that should use Tensor Cores and no CUDA Cores while FP32 should use the CUDA Cores and no Tensor cores.&lt;/p&gt;

&lt;p&gt;While nvidia-smi is showing us 100% in both cases we would like to know if our workload is using the Tensor cores or not.&lt;br&gt;
nvidia-smi is not able to show us that info, So what option do we have now ?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DCGM is our saviour !&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;DCGM stands for Data Center GPU Manager it is a suite of utility provided by nvidia for monitoring GPU.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsl9c667iqdsl51x2bsq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsl9c667iqdsl51x2bsq.png" alt="DCGM GPU monitoring" width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;
Figure B &amp;amp; C monitored using DCGM&lt;/p&gt;

&lt;p&gt;We can now see that Tensor Cores are not used in FP32 workload while FP16 is showing Tensor Core usage.&lt;/p&gt;

&lt;p&gt;This is what can help us in understanding depth of our workload.&lt;/p&gt;

&lt;p&gt;Using nvidia-smi we were not able to monitor if Tensor Cores were used or not.&lt;br&gt;
I recently gave a talk at FOSDEM 2026 regarding this: &lt;a href="https://fosdem.org/2026/schedule/event/BBYZLU-gpu-performance-monitoring/" rel="noopener noreferrer"&gt;https://fosdem.org/2026/schedule/event/BBYZLU-gpu-performance-monitoring/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gpu</category>
      <category>ai</category>
      <category>performance</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>Kubernetes components and their usage</title>
      <dc:creator>Yash Panchal</dc:creator>
      <pubDate>Mon, 19 Jun 2023 05:58:54 +0000</pubDate>
      <link>https://dev.to/panchalhimself/kubernetes-components-and-their-usage-1kf8</link>
      <guid>https://dev.to/panchalhimself/kubernetes-components-and-their-usage-1kf8</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Basic Kubernetes components and their use utility.&lt;/strong&gt;
&lt;/h2&gt;




&lt;h2&gt;
  
  
  &lt;em&gt;K8s Components&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;k8s-control-plane:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responsible for managing the cluster.&lt;/li&gt;
&lt;li&gt;Can be on a single machine or can span across multiple servers (Usually across dedicated controller machines).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Kubernetes Node (Control Plane Node)
&lt;/h2&gt;

&lt;p&gt;Control plane node is the backbone of the entire kubernetes cluster.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Following are the 5 main control plane components:-&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;kube-api-server:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serves the K8s API&lt;/li&gt;
&lt;li&gt;Primary interface to interact with k8s cluster and is a central component.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;etcd:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HA backend data store for the k8s cluster.&lt;/li&gt;
&lt;li&gt;data stored is related to the state of the cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;kube-scheduler&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;handles scheduling: selecting the node to run containers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;kube-controller-manager&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single process&lt;/li&gt;
&lt;li&gt;Runs collection of controller utilities.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;controllers:&lt;/strong&gt; execute various automation related tasks inside the cluster.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;cloud-controller-manager&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;provides interfaces between the cluster and cloud providers.&lt;/li&gt;
&lt;li&gt;useful only when you need to interact with cloud providers from the cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These components can be on same server or can be spread across multiple servers.&lt;/p&gt;

&lt;p&gt;In case of HA requirement these components can have more than single instance running simultaneously across multiple servers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Kubernetes Node (Worker Nodes)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;containers managed by cluster run here.&lt;/li&gt;
&lt;li&gt;can have any no of nodes.&lt;/li&gt;
&lt;li&gt;has node components on the server that communicate with the control plane via &lt;em&gt;kube-api-server&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Node components:-&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;kubelet&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;k8s agent&lt;/li&gt;
&lt;li&gt;ensures that containers are run on its node.&lt;/li&gt;
&lt;li&gt;communicates with control plane and follows what it commands.&lt;/li&gt;
&lt;li&gt;communicates with control plane regarding node status and various info of the running containers.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;container-runtime&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;container software for actual container process.&lt;/li&gt;
&lt;li&gt;ex: docker and contianerd&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;kube-proxy&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network proxy&lt;/li&gt;
&lt;li&gt;runs on each node&lt;/li&gt;
&lt;li&gt;handles networking between containers and servers in the cluster&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>containers</category>
      <category>kubectl</category>
    </item>
    <item>
      <title>local k8s setup using vagrant.</title>
      <dc:creator>Yash Panchal</dc:creator>
      <pubDate>Mon, 12 Jun 2023 16:52:47 +0000</pubDate>
      <link>https://dev.to/panchalhimself/local-k8s-setup-using-vagrant-2f1p</link>
      <guid>https://dev.to/panchalhimself/local-k8s-setup-using-vagrant-2f1p</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Steps to initialize k8s cluster&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialize the k8s cluster on node1&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       kubeadm init --apiserver-advertise-address=192.168.1.101 --pod-network-cidr=192.168.1.0/24 --v=5


       IPADDR="192.168.1.101"
       NODENAME=$(hostname -s)
       POD_CIDR="192.168.1.0/16"

       sudo kubeadm init --apiserver-advertise-address=$IPADDR  --apiserver-cert-extra-sans=$IPADDR  --pod-network-cidr=$POD_CIDR --node-name $NODENAME --ignore-preflight-errors Swap

    To start using your cluster, you need to run the following as a regular user:

       mkdir -p $HOME/.kube
       sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
       sudo chown $(id -u):$(id -g) $HOME/.kube/config

    Alternatively, if you are the root user, you can run:

       export KUBECONFIG=/etc/kubernetes/admin.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Setup Calico/WEAVE Net networking interface&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use any one of the following CNI setup, I used Weavenet&lt;/p&gt;

&lt;p&gt;Calico&lt;br&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/calico.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Weavenet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Join the other nodes with the node1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Paste the output from the node 1 to join the node 1 &lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Vagrantfile and Scripts for setup&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;




&lt;p&gt;Ensure that the Vagrantfile and setup.sh are in the same folder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vagrantfile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    Vagrant.configure("2") do |config|
      config.vm.define "db1" do |db1|
        db1.vm.box = "ubuntu/focal64"
        db1.vm.hostname = 'db1'
        db1.vm.box_url = "ubuntu/focal64"
        db1.vm.provision "shell", path: "setup-k8s.sh"
        db1.vm.provision "shell", path: "master.sh"
        db1.vm.network "public_network", ip: '192.168.1.101', bridge: 'enp11s0'
        db1.vm.provider :virtualbox do |v|
          v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
          v.customize ["modifyvm", :id, "--memory", 2000]
          v.customize ["modifyvm", :id, "--name", "db1"]
        end
      end

      config.vm.define "db2" do |db2|
        db2.vm.box = "ubuntu/focal64"
        db2.vm.hostname = 'db2'
        db2.vm.box_url = "ubuntu/focal64"
        db2.vm.provision "shell", path: "setup-k8s.sh"
        db2.vm.provision "shell", path: "worker.sh"
        db2.vm.network "public_network", ip: '192.168.1.102', bridge: 'enp11s0'
        db2.vm.provider :virtualbox do |v|
          v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
          v.customize ["modifyvm", :id, "--memory", 2000]
          v.customize ["modifyvm", :id, "--name", "db2"]

        end
      end

      config.vm.define "db3" do |db3|
        db3.vm.box = "ubuntu/focal64"
        db3.vm.hostname = 'db3'
        db3.vm.box_url = "ubuntu/focal64"
        db3.vm.provision "shell", path: "setup-k8s.sh"
        db3.vm.provision "shell", path: "worker.sh"
        db3.vm.network "public_network", ip: '192.168.1.103', bridge: 'enp11s0'
        db3.vm.provider :virtualbox do |v|
          v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
          v.customize ["modifyvm", :id, "--memory", 2000]
          v.customize ["modifyvm", :id, "--name", "db3"]

        end
      end
    end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;setup-k8s.sh&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    #!/bin/bash

    set +xe

    yes y | ssh-keygen -q -t rsa -N '' &amp;gt;/dev/null

    echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC4ns0dEv0sJV+rMDftaaTDwsj2y0hf0/vOsPepy+YJzFW4B8dgTa75bN12uexH78Xcth06MkOCiB3iOuIkoxEcQx8JMUiUCiIpNSWTTTjxu4zhx6k68Fw6eczbbBoXenNO6i7lCB1rXsd2NO4JgOEMobi6IzdkOXINV3LX5Pu3zrbxOKSeTIKnVEt3kK0/yrvCEKAg8lyGIuZ6Xh6zOLkbhQGpWDNexQa8kx4K/2QN98dNWAFktihcy1UOZJ4ha17MEsDRxyNb5lixWurv23/BpjbaiywpQbmZ+hAfS3wN2hxMSuP4pwkoCiRBvQjT7fD5jeMJ3YiYVv56VBbf0TAAcLentCowfzEdwPYyExma0J0PXmregNPlaw38KcmlSmUfXn77XRIgJ70aAcq3MscsqlKpIN7AYYbTBuDj/7ENpI8dsJarNWmeHMlfoi0mwI9izPnJim3XODdGWAZlV0CXvG2NpmzASxuKYrf8occNtyjjrD/Fn5DBHuD6PbJn8KE= yash@yash-ThinkPad-P15-Gen-2i" &amp;gt;&amp;gt; ~/.ssh/authorized_keys

    cat &amp;lt;&amp;lt;EOF &amp;gt;&amp;gt; /etc/hosts
    192.168.1.101 db1
    192.168.1.102 db2
    192.168.1.103 db3
    EOF
    sudo swapoff -a
    sudo apt-get install -y apt-transport-https 
    cat &amp;lt;&amp;lt;EOF | sudo tee /etc/modules-load.d/k8s.conf
    overlay
    br_netfilter
    EOF
    sudo modprobe overlay
    sudo modprobe br_netfilter
    # sysctl params required by setup, params persist across reboots
    cat &amp;lt;&amp;lt;EOF | sudo tee /etc/sysctl.d/k8s.conf
    net.bridge.bridge-nf-call-iptables  = 1
    net.bridge.bridge-nf-call-ip6tables = 1
    net.ipv4.ip_forward                 = 1
    EOF
    # Apply sysctl params without reboot
    sudo sysctl --system
    sudo apt-get update

    for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done

    sudo apt-get update
    sudo apt-get install ca-certificates curl gnupg -y
    sudo install -m 0755 -d /etc/apt/keyrings
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    sudo chmod a+r /etc/apt/keyrings/docker.gpg
    echo \
    "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
    "$(. /etc/os-release &amp;amp;&amp;amp; echo "$VERSION_CODENAME")" stable" | \
    sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null

    sudo apt-get update

    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y



    curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
    cat &amp;lt;&amp;lt; EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
    deb https://apt.kubernetes.io/ kubernetes-xenial main
    EOF
    sudo apt-get update
    sudo apt-get install -y kubelet=1.26.0-00 kubeadm=1.26.0-00 kubectl=1.26.0-00
    sudo apt-mark hold kubelet kubeadm kubectl

    sudo rm /etc/containerd/config.toml
    #https://stackoverflow.com/questions/72504257/i-encountered-when-executing-kubeadm-init-error-issue
    sudo systemctl restart containerd

    apt-get install net-tools -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;master.sh&lt;/strong&gt; (Setup to provision and initialize control node k8s)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    #!/bin/bash

    kubeadm init --apiserver-advertise-address=192.168.1.101 --pod-network-cidr=192.168.1.0/24 --v=5


    IPADDR="192.168.1.101"
    NODENAME=$(hostname -s)
    POD_CIDR="192.168.1.0/16"

    sudo kubeadm init --apiserver-advertise-address=$IPADDR  --apiserver-cert-extra-sans=$IPADDR  --pod-network-cidr=$POD_CIDR --node-name $NODENAME --ignore-preflight-errors Swap


    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config


    echo "Setting up Weaveworks Network"

    kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml

    kubectl get nodes
    kubectl get pods --all-namespaces
    kubectl cluster-info

    kubeadm token create --print-join-command &amp;gt; index.html

    docker run -dit -p 80:80 -v ./index.html:/usr/share/nginx/html/index.html nginx

    cat ~/.kube/config &amp;gt; index-config.html

    docker run -dit -p 8080:80 -v ./index-config.html:/usr/share/nginx/html/index.html nginx



**worker.sh** (Setup to provision the worker nodes)

    #!/bin/bash

    JOIN_COMMAND=$(curl db1:80)

    echo "Following is the Join Command:- $JOIN_COMMAND"

    $JOIN_COMMAND

    curl db1:8080 &amp;gt; /etc/kubernetes/kubelet-admin.conf

    echo "KUBECONFIG=/etc/kubernetes/kubelet-admin.conf" &amp;gt;&amp;gt; /etc/environment

    source /etc/environment

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Start the vms and provision them using setup.sh using the following command:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    vagrant up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ssh into the vms using the following command:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    vagrant ssh db1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You might need to replace &lt;strong&gt;wlp9s0&lt;/strong&gt; with your own network interface along with the cidr ranges (here: 192.168.56.0/24).&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Executing kubectl commands from worker nodes&lt;/em&gt;&lt;/strong&gt; 
&lt;/h2&gt;

&lt;p&gt;By default your kubeconfig file of control node is not present in the worker node.&lt;br&gt;
This means that you can only administer cluster from the control node.&lt;/p&gt;

&lt;p&gt;In order to admin the cluster from the worker nodes as well, you will need to do the following configurations:-&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Ensure that the kubectl config file from the control plane node is copied to the worker nodes.&lt;/p&gt;

&lt;p&gt;Usually preset at ~/.kube/config on controller node.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the control node kube config file data and paste it in a config file at the worker node. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set the path using export KUBECONFIG=PATH/TO/YOUR/CONFIG (Can be located anywhere)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In my case I override /etc/kubernetes/kubelet.conf file with the kubeconfig of the control node.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Exposing the service (sample nginx application)&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First download the sample manifest of nginx application created by nonanom.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   curl -lo nginx.yaml "https://gist.githubusercontent.com/nonanom/498b913a69cede7037d55e28bb00344e/raw"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;nginx.yaml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    kind: Service
    apiVersion: v1
    metadata:
    name: nginx
    labels:
       app: nginx
    spec:
    selector:
       app: nginx
    ports:
    - port: 80
       protocol: TCP
       targetPort: 80
    type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: nginx
    labels:
       app: nginx
    spec:
    replicas: 1
    selector:
       matchLabels:
          app: nginx
    template:
       metadata:
          labels:
          app: nginx
       spec:
          containers:
          - name: nginx
          image: nginx:latest
          imagePullPolicy: Always
          ports:
          - containerPort: 80
             protocol: TCP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Deploy the manifest in the cluster&lt;/p&gt;

&lt;p&gt;kubectl apply --filename nginx.yaml&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Expose the service (Portforward the service)&lt;/p&gt;

&lt;p&gt;kubectl port-forward service/nginx --address 0.0.0.0 8080:80&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; the node from where you execute the command for exposing the service will be the node from which you can access the application service.&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://nonanom.medium.com/run-nginx-on-kubernetes-ee6ea937bc99" rel="noopener noreferrer"&gt;https://nonanom.medium.com/run-nginx-on-kubernetes-ee6ea937bc99&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Github repo for reference&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/panchal-yash/vagrant-k8s-setup" rel="noopener noreferrer"&gt;https://github.com/panchal-yash/vagrant-k8s-setup&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
