PyratLabs
ansible-role-k3s
Jinja

Ansible role for installing k3s as either a standalone server or HA cluster.

Last updated May 28, 2026
713
Stars
149
Forks
3
Issues
0
Stars/day
Attention Score
88
Language breakdown
No language data available.
Files click to expand
README

Ansible Role: k3s (v3.x)

Ansible role for installing K3S ("Lightweight Kubernetes") as either a standalone server or cluster.

CI

Help Wanted!

Hi! :wave: @xanmanning is looking for a new maintainer to work on this Ansible role. This is because I don't have as much free time any more and I no longer write Ansible regularly as part of my day job. If you're interested, get in touch.

Release notes

Please see Releases and CHANGELOG.md.

Requirements

The host you're running Ansible from requires the following Python dependencies:

- python >= 3.6.0 - See Notes below. - ansible >= 2.9.16 or ansible-base >= 2.10.4 - netaddr >= 1.3.0 - Required for dual-stack IP address handling

You can install dependencies using the requirements.txt file in this repository: pip3 install -r requirements.txt.

This role has been tested against the following Linux Distributions:

- Alpine Linux - Archlinux - CentOS 8 - Debian 11 - Debian 12 - Fedora 41 - Fedora 42 - openSUSE Leap 15 - RockyLinux 9 - RockyLinux 10 - Ubuntu 22.04 LTS - Ubuntu 24.04 LTS

:warning: The v3 releases of this role only supports k3s >= v1.19, for k3s < v1.19 please consider updating or use the v1.x releases of this role.

Before upgrading, see CHANGELOG for notifications of breaking changes.

Role Variables

Since K3s v1.19.1+k3s1 you can now configure K3s using a configuration file rather than environment variables or command line arguments. The v2 release of this role has moved to the configuration file method rather than populating a systemd unit file with command-line arguments. There may be exceptions that are defined in Global/Cluster Variables, however you will mostly be configuring k3s by configuration files using the k3s_server and k3s_agent variables.

See "Server (Control Plane) Configuration" and "Agent (Worker) Configuraion" below.

Global/Cluster Variables

Below are variables that are set against all of the play hosts for environment consistency. These are generally cluster-level configuration.

| Variable | Description | Default Value | |--------------------------------------|--------------------------------------------------------------------------------------------|--------------------------------| | k3s_state | State of k3s: installed, started, stopped, downloaded, uninstalled, validated. | installed | | k3sreleaseversion | Use a specific version of k3s, eg. v0.2.0. Specify false for stable. | false | | k3s_airgap | Boolean to enable air-gapped installations | false | | k3sconfigfile | Location of the k3s configuration file. | /etc/rancher/k3s/config.yaml | | k3sbuildcluster | When multiple play hosts are available, attempt to cluster. Read notes below. | true | | k3sregistrationaddress | Fixed registration address for nodes. IP or FQDN. | NULL | | k3sgithuburl | Set the GitHub URL to install k3s from. | https://github.com/k3s-io/k3s | | k3sapiurl | URL for K3S updates API. | https://update.k3s.io | | k3sinstalldir | Installation directory for k3s. | /usr/local/bin | | k3sinstallhard_links | Install using hard links rather than symbolic links. | false | | k3sserverconfigyamldfiles | A flat list of templates to supplement the k3sserver configuration. | [] | | k3sagentconfigyamldfiles | A flat list of templates to supplement the k3sagent configuration. | [] | | k3sservermanifests_urls | A list of URLs to deploy on the primary control plane. Read notes below. | [] | | k3sservermanifests_templates | A flat list of templates to deploy on the primary control plane. | [] | | k3sserverpodmanifestsurls | A list of URLs for installing static pod manifests on the control plane. Read notes below. | [] | | k3sserverpodmanifeststemplates | A flat list of templates for installing static pod manifests on the control plane. | [] | | k3suseexperimental | Allow the use of experimental features in k3s. | false | | k3suseunsupported_config | Allow the use of unsupported configurations in k3s. | false | | k3setcddatastore | Enable etcd embedded datastore (read notes below). | false | | k3s_debug | Enable debug logging on the k3s service. | false | | k3s_registries | Registries configuration file content. | { mirrors: {}, configs:{} } |

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 for more information.

