Merge pull request #92 from PyratLabs/feature-systemd_documentation

systemd unit ordering + documentation
This commit is contained in:
Xan Manning 2021-02-16 19:11:04 +00:00 committed by GitHub
commit 05242ba232
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
57 changed files with 383 additions and 140 deletions

View file

@ -1,4 +1,4 @@
--- ---
skip_list: skip_list:
- '106' - role-name

View file

@ -14,6 +14,19 @@
--- ---
--> -->
## 2021-02-16, v2.6.0
### Notable changes
- Tidy up of `when` params and `assert` tasks to be more readable.
- Added feature to tweak K3S service dependencies.
- Updated documentation:
- Node labels and component arguments
- systemd config
- Use alternate CNI (Calico example)
---
## 2021-01-31, v2.5.3 ## 2021-01-31, v2.5.3
### Notable changes ### Notable changes

View file

@ -71,13 +71,29 @@ consistency. These are generally cluster-level configuration.
| `k3s_github_url` | Set the GitHub URL to install k3s from. | https://github.com/k3s-io/k3s | | `k3s_github_url` | Set the GitHub URL to install k3s from. | https://github.com/k3s-io/k3s |
| `k3s_install_dir` | Installation directory for k3s. | `/usr/local/bin` | | `k3s_install_dir` | Installation directory for k3s. | `/usr/local/bin` |
| `k3s_install_hard_links` | Install using hard links rather than symbolic links. | `false` | | `k3s_install_hard_links` | Install using hard links rather than symbolic links. | `false` |
| `k3s_start_on_boot` | Start k3s on boot. | `true` |
| `k3s_server_manifests_templates` | A list of Auto-Deploying Manifests Templates. | [] | | `k3s_server_manifests_templates` | A list of Auto-Deploying Manifests Templates. | [] |
| `k3s_use_experimental` | Allow the use of experimental features in k3s. | `false` | | `k3s_use_experimental` | Allow the use of experimental features in k3s. | `false` |
| `k3s_use_unsupported_config` | Allow the use of unsupported configurations in k3s. | `false` | | `k3s_use_unsupported_config` | Allow the use of unsupported configurations in k3s. | `false` |
| `k3s_etcd_datastore` | Enable etcd embedded datastore (read notes below). | `false` | | `k3s_etcd_datastore` | Enable etcd embedded datastore (read notes below). | `false` |
| `k3s_debug` | Enable debug logging on the k3s service. | `false` | | `k3s_debug` | Enable debug logging on the k3s service. | `false` |
### K3S Service Configuration
The below variables change how and when the systemd service unit file for K3S
is run. Use this with caution, please refer to the [systemd documentation](https://www.freedesktop.org/software/systemd/man/systemd.unit.html#%5BUnit%5D%20Section%20Options)
for more information.
| Variable | Description | Default Value |
|------------------------|----------------------------------------------------------------|---------------|
| `k3s_start_on_boot` | Start k3s on boot. | `true` |
| `k3s_service_requires` | List of required systemd units to k3s service unit. | [] |
| `k3s_service_wants` | List of "wanted" systemd unit to k3s (weaker than "requires"). | []\* |
| `k3s_service_before` | Start k3s before a defined list of systemd units. | [] |
| `k3s_service_after` | Start k3s after a defined list of systemd units. | []\* |
\* The systemd unit template **always** specifies `network-online.target` for
`wants` and `after`.
### Group/Host Variables ### Group/Host Variables
Below are variables that are set against individual or groups of play hosts. Below are variables that are set against individual or groups of play hosts.

View file

@ -35,9 +35,6 @@ k3s_install_dir: /usr/local/bin
# Install using hard links rather than symbolic links # Install using hard links rather than symbolic links
k3s_install_hard_links: false k3s_install_hard_links: false
# Start k3s on system boot
k3s_start_on_boot: true
# A list of templates used for preconfigure the cluster. # A list of templates used for preconfigure the cluster.
k3s_server_manifests_templates: [] k3s_server_manifests_templates: []
@ -50,6 +47,24 @@ k3s_use_unsupported_config: false
# Enable etcd embedded datastore # Enable etcd embedded datastore
k3s_etcd_datastore: false k3s_etcd_datastore: false
##
# Systemd config
##
# Start k3s on system boot
k3s_start_on_boot: true
# List of required systemd units to k3s service unit.
k3s_service_requires: []
# List of "wanted" systemd unit to k3s (weaker than "requires").
k3s_service_wants: []
# Start k3s before a defined list of systemd units.
k3s_service_before: []
# Start k3s after a defined list of systemd units.
k3s_service_after: []
## ##
# Server Configuration # Server Configuration

View file

@ -31,6 +31,9 @@ minimum configuration.
- [Setting up 2-node HA control plane with external datastore](configuration/2-node-ha-ext-datastore.md) - [Setting up 2-node HA control plane with external datastore](configuration/2-node-ha-ext-datastore.md)
- [Provision multiple standalone k3s nodes](configuration/multiple-standalone-k3s-nodes.md) - [Provision multiple standalone k3s nodes](configuration/multiple-standalone-k3s-nodes.md)
- [Set node labels and component arguments](configuration/node-labels-and-component-args.md)
- [Use an alternate CNI](configuration/use-an-alternate-cni.md)
- [Start K3S after another service](configuration/systemd-config.md)
### Operations ### Operations

View file

@ -64,6 +64,8 @@ https://rancher.com/docs/k3s/latest/en/installation/datastore/#datastore-endpoin
k3s_server: k3s_server:
datastore-endpoint: postgres://postgres:verybadpass@database:5432/postgres?sslmode=disable datastore-endpoint: postgres://postgres:verybadpass@database:5432/postgres?sslmode=disable
node-taint:
- "k3s-controlplane=true:NoExecute"
``` ```
Your worker nodes need to know how to connect to the control plane, this is Your worker nodes need to know how to connect to the control plane, this is

View file

@ -0,0 +1,39 @@
# Configure node labels and component arguments
The following command line arguments can be specified multiple times with
`key=value` pairs:
- `--kube-kubelet-arg`
- `--kube-proxy-arg`
- `--kube-apiserver-arg`
- `--kube-scheduler-arg`
- `--kube-controller-manager-arg`
- `--kube-cloud-controller-manager-arg`
- `--node-label`
- `--node-taint`
In the config file, this is done by defining a list of values for each
command like argument, for example:
```yaml
---
k3s_server:
# Set the plugins registry directory
kubelet-arg:
- "volume-plugin-dir=/var/lib/rancher/k3s/agent/kubelet/plugins_registry"
# Set the pod eviction timeout and node monitor grace period
kube-controller-manager-arg:
- "pod-eviction-timeout=2m"
- "node-monitor-grace-period=30s"
# Set API server feature gate
kube-apiserver-arg:
- "feature-gates=RemoveSelfLink=false"
# Laels to apply to a node
node-label:
- "NodeTier=development"
- "NodeLocation=eu-west-2a"
# Stop k3s control plane having workloads scheduled on them
node-taint:
- "k3s-controlplane=true:NoExecute"
```

View file

@ -0,0 +1,19 @@
# systemd config
Below are examples to tweak how and when K3S starts up.
## Wanted service units
In this example, we're going to start K3S after Wireguard. Our example server
has a Wireguard connection `wg0`. We are using "wants" rather than "requires"
as it's a weaker requirement that Wireguard must be running. We then want
K3S to start after Wireguard has started.
```yaml
---
k3s_service_wants:
- wg-quick@wg0.service
k3s_service_after:
- wg-quick@wg0.service
```

View file

@ -0,0 +1,63 @@
# Use an alternate CNI
K3S ships with Flannel, however sometimes you want an different CNI such as
Calico, Canal or Weave Net. To do this you will need to disable Flannel with
`flannel-backend: "none"`, specify a `cluster-cidr` and add your CNI manifests
to the `k3s_server_manifests_templates`.
## Calico example
The below is based on the
[Calico quickstart documentation](https://docs.projectcalico.org/getting-started/kubernetes/quickstart).
Steps:
1. Download `tigera-operator.yaml` to the manifests directory.
1. Download `custom-resources.yaml` to the manifests directory.
1. Choose a `cluster-cidr` (we are using 192.168.0.0/16)
1. Set `k3s_server` and `k3s_server_manifest_templates` as per the below,
ensure the paths to manifests are correct for your project repo.
```yaml
---
# K3S Server config, don't deploy flannel and set cluster pod CIDR.
k3s_server:
cluster-cidr: 192.168.0.0/16
flannel-backend: "none"
# Deploy the following k3s server templates.
k3s_server_manifests_templates:
- "manifests/calico/tigera-operator.yaml"
- "manifests/calico/custom-resources.yaml"
```
All nodes should come up as "Ready", below is a 3-node cluster:
```text
$ kubectl get nodes -o wide -w
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
kube-0 Ready control-plane,etcd,master 114s v1.20.2+k3s1 10.10.9.2 10.10.9.2 Ubuntu 20.04.1 LTS 5.4.0-56-generic containerd://1.4.3-k3s1
kube-1 Ready control-plane,etcd,master 80s v1.20.2+k3s1 10.10.9.3 10.10.9.3 Ubuntu 20.04.1 LTS 5.4.0-56-generic containerd://1.4.3-k3s1
kube-2 Ready control-plane,etcd,master 73s v1.20.2+k3s1 10.10.9.4 10.10.9.4 Ubuntu 20.04.1 LTS 5.4.0-56-generic containerd://1.4.3-k3s1
```
Pods should be deployed with deployed within the CIDR specified in our config
file.
```text
$ kubectl get pods -o wide -A
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
calico-system calico-kube-controllers-cfb4ff54b-8rp8r 1/1 Running 0 5m4s 192.168.145.65 kube-0 <none> <none>
calico-system calico-node-2cm2m 1/1 Running 0 5m4s 10.10.9.2 kube-0 <none> <none>
calico-system calico-node-2s6lx 1/1 Running 0 4m42s 10.10.9.4 kube-2 <none> <none>
calico-system calico-node-zwqjz 1/1 Running 0 4m49s 10.10.9.3 kube-1 <none> <none>
calico-system calico-typha-7b6747d665-78swq 1/1 Running 0 3m5s 10.10.9.4 kube-2 <none> <none>
calico-system calico-typha-7b6747d665-8ff66 1/1 Running 0 3m5s 10.10.9.3 kube-1 <none> <none>
calico-system calico-typha-7b6747d665-hgplx 1/1 Running 0 5m5s 10.10.9.2 kube-0 <none> <none>
kube-system coredns-854c77959c-6qhgt 1/1 Running 0 5m20s 192.168.145.66 kube-0 <none> <none>
kube-system helm-install-traefik-4czr9 0/1 Completed 0 5m20s 192.168.145.67 kube-0 <none> <none>
kube-system metrics-server-86cbb8457f-qcxf5 1/1 Running 0 5m20s 192.168.145.68 kube-0 <none> <none>
kube-system traefik-6f9cbd9bd4-7h4rl 1/1 Running 0 2m50s 192.168.126.65 kube-1 <none> <none>
tigera-operator tigera-operator-b6c4bfdd9-29hhr 1/1 Running 0 5m20s 10.10.9.2 kube-0 <none> <none>
```

View file

@ -86,7 +86,7 @@ Here is our playbook for the k3s cluster (`cluster.yml`):
vars: vars:
k3s_become_for_all: true k3s_become_for_all: true
roles: roles:
- xanmanning.k3s - role: xanmanning.k3s
``` ```
## Execution ## Execution

View file

@ -94,7 +94,7 @@ Here is our playbook for the k3s cluster (`ha_cluster.yml`):
k3s_etcd_datastore: true k3s_etcd_datastore: true
k3s_use_experimental: true # Note this is required for k3s < v1.19.5+k3s1 k3s_use_experimental: true # Note this is required for k3s < v1.19.5+k3s1
roles: roles:
- xanmanning.k3s - role: xanmanning.k3s
``` ```
## Execution ## Execution

View file

@ -68,7 +68,7 @@ Here is our playbook for a single node k3s cluster (`single_node.yml`):
vars: vars:
k3s_become_for_all: true k3s_become_for_all: true
roles: roles:
- xanmanning.k3s - role: xanmanning.k3s
``` ```
## Execution ## Execution

View file

@ -13,4 +13,4 @@
k3s_server_manifests_templates: k3s_server_manifests_templates:
- "molecule/autodeploy/templates/00-ns-monitoring.yml.j2" - "molecule/autodeploy/templates/00-ns-monitoring.yml.j2"
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -7,7 +7,7 @@ driver:
lint: | lint: |
set -e set -e
yamllint -s . yamllint -s .
ansible-lint ansible-lint --exclude molecule/
platforms: platforms:
- name: node1 - name: node1
image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest" image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest"

View file

@ -7,7 +7,7 @@ driver:
lint: | lint: |
set -e set -e
yamllint -s . yamllint -s .
ansible-lint ansible-lint --exclude molecule/
platforms: platforms:
- name: node1 - name: node1
image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest" image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest"

View file

@ -6,4 +6,4 @@
molecule_is_test: true molecule_is_test: true
k3s_install_hard_links: true k3s_install_hard_links: true
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -7,7 +7,7 @@ driver:
lint: | lint: |
set -e set -e
yamllint -s . yamllint -s .
ansible-lint ansible-lint --exclude molecule/
platforms: platforms:
- name: node1 - name: node1
image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest" image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest"

View file

@ -6,4 +6,4 @@
molecule_is_test: true molecule_is_test: true
k3s_state: downloaded k3s_state: downloaded
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -6,4 +6,4 @@
molecule_is_test: true molecule_is_test: true
k3s_state: restarted k3s_state: restarted
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -12,4 +12,4 @@
rootless: true rootless: true
k3s_install_dir: "/home/{{ ansible_user_id }}/bin" k3s_install_dir: "/home/{{ ansible_user_id }}/bin"
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -6,4 +6,4 @@
molecule_is_test: true molecule_is_test: true
k3s_build_cluster: false k3s_build_cluster: false
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -6,4 +6,4 @@
molecule_is_test: true molecule_is_test: true
k3s_state: started k3s_state: started
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -6,4 +6,4 @@
molecule_is_test: true molecule_is_test: true
k3s_state: stopped k3s_state: stopped
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -6,4 +6,4 @@
molecule_is_test: true molecule_is_test: true
k3s_state: uninstalled k3s_state: uninstalled
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -10,4 +10,4 @@
k3s_agent: k3s_agent:
docker: true docker: true
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -7,7 +7,7 @@ driver:
lint: | lint: |
set -e set -e
yamllint -s . yamllint -s .
ansible-lint ansible-lint --exclude molecule/
platforms: platforms:
- name: node1 - name: node1
image: "${MOLECULE_DISTRO:-geerlingguy/docker-ubuntu2004-ansible:latest}" image: "${MOLECULE_DISTRO:-geerlingguy/docker-ubuntu2004-ansible:latest}"

View file

@ -14,4 +14,4 @@
k3s_control_node: true k3s_control_node: true
when: inventory_hostname in ['node2', 'node3'] when: inventory_hostname in ['node2', 'node3']
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -7,7 +7,7 @@ driver:
lint: | lint: |
set -e set -e
yamllint -s . yamllint -s .
ansible-lint ansible-lint --exclude molecule/
platforms: platforms:
- name: node1 - name: node1
image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest" image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest"

View file

@ -14,4 +14,4 @@
ansible.builtin.set_fact: ansible.builtin.set_fact:
k3s_control_node: true k3s_control_node: true
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -7,7 +7,7 @@ driver:
lint: | lint: |
set -e set -e
yamllint -s . yamllint -s .
ansible-lint ansible-lint --exclude molecule/
platforms: platforms:
- name: node1 - name: node1
image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest" image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest"

View file

@ -7,4 +7,4 @@
k3s_server: "{{ lookup('file', 'k3s_server.yml') | from_yaml }}" k3s_server: "{{ lookup('file', 'k3s_server.yml') | from_yaml }}"
k3s_agent: "{{ lookup('file', 'k3s_agent.yml') | from_yaml }}" k3s_agent: "{{ lookup('file', 'k3s_agent.yml') | from_yaml }}"
roles: roles:
- role: xanmanning.k3s - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

View file

@ -7,7 +7,7 @@ driver:
lint: | lint: |
set -e set -e
yamllint -s . yamllint -s .
ansible-lint ansible-lint --exclude molecule/
platforms: platforms:
- name: node1 - name: node1
image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest" image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest"

View file

@ -5,7 +5,9 @@
path: "{{ k3s_runtime_config['data-dir'] | default(k3s_data_dir) }}/server/token" path: "{{ k3s_runtime_config['data-dir'] | default(k3s_data_dir) }}/server/token"
register: k3s_slurped_cluster_token register: k3s_slurped_cluster_token
delegate_to: "{{ k3s_control_delegate }}" delegate_to: "{{ k3s_control_delegate }}"
when: k3s_control_token is not defined and not ansible_check_mode when:
- k3s_control_token is not defined
- not ansible_check_mode
become: "{{ k3s_become_for_kubectl | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_kubectl | ternary(true, false, k3s_become_for_all) }}"
- name: Ensure cluster token is formatted correctly for use in templates - name: Ensure cluster token is formatted correctly for use in templates
@ -66,7 +68,9 @@
until: ensure_secondary_controllers_started is succeeded until: ensure_secondary_controllers_started is succeeded
retries: "{{ ansible_play_hosts_all | length }}" retries: "{{ ansible_play_hosts_all | length }}"
delay: 5 delay: 5
when: k3s_control_node and not k3s_primary_control_node when:
- k3s_control_node
- not k3s_primary_control_node
become: "{{ k3s_become_for_systemd | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_systemd | ternary(true, false, k3s_become_for_all) }}"
- import_tasks: ../validate/state/control-plane.yml - import_tasks: ../validate/state/control-plane.yml

View file

@ -40,14 +40,16 @@
enabled: true enabled: true
gpgcheck: true gpgcheck: true
state: present state: present
when: ansible_distribution | lower not in ['amazon'] when:
and k3s_redhat_repo_check.status == 200 - ansible_distribution | lower not in ['amazon']
- k3s_redhat_repo_check.status == 200
become: "{{ k3s_become_for_package_install | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_package_install | ternary(true, false, k3s_become_for_all) }}"
- name: Ensure Docker repository is installed and configured from file - name: Ensure Docker repository is installed and configured from file
ansible.builtin.command: yum-config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo ansible.builtin.command: yum-config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
args: args:
creates: /etc/yum.repos.d/docker-ce.repo creates: /etc/yum.repos.d/docker-ce.repo
when: ansible_distribution | lower not in ['amazon'] when:
and k3s_redhat_repo_check.status != 200 - ansible_distribution | lower not in ['amazon']
- k3s_redhat_repo_check.status != 200
become: "{{ k3s_become_for_package_install | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_package_install | ternary(true, false, k3s_become_for_all) }}"

View file

@ -4,6 +4,7 @@
ansible.builtin.set_fact: ansible.builtin.set_fact:
k3s_systemd_context: user k3s_systemd_context: user
k3s_systemd_unit_dir: "{{ ansible_user_dir }}/.config/systemd/user" k3s_systemd_unit_dir: "{{ ansible_user_dir }}/.config/systemd/user"
when: k3s_runtime_config is defined when:
and "rootless" in k3s_runtime_config - k3s_runtime_config is defined
and k3s_runtime_config.rootless - k3s_runtime_config.rootless is defined
- k3s_runtime_config.rootless

View file

@ -4,7 +4,9 @@
ansible.builtin.set_fact: ansible.builtin.set_fact:
k3s_release_version: "{{ k3s_release_channel }}" k3s_release_version: "{{ k3s_release_channel }}"
check_mode: false check_mode: false
when: k3s_release_version is defined and not k3s_release_version when:
- k3s_release_version is defined
- not k3s_release_version
- name: Ensure the default release channel is set - name: Ensure the default release channel is set
ansible.builtin.set_fact: ansible.builtin.set_fact:
@ -24,5 +26,6 @@
k3s_release_version: "{{ item.latest }}" k3s_release_version: "{{ item.latest }}"
loop: "{{ k3s_latest_release.json.data }}" loop: "{{ k3s_latest_release.json.data }}"
check_mode: false check_mode: false
when: item.name == k3s_release_channel when:
and item.type == "channel" - item.name == k3s_release_channel
- item.type == "channel"

View file

@ -6,6 +6,7 @@
state: directory state: directory
mode: "{{ directory.mode | default(0755) }}" mode: "{{ directory.mode | default(0755) }}"
become: "{{ k3s_become_for_directory_creation | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_directory_creation | ternary(true, false, k3s_become_for_all) }}"
when: directory.path is defined when:
and directory.path | length > 0 - directory.path is defined
and directory.path != omit - directory.path | length > 0
- directory.path != omit

View file

@ -43,9 +43,9 @@
dest: "/usr/local/bin/k3s-killall.sh" dest: "/usr/local/bin/k3s-killall.sh"
mode: 0700 mode: 0700
become: "{{ k3s_become_for_usr_local_bin | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_usr_local_bin | ternary(true, false, k3s_become_for_all) }}"
when: k3s_runtime_config is defined when:
and ("rootless" not in k3s_runtime_config - k3s_runtime_config is defined
or not k3s_runtime_config.rootless) - ("rootless" not in k3s_runtime_config or not k3s_runtime_config.rootless)
- name: Ensure k3s uninstall script is present - name: Ensure k3s uninstall script is present
ansible.builtin.template: ansible.builtin.template:
@ -53,6 +53,6 @@
dest: "/usr/local/bin/k3s-uninstall.sh" dest: "/usr/local/bin/k3s-uninstall.sh"
mode: 0700 mode: 0700
become: "{{ k3s_become_for_usr_local_bin | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_usr_local_bin | ternary(true, false, k3s_become_for_all) }}"
when: k3s_runtime_config is defined when:
and ("rootless" not in k3s_runtime_config - k3s_runtime_config is defined
or not k3s_runtime_config.rootless) - ("rootless" not in k3s_runtime_config or not k3s_runtime_config.rootless)

View file

@ -6,8 +6,10 @@
loop_var: directory loop_var: directory
- include_tasks: install-k3s-node.yml - include_tasks: install-k3s-node.yml
when: ((k3s_control_node and k3s_controller_list | length == 1) when:
or (k3s_primary_control_node and k3s_controller_list | length > 1)) and not ansible_check_mode - ((k3s_control_node and k3s_controller_list | length == 1)
or (k3s_primary_control_node and k3s_controller_list | length > 1))
- not ansible_check_mode
- meta: flush_handlers - meta: flush_handlers

View file

@ -3,8 +3,9 @@
- name: Ensure k3s_build_cluster is false if running against a single node. - name: Ensure k3s_build_cluster is false if running against a single node.
ansible.builtin.set_fact: ansible.builtin.set_fact:
k3s_build_cluster: false k3s_build_cluster: false
when: ansible_play_hosts_all | length < 2 when:
and k3s_control_node_address is not defined - ansible_play_hosts_all | length < 2
- k3s_control_node_address is not defined
- name: Ensure k3s control node fact is set - name: Ensure k3s control node fact is set
ansible.builtin.set_fact: ansible.builtin.set_fact:
@ -24,8 +25,9 @@
- name: Ensure a count of control nodes is generated - name: Ensure a count of control nodes is generated
ansible.builtin.set_fact: ansible.builtin.set_fact:
k3s_controller_list: "{{ k3s_controller_list + [ item ] }}" k3s_controller_list: "{{ k3s_controller_list + [ item ] }}"
when: hostvars[item].k3s_control_node is defined when:
and hostvars[item].k3s_control_node - hostvars[item].k3s_control_node is defined
- hostvars[item].k3s_control_node
loop: "{{ ansible_play_hosts_all }}" loop: "{{ ansible_play_hosts_all }}"
- name: Ensure a k3s control node is defined if none are found in ansible_play_hosts_all - name: Ensure a k3s control node is defined if none are found in ansible_play_hosts_all
@ -39,20 +41,25 @@
- name: Ensure a count of control nodes is generated - name: Ensure a count of control nodes is generated
ansible.builtin.set_fact: ansible.builtin.set_fact:
k3s_controller_list: "{{ k3s_controller_list + [ item ] }}" k3s_controller_list: "{{ k3s_controller_list + [ item ] }}"
when: hostvars[item].k3s_control_node is defined when:
and hostvars[item].k3s_control_node - hostvars[item].k3s_control_node is defined
- hostvars[item].k3s_control_node
loop: "{{ ansible_play_hosts_all }}" loop: "{{ ansible_play_hosts_all }}"
when: k3s_controller_list | length < 1 when:
and k3s_build_cluster is defined and k3s_build_cluster - k3s_controller_list | length < 1
- k3s_build_cluster is defined
- k3s_build_cluster
- name: Ensure a primary k3s control node is defined if multiple are found in ansible_play_hosts_all - name: Ensure a primary k3s control node is defined if multiple are found in ansible_play_hosts_all
ansible.builtin.set_fact: ansible.builtin.set_fact:
k3s_primary_control_node: true k3s_primary_control_node: true
when: k3s_controller_list is defined when:
and k3s_controller_list | length > 1 - k3s_controller_list is defined
and inventory_hostname == k3s_controller_list[0] - k3s_controller_list | length > 1
and k3s_build_cluster is defined and k3s_build_cluster - inventory_hostname == k3s_controller_list[0]
- k3s_build_cluster is defined
- k3s_build_cluster
- name: Ensure ansible_host is mapped to inventory_hostname - name: Ensure ansible_host is mapped to inventory_hostname
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
@ -98,11 +105,13 @@
- name: Ensure k3s_runtime_config is set for control plane - name: Ensure k3s_runtime_config is set for control plane
ansible.builtin.set_fact: ansible.builtin.set_fact:
k3s_runtime_config: "{{ (k3s_server | default({})) | combine((k3s_agent | default({}))) }}" k3s_runtime_config: "{{ (k3s_server | default({})) | combine((k3s_agent | default({}))) }}"
when: (k3s_server is defined or k3s_agent is defined) when:
and (k3s_control_node is defined and k3s_control_node) - (k3s_server is defined or k3s_agent is defined)
- (k3s_control_node is defined and k3s_control_node)
- name: Ensure k3s_runtime_config is set for agents - name: Ensure k3s_runtime_config is set for agents
ansible.builtin.set_fact: ansible.builtin.set_fact:
k3s_runtime_config: "{{ (k3s_agent | default({})) }}" k3s_runtime_config: "{{ (k3s_agent | default({})) }}"
when: k3s_agent is defined when:
and (k3s_control_node is not defined or not k3s_control_node) - k3s_agent is defined
- (k3s_control_node is not defined or not k3s_control_node)

View file

@ -14,5 +14,7 @@
state: started state: started
enabled: "{{ k3s_start_on_boot }}" enabled: "{{ k3s_start_on_boot }}"
scope: user scope: user
when: k3s_non_root is defined and k3s_non_root when:
- k3s_non_root is defined
- k3s_non_root
become: "{{ k3s_become_for_systemd | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_systemd | ternary(true, false, k3s_become_for_all) }}"

View file

@ -14,5 +14,7 @@
state: stopped state: stopped
enabled: "{{ k3s_start_on_boot }}" enabled: "{{ k3s_start_on_boot }}"
scope: user scope: user
when: k3s_non_root is defined and k3s_non_root when:
- k3s_non_root is defined
- k3s_non_root
become: "{{ k3s_become_for_systemd | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_systemd | ternary(true, false, k3s_become_for_all) }}"

View file

@ -25,19 +25,23 @@
- include_tasks: build/docker/{{ ansible_distribution | replace(" ", "-") | lower }}/install.yml - include_tasks: build/docker/{{ ansible_distribution | replace(" ", "-") | lower }}/install.yml
when: ansible_distribution | replace(" ", "-") | lower in ['amazon', 'suse', 'opensuse-leap', 'archlinux'] when: ansible_distribution | replace(" ", "-") | lower in ['amazon', 'suse', 'opensuse-leap', 'archlinux']
when: ('docker' in k3s_runtime_config and k3s_runtime_config.docker) when:
and ('rootless' not in k3s_runtime_config or not k3s_runtime_config.rootless) - ('docker' in k3s_runtime_config and k3s_runtime_config.docker)
- ('rootless' not in k3s_runtime_config or not k3s_runtime_config.rootless)
- meta: flush_handlers - meta: flush_handlers
- import_tasks: build/download-k3s.yml - import_tasks: build/download-k3s.yml
- import_tasks: build/preconfigure-k3s-auto-deploying-manifests.yml - import_tasks: build/preconfigure-k3s-auto-deploying-manifests.yml
when: k3s_control_node when:
and k3s_server_manifests_templates | length > 0 - k3s_control_node
- k3s_server_manifests_templates | length > 0
- import_tasks: build/install-k3s.yml - import_tasks: build/install-k3s.yml
- import_tasks: build/configure-k3s-cluster.yml - import_tasks: build/configure-k3s-cluster.yml
when: k3s_build_cluster is defined and k3s_build_cluster when:
and k3s_control_node_address is defined - k3s_build_cluster is defined
- k3s_build_cluster
- k3s_control_node_address is defined

View file

@ -17,8 +17,9 @@
- include_tasks: teardown/docker/{{ ansible_os_family | lower }}/uninstall-prerequisites.yml - include_tasks: teardown/docker/{{ ansible_os_family | lower }}/uninstall-prerequisites.yml
when: ('docker' in k3s_runtime_config and k3s_runtime_config.docker) when:
and ('rootless' not in k3s_runtime_config or not k3s_runtime_config.rootless) - ('docker' in k3s_runtime_config and k3s_runtime_config.docker)
- ('rootless' not in k3s_runtime_config or not k3s_runtime_config.rootless)
- import_tasks: validate/state/uninstalled.yml - import_tasks: validate/state/uninstalled.yml
when: not k3s_skip_validation when: not k3s_skip_validation

View file

@ -22,9 +22,10 @@
ansible.builtin.command: "{{ k3s_install_dir }}/kubectl drain {{ item }} --ignore-daemonsets --delete-local-data" ansible.builtin.command: "{{ k3s_install_dir }}/kubectl drain {{ item }} --ignore-daemonsets --delete-local-data"
delegate_to: "{{ k3s_control_delegate }}" delegate_to: "{{ k3s_control_delegate }}"
run_once: true run_once: true
when: item in kubectl_get_nodes_result.stdout when:
and hostvars[item].k3s_state is defined - item in kubectl_get_nodes_result.stdout
and hostvars[item].k3s_state == 'uninstalled' - hostvars[item].k3s_state is defined
- hostvars[item].k3s_state == 'uninstalled'
loop: "{{ ansible_play_hosts_all }}" loop: "{{ ansible_play_hosts_all }}"
become: "{{ k3s_become_for_kubectl | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_kubectl | ternary(true, false, k3s_become_for_all) }}"
@ -32,13 +33,15 @@
ansible.builtin.command: "{{ k3s_install_dir }}/kubectl delete node {{ item }}" ansible.builtin.command: "{{ k3s_install_dir }}/kubectl delete node {{ item }}"
delegate_to: "{{ k3s_control_delegate }}" delegate_to: "{{ k3s_control_delegate }}"
run_once: true run_once: true
when: item in kubectl_get_nodes_result.stdout when:
and hostvars[item].k3s_state is defined - item in kubectl_get_nodes_result.stdout
and hostvars[item].k3s_state == 'uninstalled' - hostvars[item].k3s_state is defined
- hostvars[item].k3s_state == 'uninstalled'
loop: "{{ ansible_play_hosts_all }}" loop: "{{ ansible_play_hosts_all }}"
become: "{{ k3s_become_for_kubectl | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_kubectl | ternary(true, false, k3s_become_for_all) }}"
when: k3s_check_kubectl.stat.exists is defined when:
and k3s_check_kubectl.stat.exists - k3s_check_kubectl.stat.exists is defined
and k3s_control_delegate is defined - k3s_check_kubectl.stat.exists
and not ansible_check_mode - k3s_control_delegate is defined
- not ansible_check_mode

View file

@ -40,11 +40,13 @@
- kubectl - kubectl
- crictl - crictl
- ctr - ctr
when: k3s_install_hard_links when:
and not ansible_check_mode - k3s_install_hard_links
- not ansible_check_mode
become: "{{ k3s_become_for_uninstall | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_uninstall | ternary(true, false, k3s_become_for_all) }}"
- name: Clean up Docker - name: Clean up Docker
ansible.builtin.command: docker system prune -a --force ansible.builtin.command: docker system prune -a --force
when: ("docker" in k3s_runtime_config and k3s_runtime_config.docker) when:
and check_k3s_docker_path.rc == 0 - ("docker" in k3s_runtime_config and k3s_runtime_config.docker)
- check_k3s_docker_path.rc == 0

View file

@ -4,33 +4,36 @@
ansible.builtin.assert: ansible.builtin.assert:
that: that:
- (k3s_controller_list | length == 1) - (k3s_controller_list | length == 1)
and ("datastore-endpoint" not in k3s_runtime_config or not k3s_runtime_config['datastore-endpoint']) - ("datastore-endpoint" not in k3s_runtime_config or not k3s_runtime_config['datastore-endpoint'])
and (k3s_etcd_datastore is not defined or not k3s_etcd_datastore) - (k3s_etcd_datastore is not defined or not k3s_etcd_datastore)
success_msg: "Control plane configuration is valid." success_msg: "Control plane configuration is valid."
fail_msg: "Control plane configuration is invalid. Please see notes about k3s_control_node and HA in README.md." fail_msg: "Control plane configuration is invalid. Please see notes about k3s_control_node and HA in README.md."
when: k3s_controller_list | length == 1 when:
and not k3s_use_unsupported_config - k3s_controller_list | length == 1
and k3s_control_node - not k3s_use_unsupported_config
- k3s_control_node
- name: Check the conditions when multiple controllers are defined - name: Check the conditions when multiple controllers are defined
ansible.builtin.assert: ansible.builtin.assert:
that: that:
- (k3s_controller_list | length >= 2) - (k3s_controller_list | length >= 2)
and (("datastore-endpoint" in k3s_runtime_config and k3s_runtime_config['datastore-endpoint']) - (("datastore-endpoint" in k3s_runtime_config and k3s_runtime_config['datastore-endpoint'])
or (k3s_etcd_datastore is defined and k3s_etcd_datastore)) or (k3s_etcd_datastore is defined and k3s_etcd_datastore))
success_msg: "Control plane configuration is valid." success_msg: "Control plane configuration is valid."
fail_msg: "Control plane configuration is invalid. Please see notes about k3s_control_node and HA in README.md." fail_msg: "Control plane configuration is invalid. Please see notes about k3s_control_node and HA in README.md."
when: k3s_controller_list | length >= 2 when:
and k3s_control_node - k3s_controller_list | length >= 2
- k3s_control_node
- name: Check the conditions when embedded etcd is defined - name: Check the conditions when embedded etcd is defined
ansible.builtin.assert: ansible.builtin.assert:
that: that:
- (k3s_controller_list | length >= 3) - (k3s_controller_list | length >= 3)
and (((k3s_controller_list | length) % 2) == 1) - (((k3s_controller_list | length) % 2) == 1)
success_msg: "Control plane configuration is valid." success_msg: "Control plane configuration is valid."
fail_msg: "Etcd should have a minimum of 3 defined members and the number of members should be odd. Please see notes about HA in README.md" fail_msg: "Etcd should have a minimum of 3 defined members and the number of members should be odd. Please see notes about HA in README.md"
when: k3s_etcd_datastore is defined when:
and k3s_etcd_datastore - k3s_etcd_datastore is defined
and not k3s_use_unsupported_config - k3s_etcd_datastore
and k3s_control_node - not k3s_use_unsupported_config
- k3s_control_node

View file

@ -8,8 +8,10 @@
fail_msg: >- fail_msg: >-
Experimental variable k3s_etcd_datastore has been configured. Experimental variable k3s_etcd_datastore has been configured.
If you want to use this ensure you set k3s_use_experimental, If you want to use this ensure you set k3s_use_experimental,
when: k3s_etcd_datastore is defined and k3s_etcd_datastore when:
and (k3s_release_version | replace('v', '')) is version_compare("1.19.5", '<') - k3s_etcd_datastore is defined
- k3s_etcd_datastore
- (k3s_release_version | replace('v', '')) is version_compare("1.19.5", '<')
- name: Check if any experimental variables are configure and if they are enabled with k3s_use_experimental - name: Check if any experimental variables are configure and if they are enabled with k3s_use_experimental
ansible.builtin.assert: ansible.builtin.assert:
@ -23,6 +25,7 @@
Documentation: {{ item.documentation }} Documentation: {{ item.documentation }}
{% endif %} {% endif %}
loop: "{{ k3s_experimental_config }}" loop: "{{ k3s_experimental_config }}"
when: (item.setting in k3s_runtime_config and k3s_runtime_config[item.setting]) when:
and ((item.until is not defined) or - (item.setting in k3s_runtime_config and k3s_runtime_config[item.setting])
- ((item.until is not defined) or
(item.until is defined and (k3s_release_version | replace('v', '')) is version_compare(item.until, '<'))) (item.until is defined and (k3s_release_version | replace('v', '')) is version_compare(item.until, '<')))

View file

@ -57,5 +57,6 @@
- ansible_env['XDG_RUNTIME_DIR'] is defined - ansible_env['XDG_RUNTIME_DIR'] is defined
- k3s_check_newuidmap_installed.rc == 0 - k3s_check_newuidmap_installed.rc == 0
success_msg: All kernel parameters passed success_msg: All kernel parameters passed
fail_msg: Kernel parameters are not set correctly, please check fail_msg: >-
Kernel parameters are not set correctly, please check
https://github.com/rootless-containers/rootlesskit https://github.com/rootless-containers/rootlesskit

View file

@ -33,9 +33,10 @@
Documentation: {{ item.documentation }} Documentation: {{ item.documentation }}
{% endif %} {% endif %}
loop: "{{ k3s_deprecated_config }}" loop: "{{ k3s_deprecated_config }}"
when: (item.when is not defined when:
- (item.when is not defined
or (item.when is defined and (k3s_release_version | replace('v', '')) is version_compare(item.when, '>='))) or (item.when is defined and (k3s_release_version | replace('v', '')) is version_compare(item.when, '>=')))
and not k3s_use_unsupported_config - not k3s_use_unsupported_config
- name: Check configuration in k3s_server and k3s_agent against release version - name: Check configuration in k3s_server and k3s_agent against release version
ansible.builtin.assert: ansible.builtin.assert:
@ -49,5 +50,6 @@
Documentation: {{ item.documentation }} Documentation: {{ item.documentation }}
{% endif %} {% endif %}
loop: "{{ k3s_config_version_check }}" loop: "{{ k3s_config_version_check }}"
when: k3s_config_version_check is defined when:
and item.setting in k3s_runtime_config - k3s_config_version_check is defined
- item.setting in k3s_runtime_config

View file

@ -4,7 +4,9 @@
ansible.builtin.assert: ansible.builtin.assert:
that: that:
- ansible_version.string is version_compare(k3s_ansible_min_version, '>=') - ansible_version.string is version_compare(k3s_ansible_min_version, '>=')
fail_msg: "Ansible v{{ ansible_version.string }} is not supported by this role. Please install >= v{{ k3s_ansible_min_version }}" fail_msg: >-
Ansible v{{ ansible_version.string }} is not supported by this role.
Please install >= v{{ k3s_ansible_min_version }}
success_msg: "Ansible v{{ ansible_version.string }} is supported." success_msg: "Ansible v{{ ansible_version.string }} is supported."
become: false become: false
delegate_to: localhost delegate_to: localhost

View file

@ -16,7 +16,8 @@
{% if package.documentation is defined %} {% if package.documentation is defined %}
Documentation: {{ package.documentation }} Documentation: {{ package.documentation }}
{% endif %} {% endif %}
when: (package.until is not defined when:
- (package.until is not defined
or k3s_release_version is version_compare(package.until, '>=')) or k3s_release_version is version_compare(package.until, '>='))
and (package.from is not defined - (package.from is not defined
or k3s_release_version is version_compare(package.from, '>=')) or k3s_release_version is version_compare(package.from, '>='))

View file

@ -5,8 +5,11 @@
- import_tasks: configuration/experimental-variables.yml - import_tasks: configuration/experimental-variables.yml
- import_tasks: configuration/unsupported-rootless.yml - import_tasks: configuration/unsupported-rootless.yml
when: ("rootless" in k3s_runtime_config) when:
and k3s_runtime_config.rootless - k3s_runtime_config.rootless is defined
- k3s_runtime_config.rootless
- import_tasks: configuration/control-node-count.yml - import_tasks: configuration/control-node-count.yml
when: k3s_build_cluster is defined and k3s_build_cluster when:
- k3s_build_cluster is defined
- k3s_build_cluster

View file

@ -9,15 +9,19 @@
when: k3s_state is defined when: k3s_state is defined
- import_tasks: environment/local/packages.yml - import_tasks: environment/local/packages.yml
when: not k3s_skip_validation when:
and not k3s_skip_env_checks - not k3s_skip_validation
- not k3s_skip_env_checks
- include_tasks: environment/remote/packages.yml - include_tasks: environment/remote/packages.yml
loop: "{{ k3s_check_packages }}" loop: "{{ k3s_check_packages }}"
loop_control: loop_control:
loop_var: package loop_var: package
when: not k3s_skip_validation when:
and not k3s_skip_env_checks - k3s_skip_validation
- not k3s_skip_env_checks
- include_tasks: environment/local/issue-data.yml - include_tasks: environment/local/issue-data.yml
when: pyratlabs_issue_controller_dump is defined and pyratlabs_issue_controller_dump when:
- pyratlabs_issue_controller_dump is defined
- pyratlabs_issue_controller_dump

View file

@ -6,12 +6,14 @@
failed_when: kubectl_get_nodes_result.stdout.find("was refused") != -1 or failed_when: kubectl_get_nodes_result.stdout.find("was refused") != -1 or
kubectl_get_nodes_result.stdout.find("ServiceUnavailable") != -1 kubectl_get_nodes_result.stdout.find("ServiceUnavailable") != -1
register: kubectl_get_nodes_result register: kubectl_get_nodes_result
until: kubectl_get_nodes_result.rc == 0 until:
and kubectl_get_nodes_result.stdout.find("NotReady") == -1 - kubectl_get_nodes_result.rc == 0
- kubectl_get_nodes_result.stdout.find("NotReady") == -1
retries: 30 retries: 30
delay: 20 delay: 20
when: k3s_control_node when:
and ("flannel-backend" not in k3s_runtime_config - k3s_control_node
- ("flannel-backend" not in k3s_runtime_config
or k3s_runtime_config["flannel-backend"] != "none") or k3s_runtime_config["flannel-backend"] != "none")
and not ansible_check_mode - not ansible_check_mode
become: "{{ k3s_become_for_kubectl | ternary(true, false, k3s_become_for_all) }}" become: "{{ k3s_become_for_kubectl | ternary(true, false, k3s_become_for_all) }}"

View file

@ -16,12 +16,16 @@
ignore_errors: true ignore_errors: true
changed_when: false changed_when: false
register: check_k3s_docker_process register: check_k3s_docker_process
when: ("docker" in k3s_runtime_config and k3s_runtime_config.docker) when:
- k3s_runtime_config.docker is defined
- k3s_runtime_config.docker
- name: Fail if docker is still running - name: Fail if docker is still running
ansible.builtin.fail: ansible.builtin.fail:
msg: docker is still running, uninstall script failed. Please investigate. msg: docker is still running, uninstall script failed. Please investigate.
when: ("docker" in k3s_runtime_config and k3s_runtime_config.docker) when:
- k3s_runtime_config.docker is defined
- k3s_runtime_config.docker
- name: Fail if k3s binaries have not been removed - name: Fail if k3s binaries have not been removed
ansible.builtin.stat: ansible.builtin.stat:
@ -41,7 +45,7 @@
- name: Fail if k3s-killall.sh script still exists - name: Fail if k3s-killall.sh script still exists
ansible.builtin.fail: ansible.builtin.fail:
msg: k3s-killall.sh is still running, uninstall script failed. Please investigate. msg: k3s-killall.sh still exists, uninstall script failed. Please investigate.
when: check_k3s_killall.stat.exists when: check_k3s_killall.stat.exists
- name: Check k3s-uninstall.sh is removed - name: Check k3s-uninstall.sh is removed
@ -51,5 +55,5 @@
- name: Fail if k3s-uninstall.sh script still exists - name: Fail if k3s-uninstall.sh script still exists
ansible.builtin.fail: ansible.builtin.fail:
msg: k3s-uninstall.sh is still running, uninstall script failed. Please investigate. msg: k3s-uninstall.sh is still exists, uninstall script failed. Please investigate.
when: check_k3s_uninstall.stat.exists when: check_k3s_uninstall.stat.exists

View file

@ -1,8 +1,20 @@
[Unit] [Unit]
Description=Lightweight Kubernetes Description=Lightweight Kubernetes
Documentation=https://k3s.io Documentation=https://k3s.io
{% for requires_unit in k3s_service_requires %}
Requires={{ requires_unit }}
{% endfor %}
Wants=network-online.target Wants=network-online.target
{% for wants_unit in k3s_service_wants %}
Wants={{ wants_unit }}
{% endfor %}
{% for before_unit in k3s_service_before %}
Before={{ before_unit }}
{% endfor %}
After=network-online.target After=network-online.target
{% for after_unit in k3s_service_after %}
After={{ after_unit }}
{% endfor %}
[Service] [Service]
Type={{ 'notify' if k3s_control_node else 'exec' }} Type={{ 'notify' if k3s_control_node else 'exec' }}