infra/home/ansible/deploy-k3s.yml
2025-09-06 10:55:13 -05:00

416 lines
No EOL
11 KiB
YAML

---
- name: Prepare K3s nodes
hosts: k3s_cluster
become: true
tasks:
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
when: ansible_os_family == "Debian"
- name: Install curl
package:
name: curl
state: present
- name: Configure DNS
copy:
content: |
nameserver 9.9.9.9
nameserver 149.112.112.112
nameserver 1.1.1.1
dest: /etc/resolv.conf
backup: yes
- name: Test DNS resolution
command: nslookup github.com
changed_when: false
register: dns_test
failed_when: false
- name: Show DNS test result
debug:
var: dns_test.stdout_lines
when: dns_test.rc != 0
- name: Load required kernel modules
modprobe:
name: "{{ item }}"
state: present
loop:
- br_netfilter
- overlay
- wireguard
ignore_errors: yes # Wireguard module may not exist in Debian 13
- name: Persist kernel modules
copy:
content: |
br_netfilter
overlay
wireguard
dest: /etc/modules-load.d/k3s.conf
- name: Set sysctl parameters
sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
state: present
sysctl_file: /etc/sysctl.d/k3s.conf
reload: yes
loop:
- { name: 'net.bridge.bridge-nf-call-iptables', value: '1' }
- { name: 'net.bridge.bridge-nf-call-ip6tables', value: '1' }
- { name: 'net.ipv4.ip_forward', value: '1' }
- { name: 'net.ipv6.conf.all.forwarding', value: '1' }
- name: Download k3s binary
hosts: k3s_cluster
become: true
tasks:
- name: Download k3s binary
get_url:
url: https://github.com/k3s-io/k3s/releases/download/{{ k3s_version }}/k3s
dest: /usr/local/bin/k3s
mode: '0755'
- name: Deploy first control plane node
hosts: home-k3s-control-1
become: true
tasks:
- name: Create k3s config directory
file:
path: /etc/rancher/k3s
state: directory
mode: '0755'
- name: Create k3s server config
copy:
content: |
cluster-init: true
disable:
- servicelb
- traefik
cluster-cidr: 10.42.0.0/16
service-cidr: 10.43.0.0/16
cluster-dns: 10.43.0.10
flannel-backend: vxlan
write-kubeconfig-mode: "0644"
tls-san:
- "{{ ansible_host }}"
- "{{ ansible_hostname }}"
dest: /etc/rancher/k3s/config.yaml
- name: Create k3s systemd service
copy:
content: |
[Unit]
Description=Lightweight Kubernetes
Documentation=https://k3s.io
Wants=network-online.target
After=network-online.target
[Service]
Type=notify
EnvironmentFile=-/etc/default/%N
EnvironmentFile=-/etc/sysconfig/%N
KillMode=process
Delegate=yes
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
TimeoutStartSec=0
Restart=always
RestartSec=5s
ExecStartPre=/bin/sh -xc '! /usr/bin/systemctl is-enabled --quiet nm-cloud-setup.service'
ExecStartPre=-/sbin/modprobe br_netfilter
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/k3s server
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/k3s.service
- name: Start k3s on first control plane
systemd:
name: k3s
daemon_reload: yes
enabled: yes
state: started
- name: Wait for node token
wait_for:
path: /var/lib/rancher/k3s/server/node-token
timeout: 120
- name: Read node token
slurp:
src: /var/lib/rancher/k3s/server/node-token
register: node_token
- name: Set token fact
set_fact:
k3s_token: "{{ node_token.content | b64decode | trim }}"
- name: Wait for k3s to be ready
command: /usr/local/bin/k3s kubectl get nodes
register: nodes_result
until: nodes_result.rc == 0
retries: 30
delay: 10
changed_when: false
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Check k3s service status
command: systemctl status k3s
register: k3s_status
changed_when: false
failed_when: false
- name: Show k3s logs if not ready
command: journalctl -u k3s -n 50 --no-pager
register: k3s_logs
when: nodes_result.rc != 0
changed_when: false
- name: Display logs
debug:
var: k3s_logs.stdout_lines
when: k3s_logs is defined
- name: Deploy additional control plane nodes
hosts: k3s_control:!home-k3s-control-1
become: true
serial: 1
tasks:
- name: Create k3s config directory
file:
path: /etc/rancher/k3s
state: directory
mode: '0755'
- name: Create k3s server config for additional control planes
copy:
content: |
server: https://{{ hostvars['home-k3s-control-1']['ansible_host'] }}:6443
token: {{ hostvars['home-k3s-control-1']['k3s_token'] }}
disable:
- servicelb
- traefik
cluster-cidr: 10.42.0.0/16
service-cidr: 10.43.0.0/16
cluster-dns: 10.43.0.10
flannel-backend: vxlan
write-kubeconfig-mode: "0644"
tls-san:
- "{{ ansible_host }}"
- "{{ ansible_hostname }}"
dest: /etc/rancher/k3s/config.yaml
- name: Create k3s systemd service
copy:
content: |
[Unit]
Description=Lightweight Kubernetes
Documentation=https://k3s.io
Wants=network-online.target
After=network-online.target
[Service]
Type=notify
EnvironmentFile=-/etc/default/%N
EnvironmentFile=-/etc/sysconfig/%N
KillMode=process
Delegate=yes
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
TimeoutStartSec=0
Restart=always
RestartSec=5s
ExecStartPre=/bin/sh -xc '! /usr/bin/systemctl is-enabled --quiet nm-cloud-setup.service'
ExecStartPre=-/sbin/modprobe br_netfilter
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/k3s server
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/k3s.service
- name: Start k3s on additional control planes
systemd:
name: k3s
daemon_reload: yes
enabled: yes
state: started
- name: Deploy worker nodes
hosts: k3s_workers
become: true
tasks:
- name: Create k3s config directory
file:
path: /etc/rancher/k3s
state: directory
mode: '0755'
- name: Create k3s agent config
copy:
content: |
server: https://{{ hostvars['home-k3s-control-1']['ansible_host'] }}:6443
token: {{ hostvars['home-k3s-control-1']['k3s_token'] }}
dest: /etc/rancher/k3s/config.yaml
- name: Create k3s-agent systemd service
copy:
content: |
[Unit]
Description=Lightweight Kubernetes
Documentation=https://k3s.io
Wants=network-online.target
After=network-online.target
[Service]
Type=notify
EnvironmentFile=-/etc/default/%N
EnvironmentFile=-/etc/sysconfig/%N
KillMode=process
Delegate=yes
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
TimeoutStartSec=0
Restart=always
RestartSec=5s
ExecStartPre=/bin/sh -xc '! /usr/bin/systemctl is-enabled --quiet nm-cloud-setup.service'
ExecStartPre=-/sbin/modprobe br_netfilter
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/k3s agent
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/k3s-agent.service
- name: Start k3s-agent on workers
systemd:
name: k3s-agent
daemon_reload: yes
enabled: yes
state: started
- name: Configure kubectl access
hosts: home-k3s-control-1
become: true
tasks:
- name: Create kubectl symlink
file:
src: /usr/local/bin/k3s
dest: /usr/local/bin/kubectl
state: link
- name: Create crictl symlink
file:
src: /usr/local/bin/k3s
dest: /usr/local/bin/crictl
state: link
- name: Create .kube directory for user
file:
path: "/home/{{ ansible_user }}/.kube"
state: directory
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0755'
- name: Copy kubeconfig to user
copy:
src: /etc/rancher/k3s/k3s.yaml
dest: "/home/{{ ansible_user }}/.kube/config"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0600'
remote_src: yes
- name: Fetch kubeconfig
fetch:
src: /etc/rancher/k3s/k3s.yaml
dest: "{{ playbook_dir }}/kubeconfig"
flat: yes
- name: Update kubeconfig server URL
replace:
path: "{{ playbook_dir }}/kubeconfig"
regexp: 'server: https://127.0.0.1:6443'
replace: 'server: https://{{ ansible_host }}:6443'
delegate_to: localhost
become: false
- name: Apply MetalLB configuration
hosts: home-k3s-control-1
become: true
tasks:
- name: Wait for MetalLB namespace
command: /usr/local/bin/k3s kubectl get namespace metallb-system
register: metallb_ns
until: metallb_ns.rc == 0
retries: 60
delay: 5
changed_when: false
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Wait for MetalLB controller deployment
command: /usr/local/bin/k3s kubectl -n metallb-system wait --for=condition=available --timeout=300s deployment/controller
changed_when: false
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Create MetalLB IP pool manifest
copy:
content: |
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: home-pool
namespace: metallb-system
spec:
addresses:
- 10.0.19.1-10.0.19.99
dest: /tmp/metallb-pool.yaml
- name: Apply MetalLB IP pool
command: /usr/local/bin/k3s kubectl apply -f /tmp/metallb-pool.yaml
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Create MetalLB L2 advertisement manifest
copy:
content: |
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: home-l2
namespace: metallb-system
spec:
ipAddressPools:
- home-pool
dest: /tmp/metallb-l2.yaml
- name: Apply MetalLB L2 advertisement
command: /usr/local/bin/k3s kubectl apply -f /tmp/metallb-l2.yaml
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Clean up manifests
file:
path: "{{ item }}"
state: absent
loop:
- /tmp/metallb-pool.yaml
- /tmp/metallb-l2.yaml