| Variable | Description | Default Value | |------------------------|----------------------------------------------------------------------|---------------| | k3sstarton_boot | Start k3s on boot. | true | | k3sservicerequires | List of required systemd units to k3s service unit. | [] | | k3sservicewants | List of "wanted" systemd unit to k3s (weaker than "requires"). | []\* | | k3sservicebefore | Start k3s before a defined list of systemd units. | [] | | k3sserviceafter | Start k3s after a defined list of systemd units. | []\* | | k3sserviceenv_vars | Dictionary of environment variables to use within systemd unit file. | {} | | k3sserviceenv_file | Location on host of a environment file to include. | false\\ | | k3sservicecpu_limit | Limit the cpu usage, e.g. to 2 CPUs set value to 200% | N/A | | k3sservicememory_limit | Limit the memory usage, e.g for 4G set value to 4G | N/A |

\* The systemd unit template always specifies network-online.target for wants and after.

\\ The file must already exist on the target host, this role will not create nor manage the file. You can manage this file outside of the role with pre-tasks in your Ansible playbook.

Group/Host Variables

Below are variables that are set against individual or groups of play hosts. Typically you'd set these at group level for the control plane or worker nodes.

| Variable | Description | Default Value | |--------------------|-------------------------------------------------------------------|---------------------------------------------------| | k3scontrolnode | Specify if a host (or host group) are part of the control plane. | false (role will automatically delegate a node) | | k3s_server | Server (control plane) configuration, see notes below. | {} | | k3s_agent | Agent (worker) configuration, see notes below. | {} |

Server (Control Plane) Configuration

The control plane is configured with the k3s_server dict variable. Please refer to the below documentation for configuration options:

https://rancher.com/docs/k3s/latest/en/installation/install-options/server-config/

The k3s_server dictionary variable will contain flags from the above (removing the -- prefix). Below is an example:

<pre><code class="lang-yaml">k3s_server: datastore-endpoint: postgres://postgres:verybadpass@database:5432/postgres?sslmode=disable cluster-cidr: 172.20.0.0/16 flannel-backend: &#39;none&#39; # This needs to be in quotes disable: - traefik - coredns</code></pre>

Alternatively, you can create a .yaml file and read it in to the k3s_server variable as per the below example:

