Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-deploy templates, HA support now possible. #6

Merged
merged 21 commits into from
Jan 13, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
734e49a
Documentation, and validation logic for HA configuration added.
xanmanning Jan 11, 2020
2307546
add support place k8s manifests to the nodes
Jan 11, 2020
2b646e4
update task documentation and add new config parameters to the Readme
Jan 11, 2020
b89f2f3
remove trailing spaces
Jan 11, 2020
2aedce0
add first draft for running molecule test with auto manifests deploym…
Jan 11, 2020
cb13c5b
create manifests directory if not exists
Jan 11, 2020
1dd9297
change template path for molecule test
Jan 11, 2020
227b24c
Update defaults/main.yml
nolte Jan 11, 2020
2e03ea2
Update tasks/build/preconfigure-k3s-auto-deploying-manifests.yml
nolte Jan 11, 2020
b896e90
Update tasks/build/preconfigure-k3s-auto-deploying-manifests.yml
nolte Jan 11, 2020
a73a1fb
Update molecule/default/playbook-auto-deploying-manifests.yml
nolte Jan 11, 2020
2d0dc8d
Update molecule/default/templates/00-ns-monitoring.yml.j2
nolte Jan 11, 2020
c3ae2b7
Added database container and proved connectivity. Logic needs to be c…
xanmanning Jan 11, 2020
09fc37e
Fixed provisioning of multi-master, need to test LB with k3s_control_…
xanmanning Jan 11, 2020
5331e22
fix path, missing prefix
Jan 11, 2020
7e7cf2b
Moved HA testing to a new scenario
xanmanning Jan 12, 2020
3a1c7e7
Added workflow for Database backed and DQLite HA
xanmanning Jan 12, 2020
3ef36b8
Merge branch 'multi_master_support' into feature/add_manifests
xanmanning Jan 13, 2020
c8fb27e
Merge pull request #5 from nolte/feature/add_manifests
xanmanning Jan 13, 2020
e3ce213
Testing auto-deploy on multi-master
xanmanning Jan 13, 2020
c5b6dcd
Fixed control nodes to match nginx template in test
xanmanning Jan 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ services: docker
env:
global:
- ROLE_NAME: k3s
- MOLECULE_SCENARIO: default
matrix:
- MOLECULE_DISTRO: geerlingguy/docker-centos8-ansible:latest
- MOLECULE_DISTRO: geerlingguy/docker-centos7-ansible:latest
Expand Down Expand Up @@ -37,6 +38,15 @@ env:
# Test auto deploying manifests
- MOLECULE_DISTRO: geerlingguy/docker-ubuntu1804-ansible:latest
MOLECULE_PLAYBOOK: playbook-auto-deploying-manifests.yml

# Test multiple masters in control plane with PostgreSQL
- MOLECULE_DISTRO: geerlingguy/docker-centos8-ansible:latest
MOLECULE_SCENARIO: highavailability

# Test multiple masters in control plane with DQLite
- MOLECULE_DISTRO: geerlingguy/docker-centos8-ansible:latest
MOLECULE_SCENARIO: highavailability
MOLECULE_PLAYBOOK: playbook-dqlite.yml

install:
# Install test dependencies.
Expand All @@ -45,12 +55,12 @@ install:
before_script:
# Use actual Ansible Galaxy role name for the project directory.
- cd ../
- mv ansible-role-$ROLE_NAME xanmanning.$ROLE_NAME
- cd xanmanning.$ROLE_NAME
- mv ansible-role-${ROLE_NAME} xanmanning.${ROLE_NAME}
- cd xanmanning.${ROLE_NAME}

script:
# Run tests.
- molecule test
- molecule test --scenario-name "${MOLECULE_SCENARIO}"

notifications:
webhooks: https://galaxy.ansible.com/api/v1/notifications/
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down Expand Up @@ -124,13 +129,25 @@ Below are variables that are set against specific hosts in your inventory.
| `k3s_server_manifests_templates` | A list of Auto-Deploying Manifests Templates. | [] |


#### 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`

Expand Down
21 changes: 21 additions & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,27 @@ k3s_server_manifests_templates: []
# 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

