--- - name: kubeadm init | Get full kubeadm version ansible.builtin.command: kubeadm version -o short register: _kubeadm_full_version changed_when: false - name: kubeadm init | Check if cluster already initialized ansible.builtin.stat: path: /etc/kubernetes/admin.conf register: _admin_conf - name: kubeadm init | Write kubeadm config ansible.builtin.template: src: kubeadm_config.yml.j2 dest: /tmp/kubeadm_config.yml mode: "0600" when: not _admin_conf.stat.exists - name: kubeadm init | Initialize cluster ansible.builtin.command: > kubeadm init --config /tmp/kubeadm_config.yml --upload-certs when: not _admin_conf.stat.exists register: _kubeadm_init changed_when: true - name: kubeadm init | Ensure .kube dir for root ansible.builtin.file: path: /root/.kube state: directory mode: "0700" - name: kubeadm init | Copy admin.conf for root ansible.builtin.copy: src: /etc/kubernetes/admin.conf dest: /root/.kube/config remote_src: true mode: "0600" - name: kubeadm init | Ensure .kube dir for ansible_user ansible.builtin.file: path: "/home/{{ ansible_user }}/.kube" state: directory owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "0700" - name: kubeadm init | Copy admin.conf for ansible_user ansible.builtin.copy: src: /etc/kubernetes/admin.conf dest: "{{ kubeconfig_path }}" remote_src: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "0600" # Fix #6: pinned Flannel version — change flannel_version in defaults to upgrade - name: kubeadm init | Install Flannel CNI ansible.builtin.command: > kubectl apply -f https://github.com/flannel-io/flannel/releases/download/{{ flannel_version }}/kube-flannel.yml environment: KUBECONFIG: /etc/kubernetes/admin.conf when: - cni_plugin == "flannel" - not _admin_conf.stat.exists changed_when: true - name: kubeadm init | Install Calico CNI ansible.builtin.command: > kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/{{ calico_version }}/manifests/calico.yaml environment: KUBECONFIG: /etc/kubernetes/admin.conf when: - cni_plugin == "calico" - not _admin_conf.stat.exists changed_when: true # single-node cluster — remove taint so workloads can schedule on master - name: kubeadm init | Remove control-plane taint (single-node) ansible.builtin.command: > kubectl taint nodes {{ inventory_hostname }} node-role.kubernetes.io/control-plane:NoSchedule- environment: KUBECONFIG: /etc/kubernetes/admin.conf when: not _admin_conf.stat.exists failed_when: false changed_when: true # Fix #5: save join command so worker nodes can be added later (tokens expire in 24h) - name: kubeadm init | Save worker join command ansible.builtin.shell: > kubeadm token create --print-join-command register: _join_command changed_when: false - name: kubeadm init | Write join command to file ansible.builtin.copy: content: "{{ _join_command.stdout }}\n" dest: /etc/kubernetes/worker_join_command.sh mode: "0600" # Fix #3: create .kube dir on managers before copying kubeconfig (race condition) - name: kubeadm init | Ensure .kube dir on manager nodes ansible.builtin.file: path: "/home/{{ ansible_user }}/.kube" state: directory owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "0700" delegate_to: "{{ item }}" loop: "{{ groups['manager_nodes'] }}" when: kubeconfig_fetch_to_managers | bool - name: kubeadm init | Fetch kubeconfig to controller ansible.builtin.fetch: src: /etc/kubernetes/admin.conf dest: "/tmp/k8s_admin_{{ inventory_hostname }}.conf" flat: true when: kubeconfig_fetch_to_managers | bool - name: kubeadm init | Distribute kubeconfig to manager nodes ansible.builtin.copy: src: "/tmp/k8s_admin_{{ inventory_hostname }}.conf" dest: "/home/{{ ansible_user }}/.kube/config" owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "0600" delegate_to: "{{ item }}" loop: "{{ groups['manager_nodes'] }}" when: kubeconfig_fetch_to_managers | bool