300 lines
No EOL
8.2 KiB
YAML
300 lines
No EOL
8.2 KiB
YAML
---
|
|
# Playbook to deploy a 3-node Kubernetes cluster on Proxmox
|
|
# This creates VMs on Proxmox and then installs K8s
|
|
|
|
- name: Create VMs on Proxmox
|
|
hosts: proxmox
|
|
gather_facts: yes
|
|
vars:
|
|
k8s_nodes:
|
|
- name: k8s-master
|
|
vmid: 200
|
|
cores: 2
|
|
memory: 4096
|
|
disk: 40
|
|
ip: 10.0.19.200/24
|
|
- name: k8s-worker1
|
|
vmid: 201
|
|
cores: 2
|
|
memory: 4096
|
|
disk: 40
|
|
ip: 10.0.19.201/24
|
|
- name: k8s-worker2
|
|
vmid: 202
|
|
cores: 2
|
|
memory: 4096
|
|
disk: 40
|
|
ip: 10.0.19.202/24
|
|
template_vmid: 9000 # Your cloud-init template
|
|
gateway: 10.0.19.254
|
|
nameserver: 10.0.19.254
|
|
storage: local-lvm
|
|
network_bridge: vmbr0
|
|
|
|
tasks:
|
|
- name: Clone VMs from template
|
|
community.general.proxmox_kvm:
|
|
api_user: root@pam
|
|
api_password: "{{ proxmox_password }}"
|
|
api_host: "{{ ansible_host | default(ansible_default_ipv4.address) }}"
|
|
clone: "{{ template_vmid }}"
|
|
name: "{{ item.name }}"
|
|
vmid: "{{ item.vmid }}"
|
|
node: "{{ ansible_hostname }}"
|
|
storage: "{{ storage }}"
|
|
timeout: 300
|
|
loop: "{{ k8s_nodes }}"
|
|
when: ansible_hostname == "lab01" # Create all VMs on first host
|
|
|
|
- name: Configure VM resources
|
|
community.general.proxmox_kvm:
|
|
api_user: root@pam
|
|
api_password: "{{ proxmox_password }}"
|
|
api_host: "{{ ansible_host | default(ansible_default_ipv4.address) }}"
|
|
name: "{{ item.name }}"
|
|
cores: "{{ item.cores }}"
|
|
memory: "{{ item.memory }}"
|
|
update: yes
|
|
loop: "{{ k8s_nodes }}"
|
|
when: ansible_hostname == "lab01"
|
|
|
|
- name: Configure cloud-init
|
|
community.general.proxmox_kvm:
|
|
api_user: root@pam
|
|
api_password: "{{ proxmox_password }}"
|
|
api_host: "{{ ansible_host | default(ansible_default_ipv4.address) }}"
|
|
name: "{{ item.name }}"
|
|
ciuser: debian
|
|
cipassword: "{{ vm_password | default('changeme') }}"
|
|
ipconfig:
|
|
ipconfig0: "ip={{ item.ip }},gw={{ gateway }}"
|
|
nameservers: "{{ nameserver }}"
|
|
sshkeys: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
|
|
update: yes
|
|
loop: "{{ k8s_nodes }}"
|
|
when: ansible_hostname == "lab01"
|
|
|
|
- name: Start VMs
|
|
community.general.proxmox_kvm:
|
|
api_user: root@pam
|
|
api_password: "{{ proxmox_password }}"
|
|
api_host: "{{ ansible_host | default(ansible_default_ipv4.address) }}"
|
|
name: "{{ item.name }}"
|
|
state: started
|
|
loop: "{{ k8s_nodes }}"
|
|
when: ansible_hostname == "lab01"
|
|
|
|
- name: Wait for VMs to be reachable
|
|
wait_for:
|
|
host: "{{ item.ip.split('/')[0] }}"
|
|
port: 22
|
|
delay: 30
|
|
timeout: 300
|
|
loop: "{{ k8s_nodes }}"
|
|
delegate_to: localhost
|
|
|
|
- name: Prepare K8s nodes
|
|
hosts: k8s_cluster
|
|
become: yes
|
|
tasks:
|
|
- name: Update apt cache
|
|
apt:
|
|
update_cache: yes
|
|
cache_valid_time: 3600
|
|
|
|
- name: Install required packages
|
|
apt:
|
|
name:
|
|
- apt-transport-https
|
|
- ca-certificates
|
|
- curl
|
|
- gnupg
|
|
- lsb-release
|
|
- software-properties-common
|
|
state: present
|
|
|
|
- name: Disable swap
|
|
command: swapoff -a
|
|
|
|
- name: Remove swap from fstab
|
|
lineinfile:
|
|
path: /etc/fstab
|
|
regexp: '\sswap\s'
|
|
state: absent
|
|
|
|
- name: Load required kernel modules
|
|
modprobe:
|
|
name: "{{ item }}"
|
|
state: present
|
|
loop:
|
|
- overlay
|
|
- br_netfilter
|
|
|
|
- name: Setup required sysctl params
|
|
sysctl:
|
|
name: "{{ item.key }}"
|
|
value: "{{ item.value }}"
|
|
sysctl_set: yes
|
|
state: present
|
|
reload: yes
|
|
loop:
|
|
- { key: net.bridge.bridge-nf-call-iptables, value: 1 }
|
|
- { key: net.bridge.bridge-nf-call-ip6tables, value: 1 }
|
|
- { key: net.ipv4.ip_forward, value: 1 }
|
|
|
|
- name: Install containerd
|
|
hosts: k8s_cluster
|
|
become: yes
|
|
tasks:
|
|
- name: Add Docker GPG key
|
|
apt_key:
|
|
url: https://download.docker.com/linux/debian/gpg
|
|
state: present
|
|
|
|
- name: Add Docker repository
|
|
apt_repository:
|
|
repo: "deb [arch=amd64] https://download.docker.com/linux/debian {{ ansible_distribution_release }} stable"
|
|
state: present
|
|
|
|
- name: Install containerd
|
|
apt:
|
|
name: containerd.io
|
|
state: present
|
|
|
|
- name: Create containerd config directory
|
|
file:
|
|
path: /etc/containerd
|
|
state: directory
|
|
|
|
- name: Generate default containerd config
|
|
shell: containerd config default > /etc/containerd/config.toml
|
|
args:
|
|
creates: /etc/containerd/config.toml
|
|
|
|
- name: Configure containerd to use systemd cgroup
|
|
lineinfile:
|
|
path: /etc/containerd/config.toml
|
|
regexp: ' SystemdCgroup = false'
|
|
line: ' SystemdCgroup = true'
|
|
|
|
- name: Restart containerd
|
|
systemd:
|
|
name: containerd
|
|
state: restarted
|
|
enabled: yes
|
|
|
|
- name: Install Kubernetes
|
|
hosts: k8s_cluster
|
|
become: yes
|
|
vars:
|
|
kubernetes_version: "1.33"
|
|
kubernetes_patch_version: "1.33.3"
|
|
tasks:
|
|
- name: Add Kubernetes GPG key
|
|
apt_key:
|
|
url: https://pkgs.k8s.io/core:/stable:/v{{ kubernetes_version }}/deb/Release.key
|
|
state: present
|
|
|
|
- name: Add Kubernetes repository
|
|
apt_repository:
|
|
repo: "deb https://pkgs.k8s.io/core:/stable:/v{{ kubernetes_version }}/deb/ /"
|
|
state: present
|
|
|
|
- name: Install Kubernetes packages
|
|
apt:
|
|
name:
|
|
- kubelet={{ kubernetes_patch_version }}-*
|
|
- kubeadm={{ kubernetes_patch_version }}-*
|
|
- kubectl={{ kubernetes_patch_version }}-*
|
|
state: present
|
|
|
|
- name: Hold Kubernetes packages
|
|
dpkg_selections:
|
|
name: "{{ item }}"
|
|
selection: hold
|
|
loop:
|
|
- kubelet
|
|
- kubeadm
|
|
- kubectl
|
|
|
|
- name: Initialize Kubernetes master
|
|
hosts: k8s_master
|
|
become: yes
|
|
vars:
|
|
pod_network_cidr: "10.244.0.0/16"
|
|
tasks:
|
|
- name: Check if kubeadm has already run
|
|
stat:
|
|
path: /etc/kubernetes/admin.conf
|
|
register: kubeadm_init
|
|
|
|
- name: Initialize master node
|
|
command: |
|
|
kubeadm init --pod-network-cidr={{ pod_network_cidr }} \
|
|
--apiserver-advertise-address={{ ansible_default_ipv4.address }}
|
|
when: not kubeadm_init.stat.exists
|
|
register: kubeadm_output
|
|
|
|
- name: Create .kube directory for debian user
|
|
file:
|
|
path: /home/debian/.kube
|
|
state: directory
|
|
owner: debian
|
|
group: debian
|
|
mode: '0755'
|
|
|
|
- name: Copy admin.conf to debian user
|
|
copy:
|
|
src: /etc/kubernetes/admin.conf
|
|
dest: /home/debian/.kube/config
|
|
remote_src: yes
|
|
owner: debian
|
|
group: debian
|
|
mode: '0644'
|
|
|
|
- name: Install Flannel CNI
|
|
become: no
|
|
command: kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
|
|
|
|
- name: Generate join command
|
|
command: kubeadm token create --print-join-command
|
|
register: join_command
|
|
|
|
- name: Save join command
|
|
set_fact:
|
|
kubeadm_join_command: "{{ join_command.stdout }}"
|
|
|
|
- name: Join worker nodes
|
|
hosts: k8s_workers
|
|
become: yes
|
|
tasks:
|
|
- name: Check if node has already joined
|
|
stat:
|
|
path: /etc/kubernetes/kubelet.conf
|
|
register: kubelet_conf
|
|
|
|
- name: Join cluster
|
|
command: "{{ hostvars[groups['k8s_master'][0]]['kubeadm_join_command'] }}"
|
|
when: not kubelet_conf.stat.exists
|
|
|
|
- name: Configure kubectl for management
|
|
hosts: k8s_master
|
|
become: no
|
|
tasks:
|
|
- name: Check nodes
|
|
command: kubectl get nodes
|
|
register: nodes_output
|
|
|
|
- name: Display nodes
|
|
debug:
|
|
var: nodes_output.stdout_lines
|
|
|
|
- name: Install metrics server
|
|
command: kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
|
|
|
|
- name: Create dashboard namespace
|
|
command: kubectl create namespace kubernetes-dashboard
|
|
ignore_errors: yes
|
|
|
|
- name: Install Kubernetes dashboard
|
|
command: kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml |