diff --git a/README.md b/README.md index 573f7e6..6df7735 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,11 @@ consistency. | `k3s_disable_cloud_controller` | Disable k3s default cloud controller manager. | `false` | | `k3s_disable_network_policy` | Disable k3s default network policy controller. | `false` | | `k3s_write_kubeconfig_mode` | Define the file mode from the generated KubeConfig, eg. `644` | _NULL_ | +| `k3s_datastore_endpoint` | Define the database or etcd cluster endpoint for HA. | _NULL_ | +| `k3s_datastore_cafile` | Define the database TLS CA file. | _NULL_ | +| `k3s_datastore_certfile` | Define the database TLS Cert file. | _NULL_ | +| `k3s_datastore_keyfile` | Define the database TLS Key file. | _NULL_ | +| `k3s_dqlite_datastore` | Use DQLite as the database backend for HA. (EXPERIMENTAL) | `false` | #### Important note about `k3s_release_version` @@ -121,13 +126,25 @@ Below are variables that are set against specific hosts in your inventory. | `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` +#### Important note about `k3s_control_node` and High Availability (HA) -Currently only one host can be defined as a control node, if multiple hosts are -set to true the play will fail. +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, the role will automatically delegate +the first play host as a control node (master). This is not suitable for use in +a Production workload. -If you do not set a host as a control node, the role will automatically delegate -the first play host as a control node. +If multiple hosts have `k3s_control_node` set to true, you must also set +`k3s_datastore_endpoint` as the connection string to a MySQL or PostgreSQL +database, or 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](https://rancher.com/docs/k3s/latest/en/installation/ha/) + +Since K3s v1.0.0 it is possible to use DQLite as the backend database, and this +is done by setting `k3s_dqlite_datastore` to true. As this is an experimental +feature you will also need to set `k3s_use_experimental` to true. #### Important note about `k3s_flannel_interface` diff --git a/defaults/main.yml b/defaults/main.yml index e4f27a2..1d077b7 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -17,6 +17,27 @@ k3s_install_dir: /usr/local/bin # Use experimental features in k3s? k3s_use_experimental: false +# Use a database or etcd cluster to enable HA. Examples below: +# MySQL: +# k3s_datastore_endpoint "mysql://username:password@tcp(hostname:3306)/database-name" +# PostgreSQL: +# k3s_datastore_endpoint: "postgres://username:password@hostname:port/database-name" +# Etcd: +# k3s_datastore_endpoint: "https://etcd-host-1:2379,https://etcd-host-2:2379,https://etcd-host-3:2379" +k3s_datastore_endpoint: false + +# If using a database endpoint for HA, you can optionally set the CA file, +# Cert file and Key file for connecting to the database using TLS. +# +# These need to already be present on the play hosts. +# +# k3s_datastore_cafile: /path/to/ca.crt +# k3s_datastore_certfile: /path/to/cert.crt +# k3s_datastore_keyfile: /path/to/key.pem + +# Use DQLite for HA Datastore? (EXPERIMENTAL) +k3s_dqlite_datastore: false + # Are control hosts also worker nodes? k3s_control_workers: true diff --git a/tasks/validate/check-experimental-variables.yml b/tasks/validate/check-experimental-variables.yml index ee9b16a..fc3c992 100644 --- a/tasks/validate/check-experimental-variables.yml +++ b/tasks/validate/check-experimental-variables.yml @@ -1,9 +1,10 @@ --- -- name: Check k3s_non_root is enabled with k3s_use_experimental +- name: Check if any experimental variables are configure and if they are enabled with k3s_use_experimental assert: that: - k3s_use_experimental is defined and k3s_use_experimental + - k3s_dqlite_datastore 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 diff --git a/tasks/validate/check-master-count.yml b/tasks/validate/check-master-count.yml index 5c34ccd..8e248ca 100644 --- a/tasks/validate/check-master-count.yml +++ b/tasks/validate/check-master-count.yml @@ -1,8 +1,21 @@ --- -- name: Check if multiple controllers defined +- name: Check the conditions when a single controller is 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." + - (k3s_controller_count | length == 1) + and (k3s_datastore_endpoint is not defined or not k3s_datastore_endpoint) + and (k3s_dqlite_datastore is not defined or not k3s_dqlite_datastore) + 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." + when: k3s_controller_count | length == 1 + +- name: Check the conditions when multiple controllers are defined + assert: + that: + - (k3s_controller_count | length >= 2) + and ((k3s_datastore_endpoint is defined and k3s_datastore_endpoint) + or k3s_dqlite_datastore is defined and k3s_dqlite_datastore) + 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." + when: k3s_controller_count | length >= 2 diff --git a/tasks/validate/check-variables.yml b/tasks/validate/check-variables.yml index 263735d..f5f9dd6 100644 --- a/tasks/validate/check-variables.yml +++ b/tasks/validate/check-variables.yml @@ -137,3 +137,43 @@ 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 + +- name: Check k3s_datastore_endpoint against k3s version + assert: + that: + - (k3s_release_version | replace('v', '')) is version_compare('1.0.0', '>=') + success_msg: "--datastore-endpoint supported in {{ k3s_release_version }}" + fail_msg: "--datastore-endpoint not supported in {{ k3s_release_version }}" + when: k3s_datastore_endpoint is defined and k3s_datastore_endpoint + +- name: Check k3s_dqlite_datastore against k3s version + assert: + that: + - (k3s_release_version | replace('v', '')) is version_compare('1.0.0', '>=') + success_msg: "--cluster-init supported in {{ k3s_release_version }}" + fail_msg: "--cluster-init not supported in {{ k3s_release_version }}" + when: k3s_dqlite_datastore is defined and k3s_dqlite_datastore + +- name: Check k3s_datastore_cafile against k3s version + assert: + that: + - (k3s_release_version | replace('v', '')) is version_compare('1.0.0', '>=') + success_msg: "--datastore-endpoint supported in {{ k3s_release_version }}" + fail_msg: "--datastore-endpoint not supported in {{ k3s_release_version }}" + when: k3s_datastore_cafile is defined and k3s_datastore_cafile + +- name: Check k3s_datastore_certfile against k3s version + assert: + that: + - (k3s_release_version | replace('v', '')) is version_compare('1.0.0', '>=') + success_msg: "--datastore-endpoint supported in {{ k3s_release_version }}" + fail_msg: "--datastore-endpoint not supported in {{ k3s_release_version }}" + when: k3s_datastore_certfile is defined and k3s_datastore_certfile + +- name: Check k3s_datastore_keyfile against k3s version + assert: + that: + - (k3s_release_version | replace('v', '')) is version_compare('1.0.0', '>=') + success_msg: "--datastore-endpoint supported in {{ k3s_release_version }}" + fail_msg: "--datastore-endpoint not supported in {{ k3s_release_version }}" + when: k3s_datastore_keyfile is defined and k3s_datastore_keyfile