Added some validation steps, fixed issue with checksum, introducing rootless

as an option, however this is experimental in both K3s and this role.
This commit is contained in:
Xan Manning 2019-12-21 17:11:30 +00:00
parent fe688dfc70
commit f2a3f75f08
23 changed files with 380 additions and 33 deletions

View File

@ -11,7 +11,7 @@ The control host requires the following Python dependencies:
- `jmespath >= 0.9.0`
This role has been tested on Ansible 2.6.0+ against the following Linux Distributions:
This role has been tested on Ansible 2.7.0+ against the following Linux Distributions:
- Amazon Linux 2
- CentOS 8
@ -49,7 +49,11 @@ consistency.
| `k3s_release_version` | Use a specific version of k3s, eg. `v0.2.0`. Specify `false` for latest. | `false` |
| `k3s_github_url` | Set the GitHub URL to install k3s from. | https://github.com/rancher/k3s |
| `k3s_install_dir` | Installation directory for k3s. | `/usr/local/bin` |
| `k3s_use_experimental` | Allow the use of experimental features in k3s. | `false` |
| `k3s_non_root` | Install k3s as non-root user. See notes below. | `false` |
| `k3s_control_workers` | Are control hosts also workers? | `true` |
| `k3s_cluster_cidr` | Network CIDR to use for pod IPs | 10.42.0.0/16 |
| `k3s_service_cidr` | Network CIDR to use for service IPs | 10.43.0.0/16 |
| `k3s_control_node_address` | Use a specific control node address. IP or FQDN. | _NULL_ |
| `k3s_control_token` | Use a specific control token, please read notes below. | _NULL_ |
| `k3s_https_port` | HTTPS port listening port. | 6443 |
@ -59,6 +63,7 @@ consistency.
| `k3s_no_coredns` | Do not use CoreDNS | `false` |
| `k3s_cluster_dns` | Cluster IP for CoreDNS service. Should be in your service-cidr range. | _NULL_ |
| `k3s_cluster_domain` | Cluster Domain. | cluster.local |
| `k3s_resolv_conf` | Kubelet resolv.conf file | _NULL_ |
| `k3s_no_traefik` | Do not use Traefik | `false` |
| `k3s_no_servicelb` | Do not use ServiceLB, necessary for using something like MetalLB. | `false` |
| `k3s_no_local_storage` | Do not use Local Storage | `false` |
@ -78,6 +83,16 @@ ensure this is set in your Ansible configuration, eg:
k3s_release_version: v0.2.0
```
#### Important note about `k3s_non_root`
To install k3s as non root you must not use `become: true`. The intention of
this variable is to run a single node development environment. At the time
of release v1.0.1, rootless is still experimental.
You must also ensure that you set `k3s_use_experimental` to `true`.
Additionally `k3s_install_dir` must be writable by your user.
#### Important notes about `k3s_control_node_address` and `k3s_control_token`
If you set this, you are explicitly specifying the control host that agents
@ -92,18 +107,19 @@ Please note that this may potentially break setting up agents.
Below are variables that are set against specific hosts in your inventory.
| Variable | Description | Default Value |
|-----------------------------|--------------------------------------------------------|------------------------|
| `k3s_control_node` | Define the host as a control plane node, (True/False). | `false` |
| `k3s_node_name` | Define the name of this node. | `$(hostname)` |
| `k3s_node_id` | Define the ID of this node. | _NULL_ |
| `k3s_flannel_interface` | Define the flannel proxy interface for this node. | _NULL_ |
| `k3s_bind_address` | Define the bind address for this node. | localhost |
| `k3s_node_ip_address` | IP Address to advertise for this node. | _NULL_ |
| `k3s_node_external_address` | External IP Address to advertise for this node. | _NULL_ |
| `k3s_node_labels` | List of node labels. | _NULL_ |
| `k3s_node_taints` | List of node taints. | _NULL_ |
| `k3s_node_data_dir` | Folder to hold state. | `/var/lib/rancher/k3s` |
| Variable | Description | Default Value |
|-----------------------------|--------------------------------------------------------------------------|------------------------|
| `k3s_control_node` | Define the host as a control plane node, (True/False). | `false` |
| `k3s_node_name` | Define the name of this node. | `$(hostname)` |
| `k3s_node_id` | Define the ID of this node. | _NULL_ |
| `k3s_flannel_interface` | Define the flannel proxy interface for this node. | _NULL_ |
| `k3s_bind_address` | Define the bind address for this node. | localhost |
| `k3s_node_ip_address` | IP Address to advertise for this node. | _NULL_ |
| `k3s_node_external_address` | External IP Address to advertise for this node. | _NULL_ |
| `k3s_node_labels` | List of node labels. | _NULL_ |
| `k3s_node_taints` | List of node taints. | _NULL_ |
| `k3s_node_data_dir` | Folder to hold state. | `/var/lib/rancher/k3s` |
| `k3s_tls_san` | Add additional hosname or IP as Subject Alternate Name in the TLS cert. | _NULL_ |
#### Important note about `k3s_control_node`

View File

@ -14,6 +14,9 @@ k3s_github_url: https://github.com/rancher/k3s
# Installation directory for k3s
k3s_install_dir: /usr/local/bin
# Use experimental features in k3s?
k3s_use_experimental: false
# Are control hosts also worker nodes?
k3s_control_workers: true
@ -27,7 +30,7 @@ k3s_use_docker: false
k3s_no_flannel: false
# Flannel backend ('none', 'vxlan', 'ipsec', or 'wireguard')
k3s_flannel_backend: vxlan
# k3s_flannel_backend: vxlan
# Disable CoreDNS, you will need to install your own DNS provider.
k3s_no_coredns: false
@ -37,7 +40,7 @@ k3s_no_coredns: false
k3s_cluster_dns: false
# Cluster Domain (default: "cluster.local")
k3s_cluster_domain: cluster.local
# k3s_cluster_domain: cluster.local
# Disable Traefik
k3s_no_traefik: false

View File

@ -3,15 +3,17 @@
- name: reload systemd
systemd:
daemon_reload: true
scope: "{{ k3s_systemd_context }}"
- name: restart k3s
service:
systemd:
name: k3s
state: restarted
scope: "{{ k3s_systemd_context }}"
enabled: true
- name: restart docker
service:
systemd:
name: docker
state: restarted
enabled: true

View File

@ -19,7 +19,7 @@ galaxy_info:
# - CC-BY
license: BSD
min_ansible_version: 2.6
min_ansible_version: 2.7
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:

View File

@ -41,6 +41,7 @@ provisioner:
lint:
name: ansible-lint
playbooks:
prepare: ${MOLECULE_PREPARE_PLAYBOOK:-prepare.yml}
converge: ${MOLECULE_PLAYBOOK:-playbook.yml}
verifier:
name: testinfra

View File

@ -0,0 +1,12 @@
---
- name: Converge
hosts: node1
become: true
become_user: k3suser
vars:
molecule_is_test: true
k3s_non_root: true
k3s_use_experimental: true
k3s_install_dir: "/home/{{ ansible_user_id }}/bin"
roles:
- role: xanmanning.k3s

View File

@ -0,0 +1,9 @@
---
- name: Converge
hosts: all
become: true
vars:
molecule_is_test: true
k3s_release_version: v0.4.0
roles:
- role: xanmanning.k3s

View File

@ -0,0 +1,22 @@
---
- name: Prepare
hosts: all
become: true
tasks:
- name: Ensure a user group exists
group:
name: user
state: present
- name: Ensure a normal user exists
user:
name: k3suser
group: user
state: present
- name: Ensure a normal user has bin directory
file:
path: /home/k3suser/bin
state: directory
owner: k3suser
group: user

View File

@ -0,0 +1,7 @@
---
- name: Prepare
hosts: all
tasks:
- name: Debug Message
debug:
msg: No prepare steps required

View File

@ -18,9 +18,14 @@
- name: Ensure sha256sum is set from hashsum variable
set_fact:
k3s_hash_sum: "{{ (k3s_hash_sum_raw.content.split('\n') | select('search', k3s_arch_suffix) | first).split() | first }}"
k3s_hash_sum: "{{ (k3s_hash_sum_raw.content.split('\n') | select('search', 'k3s') | first).split() | first }}"
changed_when: false
- name: Ensure installation directory exists
file:
path: "{{ k3s_install_dir }}"
state: directory
- name: Ensure k3s binary is downloaded
get_url:
url: "{{ k3s_binary_url }}"

View File

@ -0,0 +1,7 @@
---
- name: Ensure systemd context is correct if we are running k3s rootless
set_fact:
k3s_systemd_context: user
k3s_systemd_unit_directory: "{{ ansible_user_dir }}/.config/systemd/user"
when: k3s_non_root is defined and k3s_non_root

View File

@ -1,9 +1,16 @@
---
- name: Ensure systemd unit file directory exists
file:
path: "{{ k3s_systemd_unit_directory }}"
state: directory
recurse: true
when: k3s_control_node
- name: Ensure k3s service unit file is present on control plane
template:
src: k3s.service.j2
dest: /etc/systemd/system/k3s.service
dest: "{{ k3s_systemd_unit_directory }}/k3s.service"
when: k3s_control_node
notify:
- reload systemd
@ -24,8 +31,9 @@
- ctr
- name: Ensure k3s control plane is started
service:
systemd:
name: k3s
state: started
enabled: true
scope: "{{ k3s_systemd_context }}"
when: k3s_control_node

View File

@ -18,8 +18,3 @@
k3s_controller_count: "{{ k3s_controller_count + [ item ] }}"
when: item
loop: "{{ hostvars | json_query('*.k3s_control_node') }}"
- name: Fail playbook if there are multiple controllers defined
fail:
msg: "Multiple controllers have been defined. This is not yet supported."
when: k3s_controller_count | length > 1

View File

@ -1,7 +1,16 @@
---
- name: Ensure k3s service is started
service:
systemd:
name: k3s
state: started
enabled: true
when: k3s_non_root is not defined or not k3s_non_root
- name: Ensure k3s service is started
systemd:
name: k3s
state: started
enabled: true
scope: user
when: k3s_non_root is defined and k3s_non_root

View File

@ -1,7 +1,16 @@
---
- name: Ensure k3s service is stopped
service:
systemd:
name: k3s
state: stopped
enabled: false
when: k3s_non_root is not defined or not k3s_non_root
- name: Ensure k3s service is started
systemd:
name: k3s
state: stopped
enabled: false
scope: user
when: k3s_non_root is defined and k3s_non_root

View File

@ -1,23 +1,30 @@
---
- import_tasks: preconfigure-k3s.yml
- import_tasks: build/preconfigure-k3s.yml
- import_tasks: build/get-version.yml
when: k3s_release_version is not defined or not k3s_release_version
- import_tasks: validate/main.yml
- import_tasks: build/get-systemd-context.yml
- include_tasks: build/install-docker-prerequisites-{{ ansible_os_family | lower }}.yml
when: k3s_use_docker
and ((k3s_control_workers)
or (not k3s_control_workers and not k3s_control_node))
and (k3s_non_root is not defined or not k3s_non_root)
- import_tasks: build/install-docker.yml
when: k3s_use_docker
and ((k3s_control_workers)
or (not k3s_control_workers and not k3s_control_node))
and ansible_distribution | replace(" ", "-") | lower not in ['amazon', 'suse', 'opensuse-leap']
and (k3s_non_root is not defined or not k3s_non_root)
- include_tasks: build/install-docker-{{ ansible_distribution | replace(" ", "-") | lower }}.yml
when: ansible_distribution | replace(" ", "-") | lower in ['amazon', 'suse', 'opensuse-leap']
- import_tasks: build/get-version.yml
when: k3s_release_version is not defined or not k3s_release_version
and (k3s_non_root is not defined or not k3s_non_root)
- import_tasks: build/download-k3s.yml

View File

@ -0,0 +1,9 @@
---
- name: Check k3s_non_root is enabled with k3s_use_experimental
assert:
that:
- k3s_use_experimental is defined and k3s_use_experimental
success_msg: "Experimental variables are defined and enabled."
fail_msg: "Experimental variables have been configured. If you want to use them ensure you set k3s_use_experimental"
when: k3s_non_root is defined and k3s_non_root

View File

@ -0,0 +1,8 @@
---
- name: Check if multiple controllers defined
assert:
that:
- k3s_controller_count | length == 1
success_msg: "Only one controller has been defined."
fail_msg: "Multiple controllers have been defined. This is not yet supported."

View File

@ -0,0 +1,54 @@
---
- name: Check if /proc/sys/kernel/unprivileged_userns_clone exists
stat:
path: /proc/sys/kernel/unprivileged_userns_clone
register: k3s_check_unprivileged_userns_exists
- name: Get the value of /proc/sys/kernel/unprivileged_userns_clone
slurp:
src: /proc/sys/kernel/unprivileged_userns_clone
register: k3s_get_unprivileged_userns_clone
when: k3s_check_unprivileged_userns_exists.stat.exists
- name: Set the value of k3s_get_unprivileged_userns_clone
set_fact:
k3s_get_unprivileged_userns_clone:
content: "MQo="
when: not k3s_check_unprivileged_userns_exists.stat.exists
- name: Get the value of /proc/sys/user/max_user_namespaces
slurp:
src: /proc/sys/user/max_user_namespaces
register: k3s_get_max_user_namespaces
- name: Get the contents of /etc/subuid
slurp:
src: /etc/subuid
register: k3s_get_subuid
- name: Get the contents of /etc/subgid
slurp:
src: /etc/subgid
register: k3s_get_subgid
- name: Get current user subuid and subgid values
set_fact:
k3s_current_user_subuid: "{{ (k3s_get_subuid['content'] | b64decode).split('\n')
| select('search', ansible_user_id) | first | default('UserNotFound:0:0') }}"
k3s_current_user_subgid: "{{ (k3s_get_subgid['content'] | b64decode).split('\n')
| select('search', ansible_user_id) | first | default('UserNotFound:0:0') }}"
- name: Check user namespaces kernel parameters are adequate
assert:
that:
- k3s_get_unprivileged_userns_clone['content'] | b64decode | int == 1
- k3s_get_max_user_namespaces['content'] | b64decode | int >= 28633
- k3s_current_user_subuid != "UserNotFound:0:0"
- k3s_current_user_subgid != "UserNotFound:0:0"
- k3s_current_user_subuid.split(':')[2] | int >= 65536
- k3s_current_user_subgid.split(':')[2] | int >= 65536
- ansible_env['XDG_RUNTIME_DIR'] is defined
success_msg: All kernel parameters passed
fail_msg: Kernel parameters are not set correctly, please check
https://github.com/rootless-containers/rootlesskit

View File

@ -0,0 +1,139 @@
---
- name: Check k3s_no_flannel against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.2.0', '>=')
success_msg: "--no-flannel is supported in {{ k3s_release_version }}"
fail_msg: "--no-flannel is not supported in {{ k3s_release_version }}"
when: k3s_no_flannel is defined and k3s_no_flannel
- name: Check k3s_service_cidr against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.2.0', '>=')
success_msg: "--service-cidr is supported in {{ k3s_release_version }}"
fail_msg: "--service-cidr is not supported in {{ k3s_release_version }}"
when: k3s_service_cidr is defined
- name: Check k3s_cluster_dns against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.2.0', '>=')
success_msg: "--cluster-dns is supported in {{ k3s_release_version }}"
fail_msg: "--cluster-dns is not supported in {{ k3s_release_version }}"
when: k3s_cluster_dns is defined and k3s_cluster_dns
- name: Check k3s_use_docker against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.2.0', '>=')
success_msg: "--docker is supported in {{ k3s_release_version }}"
fail_msg: "--docker is not supported in {{ k3s_release_version }}"
when: k3s_use_docker is defined and k3s_use_docker
- name: Check k3s_no_traefik against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.2.0', '>=')
success_msg: "--no-deploy traefik is supported in {{ k3s_release_version }}"
fail_msg: "--no-deploy traefik is not supported in {{ k3s_release_version }}"
when: k3s_no_traefik is defined and k3s_no_traefik
- name: Check k3s_non_root against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.4.0', '>=')
- ansible_user_id != "root"
- play_hosts | length == 1
success_msg: "k3s_non_root is supported in {{ k3s_release_version }}"
fail_msg: "k3s_non_root only works in >= v0.4.0, on a single node and must not be installed as root."
when: k3s_non_root is defined and k3s_non_root
- name: Check k3s_resolv_conf against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.3.0', '>=')
success_msg: "--resolv-conf is supported in {{ k3s_release_version }}"
fail_msg: "--resolv-conf is not supported in {{ k3s_release_version }}"
when: k3s_resolv_conf is defined and k3s_resolv_conf
- name: Check k3s_tls_san against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.3.0', '>=')
success_msg: "--tls-san is supported in {{ k3s_release_version }}"
fail_msg: "--tls-san is not supported in {{ k3s_release_version }}"
when: k3s_tls_san is defined and k3s_tls_san
- name: Check k3s_flannel_interface against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.4.0', '>=')
success_msg: "--flannel-iface is supported in {{ k3s_release_version }}"
fail_msg: "--flannel-iface is not supported in {{ k3s_release_version }}"
when: k3s_flannel_interface is defined and k3s_flannel_interface
- name: Check k3s_cluster_domain against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.4.0', '>=')
success_msg: "--cluster-domain is supported in {{ k3s_release_version }}"
fail_msg: "--cluster-domain is not supported in {{ k3s_release_version }}"
when: k3s_cluster_domain is defined and k3s_cluster_domain
- name: Check k3s_bind_address against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.4.0', '>=')
success_msg: "--bind-address is supported in {{ k3s_release_version }}"
fail_msg: "--bind-address is not supported in {{ k3s_release_version }}"
when: k3s_bind_address is defined and k3s_bind_address
- name: Check k3s_node_labels against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.6.0', '>=')
success_msg: "Node Labels supported in {{ k3s_release_version }}"
fail_msg: "Node Labels are not supported in {{ k3s_release_version }}"
when: k3s_node_labels is defined and k3s_node_labels
- name: Check k3s_node_taints against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.6.0', '>=')
success_msg: "Node Taints supported in {{ k3s_release_version }}"
fail_msg: "Node Taints are not supported in {{ k3s_release_version }}"
when: k3s_node_taints is defined and k3s_node_taints
- name: Check k3s_flannel_backend against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.10.0', '>=')
success_msg: "Alternate flannel backends supported in {{ k3s_release_version }}"
fail_msg: "Alternate flannel backends are not supported in {{ k3s_release_version }}"
when: k3s_flannel_backend is defined and k3s_flannel_backend
- name: Check k3s_disable_network_policy against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('0.10.0', '>=')
success_msg: "--disable-network-policy supported in {{ k3s_release_version }}"
fail_msg: "--disable-network-policy not supported in {{ k3s_release_version }}"
when: k3s_disable_network_policy is defined and k3s_disable_network_policy
- name: Check k3s_disable_cloud_controller against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('1.0.0', '>=')
success_msg: "--disable-cloud-controller supported in {{ k3s_release_version }}"
fail_msg: "--disable-cloud-controller not supported in {{ k3s_release_version }}"
when: k3s_disable_cloud_controller is defined and k3s_disable_cloud_controller
- name: Check k3s_disable_scheduler against k3s version
assert:
that:
- (k3s_release_version | replace('v', '')) is version_compare('1.0.0', '>=')
success_msg: "--disable-scheduler supported in {{ k3s_release_version }}"
fail_msg: "--disable-scheduler not supported in {{ k3s_release_version }}"
when: k3s_disable_scheduler is defined and k3s_disable_scheduler

7
tasks/validate/main.yml Normal file
View File

@ -0,0 +1,7 @@
---
- import_tasks: check-variables.yml
- import_tasks: check-experimental-variables.yml
- import_tasks: check-unsupported-rootless.yml
when: k3s_non_root is defined and k3s_non_root
- import_tasks: check-master-count.yml

View File

@ -12,6 +12,9 @@ ExecStartPre=-/sbin/modprobe overlay
ExecStart={{ k3s_install_dir }}/k3s
{% if k3s_control_node %}
server{{ ' --disable-agent' if not k3s_control_workers else '' }}
{% if k3s_non_root is defined and k3s_non_root %}
--rootless
{% endif %}
{% if k3s_https_port != 6443 %}
--https-listen-port {{ k3s_https_port }}
{% endif %}
@ -31,7 +34,13 @@ ExecStart={{ k3s_install_dir }}/k3s
--flannel-backend none
{% endif %}
{% endif %}
{% if k3s_flannel_backend != "vxlan" and not k3s_no_flannel %}
{% if k3s_cluster_cidr is defined %}
--cluster-cidr {{ k3s_cluster_cidr }}
{% endif %}
{% if k3s_service_cidr is defined %}
--service-cidr {{ k3s_service_cidr }}
{% endif %}
{% if k3s_flannel_backend is defined and not k3s_no_flannel %}
--flannel-backend {{ k3s_flannel_backend }}
{% endif %}
{% if k3s_no_coredns is defined or k3s_no_traefik is defined or k3s_no_servicelb is defined %}
@ -50,6 +59,12 @@ ExecStart={{ k3s_install_dir }}/k3s
--server https://{{ k3s_control_node_address }}:{{ k3s_https_port }}
--token {{ k3s_control_token }}
{% endif %}
{% if k3s_resolv_conf is defined and k3s_resolv_conf %}
--resolv-conf {{ k3s_resolv_conf }}
{% endif %}
{% if k3s_tls_san is defined and k3s_tls_san %}
--tls-san {{ k3s_tls_san }}
{% endif %}
{% if k3s_node_data_dir is defined %}
--data-dir {{ k3s_node_data_dir }}
{% endif %}

View File

@ -28,3 +28,6 @@ k3s_arch_lookup:
k3s_github_download_url: "{{ k3s_github_url }}/releases/download"
k3s_controller_count: []
k3s_systemd_context: system
k3s_systemd_unit_directory: "/etc/systemd/{{ k3s_systemd_context }}"