Onur Yasarlar
Search…
Installing Prerequisites for Kubernetes Cluster Installation

Getting Started

If you want to install a Kubernetes cluster, you need to meet the following prerequisites before you start your actual work. Below requirements are taken from the official website:
  • One or more machines running one of:
    • Ubuntu 16.04+
    • Debian 9+
    • CentOS 7
    • Red Hat Enterprise Linux (RHEL) 7
    • Fedora 25+
    • HypriotOS v1.0.1+
    • Flatcar Container Linux (tested with 2512.3.0)
  • 2 GB or more of RAM per machine (any less will leave little room for your apps).
  • 2 CPUs or more.
  • Full network connectivity between all machines in the cluster (public or private network is fine).
  • Unique hostname, MAC address, and product_uuid for every node. See here for more details.
  • Certain ports are open on your machines. See here for more details.
  • Swap disabled. You MUST disable swap in order for the kubelet to work properly.
I will try to cover CentOS 7 and Ubuntu 18.04 / 20.04 under that post. So let's write an Ansible role to cover the prerequisites.
Kubernetes cluster installation and configuration require certain prerequisites to be done in advance. I divided those prerequisites into 3 categories in my role:
  1. 1.
    Swap
  2. 2.
    SELinux
  3. 3.
    Firewall
I prefer to keep the above specific tasks into their own yaml files and import them in the role's main file. You can find the Ansible role here.

Disabling Swap

If you fail to disable swap space before your Kubernetes cluster setup, it will throw an ugly error and will ask you to disable it. Disabling swap space looks straightforward but if you want to automate it, it can be a tricky task because you can have either a swap volume or a file. There is also another risk that if you remove the swap logical volume and if your GRUB configuration expects for it, your server will not boot up after the first reboot. That's why I decided to only disable swap and uncomment it in the /etc/fstab file and let the administrators handle it properly if they want to reclaim the swap space.
I am disabling swap space in a separate playbook as below:
tasks/disable_swap.yaml
1
---
2
- name: Disable swap
3
command: swapoff -a
4
when: ansible_swaptotal_mb > 0
5
tags:
6
- skip_ansible_lint
7
8
# Removing swap LV can cause issues if your grub dependant in it
9
# I will only comment it out
10
- name: Remove swap from fstab
11
replace:
12
path: /etc/fstab
13
regexp: '^([^#].*?\sswap\s.*)#x27;
14
replace: '# \1'
15
16
- name: Remove swap file if exists
17
file:
18
path: "{{ swapfile_path }}"
19
state: absent
20
Copied!
Please pay attention to the swapfile_path variable in the vars/main.yml file and change it accordingly.
Please note that swap needs to be disabled on both control and worker nodes

Disable SELinux

I call the title of the section "disable" but I prefer to put SELinux into permissive mode. Since SELinux status is a variable (either permissive or disabled ), I kept it in vars/main.yml file as below:
vars/main.yml
1
selinux_policy: "targeted"
2
selinux_state: "permissive"
Copied!
Ubuntu servers do not come with SELinux by default, so I decided to touch SELinux configuration only if its configuration file exists. The playbook to handle SELinux tasks will be like below:
tasks/selinux.yaml
1
---
2
- name: Check if SElinux config exists
3
stat:
4
path: /etc/selinux/config
5
register: selinux_config
6
7
- name: Make SELinux permissive if not disabled
8
selinux:
9
policy: "{{ selinux_policy }}"
10
state: "{{ selinux_state }}"
11
when: selinux_config.stat.exists
12
Copied!
Please note that. SELinux needs to be disabled on both control and worker nodes.

Enable Firewall Rules for Control and Worker Nodes

There are some ports to be enabled on both the control plane and worker nodes. The list of ports can be also found here.

Control-plane node(s)

Protocol
Direction
Port Range
Purpose
Used By
TCP
Inbound
6443*
Kubernetes API server
All
TCP
Inbound
2379-2380
etcd server client API
kube-apiserver, etcd
TCP
Inbound
10250
kubelet API
Self, Control plane
TCP
Inbound
10251
kube-scheduler
Self
TCP
Inbound
10252
kube-controller-manager
Self

Worker node(s)

Protocol
Direction
Port Range
Purpose
Used By
TCP
Inbound
10250
kubelet API
Self, Control plane
TCP
Inbound
30000-32767
NodePort Services†
All
CentOS servers by default use firewalld and Ubuntu servers use ufw to manage firewall rules. I will not make any exception here and assume you are using the default services. Then the playbook will look like below:
tasks/firewall.yaml
1
---
2
- name: Allow firewall for Control-plane node(s)
3
block:
4
- name: CentOS Control-plane node(s) firewall rules
5
firewalld:
6
port: "{{ item }}"
7
permanent: yes
8
state: enabled
9
loop:
10
- 6443/tcp
11
- 2379-2380/tcp
12
- 10250/tcp
13
- 10251/tcp
14
- 10252/tcp
15
when: ansible_distribution | lower == "centos"
16
17
- name: Ubuntu Control-plane node(s) firewall rules
18
community.general.ufw:
19
rule: allow
20
port: "{{ item }}"
21
proto: tcp
22
loop:
23
- 6443
24
- 2379:2380
25
- 10250
26
- 10251
27
- 10252
28
when: ansible_distribution | lower == "ubuntu"
29
when: inventory_hostname in groups['master']
30
31
- name: Allow firewall for Worker node(s)
32
block:
33
- name: CentOS Worker node(s) firewall rules
34
firewalld:
35
port: "{{ item }}"
36
permanent: yes
37
state: enabled
38
loop:
39
- 10250/tcp
40
- 30000-32767/tcp
41
when: ansible_distribution | lower == "centos"
42
43
- name: Ubuntu Worker node(s) firewall rules
44
community.general.ufw:
45
rule: allow
46
port: "{{ item }}"
47
proto: tcp
48
loop:
49
- 10250
50
- 30000:32767
51
when: ansible_distribution | lower == "ubuntu"
52
when: inventory_hostname in groups['node']
53
Copied!

Putting things together

Now we are ready to put things together.
Please note that the control plane nodes should be under master group in the inventory file and worker nodes should be in node group.
What we need to do is relatively simple now. We just need to include our tasks in the main playbook like below:
tasks/main.yml
1
---
2
# tasks file for ansible-role-k8s_prereq
3
- name: Setting OS version fact
4
set_fact:
5
osversion: "{{ ansible_distribution | lower }}{{ ansible_distribution_major_version }}"
6
7
- name: Check OS version
8
fail:
9
msg: "OS Version( {{ ansible_distribution }}{{ ansible_distribution_major_version }} ) is not certified for the role"
10
when:
11
- osversion != "ubuntu20"
12
- osversion != "ubuntu18"
13
- osversion != "centos7"
14
15
- name: Disable swap
16
include_tasks: disable_swap.yaml
17
18
- name: Disable SELinux
19
include_tasks: selinux.yaml
20
21
- name: Apply firewall rules
22
include_tasks: firewall.yaml
Copied!
Now we are ready to install the container runtime interface.
Last modified 1yr ago