{"id":20,"date":"2026-03-23T09:13:53","date_gmt":"2026-03-23T09:13:53","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=20"},"modified":"2026-03-24T03:52:20","modified_gmt":"2026-03-24T03:52:20","slug":"install-kubernetes-using-ansible-on-ubuntu-24-04","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=20","title":{"rendered":"Install Kubernetes Using Ansible on Ubuntu 24.04"},"content":{"rendered":"\n<div class=\"wp-block-file\"><a id=\"wp-block-file--media-f58334a9-9d96-46c3-a844-9b43599bfead\" href=\"https:\/\/blog.ngocha.biz\/wp-content\/uploads\/2026\/03\/install.png\">install<\/a><a href=\"https:\/\/blog.ngocha.biz\/wp-content\/uploads\/2026\/03\/install.png\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-f58334a9-9d96-46c3-a844-9b43599bfead\">Download<\/a><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Learn how to install Kubernetes using Ansible on Ubuntu 24.04. This comprehensive guide covers prerequisites, setup, and configuration, ensuring a streamlined and consistent deployment process.<br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Deploying Kubernetes on Ubuntu 24.04 can be a complex task. However, using Ansible roles simplifies this process significantly. Ansible, an open-source automation tool, allows you to automate and manage configuration tasks efficiently. In a previous article, we reviewed how to manually deploy&nbsp;<a href=\"https:\/\/infotechys.com\/setting-up-a-kubernetes-cluster-on-ubuntu-23-10\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Kubernetes on Ubuntu 23.10<\/strong>.<\/a>&nbsp;In this guide, we will walk through the steps to deploy a Kubernetes cluster on Ubuntu 24.04 using Ansible roles.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why Use Ansible Roles for Kubernetes Deployment?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ansible roles are modular and reusable units of automation. They allow you to separate your configuration into reusable components. This modularity simplifies the management and maintenance of your infrastructure. Additionally, using Ansible roles ensures consistency across different environments.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before we begin, ensure you have the following:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>A stable internet connection<strong>A control node with Ansible installed (preferably&nbsp;Ubuntu 24.04).&nbsp;&nbsp;<\/strong><strong>At least two&nbsp;Ubuntu 24.04&nbsp;nodes (one master and one worker).&nbsp;<\/strong>SSH access to all nodes from the control node.&nbsp;Establish a user account with sudo (root) privileges on all nodes.Basic Knowledge of Ansible and Kubernetes.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>For demonstration purposes, we have set up our Ubuntu 24.04 instances as follows:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Hostname<\/strong><\/td><td><strong>RAM<\/strong><\/td><td><strong>Cores<\/strong><\/td><td><strong>OS<\/strong><\/td><\/tr><tr><td><strong>control.naijalabs.net<\/strong><\/td><td>4<\/td><td>2<\/td><td>Ubuntu 24.04 (Noble Numbat)<\/td><\/tr><tr><td>master.naijalabs.net<\/td><td>4<\/td><td>2<\/td><td>Ubuntu 24.04 (Noble Numbat)<\/td><\/tr><tr><td>worker1.naijalabs.net<\/td><td>4<\/td><td>2<\/td><td>Ubuntu 24.04 (Noble Numbat)<\/td><\/tr><tr><td>worker2.naijalabs.net<\/td><td>4<\/td><td>2<\/td><td>Ubuntu 24.04 (Noble Numbat)<\/td><\/tr><tr><td>worker3.naijalabs.net<\/td><td>4<\/td><td>2<\/td><td>Ubuntu 24.04 (Noble Numbat)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>\ud83d\udc40<strong>IMPORTANT NOTE:&nbsp;If you don\u2019t have a&nbsp;DNS&nbsp;server, you need to add the following entries to the&nbsp;<code>\/etc\/hosts<\/code>&nbsp;file on&nbsp;each node.<\/strong><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code># Kubernetes Cluster\n192.168.1.168 control.naijalabs.net   control  # Ansible Control Node\n192.168.1.169 master.naijalabs.net    master\n192.168.1.170 worker1.naijalabs.net   worker1\n192.168.1.171 worker2.naijalabs.net   worker2\n192.168.1.172 worker3.naijalabs.net   worker3<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>\ud83d\udc40<strong>To clarify, replace the IP addresses and hostnames with those specific to your environment. The provided information is intended to give you an idea of what our&nbsp;<\/strong><strong><code>\/etc\/hosts<\/code><\/strong><strong>&nbsp;file looks like for reference before we proceed.&nbsp;<\/strong><strong>This is an on-premises k8s cluster instance.<\/strong><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Install Kubernetes Using Ansible on Ubuntu 24.04<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s proceed with the installation. First things first, update&nbsp;<strong>all nodes<\/strong>&nbsp;with the following command (below).&nbsp;<strong>Please read each instruction carefully before executing:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt update -y &amp;&amp; sudo apt upgrade -y<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Step 1: Setting Up Your Workspace<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Before we start, let\u2019s set up a workspace on the&nbsp;<strong>control node<\/strong>&nbsp;to store all the files needed for our Kubernetes deployment. Create a directory named&nbsp;<code><strong>k8s<\/strong><\/code>&nbsp;and navigate into it by running the following commands:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p k8s &amp;&amp; cd k8s<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong>&nbsp;If you haven\u2019t done so already, ensure you have a user account with sudo privileges to become root&nbsp;<strong>on all nodes<\/strong>&nbsp;before setting up your workspace. You can create an account and apply the appropriate permissions with the following commands (otherwise, skip to&nbsp;<a href=\"https:\/\/infotechys.com\/install-kubernetes-using-ansible-on-ubuntu-24-04#elementor-toc__heading-anchor-5\">step #2<\/a>):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo adduser sysadmin<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>info: Adding user `sysadmin' ...\ninfo: Selecting UID\/GID from range 1000 to 59999 ...\ninfo: Adding new group `sysadmin' (1000) ...\ninfo: Adding new user `sysadmin' (1000) with group `sysadmin (1000)' ...\ninfo: Creating home directory `\/home\/sysadmin' ...\ninfo: Copying files from `\/etc\/skel' ...\nNew password:\nRetype new password:\npasswd: password updated successfully\nChanging the user information for sysadmin\nEnter the new value, or press ENTER for the default\n\tFull Name &#91;]:\n\tRoom Number &#91;]:\n\tWork Phone &#91;]:\n\tHome Phone &#91;]:\n\tOther &#91;]:\nIs the information correct? &#91;Y\/n] Y\ninfo: Adding new user `sysadmin' to supplemental \/ extra groups `users' ...\ninfo: Adding user `sysadmin' to group `users' ...<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For this demonstration, we created an account named&nbsp;<code>sysadmin<\/code>&nbsp;and pressed the&nbsp;<code><strong>[Enter]<\/strong><\/code>&nbsp;key multiple times to accept all defaults. Next, add the new user to the sudo group:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo usermod -aG sudo sysadmin<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, verify that the user has sudo privileges by switching to the new user:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>su - sysadmin<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This command should produce no errors:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -v<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Step 2: Setting Up Your Environment<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">First, update your package lists and install Ansible on your&nbsp;<strong>control node only:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install ansible -y<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, set up SSH keys to allow passwordless access to your nodes. Generate an SSH key pair if you haven\u2019t already:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh-keygen -t rsa -b 4096 -C \"your_email@example.com\"<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Generating public\/private rsa key pair.\nEnter file in which to save the key (\/home\/sysadmin\/.ssh\/id_rsa):\nEnter passphrase (empty for no passphrase):\nEnter same passphrase again:\nYour identification has been saved in \/home\/sysadmin\/.ssh\/id_rsa\nYour public key has been saved in \/home\/sysadmin\/.ssh\/id_rsa.pub\nThe key fingerprint is:\nSHA256:ZCOCj3nJH4acPXTcNG7uc2P8TrGHyW9fbfWnfFNI874 Infotechystaff@gmail.com\nThe key's randomart image is:\n+---&#91;RSA 4096]----+\n|          o      |\n|   .   . + .     |\n|  . . o * +      |\n|   * B = +    o  |\n|  o O = S .  ..+.|\n|   . o o . . ..=*|\n|      .   o = *.O|\n|           + = **|\n|             .=E*|\n+----&#91;SHA256]-----+<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now that you\u2019ve created a public key on your control node, copy that key to each of your nodes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh-copy-id your_privileged_user@your_master_node_ip_address<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh-copy-id your_privileged_user@your_worker_node_ip_address<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Step 3: Define Your Inventory File<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Using your preferred&nbsp;<a href=\"https:\/\/infotechys.com\/popular-text-editors-for-linux\" target=\"_blank\" rel=\"noreferrer noopener\">text editor<\/a>, create an inventory file to list your nodes. This file, typically named&nbsp;<code><strong>hosts<\/strong><\/code>&nbsp;or&nbsp;<code><strong>inventory<\/strong><\/code>, should look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vim hosts<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, copy and Paste the following entries (<em>below<\/em>) and modify to suit your environment.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;master_nodes]\nmaster  ansible_host=192.168.1.169\n\n&#91;worker_nodes]\nworker1 ansible_host=192.168.1.170\nworker2 ansible_host=192.168.1.171\nworker3 ansible_host=192.168.1.172\n\n&#91;all:vars]\nansible_python_interpreter=\/usr\/bin\/python3<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Step 4: Create Ansible Roles<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Now, let\u2019s create Ansible roles for the Kubernetes master, network and worker nodes.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Role for Kubernetes Master<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Create a directory structure for the master role with the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible-galaxy init kubernetes_master<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Edit the&nbsp;<strong><code>tasks\/main.yml<\/code><\/strong>&nbsp;file in the&nbsp;<code><strong>kubernetes_master<\/strong><\/code>&nbsp;role:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vim kubernetes_master\/tasks\/main.yml<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Copy and paste the following entries into the&nbsp;<code>main.yml<\/code>&nbsp;file (<em>then, save and exit the file<\/em>):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>---\n# tasks file for kubernetes_master\n- name: Install required packages\n  apt:\n    name:\n      - curl\n      - gnupg2\n      - software-properties-common\n      - apt-transport-https\n      - ca-certificates\n    state: present\n    update_cache: yes\n\n- name: Install Docker\n  apt:\n    name: docker.io\n    state: present\n    update_cache: yes\n\n- name: Remove Keyrings Directory (if it exists)\n  ansible.builtin.shell: rm -rf \/etc\/apt\/keyrings\n\n- name: Remove Existing Kubernetes Directory (if it exists)\n  ansible.builtin.shell: sudo rm -rf \/etc\/apt\/sources.list.d\/pkgs_k8s_io_core_stable_v1_30_deb.list\n\n- name: Disable swap\n  ansible.builtin.command:\n    cmd: swapoff -a\n\n- name: Ensure swap is disabled on boot\n  ansible.builtin.command:\n    cmd: sudo sed -i -e '\/\\\/swap.img\\s\\+none\\s\\+swap\\s\\+sw\\s\\+0\\s\\+0\/s\/^\/#\/' \/etc\/fstab\n\n- name: Add kernel modules for Containerd\n  ansible.builtin.copy:\n    dest: \/etc\/modules-load.d\/containerd.conf\n    content: |\n      overlay\n      br_netfilter\n\n- name: Load kernel modules for Containerd\n  ansible.builtin.shell:\n    cmd: modprobe overlay &amp;&amp; modprobe br_netfilter\n  become: true\n\n- name: Add kernel parameters for Kubernetes\n  ansible.builtin.copy:\n    dest: \/etc\/sysctl.d\/kubernetes.conf\n    content: |\n      net.bridge.bridge-nf-call-ip6tables = 1\n      net.bridge.bridge-nf-call-iptables = 1\n      net.ipv4.ip_forward = 1\n\n- name: Load kernel parameter changes\n  ansible.builtin.command:\n    cmd: sudo sysctl --system\n\n- name: Configuring Containerd (building the configuration file)\n  ansible.builtin.command:\n    cmd: sudo sh -c \"containerd config default &gt; \/opt\/containerd\/config.toml\"\n\n- name: Configuring Containerd (Setting SystemdCgroup Variable to True)\n  ansible.builtin.command:\n    cmd: sudo sed -i 's\/SystemdCgroup = false\/SystemdCgroup = true\/' \/opt\/containerd\/config.toml\n\n- name: Reload systemd configuration\n  ansible.builtin.command:\n    cmd: systemctl daemon-reload\n\n- name: Restart containerd service\n  ansible.builtin.service:\n    name: containerd\n    state: restarted\n\n- name: Allow 6443\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 6443\/tcp\n\n- name: Allow 2379:2380\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 2379:2380\/tcp\n\n- name: Allow 22\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 22\/tcp\n\n- name: Allow 8080\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 8080\/tcp\n\n- name: Allow 10250\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10250\/tcp\n\n- name: Allow 10251\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10251\/tcp\n\n- name: Allow 10252\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10252\/tcp\n\n- name: Allow 10255\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10255\/tcp\n\n- name: Allow 5473\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 5473\/tcp\n\n- name: Enable the firewall\n  ansible.builtin.ufw:\n    state: enabled\n\n- name: Reload the firewall\n  ansible.builtin.command:\n    cmd: sudo ufw reload\n\n- name: Prepare keyrings directory and update permissions\n  file:\n    path: \/etc\/apt\/keyrings\n    state: directory\n    mode: '0755'\n\n- name: Download Kubernetes GPG key securely\n  ansible.builtin.shell: curl -fsSL https:\/\/pkgs.k8s.io\/core:\/stable:\/v1.30\/deb\/Release.key | sudo gpg --dearmor -o \/etc\/apt\/keyrings\/kubernetes-apt-keyring.gpg\n\n- name: Add Kubernetes repository\n  ansible.builtin.apt_repository:\n    repo: \"deb &#91;signed-by=\/etc\/apt\/keyrings\/kubernetes-apt-keyring.gpg] https:\/\/pkgs.k8s.io\/core:\/stable:\/v1.30\/deb\/ \/\"\n    state: present\n\n- name: Install kubeadm, kubelet, kubectl\n  ansible.builtin.apt:\n    name:\n      - kubelet\n      - kubeadm\n      - kubectl\n    state: present\n    update_cache: yes\n\n- name: Hold kubelet, kubeadm, kubectl packages\n  ansible.builtin.command:\n    cmd: sudo apt-mark hold kubelet kubeadm kubectl\n\n- name: Replace \/etc\/default\/kubelet contents\n  ansible.builtin.copy:\n    dest: \/etc\/default\/kubelet\n    content: 'KUBELET_EXTRA_ARGS=\"--cgroup-driver=cgroupfs\"'\n\n- name: Reload systemd configuration\n  ansible.builtin.command:\n    cmd: systemctl daemon-reload\n\n- name: Restart kubelet service\n  ansible.builtin.service:\n    name: kubelet\n    state: restarted\n\n- name: Update System-Wide Profile for Kubernetes\n  ansible.builtin.copy:\n    dest: \/etc\/profile.d\/kubernetes.sh\n    content: |\n      export KUBECONFIG=\/etc\/kubernetes\/admin.conf\n      export ANSIBLE_USER=\"sysadmin\"\n\n- name: Reboot the system\n  ansible.builtin.reboot:\n    msg: \"Reboot initiated by Ansible for Kubernetes setup\"\n    reboot_timeout: 150\n\n- name: Replace Docker daemon.json configuration\n  ansible.builtin.copy:\n    dest: \/etc\/docker\/daemon.json\n    content: |\n      {\n        \"exec-opts\": &#91;\"native.cgroupdriver=systemd\"],\n        \"log-driver\": \"json-file\",\n        \"log-opts\": {\n          \"max-size\": \"100m\"\n        },\n        \"storage-driver\": \"overlay2\"\n      }\n\n- name: Reload systemd configuration\n  ansible.builtin.command:\n    cmd: systemctl daemon-reload\n\n- name: Restart Docker service\n  ansible.builtin.service:\n    name: docker\n    state: restarted\n\n- name: Update Kubeadm Environment Variable\n  ansible.builtin.command:\n    cmd: sudo sed -i -e '\/^\\&#91;Service\\]\/a Environment=\"KUBELET_EXTRA_ARGS=--fail-swap-on=false\"' \/usr\/lib\/systemd\/system\/kubelet.service.d\/10-kubeadm.conf\n\n- name: Reload systemd configuration\n  ansible.builtin.command:\n    cmd: systemctl daemon-reload\n\n- name: Restart kubelet service\n  ansible.builtin.service:\n    name: kubelet\n    state: restarted\n\n- name: Pull kubeadm container images\n  ansible.builtin.command:\n    cmd: sudo kubeadm config images pull\n\n- name: Initialize Kubernetes control plane\n  ansible.builtin.command:\n    cmd: kubeadm init --pod-network-cidr=10.244.0.0\/16\n    creates: \/tmp\/kubeadm_output\n  register: kubeadm_init_output\n  become: true\n  changed_when: false\n\n- name: Set permissions for Kubernetes Admin\n  file:\n    path: \/etc\/kubernetes\/admin.conf\n    state: file\n    mode: '0755'\n\n- name: Store Kubernetes initialization output to file\n  copy:\n    content: \"{{ kubeadm_init_output.stdout }}\"\n    dest: \/tmp\/kubeadm_output\n  become: true\n  delegate_to: localhost\n\n- name: Generate the Join Command\n  ansible.builtin.shell: cat \/tmp\/kubeadm_output | tail -n 2 | sed ':a;N;$!ba;s\/\\\\\\n\\s*\/ \/g' &gt; \/tmp\/join-command\n  delegate_to: localhost\n\n- name: Set permissions for the Join Executable\n  file:\n    path: \/tmp\/join-command\n    state: file\n    mode: '0755'\n  delegate_to: localhost<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong>&nbsp;If your user account differs from&nbsp;<strong><code>sysadmin<\/code><\/strong>, ensure that you update the&nbsp;<strong><code>ANSIBLE_USER<\/code><\/strong>&nbsp;variable in the&nbsp;<code>main.yml<\/code>&nbsp;file to reflect your user account.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>export ANSIBLE_USER=\"your_privileged_user\"<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Role for Kubernetes Worker<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Create a directory structure for the worker role:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible-galaxy init kubernetes_worker<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Edit the&nbsp;<code><strong>tasks\/main.yml<\/strong><\/code>&nbsp;file in the&nbsp;<code><strong>kubernetes_worker<\/strong><\/code>&nbsp;role:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vim kubernetes_worker\/tasks\/main.yml<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Copy and paste the following to the file (<em>save and exit the file<\/em>):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>---\n# tasks file for kubernetes_worker\n- name: Install required packages\n  apt:\n    name:\n      - curl\n      - gnupg2\n      - software-properties-common\n      - apt-transport-https\n      - ca-certificates\n    state: present\n    update_cache: yes\n\n- name: Install Docker\n  apt:\n    name: docker.io\n    state: present\n    update_cache: yes\n\n- name: Remove Keyrings Directory (if it exists)\n  ansible.builtin.shell: rm -rf \/etc\/apt\/keyrings\n\n- name: Remove Existing Kubernetes Directory (if it exists)\n  ansible.builtin.shell: sudo rm -rf \/etc\/apt\/sources.list.d\/pkgs_k8s_io_core_stable_v1_30_deb.list\n\n- name: Disable swap\n  ansible.builtin.command:\n    cmd: swapoff -a\n\n- name: Ensure swap is disabled on boot\n  ansible.builtin.command:\n    cmd: sudo sed -i -e '\/\\\/swap.img\\s\\+none\\s\\+swap\\s\\+sw\\s\\+0\\s\\+0\/s\/^\/#\/' \/etc\/fstab\n\n- name: Add kernel modules for Containerd\n  ansible.builtin.copy:\n    dest: \/etc\/modules-load.d\/containerd.conf\n    content: |\n      overlay\n      br_netfilter\n\n- name: Load kernel modules for Containerd\n  ansible.builtin.shell:\n    cmd: modprobe overlay &amp;&amp; modprobe br_netfilter\n  become: true\n\n- name: Add kernel parameters for Kubernetes\n  ansible.builtin.copy:\n    dest: \/etc\/sysctl.d\/kubernetes.conf\n    content: |\n      net.bridge.bridge-nf-call-ip6tables = 1\n      net.bridge.bridge-nf-call-iptables = 1\n      net.ipv4.ip_forward = 1\n\n- name: Load kernel parameter changes\n  ansible.builtin.command:\n    cmd: sudo sysctl --system\n\n- name: Configuring Containerd (building the configuration file)\n  ansible.builtin.command:\n    cmd: sudo sh -c \"containerd config default &gt; \/opt\/containerd\/config.toml\"\n\n- name: Configuring Containerd (Setting SystemdCgroup Variable to True)\n  ansible.builtin.command:\n    cmd: sudo sed -i 's\/SystemdCgroup = false\/SystemdCgroup = true\/' \/opt\/containerd\/config.toml\n\n- name: Reload systemd configuration\n  ansible.builtin.command:\n    cmd: systemctl daemon-reload\n\n- name: Restart containerd service\n  ansible.builtin.service:\n    name: containerd\n    state: restarted\n\n- name: Allow 6443\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 6443\/tcp\n\n- name: Allow 2379:2380\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 2379:2380\/tcp\n\n- name: Allow 22\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 22\/tcp\n\n- name: Allow 8080\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 8080\/tcp\n\n- name: Allow 10250\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10250\/tcp\n\n- name: Allow 10251\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10251\/tcp\n\n- name: Allow 10252\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10252\/tcp\n\n- name: Allow 10255\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10255\/tcp\n\n- name: Allow 5473\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 5473\/tcp\n\n- name: Enable the firewall\n  ansible.builtin.ufw:\n    state: enabled\n\n- name: Reload the firewall\n  ansible.builtin.command:\n    cmd: sudo ufw reload\n\n- name: Prepare keyrings directory and update permissions\n  file:\n    path: \/etc\/apt\/keyrings\n    state: directory\n    mode: '0755'\n\n- name: Download Kubernetes GPG key securely\n  ansible.builtin.shell: curl -fsSL https:\/\/pkgs.k8s.io\/core:\/stable:\/v1.30\/deb\/Release.key | sudo gpg --dearmor -o \/etc\/apt\/keyrings\/kubernetes-apt-keyring.gpg\n\n- name: Add Kubernetes repository\n  ansible.builtin.apt_repository:\n    repo: \"deb &#91;signed-by=\/etc\/apt\/keyrings\/kubernetes-apt-keyring.gpg] https:\/\/pkgs.k8s.io\/core:\/stable:\/v1.30\/deb\/ \/\"\n    state: present\n\n- name: Install kubeadm, kubelet, kubectl\n  ansible.builtin.apt:\n    name:\n      - kubelet\n      - kubeadm\n      - kubectl\n    state: present\n    update_cache: yes\n\n- name: Hold kubelet, kubeadm, kubectl packages\n  ansible.builtin.command:\n    cmd: sudo apt-mark hold kubelet kubeadm kubectl\n\n- name: Replace \/etc\/default\/kubelet contents\n  ansible.builtin.copy:\n    dest: \/etc\/default\/kubelet\n    content: 'KUBELET_EXTRA_ARGS=\"--cgroup-driver=cgroupfs\"'\n\n- name: Reload systemd configuration\n  ansible.builtin.command:\n    cmd: systemctl daemon-reload\n\n- name: Restart kubelet service\n  ansible.builtin.service:\n    name: kubelet\n    state: restarted\n\n- name: Reboot the system\n  ansible.builtin.reboot:\n    msg: \"Reboot initiated by Ansible for Kubernetes setup\"\n    reboot_timeout: 150\n\n- name: Copy join-command file to worker nodes\n  copy:\n    src: \/tmp\/join-command\n    dest: \/tmp\/join-command\n    mode: 0755\n\n- name: Join Worker Nodes\n  ansible.builtin.shell: sh \/tmp\/join-command\n  become: yes<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Role for Kubernetes Network<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Create a directory structure for the network role:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible-galaxy init kubernetes_network<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Edit the&nbsp;<code><strong>tasks\/main.yml<\/strong><\/code>&nbsp;file in the&nbsp;<code><strong>kubernetes_network<\/strong><\/code>&nbsp;role:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vim kubernetes_network\/tasks\/main.yml<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Populate that file with the following (<em>then, save and exit the file<\/em>):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>---\n# tasks file for kubernetes_network\n- name: Install Flannel network plugin\n  ansible.builtin.shell: su - $ANSIBLE_USER -c \"kubectl apply -f https:\/\/raw.githubusercontent.com\/coreos\/flannel\/master\/Documentation\/kube-flannel.yml\"\n\n- name: Taint master node to prevent workload scheduling\n  ansible.builtin.shell: su - $ANSIBLE_USER -c \"kubectl taint nodes --all node-role.kubernetes.io\/control-plane-\"<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Step 5: Create a Playbook to Run the Roles<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Create a playbook to run these roles. Create a file named&nbsp;<code>site.yml<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vim site.yml<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Populate that file with the following contents (below) then save and exit the file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>---\n- name: Configure Kubernetes Master\n  hosts: master_nodes\n  become: yes\n  roles:\n    - kubernetes_master\n\n- name: Configure Kubernetes Network\n  hosts: master_nodes\n  become: yes\n  roles:\n    - kubernetes_network\n\n- name: Configure Kubernetes Worker\n  hosts: worker_nodes\n  become: yes\n  roles:\n    - kubernetes_worker<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>\ud83d\udc40<strong>If you are running virtual machines, this is a good time to take snapshots of your&nbsp;master and worker&nbsp;nodes.&nbsp;This will allow you to revert to this current state if any unforeseen issues arise during the installation.<\/strong><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Install Kubernetes Using Ansible on Ubuntu 24.04: Breaking down the roles<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In this section, we break down the tasks required for setting up the Kubernetes master, network and worker nodes using Ansible. As part of this process, we will gain a deeper understanding of the various configuration steps involved with preparing a node for Kubernetes deployment.&nbsp;If you prefer to skip this section and continue with the installation, click this&nbsp;<a href=\"https:\/\/infotechys.com\/install-kubernetes-using-ansible-on-ubuntu-24-04#elementor-toc__heading-anchor-33\">link<\/a>&nbsp;to navigate to playbook execution section.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>1. Install Required Packages<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">First, we need to install several essential packages:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Install required packages\napt:\n  name:\n    - curl\n    - gnupg2\n    - software-properties-common\n    - apt-transport-https\n    - ca-certificates\n  state: present\n  update_cache: yes<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These packages are necessary for fetching and verifying Kubernetes components.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>2. Install Docker<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Next, we install Docker, which is a container runtime required by Kubernetes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Install Docker\napt:\n  name: docker.io\n  state: present\n  update_cache: yes<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>3. Remove Existing Directories (if they exist)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We ensure the removal of any existing directories that might interfere with our installation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Remove Keyrings Directory (if it exists)\n  ansible.builtin.shell: rm -rf \/etc\/apt\/keyrings\n\n- name: Remove Existing Kubernetes Directory (if it exists)\n  ansible.builtin.shell: sudo rm -rf \/etc\/apt\/sources.list.d\/pkgs_k8s_io_core_stable_v1_30_deb.list<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Important Note:<\/strong>&nbsp;These tasks were added to ensure&nbsp;<a href=\"https:\/\/infotechys.com\/install-kubernetes-using-ansible-on-ubuntu-24-04#elementor-toc__heading-anchor-41\" target=\"_blank\" rel=\"noreferrer noopener\">idempotence<\/a><strong>.<\/strong>&nbsp;Without them, running the playbook multiple times could result in hung processes or errors when updating the package lists or GPG signing issues. By removing these specific directories, we guarantee that each execution of the playbook starts with a clean slate, allowing the secure GPG key and Kubernetes repository to be added afresh every time.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>4. Disable Swap<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Kubernetes requires swap to be disabled:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Disable swap\n  ansible.builtin.command:\n    cmd: swapoff -a\n\n- name: Ensure swap is disabled on boot\n  ansible.builtin.command:\n    cmd: sudo sed -i -e '\/\\\/swap.img\\s\\+none\\s\\+swap\\s\\+sw\\s\\+0\\s\\+0\/s\/^\/#\/' \/etc\/fstab<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In this step, swap is deactivated and also disabled on boot.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong>&nbsp;Depending on how your Ubuntu 24.04 instances were configured or the platform you are using, your swap entries may vary. Make sure to disable swap (<strong>and ensuring swap remains disabled upon reboot<\/strong>)&nbsp; before running the playbook to prevent unnecessary errors.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>5. Load Kernel Parameters<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Configure kernel parameters required by Containerd and Kubernetes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Load kernel parameters for Containerd\n  ansible.builtin.copy:\n    dest: \/etc\/modules-load.d\/containerd.conf\n    content: |\n      overlay\n      br_netfilter\n\n- name: Load kernel parameters for Kubernetes\n  ansible.builtin.copy:\n    dest: \/etc\/sysctl.d\/kubernetes.conf\n    content: |\n      net.bridge.bridge-nf-call-ip6tables = 1\n      net.bridge.bridge-nf-call-iptables = 1\n      net.ipv4.ip_forward = 1\n\n- name: Reload Parameter Changes\n  ansible.builtin.command:\n    cmd: sudo sysctl --system<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These tasks configure and load the necessary kernel parameters for Containerd and Kubernetes. First, it creates a configuration file at&nbsp;<code>\/etc\/modules-load.d\/containerd.conf<\/code>&nbsp;to load the&nbsp;<code>overlay<\/code>&nbsp;and&nbsp;<code>br_netfilter<\/code>&nbsp;modules. Next, it sets kernel parameters for Kubernetes by creating&nbsp;<code>\/etc\/sysctl.d\/kubernetes.conf<\/code>&nbsp;with settings to enable IP forwarding and bridge network calls to iptables. Finally, it applies these changes system-wide by running&nbsp;<code>sudo sysctl --system<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>6. Configure Containerd<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Set up Containerd, the container runtime used by Kubernetes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Configuring Containerd (building the configuration file)\n  ansible.builtin.command:\n    cmd: sudo sh -c \"containerd config default &gt; \/opt\/containerd\/config.toml\"\n\n- name: Configuring Containerd (Setting SystemdCgroup Variable to True)\n  ansible.builtin.command:\n    cmd: sudo sed -i 's\/SystemdCgroup = false\/SystemdCgroup = true\/' \/opt\/containerd\/config.toml\n\n- name: Reload systemd configuration\n  ansible.builtin.command:\n    cmd: systemctl daemon-reload\n\n- name: Restart containerd service\n  ansible.builtin.service:\n    name: containerd\n    state: restarted<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These tasks configure Containerd for use with Kubernetes. First, it creates a default configuration file for Containerd at&nbsp;<code>\/opt\/containerd\/config.toml<\/code>. Next, it modifies this file to set the&nbsp;<code>SystemdCgroup<\/code>&nbsp;variable to&nbsp;<code>true<\/code>, ensuring that Containerd uses systemd for managing cgroups. Then, it reloads the systemd configuration to apply any changes. Finally, it restarts the Containerd service to ensure that the new configuration is in effect.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>7. Configure Firewall<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Open necessary ports for Kubernetes components:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Allow 6443\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 6443\/tcp\n\n- name: Allow 2379:2380\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 2379:2380\/tcp\n\n- name: Allow 8080\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 8080\/tcp\n\n- name: Allow 22\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 22\/tcp\n\n- name: Allow 10250\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10250\/tcp\n\n- name: Allow 10251\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10251\/tcp\n\n- name: Allow 10252\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10252\/tcp\n\n- name: Allow 10255\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 10255\/tcp\n\n- name: Allow 5473\/tcp through firewall\n  ansible.builtin.command:\n    cmd: sudo ufw allow 5473\/tcp\n\n- name: Enable the firewall\n  ansible.builtin.ufw:\n    state: enabled\n\n- name: Reload the firewall\n  ansible.builtin.command:\n    cmd: sudo ufw reload<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>8. Add Kubernetes Repository<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Add the Kubernetes APT repository and install the Kubernetes components:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Create directory for APT keys\n  file:\n    path: \/etc\/apt\/keyrings\n    state: directory\n    mode: '0755'\n\n- name: Download Kubernetes GPG key securely\n  ansible.builtin.shell: curl -fsSL https:\/\/pkgs.k8s.io\/core:\/stable:\/v1.30\/deb\/Release.key | sudo gpg --dearmor -o \/etc\/apt\/keyrings\/kubernetes-apt-keyring.gpg\n\n- name: Add Kubernetes repository\n  ansible.builtin.apt_repository:\n    repo: \"deb &#91;signed-by=\/etc\/apt\/keyrings\/kubernetes-apt-keyring.gpg] https:\/\/pkgs.k8s.io\/core:\/stable:\/v1.30\/deb\/ \/\"\n    state: present\n\n- name: Install kubeadm, kubelet, kubectl\n  ansible.builtin.apt:\n    name:\n      - kubelet\n      - kubeadm\n      - kubectl\n    state: present\n    update_cache: yes\n\n- name: Hold kubelet, kubeadm, kubectl packages\n  ansible.builtin.command:\n    cmd: sudo apt-mark hold kubelet kubeadm kubectl<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>9. Configure Kubelet<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Set the cgroup driver for Kubelet:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Replace \/etc\/default\/kubelet contents\n  ansible.builtin.copy:\n    dest: \/etc\/default\/kubelet\n    content: 'KUBELET_EXTRA_ARGS=\"--cgroup-driver=cgroupfs\"'\n\n- name: Reload systemd configuration\n  ansible.builtin.command:\n    cmd: systemctl daemon-reload\n\n- name: Restart kubelet service\n  ansible.builtin.service:\n    name: kubelet\n    state: restarted<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These tasks update the configuration for the kubelet service. First, the contents of&nbsp;<code>\/etc\/default\/kubelet<\/code>&nbsp;are replaced to set the&nbsp;<code>KUBELET_EXTRA_ARGS<\/code>&nbsp;environment variable to use the&nbsp;<code>cgroupfs<\/code>&nbsp;cgroup driver. Next, the systemd configuration is reloaded to apply these changes. Finally, the kubelet service is restarted to ensure that it runs with the updated configuration.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>10. Reboot the System<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Reboot the system and confirm all changes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Reboot the system\nansible.builtin.reboot:\n  msg: \"Reboot initiated by Ansible for Kubernetes setup\"\n  reboot_timeout: 150<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is an ideal time to verify that services are running as expected after the reboot and to ensure that configuration changes, such as the disabling of swap, remain in effect.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>\ud83d\udc40<strong>All the tasks reviewed so far apply to both master and worker nodes.&nbsp;The following tasks, starting from Step #11, are intended to run exclusively on the master node.<\/strong><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>11. Configure Docker<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Set Docker daemon options:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Replace Docker daemon.json configuration\n  ansible.builtin.copy:\n    dest: \/etc\/docker\/daemon.json\n    content: |\n      {\n        \"exec-opts\": &#91;\"native.cgroupdriver=systemd\"],\n        \"log-driver\": \"json-file\",\n        \"log-opts\": {\n          \"max-size\": \"100m\"\n        },\n        \"storage-driver\": \"overlay2\"\n      }\n\n- name: Reload systemd configuration\n  ansible.builtin.command:\n    cmd: systemctl daemon-reload\n\n- name: Restart Docker service\n  ansible.builtin.service:\n    name: docker\n    state: restarted<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>12. Update Kubeadm Environment Variable<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Ensure Kubeadm does not fail due to swap:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Update Kubeadm Environment Variable\n  ansible.builtin.command:\n    cmd: sudo sed -i -e '\/^\\&#91;Service\\]\/a Environment=\"KUBELET_EXTRA_ARGS=--fail-swap-on=false\"' \/usr\/lib\/systemd\/system\/kubelet.service.d\/10-kubeadm.conf\n\n- name: Reload systemd configuration\n  ansible.builtin.command:\n    cmd: systemctl daemon-reload\n\n- name: Restart kubelet service\n  ansible.builtin.service:\n    name: kubelet\n    state: restarted<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>13. Pull Kubernetes Container Images<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Pull the required container images:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Pull Kubernetes container images\nansible.builtin.command:\n  cmd: sudo kubeadm config images pull<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>14. Initialize Kubernetes Control Plane<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Initializing the Kubernetes control plane is crucial to the entire installation process. If this step fails, you won\u2019t be able to successfully set up the Kubernetes cluster, as it won\u2019t generate the necessary tokens for joining the worker nodes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Initialize Kubernetes control plane\nansible.builtin.command:\n  cmd: kubeadm init --pod-network-cidr=10.244.0.0\/16\n  creates: \/tmp\/kubeadm_output\nregister: kubeadm_init_output\nbecome: true\nchanged_when: false<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This task initializes the Kubernetes control plane by running the&nbsp;<code>kubeadm init<\/code>&nbsp;command with a specified pod network CIDR. It creates an output file&nbsp;<code>\/tmp\/kubeadm_output<\/code>&nbsp;to store the command\u2019s result, registers this output in the&nbsp;<code>kubeadm_init_output<\/code>&nbsp;variable, and executes the command with elevated privileges. The&nbsp;<code>changed_when: false<\/code>&nbsp;directive indicates that the task\u2019s status is not considered changed, even if it runs successfully.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>15. Store the initialization output<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This task uses the&nbsp;<code>copy<\/code>&nbsp;module to save the output of the Kubernetes initialization command (stored in&nbsp;<code>kubeadm_init_output.stdout<\/code>) to a file at&nbsp;<code>\/tmp\/kubeadm_output<\/code>&nbsp;on the control node. The&nbsp;<code>become: true<\/code>&nbsp;directive ensures that the task is executed with elevated privileges, and&nbsp;<code>delegate_to: localhost<\/code>&nbsp;specifies that the task should be run on the local control node.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Store Kubernetes initialization output to file\ncopy:\n  content: \"{{ kubeadm_init_output.stdout }}\"\n  dest: \/tmp\/kubeadm_output\nbecome: true\ndelegate_to: localhost<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>16. Generate the Join Token<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">To generate the join command from the Kubernetes initialization output and store it in&nbsp;<code>\/tmp\/join-command<\/code>, you can use the following Ansible task:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Generate the Join Command\nansible.builtin.shell: cat \/tmp\/kubeadm_output | tail -n 2 | sed ':a;N;$!ba;s\/\\\\\\n\\s*\/ \/g' &gt; \/tmp\/join-command\ndelegate_to: localhost<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This task does the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Uses\u00a0<code><strong>ansible.builtin.shell<\/strong><\/code>\u00a0module to execute a shell command on the\u00a0<strong>control node<\/strong>\u00a0(localhost).<\/li>\n\n\n\n<li>Reads the last two lines of the file\u00a0<code><strong>\/tmp\/kubeadm_output<\/strong><\/code>\u00a0using\u00a0<code><strong>tail -n 2<\/strong><\/code>.<\/li>\n\n\n\n<li>Uses\u00a0<code><strong>sed<\/strong><\/code>\u00a0to remove line breaks (<code><strong>\\\\\\n<\/strong><\/code>) and concatenate the lines into a single line.<\/li>\n\n\n\n<li>Redirects the output to\u00a0<code><strong>\/tmp\/join-command<\/strong><\/code><strong>.<\/strong><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>17. Make the join-command file executable<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">To set permissions for the join command executable (<code>\/tmp\/join-command<\/code>), ensuring it has the correct mode (755), you can use the following Ansible task:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Set permissions for the Join Executable\nfile:\n  path: \/tmp\/join-command\n  state: file\n  mode: '0755'\ndelegate_to: localhost<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">It ensures that&nbsp;<code><strong>\/tmp\/join-command<\/strong><\/code>&nbsp;is executable by its owner and suitable for executing the Kubernetes join command.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>18. Configuring Kubernetes Network Environment<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The provided Ansible tasks are designed for configuring networking in a Kubernetes environment. The first task installs the Flannel network plugin using&nbsp;<strong><code>kubectl apply<\/code><\/strong>, ensuring network connectivity and pod communication within the cluster.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The second task taints the Kubernetes master node to prevent scheduling of workloads on it, which is a common practice to reserve the master node exclusively for control plane operations rather than running user workloads. These tasks are typically executed with elevated privileges (<code><strong>su - $ANSIBLE_USER<\/strong><\/code>) to ensure proper access and execution permissions within the Kubernetes environment managed by Ansible.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>---\n# tasks file for kubernetes_network\n- name: Install Flannel network plugin\n  ansible.builtin.shell: su - $ANSIBLE_USER -c \"kubectl apply -f https:\/\/raw.githubusercontent.com\/coreos\/flannel\/master\/Documentation\/kube-flannel.yml\"\n\n- name: Taint master node to prevent workload scheduling\n  ansible.builtin.shell: su - $ANSIBLE_USER -c \"kubectl taint nodes --all node-role.kubernetes.io\/control-plane-\"<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>19. Copy Join-command executable to worker nodes<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This task ensures that the&nbsp;<code>join-command<\/code>&nbsp;file is copied to the destination&nbsp;<code>\/tmp\/join-command<\/code>&nbsp;on the worker nodes with executable permissions (mode&nbsp;<code>0755<\/code>).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Copy join-command file to worker nodes\ncopy:\n  src: \/tmp\/join-command\n  dest: \/tmp\/join-command\n  mode: 0755<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>20. Join Worker Nodes<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The&nbsp;<code>join-command<\/code>&nbsp;file contains the&nbsp;<code>kubeadm join<\/code>&nbsp;command needed to join the worker nodes to the Kubernetes cluster:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Join Worker Nodes\nansible.builtin.shell: sh \/tmp\/join-command\nbecome: yes<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Install Kubernetes Using Ansible on Ubuntu 24.04: Playbook execution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now that we have reviewed each Ansible role necessary for configuring a Kubernetes cluster, we will proceed with executing the playbook. Please note that this process may take anywhere from 10 to 15 minutes to complete, depending on your network and system resources.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible-playbook -i hosts site.yml -K<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The command&nbsp;<code>ansible-playbook<\/code>&nbsp;is used to run a playbook with specific options. Here\u2019s a breakdown of each part of the command:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Command Option<\/th><th>Description<\/th><\/tr><\/thead><tbody><tr><td><code><strong>ansible-playbook<\/strong><\/code><\/td><td>This is the Ansible command used to run playbooks. A playbook is a file containing a series of tasks that Ansible will execute on the specified hosts.<\/td><\/tr><tr><td><code><strong>-i hosts<\/strong><\/code><\/td><td>The&nbsp;<code>-i<\/code>&nbsp;option specifies the inventory file. In this case,&nbsp;<code>hosts<\/code>&nbsp;is the inventory file that lists the target hosts and their groupings. This file tells Ansible which machines to run the tasks on.<\/td><\/tr><tr><td><strong><code>site.yml<\/code><\/strong><\/td><td>This is the name of the playbook file.&nbsp;<code>site.yml<\/code>&nbsp;contains the tasks and roles that Ansible will execute on the specified hosts.<\/td><\/tr><tr><td><code><strong>-K<\/strong><\/code><\/td><td>This option prompts the user for the sudo password. It stands for&nbsp;<strong>\u201cask for privilege escalation password.\u201d<\/strong>&nbsp;This is necessary when tasks in the playbook require elevated privileges (sudo) to execute.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Putting it all together, this command runs the&nbsp;<strong><code>site.yml<\/code><\/strong>&nbsp;playbook on the hosts specified in the&nbsp;<code>hosts<\/code>&nbsp;inventory file, and it will prompt you to enter the sudo password to execute tasks that require elevated privileges.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/infotechys.com\/wp-content\/uploads\/2024\/10\/running_ansible_playbook.webp\" alt=\"Install Kubernetes Using Ansible on Ubuntu 24.04\" class=\"wp-image-34027\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Photo by&nbsp;<a href=\"https:\/\/infotechys.com\/install-kubernetes-using-ansible-on-ubuntu-24-04\" target=\"_blank\" rel=\"noreferrer noopener\">admingeek<\/a>&nbsp;from&nbsp;<a href=\"https:\/\/infotechys.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Infotechys<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Post-Install Verification<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Once the playbook has finished running, there are several ways to verify if we have successfully configured a Kubernetes cluster.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/infotechys.com\/wp-content\/uploads\/2024\/10\/finished_playbook_recap.webp\" alt=\"Install Kubernetes Using Ansible on Ubuntu 24.04\" class=\"wp-image-34112\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Photo by&nbsp;<a href=\"https:\/\/infotechys.com\/install-kubernetes-using-ansible-on-ubuntu-24-04\" target=\"_blank\" rel=\"noreferrer noopener\">admingeek<\/a>&nbsp;from&nbsp;<a href=\"https:\/\/infotechys.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Infotechys<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Use Kubectl Commands<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">SSH to the&nbsp;<strong>master node<\/strong>&nbsp;and run the following command to check the status of the nodes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get nodes<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME                    STATUS   ROLES           AGE   VERSION\nmaster.naijalabs.net    Ready    control-plane   37m   v1.30.2\nworker1.naijalabs.net   Ready    &lt;none&gt;          32m   v1.30.2\nworker2.naijalabs.net   Ready    &lt;none&gt;          32m   v1.30.2\nworker3.naijalabs.net   Ready    &lt;none&gt;          32m   v1.30.2<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Additionally, you can list the pods in all namespaces with this command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods --all-namespaces<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>NAMESPACE      NAME                                           READY   STATUS    RESTARTS   AGE\nkube-flannel   kube-flannel-ds-f67vw                          1\/1     Running   0          36m\nkube-flannel   kube-flannel-ds-f6mr2                          1\/1     Running   0          36m\nkube-flannel   kube-flannel-ds-mvdvf                          1\/1     Running   0          41m\nkube-flannel   kube-flannel-ds-r96dj                          1\/1     Running   0          36m\nkube-system    coredns-7db6d8ff4d-cq9wq                       1\/1     Running   0          41m\nkube-system    coredns-7db6d8ff4d-n5h8d                       1\/1     Running   0          41m\nkube-system    etcd-master.naijalabs.net                      1\/1     Running   0          41m\nkube-system    kube-apiserver-master.naijalabs.net            1\/1     Running   0          41m\nkube-system    kube-controller-manager-master.naijalabs.net   1\/1     Running   0          41m\nkube-system    kube-proxy-4b8tj                               1\/1     Running   0          36m\nkube-system    kube-proxy-dflsd                               1\/1     Running   0          36m\nkube-system    kube-proxy-nclxg                               1\/1     Running   0          41m\nkube-system    kube-proxy-vrl9s                               1\/1     Running   0          36m\nkube-system    kube-scheduler-master.naijalabs.net            1\/1     Running   0          41m<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Run this command to view services:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get services<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE\nkubernetes   ClusterIP   10.96.0.1    &lt;none&gt;        443\/TCP   10h<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Dashboard Access<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;Access the Kubernetes dashboard (if installed) through a web browser:&nbsp;<a href=\"http:\/\/localhost:8001\/api\/v1\/namespaces\/kubernetes-dashboard\/services\/https:kubernetes-dashboard:\/proxy\/\" target=\"_blank\" rel=\"noreferrer noopener\">http:\/\/localhost:8001\/api\/v1\/namespaces\/kubernetes-dashboard\/services\/https:kubernetes-dashboard:\/proxy<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl proxy<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Starting to serve on 127.0.0.1:8001<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/infotechys.com\/wp-content\/uploads\/2024\/10\/kubernetes_dashboard.webp\" alt=\"Install Kubernetes Using Ansible on Ubuntu 24.04\" class=\"wp-image-34172\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Photo by&nbsp;<a href=\"https:\/\/infotechys.com\/install-kubernetes-using-ansible-on-ubuntu-24-04\" target=\"_blank\" rel=\"noreferrer noopener\">admingeek<\/a>&nbsp;from&nbsp;<a href=\"https:\/\/infotechys.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Infotechys<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Cluster API Responses<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Verify responses from the Kubernetes API server using&nbsp;<code><strong>kubectl<\/strong><\/code>&nbsp;or directly accessing the API endpoint:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl cluster-info<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Kubernetes control plane is running at https:\/\/192.168.1.169:6443\nCoreDNS is running at https:\/\/192.168.1.169:6443\/api\/v1\/namespaces\/kube-system\/services\/kube-dns:dns\/proxy<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Get API versions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl api-versions<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>admissionregistration.k8s.io\/v1\napiextensions.k8s.io\/v1\napiregistration.k8s.io\/v1\napps\/v1\nauthentication.k8s.io\/v1\nauthorization.k8s.io\/v1\nautoscaling\/v1\nautoscaling\/v2\nbatch\/v1\ncertificates.k8s.io\/v1\n...omitted for brevity...<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">View Kubernetes configuration:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl config view<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nclusters:\n- cluster:\n    certificate-authority-data: DATA+OMITTED\n    server: https:\/\/192.168.1.169:6443\n  name: kubernetes\ncontexts:\n- context:\n    cluster: kubernetes\n    user: kubernetes-admin\n  name: kubernetes-admin@kubernetes\ncurrent-context: kubernetes-admin@kubernetes\nkind: Config\npreferences: {}\nusers:\n- name: kubernetes-admin\n  user:\n    client-certificate-data: DATA+OMITTED\n    client-key-data: DATA+OMITTED<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These methods provide comprehensive ways to ensure that the Kubernetes cluster is operational and configured correctly after running the playbook.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Congratulations! You\u2019ve successfully completed the automated deployment of a Kubernetes cluster using Ansible. If you\u2019ve reached this point, you might be interested in exploring further. This exercise is designed to spark your interest by introducing Kubernetes from a beginner\u2019s perspective. To make this cluster truly&nbsp;<strong>\u201cproduction-ready,\u201d<\/strong>&nbsp;additional customizations are necessary, and we\u2019ve only just scratched the surface with the information covered here. Be sure to check out the provided resources for troubleshooting and more in-depth tutorials.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Did you find this article useful? Your feedback is invaluable to us! Please feel free to share your thoughts in the comments section below.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Additional Resources<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here are some helpful links to help you along your automation journey!<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong><a href=\"https:\/\/kubernetes.io\/docs\/home\" target=\"_blank\" rel=\"noreferrer noopener\">Kubernetes Documentation<\/a><\/strong><\/td><td>The official page for Kubernetes<\/td><\/tr><tr><td><a href=\"https:\/\/github.com\/elastic\/elasticsearch\/blob\/7.8\/libs\/grok\/src\/main\/resources\/patterns\/grok-patterns\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Ansible Documentation<\/strong><\/a><\/td><td>The official page for Ansible<\/td><\/tr><tr><td><a href=\"https:\/\/github.com\/flannel-io\/flannel\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Flannel Documentation<\/strong><\/a><\/td><td>The GitHub resource page for Flannel<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">By following this comprehensive guide, you are well on your way to deploying a scalable and efficient Kubernetes cluster on Ubuntu 24.04 using Ansible roles.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Glossary Terms<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Idempotent<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In the context of Ansible,<strong>&nbsp;\u201cidempotent\u201d<\/strong>&nbsp;refers to the ability of tasks to be run multiple times without changing the result beyond the initial application. An idempotent operation ensures that no matter how many times it is executed, the system\u2019s state will remain the same after the first application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In other words, if you apply an idempotent Ansible playbook or task to a system that is already in the desired state, the playbook or task will not make any changes or perform any actions. This is crucial for configuration management and automation, as it ensures that repeated runs of a playbook will not lead to unintended side effects or changes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here\u2019s why idempotence is important in Ansible:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Consistency<\/strong>:&nbsp;Ensures the system remains in the desired state, even if the playbook is run multiple times.<strong>Reliability<\/strong>:&nbsp;Reduces the risk of errors and unintended changes during repeated executions.<strong>Ease of Management<\/strong>:&nbsp;Simplifies the management of system configurations, as administrators can rerun playbooks without worrying about causing disruptions.<strong>Automation<\/strong>:&nbsp;Facilitates the automation of system configuration and updates, making it easier to maintain large-scale deployments.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to install Kubernetes using Ansible on Ubuntu 24.04. This comprehensive guide covers prerequisites, setup, and configuration, ensuring a streamlined and consistent deployment process. Introduction Deploying Kubernetes on Ubuntu 24.04 can be a complex task. However, using Ansible roles simplifies this process significantly. Ansible, an open-source automation tool, allows you to automate and manage [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-20","post","type-post","status-publish","format-standard","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/20","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=20"}],"version-history":[{"count":4,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/20\/revisions"}],"predecessor-version":[{"id":26,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/20\/revisions\/26"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=20"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=20"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=20"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}