Ansible Kubernetes Cluster
This page will demonstrate how to setup a Kubernetes Cluster using Ansible.
Note
I am using TechnoTim's k3s-ansible ansible role.
Ansible Project Setup
Fetch the repository:
pushd /tmp
git clone https://github.com/techno-tim/k3s-ansible && cd k3s-ansible
git checkout v1.25.9+k3s1
cd ..
Create the directory structure for the cluster:
Copy content across:
cp -R k3s-ansible/inventory/sample k3s-cluster/inventory/sektorlab
cp -R k3s-ansible/collections k3s-cluster/collections
cp -R k3s-ansible/example k3s-cluster/example
cp -R k3s-ansible/roles k3s-cluster/roles
cp -R k3s-ansible/ansible.example.cfg k3s-cluster/ansible.cfg
cp -R k3s-ansible/*.yml k3s-cluster/
Configure ansible.cfg
:
cat > k3s-cluster/ansible.cfg << EOF
[defaults]
inventory = inventory/sektorlab/hosts.ini
host_key_checking = False
timeout = 60
EOF
Configure inventory with the nodes that we provisioned in Proxmox:
cat > k3s-cluster/inventory/sektorlab/hosts.ini << EOF
[master]
10.8.0.101
10.8.0.102
10.8.0.103
[node]
10.8.0.104
10.8.0.105
10.8.0.106
[k3s_cluster:children]
master
node
EOF
In inventory/sektorlab/group_vars/all.yml
we need to configure a couple of configuration options, which we enable metallb, we define the address of our api server, and the range of addresses that metallb will use, etc:
---
k3s_version: v1.25.12+k3s1
ansible_user: ruan
systemd_dir: /etc/systemd/system
system_timezone: "Africa/Johannesburg"
# interface which will be used for flannel
flannel_iface: "ens18"
# apiserver_endpoint is virtual ip-address which will be configured on each master
apiserver_endpoint: "10.8.0.100"
# k3s_token is required masters can talk together securely
# this token should be alpha numeric only
k3s_token: "x0x0x0x0x" # make sure to change this
# The IP on which the node is reachable in the cluster.
k3s_node_ip: '{{ ansible_facts[flannel_iface]["ipv4"]["address"] }}'
# Disable the taint manually by setting: k3s_master_taint = false
k3s_master_taint: "{{ true if groups['node'] | default([]) | length >= 1 else false }}"
# these arguments are recommended for servers as well as agents:
extra_args: >-
--flannel-iface={{ flannel_iface }}
--node-ip={{ k3s_node_ip }}
# change these to your liking, the only required are: --disable servicelb, --tls-san {{ apiserver_endpoint }}
extra_server_args: >-
{{ extra_args }}
{{ '--node-taint node-role.kubernetes.io/master=true:NoSchedule' if k3s_master_taint else '' }}
--tls-san {{ apiserver_endpoint }}
--disable servicelb
--disable traefik
--write-kubeconfig-mode 644
--kube-apiserver-arg default-not-ready-toleration-seconds=30
--kube-apiserver-arg default-unreachable-toleration-seconds=30
--kube-controller-arg node-monitor-period=20s
--kube-controller-arg node-monitor-grace-period=20s
--kubelet-arg node-status-update-frequency=5s
extra_agent_args: >-
{{ extra_args }}
--kubelet-arg node-status-update-frequency=5s
# image tag for kube-vip
kube_vip_tag_version: "v0.5.12"
# metallb type frr or native
metal_lb_type: "native"
# metallb mode layer2 or bgp
metal_lb_mode: "layer2"
# image tag for metal lb
metal_lb_speaker_tag_version: "v0.13.9"
metal_lb_controller_tag_version: "v0.13.9"
# metallb ip range for load balancer
metal_lb_ip_range: "10.8.0.110-10.8.0.115"
in .gitlab-ci.yml
set:
default:
tags:
- sektorlab
stages:
- deploy
kubernetes:deploy:
stage: deploy
image: ruanbekker/ansible:2.12.5-kubernetes
variables:
ANSIBLE_CONFIG: $CI_PROJECT_DIR/ansible.cfg
ROLES_REQUIREMENTS_FILE: $CI_PROJECT_DIR/collections/requirements.yml
EXTERNAL_ROLE_DIR: $CI_PROJECT_DIR/roles
ANSIBLE_COLLECTIONS_PATH: $CI_PROJECT_DIR/roles
script:
- ansible-galaxy install -r "$ROLES_REQUIREMENTS_FILE" -p "$EXTERNAL_ROLE_DIR"
- ansible-playbook -e "ansible_ssh_user=ruan ansible_ssh_pass=$ANSIBLE_PASSWORD" site.yml
only:
- /^kubernetes-.*$/
And make sure ANSIBLE_PASSWORD
is defined in the CICD variables.
Then tag the commit:
cd k3s-cluster
git add .
git commit -m "initial"
git tag -f kubernetes-v1.25.12
git push origin -f kubernetes-v1.25.12
Kubeconfig Setup
To access the kubeconfig, ssh to one of the master nodes and view the file:
You will need to replace server: https://127.0.0.1:6443
with the address of your apiserver endpoint, in my case server: https://10.8.0.100:6443
and the store it on your local workstation at ~/.kube/config
and set it to:
Then view your nodes:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready control-plane,etcd,master 2d v1.25.12+k3s1
node2 Ready control-plane,etcd,master 2d v1.25.12+k3s1
node3 Ready control-plane,etcd,master 2d v1.25.12+k3s1
node4 Ready <none> 2d v1.25.12+k3s1
node5 Ready <none> 2d v1.25.12+k3s1
node6 Ready <none> 2d v1.25.12+k3s1