Expand Down
2 changes: 1 addition & 1 deletion molecule/default/prepare-rootless.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
- name: Prepare
hosts: all
hosts: node1
become: true
tasks:
- name: Ensure a user group exists
Expand Down
14 changes: 14 additions & 0 deletions molecule/highavailability/Dockerfile.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Molecule managed

{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}

RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi
22 changes: 22 additions & 0 deletions molecule/highavailability/INSTALL.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
*******
Docker driver installation guide
*******

Requirements
============

* Docker Engine

Install
=======

Please refer to the `Virtual environment`_ documentation for installation best
practices. If not using a virtual environment, please consider passing the
widely recommended `'--user' flag`_ when invoking ``pip``.

.. _Virtual environment: https://virtualenv.pypa.io/en/latest/
.. _'--user' flag: https://packaging.python.org/tutorials/installing-packages/#installing-to-the-user-site

.. code-block:: bash
$ pip install 'molecule[docker]'
67 changes: 67 additions & 0 deletions molecule/highavailability/molecule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---

dependency:
name: galaxy
driver:
name: docker
lint:
name: yamllint
platforms:
- name: node1
image: "${MOLECULE_DISTRO:-geerlingguy/docker-centos8-ansible:latest}"
command: ${MOLECULE_DOCKER_COMMAND:-""}
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
pre_build_image: ${MOLECULE_PREBUILT:-true}
networks:
- name: k3snet
- name: node2
image: "${MOLECULE_DISTRO:-geerlingguy/docker-centos8-ansible:latest}"
command: ${MOLECULE_DOCKER_COMMAND:-""}
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
pre_build_image: ${MOLECULE_PREBUILT:-true}
networks:
- name: k3snet
- name: node3
image: "${MOLECULE_DISTRO:-geerlingguy/docker-centos8-ansible:latest}"
command: ${MOLECULE_DOCKER_COMMAND:-""}
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
pre_build_image: ${MOLECULE_PREBUILT:-true}
networks:
- name: k3snet
- name: database
image: postgres:11-alpine
pre_build_image: true
command: "postgres"
env:
POSTGRES_PASSWORD: "verybadpass"
networks:
- name: k3snet
- name: loadbalancer
image: nginx:1.17-alpine
pre_build_image: true
ports:
- "6443:6443"
volumes:
- ${MOLECULE_SCENARIO_DIRECTORY}/nginx-loadbalancer.conf:/etc/nginx/nginx.conf:ro
command: "nginx -g 'daemon off;'"
networks:
- name: k3snet
provisioner:
name: ansible
options:
verbose: true
lint:
name: ansible-lint
playbooks:
prepare: ${MOLECULE_PREPARE_PLAYBOOK:-prepare.yml}
converge: ${MOLECULE_PLAYBOOK:-playbook.yml}
verifier:
name: testinfra
lint:
name: flake8
34 changes: 34 additions & 0 deletions molecule/highavailability/nginx-loadbalancer.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
worker_processes 4;
worker_rlimit_nofile 40000;

events {
worker_connections 8192;
}

stream {
# Set up our upstream of control (master) nodes. The default load balancing
# algorithm for nginx is to round-robin. Perfect!
upstream control_plane {
server node2:6443 max_fails=3 fail_timeout=5s;
server node3:6443 max_fails=3 fail_timeout=5s;
}

upstream control_plane_443 {
server node2:443 max_fails=3 fail_timeout=5s;
server node3:443 max_fails=3 fail_timeout=5s;
}

# Listen on port 6443, this is our default control plane port, then pass
# all traffic to one of the control (master) nodes.
server {
listen 6443;
proxy_pass control_plane;
}

# Listen on port 443, this is our default ssl port, then pass
# all traffic to one of the control (master) nodes.
server {
listen 443;
proxy_pass control_plane_443;
}
}
15 changes: 15 additions & 0 deletions molecule/highavailability/playbook-dqlite.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
- name: Converge
hosts: node*
become: true
vars:
molecule_is_test: true
k3s_dqlite_datastore: true
k3s_use_experimental: true
pre_tasks:
- name: Set each node to be a control node
set_fact:
k3s_control_node: true
when: inventory_hostname in ['node2', 'node3']
roles:
- role: xanmanning.k3s
15 changes: 15 additions & 0 deletions molecule/highavailability/playbook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
- name: Converge
hosts: node*
become: true
vars:
molecule_is_test: true
k3s_control_node_address: loadbalancer
k3s_datastore_endpoint: "postgres://postgres:verybadpass@database:5432/postgres?sslmode=disable"
pre_tasks:
- name: Set each node to be a control node
set_fact:
k3s_control_node: true
when: inventory_hostname in ['node2', 'node3']
roles:
- role: xanmanning.k3s
7 changes: 7 additions & 0 deletions molecule/highavailability/prepare.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
- name: Prepare
hosts: node*
tasks:
- name: Debug Message
debug:
msg: No prepare steps required
14 changes: 14 additions & 0 deletions molecule/highavailability/tests/test_default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import os