<pre><code class="lang-yaml">k3sserver: &quot;{{ lookup(&#39;file&#39;, &#39;path/to/k3sserver.yml&#39;) | from_yaml }}&quot;</code></pre>

Check out the Documentation for example configuration.

Agent (Worker) Configuration

Workers are configured with the k3s_agent dict variable. Please refer to the below documentation for configuration options:

https://rancher.com/docs/k3s/latest/en/installation/install-options/agent-config

The k3s_agent dictionary variable will contain flags from the above (removing the -- prefix). Below is an example:

<pre><code class="lang-yaml">k3s_agent: with-node-id: true node-label: - &quot;foo=bar&quot; - &quot;hello=world&quot;</code></pre>

Alternatively, you can create a .yaml file and read it in to the k3s_agent variable as per the below example:

<pre><code class="lang-yaml">k3sagent: &quot;{{ lookup(&#39;file&#39;, &#39;path/to/k3sagent.yml&#39;) | from_yaml }}&quot;</code></pre>

Check out the Documentation for example configuration.

Ansible Controller Configuration Variables

The below variables are used to change the way the role executes in Ansible, particularly with regards to privilege escalation.

| Variable | Description | Default Value | |------------------------|----------------------------------------------------------------|---------------| | k3sskipvalidation | Skip all tasks that validate configuration. | false | | k3sskipenv_checks | Skip all tasks that check environment configuration. | false | | k3sskippost_checks | Skip all tasks that check post execution state. | false | | k3s_become | Escalate user privileges for tasks that need root permissions. | false |

Important note about Python

From v3 of this role, Python 3 is required on the target system as well as on the Ansible controller. This is to ensure consistent behaviour for Ansible tasks as Python 2 is now EOL.

If target systems have both Python 2 and Python 3 installed, it is most likely that Python 2 will be selected by default. To ensure Python 3 is used on a target with both versions of Python, ensure ansiblepythoninterpreter is set in your inventory. Below is an example inventory:

<pre><code class="lang-yaml">---

k3s_cluster: hosts: kube-0: ansible_user: ansible ansible_host: 10.10.9.2 ansiblepythoninterpreter: /usr/bin/python3 kube-1: ansible_user: ansible ansible_host: 10.10.9.3 ansiblepythoninterpreter: /usr/bin/python3 kube-2: ansible_user: ansible ansible_host: 10.10.9.4 ansiblepythoninterpreter: /usr/bin/python3</code></pre>

Important note about k3sreleaseversion

If you do not set a k3sreleaseversion the latest version from the stable channel of k3s will be installed. If you are developing against a specific version of k3s you must ensure this is set in your Ansible configuration, eg:

<pre><code class="lang-yaml">k3sreleaseversion: v1.19.3+k3s1</code></pre>

It is also possible to install specific K3s "Channels", below are some examples for k3sreleaseversion:

<pre><code class="lang-yaml">k3sreleaseversion: false # defaults to &#39;stable&#39; channel k3sreleaseversion: stable # latest &#39;stable&#39; release k3sreleaseversion: testing # latest &#39;testing&#39; release k3sreleaseversion: v1.19 # latest &#39;v1.19&#39; release k3sreleaseversion: v1.19.3+k3s3 # specific release

Specific commit

CAUTION - only used for testing - must be 40 characters

k3sreleaseversion: 48ed47c4a3e420fa71c18b2ec97f13dc0659778b</code></pre>

Important note about k3sinstallhard_links

If you are using the system-upgrade-controller you will need to use hard links rather than symbolic links as the controller will not be able to follow symbolic links. This option has been added however is not enabled by default to avoid breaking existing installations.

To enable the use of hard links, ensure k3sinstallhard_links is set to true.

<pre><code class="lang-yaml">k3sinstallhard_links: true</code></pre>

The result of this can be seen by running the following in k3sinstalldir:

ls -larthi | grep -E 'k3s|ctr|ctl' | grep -vE ".sh$" | sort

Symbolic Links:

<pre><code class="lang-text">[root@node1 bin]# ls -larthi | grep -E &#39;k3s|ctr|ctl&#39; | grep -vE &quot;.sh$&quot; | sort 3277823 -rwxr-xr-x 1 root root 52M Jul 25 12:50 k3s-v1.18.4+k3s1 3279565 lrwxrwxrwx 1 root root 31 Jul 25 12:52 k3s -&gt; /usr/local/bin/k3s-v1.18.6+k3s1 3279644 -rwxr-xr-x 1 root root 51M Jul 25 12:52 k3s-v1.18.6+k3s1 3280079 lrwxrwxrwx 1 root root 31 Jul 25 12:52 ctr -&gt; /usr/local/bin/k3s-v1.18.6+k3s1 3280080 lrwxrwxrwx 1 root root 31 Jul 25 12:52 crictl -&gt; /usr/local/bin/k3s-v1.18.6+k3s1 3280081 lrwxrwxrwx 1 root root 31 Jul 25 12:52 kubectl -&gt; /usr/local/bin/k3s-v1.18.6+k3s1</code></pre>

Hard Links:

<pre><code class="lang-text">[root@node1 bin]# ls -larthi | grep -E &#39;k3s|ctr|ctl&#39; | grep -vE &quot;.sh$&quot; | sort 3277823 -rwxr-xr-x 1 root root 52M Jul 25 12:50 k3s-v1.18.4+k3s1 3279644 -rwxr-xr-x 5 root root 51M Jul 25 12:52 crictl 3279644 -rwxr-xr-x 5 root root 51M Jul 25 12:52 ctr 3279644 -rwxr-xr-x 5 root root 51M Jul 25 12:52 k3s 3279644 -rwxr-xr-x 5 root root 51M Jul 25 12:52 k3s-v1.18.6+k3s1 3279644 -rwxr-xr-x 5 root root 51M Jul 25 12:52 kubectl</code></pre>

Important note about k3sbuildcluster

If you set k3sbuildcluster to false, this role will install each play host as a standalone node. An example of when you might use this would be when building a large number of standalone IoT devices running K3s. Below is a hypothetical situation where we are to deploy 25 Raspberry Pi devices, each a standalone system and not a cluster of 25 nodes. To do this we'd use a playbook similar to the below:

<pre><code class="lang-yaml">- hosts: k3s_nodes # eg. 25 RPi&#39;s defined in our inventory. vars: k3sbuildcluster: false roles: - xanmanning.k3s</code></pre>

Important note about k3scontrolnode and High Availability (HA)

By default only one host will be defined as a control node by Ansible, If you do not set a host as a control node, this role will automatically delegate the first play host as a control node. This is not suitable for use within a Production workload.

If multiple hosts have k3scontrolnode set to true, you must also set datastore-endpoint in k3s_server as the connection string to a MySQL or PostgreSQL database, or external Etcd cluster else the play will fail.

If using TLS, the CA, Certificate and Key need to already be available on the play hosts.

See: High Availability with an External DB

It is also possible, though not supported, to run a single K3s control node with a datastore-endpoint defined. As this is not a typically supported configuration you will need to set k3suseunsupported_config to true.

Since K3s v1.19.1 it is possible to use an embedded Etcd as the backend database, and this is done by setting k3setcddatastore to true. The best practice for Etcd is to define at least 3 members to ensure quorum is established. In addition to this, an odd number of members is recommended to ensure a majority in the event of a network partition. If you want to use 2 members or an even number of members, please set k3suseunsupported_config to true.

Important note about k3sservermanifestsurls and k3sserverpodmanifests_urls

To deploy server manifests and server pod manifests from URL, you need to specify a url and optionally a filename (if none provided basename is used). Below is an example of how to deploy the Tigera operator for Calico and kube-vip.

<pre><code class="lang-yaml">---

k3sservermanifests_urls: - url: https://docs.projectcalico.org/archive/v3.19/manifests/tigera-operator.yaml filename: tigera-operator.yaml

k3sserverpodmanifestsurls: - url: https://raw.githubusercontent.com/kube-vip/kube-vip/main/example/deploy/0.1.4.yaml filename: kube-vip.yaml</code></pre>

Important note about k3s_airgap

When deploying k3s in an air gapped environment you should provide the k3s binary in ./files/. The binary will not be downloaded from Github and will subsequently not be verified using the provided sha256 sum, nor able to verify the version that you are running. All risks and burdens associated are assumed by the user in this scenario.

Dependencies

No dependencies on other roles.

Example Playbooks

Example playbook, single control node running testing` channel k3s:

- hosts: k3s_nodes
  vars:
    k3sreleaseversion: testing
  roles:
     - role: xanmanning.k3s

Example playbook, Highly Available with PostgreSQL database running the latest stable release:

- hosts: k3s_nodes
  vars:
    k3sregistrationaddress: loadbalancer  # Typically a load balancer.
    k3s_server:
      datastore-endpoint: "postgres://postgres:verybadpass@database:5432/postgres?sslmode=disable"
  pre_tasks:
    - name: Set each node to be a control node
      ansible.builtin.set_fact:
        k3scontrolnode: true
      when: inventory_hostname in ['node2', 'node3']
  roles:
    - role: xanmanning.k3s

License

BSD 3-clause

Contributors

Contributions from the community are very welcome, but please read the contribution guidelines before doing so, this will help make things as streamlined as possible.

Also, please check out the awesome list of contributors.

Author Information

Xan Manning

🔗 More in this category

© 2026 GitRepoTrend · PyratLabs/ansible-role-k3s · Updated daily from GitHub