Initial commit with basic Molecule
Change-Id: If55c8b62cb219e575857ba5395a48ddac5973e01
diff --git a/roles/kubernetes/defaults/main.yml b/roles/kubernetes/defaults/main.yml
new file mode 100644
index 0000000..74f6c2c
--- /dev/null
+++ b/roles/kubernetes/defaults/main.yml
@@ -0,0 +1,35 @@
+# Copyright (c) 2022 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+kubernetes_repo_url: "{{ _kubernetes_upstream_apt_repository }}"
+kubernetes_version: 1.22.7
+
+kubernetes_kernel_modules:
+ - br_netfilter
+
+kubernetes_sysctls:
+ - name: net.ipv4.ip_forward
+ value: 1
+ - name: net.ipv4.tcp_l3mdev_accept
+ value: 1
+ - name: net.ipv4.udp_l3mdev_accept
+ value: 1
+ - name: net.bridge.bridge-nf-call-iptables
+ value: 1
+ - name: net.bridge.bridge-nf-call-ip6tables
+ value: 1
+ - name: net.ipv4.conf.all.rp_filter
+ value: 0
+
+kubernetes_control_plane_group: controllers
diff --git a/roles/kubernetes/files/apt-key.gpg b/roles/kubernetes/files/apt-key.gpg
new file mode 100644
index 0000000..3f0b5a8
--- /dev/null
+++ b/roles/kubernetes/files/apt-key.gpg
Binary files differ
diff --git a/roles/kubernetes/files/haproxy.yaml b/roles/kubernetes/files/haproxy.yaml
new file mode 100644
index 0000000..0c8f04f
--- /dev/null
+++ b/roles/kubernetes/files/haproxy.yaml
@@ -0,0 +1,27 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: haproxy
+ namespace: kube-system
+spec:
+ containers:
+ - image: haproxy:2.5
+ name: haproxy
+ livenessProbe:
+ failureThreshold: 8
+ httpGet:
+ host: localhost
+ path: /healthz
+ port: 6443
+ scheme: HTTPS
+ volumeMounts:
+ - mountPath: /usr/local/etc/haproxy/haproxy.cfg
+ name: haproxyconf
+ readOnly: true
+ hostNetwork: true
+ volumes:
+ - hostPath:
+ path: /etc/haproxy/haproxy.cfg
+ type: FileOrCreate
+ name: haproxyconf
+status: {}
diff --git a/roles/kubernetes/files/keepalived.yaml b/roles/kubernetes/files/keepalived.yaml
new file mode 100644
index 0000000..643ebbe
--- /dev/null
+++ b/roles/kubernetes/files/keepalived.yaml
@@ -0,0 +1,32 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ creationTimestamp: null
+ name: keepalived
+ namespace: kube-system
+spec:
+ containers:
+ - name: keepalived
+ image: us-docker.pkg.dev/vexxhost-infra/openstack/keepalived:2.0.19
+ command: ["keepalived", "-f", "/etc/keepalived/keepalived.conf", "--dont-fork", "--log-console", "--log-detail", "--dump-conf"]
+ resources: {}
+ securityContext:
+ capabilities:
+ add:
+ - NET_ADMIN
+ - NET_BROADCAST
+ - NET_RAW
+ volumeMounts:
+ - mountPath: /etc/keepalived/keepalived.conf
+ name: config
+ - mountPath: /etc/keepalived/check_apiserver.sh
+ name: check
+ hostNetwork: true
+ volumes:
+ - hostPath:
+ path: /etc/keepalived/keepalived.conf
+ name: config
+ - hostPath:
+ path: /etc/keepalived/check_apiserver.sh
+ name: check
+status: {}
diff --git a/roles/kubernetes/meta/main.yml b/roles/kubernetes/meta/main.yml
new file mode 100644
index 0000000..ca80af7
--- /dev/null
+++ b/roles/kubernetes/meta/main.yml
@@ -0,0 +1,16 @@
+# Copyright (c) 2022 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+dependencies:
+ - role: containerd
diff --git a/roles/kubernetes/tasks/bootstrap-cluster.yml b/roles/kubernetes/tasks/bootstrap-cluster.yml
new file mode 100644
index 0000000..8231267
--- /dev/null
+++ b/roles/kubernetes/tasks/bootstrap-cluster.yml
@@ -0,0 +1,57 @@
+# Copyright (c) 2022 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Determine node to use for bootstrapping cluster
+ block:
+ - name: Check if any control plane is bootstrapped
+ ansible.builtin.stat:
+ path: /etc/kubernetes/admin.conf
+ register: _kubernetes_stat
+ loop: "{{ groups[kubernetes_control_plane_group] }}"
+ delegate_to: "{{ item }}"
+ delegate_facts: True
+
+- name: Pick node from pre-existing cluster
+ ansible.builtin.set_fact:
+ _kubernetes_bootstrap_node: "{{ _kubernetes_stat.results | selectattr('stat.exists', 'equalto', true) | map(attribute='item') | first }}"
+ when: _kubernetes_stat.results | selectattr('stat.exists', 'equalto', true) | length > 0
+
+- name: Select first node to initialize cluster
+ ansible.builtin.set_fact:
+ _kubernetes_bootstrap_node: "{{ groups[kubernetes_control_plane_group] | first }}"
+ when: _kubernetes_stat.results | selectattr('stat.exists', 'equalto', true) | length == 0
+
+- name: Print selected bootstrap node
+ ansible.builtin.debug:
+ msg: "{{ _kubernetes_bootstrap_node }}"
+
+- name: Upload cluster configuration for bootstrap node
+ ansible.builtin.template:
+ src: kubeadm.yaml.j2
+ dest: /etc/kubernetes/kubeadm.yaml
+ when: inventory_hostname == _kubernetes_bootstrap_node
+
+- name: Initialize cluster
+ throttle: 1
+ ansible.builtin.shell: |
+ kubeadm init --config /etc/kubernetes/kubeadm.yaml --upload-certs
+ args:
+ creates: /etc/kubernetes/admin.conf
+ environment:
+ PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+ when: inventory_hostname == _kubernetes_bootstrap_node
+
+- name: Join cluster
+ ansible.builtin.include_tasks: join-cluster.yml
+ when: inventory_hostname != _kubernetes_bootstrap_node
diff --git a/roles/kubernetes/tasks/control-plane.yml b/roles/kubernetes/tasks/control-plane.yml
new file mode 100644
index 0000000..cbb8752
--- /dev/null
+++ b/roles/kubernetes/tasks/control-plane.yml
@@ -0,0 +1,89 @@
+# Copyright (c) 2022 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Upload configuration for Keepalived
+ block:
+ - name: Create folder
+ ansible.builtin.file:
+ dest: /etc/keepalived
+ state: directory
+ - name: Upload configuration
+ ansible.builtin.template:
+ src: keepalived.conf.j2
+ dest: /etc/keepalived/keepalived.conf
+ - name: Upload health check
+ ansible.builtin.template:
+ src: check_apiserver.sh.j2
+ dest: /etc/keepalived/check_apiserver.sh
+ mode: 0755
+ - name: Upload Kubernetes manifest
+ ansible.builtin.copy:
+ src: keepalived.yaml
+ dest: /etc/kubernetes/manifests/keepalived.yaml
+
+- name: Upload configuration for HAproxy
+ block:
+ - name: Create folder
+ ansible.builtin.file:
+ dest: /etc/haproxy
+ state: directory
+ - name: Upload configuration
+ ansible.builtin.template:
+ src: haproxy.cfg.j2
+ dest: /etc/haproxy/haproxy.cfg
+ - name: Upload Kubernetes manifest
+ ansible.builtin.copy:
+ src: haproxy.yaml
+ dest: /etc/kubernetes/manifests/haproxy.yaml
+
+- name: Bootstrap cluster
+ include_tasks: bootstrap-cluster.yml
+
+- name: create folder for admin configuration
+ ansible.builtin.file:
+ path: /root/.kube
+ state: directory
+
+- name: copy admin configuration file
+ ansible.builtin.copy:
+ src: /etc/kubernetes/admin.conf
+ dest: /root/.kube/config
+ mode: 0600
+ remote_src: true
+
+- name: install pip
+ ansible.builtin.apt:
+ name: python3-pip
+ install_recommends: false
+
+- name: install kubernetes python package
+ ansible.builtin.pip:
+ name: kubernetes
+
+- name: Allow workloads on control plane nodes
+ run_once: true
+ ansible.builtin.shell: |
+ kubectl taint nodes --all node-role.kubernetes.io/master-
+ ignore_errors: true
+ changed_when: false
+
+- name: Add labels to control plane nodes
+ kubernetes.core.k8s:
+ state: patched
+ kind: Node
+ name: "{{ inventory_hostname_short }}"
+ definition:
+ metadata:
+ labels:
+ openstack-control-plane: enabled
diff --git a/roles/kubernetes/tasks/join-cluster.yml b/roles/kubernetes/tasks/join-cluster.yml
new file mode 100644
index 0000000..b65e347
--- /dev/null
+++ b/roles/kubernetes/tasks/join-cluster.yml
@@ -0,0 +1,63 @@
+# Copyright (c) 2022 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Check if the node is already part of the cluster
+ ansible.builtin.stat:
+ path: /etc/kubernetes/kubelet.conf
+ register: _stat_etc_kubernetes_kubelet_conf
+
+- name: Generate control-plane certificates for joining cluster
+ run_once: true
+ delegate_to: "{{ _kubernetes_bootstrap_node | default(groups[kubernetes_control_plane_group][0]) }}"
+ ansible.builtin.shell: |
+ kubeadm init phase upload-certs --upload-certs 2>/dev/null | grep -v upload-certs
+ changed_when: false
+ register: _kubeadm_init_upload_certs
+ when:
+ - not _stat_etc_kubernetes_kubelet_conf.stat.exists
+ - inventory_hostname in groups[kubernetes_control_plane_group]
+
+- name: Retrieve SHA256 certificate hash
+ run_once: true
+ delegate_to: "{{ _kubernetes_bootstrap_node | default(groups[kubernetes_control_plane_group][0]) }}"
+ community.crypto.x509_certificate_info:
+ path: /etc/kubernetes/pki/ca.crt
+ register: _kubeadm_certificate_info
+ when:
+ - not _stat_etc_kubernetes_kubelet_conf.stat.exists
+
+- name: Generate token for joining cluster
+ run_once: true
+ delegate_to: "{{ _kubernetes_bootstrap_node | default(groups[kubernetes_control_plane_group][0]) }}"
+ ansible.builtin.shell: |
+ kubeadm token create
+ register: _kubeadm_token_create
+ when:
+ - not _stat_etc_kubernetes_kubelet_conf.stat.exists
+
+- name: Upload kubeadm configuration
+ ansible.builtin.template:
+ src: kubeadm.yaml.j2
+ dest: /etc/kubernetes/kubeadm.yaml
+ when:
+ - not _stat_etc_kubernetes_kubelet_conf.stat.exists
+
+- name: Join cluster
+ ansible.builtin.shell: |
+ kubeadm join --config /etc/kubernetes/kubeadm.yaml \
+ --ignore-preflight-errors=DirAvailable--etc-kubernetes-manifests
+ environment:
+ PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+ args:
+ creates: /etc/kubernetes/kubelet.conf
diff --git a/roles/kubernetes/tasks/main.yml b/roles/kubernetes/tasks/main.yml
new file mode 100644
index 0000000..383ce1f
--- /dev/null
+++ b/roles/kubernetes/tasks/main.yml
@@ -0,0 +1,124 @@
+# Copyright (c) 2022 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Add repository keys
+ ansible.builtin.copy:
+ src: apt-key.gpg
+ dest: /usr/share/keyrings/kubernetes-archive-keyring.gpg
+ when:
+ - kubernetes_repo_url == _kubernetes_upstream_apt_repository
+
+- name: Add repository
+ ansible.builtin.apt_repository:
+ repo: "deb {% if kubernetes_repo_url == _kubernetes_upstream_apt_repository %}[signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg]{% endif %} {{ kubernetes_repo_url }} kubernetes-xenial main"
+ state: present
+
+- name: Setup version pins
+ ansible.builtin.template:
+ src: apt-preferences.j2
+ dest: /etc/apt/preferences.d/kubernetes
+ mode: 0644
+
+- name: Install packages
+ ansible.builtin.apt:
+ name:
+ - "containerd"
+ - "kubeadm={{ kubernetes_version }}-00"
+ - "kubectl={{ kubernetes_version }}-00"
+ - "kubelet={{ kubernetes_version }}-00"
+ state: present
+
+- name: Enable kernel modules on-boot
+ ansible.builtin.template:
+ src: modules-load.conf.j2
+ dest: /etc/modules-load.d/k8s.conf
+
+- name: Enable kernel modules in runtime
+ community.general.modprobe:
+ name: "{{ item }}"
+ state: present
+ loop: "{{ kubernetes_kernel_modules }}"
+
+- name: Configure sysctl values
+ ansible.posix.sysctl:
+ name: "{{ item.name }}"
+ value: "{{ item.value }}"
+ state: present
+ loop: "{{ kubernetes_sysctls }}"
+
+- name: Check swap status
+ ansible.builtin.command: /sbin/swapon -s
+ changed_when: false
+ register: _swapon
+
+- name: Disable swap
+ ansible.builtin.command: /sbin/swapoff -a
+ ignore_errors: "{{ ansible_check_mode }}"
+ when:
+ - _swapon.stdout
+
+- name: Remove swapfile from /etc/fstab
+ ansible.posix.mount:
+ name: "{{ item }}"
+ fstype: swap
+ state: absent
+ with_items:
+ - swap
+ - none
+
+- name: Configure short hostname
+ ansible.builtin.hostname:
+ name: "{{ inventory_hostname_short }}"
+
+- name: Ensure hostname inside hosts file
+ ansible.builtin.lineinfile:
+ path: /etc/hosts
+ regexp: '^127\.0\.1\.1'
+ line: 127.0.1.1 {{ inventory_hostname }} {{ inventory_hostname_short }}
+
+- name: Setup control plane
+ when: inventory_hostname in groups[kubernetes_control_plane_group]
+ ansible.builtin.include_tasks: control-plane.yml
+
+- name: Setup nodes
+ when: inventory_hostname not in groups[kubernetes_control_plane_group]
+ ansible.builtin.include_tasks: nodes.yml
+
+- name: Add labels to control plane nodes
+ delegate_to: "{{ groups[kubernetes_control_plane_group][0] }}"
+ kubernetes.core.k8s:
+ state: patched
+ kind: Node
+ name: "{{ inventory_hostname_short }}"
+ definition:
+ metadata:
+ labels:
+ openstack-control-plane: enabled
+ openvswitch: enabled
+ when:
+ - inventory_hostname in groups['controllers']
+
+- name: Add labels to compute nodes
+ delegate_to: "{{ groups[kubernetes_control_plane_group][0] }}"
+ kubernetes.core.k8s:
+ state: patched
+ kind: Node
+ name: "{{ inventory_hostname_short }}"
+ definition:
+ metadata:
+ labels:
+ openstack-compute-node: enabled
+ openvswitch: enabled
+ when:
+ - inventory_hostname in groups['computes']
diff --git a/roles/kubernetes/tasks/nodes.yml b/roles/kubernetes/tasks/nodes.yml
new file mode 100644
index 0000000..bc11ac5
--- /dev/null
+++ b/roles/kubernetes/tasks/nodes.yml
@@ -0,0 +1,22 @@
+# Copyright (c) 2022 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Check if Kubernetes is already deployed
+ stat:
+ path: /etc/kubernetes/kubelet.conf
+ register: _kubernetes_kubelet
+
+- name: Join cluster
+ when: not _kubernetes_kubelet.stat.exists
+ ansible.builtin.include_tasks: join-cluster.yml
diff --git a/roles/kubernetes/templates/apt-preferences.j2 b/roles/kubernetes/templates/apt-preferences.j2
new file mode 100644
index 0000000..494a3a8
--- /dev/null
+++ b/roles/kubernetes/templates/apt-preferences.j2
@@ -0,0 +1,11 @@
+Package: kubectl
+Pin: version {{ kubernetes_version }}-00
+Pin-Priority: 1000
+
+Package: kubeadm
+Pin: version {{ kubernetes_version }}-00
+Pin-Priority: 1000
+
+Package: kubelet
+Pin: version {{ kubernetes_version }}-00
+Pin-Priority: 1000
\ No newline at end of file
diff --git a/roles/kubernetes/templates/check_apiserver.sh.j2 b/roles/kubernetes/templates/check_apiserver.sh.j2
new file mode 100644
index 0000000..bc9aa95
--- /dev/null
+++ b/roles/kubernetes/templates/check_apiserver.sh.j2
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+errorExit() {
+ echo "*** $*" 1>&2
+ exit 1
+}
+
+curl --silent --max-time 2 --insecure https://localhost:16443/ -o /dev/null || errorExit "Error GET https://localhost:16443/"
+if ip addr | grep -q {{ kubernetes_keepalived_vip }}; then
+ curl --silent --max-time 2 --insecure https://{{ kubernetes_keepalived_vip }}:6443/ -o /dev/null || errorExit "Error GET https://{{ kubernetes_keepalived_vip }}:6443/"
+fi
\ No newline at end of file
diff --git a/roles/kubernetes/templates/haproxy.cfg.j2 b/roles/kubernetes/templates/haproxy.cfg.j2
new file mode 100644
index 0000000..b4cb838
--- /dev/null
+++ b/roles/kubernetes/templates/haproxy.cfg.j2
@@ -0,0 +1,51 @@
+# /etc/haproxy/haproxy.cfg
+#---------------------------------------------------------------------
+# Global settings
+#---------------------------------------------------------------------
+global
+ log /dev/log local0
+ log /dev/log local1 notice
+ daemon
+
+#---------------------------------------------------------------------
+# common defaults that all the 'listen' and 'backend' sections will
+# use if not designated in their block
+#---------------------------------------------------------------------
+defaults
+ mode http
+ log global
+ option httplog
+ option dontlognull
+ option http-server-close
+ option forwardfor except 127.0.0.0/8
+ option redispatch
+ retries 1
+ timeout http-request 10s
+ timeout queue 20s
+ timeout connect 5s
+ timeout client 20s
+ timeout server 20s
+ timeout http-keep-alive 10s
+ timeout check 10s
+
+#---------------------------------------------------------------------
+# apiserver frontend which proxys to the masters
+#---------------------------------------------------------------------
+frontend apiserver
+ bind *:6443
+ mode tcp
+ option tcplog
+ default_backend apiserver
+
+#---------------------------------------------------------------------
+# round robin balancing for apiserver
+#---------------------------------------------------------------------
+backend apiserver
+ option httpchk GET /healthz
+ http-check expect status 200
+ mode tcp
+ option ssl-hello-chk
+ balance roundrobin
+{% for host in groups[kubernetes_control_plane_group] %}
+ server {{ host }} {{ hostvars[host]['ansible_host'] }}:16443 check
+{% endfor %}
diff --git a/roles/kubernetes/templates/keepalived.conf.j2 b/roles/kubernetes/templates/keepalived.conf.j2
new file mode 100644
index 0000000..58fde31
--- /dev/null
+++ b/roles/kubernetes/templates/keepalived.conf.j2
@@ -0,0 +1,25 @@
+global_defs {
+ router_id LVS_DEVEL
+}
+
+vrrp_script check_apiserver {
+ script "/etc/keepalived/check_apiserver.sh"
+ interval 3
+ weight -2
+ fall 10
+ rise 2
+}
+
+vrrp_instance kubernetes {
+ state MASTER
+ interface {{ kubernetes_keepalived_interface }}
+ virtual_router_id {{ kubernetes_keepalived_vrid }}
+
+ virtual_ipaddress {
+ {{ kubernetes_keepalived_vip }}
+ }
+
+ track_script {
+ check_apiserver
+ }
+}
\ No newline at end of file
diff --git a/roles/kubernetes/templates/kubeadm.yaml.j2 b/roles/kubernetes/templates/kubeadm.yaml.j2
new file mode 100644
index 0000000..eba1d7c
--- /dev/null
+++ b/roles/kubernetes/templates/kubeadm.yaml.j2
@@ -0,0 +1,55 @@
+---
+apiVersion: kubeadm.k8s.io/v1beta3
+kind: InitConfiguration
+localAPIEndpoint:
+ bindPort: 16443
+nodeRegistration:
+ kubeletExtraArgs:
+ cgroups-per-qos: "false"
+ enforce-node-allocatable: ""
+ node-ip: "{{ ansible_host }}"
+---
+apiVersion: kubeadm.k8s.io/v1beta3
+kind: JoinConfiguration
+nodeRegistration:
+ kubeletExtraArgs:
+ cgroups-per-qos: "false"
+ enforce-node-allocatable: ""
+ node-ip: "{{ ansible_host }}"
+{% if (_kubernetes_bootstrap_node is not defined) or (_kubernetes_bootstrap_node is defined and inventory_hostname != _kubernetes_bootstrap_node) %}
+discovery:
+ bootstrapToken:
+ token: "{{ _kubeadm_token_create.stdout | trim }}"
+ apiServerEndpoint: "{{ kubernetes_hostname }}:6443"
+ caCertHashes: ["sha256:{{ _kubeadm_certificate_info.public_key_fingerprints.sha256 | replace(':', '') }}"]
+{% if inventory_hostname in groups[kubernetes_control_plane_group] %}
+controlPlane:
+ localAPIEndpoint:
+ bindPort: 16443
+ certificateKey: {{ _kubeadm_init_upload_certs.stdout | trim }}
+{% endif %}
+{% endif %}
+---
+apiVersion: kubeadm.k8s.io/v1beta3
+kind: ClusterConfiguration
+controlPlaneEndpoint: "{{ kubernetes_hostname }}:6443"
+apiServer:
+ extraArgs:
+ oidc-username-claim: email
+{% if kubernetes_oidc_issuer_url is defined %}
+ oidc-issuer-url: {{ kubernetes_oidc_issuer_url }}
+ oidc-client-id: {{ kubernetes_oidc_client_id }}
+{% endif %}
+controllerManager:
+ extraArgs:
+ bind-address: "0.0.0.0"
+scheduler:
+ extraArgs:
+ bind-address: "0.0.0.0"
+---
+apiVersion: kubelet.config.k8s.io/v1beta1
+kind: KubeletConfiguration
+---
+apiVersion: kubeproxy.config.k8s.io/v1alpha1
+kind: KubeProxyConfiguration
+metricsBindAddress: 0.0.0.0
\ No newline at end of file
diff --git a/roles/kubernetes/templates/modules-load.conf.j2 b/roles/kubernetes/templates/modules-load.conf.j2
new file mode 100644
index 0000000..2c4d984
--- /dev/null
+++ b/roles/kubernetes/templates/modules-load.conf.j2
@@ -0,0 +1,3 @@
+{% for kubernetes_kernel_module in kubernetes_kernel_modules %}
+{{ kubernetes_kernel_module }}
+{% endfor %}
\ No newline at end of file
diff --git a/roles/kubernetes/vars/main.yml b/roles/kubernetes/vars/main.yml
new file mode 100644
index 0000000..cf153c5
--- /dev/null
+++ b/roles/kubernetes/vars/main.yml
@@ -0,0 +1,15 @@
+# Copyright (c) 2022 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+_kubernetes_upstream_apt_repository: https://apt.kubernetes.io/