--- - name: Install dependencies, mount NFS at /home/{{ ansible_user }}/k3s, setup K3s, DNS, Traefik, venv for k8s module hosts: all become: yes vars: nfs_server: storage.mngoma.lab nfs_export_path: /export/k3s dns_server_ip: 192.168.1.151 dns_fallback_ip: 192.168.1.1 ansible_user_home: "/home/{{ ansible_user }}" nfs_mount_path: "{{ ansible_user_home }}/k3s" kube_config_path: "{{ ansible_user_home }}/.kube/config" kube_venv_path: "/opt/kube-venv" tasks: - name: Configure systemd-resolved permanent DNS copy: dest: /etc/systemd/resolved.conf content: | [Resolve] DNS={{ dns_server_ip }} FallbackDNS={{ dns_fallback_ip }} Domains=mngoma.lab DNSStubListener=yes owner: root group: root mode: '0644' - name: Ensure /etc/resolv.conf points to systemd-resolved stub file: src: /run/systemd/resolve/stub-resolv.conf dest: /etc/resolv.conf state: link force: yes - name: Restart systemd-resolved to apply DNS changes systemd: name: systemd-resolved state: restarted enabled: yes - name: Ensure NFS mount point exists file: path: "{{ nfs_mount_path }}" state: directory owner: "{{ ansible_user | default('root') }}" group: "{{ ansible_user | default('root') }}" mode: '0755' - name: Mount NFS share immediately (direct, idempotent) mount: src: "{{ nfs_server }}:{{ nfs_export_path }}" path: "{{ nfs_mount_path }}" fstype: nfs opts: defaults state: mounted - name: Ensure NFS mount persists across reboots (fstab entry) mount: src: "{{ nfs_server }}:{{ nfs_export_path }}" path: "{{ nfs_mount_path }}" fstype: nfs opts: defaults state: present - name: Ensure .kube directory exists file: path: "{{ ansible_user_home }}/.kube" state: directory owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: '0700' - name: Download latest kubectl shell: | arch=$(uname -m) if [ "$arch" = "x86_64" ]; then arch="amd64"; elif [ "$arch" = "aarch64" ]; then arch="arm64"; fi curl -Lo /usr/local/bin/kubectl "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${arch}/kubectl" chmod +x /usr/local/bin/kubectl args: creates: /usr/local/bin/kubectl environment: KUBECONFIG: "{{ kube_config_path }}" - name: Install Helm shell: | curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash args: creates: /usr/local/bin/helm environment: KUBECONFIG: "{{ kube_config_path }}" - name: Download and install kustomize shell: | kustomize_ver=$(curl -s https://api.github.com/repos/kubernetes-sigs/kustomize/releases/latest | jq -r '.tag_name') arch=$(uname -m) if [ "$arch" = "x86_64" ]; then arch="amd64"; elif [ "$arch" = "aarch64" ]; then arch="arm64"; fi url="https://github.com/kubernetes-sigs/kustomize/releases/download/${kustomize_ver}/kustomize_${kustomize_ver#kustomize/}_linux_${arch}.tar.gz" tmpfile=$(mktemp) curl -L -o "$tmpfile" "$url" tar -xz -C /usr/local/bin -f "$tmpfile" chmod +x /usr/local/bin/kustomize rm -f "$tmpfile" args: creates: /usr/local/bin/kustomize ignore_errors: true environment: KUBECONFIG: "{{ kube_config_path }}" - name: Install kubectx and kubens shell: | git clone https://github.com/ahmetb/kubectx /opt/kubectx || true ln -sf /opt/kubectx/kubectx /usr/local/bin/kubectx ln -sf /opt/kubectx/kubens /usr/local/bin/kubens environment: KUBECONFIG: "{{ kube_config_path }}" - name: Ensure systemd override directory for k3s exists file: path: /etc/systemd/system/k3s.service.d state: directory owner: root group: root mode: '0755' - name: Enable Traefik ping via CLI arguments copy: dest: /etc/systemd/system/k3s.service.d/10-traefik-ping.conf content: | [Service] ExecStart= ExecStart=/usr/local/bin/k3s server --no-deploy=servicelb --kubelet-arg="cloud-provider=external" \ --traefik-arg="--ping.entryPoint=web" \ --traefik-arg="--ping.manualRouting=false" \ --traefik-arg="--ping.responseMessage=Healthy" owner: root group: root mode: '0644' - name: Reload systemd to pick up k3s override systemd: daemon_reload: yes # --- VENV FOR KUBERNETES MODULE --- - name: Create venv for k8s ansible modules command: python3 -m venv {{ kube_venv_path }} args: creates: "{{ kube_venv_path }}/bin/activate" - name: Install kubernetes python library in venv pip: name: kubernetes virtualenv: "{{ kube_venv_path }}" virtualenv_python: python3 # The following play block will ONLY target the manager group - name: Expose Traefik dashboard via IngressRoute (manager only) hosts: manager # Change to your actual manager inventory group name become: yes vars: ansible_user_home: "/home/{{ ansible_user }}" kube_config_path: "{{ ansible_user_home }}/.kube/config" kube_venv_path: "/opt/kube-venv" tasks: - name: Expose Traefik dashboard via IngressRoute (inline) kubernetes.core.k8s: state: present definition: apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: traefik-dashboard namespace: kube-system spec: entryPoints: - web - websecure routes: - match: Host(`dashboard.apps.mngoma.lab`) kind: Rule services: - name: traefik port: 8080 tls: {} environment: KUBECONFIG: "{{ kube_config_path }}" vars: ansible_python_interpreter: "{{ kube_venv_path }}/bin/python"