migrate
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
---
|
||||
- name: Bootstrap K3s cluster with k3sup
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
<%- if secrets_file %>
|
||||
vars_files:
|
||||
- << secrets_file >>
|
||||
<%- endif %>
|
||||
|
||||
vars:
|
||||
k3s_server_target: "{{ hostvars['<< k3s_server_host >>'].ansible_host | default('<< k3s_server_host >>') }}"
|
||||
<%- if kubeconfig_destination_mode == 'remote' %>
|
||||
k3s_generated_kubeconfig_path: "/tmp/<< k3s_context_name | default('homelab-k3s') >>-kubeconfig"
|
||||
<%- else %>
|
||||
k3s_generated_kubeconfig_path: "<< local_kubeconfig_path >>"
|
||||
<%- endif %>
|
||||
|
||||
tasks:
|
||||
- name: Gather control machine facts
|
||||
ansible.builtin.setup:
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
register: localhost_facts
|
||||
|
||||
- name: Validate that the first server host exists in inventory
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "'<< k3s_server_host >>' in hostvars"
|
||||
fail_msg: "Inventory host '<< k3s_server_host >>' was not found."
|
||||
run_once: true
|
||||
|
||||
- name: Resolve k3sup release asset
|
||||
ansible.builtin.set_fact:
|
||||
k3sup_release_asset: >-
|
||||
{%- if localhost_facts.ansible_facts.ansible_system == 'Linux' and localhost_facts.ansible_facts.ansible_architecture in ['x86_64', 'amd64'] -%}
|
||||
k3sup
|
||||
{%- elif localhost_facts.ansible_facts.ansible_system == 'Linux' and localhost_facts.ansible_facts.ansible_architecture in ['aarch64', 'arm64'] -%}
|
||||
k3sup-arm64
|
||||
{%- elif localhost_facts.ansible_facts.ansible_system == 'Linux' and localhost_facts.ansible_facts.ansible_architecture in ['armv7l', 'armv6l'] -%}
|
||||
k3sup-arm
|
||||
{%- elif localhost_facts.ansible_facts.ansible_system == 'Darwin' and localhost_facts.ansible_facts.ansible_architecture in ['x86_64', 'amd64'] -%}
|
||||
k3sup-darwin
|
||||
{%- elif localhost_facts.ansible_facts.ansible_system == 'Darwin' and localhost_facts.ansible_facts.ansible_architecture in ['arm64', 'aarch64'] -%}
|
||||
k3sup-darwin-arm64
|
||||
{%- else -%}
|
||||
unsupported
|
||||
{%- endif -%}
|
||||
when: install_k3sup_binary | default(false)
|
||||
run_once: true
|
||||
|
||||
- name: Fail when k3sup binary installation is not supported for this control machine
|
||||
ansible.builtin.fail:
|
||||
msg: "Automatic k3sup installation is not supported for {{ localhost_facts.ansible_facts.ansible_system }}/{{ localhost_facts.ansible_facts.ansible_architecture }}. Set install_k3sup_binary=false and install k3sup manually."
|
||||
when:
|
||||
- install_k3sup_binary | default(false)
|
||||
- k3sup_release_asset == "unsupported"
|
||||
run_once: true
|
||||
|
||||
- name: Ensure local directory for k3sup exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ '<< k3sup_install_path >>' | dirname }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
delegate_to: localhost
|
||||
become: true
|
||||
when: install_k3sup_binary | default(false)
|
||||
run_once: true
|
||||
|
||||
- name: Install k3sup binary on the control machine
|
||||
ansible.builtin.get_url:
|
||||
url: "https://github.com/alexellis/k3sup/releases/download/<< k3sup_version >>/{{ k3sup_release_asset }}"
|
||||
dest: "<< k3sup_install_path >>"
|
||||
mode: "0755"
|
||||
delegate_to: localhost
|
||||
become: true
|
||||
when: install_k3sup_binary | default(false)
|
||||
run_once: true
|
||||
|
||||
- name: Verify k3sup is available
|
||||
ansible.builtin.command:
|
||||
cmd: "<< k3sup_install_path >> version"
|
||||
changed_when: false
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
- name: Ensure local kubeconfig directory exists when using local destination mode
|
||||
ansible.builtin.file:
|
||||
path: "{{ k3s_generated_kubeconfig_path | dirname }}"
|
||||
state: directory
|
||||
mode: "0700"
|
||||
delegate_to: localhost
|
||||
when: "<< kubeconfig_destination_mode >>" == "local"
|
||||
run_once: true
|
||||
|
||||
- name: Check whether K3s is already present on the first server
|
||||
ansible.builtin.stat:
|
||||
path: /etc/rancher/k3s/k3s.yaml
|
||||
delegate_to: "<< k3s_server_host >>"
|
||||
register: k3s_server_install_state
|
||||
run_once: true
|
||||
|
||||
- name: Bootstrap the first K3s server with k3sup
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
<< k3sup_install_path >> install
|
||||
--ip {{ k3s_server_target }}
|
||||
--user << k3s_server_user | default('ubuntu') >>
|
||||
--ssh-port << k3s_server_ssh_port | default(22) >>
|
||||
--local-path {{ k3s_generated_kubeconfig_path }}
|
||||
--merge=false
|
||||
--context << k3s_context_name | default('homelab-k3s') >>
|
||||
<%- if k3sup_use_sudo %>
|
||||
--sudo
|
||||
<%- endif %>
|
||||
<%- if k3s_server_ssh_key_path %>
|
||||
--ssh-key << k3s_server_ssh_key_path | quote >>
|
||||
<%- endif %>
|
||||
<%- if extra_server_args %>
|
||||
--k3s-extra-args << extra_server_args | quote >>
|
||||
<%- endif %>
|
||||
delegate_to: localhost
|
||||
when:
|
||||
- bootstrap_control_plane | default(true)
|
||||
- not (k3s_server_install_state.stat.exists | default(false))
|
||||
run_once: true
|
||||
|
||||
- name: Resolve inventory hosts for K3s agents
|
||||
ansible.builtin.set_fact:
|
||||
k3s_agent_inventory_hosts: "{{ query('inventory_hostnames', '<< k3s_agent_hosts_pattern >>') }}"
|
||||
when: join_agent_nodes | default(true)
|
||||
run_once: true
|
||||
|
||||
- name: Fail when agent join is enabled but no hosts match the inventory pattern
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- k3s_agent_inventory_hosts | length > 0
|
||||
fail_msg: "No inventory hosts matched '<< k3s_agent_hosts_pattern >>'."
|
||||
when: join_agent_nodes | default(true)
|
||||
run_once: true
|
||||
|
||||
- name: Check whether K3s agent is already present on each node
|
||||
ansible.builtin.stat:
|
||||
path: /etc/systemd/system/k3s-agent.service
|
||||
delegate_to: "{{ item }}"
|
||||
loop: "{{ k3s_agent_inventory_hosts | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
register: k3s_agent_install_state
|
||||
when: join_agent_nodes | default(true)
|
||||
run_once: true
|
||||
|
||||
- name: Join agent nodes to the K3s cluster with k3sup
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
<< k3sup_install_path >> join
|
||||
--ip {{ hostvars[item.item].ansible_host | default(item.item) }}
|
||||
--server-ip {{ k3s_server_target }}
|
||||
--user << k3s_agent_user | default('ubuntu') >>
|
||||
--server-user << k3s_server_user | default('ubuntu') >>
|
||||
--ssh-port << k3s_agent_ssh_port | default(22) >>
|
||||
--server-ssh-port << k3s_server_ssh_port | default(22) >>
|
||||
<%- if k3sup_use_sudo %>
|
||||
--sudo
|
||||
<%- endif %>
|
||||
<%- if k3s_server_ssh_key_path %>
|
||||
--ssh-key << k3s_server_ssh_key_path | quote >>
|
||||
<%- endif %>
|
||||
<%- if extra_agent_args %>
|
||||
--k3s-extra-args << extra_agent_args | quote >>
|
||||
<%- endif %>
|
||||
delegate_to: localhost
|
||||
loop: "{{ k3s_agent_install_state.results | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item.item }}"
|
||||
when:
|
||||
- join_agent_nodes | default(true)
|
||||
- not (item.stat.exists | default(false))
|
||||
run_once: true
|
||||
|
||||
- name: Ensure remote kubeconfig directory exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ '<< kubeconfig_remote_path >>' | dirname }}"
|
||||
state: directory
|
||||
mode: "0700"
|
||||
delegate_to: "<< kubeconfig_remote_host | default('localhost') >>"
|
||||
become: << kubeconfig_remote_become | default(false) >>
|
||||
when: "<< kubeconfig_destination_mode >>" == "remote"
|
||||
run_once: true
|
||||
|
||||
- name: Copy kubeconfig to the remote destination host
|
||||
ansible.builtin.copy:
|
||||
src: "{{ k3s_generated_kubeconfig_path }}"
|
||||
dest: "<< kubeconfig_remote_path >>"
|
||||
owner: "<< kubeconfig_remote_owner | default('ubuntu') >>"
|
||||
group: "<< kubeconfig_remote_group | default('ubuntu') >>"
|
||||
mode: "<< kubeconfig_remote_mode | default('0600') >>"
|
||||
delegate_to: "<< kubeconfig_remote_host | default('localhost') >>"
|
||||
become: << kubeconfig_remote_become | default(false) >>
|
||||
when: "<< kubeconfig_destination_mode >>" == "remote"
|
||||
run_once: true
|
||||
@@ -0,0 +1,353 @@
|
||||
{
|
||||
"slug": "k3sup-k3s-cluster",
|
||||
"kind": "ansible",
|
||||
"metadata": {
|
||||
"name": "Bootstrap K3s Cluster with k3sup",
|
||||
"description": "Bootstraps a K3s cluster from the Ansible control machine by using k3sup over SSH. Supports first-server install, optional agent joins, and local or remote kubeconfig placement.",
|
||||
"tags": [
|
||||
"kubernetes",
|
||||
"k3s",
|
||||
"k3sup",
|
||||
"bootstrap"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "simple-icons",
|
||||
"id": "kubernetes"
|
||||
},
|
||||
"draft": true,
|
||||
"version": {
|
||||
"name": "1.0.0",
|
||||
"source_dep_name": "manual/k3sup-k3s-cluster"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Execution",
|
||||
"name": "execution",
|
||||
"items": [
|
||||
{
|
||||
"name": "secrets_file",
|
||||
"type": "str",
|
||||
"title": "Secrets File",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"description": "Optional vars file to load before running the playbook."
|
||||
},
|
||||
{
|
||||
"name": "install_k3sup_binary",
|
||||
"type": "bool",
|
||||
"title": "Install k3sup",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"description": "Download and install the k3sup binary on the Ansible control machine before bootstrapping"
|
||||
},
|
||||
{
|
||||
"name": "k3sup_version",
|
||||
"type": "str",
|
||||
"title": "k3sup Version",
|
||||
"required": false,
|
||||
"default": "0.13.15",
|
||||
"description": "Version of k3sup to install when binary installation is enabled",
|
||||
"needs": [
|
||||
"install_k3sup_binary=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "0.13.15"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "k3sup_install_path",
|
||||
"type": "str",
|
||||
"title": "k3sup Path",
|
||||
"required": false,
|
||||
"default": "/usr/local/bin/k3sup",
|
||||
"description": "Local filesystem path for the k3sup binary",
|
||||
"config": {
|
||||
"placeholder": "/usr/local/bin/k3sup"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Control Plane",
|
||||
"name": "control-plane",
|
||||
"items": [
|
||||
{
|
||||
"name": "bootstrap_control_plane",
|
||||
"type": "bool",
|
||||
"title": "Bootstrap Server",
|
||||
"required": false,
|
||||
"default": true,
|
||||
"description": "Run k3sup install against the first K3s server"
|
||||
},
|
||||
{
|
||||
"name": "k3s_server_host",
|
||||
"type": "str",
|
||||
"title": "Server Host",
|
||||
"required": true,
|
||||
"default": "k3s-server-01",
|
||||
"description": "Inventory host name for the first K3s server",
|
||||
"config": {
|
||||
"placeholder": "k3s-server-01"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "k3s_server_user",
|
||||
"type": "str",
|
||||
"title": "Server SSH User",
|
||||
"required": false,
|
||||
"default": "ubuntu",
|
||||
"description": "SSH user used by k3sup for the first server",
|
||||
"config": {
|
||||
"placeholder": "ubuntu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "k3s_server_ssh_port",
|
||||
"type": "int",
|
||||
"title": "Server SSH Port",
|
||||
"required": false,
|
||||
"default": 22,
|
||||
"description": "SSH port used for the first server",
|
||||
"config": {
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 65535,
|
||||
"step": 1,
|
||||
"placeholder": "22"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "k3s_server_ssh_key_path",
|
||||
"type": "str",
|
||||
"title": "SSH Key Path",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"description": "Optional private SSH key path for k3sup",
|
||||
"config": {
|
||||
"placeholder": "~/.ssh/id_ed25519"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "k3s_context_name",
|
||||
"type": "str",
|
||||
"title": "Cluster Context",
|
||||
"required": false,
|
||||
"default": "homelab-k3s",
|
||||
"description": "kubectl context name written into the generated kubeconfig",
|
||||
"config": {
|
||||
"placeholder": "homelab-k3s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "k3sup_use_sudo",
|
||||
"type": "bool",
|
||||
"title": "Use sudo",
|
||||
"required": false,
|
||||
"default": true,
|
||||
"description": "Run k3sup remote operations with sudo on the target hosts"
|
||||
},
|
||||
{
|
||||
"name": "extra_server_args",
|
||||
"type": "str",
|
||||
"title": "Server Args",
|
||||
"required": false,
|
||||
"default": "--write-kubeconfig-mode 644 --disable servicelb",
|
||||
"description": "Optional extra K3s server arguments passed through k3sup",
|
||||
"config": {
|
||||
"placeholder": "--write-kubeconfig-mode 644 --disable servicelb"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Agents",
|
||||
"name": "agents",
|
||||
"items": [
|
||||
{
|
||||
"name": "join_agent_nodes",
|
||||
"type": "bool",
|
||||
"title": "Join Agents",
|
||||
"required": false,
|
||||
"default": true,
|
||||
"description": "Join matching inventory hosts to the cluster as K3s agents"
|
||||
},
|
||||
{
|
||||
"name": "k3s_agent_hosts_pattern",
|
||||
"type": "str",
|
||||
"title": "Agent Hosts",
|
||||
"required": false,
|
||||
"default": "k3s_agents",
|
||||
"description": "Inventory host pattern used to discover K3s agent nodes",
|
||||
"needs": [
|
||||
"join_agent_nodes=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "k3s_agents"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "k3s_agent_user",
|
||||
"type": "str",
|
||||
"title": "Agent SSH User",
|
||||
"required": false,
|
||||
"default": "ubuntu",
|
||||
"description": "SSH user used by k3sup for agent nodes",
|
||||
"needs": [
|
||||
"join_agent_nodes=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "ubuntu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "k3s_agent_ssh_port",
|
||||
"type": "int",
|
||||
"title": "Agent SSH Port",
|
||||
"required": false,
|
||||
"default": 22,
|
||||
"description": "SSH port used for agent nodes",
|
||||
"needs": [
|
||||
"join_agent_nodes=true"
|
||||
],
|
||||
"config": {
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 65535,
|
||||
"step": 1,
|
||||
"placeholder": "22"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "extra_agent_args",
|
||||
"type": "str",
|
||||
"title": "Agent Args",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"description": "Optional extra K3s agent arguments passed through k3sup",
|
||||
"needs": [
|
||||
"join_agent_nodes=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "--node-label role=worker"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Kubeconfig",
|
||||
"name": "kubeconfig",
|
||||
"items": [
|
||||
{
|
||||
"name": "kubeconfig_destination_mode",
|
||||
"type": "enum",
|
||||
"title": "Destination Mode",
|
||||
"required": false,
|
||||
"default": "local",
|
||||
"description": "Store the generated kubeconfig locally on the control machine or copy it to another managed host",
|
||||
"config": {
|
||||
"options": [
|
||||
"local",
|
||||
"remote"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "local_kubeconfig_path",
|
||||
"type": "str",
|
||||
"title": "Local Kubeconfig",
|
||||
"required": false,
|
||||
"default": "{{ lookup('env', 'HOME') }}/.kube/config",
|
||||
"description": "Local kubeconfig path used when destination mode is local",
|
||||
"needs": [
|
||||
"kubeconfig_destination_mode=local"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "{{ lookup('env', 'HOME') }}/.kube/config"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kubeconfig_remote_host",
|
||||
"type": "str",
|
||||
"title": "Remote Host",
|
||||
"required": false,
|
||||
"default": "localhost",
|
||||
"description": "Managed inventory host that should receive the kubeconfig copy",
|
||||
"needs": [
|
||||
"kubeconfig_destination_mode=remote"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "bastion-01"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kubeconfig_remote_path",
|
||||
"type": "str",
|
||||
"title": "Remote Kubeconfig",
|
||||
"required": false,
|
||||
"default": "/home/ubuntu/.kube/config",
|
||||
"description": "Destination path on the remote host for the kubeconfig file",
|
||||
"needs": [
|
||||
"kubeconfig_destination_mode=remote"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "/home/ubuntu/.kube/config"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kubeconfig_remote_owner",
|
||||
"type": "str",
|
||||
"title": "Remote Owner",
|
||||
"required": false,
|
||||
"default": "ubuntu",
|
||||
"description": "Owner for the remote kubeconfig file",
|
||||
"needs": [
|
||||
"kubeconfig_destination_mode=remote"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "ubuntu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kubeconfig_remote_group",
|
||||
"type": "str",
|
||||
"title": "Remote Group",
|
||||
"required": false,
|
||||
"default": "ubuntu",
|
||||
"description": "Group for the remote kubeconfig file",
|
||||
"needs": [
|
||||
"kubeconfig_destination_mode=remote"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "ubuntu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kubeconfig_remote_mode",
|
||||
"type": "str",
|
||||
"title": "Remote Mode",
|
||||
"required": false,
|
||||
"default": "0600",
|
||||
"description": "Filesystem mode for the remote kubeconfig file",
|
||||
"needs": [
|
||||
"kubeconfig_destination_mode=remote"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "0600"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kubeconfig_remote_become",
|
||||
"type": "bool",
|
||||
"title": "Remote Become",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"description": "Use become when creating directories or copying the remote kubeconfig",
|
||||
"needs": [
|
||||
"kubeconfig_destination_mode=remote"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user