import testinfra.utils.ansible_runner

testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')


def test_hosts_file(host):
f = host.file('/etc/hosts')

assert f.exists
assert f.user == 'root'
assert f.group == 'root'
Binary file not shown.
6 changes: 4 additions & 2 deletions tasks/build/configure-k3s-cluster.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
@@@
{{ hostvars[item].ansible_host | default(hostvars[item].ansible_fqdn) }}
@@@
{{ hostvars[item].k3s_control_node }}
C_{{ hostvars[item].k3s_control_node }}
@@@
P_{{ hostvars[item].k3s_primary_control_node | default(False) }}
create: true
loop: "{{ play_hosts }}"

- name: Lookup control node from file
command: "grep 'True' /tmp/inventory.txt"
command: "grep '{{ 'P_True' if (k3s_controller_count | length > 1) else 'C_True' }}' /tmp/inventory.txt"
changed_when: false
register: k3s_control_delegate_raw

Expand Down
9 changes: 6 additions & 3 deletions tasks/build/install-k3s.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
path: "{{ k3s_systemd_unit_directory }}"
state: directory
recurse: true
when: k3s_control_node
when: (k3s_control_node and k3s_controller_count | length == 1)
or (k3s_primary_control_node and k3s_controller_count | length > 1)

- name: Ensure k3s service unit file is present on control plane
template:
src: k3s.service.j2
dest: "{{ k3s_systemd_unit_directory }}/k3s.service"
when: k3s_control_node
when: (k3s_control_node and k3s_controller_count | length == 1)
or (k3s_primary_control_node and k3s_controller_count | length > 1)
notify:
- reload systemd

Expand All @@ -36,4 +38,5 @@
state: started
enabled: true
scope: "{{ k3s_systemd_context }}"
when: k3s_control_node
when: (k3s_control_node and k3s_controller_count | length == 1)
or (k3s_primary_control_node and k3s_controller_count | length > 1)
15 changes: 13 additions & 2 deletions tasks/build/preconfigure-k3s.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
k3s_control_node: false
when: k3s_control_node is not defined

- name: Ensure k3s master control node fact is set
set_fact:
k3s_primary_control_node: false
when: k3s_primary_control_node is not defined

- name: Ensure a k3s control node is defined if none are found in play_hosts
block:
- name: Set control host
Expand All @@ -16,5 +21,11 @@
- name: Ensure a count of control masters is generated
set_fact:
k3s_controller_count: "{{ k3s_controller_count + [ item ] }}"
when: item
loop: "{{ hostvars | json_query('*.k3s_control_node') }}"
when: hostvars[item].k3s_control_node
loop: "{{ play_hosts }}"

- name: Ensure a primary k3s control node is defined if multiple are found in play_hosts
set_fact:
k3s_primary_control_node: true
when: k3s_controller_count | length > 1
and inventory_hostname == k3s_controller_count[0]
5 changes: 3 additions & 2 deletions tasks/validate/check-experimental-variables.yml
Original file line number Diff line number Diff line change
@@ -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
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
when: (k3s_non_root is defined and k3s_non_root)
or (k3s_dqlite_datastore is defined and k3s_dqlite_datastore)
Loading