Free AI web copilot to create summaries, insights and extended knowledge, download it at here
9845
Abstract
<div id="017c"><pre><span class="hljs-built_in">echo</span> <span class="hljs-string">'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /'</span> | \
sudo <span class="hljs-built_in">tee</span> /etc/apt/sources.list.d/kubernetes.list</pre></div><p id="962b"><b>4. Update the package manager and install Kubernetes tools / CP-W</b></p><div id="1e40"><pre>sudo apt update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl</pre></div><p id="c402">At this point, we have installed all the necessary Kubernetes tools. Kubernetes services such as API server and kube-scheduler are running as containers. Also, pods we deploy run as containers. Therefore, we need a platform to manage these containers. Although Docker is the most popular container runtime, Kubernetes has recently switched to containerd as the default runtime. While Docker or CRI-O can still be configured as the runtime, this tutorial will focus on the containerd runtime</p><h2 id="abfe">Install containerd runtime</h2><p id="4f5d">If you are starting over with this tutorial, verify whether the overlay and br_netfilter kernel modules are loaded. If not, load them as we discussed earlier</p><div id="0b93"><pre>lsmod | grep <span class="hljs-string">"overlay\|br_netfilter"</span></pre></div><p id="8e80"><b>1. Add containerd repository key and add the repository to source list / CP-W</b></p><div id="b96d"><pre>curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg</pre></div><div id="2434"><pre>sudo <span class="hljs-built_in">chmod</span> a+r /etc/apt/keyrings/docker.gpg</pre></div><div id="a513"><pre><span class="hljs-built_in">echo</span> \
<span class="hljs-string">"deb [arch="</span>$(dpkg --print-architecture)<span class="hljs-string">" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"</span>$(. /etc/os-release && <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$VERSION_CODENAME</span>"</span>)<span class="hljs-string">" stable"</span></pre></div><div id="b18d"><pre>sudo <span class="hljs-built_in">tee</span> /etc/apt/sources.list.d/docker.list > /dev/null</pre></div><p id="d5e1"><b>2. Install containerd / CP-W</b></p><div id="78b8"><pre>sudo apt update
sudo apt install -y containerd.io</pre></div><p id="9a21"><b>3. Configure containerd / CP-W</b></p><p id="911c">Create a directory to store containerd config file in <i>/etc/</i></p><div id="192f"><pre>sudo <span class="hljs-built_in">mkdir</span> -p /etc/containerd</pre></div><p id="2667">Generate the default config toml file</p><div id="8ce2"><pre>sudo containerd config default|sudo <span class="hljs-built_in">tee</span> /etc/containerd/config.toml</pre></div><p id="bf32">Open the generated file in any text editor and verify whether the following settings are present. If not, you should set them as shown below</p><div id="145d"><pre><span class="hljs-section">[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]</span>
<span class="hljs-attr">runtime_type</span> = <span class="hljs-string">"io.containerd.runc.v2"</span> <span class="hljs-comment"># <- note this, this line might have been missed</span>
<span class="hljs-section">[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]</span>
<span class="hljs-attr">SystemdCgroup</span> = <span class="hljs-literal">true</span> <span class="hljs-comment"># <- note this, this could be set as false in the default configuration, please make it true</span></pre></div><figure id="9d05"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*7HKoBp4oOiDO_uY_oGeTBQ.png"><figcaption>/etc/containerd/config.toml</figcaption></figure><p id="b5a7">Additionally, at the beginning of this config file, you should see the ‘disabled_plugins’ set as an empty list ([ ]). Please verify that it is indeed empty</p><figure id="a2f6"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*IvO8AMQISh4HyTESNPziXA.png"><figcaption>/etc/containerd/config.toml beginning</figcaption></figure><p id="8eaa">Now save the config file, close it and restart the containerd service</p><div id="ac5e"><pre>sudo systemctl restart containerd
sudo systemctl <span class="hljs-built_in">enable</span> containerd
systemctl status containerd</pre></div><figure id="0cba"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*D7OzjnDOmmrxvv-SvRWCKg.png"><figcaption>containerd running status</figcaption></figure><p id="39a1">At this point, our runtime installation and configuration setup is completed. However, it’s beneficial to have <i>crictl </i>for debugging purposes. You can use this tool to inspect running containerd containers, their status, and images. So, let’s configure crictl as well</p><p id="cf4c"><b>4. Setup <i>crictl </i>for inspecting containers / CP-W</b></p><p id="b44f">First run the below command and check the output</p><div id="9261"><pre> sudo crictl ps</pre></div><p id="26cf">If the <i>crictl </i>is not present, install it using the below command</p><div id="688f"><pre>sudo apt install cri-tools</pre></div><p id="dfad">Once the installation is completed, re-run the <i>sudo crictl ps </i>command. You may encounter output with errors and warnings. To address these issues, we need to add configurations for crictl. Additionally, you can customize the debug output using this config file</p><figure id="2371"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*TbSquSrZs4O_xrCX-Fnf5w.png"><figcaption>crictl output with errors and warnings</figcaption></figure><p id="ed53">Create <i>crictl.yaml</i> file in <i>/etc/</i></p><div id="b57f"><pre>sudo vim /etc/crictl.yaml</pre></div><p id="5fa8">Paste below content, save and exit</p><div id="e878"><pre><span class="hljs-attr">runtime-endpoint:</span> <span class="hljs-string">unix:///run/containerd/containerd.sock</span>
<span class="hljs-attr">image-endpoint:</span> <span class="hljs-string">unix:///run/containerd/containerd.sock</span>
<span class="hljs-attr">timeout:</span> <span class="hljs-number">2</span>
<span class="hljs-attr">debug:</span> <span class="hljs-literal">true</span> <span class="hljs-comment"># <- if you don't want to see debug info you can set this to false</span>
<span class="hljs-attr">pull-image-on-create:</span> <span class="hljs-literal">false</span></pre></div><p id="10d5">Run the <i>sudo crictl ps </i>again<i>,</i>and you shouldn’t encounter any errors or warnings</p><figure id="f553"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*2iZeLqYd75K7Bt9v5SE_hg.png"><figcaption>crictl ps output with debug info enabled</figcaption></figure><p id="84e2">If you prefer not to see debug information, set the <i>debug </i>parameter to <i>false </i>in the <i>crictl.yaml</i> file</p><p id="b8c4">At this point, you won’t find any running containers. You can verify container images using the <i>sudo crictl images</i> command, and there won’t be any images present</p><p id="8cdd"><b>5. Enable <i>kubelet</i> service / CW-P</b></p><div id="9213"><pre>sudo systemctl <span class="hljs-built_in">enable</span> kubelet</pre></div><p id="3236">However, attempting to run the <i>kubelet </i>service will not be successful as the <i>kubectl configs</i> are missing. We won’t need to create these manually; they will be added to the system using <i>kubeadm </i>commands. Therefore, refrain from trying to start the <i>kubelet </i>service at this stage. Our current focus is on enabling the service only</p><p id="e746">Now it is time to initiate our control plane node</p><h1 id="bae5">Initializing Control-Plane Node</h1><p id="4583"><b>1. Run the below command and check for existing images / CP</b></p><div id="4f6d"><pre>sudo crictl images</pre></div><p id="fba3">You won’t find any images at this point as it’s a fresh installation</p><p id="21f5"><b>2. Pull necessary Kubernets images / CP</b></p><p id="c12f">We don’t have to perform this as an isolated process, but for the sake of verifying each small step, we’ll proceed with it separately</p><p id="d5eb">Run below command to pull images</p><div id="5855"><pre>sudo kubeadm config images pull --cri-socket unix:///var/run/containerd/containerd.sock</pre></div><figure id="8284"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*6TaZq5om-6_jEFC_E8vznA.png"><figcaption>Kubernets control-plane images</figcaption></figure><p id="6b1a">Now, if you execute the following command, you’ll see a list of containerd images</p><div id="e371"><pre>sudo crictl images</pre></div><figure id="4dfe"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*G73Enxk6tGtjfVBKUBykAQ.png"><figcaption></figcaption></figure><p id="b5e3">If you’re encountering extensive debug information, you can disable it as previously discussed in the crictl configuration section</p><p id="a638"><b>3. Initialize the control-plane / CP</b></p><p id="7e84"><b>This command will take some time to complete. Do not clear the output as you’ll need to refer to instructions from the command output</b></p><div id="714e"><pre>sudo kubeadm init \
--pod-network-cidr=10.244.0.0/16 \
--cri-socket unix:///var/run/containerd/containerd.sock \
--v=5</pre></div><p id="6906">If you have multiple container runtimes like Docker and containerd installed, you’ll need to specify the correct CRI socket. You can find these values in the official documentation. However, in our case, specifying the containerd socket should suffice</p><div id="0ecc" class="link-block">
<a href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-runtime">
<div>
<div>
<h2>In
# Options
stalling kubeadm</h2>
<div><h3>This page shows how to install the kubeadm toolbox. For information on how to create a cluster with kubeadm once you…</h3></div>
<div><p>kubernetes.io</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*2gI423xnb-J9AWUw)"></div>
</div>
</div>
</a>
</div><p id="3a5d">When selecting the pod-network-cidr range, choose a range that does not conflict with your network’s IP range</p><p id="ed94"><i>v=5</i> or higher would print verbose messages. This is useful when there are issues to fix</p><p id="a28d">At the end of the command output, you will see something like the following</p><figure id="3441"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*d_rhOFztJg9mSV4yThHyNA.png"><figcaption>kubeadm init output</figcaption></figure><p id="cf2e"><b>DO NOT skip the instruction in the beginning (1)</b>. Otherwise your <i>kubectl </i>won’t be connected with the API server. Even if you are running the cluster using the root user, you still need to follow this step. <i>kubectl </i>fetch the config from this location by default</p><p id="3915">error :</p><p id="ab4f"><i>couldn’t get current server API group list: Get “<a href="http://localhost:8080/api?timeout=32s">http://localhost:8080/api?timeout=32s</a>": dial tcp 127.0.0.1:8080: connect: connection refused</i></p><p id="b987"><i>The connection to the server localhost:8080 was refused — did you specify the right host or port?</i></p><figure id="3472"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*nmQDIdbnL8Ukxn2y2dKvmQ.png"><figcaption>kubectl won’t connect to API server even with root user if you haven’t done config copy as instructed</figcaption></figure><p id="2409">You will need the kubeadm join command (2) to connect the worker node with the control plane. However, you can always generate this. We’ll generate a new join command later when connecting our worker node with the control plane node</p><p id="5809">Run below command to copy config. You should perform this as a normal user if you plan to run <i>kubectl </i>with a regular user account. If you intend to run kubectl as root, execute it under the root account</p><div id="be2a"><pre> <span class="hljs-built_in">mkdir</span> -p <span class="hljs-variable">$HOME</span>/.kube
sudo <span class="hljs-built_in">cp</span> -i /etc/kubernetes/admin.conf <span class="hljs-variable">$HOME</span>/.kube/config
sudo <span class="hljs-built_in">chown</span> $(<span class="hljs-built_in">id</span> -u):$(<span class="hljs-built_in">id</span> -g) <span class="hljs-variable">$HOME</span>/.kube/config</pre></div><p id="bca8">Now, if you run the command <i>kubectl get nodes</i>, it should work</p><p id="74d4">Run below <i>kubectl </i>command to get the cluster nodes</p><div id="1f4e"><pre>kubectl <span class="hljs-keyword">get</span> nodes</pre></div><figure id="504d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*g9_alLqV7vdkQYecRLMUGQ.png"><figcaption>kubectl get nodes output</figcaption></figure><p id="5f61">Note that you can see the control-plane node here, but the status is not ready. We need to apply the CNI plugin to make this control-plane ready. Also, if you check the running containers using <i>crictl ps</i>, you should see something similar to the following</p><figure id="10f5"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*-1lPbsnrzK9gsxr3_O25XQ.png"><figcaption>crictl ps output for freshly initialized kubernets control-plane node without CNI plugin</figcaption></figure><p id="bf09">We are going to use <b>Weave Net</b> in this tutorial as our CNI plugin</p><p id="50d0"><b>4. Add network add-on / CP</b></p><p id="4ede">You can get the latest add-on apply command from here</p><div id="f104" class="link-block">
<a href="https://www.weave.works/docs/net/latest/kubernetes/kube-addon/#-installation">
<div>
<div>
<h2>Integrating Kubernetes via the Addon</h2>
<div><h3>The following topics are discussed: Before installing Weave Net, you should make sure the following ports are not…</h3></div>
<div><p>www.weave.works</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/)"></div>
</div>
</div>
</a>
</div><p id="c282">or you can use below command</p><div id="9e2b"><pre>kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml</pre></div><p id="9331">Once you run the above command and still see the control-plane node in Not Ready status check the <i>sudo</i> <i>crictl ps </i>output. If it shown as below,</p><figure id="c7ed"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*m1am9PLRazWwXwSRFYE5Tw.png"><figcaption>weave add-on no attempts</figcaption></figure><p id="4eb6">Just restart your control-plane server and check. <b>Before restarting your control-plane server, exercise caution</b>. If your node has a dynamic IP interface and its IP changes upon restarting, the control-plane may not function correctly. Kubernetes utilizes IP as a component to sign certificates for network security</p><p id="e3ad">You would now see there is one or more attempts and the control plane is ready</p><div id="fc25"><pre>sudo crictl ps</pre></div><figure id="6278"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*fpidOPp07ustv571k11rRg.png"><figcaption>weave add-on has added successfully</figcaption></figure><div id="9745"><pre>kubectl get nodes</pre></div><figure id="7a74"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*HuaU04lIBQuQ2kIWvewNSw.png"><figcaption>Kubernets control-plane node is ready</figcaption></figure><p id="7ad5">At this point, your control plane node is ready. Let’s proceed to configure the worker node</p><h1 id="16c4">Join the Worker Node to Kubernets Control-Plane</h1><p id="51e0">In this section, we’ll switch between the control plane and worker node to execute various commands. <b>Pay attention to the short codes for each</b></p><ol><li><b>Switch to the control-plane node and generate the join command / CP</b></li></ol><p id="069a">As you already know, during the initialization of the control-plane, there was a join command provided. You can use it instead of generating a new one. However, it’s advisable to generate a new one, considering that the token has a short lifespan</p><p id="a973">Use the below command in the control plane node to generate the join command</p><div id="bfb9"><pre>kubeadm token create --print-join-command</pre></div><p id="0f16">It would display something similar to the following in the console</p><p id="45d9"><i>kubeadm join 192.168.8.120:6443 — token dg67p7.wvt7n5zxx9pxbmaz — discovery-token-ca-cert-hash sha256:36f9eb64ef8a6d45254b8994108b0e3a56e856bcb3b07d46cd83554db4114490</i></p><p id="f869">Copy the entire command as we’ll need this to join the worker node with the control-plane.</p><p id="f78a"><b>2. Switch to the worker node and follow the below instructions / W</b></p><p id="ee75">Verify whether you’ve completed all the steps marked as <b>CP-W</b> or <b>W </b>in the previous sections</p><p id="a6ac">Execute the join command you copied from the control-plane console. You’ll receive something similar to the following</p><figure id="0357"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*IK0cU5NQu4-AgYam6KCvZw.png"><figcaption>Kubernets worker node join command output</figcaption></figure><p id="8bab"><b>3. Switch back to the control-plane node and run the below command to verify / CP</b></p><div id="8db5"><pre>kubectl get nodes -o wide</pre></div><figure id="1221"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*FkXlBH-dmvAaxdc53rWwUA.png"><figcaption>kubectl output for get nodes -o wide command</figcaption></figure><p id="8f3f">Congratulations! At this stage, you have a functional minimum Kubernetes cluster</p><h1 id="22ee">What is Next?</h1><p id="1a87">You might want to explore this simple official documentation section on deploying a simple Nginx pod to your cluster</p><div id="4d13" class="link-block">
<a href="https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/">
<div>
<div>
<h2>Run a Stateless Application Using a Deployment</h2>
<div><h3>This page shows how to run an application using a Kubernetes Deployment object. Objectives Create an nginx deployment…</h3></div>
<div><p>kubernetes.io</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*af-sBd8CqTyP8r6J)"></div>
</div>
</div>
</a>
</div><h1 id="1692">Needing some motivation to continue? Consider watching the following Honeypot documentary on Kubernetes</h1>
<figure id="81bd">
<div>
<div>
<img class="ratio" src="http://placehold.it/16x9">
<iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FBE77h7dmoQU&display_name=YouTube&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DBE77h7dmoQU&image=http%3A%2F%2Fi.ytimg.com%2Fvi%2FBE77h7dmoQU%2Fhqdefault.jpg&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=youtube" allowfullscreen="" frameborder="0" height="480" width="854">
</div>
</div>
</figure></iframe></div></div></figure></article></body>