{"id":21430,"date":"2023-03-20T08:00:00","date_gmt":"2023-03-20T07:00:00","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/?p=21430"},"modified":"2023-03-31T14:23:30","modified_gmt":"2023-03-31T12:23:30","slug":"how-to-build-a-kubernetes-cluster-with-kubeadm","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/","title":{"rendered":"Easily build a kubernetes cluster with kubeadm"},"content":{"rendered":"\n<p>In the upcoming blog posts, I will cover monitoring with Prometheus in a Kubernetes infrastructure. As I started blogging, I decided it would be useful to delve into the design of the k8s infrastructure. <br>This will allow you to approach these blogs better if you wish to reproduce them. <\/p>\n\n\n\n<p>Therefore, I will start with the basics and explain step by step how to build a Kubernetes cluster with kubeadm easily.<br>I suggest we start with a relatively simple, if not basic, installation with a cluster including a Master (Control Plane) and two worker nodes. To do this, I will use a Debian distribution, with a rather minimalist sizing with 2 CPUs and 4GB of RAM each.<br><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Install Packages<\/h3>\n\n\n\n<p>1. Login to your master server (Control Plane)<\/p>\n\n\n\n<p>2. Create a configuration file <em>containerd<\/em>, which will contain the necessary packages for the container runtime :<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ncat &lt;&lt;EOF | sudo tee \/etc\/modules-load.d\/containerd.conf\noverlay\nbr_netfilter\nEOF\n<\/pre><\/div>\n\n\n<p>3. Load the overlay and br_netfilter kernel modules:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo modprobe overlay\nsudo modprobe br_netfilter\n<\/pre><\/div>\n\n\n<p>4. Set system configurations for Kubernetes networking:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ncat &lt;&lt;EOF | sudo tee \/etc\/sysctl.d\/k8s.conf \nnet.bridge.bridge-nf-call-iptables = 1 \nnet.ipv4.ip_forward = 1 \nnet.bridge.bridge-nf-call-ip6tables = 1 \nEOF\n<\/pre><\/div>\n\n\n<p>5. Load sysctl settings from all available configuration files:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo sysctl --system\n<\/pre><\/div>\n\n\n<p>6. Update the package list and install the &#8220;containerd&#8221; package:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo apt-get update &amp;&amp; sudo apt-get install -y containerd\n<\/pre><\/div>\n\n\n<p>7. Create the \/etc\/containerd directory if it doesn&#8217;t exist (we will use it to store the default configuration file for containerd ):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo mkdir -p \/etc\/containerd\n<\/pre><\/div>\n\n\n<p>8. Generate a default config file for containerd and save it to the newly created default file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo containerd config default | sudo tee \/etc\/containerd\/config.toml\n<\/pre><\/div>\n\n\n<p>9. Restart containerd to ensure new configuration file usage:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n sudo systemctl restart containerd\n<\/pre><\/div>\n\n\n<p>10. Verify that containerd is running:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo systemctl status containerd\n<\/pre><\/div>\n\n\n<pre class=\"wp-block-code\"><code>dbinla@dbisbx-master01:~$  sudo systemctl status containerd\n\u25cf containerd.service - containerd container runtime\n     Loaded: loaded (\/lib\/systemd\/system\/containerd.service; enabled; vendor preset: enabled)\n     Active: active (running) since Mon 2023-01-09 10:28:12 UTC; 22s ago\n       Docs: https:\/\/containerd.io\n    Process: 2013 ExecStartPre=\/sbin\/modprobe overlay (code=exited, status=0\/SUCCESS)\n   Main PID: 2014 (containerd)\n      Tasks: 8\n     Memory: 10.8M\n        CPU: 140ms\n     CGroup: \/system.slice\/containerd.service\n             \u2514\u25002014 \/usr\/bin\/containerd\n\nJan 09 10:28:12 dbisbx-master01 containerd&#091;2014]: time=\"2023-01-09T10:28:12.551429182Z\" level=info msg=serving... address=\/run\/containerd\/containerd.sock.ttrpc\nJan 09 10:28:12 dbisbx-master01 containerd&#091;2014]: time=\"2023-01-09T10:28:12.551607403Z\" level=info msg=serving... address=\/run\/containerd\/containerd.sock\nJan 09 10:28:12 dbisbx-master01 containerd&#091;2014]: time=\"2023-01-09T10:28:12.551954435Z\" level=info msg=\"containerd successfully booted in 0.051594s\"\nJan 09 10:28:12 dbisbx-master01 systemd&#091;1]: Started containerd container runtime.\nJan 09 10:28:12 dbisbx-master01 containerd&#091;2014]: time=\"2023-01-09T10:28:12.557282442Z\" level=info msg=\"Start subscribing containerd event\"\nJan 09 10:28:12 dbisbx-master01 containerd&#091;2014]: time=\"2023-01-09T10:28:12.557379562Z\" level=info msg=\"Start recovering state\"\nJan 09 10:28:12 dbisbx-master01 containerd&#091;2014]: time=\"2023-01-09T10:28:12.557588184Z\" level=info msg=\"Start event monitor\"\nJan 09 10:28:12 dbisbx-master01 containerd&#091;2014]: time=\"2023-01-09T10:28:12.557619734Z\" level=info msg=\"Start snapshots syncer\"\nJan 09 10:28:12 dbisbx-master01 containerd&#091;2014]: time=\"2023-01-09T10:28:12.557634754Z\" level=info msg=\"Start cni network conf syncer\"\nJan 09 10:28:12 dbisbx-master01 containerd&#091;2014]: time=\"2023-01-09T10:28:12.557649394Z\" level=info msg=\"Start streaming server\"\ndbinla@dbisbx-master01:~$<\/code><\/pre>\n\n\n\n<p>11. Disable swap:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo swapoff -a\n<\/pre><\/div>\n\n\n<p>12. Update and install dependency packages:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo apt-get update &amp;&amp; sudo apt-get install -y apt-transport-https curl\n<\/pre><\/div>\n\n\n<p>13. Download and add the Google Cloud public signing key:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ncurl -s https:\/\/packages.cloud.google.com\/apt\/doc\/apt-key.gpg | sudo apt-key add -\n<\/pre><\/div>\n\n\n<p><em>Depending on the version of your distribution, you might have a warning about the deprecated command. Therefore you can type instead of:<\/em><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo curl -fsSLo \/etc\/apt\/keyrings\/kubernetes-archive-keyring.gpg https:\/\/packages.cloud.google.com\/apt\/doc\/apt-key.gpg\n<\/pre><\/div>\n\n\n<p>14. Create a new file called &#8220;\/etc\/apt\/sources.list.d\/kubernetes.list&#8221; and add the Kubernetes apt repository to it:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\necho &quot;deb &#x5B;signed-by=\/etc\/apt\/keyrings\/kubernetes-archive-keyring.gpg] https:\/\/apt.kubernetes.io\/ kubernetes-xenial main&quot; | sudo tee \/etc\/apt\/sources.list.d\/kubernetes.list\n<\/pre><\/div>\n\n\n<p>15. Update package listings:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo apt-get update\n<\/pre><\/div>\n\n\n<p>16. Install specific versions of the kubelet, kubeadm, and kubectl packages :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-get install -y kubelet=1.24.0-00 kubeadm=1.24.0-00 kubectl=1.24.0-00<\/code><\/pre>\n\n\n\n<p>17. Mark the kubelet, kubeadm, and kubectl packages as &#8220;held&#8221; to prevent them from being automatically upgraded:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo apt-mark hold kubelet kubeadm kubectl\n<\/pre><\/div>\n\n\n<p>18. The installation of the packages must be performed on all servers. The entire part 1 must be repeated on the worker nodes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Initialize the Cluster<\/h3>\n\n\n\n<p>1. <em>This part had to be done only on the Master server (Control Plane)<\/em><br>Install specific versions of the kubelet, kubeadm, and kubectl packages. And then initialize the Kubernetes cluster with kubeadm, specifying the pod network CIDR and the Kubernetes version<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsudo apt-get install -y kubelet=1.24.0-00 kubeadm=1.24.0-00 kubectl=1.24.0-00\nsudo kubeadm init --pod-network-cidr 192.168.0.0\/16 --kubernetes-version 1.24.0\n<\/pre><\/div>\n\n\n<pre class=\"wp-block-code\"><code>dbinla@dbisbx-master01:~$ sudo kubeadm init --pod-network-cidr 192.168.0.0\/16 --kubernetes-version 1.24.0\n&#091;init] Using Kubernetes version: v1.24.0\n&#091;preflight] Running pre-flight checks\n&#091;preflight] Pulling images required for setting up a Kubernetes cluster\n&#091;preflight] This might take a minute or two, depending on the speed of your internet connection\n&#091;preflight] You can also perform this action in beforehand using 'kubeadm config images pull'\n&#091;certs] Using certificateDir folder \"\/etc\/kubernetes\/pki\"\n&#091;certs] Generating \"ca\" certificate and key\n&#091;certs] Generating \"apiserver\" certificate and key\n&#091;certs] apiserver serving cert is signed for DNS names &#091;dbisbx-master01 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs &#091;10.*.*.* 172.*.*.*]\n&#091;certs] Generating \"apiserver-kubelet-client\" certificate and key\n&#091;certs] Generating \"front-proxy-ca\" certificate and key\n&#091;certs] Generating \"front-proxy-client\" certificate and key\n&#091;certs] Generating \"etcd\/ca\" certificate and key\n&#091;certs] Generating \"etcd\/server\" certificate and key\n&#091;certs] etcd\/server serving cert is signed for DNS names &#091;dbisbx-master01 localhost] and IPs &#091;172.*.*.* 127.0.0.1 ::1]\n&#091;certs] Generating \"etcd\/peer\" certificate and key\n&#091;certs] etcd\/peer serving cert is signed for DNS names &#091;dbisbx-master01 localhost] and IPs &#091;172.*.*.* 127.0.0.1 ::1]\n&#091;certs] Generating \"etcd\/healthcheck-client\" certificate and key\n&#091;certs] Generating \"apiserver-etcd-client\" certificate and key\n&#091;certs] Generating \"sa\" key and public key\n&#091;kubeconfig] Using kubeconfig folder \"\/etc\/kubernetes\"\n&#091;kubeconfig] Writing \"admin.conf\" kubeconfig file\n&#091;kubeconfig] Writing \"kubelet.conf\" kubeconfig file\n&#091;kubeconfig] Writing \"controller-manager.conf\" kubeconfig file\n&#091;kubeconfig] Writing \"scheduler.conf\" kubeconfig file\n&#091;kubelet-start] Writing kubelet environment file with flags to file \"\/var\/lib\/kubelet\/kubeadm-flags.env\"\n&#091;kubelet-start] Writing kubelet configuration to file \"\/var\/lib\/kubelet\/config.yaml\"\n&#091;kubelet-start] Starting the kubelet\n&#091;control-plane] Using manifest folder \"\/etc\/kubernetes\/manifests\"\n&#091;control-plane] Creating static Pod manifest for \"kube-apiserver\"\n&#091;control-plane] Creating static Pod manifest for \"kube-controller-manager\"\n&#091;control-plane] Creating static Pod manifest for \"kube-scheduler\"\n&#091;etcd] Creating static Pod manifest for local etcd in \"\/etc\/kubernetes\/manifests\"\n&#091;wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory \"\/etc\/kubernetes\/manifests\". This can take up to 4m0s\n&#091;kubelet-check] Initial timeout of 40s passed.\n&#091;apiclient] All control plane components are healthy after 53.186020 seconds\n&#091;upload-config] Storing the configuration used in ConfigMap \"kubeadm-config\" in the \"kube-system\" Namespace\n&#091;kubelet] Creating a ConfigMap \"kubelet-config\" in namespace kube-system with the configuration for the kubelets in the cluster\n&#091;upload-certs] Skipping phase. Please see --upload-certs\n&#091;mark-control-plane] Marking the node dbisbx-master01 as control-plane by adding the labels: &#091;node-role.kubernetes.io\/control-plane node.kubernetes.io\/exclude-from-external-load-balancers]\n&#091;mark-control-plane] Marking the node dbisbx-master01 as control-plane by adding the taints &#091;node-role.kubernetes.io\/master:NoSchedule node-role.kubernetes.io\/control-plane:NoSchedule]\n&#091;bootstrap-token] Using token: vnv0kw.xmh*************\n&#091;bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles\n&#091;bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes\n&#091;bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials\n&#091;bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token\n&#091;bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster\n&#091;bootstrap-token] Creating the \"cluster-info\" ConfigMap in the \"kube-public\" namespace\n&#091;kubelet-finalize] Updating \"\/etc\/kubernetes\/kubelet.conf\" to point to a rotatable kubelet client certificate and key\n&#091;addons] Applied essential addon: CoreDNS\n&#091;addons] Applied essential addon: kube-proxy\n\nYour Kubernetes control-plane has initialized successfully!\n\nTo start using your cluster, you need to run the following as a regular user:\n\n  mkdir -p $HOME\/.kube\n  sudo cp -i \/etc\/kubernetes\/admin.conf $HOME\/.kube\/config\n  sudo chown $(id -u):$(id -g) $HOME\/.kube\/config\n\nAlternatively, if you are the root user, you can run:\n\n  export KUBECONFIG=\/etc\/kubernetes\/admin.conf\n\nYou should now deploy a pod network to the cluster.\nRun \"kubectl apply -f &#091;podnetwork].yaml\" with one of the options listed at:\n  https:&#047;&#047;kubernetes.io\/docs\/concepts\/cluster-administration\/addons\/\n\nThen you can join any number of worker nodes by running the following on each as root:\n\nkubeadm join 172.*.*.*:6443 --token vnv0kw.xmh************* \\\n\t--discovery-token-ca-cert-hash sha256:eaec80d623e107619c02f743a726d8e5f6******************************\ndbinla@dbisbx-master01:~$<\/code><\/pre>\n\n\n\n<p>2. Once the initialization is done, we have to set the kubectl access. <br>For this aim, let&#8217;s create the <em>.kube<\/em> folder in our user&#8217;s home directory if it doesn&#8217;t already exist. <br>We will then copy the admin.conf file from \/etc\/kubernetes to the .kube directory. Finally, we will change the owner of the copied file to the current user.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nmkdir -p $HOME\/.kube\nsudo cp -i \/etc\/kubernetes\/admin.conf $HOME\/.kube\/config\nsudo chown $(id -u):$(id -g) $HOME\/.kube\/config\n<\/pre><\/div>\n\n\n<p>3. Test the access to the cluster.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nkubectl get nodes\n<\/pre><\/div>\n\n\n<pre class=\"wp-block-code\"><code>dbinla@dbisbx-master01:~$ kubectl get nodes\nNAME              STATUS     ROLES           AGE   VERSION\ndbisbx-master01   NotReady   control-plane   02m   v1.24.0\ndbinla@dbisbx-master01:~$<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Install the Calico Network Add-On<\/h3>\n\n\n\n<p>1. On the control plane node, install Calico Networking by creating the necessary custom resource:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nkubectl create -f https:\/\/raw.githubusercontent.com\/projectcalico\/calico\/v3.25.0\/manifests\/custom-resources.yaml\n<\/pre><\/div>\n\n\n<p><em>More information on configuration option are available<\/em> <a href=\"https:\/\/docs.tigera.io\/calico\/latest\/reference\/installation\/api\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dbinla@dbisbx-master01:~$ kubectl create -f https:\/\/raw.githubusercontent.com\/projectcalico\/calico\/v3.25.0\/manifests\/custom-resources.yaml\npoddisruptionbudget.policy\/calico-kube-controllers created\nserviceaccount\/calico-kube-controllers created\nserviceaccount\/calico-node created\nconfigmap\/calico-config created\ncustomresourcedefinition.apiextensions.k8s.io\/bgpconfigurations.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/bgppeers.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/blockaffinities.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/caliconodestatuses.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/clusterinformations.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/felixconfigurations.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/globalnetworkpolicies.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/globalnetworksets.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/hostendpoints.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/ipamblocks.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/ipamconfigs.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/ipamhandles.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/ippools.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/ipreservations.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/kubecontrollersconfigurations.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/networkpolicies.crd.projectcalico.org created\ncustomresourcedefinition.apiextensions.k8s.io\/networksets.crd.projectcalico.org created\nclusterrole.rbac.authorization.k8s.io\/calico-kube-controllers created\nclusterrole.rbac.authorization.k8s.io\/calico-node created\nclusterrolebinding.rbac.authorization.k8s.io\/calico-kube-controllers created\nclusterrolebinding.rbac.authorization.k8s.io\/calico-node created\ndaemonset.apps\/calico-node created\ndeployment.apps\/calico-kube-controllers created\ndbinla@dbisbx-master01:~$<\/code><\/pre>\n\n\n\n<p>2. Check the status of the control plane node:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nkubectl get nodes -owide\n<\/pre><\/div>\n\n\n<pre class=\"wp-block-code\"><code>dbinla@dbisbx-master01:~$ kubectl get nodes -owide\nNAME              STATUS   ROLES           AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME\ndbisbx-master01   Ready    control-plane   07m   v1.24.0   172.*.*.*    &lt;none&gt;        Ubuntu 20.04.5 LTS   5.15.0-1027-aws   containerd:\/\/1.5.9\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Join the worker nodes to k8s cluster<\/h3>\n\n\n\n<p>In the chapter &#8220;Cluster Initialization&#8221;, we retrieved the command allowing us to add our workers to the cluster.<br>You can retrieve the command and run it on each worker.<br>In case you didn&#8217;t copy the command, you still have the possibility to display the join command by recreating the token that will allow you to join your nodes.<br>1. From the control plane server, execute the following command.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nkubeadm token create --print-join-command\n<\/pre><\/div>\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ndbinla@dbisbx-master01:~$ kubeadm token create --print-join-command\nkubeadm join 172.31.99.146:6443 --token u871a6.k*************** --discovery-token-ca-cert-hash sha256:eaec80d623e107619c02f743a726*********************************\n\n<\/pre><\/div>\n\n\n<pre class=\"wp-block-preformatted\">2. On the first worker node, execute the previous printed command \"kubeadm join &lt;IP:PORT&gt; ...\" being root, or running as root user.<\/pre>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nsudo kubeadm join 172.*.*.*:6443 --token u871a6.kbzwx2j6jztxyvg3 --discovery-token-ca-cert-hash sha256:eaec80d623e107619c02f743a726*********************************\n<\/pre><\/div>\n\n\n<pre class=\"wp-block-code\"><code>dbinla@dbisbx-worker01:~$ sudo kubeadm join 172.*.*.*:6443 --token u871a6.kbzwx2j6jztxyvg3 --discovery-token-ca-cert-hash sha256:eaec80d623e107619c02f743a726*********************************\n&#091;preflight] Running pre-flight checks\n&#091;preflight] Reading configuration from the cluster...\n&#091;preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'\n&#091;kubelet-start] Writing kubelet configuration to file \"\/var\/lib\/kubelet\/config.yaml\"\n&#091;kubelet-start] Writing kubelet environment file with flags to file \"\/var\/lib\/kubelet\/kubeadm-flags.env\"\n&#091;kubelet-start] Starting the kubelet\n&#091;kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...\n\nThis node has joined the cluster:\n* Certificate signing request was sent to apiserver and a response was received.\n* The Kubelet was informed of the new secure connection details.\n\nRun 'kubectl get nodes' on the control-plane to see this node join the cluster.\n\ndbinla@dbisbx-worker01:~$<\/code><\/pre>\n\n\n\n<p>All that remains is to check that the node has been added to the cluster; it may take a few minutes for the node to go to the ready status<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nkubectl get nodes -owide\n<\/pre><\/div>\n\n\n<pre class=\"wp-block-code\"><code>dbinla@dbisbx-master01:~$ kubectl get nodes -owide\nNAME              STATUS   ROLES           AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION    CONTAINER-RUNTIME\ndbisbx-master01   Ready    control-plane   19m   v1.24.0   172.31.99.146    &lt;none&gt;        Ubuntu 20.04.5 LTS   5.15.0-1027-aws   containerd:\/\/1.5.9\ndbisbx-worker01   Ready    &lt;none&gt;          05m   v1.24.0   172.31.101.246   &lt;none&gt;        Ubuntu 20.04.5 LTS   5.15.0-1027-aws   containerd:\/\/1.5.9\ndbisbx-worker02   Ready    &lt;none&gt;          03m   v1.24.0   172.31.96.172    &lt;none&gt;        Ubuntu 20.04.5 LTS   5.15.0-1027-aws   containerd:\/\/1.5.9<\/code><\/pre>\n\n\n\n<p>Here we are; we could quickly build a small Kubernetes cluster in less than 20 minutes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the upcoming blog posts, I will cover monitoring with Prometheus in a Kubernetes infrastructure. As I started blogging, I decided it would be useful to delve into the design of the k8s infrastructure. This will allow you to approach these blogs better if you wish to reproduce them. Therefore, I will start with the [&hellip;]<\/p>\n","protected":false},"author":40,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1320,1522],"tags":[38,101,89],"type_dbi":[],"class_list":["post-21430","post","type-post","status-publish","format-standard","hentry","category-devops","category-kubernetes","tag-cluster","tag-installation","tag-kubernetes"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.5) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Easily build a kubernetes cluster with kubeadm - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Easily build a kubernetes cluster with kubeadm\" \/>\n<meta property=\"og:description\" content=\"In the upcoming blog posts, I will cover monitoring with Prometheus in a Kubernetes infrastructure. As I started blogging, I decided it would be useful to delve into the design of the k8s infrastructure. This will allow you to approach these blogs better if you wish to reproduce them. Therefore, I will start with the [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2023-03-20T07:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-03-31T12:23:30+00:00\" \/>\n<meta name=\"author\" content=\"Middleware Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Middleware Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/how-to-build-a-kubernetes-cluster-with-kubeadm\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/how-to-build-a-kubernetes-cluster-with-kubeadm\\\/\"},\"author\":{\"name\":\"Middleware Team\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/8d8563acfc6e604cce6507f45bac0ea1\"},\"headline\":\"Easily build a kubernetes cluster with kubeadm\",\"datePublished\":\"2023-03-20T07:00:00+00:00\",\"dateModified\":\"2023-03-31T12:23:30+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/how-to-build-a-kubernetes-cluster-with-kubeadm\\\/\"},\"wordCount\":604,\"commentCount\":0,\"keywords\":[\"Cluster\",\"Installation\",\"kubernetes\"],\"articleSection\":[\"DevOps\",\"Kubernetes\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/how-to-build-a-kubernetes-cluster-with-kubeadm\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/how-to-build-a-kubernetes-cluster-with-kubeadm\\\/\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/how-to-build-a-kubernetes-cluster-with-kubeadm\\\/\",\"name\":\"Easily build a kubernetes cluster with kubeadm - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\"},\"datePublished\":\"2023-03-20T07:00:00+00:00\",\"dateModified\":\"2023-03-31T12:23:30+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/8d8563acfc6e604cce6507f45bac0ea1\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/how-to-build-a-kubernetes-cluster-with-kubeadm\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/how-to-build-a-kubernetes-cluster-with-kubeadm\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/how-to-build-a-kubernetes-cluster-with-kubeadm\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Easily build a kubernetes cluster with kubeadm\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/8d8563acfc6e604cce6507f45bac0ea1\",\"name\":\"Middleware Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g\",\"caption\":\"Middleware Team\"},\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/author\\\/middleware-team\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Easily build a kubernetes cluster with kubeadm - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/","og_locale":"en_US","og_type":"article","og_title":"Easily build a kubernetes cluster with kubeadm","og_description":"In the upcoming blog posts, I will cover monitoring with Prometheus in a Kubernetes infrastructure. As I started blogging, I decided it would be useful to delve into the design of the k8s infrastructure. This will allow you to approach these blogs better if you wish to reproduce them. Therefore, I will start with the [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/","og_site_name":"dbi Blog","article_published_time":"2023-03-20T07:00:00+00:00","article_modified_time":"2023-03-31T12:23:30+00:00","author":"Middleware Team","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Middleware Team","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/"},"author":{"name":"Middleware Team","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1"},"headline":"Easily build a kubernetes cluster with kubeadm","datePublished":"2023-03-20T07:00:00+00:00","dateModified":"2023-03-31T12:23:30+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/"},"wordCount":604,"commentCount":0,"keywords":["Cluster","Installation","kubernetes"],"articleSection":["DevOps","Kubernetes"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/","url":"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/","name":"Easily build a kubernetes cluster with kubeadm - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2023-03-20T07:00:00+00:00","dateModified":"2023-03-31T12:23:30+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/how-to-build-a-kubernetes-cluster-with-kubeadm\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Easily build a kubernetes cluster with kubeadm"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1","name":"Middleware Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g","caption":"Middleware Team"},"url":"https:\/\/www.dbi-services.com\/blog\/author\/middleware-team\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/21430","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/40"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=21430"}],"version-history":[{"count":36,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/21430\/revisions"}],"predecessor-version":[{"id":23651,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/21430\/revisions\/23651"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=21430"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=21430"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=21430"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=21430"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}