Compare commits

..

13 Commits

Author SHA1 Message Date
Max Gautier
e86c0cf036 Use calico_pool_blocksize from cluster when existing (#10516)
The blockSize attribute from Calico IPPool resources cannot be changed
once set [1]. Consequently, we use the one currently defined when
configuring the existing IPPool, avoiding upgrade errors by trying to
change it.

In particular, this can be useful when calico_pool_blocksize default
changes in kubespray, which would otherwise force users to add an
explicit setting to their inventories.

[1]: https://docs.tigera.io/calico/latest/reference/resources/ippool#spec
2024-01-22 17:13:31 +01:00
ERIK
b50e4c9eb7 Fix hardcoded pod infra version (#10804)
Signed-off-by: bo.jiang <bo.jiang@daocloud.io>
2024-01-22 16:20:03 +01:00
kyrie
e4ac3ab799 Clear http scheme on containerd insecure-registry tls config (#10084) (#10782)
Signed-off-by: KubeKyrie <shaolong.qin@daocloud.io>
Co-authored-by: Louis Tu <92532497+tu1h@users.noreply.github.com>
2024-01-12 08:28:51 +01:00
Kay Yan
0af6dfca5d bump vagrant 2.3.7 (#10790) 2024-01-11 15:57:54 +01:00
ERIK
d6f688f060 Fix containerd config_path error when containerd_registries is configed (#9770) (#10665)
Signed-off-by: rongfu.leng <rongfu.leng@daocloud.io>
Co-authored-by: rongfu.leng <rongfu.leng@daocloud.io>
2023-12-05 16:08:25 +01:00
ERIK
a97fbec320 Downgrade version of coredns to 1.8.6 for compatibility with 1.23-1.24 (#10635)
Signed-off-by: bo.jiang <bo.jiang@daocloud.io>
2023-12-05 11:55:58 +01:00
ERIK
c3e73aabcf [2.21] Ensure that CI is available (#10673)
* Convert exoscale tf provider to new version (#10646)

This is untested. It passes terraform validate to un-broke the CI.

* specify pyyaml version to 5.3.1

Signed-off-by: bo.jiang <bo.jiang@daocloud.io>

* Migrate CI_BUILD_ID to CI_JOB_ID and CI_BUILD_REF to CI_COMMIT_SHA (#10063)

* Use supported version of fedora in CI (#10108)

* tests: replace fedora35 with fedora37

Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>

* tests: replace fedora36 with fedora38

Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>

* docs: update fedora version in docs

Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>

* molecule: upgrade fedora version

Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>

* tests: upgrade fedora images for vagrant and kubevirt

Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>

* vagrant: workaround to fix private network ip address in fedora

Fedora stop supporting syconfig network script so we added a workaround
here
https://github.com/hashicorp/vagrant/issues/12762#issuecomment-1535957837
to fix it.

* netowrkmanager: do not configure dns if using systemd-resolved

We should not configure dns if we point to systemd-resolved.
Systemd-resolved is using NetworkManager to infer the upstream DNS
server so if we set NetworkManager to 127.0.0.53 it will prevent
systemd-resolved to get the correct network DNS server.

Thus if we are in this case we just don't set this setting.

Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>

* image-builder: update centos7 image

Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>

* gitlab-ci: mark fedora packet jobs as allow failure

Fedora networking is still broken on Packet, let's mark it as allow
failure for now.

Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>

---------

Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>

---------

Signed-off-by: bo.jiang <bo.jiang@daocloud.io>
Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>
Co-authored-by: Max Gautier <mg@max.gautier.name>
Co-authored-by: Florian Ruynat <16313165+floryut@users.noreply.github.com>
Co-authored-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>
2023-12-01 04:42:21 +01:00
vbottu
d498df20db Adding the missing rsync utility
rsync is missing from the image in v2.21.0, adding it
2023-06-19 11:50:37 +02:00
Kenichi Omichi
08467ad6b3 Fix cilium's hubble ui configuration (#9735) (#9864)
This fixes the CrashLoopBackoff error that appears because envoy
configuration has changed a lot and upstream removed the envoy proxy to
use nginx only instead. Those changes are based on upstream cilium helm.

Co-authored-by: James <gwendal.landrein@epita.fr>
2023-03-22 19:48:22 -07:00
Kenichi Omichi
3f41d8b274 update args (#9856) (#9871)
Signed-off-by: Anant Vijay <anantvijay3@gmail.com>
Co-authored-by: DRAGON2002 <81813720+XDRAGON2002@users.noreply.github.com>
2023-03-08 22:12:00 -08:00
Florian Ruynat
0634be4c88 fix: with_item to with_dict (#9729) (#9751)
Signed-off-by: rongfu.leng <rongfu.leng@daocloud.io>
Co-authored-by: rongfu.leng <rongfu.leng@daocloud.io>
2023-02-02 15:38:28 -08:00
Florian Ruynat
919e666fb9 [2.21] Backport hotfix to Dockerfile image (#9721)
* Add ruamel.yaml to docker image (#9707)

* Add jmespath back to Dockerfile image (#9697)
2023-01-27 19:20:33 -08:00
Tristan
813576efeb 9693: Fix comma-separated-list splitting of kubelet_enforce_node_allocatable (#9700)
See https://github.com/kubernetes-sigs/kubespray/issues/9693
2023-01-24 16:02:12 -08:00
365 changed files with 8391 additions and 7696 deletions

View File

@@ -24,17 +24,7 @@ skip_list:
# (Disabled in June 2021) # (Disabled in June 2021)
- 'role-name' - 'role-name'
- 'experimental'
# [var-naming] "defaults/main.yml" File defines variable 'apiVersion' that violates variable naming standards # [var-naming] "defaults/main.yml" File defines variable 'apiVersion' that violates variable naming standards
# In Kubespray we use variables that use camelCase to match their k8s counterparts # In Kubespray we use variables that use camelCase to match their k8s counterparts
# (Disabled in June 2021) # (Disabled in June 2021)
- 'var-naming' - 'var-naming'
- 'var-spacing'
# [fqcn-builtins]
# Roles in kubespray don't need fully qualified collection names
# (Disabled in Feb 2023)
- 'fqcn-builtins'
exclude_paths:
# Generated files
- tests/files/custom_cni/cilium.yaml

5
.gitignore vendored
View File

@@ -12,7 +12,6 @@ contrib/offline/offline-files.tar.gz
*.bak *.bak
*.tfstate *.tfstate
*.tfstate.backup *.tfstate.backup
*.lock.hcl
.terraform/ .terraform/
contrib/terraform/aws/credentials.tfvars contrib/terraform/aws/credentials.tfvars
.terraform.lock.hcl .terraform.lock.hcl
@@ -114,7 +113,3 @@ roles/**/molecule/**/__pycache__/
# Temp location used by our scripts # Temp location used by our scripts
scripts/tmp/ scripts/tmp/
tmp.md tmp.md
# Ansible collection files
kubernetes_sigs-kubespray*tar.gz
ansible_collections

View File

@@ -9,7 +9,7 @@ stages:
- deploy-special - deploy-special
variables: variables:
KUBESPRAY_VERSION: v2.21.0 KUBESPRAY_VERSION: v2.20.0
FAILFASTCI_NAMESPACE: 'kargo-ci' FAILFASTCI_NAMESPACE: 'kargo-ci'
GITLAB_REPOSITORY: 'kargo-ci/kubernetes-sigs-kubespray' GITLAB_REPOSITORY: 'kargo-ci/kubernetes-sigs-kubespray'
ANSIBLE_FORCE_COLOR: "true" ANSIBLE_FORCE_COLOR: "true"
@@ -34,7 +34,7 @@ variables:
ANSIBLE_LOG_LEVEL: "-vv" ANSIBLE_LOG_LEVEL: "-vv"
RECOVER_CONTROL_PLANE_TEST: "false" RECOVER_CONTROL_PLANE_TEST: "false"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:],kube_control_plane[1:]" RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:],kube_control_plane[1:]"
TERRAFORM_VERSION: 1.3.7 TERRAFORM_VERSION: 1.0.8
ANSIBLE_MAJOR_VERSION: "2.11" ANSIBLE_MAJOR_VERSION: "2.11"
PIPELINE_IMAGE: "$CI_REGISTRY_IMAGE/pipeline:${CI_PIPELINE_ID}-${CI_COMMIT_SHORT_SHA}" PIPELINE_IMAGE: "$CI_REGISTRY_IMAGE/pipeline:${CI_PIPELINE_ID}-${CI_COMMIT_SHORT_SHA}"

View File

@@ -1,40 +1,16 @@
--- ---
.build:
stage: build
image:
name: moby/buildkit:rootless
entrypoint: [""]
variables:
BUILDKITD_FLAGS: --oci-worker-no-process-sandbox
before_script:
- mkdir ~/.docker
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > ~/.docker/config.json
pipeline image: pipeline image:
extends: .build stage: build
image: docker:20.10.22-cli
variables:
DOCKER_TLS_CERTDIR: ""
services:
- name: docker:20.10.22-dind
# See https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27300 for why this is required
command: ["--tls=false"]
before_script:
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
script: script:
- | # DOCKER_HOST is overwritten if we set it as a GitLab variable
buildctl-daemonless.sh build \ - DOCKER_HOST=tcp://docker:2375; docker build --network host --file pipeline.Dockerfile --tag $PIPELINE_IMAGE .
--frontend=dockerfile.v0 \ - docker push $PIPELINE_IMAGE
--local context=. \
--local dockerfile=. \
--opt filename=./pipeline.Dockerfile \
--output type=image,name=$PIPELINE_IMAGE,push=true \
--import-cache type=registry,ref=$CI_REGISTRY_IMAGE/pipeline:cache
rules:
- if: '$CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH'
pipeline image and build cache:
extends: .build
script:
- |
buildctl-daemonless.sh build \
--frontend=dockerfile.v0 \
--local context=. \
--local dockerfile=. \
--opt filename=./pipeline.Dockerfile \
--output type=image,name=$PIPELINE_IMAGE,push=true \
--import-cache type=registry,ref=$CI_REGISTRY_IMAGE/pipeline:cache \
--export-cache type=registry,ref=$CI_REGISTRY_IMAGE/pipeline:cache,mode=max
rules:
- if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'

View File

@@ -14,7 +14,7 @@ vagrant-validate:
stage: unit-tests stage: unit-tests
tags: [light] tags: [light]
variables: variables:
VAGRANT_VERSION: 2.3.4 VAGRANT_VERSION: 2.3.7
script: script:
- ./tests/scripts/vagrant-validate.sh - ./tests/scripts/vagrant-validate.sh
except: ['triggers', 'master'] except: ['triggers', 'master']
@@ -39,28 +39,11 @@ syntax-check:
ANSIBLE_VERBOSITY: "3" ANSIBLE_VERBOSITY: "3"
script: script:
- ansible-playbook --syntax-check cluster.yml - ansible-playbook --syntax-check cluster.yml
- ansible-playbook --syntax-check playbooks/cluster.yml
- ansible-playbook --syntax-check upgrade-cluster.yml - ansible-playbook --syntax-check upgrade-cluster.yml
- ansible-playbook --syntax-check playbooks/upgrade_cluster.yml
- ansible-playbook --syntax-check reset.yml - ansible-playbook --syntax-check reset.yml
- ansible-playbook --syntax-check playbooks/reset.yml
- ansible-playbook --syntax-check extra_playbooks/upgrade-only-k8s.yml - ansible-playbook --syntax-check extra_playbooks/upgrade-only-k8s.yml
except: ['triggers', 'master'] except: ['triggers', 'master']
collection-build-install-sanity-check:
extends: .job
stage: unit-tests
tags: [light]
variables:
ANSIBLE_COLLECTIONS_PATH: "./ansible_collections"
script:
- ansible-galaxy collection build
- ansible-galaxy collection install kubernetes_sigs-kubespray-$(grep "^version:" galaxy.yml | awk '{print $2}').tar.gz
- ansible-galaxy collection list $(egrep -i '(name:\s+|namespace:\s+)' galaxy.yml | awk '{print $2}' | tr '\n' '.' | sed 's|\.$||g') | grep "^kubernetes_sigs.kubespray"
- test -f ansible_collections/kubernetes_sigs/kubespray/playbooks/cluster.yml
- test -f ansible_collections/kubernetes_sigs/kubespray/playbooks/reset.yml
except: ['triggers', 'master']
tox-inventory-builder: tox-inventory-builder:
stage: unit-tests stage: unit-tests
tags: [light] tags: [light]
@@ -92,13 +75,6 @@ check-readme-versions:
script: script:
- tests/scripts/check_readme_versions.sh - tests/scripts/check_readme_versions.sh
check-galaxy-version:
stage: unit-tests
tags: [light]
image: python:3
script:
- tests/scripts/check_galaxy_version.sh
check-typo: check-typo:
stage: unit-tests stage: unit-tests
tags: [light] tags: [light]

View File

@@ -86,11 +86,21 @@ packet_ubuntu18-crio:
stage: deploy-part2 stage: deploy-part2
when: manual when: manual
packet_fedora35-crio: packet_fedora37-crio:
extends: .packet_pr extends: .packet_pr
stage: deploy-part2 stage: deploy-part2
when: manual when: manual
packet_ubuntu16-canal-ha:
stage: deploy-part2
extends: .packet_periodic
when: on_success
packet_ubuntu16-canal-sep:
stage: deploy-special
extends: .packet_pr
when: manual
packet_ubuntu16-flannel-ha: packet_ubuntu16-flannel-ha:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
@@ -163,10 +173,16 @@ packet_almalinux8-docker:
extends: .packet_pr extends: .packet_pr
when: on_success when: on_success
packet_fedora36-docker-weave: packet_fedora38-docker-weave:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: on_success when: on_success
allow_failure: true
packet_opensuse-canal:
stage: deploy-part2
extends: .packet_periodic
when: on_success
packet_opensuse-docker-cilium: packet_opensuse-docker-cilium:
stage: deploy-part2 stage: deploy-part2
@@ -201,7 +217,7 @@ packet_almalinux8-calico-ha-ebpf:
extends: .packet_pr extends: .packet_pr
when: manual when: manual
packet_debian10-macvlan: packet_debian9-macvlan:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: manual when: manual
@@ -216,19 +232,24 @@ packet_centos7-multus-calico:
extends: .packet_pr extends: .packet_pr
when: manual when: manual
packet_fedora36-docker-calico: packet_centos7-canal-ha:
stage: deploy-part2
extends: .packet_pr
when: manual
packet_fedora38-docker-calico:
stage: deploy-part2 stage: deploy-part2
extends: .packet_periodic extends: .packet_periodic
when: on_success when: on_success
variables: variables:
RESET_CHECK: "true" RESET_CHECK: "true"
packet_fedora35-calico-selinux: packet_fedora37-calico-selinux:
stage: deploy-part2 stage: deploy-part2
extends: .packet_periodic extends: .packet_periodic
when: on_success when: on_success
packet_fedora35-calico-swap-selinux: packet_fedora37-calico-swap-selinux:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: manual when: manual
@@ -243,21 +264,11 @@ packet_almalinux8-calico-nodelocaldns-secondary:
extends: .packet_pr extends: .packet_pr
when: manual when: manual
packet_fedora36-kube-ovn: packet_fedora38-kube-ovn:
stage: deploy-part2 stage: deploy-part2
extends: .packet_periodic extends: .packet_periodic
when: on_success when: on_success
packet_debian11-custom-cni:
stage: deploy-part2
extends: .packet_pr
when: manual
packet_debian11-kubelet-csr-approver:
stage: deploy-part2
extends: .packet_pr
when: manual
# ### PR JOBS PART3 # ### PR JOBS PART3
# Long jobs (45min+) # Long jobs (45min+)

View File

@@ -60,11 +60,11 @@ tf-validate-openstack:
PROVIDER: openstack PROVIDER: openstack
CLUSTER: $CI_COMMIT_REF_NAME CLUSTER: $CI_COMMIT_REF_NAME
tf-validate-equinix: tf-validate-metal:
extends: .terraform_validate extends: .terraform_validate
variables: variables:
TF_VERSION: $TERRAFORM_VERSION TF_VERSION: $TERRAFORM_VERSION
PROVIDER: equinix PROVIDER: metal
CLUSTER: $CI_COMMIT_REF_NAME CLUSTER: $CI_COMMIT_REF_NAME
tf-validate-aws: tf-validate-aws:
@@ -80,12 +80,6 @@ tf-validate-exoscale:
TF_VERSION: $TERRAFORM_VERSION TF_VERSION: $TERRAFORM_VERSION
PROVIDER: exoscale PROVIDER: exoscale
tf-validate-hetzner:
extends: .terraform_validate
variables:
TF_VERSION: $TERRAFORM_VERSION
PROVIDER: hetzner
tf-validate-vsphere: tf-validate-vsphere:
extends: .terraform_validate extends: .terraform_validate
variables: variables:
@@ -110,7 +104,7 @@ tf-validate-upcloud:
# TF_VAR_number_of_k8s_nodes: "1" # TF_VAR_number_of_k8s_nodes: "1"
# TF_VAR_plan_k8s_masters: t1.small.x86 # TF_VAR_plan_k8s_masters: t1.small.x86
# TF_VAR_plan_k8s_nodes: t1.small.x86 # TF_VAR_plan_k8s_nodes: t1.small.x86
# TF_VAR_metro: ny # TF_VAR_facility: ewr1
# TF_VAR_public_key_path: "" # TF_VAR_public_key_path: ""
# TF_VAR_operating_system: ubuntu_16_04 # TF_VAR_operating_system: ubuntu_16_04
# #
@@ -124,7 +118,7 @@ tf-validate-upcloud:
# TF_VAR_number_of_k8s_nodes: "1" # TF_VAR_number_of_k8s_nodes: "1"
# TF_VAR_plan_k8s_masters: t1.small.x86 # TF_VAR_plan_k8s_masters: t1.small.x86
# TF_VAR_plan_k8s_nodes: t1.small.x86 # TF_VAR_plan_k8s_nodes: t1.small.x86
# TF_VAR_metro: am # TF_VAR_facility: ams1
# TF_VAR_public_key_path: "" # TF_VAR_public_key_path: ""
# TF_VAR_operating_system: ubuntu_18_04 # TF_VAR_operating_system: ubuntu_18_04

View File

@@ -45,11 +45,6 @@ vagrant_ubuntu20-flannel:
when: on_success when: on_success
allow_failure: false allow_failure: false
vagrant_ubuntu20-flannel-collection:
stage: deploy-part2
extends: .vagrant
when: on_success
vagrant_ubuntu16-kube-router-sep: vagrant_ubuntu16-kube-router-sep:
stage: deploy-part2 stage: deploy-part2
extends: .vagrant extends: .vagrant
@@ -61,7 +56,7 @@ vagrant_ubuntu16-kube-router-svc-proxy:
extends: .vagrant extends: .vagrant
when: manual when: manual
vagrant_fedora35-kube-router: vagrant_fedora37-kube-router:
stage: deploy-part2 stage: deploy-part2
extends: .vagrant extends: .vagrant
when: on_success when: on_success

View File

@@ -1,20 +1,5 @@
--- ---
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-executables-have-shebangs
- id: check-xml
- id: check-merge-conflict
- id: detect-private-key
- id: end-of-file-fixer
- id: forbid-new-submodules
- id: requirements-txt-fixer
- id: trailing-whitespace
- repo: https://github.com/adrienverge/yamllint.git - repo: https://github.com/adrienverge/yamllint.git
rev: v1.27.1 rev: v1.27.1
hooks: hooks:
@@ -28,14 +13,6 @@ repos:
args: [ -r, "~MD013,~MD029" ] args: [ -r, "~MD013,~MD029" ]
exclude: "^.git" exclude: "^.git"
- repo: https://github.com/jumanjihouse/pre-commit-hooks
rev: 3.0.0
hooks:
- id: shellcheck
args: [ --severity, "error" ]
exclude: "^.git"
files: "\\.sh$"
- repo: local - repo: local
hooks: hooks:
- id: ansible-lint - id: ansible-lint

View File

@@ -3,8 +3,6 @@ extends: default
ignore: | ignore: |
.git/ .git/
# Generated file
tests/files/custom_cni/cilium.yaml
rules: rules:
braces: braces:

2
CNAME
View File

@@ -1 +1 @@
kubespray.io kubespray.io

View File

@@ -1,44 +1,38 @@
# Use imutable image tags rather than mutable tags (like ubuntu:22.04) # Use imutable image tags rather than mutable tags (like ubuntu:20.04)
FROM ubuntu:jammy-20230308 FROM ubuntu:focal-20220531
ARG ARCH=amd64
ARG TZ=Etc/UTC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt update -y \
&& apt install -y \
curl python3 python3-pip sshpass rsync \
&& rm -rf /var/lib/apt/lists/*
# Some tools like yamllint need this # Some tools like yamllint need this
# Pip needs this as well at the moment to install ansible # Pip needs this as well at the moment to install ansible
# (and potentially other packages) # (and potentially other packages)
# See: https://github.com/pypa/pip/issues/10219 # See: https://github.com/pypa/pip/issues/10219
ENV LANG=C.UTF-8 \ ENV LANG=C.UTF-8
DEBIAN_FRONTEND=noninteractive \
PYTHONDONTWRITEBYTECODE=1
WORKDIR /kubespray
COPY *.yml ./
COPY *.cfg ./
COPY roles ./roles
COPY contrib ./contrib
COPY inventory ./inventory
COPY library ./library
COPY extra_playbooks ./extra_playbooks
COPY playbooks ./playbooks
COPY plugins ./plugins
RUN apt update -q \ WORKDIR /kubespray
&& apt install -yq --no-install-recommends \ COPY *yml /kubespray/
curl \ COPY roles /kubespray/roles
python3 \ COPY inventory /kubespray/inventory
python3-pip \ COPY library /kubespray/library
sshpass \ COPY extra_playbooks /kubespray/extra_playbooks
vim \
rsync \ RUN python3 -m pip install --no-cache-dir \
openssh-client \ ansible==5.7.1 \
&& pip install --no-compile --no-cache-dir \ ansible-core==2.12.5 \
ansible==5.7.1 \ cryptography==3.4.8 \
ansible-core==2.12.5 \ jinja2==2.11.3 \
cryptography==3.4.8 \ netaddr==0.7.19 \
jinja2==3.1.2 \ jmespath==1.0.1 \
netaddr==0.8.0 \ MarkupSafe==1.1.1 \
jmespath==1.0.1 \ ruamel.yaml==0.17.21 \
MarkupSafe==2.1.2 \
ruamel.yaml==0.17.21 \
&& KUBE_VERSION=$(sed -n 's/^kube_version: //p' roles/kubespray-defaults/defaults/main.yaml) \ && KUBE_VERSION=$(sed -n 's/^kube_version: //p' roles/kubespray-defaults/defaults/main.yaml) \
&& curl -L https://dl.k8s.io/release/$KUBE_VERSION/bin/linux/$(dpkg --print-architecture)/kubectl -o /usr/local/bin/kubectl \ && curl -LO https://storage.googleapis.com/kubernetes-release/release/$KUBE_VERSION/bin/linux/$ARCH/kubectl \
&& echo $(curl -L https://dl.k8s.io/release/$KUBE_VERSION/bin/linux/$(dpkg --print-architecture)/kubectl.sha256) /usr/local/bin/kubectl | sha256sum --check \ && chmod a+x kubectl \
&& chmod a+x /usr/local/bin/kubectl \ && mv kubectl /usr/local/bin/kubectl
&& rm -rf /var/lib/apt/lists/* /var/log/* \
&& find /usr -type d -name '*__pycache__' -prune -exec rm -rf {} \;

View File

@@ -187,7 +187,7 @@
identification within third-party archives. identification within third-party archives.
Copyright 2016 Kubespray Copyright 2016 Kubespray
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at

2
OWNERS
View File

@@ -5,4 +5,4 @@ approvers:
reviewers: reviewers:
- kubespray-reviewers - kubespray-reviewers
emeritus_approvers: emeritus_approvers:
- kubespray-emeritus_approvers - kubespray-emeritus_approvers

View File

@@ -10,7 +10,6 @@ aliases:
- cristicalin - cristicalin
- liupeng0518 - liupeng0518
- yankay - yankay
- mzaian
kubespray-reviewers: kubespray-reviewers:
- holmsten - holmsten
- bozzo - bozzo
@@ -22,7 +21,6 @@ aliases:
- yankay - yankay
- cyclinder - cyclinder
- mzaian - mzaian
- mrfreezeex
kubespray-emeritus_approvers: kubespray-emeritus_approvers:
- riverzhang - riverzhang
- atoms - atoms

View File

@@ -34,13 +34,6 @@ CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inv
cat inventory/mycluster/group_vars/all/all.yml cat inventory/mycluster/group_vars/all/all.yml
cat inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml cat inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
# Clean up old Kubernete cluster with Ansible Playbook - run the playbook as root
# The option `--become` is required, as for example cleaning up SSL keys in /etc/,
# uninstalling old packages and interacting with various systemd daemons.
# Without --become the playbook will fail to run!
# And be mind it will remove the current kubernetes cluster (if it's running)!
ansible-playbook -i inventory/mycluster/hosts.yaml --become --become-user=root reset.yml
# Deploy Kubespray with Ansible Playbook - run the playbook as root # Deploy Kubespray with Ansible Playbook - run the playbook as root
# The option `--become` is required, as for example writing SSL keys in /etc/, # The option `--become` is required, as for example writing SSL keys in /etc/,
# installing packages and interacting with various systemd daemons. # installing packages and interacting with various systemd daemons.
@@ -52,7 +45,7 @@ Note: When Ansible is already installed via system packages on the control node,
Python packages installed via `sudo pip install -r requirements.txt` will go to Python packages installed via `sudo pip install -r requirements.txt` will go to
a different directory tree (e.g. `/usr/local/lib/python2.7/dist-packages` on a different directory tree (e.g. `/usr/local/lib/python2.7/dist-packages` on
Ubuntu) from Ansible's (e.g. `/usr/lib/python2.7/dist-packages/ansible` still on Ubuntu) from Ansible's (e.g. `/usr/lib/python2.7/dist-packages/ansible` still on
Ubuntu). As a consequence, the `ansible-playbook` command will fail with: buntu). As a consequence, the `ansible-playbook` command will fail with:
```raw ```raw
ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path. ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.
@@ -75,19 +68,15 @@ You will then need to use [bind mounts](https://docs.docker.com/storage/bind-mou
to access the inventory and SSH key in the container, like this: to access the inventory and SSH key in the container, like this:
```ShellSession ```ShellSession
git checkout v2.22.0 git checkout v2.20.0
docker pull quay.io/kubespray/kubespray:v2.22.0 docker pull quay.io/kubespray/kubespray:v2.20.0
docker run --rm -it --mount type=bind,source="$(pwd)"/inventory/sample,dst=/inventory \ docker run --rm -it --mount type=bind,source="$(pwd)"/inventory/sample,dst=/inventory \
--mount type=bind,source="${HOME}"/.ssh/id_rsa,dst=/root/.ssh/id_rsa \ --mount type=bind,source="${HOME}"/.ssh/id_rsa,dst=/root/.ssh/id_rsa \
quay.io/kubespray/kubespray:v2.22.0 bash quay.io/kubespray/kubespray:v2.20.0 bash
# Inside the container you may now run the kubespray playbooks: # Inside the container you may now run the kubespray playbooks:
ansible-playbook -i /inventory/inventory.ini --private-key /root/.ssh/id_rsa cluster.yml ansible-playbook -i /inventory/inventory.ini --private-key /root/.ssh/id_rsa cluster.yml
``` ```
#### Collection
See [here](docs/ansible_collection.md) if you wish to use this repository as an Ansible collection
### Vagrant ### Vagrant
For Vagrant we need to install Python dependencies for provisioning tasks. For Vagrant we need to install Python dependencies for provisioning tasks.
@@ -142,10 +131,10 @@ vagrant up
## Supported Linux Distributions ## Supported Linux Distributions
- **Flatcar Container Linux by Kinvolk** - **Flatcar Container Linux by Kinvolk**
- **Debian** Bullseye, Buster - **Debian** Bullseye, Buster, Jessie, Stretch
- **Ubuntu** 16.04, 18.04, 20.04, 22.04 - **Ubuntu** 16.04, 18.04, 20.04, 22.04
- **CentOS/RHEL** 7, [8, 9](docs/centos.md#centos-8) - **CentOS/RHEL** 7, [8, 9](docs/centos.md#centos-8)
- **Fedora** 35, 36 - **Fedora** 37, 38
- **Fedora CoreOS** (see [fcos Note](docs/fcos.md)) - **Fedora CoreOS** (see [fcos Note](docs/fcos.md))
- **openSUSE** Leap 15.x/Tumbleweed - **openSUSE** Leap 15.x/Tumbleweed
- **Oracle Linux** 7, [8, 9](docs/centos.md#centos-8) - **Oracle Linux** 7, [8, 9](docs/centos.md#centos-8)
@@ -161,29 +150,30 @@ Note: Upstart/SysV init based OS types are not supported.
## Supported Components ## Supported Components
- Core - Core
- [kubernetes](https://github.com/kubernetes/kubernetes) v1.26.5 - [kubernetes](https://github.com/kubernetes/kubernetes) v1.25.6
- [etcd](https://github.com/etcd-io/etcd) v3.5.6 - [etcd](https://github.com/etcd-io/etcd) v3.5.6
- [docker](https://www.docker.com/) v20.10 (see note) - [docker](https://www.docker.com/) v20.10 (see note)
- [containerd](https://containerd.io/) v1.7.1 - [containerd](https://containerd.io/) v1.6.15
- [cri-o](http://cri-o.io/) v1.24 (experimental: see [CRI-O Note](docs/cri-o.md). Only on fedora, ubuntu and centos based OS) - [cri-o](http://cri-o.io/) v1.24 (experimental: see [CRI-O Note](docs/cri-o.md). Only on fedora, ubuntu and centos based OS)
- Network Plugin - Network Plugin
- [cni-plugins](https://github.com/containernetworking/plugins) v1.2.0 - [cni-plugins](https://github.com/containernetworking/plugins) v1.2.0
- [calico](https://github.com/projectcalico/calico) v3.25.1 - [calico](https://github.com/projectcalico/calico) v3.24.5
- [cilium](https://github.com/cilium/cilium) v1.13.0 - [canal](https://github.com/projectcalico/canal) (given calico/flannel versions)
- [flannel](https://github.com/flannel-io/flannel) v0.21.4 - [cilium](https://github.com/cilium/cilium) v1.12.1
- [flannel](https://github.com/flannel-io/flannel) v0.20.2
- [kube-ovn](https://github.com/alauda/kube-ovn) v1.10.7 - [kube-ovn](https://github.com/alauda/kube-ovn) v1.10.7
- [kube-router](https://github.com/cloudnativelabs/kube-router) v1.5.1 - [kube-router](https://github.com/cloudnativelabs/kube-router) v1.5.1
- [multus](https://github.com/k8snetworkplumbingwg/multus-cni) v3.8 - [multus](https://github.com/intel/multus-cni) v3.8
- [weave](https://github.com/weaveworks/weave) v2.8.1 - [weave](https://github.com/weaveworks/weave) v2.8.1
- [kube-vip](https://github.com/kube-vip/kube-vip) v0.5.12 - [kube-vip](https://github.com/kube-vip/kube-vip) v0.5.5
- Application - Application
- [cert-manager](https://github.com/jetstack/cert-manager) v1.11.1 - [cert-manager](https://github.com/jetstack/cert-manager) v1.11.0
- [coredns](https://github.com/coredns/coredns) v1.9.3 - [coredns](https://github.com/coredns/coredns) v1.9.3
- [ingress-nginx](https://github.com/kubernetes/ingress-nginx) v1.7.1 - [ingress-nginx](https://github.com/kubernetes/ingress-nginx) v1.5.1
- [krew](https://github.com/kubernetes-sigs/krew) v0.4.3 - [krew](https://github.com/kubernetes-sigs/krew) v0.4.3
- [argocd](https://argoproj.github.io/) v2.7.2 - [argocd](https://argoproj.github.io/) v2.5.7
- [helm](https://helm.sh/) v3.12.0 - [helm](https://helm.sh/) v3.10.3
- [metallb](https://metallb.universe.tf/) v0.13.9 - [metallb](https://metallb.universe.tf/) v0.12.1
- [registry](https://github.com/distribution/distribution) v2.8.1 - [registry](https://github.com/distribution/distribution) v2.8.1
- Storage Plugin - Storage Plugin
- [cephfs-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.0-k8s1.11 - [cephfs-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.0-k8s1.11
@@ -192,7 +182,7 @@ Note: Upstart/SysV init based OS types are not supported.
- [azure-csi-plugin](https://github.com/kubernetes-sigs/azuredisk-csi-driver) v1.10.0 - [azure-csi-plugin](https://github.com/kubernetes-sigs/azuredisk-csi-driver) v1.10.0
- [cinder-csi-plugin](https://github.com/kubernetes/cloud-provider-openstack/blob/master/docs/cinder-csi-plugin/using-cinder-csi-plugin.md) v1.22.0 - [cinder-csi-plugin](https://github.com/kubernetes/cloud-provider-openstack/blob/master/docs/cinder-csi-plugin/using-cinder-csi-plugin.md) v1.22.0
- [gcp-pd-csi-plugin](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver) v1.4.0 - [gcp-pd-csi-plugin](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver) v1.4.0
- [local-path-provisioner](https://github.com/rancher/local-path-provisioner) v0.0.23 - [local-path-provisioner](https://github.com/rancher/local-path-provisioner) v0.0.22
- [local-volume-provisioner](https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner) v2.5.0 - [local-volume-provisioner](https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner) v2.5.0
## Container Runtime Notes ## Container Runtime Notes
@@ -202,14 +192,14 @@ Note: Upstart/SysV init based OS types are not supported.
## Requirements ## Requirements
- **Minimum required version of Kubernetes is v1.24** - **Minimum required version of Kubernetes is v1.23**
- **Ansible v2.11+, Jinja 2.11+ and python-netaddr is installed on the machine that will run Ansible commands** - **Ansible v2.11+, Jinja 2.11+ and python-netaddr is installed on the machine that will run Ansible commands**
- The target servers must have **access to the Internet** in order to pull docker images. Otherwise, additional configuration is required (See [Offline Environment](docs/offline-environment.md)) - The target servers must have **access to the Internet** in order to pull docker images. Otherwise, additional configuration is required (See [Offline Environment](docs/offline-environment.md))
- The target servers are configured to allow **IPv4 forwarding**. - The target servers are configured to allow **IPv4 forwarding**.
- If using IPv6 for pods and services, the target servers are configured to allow **IPv6 forwarding**. - If using IPv6 for pods and services, the target servers are configured to allow **IPv6 forwarding**.
- The **firewalls are not managed**, you'll need to implement your own rules the way you used to. - The **firewalls are not managed**, you'll need to implement your own rules the way you used to.
in order to avoid any issue during deployment you should disable your firewall. in order to avoid any issue during deployment you should disable your firewall.
- If kubespray is run from non-root user account, correct privilege escalation method - If kubespray is ran from non-root user account, correct privilege escalation method
should be configured in the target servers. Then the `ansible_become` flag should be configured in the target servers. Then the `ansible_become` flag
or command parameters `--become or -b` should be specified. or command parameters `--become or -b` should be specified.
@@ -232,6 +222,8 @@ You can choose among ten network plugins. (default: `calico`, except Vagrant use
and overlay networks, with or without BGP. Calico uses the same engine to enforce network policy for hosts, and overlay networks, with or without BGP. Calico uses the same engine to enforce network policy for hosts,
pods, and (if using Istio and Envoy) applications at the service mesh layer. pods, and (if using Istio and Envoy) applications at the service mesh layer.
- [canal](https://github.com/projectcalico/canal): a composition of calico and flannel plugins.
- [cilium](http://docs.cilium.io/en/latest/): layer 3/4 networking (as well as layer 7 to protect and secure application protocols), supports dynamic insertion of BPF bytecode into the Linux kernel to implement security services, networking and visibility logic. - [cilium](http://docs.cilium.io/en/latest/): layer 3/4 networking (as well as layer 7 to protect and secure application protocols), supports dynamic insertion of BPF bytecode into the Linux kernel to implement security services, networking and visibility logic.
- [weave](docs/weave.md): Weave is a lightweight container overlay network that doesn't require an external K/V database cluster. - [weave](docs/weave.md): Weave is a lightweight container overlay network that doesn't require an external K/V database cluster.
@@ -248,9 +240,6 @@ You can choose among ten network plugins. (default: `calico`, except Vagrant use
- [multus](docs/multus.md): Multus is a meta CNI plugin that provides multiple network interface support to pods. For each interface Multus delegates CNI calls to secondary CNI plugins such as Calico, macvlan, etc. - [multus](docs/multus.md): Multus is a meta CNI plugin that provides multiple network interface support to pods. For each interface Multus delegates CNI calls to secondary CNI plugins such as Calico, macvlan, etc.
- [custom_cni](roles/network-plugin/custom_cni/) : You can specify some manifests that will be applied to the clusters to bring you own CNI and use non-supported ones by Kubespray.
See `tests/files/custom_cni/README.md` and `tests/files/custom_cni/values.yaml`for an example with a CNI provided by a Helm Chart.
The network plugin to use is defined by the variable `kube_network_plugin`. There is also an The network plugin to use is defined by the variable `kube_network_plugin`. There is also an
option to leverage built-in cloud provider networking instead. option to leverage built-in cloud provider networking instead.
See also [Network checker](docs/netcheck.md). See also [Network checker](docs/netcheck.md).
@@ -276,7 +265,7 @@ See also [Network checker](docs/netcheck.md).
## CI Tests ## CI Tests
[![Build graphs](https://gitlab.com/kargo-ci/kubernetes-sigs-kubespray/badges/master/pipeline.svg)](https://gitlab.com/kargo-ci/kubernetes-sigs-kubespray/-/pipelines) [![Build graphs](https://gitlab.com/kargo-ci/kubernetes-sigs-kubespray/badges/master/pipeline.svg)](https://gitlab.com/kargo-ci/kubernetes-sigs-kubespray/pipelines)
CI/end-to-end tests sponsored by: [CNCF](https://cncf.io), [Equinix Metal](https://metal.equinix.com/), [OVHcloud](https://www.ovhcloud.com/), [ELASTX](https://elastx.se/). CI/end-to-end tests sponsored by: [CNCF](https://cncf.io), [Equinix Metal](https://metal.equinix.com/), [OVHcloud](https://www.ovhcloud.com/), [ELASTX](https://elastx.se/).

View File

@@ -60,7 +60,7 @@ release-notes --start-sha <The start commit-id> --end-sha <The end commit-id> --
``` ```
If the release note file(/tmp/kubespray-release-note) contains "### Uncategorized" pull requests, those pull requests don't have a valid kind label(`kind/feature`, etc.). If the release note file(/tmp/kubespray-release-note) contains "### Uncategorized" pull requests, those pull requests don't have a valid kind label(`kind/feature`, etc.).
It is necessary to put a valid label on each pull request and run the above release-notes command again to get a better release note It is necessary to put a valid label on each pull request and run the above release-notes command again to get a better release note)
## Container image creation ## Container image creation

30
Vagrantfile vendored
View File

@@ -10,7 +10,6 @@ Vagrant.require_version ">= 2.0.0"
CONFIG = File.join(File.dirname(__FILE__), ENV['KUBESPRAY_VAGRANT_CONFIG'] || 'vagrant/config.rb') CONFIG = File.join(File.dirname(__FILE__), ENV['KUBESPRAY_VAGRANT_CONFIG'] || 'vagrant/config.rb')
FLATCAR_URL_TEMPLATE = "https://%s.release.flatcar-linux.net/amd64-usr/current/flatcar_production_vagrant.json" FLATCAR_URL_TEMPLATE = "https://%s.release.flatcar-linux.net/amd64-usr/current/flatcar_production_vagrant.json"
FEDORA35_MIRROR = "https://download.fedoraproject.org/pub/fedora/linux/releases/35/Cloud/x86_64/images/Fedora-Cloud-Base-Vagrant-35-1.2.x86_64.vagrant-libvirt.box"
# Uniq disk UUID for libvirt # Uniq disk UUID for libvirt
DISK_UUID = Time.now.utc.to_i DISK_UUID = Time.now.utc.to_i
@@ -30,8 +29,8 @@ SUPPORTED_OS = {
"almalinux8" => {box: "almalinux/8", user: "vagrant"}, "almalinux8" => {box: "almalinux/8", user: "vagrant"},
"almalinux8-bento" => {box: "bento/almalinux-8", user: "vagrant"}, "almalinux8-bento" => {box: "bento/almalinux-8", user: "vagrant"},
"rockylinux8" => {box: "generic/rocky8", user: "vagrant"}, "rockylinux8" => {box: "generic/rocky8", user: "vagrant"},
"fedora35" => {box: "fedora/35-cloud-base", user: "vagrant", box_url: FEDORA35_MIRROR}, "fedora37" => {box: "fedora/37-cloud-base", user: "vagrant"},
"fedora36" => {box: "fedora/36-cloud-base", user: "vagrant"}, "fedora38" => {box: "fedora/38-cloud-base", user: "vagrant"},
"opensuse" => {box: "opensuse/Leap-15.4.x86_64", user: "vagrant"}, "opensuse" => {box: "opensuse/Leap-15.4.x86_64", user: "vagrant"},
"opensuse-tumbleweed" => {box: "opensuse/Tumbleweed.x86_64", user: "vagrant"}, "opensuse-tumbleweed" => {box: "opensuse/Tumbleweed.x86_64", user: "vagrant"},
"oraclelinux" => {box: "generic/oracle7", user: "vagrant"}, "oraclelinux" => {box: "generic/oracle7", user: "vagrant"},
@@ -56,14 +55,14 @@ $subnet ||= "172.18.8"
$subnet_ipv6 ||= "fd3c:b398:0698:0756" $subnet_ipv6 ||= "fd3c:b398:0698:0756"
$os ||= "ubuntu1804" $os ||= "ubuntu1804"
$network_plugin ||= "flannel" $network_plugin ||= "flannel"
# Setting multi_networking to true will install Multus: https://github.com/k8snetworkplumbingwg/multus-cni # Setting multi_networking to true will install Multus: https://github.com/intel/multus-cni
$multi_networking ||= "False" $multi_networking ||= "False"
$download_run_once ||= "True" $download_run_once ||= "True"
$download_force_cache ||= "False" $download_force_cache ||= "False"
# The first three nodes are etcd servers # The first three nodes are etcd servers
$etcd_instances ||= [$num_instances, 3].min $etcd_instances ||= $num_instances
# The first two nodes are kube masters # The first two nodes are kube masters
$kube_master_instances ||= [$num_instances, 2].min $kube_master_instances ||= $num_instances == 1 ? $num_instances : ($num_instances - 1)
# All nodes are kube nodes # All nodes are kube nodes
$kube_node_instances ||= $num_instances $kube_node_instances ||= $num_instances
# The following only works when using the libvirt provider # The following only works when using the libvirt provider
@@ -83,13 +82,6 @@ $playbook ||= "cluster.yml"
host_vars = {} host_vars = {}
# throw error if os is not supported
if ! SUPPORTED_OS.key?($os)
puts "Unsupported OS: #{$os}"
puts "Supported OS are: #{SUPPORTED_OS.keys.join(', ')}"
exit 1
end
$box = SUPPORTED_OS[$os][:box] $box = SUPPORTED_OS[$os][:box]
# if $inventory is not set, try to use example # if $inventory is not set, try to use example
$inventory = "inventory/sample" if ! $inventory $inventory = "inventory/sample" if ! $inventory
@@ -209,7 +201,8 @@ Vagrant.configure("2") do |config|
end end
ip = "#{$subnet}.#{i+100}" ip = "#{$subnet}.#{i+100}"
node.vm.network :private_network, ip: ip, node.vm.network :private_network,
:ip => ip,
:libvirt__guest_ipv6 => 'yes', :libvirt__guest_ipv6 => 'yes',
:libvirt__ipv6_address => "#{$subnet_ipv6}::#{i+100}", :libvirt__ipv6_address => "#{$subnet_ipv6}::#{i+100}",
:libvirt__ipv6_prefix => "64", :libvirt__ipv6_prefix => "64",
@@ -224,6 +217,14 @@ Vagrant.configure("2") do |config|
node.vm.provision "shell", inline: "rm -f /etc/modprobe.d/local.conf" node.vm.provision "shell", inline: "rm -f /etc/modprobe.d/local.conf"
node.vm.provision "shell", inline: "sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf /etc/sysctl.conf" node.vm.provision "shell", inline: "sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf /etc/sysctl.conf"
end end
# Hack for fedora37/38 to get the IP address of the second interface
if ["fedora37", "fedora38"].include? $os
config.vm.provision "shell", inline: <<-SHELL
nmcli conn modify 'Wired connection 2' ipv4.addresses $(cat /etc/sysconfig/network-scripts/ifcfg-eth1 | grep IPADDR | cut -d "=" -f2)
nmcli conn modify 'Wired connection 2' ipv4.method manual
service NetworkManager restart
SHELL
end
# Disable firewalld on oraclelinux/redhat vms # Disable firewalld on oraclelinux/redhat vms
if ["oraclelinux","oraclelinux8","rhel7","rhel8"].include? $os if ["oraclelinux","oraclelinux8","rhel7","rhel8"].include? $os
@@ -256,6 +257,7 @@ Vagrant.configure("2") do |config|
if i == $num_instances if i == $num_instances
node.vm.provision "ansible" do |ansible| node.vm.provision "ansible" do |ansible|
ansible.playbook = $playbook ansible.playbook = $playbook
ansible.compatibility_mode = "2.0"
ansible.verbose = $ansible_verbosity ansible.verbose = $ansible_verbosity
$ansible_inventory_path = File.join( $inventory, "hosts.ini") $ansible_inventory_path = File.join( $inventory, "hosts.ini")
if File.exist?($ansible_inventory_path) if File.exist?($ansible_inventory_path)

View File

@@ -1,3 +1,131 @@
--- ---
- name: Install Kubernetes - name: Check ansible version
ansible.builtin.import_playbook: playbooks/cluster.yml import_playbook: ansible_version.yml
- name: Ensure compatibility with old groups
import_playbook: legacy_groups.yml
- hosts: bastion[0]
gather_facts: False
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: bastion-ssh-config, tags: ["localhost", "bastion"] }
- hosts: k8s_cluster:etcd
strategy: linear
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
gather_facts: false
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: bootstrap-os, tags: bootstrap-os}
- name: Gather facts
tags: always
import_playbook: facts.yml
- hosts: k8s_cluster:etcd
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes/preinstall, tags: preinstall }
- { role: "container-engine", tags: "container-engine", when: deploy_container_engine }
- { role: download, tags: download, when: "not skip_downloads" }
- hosts: etcd:kube_control_plane
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- role: etcd
tags: etcd
vars:
etcd_cluster_setup: true
etcd_events_cluster_setup: "{{ etcd_events_cluster_enabled }}"
when: etcd_deployment_type != "kubeadm"
- hosts: k8s_cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- role: etcd
tags: etcd
vars:
etcd_cluster_setup: false
etcd_events_cluster_setup: false
when:
- etcd_deployment_type != "kubeadm"
- kube_network_plugin in ["calico", "flannel", "canal", "cilium"] or cilium_deploy_additionally | default(false) | bool
- kube_network_plugin != "calico" or calico_datastore == "etcd"
- hosts: k8s_cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes/node, tags: node }
- hosts: kube_control_plane
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes/control-plane, tags: master }
- { role: kubernetes/client, tags: client }
- { role: kubernetes-apps/cluster_roles, tags: cluster-roles }
- hosts: k8s_cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes/kubeadm, tags: kubeadm}
- { role: kubernetes/node-label, tags: node-label }
- { role: network_plugin, tags: network }
- hosts: calico_rr
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: network_plugin/calico/rr, tags: ['network', 'calico_rr'] }
- hosts: kube_control_plane[0]
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: win_nodes/kubernetes_patch, tags: ["master", "win_nodes"] }
- hosts: kube_control_plane
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes-apps/external_cloud_controller, tags: external-cloud-controller }
- { role: kubernetes-apps/network_plugin, tags: network }
- { role: kubernetes-apps/policy_controller, tags: policy-controller }
- { role: kubernetes-apps/ingress_controller, tags: ingress-controller }
- { role: kubernetes-apps/external_provisioner, tags: external-provisioner }
- { role: kubernetes-apps, tags: apps }
- name: Apply resolv.conf changes now that cluster DNS is up
hosts: k8s_cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes/preinstall, when: "dns_mode != 'none' and resolvconf_mode == 'host_resolvconf'", tags: resolvconf, dns_late: true }

View File

@@ -1 +1 @@
boto3 # Apache-2.0 boto3 # Apache-2.0

View File

@@ -1,2 +1,2 @@
.generated .generated
/inventory /inventory

View File

@@ -31,3 +31,4 @@
[k8s_cluster:children] [k8s_cluster:children]
kube_node kube_node
kube_control_plane kube_control_plane

View File

@@ -27,4 +27,4 @@
} }
} }
] ]
} }

View File

@@ -103,4 +103,4 @@
} }
{% endif %} {% endif %}
] ]
} }

View File

@@ -5,4 +5,4 @@
"variables": {}, "variables": {},
"resources": [], "resources": [],
"outputs": {} "outputs": {}
} }

View File

@@ -16,4 +16,4 @@
} }
} }
] ]
} }

View File

@@ -43,7 +43,7 @@
package: package:
name: "{{ item }}" name: "{{ item }}"
state: present state: present
with_items: "{{ distro_extra_packages + [ 'rsyslog', 'openssh-server' ] }}" with_items: "{{ distro_extra_packages }} + [ 'rsyslog', 'openssh-server' ]"
- name: Start needed services - name: Start needed services
service: service:

View File

@@ -1,3 +1,3 @@
configparser>=3.3.0 configparser>=3.3.0
ipaddress
ruamel.yaml>=0.15.88 ruamel.yaml>=0.15.88
ipaddress

View File

@@ -1,3 +1,3 @@
hacking>=0.10.2 hacking>=0.10.2
mock>=1.3.0
pytest>=2.8.0 pytest>=2.8.0
mock>=1.3.0

View File

@@ -1,2 +1,3 @@
#k8s_deployment_user: kubespray #k8s_deployment_user: kubespray
#k8s_deployment_user_pkey_path: /tmp/ssh_rsa #k8s_deployment_user_pkey_path: /tmp/ssh_rsa

View File

@@ -41,3 +41,4 @@
# [network-storage:children] # [network-storage:children]
# gfs-cluster # gfs-cluster

View File

@@ -1,15 +0,0 @@
output "k8s_masters" {
value = equinix_metal_device.k8s_master.*.access_public_ipv4
}
output "k8s_masters_no_etc" {
value = equinix_metal_device.k8s_master_no_etcd.*.access_public_ipv4
}
output "k8s_etcds" {
value = equinix_metal_device.k8s_etcd.*.access_public_ipv4
}
output "k8s_nodes" {
value = equinix_metal_device.k8s_node.*.access_public_ipv4
}

View File

@@ -1,17 +0,0 @@
terraform {
required_version = ">= 1.0.0"
provider_meta "equinix" {
module_name = "kubespray"
}
required_providers {
equinix = {
source = "equinix/equinix"
version = "~> 1.14"
}
}
}
# Configure the Equinix Metal Provider
provider "equinix" {
}

View File

@@ -12,7 +12,7 @@ ssh_public_keys = [
machines = { machines = {
"master-0" : { "master-0" : {
"node_type" : "master", "node_type" : "master",
"size" : "Medium", "size" : "standard.medium",
"boot_disk" : { "boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit", "image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50, "root_partition_size" : 50,
@@ -22,7 +22,7 @@ machines = {
}, },
"worker-0" : { "worker-0" : {
"node_type" : "worker", "node_type" : "worker",
"size" : "Large", "size" : "standard.large",
"boot_disk" : { "boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit", "image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50, "root_partition_size" : 50,
@@ -32,7 +32,7 @@ machines = {
}, },
"worker-1" : { "worker-1" : {
"node_type" : "worker", "node_type" : "worker",
"size" : "Large", "size" : "standard.large",
"boot_disk" : { "boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit", "image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50, "root_partition_size" : 50,
@@ -42,7 +42,7 @@ machines = {
}, },
"worker-2" : { "worker-2" : {
"node_type" : "worker", "node_type" : "worker",
"size" : "Large", "size" : "standard.large",
"boot_disk" : { "boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit", "image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50, "root_partition_size" : 50,

View File

@@ -1,29 +1,25 @@
data "exoscale_compute_template" "os_image" { data "exoscale_template" "os_image" {
for_each = var.machines for_each = var.machines
zone = var.zone zone = var.zone
name = each.value.boot_disk.image_name name = each.value.boot_disk.image_name
} }
data "exoscale_compute" "master_nodes" { data "exoscale_compute_instance" "master_nodes" {
for_each = exoscale_compute.master for_each = exoscale_compute_instance.master
id = each.value.id id = each.value.id
zone = var.zone
# Since private IP address is not assigned until the nics are created we need this
depends_on = [exoscale_nic.master_private_network_nic]
} }
data "exoscale_compute" "worker_nodes" { data "exoscale_compute_instance" "worker_nodes" {
for_each = exoscale_compute.worker for_each = exoscale_compute_instance.worker
id = each.value.id id = each.value.id
zone = var.zone
# Since private IP address is not assigned until the nics are created we need this
depends_on = [exoscale_nic.worker_private_network_nic]
} }
resource "exoscale_network" "private_network" { resource "exoscale_private_network" "private_network" {
zone = var.zone zone = var.zone
name = "${var.prefix}-network" name = "${var.prefix}-network"
@@ -34,25 +30,29 @@ resource "exoscale_network" "private_network" {
netmask = cidrnetmask(var.private_network_cidr) netmask = cidrnetmask(var.private_network_cidr)
} }
resource "exoscale_compute" "master" { resource "exoscale_compute_instance" "master" {
for_each = { for_each = {
for name, machine in var.machines : for name, machine in var.machines :
name => machine name => machine
if machine.node_type == "master" if machine.node_type == "master"
} }
display_name = "${var.prefix}-${each.key}" name = "${var.prefix}-${each.key}"
template_id = data.exoscale_compute_template.os_image[each.key].id template_id = data.exoscale_template.os_image[each.key].id
size = each.value.size type = each.value.size
disk_size = each.value.boot_disk.root_partition_size + each.value.boot_disk.node_local_partition_size + each.value.boot_disk.ceph_partition_size disk_size = each.value.boot_disk.root_partition_size + each.value.boot_disk.node_local_partition_size + each.value.boot_disk.ceph_partition_size
state = "Running" state = "Running"
zone = var.zone zone = var.zone
security_groups = [exoscale_security_group.master_sg.name] security_group_ids = [exoscale_security_group.master_sg.id]
network_interface {
network_id = exoscale_private_network.private_network.id
}
elastic_ip_ids = [exoscale_elastic_ip.control_plane_lb.id]
user_data = templatefile( user_data = templatefile(
"${path.module}/templates/cloud-init.tmpl", "${path.module}/templates/cloud-init.tmpl",
{ {
eip_ip_address = exoscale_ipaddress.ingress_controller_lb.ip_address eip_ip_address = exoscale_elastic_ip.ingress_controller_lb.ip_address
node_local_partition_size = each.value.boot_disk.node_local_partition_size node_local_partition_size = each.value.boot_disk.node_local_partition_size
ceph_partition_size = each.value.boot_disk.ceph_partition_size ceph_partition_size = each.value.boot_disk.ceph_partition_size
root_partition_size = each.value.boot_disk.root_partition_size root_partition_size = each.value.boot_disk.root_partition_size
@@ -62,25 +62,29 @@ resource "exoscale_compute" "master" {
) )
} }
resource "exoscale_compute" "worker" { resource "exoscale_compute_instance" "worker" {
for_each = { for_each = {
for name, machine in var.machines : for name, machine in var.machines :
name => machine name => machine
if machine.node_type == "worker" if machine.node_type == "worker"
} }
display_name = "${var.prefix}-${each.key}" name = "${var.prefix}-${each.key}"
template_id = data.exoscale_compute_template.os_image[each.key].id template_id = data.exoscale_template.os_image[each.key].id
size = each.value.size type = each.value.size
disk_size = each.value.boot_disk.root_partition_size + each.value.boot_disk.node_local_partition_size + each.value.boot_disk.ceph_partition_size disk_size = each.value.boot_disk.root_partition_size + each.value.boot_disk.node_local_partition_size + each.value.boot_disk.ceph_partition_size
state = "Running" state = "Running"
zone = var.zone zone = var.zone
security_groups = [exoscale_security_group.worker_sg.name] security_group_ids = [exoscale_security_group.worker_sg.id]
network_interface {
network_id = exoscale_private_network.private_network.id
}
elastic_ip_ids = [exoscale_elastic_ip.ingress_controller_lb.id]
user_data = templatefile( user_data = templatefile(
"${path.module}/templates/cloud-init.tmpl", "${path.module}/templates/cloud-init.tmpl",
{ {
eip_ip_address = exoscale_ipaddress.ingress_controller_lb.ip_address eip_ip_address = exoscale_elastic_ip.ingress_controller_lb.ip_address
node_local_partition_size = each.value.boot_disk.node_local_partition_size node_local_partition_size = each.value.boot_disk.node_local_partition_size
ceph_partition_size = each.value.boot_disk.ceph_partition_size ceph_partition_size = each.value.boot_disk.ceph_partition_size
root_partition_size = each.value.boot_disk.root_partition_size root_partition_size = each.value.boot_disk.root_partition_size
@@ -90,41 +94,33 @@ resource "exoscale_compute" "worker" {
) )
} }
resource "exoscale_nic" "master_private_network_nic" {
for_each = exoscale_compute.master
compute_id = each.value.id
network_id = exoscale_network.private_network.id
}
resource "exoscale_nic" "worker_private_network_nic" {
for_each = exoscale_compute.worker
compute_id = each.value.id
network_id = exoscale_network.private_network.id
}
resource "exoscale_security_group" "master_sg" { resource "exoscale_security_group" "master_sg" {
name = "${var.prefix}-master-sg" name = "${var.prefix}-master-sg"
description = "Security group for Kubernetes masters" description = "Security group for Kubernetes masters"
} }
resource "exoscale_security_group_rules" "master_sg_rules" { resource "exoscale_security_group_rule" "master_sg_rule_ssh" {
security_group_id = exoscale_security_group.master_sg.id security_group_id = exoscale_security_group.master_sg.id
for_each = toset(var.ssh_whitelist)
# SSH # SSH
ingress { type = "INGRESS"
protocol = "TCP" start_port = 22
cidr_list = var.ssh_whitelist end_port = 22
ports = ["22"] protocol = "TCP"
} cidr = each.value
}
resource "exoscale_security_group_rule" "master_sg_rule_k8s_api" {
security_group_id = exoscale_security_group.master_sg.id
for_each = toset(var.api_server_whitelist)
# Kubernetes API # Kubernetes API
ingress { type = "INGRESS"
protocol = "TCP" start_port = 6443
cidr_list = var.api_server_whitelist end_port = 6443
ports = ["6443"] protocol = "TCP"
} cidr = each.value
} }
resource "exoscale_security_group" "worker_sg" { resource "exoscale_security_group" "worker_sg" {
@@ -132,62 +128,64 @@ resource "exoscale_security_group" "worker_sg" {
description = "security group for kubernetes worker nodes" description = "security group for kubernetes worker nodes"
} }
resource "exoscale_security_group_rules" "worker_sg_rules" { resource "exoscale_security_group_rule" "worker_sg_rule_ssh" {
security_group_id = exoscale_security_group.worker_sg.id security_group_id = exoscale_security_group.worker_sg.id
# SSH # SSH
ingress { for_each = toset(var.ssh_whitelist)
protocol = "TCP" type = "INGRESS"
cidr_list = var.ssh_whitelist start_port = 22
ports = ["22"] end_port = 22
} protocol = "TCP"
cidr = each.value
}
resource "exoscale_security_group_rule" "worker_sg_rule_http" {
security_group_id = exoscale_security_group.worker_sg.id
# HTTP(S) # HTTP(S)
ingress { for_each = toset(["80", "443"])
protocol = "TCP" type = "INGRESS"
cidr_list = ["0.0.0.0/0"] start_port = each.value
ports = ["80", "443"] end_port = each.value
} protocol = "TCP"
cidr = "0.0.0.0/0"
}
# Kubernetes Nodeport
ingress { resource "exoscale_security_group_rule" "worker_sg_rule_nodeport" {
protocol = "TCP" security_group_id = exoscale_security_group.worker_sg.id
cidr_list = var.nodeport_whitelist
ports = ["30000-32767"] # HTTP(S)
for_each = toset(var.nodeport_whitelist)
type = "INGRESS"
start_port = 30000
end_port = 32767
protocol = "TCP"
cidr = each.value
}
resource "exoscale_elastic_ip" "ingress_controller_lb" {
zone = var.zone
healthcheck {
mode = "http"
port = 80
uri = "/healthz"
interval = 10
timeout = 2
strikes_ok = 2
strikes_fail = 3
} }
} }
resource "exoscale_ipaddress" "ingress_controller_lb" { resource "exoscale_elastic_ip" "control_plane_lb" {
zone = var.zone zone = var.zone
healthcheck_mode = "http" healthcheck {
healthcheck_port = 80 mode = "tcp"
healthcheck_path = "/healthz" port = 6443
healthcheck_interval = 10 interval = 10
healthcheck_timeout = 2 timeout = 2
healthcheck_strikes_ok = 2 strikes_ok = 2
healthcheck_strikes_fail = 3 strikes_fail = 3
} }
resource "exoscale_secondary_ipaddress" "ingress_controller_lb" {
for_each = exoscale_compute.worker
compute_id = each.value.id
ip_address = exoscale_ipaddress.ingress_controller_lb.ip_address
}
resource "exoscale_ipaddress" "control_plane_lb" {
zone = var.zone
healthcheck_mode = "tcp"
healthcheck_port = 6443
healthcheck_interval = 10
healthcheck_timeout = 2
healthcheck_strikes_ok = 2
healthcheck_strikes_fail = 3
}
resource "exoscale_secondary_ipaddress" "control_plane_lb" {
for_each = exoscale_compute.master
compute_id = each.value.id
ip_address = exoscale_ipaddress.control_plane_lb.ip_address
} }

View File

@@ -1,19 +1,19 @@
output "master_ip_addresses" { output "master_ip_addresses" {
value = { value = {
for key, instance in exoscale_compute.master : for key, instance in exoscale_compute_instance.master :
instance.name => { instance.name => {
"private_ip" = contains(keys(data.exoscale_compute.master_nodes), key) ? data.exoscale_compute.master_nodes[key].private_network_ip_addresses[0] : "" "private_ip" = contains(keys(data.exoscale_compute_instance.master_nodes), key) ? data.exoscale_compute_instance.master_nodes[key].private_network_ip_addresses[0] : ""
"public_ip" = exoscale_compute.master[key].ip_address "public_ip" = exoscale_compute_instance.master[key].ip_address
} }
} }
} }
output "worker_ip_addresses" { output "worker_ip_addresses" {
value = { value = {
for key, instance in exoscale_compute.worker : for key, instance in exoscale_compute_instance.worker :
instance.name => { instance.name => {
"private_ip" = contains(keys(data.exoscale_compute.worker_nodes), key) ? data.exoscale_compute.worker_nodes[key].private_network_ip_addresses[0] : "" "private_ip" = contains(keys(data.exoscale_compute_instance.worker_nodes), key) ? data.exoscale_compute_instance.worker_nodes[key].private_network_ip_addresses[0] : ""
"public_ip" = exoscale_compute.worker[key].ip_address "public_ip" = exoscale_compute_instance.worker[key].ip_address
} }
} }
} }
@@ -23,9 +23,9 @@ output "cluster_private_network_cidr" {
} }
output "ingress_controller_lb_ip_address" { output "ingress_controller_lb_ip_address" {
value = exoscale_ipaddress.ingress_controller_lb.ip_address value = exoscale_elastic_ip.ingress_controller_lb.ip_address
} }
output "control_plane_lb_ip_address" { output "control_plane_lb_ip_address" {
value = exoscale_ipaddress.control_plane_lb.ip_address value = exoscale_elastic_ip.control_plane_lb.ip_address
} }

View File

@@ -1,7 +1,7 @@
terraform { terraform {
required_providers { required_providers {
exoscale = { exoscale = {
source = "exoscale/exoscale" source = "exoscale/exoscale"
version = ">= 0.21" version = ">= 0.21"
} }
} }

View File

@@ -1,6 +1,6 @@
prefix = "default" prefix = "default"
zone = "hel1" zone = "hel1"
network_zone = "eu-central" network_zone = "eu-central"
inventory_file = "inventory.ini" inventory_file = "inventory.ini"
ssh_public_keys = [ ssh_public_keys = [
@@ -15,17 +15,17 @@ machines = {
"master-0" : { "master-0" : {
"node_type" : "master", "node_type" : "master",
"size" : "cx21", "size" : "cx21",
"image" : "ubuntu-22.04", "image" : "ubuntu-20.04",
}, },
"worker-0" : { "worker-0" : {
"node_type" : "worker", "node_type" : "worker",
"size" : "cx21", "size" : "cx21",
"image" : "ubuntu-22.04", "image" : "ubuntu-20.04",
}, },
"worker-1" : { "worker-1" : {
"node_type" : "worker", "node_type" : "worker",
"size" : "cx21", "size" : "cx21",
"image" : "ubuntu-22.04", "image" : "ubuntu-20.04",
} }
} }

View File

@@ -2,7 +2,7 @@ provider "hcloud" {}
module "kubernetes" { module "kubernetes" {
source = "./modules/kubernetes-cluster" source = "./modules/kubernetes-cluster"
# source = "./modules/kubernetes-cluster-flatcar" #source = "./modules/kubernetes-cluster-flatcar"
prefix = var.prefix prefix = var.prefix
@@ -14,7 +14,7 @@ module "kubernetes" {
#ssh_private_key_path = var.ssh_private_key_path #ssh_private_key_path = var.ssh_private_key_path
ssh_public_keys = var.ssh_public_keys ssh_public_keys = var.ssh_public_keys
network_zone = var.network_zone network_zone = var.network_zone
ssh_whitelist = var.ssh_whitelist ssh_whitelist = var.ssh_whitelist
api_server_whitelist = var.api_server_whitelist api_server_whitelist = var.api_server_whitelist
@@ -26,32 +26,31 @@ module "kubernetes" {
# Generate ansible inventory # Generate ansible inventory
# #
locals { data "template_file" "inventory" {
inventory = templatefile( template = file("${path.module}/templates/inventory.tpl")
"${path.module}/templates/inventory.tpl",
{ vars = {
connection_strings_master = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s ip=%s etcd_member_name=etcd%d", connection_strings_master = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s ip=%s etcd_member_name=etcd%d",
keys(module.kubernetes.master_ip_addresses), keys(module.kubernetes.master_ip_addresses),
values(module.kubernetes.master_ip_addresses).*.public_ip, values(module.kubernetes.master_ip_addresses).*.public_ip,
values(module.kubernetes.master_ip_addresses).*.private_ip, values(module.kubernetes.master_ip_addresses).*.private_ip,
range(1, length(module.kubernetes.master_ip_addresses) + 1))) range(1, length(module.kubernetes.master_ip_addresses) + 1)))
connection_strings_worker = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s ip=%s", connection_strings_worker = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s ip=%s",
keys(module.kubernetes.worker_ip_addresses), keys(module.kubernetes.worker_ip_addresses),
values(module.kubernetes.worker_ip_addresses).*.public_ip, values(module.kubernetes.worker_ip_addresses).*.public_ip,
values(module.kubernetes.worker_ip_addresses).*.private_ip)) values(module.kubernetes.worker_ip_addresses).*.private_ip))
list_master = join("\n", keys(module.kubernetes.master_ip_addresses)) list_master = join("\n", keys(module.kubernetes.master_ip_addresses))
list_worker = join("\n", keys(module.kubernetes.worker_ip_addresses)) list_worker = join("\n", keys(module.kubernetes.worker_ip_addresses))
network_id = module.kubernetes.network_id network_id = module.kubernetes.network_id
} }
)
} }
resource "null_resource" "inventories" { resource "null_resource" "inventories" {
provisioner "local-exec" { provisioner "local-exec" {
command = "echo '${local.inventory}' > ${var.inventory_file}" command = "echo '${data.template_file.inventory.rendered}' > ${var.inventory_file}"
} }
triggers = { triggers = {
template = local.inventory template = data.template_file.inventory.rendered
} }
} }

View File

@@ -15,12 +15,12 @@ resource "hcloud_ssh_key" "first" {
public_key = var.ssh_public_keys.0 public_key = var.ssh_public_keys.0
} }
resource "hcloud_server" "machine" { resource "hcloud_server" "master" {
for_each = { for_each = {
for name, machine in var.machines : for name, machine in var.machines :
name => machine name => machine
if machine.node_type == "master"
} }
name = "${var.prefix}-${each.key}" name = "${var.prefix}-${each.key}"
ssh_keys = [hcloud_ssh_key.first.id] ssh_keys = [hcloud_ssh_key.first.id]
# boot into rescue OS # boot into rescue OS
@@ -30,11 +30,11 @@ resource "hcloud_server" "machine" {
server_type = each.value.size server_type = each.value.size
location = var.zone location = var.zone
connection { connection {
host = self.ipv4_address host = self.ipv4_address
timeout = "5m" timeout = "5m"
private_key = file(var.ssh_private_key_path) private_key = file(var.ssh_private_key_path)
} }
firewall_ids = each.value.node_type == "master" ? [hcloud_firewall.master.id] : [hcloud_firewall.worker.id] firewall_ids = [hcloud_firewall.machine.id]
provisioner "file" { provisioner "file" {
content = data.ct_config.machine-ignitions[each.key].rendered content = data.ct_config.machine-ignitions[each.key].rendered
destination = "/root/ignition.json" destination = "/root/ignition.json"
@@ -45,9 +45,9 @@ resource "hcloud_server" "machine" {
"set -ex", "set -ex",
"apt update", "apt update",
"apt install -y gawk", "apt install -y gawk",
"curl -fsSLO --retry-delay 1 --retry 60 --retry-connrefused --retry-max-time 60 --connect-timeout 20 https://raw.githubusercontent.com/flatcar/init/flatcar-master/bin/flatcar-install", "curl -fsSLO --retry-delay 1 --retry 60 --retry-connrefused --retry-max-time 60 --connect-timeout 20 https://raw.githubusercontent.com/kinvolk/init/flatcar-master/bin/flatcar-install",
"chmod +x flatcar-install", "chmod +x flatcar-install",
"./flatcar-install -s -i /root/ignition.json -C stable", "./flatcar-install -s -i /root/ignition.json",
"shutdown -r +1", "shutdown -r +1",
] ]
} }
@@ -55,10 +55,9 @@ resource "hcloud_server" "machine" {
# optional: # optional:
provisioner "remote-exec" { provisioner "remote-exec" {
connection { connection {
host = self.ipv4_address host = self.ipv4_address
private_key = file(var.ssh_private_key_path) timeout = "3m"
timeout = "3m" user = var.user_flatcar
user = var.user_flatcar
} }
inline = [ inline = [
@@ -67,11 +66,65 @@ resource "hcloud_server" "machine" {
} }
} }
resource "hcloud_server_network" "machine" { resource "hcloud_server_network" "master" {
for_each = hcloud_server.master
server_id = each.value.id
subnet_id = hcloud_network_subnet.kubernetes.id
}
resource "hcloud_server" "worker" {
for_each = { for_each = {
for name, machine in var.machines : for name, machine in var.machines :
name => hcloud_server.machine[name] name => machine
if machine.node_type == "worker"
} }
name = "${var.prefix}-${each.key}"
ssh_keys = [hcloud_ssh_key.first.id]
# boot into rescue OS
rescue = "linux64"
# dummy value for the OS because Flatcar is not available
image = each.value.image
server_type = each.value.size
location = var.zone
connection {
host = self.ipv4_address
timeout = "5m"
private_key = file(var.ssh_private_key_path)
}
firewall_ids = [hcloud_firewall.machine.id]
provisioner "file" {
content = data.ct_config.machine-ignitions[each.key].rendered
destination = "/root/ignition.json"
}
provisioner "remote-exec" {
inline = [
"set -ex",
"apt update",
"apt install -y gawk",
"curl -fsSLO --retry-delay 1 --retry 60 --retry-connrefused --retry-max-time 60 --connect-timeout 20 https://raw.githubusercontent.com/kinvolk/init/flatcar-master/bin/flatcar-install",
"chmod +x flatcar-install",
"./flatcar-install -s -i /root/ignition.json",
"shutdown -r +1",
]
}
# optional:
provisioner "remote-exec" {
connection {
host = self.ipv4_address
timeout = "3m"
user = var.user_flatcar
}
inline = [
"sudo hostnamectl set-hostname ${self.name}",
]
}
}
resource "hcloud_server_network" "worker" {
for_each = hcloud_server.worker
server_id = each.value.id server_id = each.value.id
subnet_id = hcloud_network_subnet.kubernetes.id subnet_id = hcloud_network_subnet.kubernetes.id
} }
@@ -81,33 +134,38 @@ data "ct_config" "machine-ignitions" {
for name, machine in var.machines : for name, machine in var.machines :
name => machine name => machine
} }
content = data.template_file.machine-configs[each.key].rendered
strict = false
content = templatefile(
"${path.module}/templates/machine.yaml.tmpl",
{
ssh_keys = jsonencode(var.ssh_public_keys)
user_flatcar = var.user_flatcar
name = each.key
}
)
} }
resource "hcloud_firewall" "master" { data "template_file" "machine-configs" {
name = "${var.prefix}-master-firewall" for_each = {
for name, machine in var.machines :
name => machine
}
template = file("${path.module}/templates/machine.yaml.tmpl")
vars = {
ssh_keys = jsonencode(var.ssh_public_keys)
user_flatcar = jsonencode(var.user_flatcar)
name = each.key
}
}
resource "hcloud_firewall" "machine" {
name = "${var.prefix}-machine-firewall"
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "22" port = "22"
source_ips = var.ssh_whitelist source_ips = var.ssh_whitelist
} }
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "6443" port = "6443"
source_ips = var.api_server_whitelist source_ips = var.api_server_whitelist
} }
} }
@@ -115,30 +173,30 @@ resource "hcloud_firewall" "worker" {
name = "${var.prefix}-worker-firewall" name = "${var.prefix}-worker-firewall"
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "22" port = "22"
source_ips = var.ssh_whitelist source_ips = var.ssh_whitelist
} }
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "80" port = "80"
source_ips = var.ingress_whitelist source_ips = var.ingress_whitelist
} }
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "443" port = "443"
source_ips = var.ingress_whitelist source_ips = var.ingress_whitelist
} }
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "30000-32767" port = "30000-32767"
source_ips = var.nodeport_whitelist source_ips = var.nodeport_whitelist
} }
} }

View File

@@ -1,22 +1,20 @@
output "master_ip_addresses" { output "master_ip_addresses" {
value = { value = {
for name, machine in var.machines : for key, instance in hcloud_server.master :
name => { instance.name => {
"private_ip" = hcloud_server_network.machine[name].ip "private_ip" = hcloud_server_network.master[key].ip
"public_ip" = hcloud_server.machine[name].ipv4_address "public_ip" = hcloud_server.master[key].ipv4_address
} }
if machine.node_type == "master"
} }
} }
output "worker_ip_addresses" { output "worker_ip_addresses" {
value = { value = {
for name, machine in var.machines : for key, instance in hcloud_server.worker :
name => { instance.name => {
"private_ip" = hcloud_server_network.machine[name].ip "private_ip" = hcloud_server_network.worker[key].ip
"public_ip" = hcloud_server.machine[name].ipv4_address "public_ip" = hcloud_server.worker[key].ipv4_address
} }
if machine.node_type == "worker"
} }
} }
@@ -26,4 +24,4 @@ output "cluster_private_network_cidr" {
output "network_id" { output "network_id" {
value = hcloud_network.kubernetes.id value = hcloud_network.kubernetes.id
} }

View File

@@ -1,11 +1,8 @@
variant: flatcar ---
version: 1.0.0
passwd: passwd:
users: users:
- name: ${user_flatcar} - name: ${user_flatcar}
ssh_authorized_keys: ${ssh_keys} ssh_authorized_keys: ${ssh_keys}
storage: storage:
files: files:
- path: /home/core/works - path: /home/core/works
@@ -16,4 +13,4 @@ storage:
#!/bin/bash #!/bin/bash
set -euo pipefail set -euo pipefail
hostname="$(hostname)" hostname="$(hostname)"
echo My name is ${name} and the hostname is $${hostname} echo My name is ${name} and the hostname is $${hostname}

View File

@@ -1,6 +1,6 @@
variable "zone" { variable "zone" {
type = string type = string
default = "fsn1" default = "fsn1"
} }
@@ -9,7 +9,7 @@ variable "prefix" {
} }
variable "user_flatcar" { variable "user_flatcar" {
type = string type = string
default = "core" default = "core"
} }

View File

@@ -1,14 +1,13 @@
terraform { terraform {
required_providers { required_providers {
hcloud = { hcloud = {
source = "hetznercloud/hcloud" source = "hetznercloud/hcloud"
} }
ct = { ct = {
source = "poseidon/ct" source = "poseidon/ct"
version = "0.11.0"
} }
null = { null = {
source = "hashicorp/null" source = "hashicorp/null"
} }
} }
} }

View File

@@ -75,17 +75,17 @@ resource "hcloud_firewall" "master" {
name = "${var.prefix}-master-firewall" name = "${var.prefix}-master-firewall"
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "22" port = "22"
source_ips = var.ssh_whitelist source_ips = var.ssh_whitelist
} }
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "6443" port = "6443"
source_ips = var.api_server_whitelist source_ips = var.api_server_whitelist
} }
} }
@@ -93,30 +93,30 @@ resource "hcloud_firewall" "worker" {
name = "${var.prefix}-worker-firewall" name = "${var.prefix}-worker-firewall"
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "22" port = "22"
source_ips = var.ssh_whitelist source_ips = var.ssh_whitelist
} }
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "80" port = "80"
source_ips = var.ingress_whitelist source_ips = var.ingress_whitelist
} }
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "443" port = "443"
source_ips = var.ingress_whitelist source_ips = var.ingress_whitelist
} }
rule { rule {
direction = "in" direction = "in"
protocol = "tcp" protocol = "tcp"
port = "30000-32767" port = "30000-32767"
source_ips = var.nodeport_whitelist source_ips = var.nodeport_whitelist
} }
} }

View File

@@ -24,4 +24,4 @@ output "cluster_private_network_cidr" {
output "network_id" { output "network_id" {
value = hcloud_network.kubernetes.id value = hcloud_network.kubernetes.id
} }

View File

@@ -14,3 +14,4 @@ ssh_authorized_keys:
%{ for ssh_public_key in ssh_public_keys ~} %{ for ssh_public_key in ssh_public_keys ~}
- ${ssh_public_key} - ${ssh_public_key}
%{ endfor ~} %{ endfor ~}

View File

@@ -1,8 +1,8 @@
terraform { terraform {
required_providers { required_providers {
hcloud = { hcloud = {
source = "hetznercloud/hcloud" source = "hetznercloud/hcloud"
version = "1.38.2" version = "1.31.1"
} }
} }
required_version = ">= 0.14" required_version = ">= 0.14"

View File

@@ -1,46 +0,0 @@
prefix = "default"
zone = "hel1"
network_zone = "eu-central"
inventory_file = "inventory.ini"
ssh_public_keys = [
# Put your public SSH key here
"ssh-rsa I-did-not-read-the-docs",
"ssh-rsa I-did-not-read-the-docs 2",
]
ssh_private_key_path = "~/.ssh/id_rsa"
machines = {
"master-0" : {
"node_type" : "master",
"size" : "cx21",
"image" : "ubuntu-22.04",
},
"worker-0" : {
"node_type" : "worker",
"size" : "cx21",
"image" : "ubuntu-22.04",
},
"worker-1" : {
"node_type" : "worker",
"size" : "cx21",
"image" : "ubuntu-22.04",
}
}
nodeport_whitelist = [
"0.0.0.0/0"
]
ingress_whitelist = [
"0.0.0.0/0"
]
ssh_whitelist = [
"0.0.0.0/0"
]
api_server_whitelist = [
"0.0.0.0/0"
]

View File

@@ -1 +0,0 @@
../../../../inventory/sample/group_vars

View File

@@ -3,7 +3,7 @@ variable "zone" {
} }
variable "network_zone" { variable "network_zone" {
description = "The network zone where the cluster is running" description = "The network zone where the cluster is running"
default = "eu-central" default = "eu-central"
} }
variable "prefix" { variable "prefix" {

View File

@@ -2,11 +2,14 @@ terraform {
required_providers { required_providers {
hcloud = { hcloud = {
source = "hetznercloud/hcloud" source = "hetznercloud/hcloud"
version = "1.38.2" version = "1.31.1"
} }
null = { null = {
source = "hashicorp/null" source = "hashicorp/null"
} }
template = {
source = "hashicorp/template"
}
} }
required_version = ">= 0.14" required_version = ">= 0.14"
} }

View File

@@ -12,7 +12,7 @@ This will install a Kubernetes cluster on Equinix Metal. It should work in all l
The terraform configuration inspects variables found in The terraform configuration inspects variables found in
[variables.tf](variables.tf) to create resources in your Equinix Metal project. [variables.tf](variables.tf) to create resources in your Equinix Metal project.
There is a [python script](../terraform.py) that reads the generated`.tfstate` There is a [python script](../terraform.py) that reads the generated`.tfstate`
file to generate a dynamic inventory that is consumed by [cluster.yml](../../../cluster.yml) file to generate a dynamic inventory that is consumed by [cluster.yml](../../..//cluster.yml)
to actually install Kubernetes with Kubespray. to actually install Kubernetes with Kubespray.
### Kubernetes Nodes ### Kubernetes Nodes
@@ -60,16 +60,16 @@ Terraform will be used to provision all of the Equinix Metal resources with base
Create an inventory directory for your cluster by copying the existing sample and linking the `hosts` script (used to build the inventory based on Terraform state): Create an inventory directory for your cluster by copying the existing sample and linking the `hosts` script (used to build the inventory based on Terraform state):
```ShellSession ```ShellSession
cp -LRp contrib/terraform/equinix/sample-inventory inventory/$CLUSTER cp -LRp contrib/terraform/metal/sample-inventory inventory/$CLUSTER
cd inventory/$CLUSTER cd inventory/$CLUSTER
ln -s ../../contrib/terraform/equinix/hosts ln -s ../../contrib/terraform/metal/hosts
``` ```
This will be the base for subsequent Terraform commands. This will be the base for subsequent Terraform commands.
#### Equinix Metal API access #### Equinix Metal API access
Your Equinix Metal API key must be available in the `METAL_AUTH_TOKEN` environment variable. Your Equinix Metal API key must be available in the `PACKET_AUTH_TOKEN` environment variable.
This key is typically stored outside of the code repo since it is considered secret. This key is typically stored outside of the code repo since it is considered secret.
If someone gets this key, they can startup/shutdown hosts in your project! If someone gets this key, they can startup/shutdown hosts in your project!
@@ -80,12 +80,10 @@ The Equinix Metal Project ID associated with the key will be set later in `clust
For more information about the API, please see [Equinix Metal API](https://metal.equinix.com/developers/api/). For more information about the API, please see [Equinix Metal API](https://metal.equinix.com/developers/api/).
For more information about terraform provider authentication, please see [the equinix provider documentation](https://registry.terraform.io/providers/equinix/equinix/latest/docs).
Example: Example:
```ShellSession ```ShellSession
export METAL_AUTH_TOKEN="Example-API-Token" export PACKET_AUTH_TOKEN="Example-API-Token"
``` ```
Note that to deploy several clusters within the same project you need to use [terraform workspace](https://www.terraform.io/docs/state/workspaces.html#using-workspaces). Note that to deploy several clusters within the same project you need to use [terraform workspace](https://www.terraform.io/docs/state/workspaces.html#using-workspaces).
@@ -103,7 +101,7 @@ This helps when identifying which hosts are associated with each cluster.
While the defaults in variables.tf will successfully deploy a cluster, it is recommended to set the following values: While the defaults in variables.tf will successfully deploy a cluster, it is recommended to set the following values:
- cluster_name = the name of the inventory directory created above as $CLUSTER - cluster_name = the name of the inventory directory created above as $CLUSTER
- equinix_metal_project_id = the Equinix Metal Project ID associated with the Equinix Metal API token above - metal_project_id = the Equinix Metal Project ID associated with the Equinix Metal API token above
#### Enable localhost access #### Enable localhost access
@@ -121,13 +119,12 @@ Once the Kubespray playbooks are run, a Kubernetes configuration file will be wr
In the cluster's inventory folder, the following files might be created (either by Terraform In the cluster's inventory folder, the following files might be created (either by Terraform
or manually), to prevent you from pushing them accidentally they are in a or manually), to prevent you from pushing them accidentally they are in a
`.gitignore` file in the `contrib/terraform/equinix` directory : `.gitignore` file in the `terraform/metal` directory :
- `.terraform` - `.terraform`
- `.tfvars` - `.tfvars`
- `.tfstate` - `.tfstate`
- `.tfstate.backup` - `.tfstate.backup`
- `.lock.hcl`
You can still add them manually if you want to. You can still add them manually if you want to.
@@ -138,7 +135,7 @@ plugins. This is accomplished as follows:
```ShellSession ```ShellSession
cd inventory/$CLUSTER cd inventory/$CLUSTER
terraform -chdir=../../contrib/terraform/metal init -var-file=cluster.tfvars terraform init ../../contrib/terraform/metal
``` ```
This should finish fairly quickly telling you Terraform has successfully initialized and loaded necessary modules. This should finish fairly quickly telling you Terraform has successfully initialized and loaded necessary modules.
@@ -149,7 +146,7 @@ You can apply the Terraform configuration to your cluster with the following com
issued from your cluster's inventory directory (`inventory/$CLUSTER`): issued from your cluster's inventory directory (`inventory/$CLUSTER`):
```ShellSession ```ShellSession
terraform -chdir=../../contrib/terraform/equinix apply -var-file=cluster.tfvars terraform apply -var-file=cluster.tfvars ../../contrib/terraform/metal
export ANSIBLE_HOST_KEY_CHECKING=False export ANSIBLE_HOST_KEY_CHECKING=False
ansible-playbook -i hosts ../../cluster.yml ansible-playbook -i hosts ../../cluster.yml
``` ```
@@ -159,7 +156,7 @@ ansible-playbook -i hosts ../../cluster.yml
You can destroy your new cluster with the following command issued from the cluster's inventory directory: You can destroy your new cluster with the following command issued from the cluster's inventory directory:
```ShellSession ```ShellSession
terraform -chdir=../../contrib/terraform/equinix destroy -var-file=cluster.tfvars terraform destroy -var-file=cluster.tfvars ../../contrib/terraform/metal
``` ```
If you've started the Ansible run, it may also be a good idea to do some manual cleanup: If you've started the Ansible run, it may also be a good idea to do some manual cleanup:

View File

@@ -1,57 +1,62 @@
resource "equinix_metal_ssh_key" "k8s" { # Configure the Equinix Metal Provider
provider "metal" {
}
resource "metal_ssh_key" "k8s" {
count = var.public_key_path != "" ? 1 : 0 count = var.public_key_path != "" ? 1 : 0
name = "kubernetes-${var.cluster_name}" name = "kubernetes-${var.cluster_name}"
public_key = chomp(file(var.public_key_path)) public_key = chomp(file(var.public_key_path))
} }
resource "equinix_metal_device" "k8s_master" { resource "metal_device" "k8s_master" {
depends_on = [equinix_metal_ssh_key.k8s] depends_on = [metal_ssh_key.k8s]
count = var.number_of_k8s_masters count = var.number_of_k8s_masters
hostname = "${var.cluster_name}-k8s-master-${count.index + 1}" hostname = "${var.cluster_name}-k8s-master-${count.index + 1}"
plan = var.plan_k8s_masters plan = var.plan_k8s_masters
metro = var.metro facilities = [var.facility]
operating_system = var.operating_system operating_system = var.operating_system
billing_cycle = var.billing_cycle billing_cycle = var.billing_cycle
project_id = var.equinix_metal_project_id project_id = var.metal_project_id
tags = ["cluster-${var.cluster_name}", "k8s_cluster", "kube_control_plane", "etcd", "kube_node"] tags = ["cluster-${var.cluster_name}", "k8s_cluster", "kube_control_plane", "etcd", "kube_node"]
} }
resource "equinix_metal_device" "k8s_master_no_etcd" { resource "metal_device" "k8s_master_no_etcd" {
depends_on = [equinix_metal_ssh_key.k8s] depends_on = [metal_ssh_key.k8s]
count = var.number_of_k8s_masters_no_etcd count = var.number_of_k8s_masters_no_etcd
hostname = "${var.cluster_name}-k8s-master-${count.index + 1}" hostname = "${var.cluster_name}-k8s-master-${count.index + 1}"
plan = var.plan_k8s_masters_no_etcd plan = var.plan_k8s_masters_no_etcd
metro = var.metro facilities = [var.facility]
operating_system = var.operating_system operating_system = var.operating_system
billing_cycle = var.billing_cycle billing_cycle = var.billing_cycle
project_id = var.equinix_metal_project_id project_id = var.metal_project_id
tags = ["cluster-${var.cluster_name}", "k8s_cluster", "kube_control_plane"] tags = ["cluster-${var.cluster_name}", "k8s_cluster", "kube_control_plane"]
} }
resource "equinix_metal_device" "k8s_etcd" { resource "metal_device" "k8s_etcd" {
depends_on = [equinix_metal_ssh_key.k8s] depends_on = [metal_ssh_key.k8s]
count = var.number_of_etcd count = var.number_of_etcd
hostname = "${var.cluster_name}-etcd-${count.index + 1}" hostname = "${var.cluster_name}-etcd-${count.index + 1}"
plan = var.plan_etcd plan = var.plan_etcd
metro = var.metro facilities = [var.facility]
operating_system = var.operating_system operating_system = var.operating_system
billing_cycle = var.billing_cycle billing_cycle = var.billing_cycle
project_id = var.equinix_metal_project_id project_id = var.metal_project_id
tags = ["cluster-${var.cluster_name}", "etcd"] tags = ["cluster-${var.cluster_name}", "etcd"]
} }
resource "equinix_metal_device" "k8s_node" { resource "metal_device" "k8s_node" {
depends_on = [equinix_metal_ssh_key.k8s] depends_on = [metal_ssh_key.k8s]
count = var.number_of_k8s_nodes count = var.number_of_k8s_nodes
hostname = "${var.cluster_name}-k8s-node-${count.index + 1}" hostname = "${var.cluster_name}-k8s-node-${count.index + 1}"
plan = var.plan_k8s_nodes plan = var.plan_k8s_nodes
metro = var.metro facilities = [var.facility]
operating_system = var.operating_system operating_system = var.operating_system
billing_cycle = var.billing_cycle billing_cycle = var.billing_cycle
project_id = var.equinix_metal_project_id project_id = var.metal_project_id
tags = ["cluster-${var.cluster_name}", "k8s_cluster", "kube_node"] tags = ["cluster-${var.cluster_name}", "k8s_cluster", "kube_node"]
} }

View File

@@ -0,0 +1,16 @@
output "k8s_masters" {
value = metal_device.k8s_master.*.access_public_ipv4
}
output "k8s_masters_no_etc" {
value = metal_device.k8s_master_no_etcd.*.access_public_ipv4
}
output "k8s_etcds" {
value = metal_device.k8s_etcd.*.access_public_ipv4
}
output "k8s_nodes" {
value = metal_device.k8s_node.*.access_public_ipv4
}

View File

@@ -1,19 +1,16 @@
# your Kubernetes cluster name here # your Kubernetes cluster name here
cluster_name = "mycluster" cluster_name = "mycluster"
# Your Equinix Metal project ID. See https://metal.equinix.com/developers/docs/accounts/ # Your Equinix Metal project ID. See hhttps://metal.equinix.com/developers/docs/accounts/
equinix_metal_project_id = "Example-Project-Id" metal_project_id = "Example-API-Token"
# The public SSH key to be uploaded into authorized_keys in bare metal Equinix Metal nodes provisioned # The public SSH key to be uploaded into authorized_keys in bare metal Equinix Metal nodes provisioned
# leave this value blank if the public key is already setup in the Equinix Metal project # leave this value blank if the public key is already setup in the Equinix Metal project
# Terraform will complain if the public key is setup in Equinix Metal # Terraform will complain if the public key is setup in Equinix Metal
public_key_path = "~/.ssh/id_rsa.pub" public_key_path = "~/.ssh/id_rsa.pub"
# Equinix interconnected bare metal across our global metros. # cluster location
metro = "da" facility = "ewr1"
# operating_system
operating_system = "ubuntu_22_04"
# standalone etcds # standalone etcds
number_of_etcd = 0 number_of_etcd = 0

View File

@@ -2,12 +2,12 @@ variable "cluster_name" {
default = "kubespray" default = "kubespray"
} }
variable "equinix_metal_project_id" { variable "metal_project_id" {
description = "Your Equinix Metal project ID. See https://metal.equinix.com/developers/docs/accounts/" description = "Your Equinix Metal project ID. See https://metal.equinix.com/developers/docs/accounts/"
} }
variable "operating_system" { variable "operating_system" {
default = "ubuntu_22_04" default = "ubuntu_20_04"
} }
variable "public_key_path" { variable "public_key_path" {
@@ -19,8 +19,8 @@ variable "billing_cycle" {
default = "hourly" default = "hourly"
} }
variable "metro" { variable "facility" {
default = "da" default = "dfw2"
} }
variable "plan_k8s_masters" { variable "plan_k8s_masters" {
@@ -54,3 +54,4 @@ variable "number_of_etcd" {
variable "number_of_k8s_nodes" { variable "number_of_k8s_nodes" {
default = 1 default = 1
} }

View File

@@ -0,0 +1,9 @@
terraform {
required_version = ">= 0.12"
required_providers {
metal = {
source = "equinix/metal"
}
}
}

View File

@@ -4,5 +4,6 @@ terraform {
source = "terraform-provider-openstack/openstack" source = "terraform-provider-openstack/openstack"
} }
} }
required_version = ">= 1.3.0" experiments = [module_variable_optional_attrs]
required_version = ">= 0.14.0"
} }

View File

@@ -44,3 +44,4 @@ resource "openstack_networking_floatingip_v2" "k8s_nodes" {
pool = var.floatingip_pool pool = var.floatingip_pool
depends_on = [null_resource.dummy_dependency] depends_on = [null_resource.dummy_dependency]
} }

View File

@@ -86,4 +86,4 @@ floatingip_pool = "<pool>"
bastion_allowed_remote_ips = ["0.0.0.0/0"] bastion_allowed_remote_ips = ["0.0.0.0/0"]
# Force port security to be null. Some cloud providers do not allow to set port security. # Force port security to be null. Some cloud providers do not allow to set port security.
# force_null_port_security = false # force_null_port_security = false

View File

@@ -5,5 +5,6 @@ terraform {
version = "~> 1.17" version = "~> 1.17"
} }
} }
required_version = ">= 1.3.0" experiments = [module_variable_optional_attrs]
required_version = ">= 0.14.0"
} }

View File

@@ -194,19 +194,9 @@ def parse_bool(string_form):
else: else:
raise ValueError('could not convert %r to a bool' % string_form) raise ValueError('could not convert %r to a bool' % string_form)
def sanitize_groups(groups):
_groups = []
chars_to_replace = ['+', '-', '=', '.', '/', ' ']
for i in groups:
_i = i
for char in chars_to_replace:
_i = _i.replace(char, '_')
_groups.append(_i)
groups.clear()
groups.extend(_groups)
@parses('equinix_metal_device') @parses('metal_device')
def equinix_metal_device(resource, tfvars=None): def metal_device(resource, tfvars=None):
raw_attrs = resource['primary']['attributes'] raw_attrs = resource['primary']['attributes']
name = raw_attrs['hostname'] name = raw_attrs['hostname']
groups = [] groups = []
@@ -230,7 +220,7 @@ def equinix_metal_device(resource, tfvars=None):
'ipv6_address': raw_attrs['network.1.address'], 'ipv6_address': raw_attrs['network.1.address'],
'public_ipv6': raw_attrs['network.1.address'], 'public_ipv6': raw_attrs['network.1.address'],
'private_ipv4': raw_attrs['network.2.address'], 'private_ipv4': raw_attrs['network.2.address'],
'provider': 'equinix', 'provider': 'metal',
} }
if raw_attrs['operating_system'] == 'flatcar_stable': if raw_attrs['operating_system'] == 'flatcar_stable':
@@ -238,14 +228,13 @@ def equinix_metal_device(resource, tfvars=None):
attrs.update({'ansible_ssh_user': 'core'}) attrs.update({'ansible_ssh_user': 'core'})
# add groups based on attrs # add groups based on attrs
groups.append('equinix_metal_operating_system_%s' % attrs['operating_system']) groups.append('metal_operating_system=' + attrs['operating_system'])
groups.append('equinix_metal_locked_%s' % attrs['locked']) groups.append('metal_locked=%s' % attrs['locked'])
groups.append('equinix_metal_state_%s' % attrs['state']) groups.append('metal_state=' + attrs['state'])
groups.append('equinix_metal_plan_%s' % attrs['plan']) groups.append('metal_plan=' + attrs['plan'])
# groups specific to kubespray # groups specific to kubespray
groups = groups + attrs['tags'] groups = groups + attrs['tags']
sanitize_groups(groups)
return name, attrs, groups return name, attrs, groups
@@ -284,6 +273,8 @@ def openstack_host(resource, module_name):
'network': parse_attr_list(raw_attrs, 'network'), 'network': parse_attr_list(raw_attrs, 'network'),
'region': raw_attrs.get('region', ''), 'region': raw_attrs.get('region', ''),
'security_groups': parse_list(raw_attrs, 'security_groups'), 'security_groups': parse_list(raw_attrs, 'security_groups'),
# ansible
'ansible_ssh_port': 22,
# workaround for an OpenStack bug where hosts have a different domain # workaround for an OpenStack bug where hosts have a different domain
# after they're restarted # after they're restarted
'host_domain': 'novalocal', 'host_domain': 'novalocal',
@@ -298,9 +289,6 @@ def openstack_host(resource, module_name):
if 'floating_ip' in raw_attrs: if 'floating_ip' in raw_attrs:
attrs['private_ipv4'] = raw_attrs['network.0.fixed_ip_v4'] attrs['private_ipv4'] = raw_attrs['network.0.fixed_ip_v4']
if 'metadata.use_access_ip' in raw_attrs and raw_attrs['metadata.use_access_ip'] == "0":
attrs.pop('access_ip')
try: try:
if 'metadata.prefer_ipv6' in raw_attrs and raw_attrs['metadata.prefer_ipv6'] == "1": if 'metadata.prefer_ipv6' in raw_attrs and raw_attrs['metadata.prefer_ipv6'] == "1":
attrs.update({ attrs.update({
@@ -319,9 +307,7 @@ def openstack_host(resource, module_name):
# attrs specific to Ansible # attrs specific to Ansible
if 'metadata.ssh_user' in raw_attrs: if 'metadata.ssh_user' in raw_attrs:
attrs['ansible_user'] = raw_attrs['metadata.ssh_user'] attrs['ansible_ssh_user'] = raw_attrs['metadata.ssh_user']
if 'metadata.ssh_port' in raw_attrs:
attrs['ansible_port'] = raw_attrs['metadata.ssh_port']
if 'volume.#' in list(raw_attrs.keys()) and int(raw_attrs['volume.#']) > 0: if 'volume.#' in list(raw_attrs.keys()) and int(raw_attrs['volume.#']) > 0:
device_index = 1 device_index = 1
@@ -348,8 +334,6 @@ def openstack_host(resource, module_name):
for group in attrs['metadata'].get('kubespray_groups', "").split(","): for group in attrs['metadata'].get('kubespray_groups', "").split(","):
groups.append(group) groups.append(group)
sanitize_groups(groups)
return name, attrs, groups return name, attrs, groups

View File

@@ -136,8 +136,4 @@ terraform destroy --var-file cluster-settings.tfvars \
* `loadbalancer_plan`: Plan to use for load balancer *(development|production-small)* * `loadbalancer_plan`: Plan to use for load balancer *(development|production-small)*
* `loadbalancers`: Ports to load balance and which machines to forward to. Key of this object will be used as the name of the load balancer frontends/backends * `loadbalancers`: Ports to load balance and which machines to forward to. Key of this object will be used as the name of the load balancer frontends/backends
* `port`: Port to load balance. * `port`: Port to load balance.
* `target_port`: Port to the backend servers.
* `backend_servers`: List of servers that traffic to the port should be forwarded to. * `backend_servers`: List of servers that traffic to the port should be forwarded to.
* `server_groups`: Group servers together
* `servers`: The servers that should be included in the group.
* `anti_affinity`: If anti-affinity should be enabled, try to spread the VMs out on separate nodes.

View File

@@ -121,7 +121,6 @@ loadbalancer_plan = "development"
loadbalancers = { loadbalancers = {
# "http" : { # "http" : {
# "port" : 80, # "port" : 80,
# "target_port" : 80,
# "backend_servers" : [ # "backend_servers" : [
# "worker-0", # "worker-0",
# "worker-1", # "worker-1",
@@ -129,20 +128,3 @@ loadbalancers = {
# ] # ]
# } # }
} }
server_groups = {
# "control-plane" = {
# servers = [
# "master-0"
# ]
# anti_affinity = true
# },
# "workers" = {
# servers = [
# "worker-0",
# "worker-1",
# "worker-2"
# ]
# anti_affinity = true
# }
}

View File

@@ -34,8 +34,6 @@ module "kubernetes" {
loadbalancer_enabled = var.loadbalancer_enabled loadbalancer_enabled = var.loadbalancer_enabled
loadbalancer_plan = var.loadbalancer_plan loadbalancer_plan = var.loadbalancer_plan
loadbalancers = var.loadbalancers loadbalancers = var.loadbalancers
server_groups = var.server_groups
} }
# #

View File

@@ -13,7 +13,7 @@ locals {
lb_backend_servers = flatten([ lb_backend_servers = flatten([
for lb_name, loadbalancer in var.loadbalancers : [ for lb_name, loadbalancer in var.loadbalancers : [
for backend_server in loadbalancer.backend_servers : { for backend_server in loadbalancer.backend_servers : {
port = loadbalancer.target_port port = loadbalancer.port
lb_name = lb_name lb_name = lb_name
server_name = backend_server server_name = backend_server
} }
@@ -80,7 +80,7 @@ resource "upcloud_server" "master" {
lifecycle { lifecycle {
ignore_changes = [storage_devices] ignore_changes = [storage_devices]
} }
firewall = var.firewall_enabled firewall = var.firewall_enabled
dynamic "storage_devices" { dynamic "storage_devices" {
@@ -525,7 +525,7 @@ resource "upcloud_loadbalancer_backend" "lb_backend" {
resource "upcloud_loadbalancer_frontend" "lb_frontend" { resource "upcloud_loadbalancer_frontend" "lb_frontend" {
for_each = var.loadbalancer_enabled ? var.loadbalancers : {} for_each = var.loadbalancer_enabled ? var.loadbalancers : {}
loadbalancer = upcloud_loadbalancer.lb[0].id loadbalancer = upcloud_loadbalancer.lb[0].id
name = "lb-frontend-${each.key}" name = "lb-frontend-${each.key}"
mode = "tcp" mode = "tcp"
@@ -535,7 +535,7 @@ resource "upcloud_loadbalancer_frontend" "lb_frontend" {
resource "upcloud_loadbalancer_static_backend_member" "lb_backend_member" { resource "upcloud_loadbalancer_static_backend_member" "lb_backend_member" {
for_each = { for_each = {
for be_server in local.lb_backend_servers: for be_server in local.lb_backend_servers:
"${be_server.server_name}-lb-backend-${be_server.lb_name}" => be_server "${be_server.server_name}-lb-backend-${be_server.lb_name}" => be_server
if var.loadbalancer_enabled if var.loadbalancer_enabled
} }
@@ -548,11 +548,3 @@ resource "upcloud_loadbalancer_static_backend_member" "lb_backend_member" {
max_sessions = var.loadbalancer_plan == "production-small" ? 50000 : 1000 max_sessions = var.loadbalancer_plan == "production-small" ? 50000 : 1000
enabled = true enabled = true
} }
resource "upcloud_server_group" "server_groups" {
for_each = var.server_groups
title = each.key
anti_affinity = each.value.anti_affinity
labels = {}
members = [for server in each.value.servers : merge(upcloud_server.master, upcloud_server.worker)[server].id]
}

View File

@@ -90,16 +90,6 @@ variable "loadbalancers" {
type = map(object({ type = map(object({
port = number port = number
target_port = number
backend_servers = list(string) backend_servers = list(string)
})) }))
} }
variable "server_groups" {
description = "Server groups"
type = map(object({
anti_affinity = bool
servers = list(string)
}))
}

View File

@@ -3,7 +3,7 @@ terraform {
required_providers { required_providers {
upcloud = { upcloud = {
source = "UpCloudLtd/upcloud" source = "UpCloudLtd/upcloud"
version = "~>2.7.1" version = "~>2.5.0"
} }
} }
required_version = ">= 0.13" required_version = ">= 0.13"

View File

@@ -122,7 +122,6 @@ loadbalancer_plan = "development"
loadbalancers = { loadbalancers = {
# "http" : { # "http" : {
# "port" : 80, # "port" : 80,
# "target_port" : 80,
# "backend_servers" : [ # "backend_servers" : [
# "worker-0", # "worker-0",
# "worker-1", # "worker-1",
@@ -130,20 +129,3 @@ loadbalancers = {
# ] # ]
# } # }
} }
server_groups = {
# "control-plane" = {
# servers = [
# "master-0"
# ]
# anti_affinity = true
# },
# "workers" = {
# servers = [
# "worker-0",
# "worker-1",
# "worker-2"
# ]
# anti_affinity = true
# }
}

View File

@@ -126,19 +126,7 @@ variable "loadbalancers" {
type = map(object({ type = map(object({
port = number port = number
target_port = number
backend_servers = list(string) backend_servers = list(string)
})) }))
default = {} default = {}
} }
variable "server_groups" {
description = "Server groups"
type = map(object({
anti_affinity = bool
servers = list(string)
}))
default = {}
}

View File

@@ -3,7 +3,7 @@ terraform {
required_providers { required_providers {
upcloud = { upcloud = {
source = "UpCloudLtd/upcloud" source = "UpCloudLtd/upcloud"
version = "~>2.7.1" version = "~>2.5.0"
} }
} }
required_version = ">= 0.13" required_version = ">= 0.13"

View File

@@ -38,7 +38,7 @@
* [Kylin Linux Advanced Server V10](docs/kylinlinux.md) * [Kylin Linux Advanced Server V10](docs/kylinlinux.md)
* [Amazon Linux 2](docs/amazonlinux.md) * [Amazon Linux 2](docs/amazonlinux.md)
* [UOS Linux](docs/uoslinux.md) * [UOS Linux](docs/uoslinux.md)
* [openEuler notes](docs/openeuler.md) * [openEuler notes](docs/openeuler.md))
* CRI * CRI
* [Containerd](docs/containerd.md) * [Containerd](docs/containerd.md)
* [Docker](docs/docker.md) * [Docker](docs/docker.md)

View File

@@ -15,6 +15,9 @@ virtualenv --python=$(which python3) $VENVDIR
source $VENVDIR/bin/activate source $VENVDIR/bin/activate
cd $KUBESPRAYDIR cd $KUBESPRAYDIR
pip install -U -r requirements-$ANSIBLE_VERSION.txt pip install -U -r requirements-$ANSIBLE_VERSION.txt
test -f requirements-$ANSIBLE_VERSION.yml && \
ansible-galaxy role install -r requirements-$ANSIBLE_VERSION.yml && \
ansible-galaxy collection -r requirements-$ANSIBLE_VERSION.yml
``` ```
### Ansible Python Compatibility ### Ansible Python Compatibility
@@ -22,7 +25,7 @@ pip install -U -r requirements-$ANSIBLE_VERSION.txt
Based on the table below and the available python version for your ansible host you should choose the appropriate ansible version to use with kubespray. Based on the table below and the available python version for your ansible host you should choose the appropriate ansible version to use with kubespray.
| Ansible Version | Python Version | | Ansible Version | Python Version |
|-----------------|----------------| | --------------- | -------------- |
| 2.11 | 2.7,3.5-3.9 | | 2.11 | 2.7,3.5-3.9 |
| 2.12 | 3.8-3.10 | | 2.12 | 3.8-3.10 |
@@ -101,134 +104,135 @@ the `-e` runtime flags (most simple way) or other layers described in the docs.
Kubespray uses only a few layers to override things (or expect them to Kubespray uses only a few layers to override things (or expect them to
be overridden for roles): be overridden for roles):
| Layer | Comment | Layer | Comment
|----------------------------------------|------------------------------------------------------------------------------| ------|--------
| **role defaults** | provides best UX to override things for Kubespray deployments | **role defaults** | provides best UX to override things for Kubespray deployments
| inventory vars | Unused | inventory vars | Unused
| **inventory group_vars** | Expects users to use ``all.yml``,``k8s_cluster.yml`` etc. to override things | **inventory group_vars** | Expects users to use ``all.yml``,``k8s_cluster.yml`` etc. to override things
| inventory host_vars | Unused | inventory host_vars | Unused
| playbook group_vars | Unused | playbook group_vars | Unused
| playbook host_vars | Unused | playbook host_vars | Unused
| **host facts** | Kubespray overrides for internal roles' logic, like state flags | **host facts** | Kubespray overrides for internal roles' logic, like state flags
| play vars | Unused | play vars | Unused
| play vars_prompt | Unused | play vars_prompt | Unused
| play vars_files | Unused | play vars_files | Unused
| registered vars | Unused | registered vars | Unused
| set_facts | Kubespray overrides those, for some places | set_facts | Kubespray overrides those, for some places
| **role and include vars** | Provides bad UX to override things! Use extra vars to enforce | **role and include vars** | Provides bad UX to override things! Use extra vars to enforce
| block vars (only for tasks in block) | Kubespray overrides for internal roles' logic | block vars (only for tasks in block) | Kubespray overrides for internal roles' logic
| task vars (only for the task) | Unused for roles, but only for helper scripts | task vars (only for the task) | Unused for roles, but only for helper scripts
| **extra vars** (always win precedence) | override with ``ansible-playbook -e @foo.yml`` | **extra vars** (always win precedence) | override with ``ansible-playbook -e @foo.yml``
## Ansible tags ## Ansible tags
The following tags are defined in playbooks: The following tags are defined in playbooks:
| Tag name | Used for | | Tag name | Used for
|--------------------------------|-------------------------------------------------------| |--------------------------------|---------
| annotate | Create kube-router annotation | | annotate | Create kube-router annotation
| apps | K8s apps definitions | | apps | K8s apps definitions
| asserts | Check tasks for download role | | asserts | Check tasks for download role
| aws-ebs-csi-driver | Configuring csi driver: aws-ebs | | aws-ebs-csi-driver | Configuring csi driver: aws-ebs
| azure-csi-driver | Configuring csi driver: azure | | azure-csi-driver | Configuring csi driver: azure
| bastion | Setup ssh config for bastion | | bastion | Setup ssh config for bastion
| bootstrap-os | Anything related to host OS configuration | | bootstrap-os | Anything related to host OS configuration
| calico | Network plugin Calico | | calico | Network plugin Calico
| calico_rr | Configuring Calico route reflector | | calico_rr | Configuring Calico route reflector
| cephfs-provisioner | Configuring CephFS | | canal | Network plugin Canal
| cert-manager | Configuring certificate manager for K8s | | cephfs-provisioner | Configuring CephFS
| cilium | Network plugin Cilium | | cert-manager | Configuring certificate manager for K8s
| cinder-csi-driver | Configuring csi driver: cinder | | cilium | Network plugin Cilium
| client | Kubernetes clients role | | cinder-csi-driver | Configuring csi driver: cinder
| cloud-provider | Cloud-provider related tasks | | client | Kubernetes clients role
| cluster-roles | Configuring cluster wide application (psp ...) | | cloud-provider | Cloud-provider related tasks
| cni | CNI plugins for Network Plugins | | cluster-roles | Configuring cluster wide application (psp ...)
| containerd | Configuring containerd engine runtime for hosts | | cni | CNI plugins for Network Plugins
| container_engine_accelerator | Enable nvidia accelerator for runtimes | | containerd | Configuring containerd engine runtime for hosts
| container-engine | Configuring container engines | | container_engine_accelerator | Enable nvidia accelerator for runtimes
| container-runtimes | Configuring container runtimes | | container-engine | Configuring container engines
| coredns | Configuring coredns deployment | | container-runtimes | Configuring container runtimes
| crio | Configuring crio container engine for hosts | | coredns | Configuring coredns deployment
| crun | Configuring crun runtime | | crio | Configuring crio container engine for hosts
| csi-driver | Configuring csi driver | | crun | Configuring crun runtime
| dashboard | Installing and configuring the Kubernetes Dashboard | | csi-driver | Configuring csi driver
| dns | Remove dns entries when resetting | | dashboard | Installing and configuring the Kubernetes Dashboard
| docker | Configuring docker engine runtime for hosts | | dns | Remove dns entries when resetting
| download | Fetching container images to a delegate host | | docker | Configuring docker engine runtime for hosts
| etcd | Configuring etcd cluster | | download | Fetching container images to a delegate host
| etcd-secrets | Configuring etcd certs/keys | | etcd | Configuring etcd cluster
| etchosts | Configuring /etc/hosts entries for hosts | | etcd-secrets | Configuring etcd certs/keys
| external-cloud-controller | Configure cloud controllers | | etchosts | Configuring /etc/hosts entries for hosts
| external-openstack | Cloud controller : openstack | | external-cloud-controller | Configure cloud controllers
| external-provisioner | Configure external provisioners | | external-openstack | Cloud controller : openstack
| external-vsphere | Cloud controller : vsphere | | external-provisioner | Configure external provisioners
| facts | Gathering facts and misc check results | | external-vsphere | Cloud controller : vsphere
| files | Remove files when resetting | | facts | Gathering facts and misc check results
| flannel | Network plugin flannel | | files | Remove files when resetting
| gce | Cloud-provider GCP | | flannel | Network plugin flannel
| gcp-pd-csi-driver | Configuring csi driver: gcp-pd | | gce | Cloud-provider GCP
| gvisor | Configuring gvisor runtime | | gcp-pd-csi-driver | Configuring csi driver: gcp-pd
| helm | Installing and configuring Helm | | gvisor | Configuring gvisor runtime
| ingress-controller | Configure ingress controllers | | helm | Installing and configuring Helm
| ingress_alb | AWS ALB Ingress Controller | | ingress-controller | Configure ingress controllers
| init | Windows kubernetes init nodes | | ingress_alb | AWS ALB Ingress Controller
| iptables | Flush and clear iptable when resetting | | init | Windows kubernetes init nodes
| k8s-pre-upgrade | Upgrading K8s cluster | | iptables | Flush and clear iptable when resetting
| k8s-secrets | Configuring K8s certs/keys | | k8s-pre-upgrade | Upgrading K8s cluster
| k8s-gen-tokens | Configuring K8s tokens | | k8s-secrets | Configuring K8s certs/keys
| kata-containers | Configuring kata-containers runtime | | k8s-gen-tokens | Configuring K8s tokens
| krew | Install and manage krew | | kata-containers | Configuring kata-containers runtime
| kubeadm | Roles linked to kubeadm tasks | | krew | Install and manage krew
| kube-apiserver | Configuring static pod kube-apiserver | | kubeadm | Roles linked to kubeadm tasks
| kube-controller-manager | Configuring static pod kube-controller-manager | | kube-apiserver | Configuring static pod kube-apiserver
| kube-vip | Installing and configuring kube-vip | | kube-controller-manager | Configuring static pod kube-controller-manager
| kubectl | Installing kubectl and bash completion | | kube-vip | Installing and configuring kube-vip
| kubelet | Configuring kubelet service | | kubectl | Installing kubectl and bash completion
| kube-ovn | Network plugin kube-ovn | | kubelet | Configuring kubelet service
| kube-router | Network plugin kube-router | | kube-ovn | Network plugin kube-ovn
| kube-proxy | Configuring static pod kube-proxy | | kube-router | Network plugin kube-router
| localhost | Special steps for the localhost (ansible runner) | | kube-proxy | Configuring static pod kube-proxy
| local-path-provisioner | Configure External provisioner: local-path | | localhost | Special steps for the localhost (ansible runner)
| local-volume-provisioner | Configure External provisioner: local-volume | | local-path-provisioner | Configure External provisioner: local-path
| macvlan | Network plugin macvlan | | local-volume-provisioner | Configure External provisioner: local-volume
| master | Configuring K8s master node role | | macvlan | Network plugin macvlan
| metallb | Installing and configuring metallb | | master | Configuring K8s master node role
| metrics_server | Configuring metrics_server | | metallb | Installing and configuring metallb
| netchecker | Installing netchecker K8s app | | metrics_server | Configuring metrics_server
| network | Configuring networking plugins for K8s | | netchecker | Installing netchecker K8s app
| mounts | Umount kubelet dirs when reseting | | network | Configuring networking plugins for K8s
| multus | Network plugin multus | | mounts | Umount kubelet dirs when reseting
| nginx | Configuring LB for kube-apiserver instances | | multus | Network plugin multus
| node | Configuring K8s minion (compute) node role | | nginx | Configuring LB for kube-apiserver instances
| nodelocaldns | Configuring nodelocaldns daemonset | | node | Configuring K8s minion (compute) node role
| node-label | Tasks linked to labeling of nodes | | nodelocaldns | Configuring nodelocaldns daemonset
| node-webhook | Tasks linked to webhook (grating access to resources) | | node-label | Tasks linked to labeling of nodes
| nvidia_gpu | Enable nvidia accelerator for runtimes | | node-webhook | Tasks linked to webhook (grating access to resources)
| oci | Cloud provider: oci | | nvidia_gpu | Enable nvidia accelerator for runtimes
| persistent_volumes | Configure csi volumes | | oci | Cloud provider: oci
| persistent_volumes_aws_ebs_csi | Configuring csi driver: aws-ebs | | persistent_volumes | Configure csi volumes
| persistent_volumes_cinder_csi | Configuring csi driver: cinder | | persistent_volumes_aws_ebs_csi | Configuring csi driver: aws-ebs
| persistent_volumes_gcp_pd_csi | Configuring csi driver: gcp-pd | | persistent_volumes_cinder_csi | Configuring csi driver: cinder
| persistent_volumes_openstack | Configuring csi driver: openstack | | persistent_volumes_gcp_pd_csi | Configuring csi driver: gcp-pd
| policy-controller | Configuring Calico policy controller | | persistent_volumes_openstack | Configuring csi driver: openstack
| post-remove | Tasks running post-remove operation | | policy-controller | Configuring Calico policy controller
| post-upgrade | Tasks running post-upgrade operation | | post-remove | Tasks running post-remove operation
| pre-remove | Tasks running pre-remove operation | | post-upgrade | Tasks running post-upgrade operation
| pre-upgrade | Tasks running pre-upgrade operation | | pre-remove | Tasks running pre-remove operation
| preinstall | Preliminary configuration steps | | pre-upgrade | Tasks running pre-upgrade operation
| registry | Configuring local docker registry | | preinstall | Preliminary configuration steps
| reset | Tasks running doing the node reset | | registry | Configuring local docker registry
| resolvconf | Configuring /etc/resolv.conf for hosts/apps | | reset | Tasks running doing the node reset
| rbd-provisioner | Configure External provisioner: rdb | | resolvconf | Configuring /etc/resolv.conf for hosts/apps
| services | Remove services (etcd, kubelet etc...) when resetting | | rbd-provisioner | Configure External provisioner: rdb
| snapshot | Enabling csi snapshot | | services | Remove services (etcd, kubelet etc...) when resetting
| snapshot-controller | Configuring csi snapshot controller | | snapshot | Enabling csi snapshot
| upgrade | Upgrading, f.e. container images/binaries | | snapshot-controller | Configuring csi snapshot controller
| upload | Distributing images/binaries across hosts | | upgrade | Upgrading, f.e. container images/binaries
| vsphere-csi-driver | Configuring csi driver: vsphere | | upload | Distributing images/binaries across hosts
| weave | Network plugin Weave | | vsphere-csi-driver | Configuring csi driver: vsphere
| win_nodes | Running windows specific tasks | | weave | Network plugin Weave
| youki | Configuring youki runtime | | win_nodes | Running windows specific tasks
| youki | Configuring youki runtime
Note: Use the ``bash scripts/gen_tags.sh`` command to generate a list of all Note: Use the ``bash scripts/gen_tags.sh`` command to generate a list of all
tags found in the codebase. New tags will be listed with the empty "Used for" tags found in the codebase. New tags will be listed with the empty "Used for"

View File

@@ -1,38 +0,0 @@
# Ansible collection
Kubespray can be installed as an [Ansible collection](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html).
## Requirements
- An inventory file with the appropriate host groups. See the [README](../README.md#usage).
- A `group_vars` directory. These group variables **need** to match the appropriate variable names under `inventory/local/group_vars`. See the [README](../README.md#usage).
## Usage
1. Add Kubespray to your requirements.yml file
```yaml
collections:
- name: https://github.com/kubernetes-sigs/kubespray
type: git
version: v2.21.0
```
2. Install your collection
```ShellSession
ansible-galaxy install -r requirements.yml
```
3. Create a playbook to install your Kubernetes cluster
```yaml
- name: Install Kubernetes
ansible.builtin.import_playbook: kubernetes_sigs.kubespray.cluster
```
4. Update INVENTORY and PLAYBOOK so that they point to your inventory file and the playbook you created above, and then install Kubespray
```ShellSession
ansible-playbook -i INVENTORY --become --become-user=root PLAYBOOK
```

View File

@@ -7,7 +7,7 @@ The following table shows the impact of the CPU architecture on compatible featu
- amd64 + arm64: Cluster with a mix of x86/amd64 and arm64 CPUs - amd64 + arm64: Cluster with a mix of x86/amd64 and arm64 CPUs
| kube_network_plugin | amd64 | arm64 | amd64 + arm64 | | kube_network_plugin | amd64 | arm64 | amd64 + arm64 |
|---------------------|-------|-------|---------------| | ------------------- | ----- | ----- | ------------- |
| Calico | Y | Y | Y | | Calico | Y | Y | Y |
| Weave | Y | Y | Y | | Weave | Y | Y | Y |
| Flannel | Y | N | N | | Flannel | Y | N | N |

View File

@@ -67,15 +67,15 @@ export REGION="us-east-2"
Declare the cloud config variables for the `aws` provider as follows. Setting these variables are optional and depend on your use case. Declare the cloud config variables for the `aws` provider as follows. Setting these variables are optional and depend on your use case.
| Variable | Type | Comment | Variable|Type|Comment
|------------------------------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ---|---|---
| aws_zone | string | Force set the AWS zone. Recommended to leave blank. | aws_zone|string|Force set the AWS zone. Recommended to leave blank.
| aws_vpc | string | The AWS VPC flag enables the possibility to run the master components on a different aws account, on a different cloud provider or on-premise. If the flag is set also the KubernetesClusterTag must be provided | aws_vpc|string|The AWS VPC flag enables the possibility to run the master components on a different aws account, on a different cloud provider or on-premise. If the flag is set also the KubernetesClusterTag must be provided
| aws_subnet_id | string | SubnetID enables using a specific subnet to use for ELB's | aws_subnet_id|string|SubnetID enables using a specific subnet to use for ELB's
| aws_route_table_id | string | RouteTableID enables using a specific RouteTable | aws_route_table_id|string|RouteTableID enables using a specific RouteTable
| aws_role_arn | string | RoleARN is the IAM role to assume when interaction with AWS APIs | aws_role_arn|string|RoleARN is the IAM role to assume when interaction with AWS APIs
| aws_kubernetes_cluster_tag | string | KubernetesClusterTag is the legacy cluster id we'll use to identify our cluster resources | aws_kubernetes_cluster_tag|string|KubernetesClusterTag is the legacy cluster id we'll use to identify our cluster resources
| aws_kubernetes_cluster_id | string | KubernetesClusterID is the cluster id we'll use to identify our cluster resources | aws_kubernetes_cluster_id|string|KubernetesClusterID is the cluster id we'll use to identify our cluster resources
| aws_disable_security_group_ingress | bool | The aws provider creates an inbound rule per load balancer on the node security group. However, this can run into the AWS security group rule limit of 50 if many LoadBalancers are created. This flag disables the automatic ingress creation. It requires that the user has setup a rule that allows inbound traffic on kubelet ports from the local VPC subnet (so load balancers can access it). E.g. 10.82.0.0/16 30000-32000. | aws_disable_security_group_ingress|bool|The aws provider creates an inbound rule per load balancer on the node security group. However, this can run into the AWS security group rule limit of 50 if many LoadBalancers are created. This flag disables the automatic ingress creation. It requires that the user has setup a rule that allows inbound traffic on kubelet ports from the local VPC subnet (so load balancers can access it). E.g. 10.82.0.0/16 30000-32000.
| aws_elb_security_group | string | Only in Kubelet version >= 1.7 : AWS has a hard limit of 500 security groups. For large clusters creating a security group for each ELB can cause the max number of security groups to be reached. If this is set instead of creating a new Security group for each ELB this security group will be used instead. | aws_elb_security_group|string|Only in Kubelet version >= 1.7 : AWS has a hard limit of 500 security groups. For large clusters creating a security group for each ELB can cause the max number of security groups to be reached. If this is set instead of creating a new Security group for each ELB this security group will be used instead.
| aws_disable_strict_zone_check | bool | During the instantiation of an new AWS cloud provider, the detected region is validated against a known set of regions. In a non-standard, AWS like environment (e.g. Eucalyptus), this check may be undesirable. Setting this to true will disable the check and provide a warning that the check was skipped. Please note that this is an experimental feature and work-in-progress for the moment. | aws_disable_strict_zone_check|bool|During the instantiation of an new AWS cloud provider, the detected region is validated against a known set of regions. In a non-standard, AWS like environment (e.g. Eucalyptus), this check may be undesirable. Setting this to true will disable the check and provide a warning that the check was skipped. Please note that this is an experimental feature and work-in-progress for the moment.

View File

@@ -14,7 +14,7 @@ If you want to deploy the Azure Disk storage class to provision volumes dynamica
Before creating the instances you must first set the `azure_csi_` variables in the `group_vars/all.yml` file. Before creating the instances you must first set the `azure_csi_` variables in the `group_vars/all.yml` file.
All values can be retrieved using the azure cli tool which can be downloaded here: <https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest> All of the values can be retrieved using the azure cli tool which can be downloaded here: <https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest>
After installation you have to run `az login` to get access to your account. After installation you have to run `az login` to get access to your account.
@@ -34,7 +34,7 @@ The name of the resource group your instances are in, a list of your resource gr
Or you can do `az vm list | grep resourceGroup` and get the resource group corresponding to the VMs of your cluster. Or you can do `az vm list | grep resourceGroup` and get the resource group corresponding to the VMs of your cluster.
The resource group name is not case-sensitive. The resource group name is not case sensitive.
### azure\_csi\_vnet\_name ### azure\_csi\_vnet\_name

View File

@@ -10,7 +10,7 @@ Not all features are supported yet though, for a list of the current status have
Before creating the instances you must first set the `azure_` variables in the `group_vars/all/all.yml` file. Before creating the instances you must first set the `azure_` variables in the `group_vars/all/all.yml` file.
All values can be retrieved using the Azure CLI tool which can be downloaded here: <https://docs.microsoft.com/en-gb/cli/azure/install-azure-cli> All of the values can be retrieved using the Azure CLI tool which can be downloaded here: <https://docs.microsoft.com/en-gb/cli/azure/install-azure-cli>
After installation you have to run `az login` to get access to your account. After installation you have to run `az login` to get access to your account.
### azure_cloud ### azure_cloud

View File

@@ -187,7 +187,7 @@ The inventory above will deploy the following topology assuming that calico's
### Optional : Define default endpoint to host action ### Optional : Define default endpoint to host action
By default Calico blocks traffic from endpoints to the host itself by using an iptables DROP action. When using it in kubernetes the action has to be changed to RETURN (default in kubespray) or ACCEPT (see <https://docs.tigera.io/calico/latest/network-policy/hosts/protect-hosts#control-default-behavior-of-workload-endpoint-to-host-traffic> ) Otherwise all network packets from pods (with hostNetwork=False) to services endpoints (with hostNetwork=True) within the same node are dropped. By default Calico blocks traffic from endpoints to the host itself by using an iptables DROP action. When using it in kubernetes the action has to be changed to RETURN (default in kubespray) or ACCEPT (see <https://github.com/projectcalico/felix/issues/660> and <https://github.com/projectcalico/calicoctl/issues/1389).> Otherwise all network packets from pods (with hostNetwork=False) to services endpoints (with hostNetwork=True) within the same node are dropped.
To re-define default action please set the following variable in your inventory: To re-define default action please set the following variable in your inventory:
@@ -376,7 +376,12 @@ Calico node, typha and kube-controllers need to be able to talk to the kubernete
Kubespray sets up the `kubernetes-services-endpoint` configmap based on the contents of the `loadbalancer_apiserver` inventory variable documented in [HA Mode](/docs/ha-mode.md). Kubespray sets up the `kubernetes-services-endpoint` configmap based on the contents of the `loadbalancer_apiserver` inventory variable documented in [HA Mode](/docs/ha-mode.md).
If no external loadbalancer is used, Calico eBPF can also use the localhost loadbalancer option. We are able to do so only if you use the same port for the localhost apiserver loadbalancer and the kube-apiserver. In this case Calico Automatic Host Endpoints need to be enabled to allow services like `coredns` and `metrics-server` to communicate with the kubernetes host endpoint. See [this blog post](https://www.projectcalico.org/securing-kubernetes-nodes-with-calico-automatic-host-endpoints/) on enabling automatic host endpoints. If no external loadbalancer is used, Calico eBPF can also use the localhost loadbalancer option. In this case Calico Automatic Host Endpoints need to be enabled to allow services like `coredns` and `metrics-server` to communicate with the kubernetes host endpoint. See [this blog post](https://www.projectcalico.org/securing-kubernetes-nodes-with-calico-automatic-host-endpoints/) on enabling automatic host endpoints.
```yaml
loadbalancer_apiserver_localhost: true
use_localhost_as_kubeapi_loadbalancer: true
```
### Tunneled versus Direct Server Return ### Tunneled versus Direct Server Return

View File

@@ -114,7 +114,7 @@ sudo apt-get install -y golang-cfssl
#### Create Root Certificate Authority (CA) Configuration File #### Create Root Certificate Authority (CA) Configuration File
The default TLS certificate expiry time period is `8760h` which is 1 years from the date the certificate is created. The default TLS certificate expiry time period is `8760h` which is 5 years from the date the certificate is created.
```shell ```shell
$ cat > ca-config.json <<EOF $ cat > ca-config.json <<EOF

View File

@@ -2,19 +2,18 @@
## Pipeline ## Pipeline
1. build: build a docker image to be used in the pipeline 1. unit-tests: fast jobs for fast feedback (linting, etc...)
2. unit-tests: fast jobs for fast feedback (linting, etc...) 2. deploy-part1: small number of jobs to test if the PR works with default settings
3. deploy-part1: small number of jobs to test if the PR works with default settings 3. deploy-part2: slow jobs testing different platforms, OS, settings, CNI, etc...
4. deploy-part2: slow jobs testing different platforms, OS, settings, CNI, etc... 4. deploy-part3: very slow jobs (upgrades, etc...)
5. deploy-part3: very slow jobs (upgrades, etc...)
## Runners ## Runners
Kubespray has 3 types of GitLab runners: Kubespray has 3 types of GitLab runners:
- packet runners: used for E2E jobs (usually long), running on Equinix Metal (ex-packet), on kubevirt managed VMs - packet runners: used for E2E jobs (usually long)
- light runners: used for short lived jobs, running on Equinix Metal (ex-packet), as managed pods - light runners: used for short lived jobs
- auto scaling runners (managed via docker-machine on Equinix Metal): used for on-demand resources, see [GitLab docs](https://docs.gitlab.com/runner/configuration/autoscale.html) for more info - auto scaling runners: used for on-demand resources, see [GitLab docs](https://docs.gitlab.com/runner/configuration/autoscale.html) for more info
## Vagrant ## Vagrant
@@ -26,181 +25,3 @@ In CI we have a set of overrides we use to ensure greater success of our CI jobs
- [Docker mirrors](/tests/common/_docker_hub_registry_mirror.yml) - [Docker mirrors](/tests/common/_docker_hub_registry_mirror.yml)
- [Test settings](/tests/common/_kubespray_test_settings.yml) - [Test settings](/tests/common/_kubespray_test_settings.yml)
## CI Environment
The CI packet and light runners are deployed on a kubernetes cluster on Equinix Metal. The cluster is deployed with kubespray itself and maintained by the kubespray maintainers.
The following files are used for that inventory:
### cluster.tfvars
```ini
# your Kubernetes cluster name here
cluster_name = "ci"
# Your Equinix Metal project ID. See https://metal.equinix.com/developers/docs/accounts/
equinix_metal_project_id = "_redacted_"
# The public SSH key to be uploaded into authorized_keys in bare metal Equinix Metal nodes provisioned
# leave this value blank if the public key is already setup in the Equinix Metal project
# Terraform will complain if the public key is setup in Equinix Metal
public_key_path = "~/.ssh/id_rsa.pub"
# cluster location
metro = "da"
# standalone etcds
number_of_etcd = 0
plan_etcd = "t1.small.x86"
# masters
number_of_k8s_masters = 1
number_of_k8s_masters_no_etcd = 0
plan_k8s_masters = "c3.small.x86"
plan_k8s_masters_no_etcd = "t1.small.x86"
# nodes
number_of_k8s_nodes = 1
plan_k8s_nodes = "c3.medium.x86"
```
### group_vars/all/mirrors.yml
```yaml
---
docker_registry_mirrors:
- "https://mirror.gcr.io"
containerd_grpc_max_recv_message_size: 16777216
containerd_grpc_max_send_message_size: 16777216
containerd_registries:
"docker.io":
- "https://mirror.gcr.io"
- "https://registry-1.docker.io"
containerd_max_container_log_line_size: -1
crio_registries_mirrors:
- prefix: docker.io
insecure: false
blocked: false
location: registry-1.docker.io
mirrors:
- location: mirror.gcr.io
insecure: false
netcheck_agent_image_repo: "{{ quay_image_repo }}/kubespray/k8s-netchecker-agent"
netcheck_server_image_repo: "{{ quay_image_repo }}/kubespray/k8s-netchecker-server"
nginx_image_repo: "{{ quay_image_repo }}/kubespray/nginx"
```
### group_vars/all/settings.yml
```yaml
---
# Networking setting
kube_service_addresses: 172.30.0.0/18
kube_pods_subnet: 172.30.64.0/18
kube_network_plugin: calico
# avoid overlap with CI jobs deploying nodelocaldns
nodelocaldns_ip: 169.254.255.100
# ipip: False
calico_ipip_mode: "Never"
calico_vxlan_mode: "Never"
calico_network_backend: "bird"
calico_wireguard_enabled: True
# Cluster settings
upgrade_cluster_setup: True
force_certificate_regeneration: True
# Etcd settings
etcd_deployment_type: "host"
# Kubernetes settings
kube_controller_terminated_pod_gc_threshold: 100
kubelet_enforce_node_allocatable: pods
kubelet_preferred_address_types: 'InternalIP,ExternalIP,Hostname'
kubelet_custom_flags:
- "--serialize-image-pulls=true"
- "--eviction-hard=memory.available<1Gi"
- "--eviction-soft-grace-period=memory.available=30s"
- "--eviction-soft=memory.available<2Gi"
- "--system-reserved cpu=100m,memory=4Gi"
- "--eviction-minimum-reclaim=memory.available=2Gi"
# DNS settings
resolvconf_mode: none
dns_min_replicas: 1
upstream_dns_servers:
- 1.1.1.1
- 1.0.0.1
# Extensions
ingress_nginx_enabled: True
helm_enabled: True
cert_manager_enabled: True
metrics_server_enabled: True
# Enable ZSWAP
kubelet_fail_swap_on: False
kube_feature_gates:
- "NodeSwap=True"
```
## Aditional files
This section documents additional files used to complete a deployment of the kubespray CI, these files sit on the control-plane node and assume a working kubernetes cluster.
### /root/nscleanup.sh
```bash
#!/bin/bash
kubectl=/usr/local/bin/kubectl
$kubectl get ns | grep -P "(\d.+-\d.+)" | awk 'match($3,/[0-9]+d/) {print $1}' | xargs -r $kubectl delete ns
$kubectl get ns | grep -P "(\d.+-\d.+)" | awk 'match($3,/[3-9]+h/) {print $1}' | xargs -r $kubectl delete ns
$kubectl get ns | grep Terminating | awk '{print $1}' | xargs -i $kubectl delete vmi/instance-1 vmi/instance-0 vmi/instance-2 -n {} --force --grace-period=0 &
```
### /root/path-calico.sh
```bash
#!/bin/bash
calicoctl patch felixconfig default -p '{"spec":{"allowIPIPPacketsFromWorkloads":true, "allowVXLANPacketsFromWorkloads": true}}'
```
### /root/kubevirt/kubevirt.sh
```bash
#!/bin/bash
export VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases | grep tag_name | grep -v -- '-rc' | sort -r | head -1 | awk -F': ' '{print $2}' | sed 's/,//' | xargs)
echo $VERSION
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-cr.yaml
```
### /root/kubevirt/virtctl.sh
```bash
#!/bin/bash
VERSION=$(kubectl get kubevirt.kubevirt.io/kubevirt -n kubevirt -o=jsonpath="{.status.observedKubeVirtVersion}")
ARCH=$(uname -s | tr A-Z a-z)-$(uname -m | sed 's/x86_64/amd64/') || windows-amd64.exe
echo ${ARCH}
curl -L -o virtctl https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/virtctl-${VERSION}-${ARCH}
chmod +x virtctl
sudo install virtctl /usr/local/bin
```

View File

@@ -4,34 +4,36 @@ To generate this Matrix run `./tests/scripts/md-table/main.py`
## containerd ## containerd
| OS / CNI | calico | cilium | custom_cni | flannel | kube-ovn | kube-router | macvlan | weave | | OS / CNI | calico | canal | cilium | flannel | kube-ovn | kube-router | macvlan | weave |
|---| --- | --- | --- | --- | --- | --- | --- | --- | |---| --- | --- | --- | --- | --- | --- | --- | --- |
almalinux8 | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | almalinux8 | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: |
amazon | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | amazon | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
centos7 | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | centos7 | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: |
debian10 | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | debian10 | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: |
debian11 | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | debian11 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
fedora35 | :white_check_mark: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | debian9 | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: |
fedora36 | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | fedora37 | :white_check_mark: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: |
opensuse | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | fedora38 | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: |
opensuse | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: |
rockylinux8 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | rockylinux8 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
rockylinux9 | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | rockylinux9 | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: |
ubuntu16 | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | ubuntu16 | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: |
ubuntu18 | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | ubuntu18 | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: |
ubuntu20 | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | ubuntu20 | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: |
ubuntu22 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | ubuntu22 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
## crio ## crio
| OS / CNI | calico | cilium | custom_cni | flannel | kube-ovn | kube-router | macvlan | weave | | OS / CNI | calico | canal | cilium | flannel | kube-ovn | kube-router | macvlan | weave |
|---| --- | --- | --- | --- | --- | --- | --- | --- | |---| --- | --- | --- | --- | --- | --- | --- | --- |
almalinux8 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | almalinux8 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
amazon | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | amazon | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
centos7 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | centos7 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
debian10 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | debian10 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
debian11 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | debian11 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
fedora35 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | debian9 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
fedora36 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | fedora37 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
fedora38 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
opensuse | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | opensuse | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
rockylinux8 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | rockylinux8 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
rockylinux9 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | rockylinux9 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
@@ -42,16 +44,17 @@ ubuntu22 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
## docker ## docker
| OS / CNI | calico | cilium | custom_cni | flannel | kube-ovn | kube-router | macvlan | weave | | OS / CNI | calico | canal | cilium | flannel | kube-ovn | kube-router | macvlan | weave |
|---| --- | --- | --- | --- | --- | --- | --- | --- | |---| --- | --- | --- | --- | --- | --- | --- | --- |
almalinux8 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | almalinux8 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
amazon | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | amazon | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
centos7 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | centos7 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
debian10 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | debian10 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
debian11 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | debian11 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
fedora35 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | debian9 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
fedora36 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | fedora37 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
opensuse | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | fedora38 | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: |
opensuse | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: |
rockylinux8 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | rockylinux8 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
rockylinux9 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | rockylinux9 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
ubuntu16 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | ubuntu16 | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: |

View File

@@ -1,59 +1,16 @@
# Cilium # Cilium
## IP Address Management (IPAM)
IP Address Management (IPAM) is responsible for the allocation and management of IP addresses used by network endpoints (container and others) managed by Cilium. The default mode is "Cluster Scope".
You can set the following parameters, for example: cluster-pool, kubernetes:
```yml
cilium_ipam_mode: cluster-pool
```
### Set the cluster Pod CIDRs
Cluster Pod CIDRs use the kube_pods_subnet value by default.
If your node network is in the same range you will lose connectivity to other nodes.
Defaults to kube_pods_subnet if not set.
You can set the following parameters:
```yml
cilium_pool_cidr: 10.233.64.0/18
```
When cilium_enable_ipv6 is used. Defaults to kube_pods_subnet_ipv6 if not set.
you need to set the IPV6 value:
```yml
cilium_pool_cidr_ipv6: fd85:ee78:d8a6:8607::1:0000/112
```
### Set the Pod CIDR size of a node
When cilium IPAM uses the "Cluster Scope" mode, it will pre-allocate a segment of IP to each node,
schedule the Pod to this node, and then allocate IP from here. cilium_pool_mask_size Specifies
the size allocated from cluster Pod CIDR to node.ipam.podCIDRs.
Defaults to kube_network_node_prefix if not set.
```yml
cilium_pool_mask_size: "24"
```
cilium_pool_mask_size Specifies the size allocated to node.ipam.podCIDRs from cluster Pod IPV6 CIDR. Defaults to kube_network_node_prefix_ipv6 if not set.
```yml
cilium_pool_mask_size_ipv6: "120"
```
## Kube-proxy replacement with Cilium ## Kube-proxy replacement with Cilium
Cilium can run without kube-proxy by setting `cilium_kube_proxy_replacement` Cilium can run without kube-proxy by setting `cilium_kube_proxy_replacement`
to `strict`. to `strict`.
Without kube-proxy, cilium needs to know the address of the kube-apiserver Without kube-proxy, cilium needs to know the address of the kube-apiserver
and this must be set globally for all Cilium components (agents and operators). and this must be set globally for all cilium components (agents and operators).
We can only use the localhost apiserver loadbalancer in this mode Hence, in this configuration in Kubespray, Cilium will always contact
whenever it uses the same port as the kube-apiserver (by default it does). the external loadbalancer (even from a node in the control plane)
and if there is no external load balancer It will ignore any local load
balancer deployed by Kubespray and **only contacts the first master**.
## Cilium Operator ## Cilium Operator

View File

@@ -2,7 +2,7 @@
## Provisioning ## Provisioning
You can deploy instances in your cloud environment in several ways. Examples include Terraform, Ansible (ec2 and gce modules), and manual creation. You can deploy instances in your cloud environment in several different ways. Examples include Terraform, Ansible (ec2 and gce modules), and manual creation.
## Deploy kubernetes ## Deploy kubernetes

View File

@@ -1,7 +1,9 @@
CNI CNI
============== ==============
This network plugin only unpacks CNI plugins version `cni_version` into `/opt/cni/bin` and instructs implementation of container runtime cri to use cni. This network plugin only unpacks CNI plugins version `cni_version` into `/opt/cni/bin` and instructs kubelet to use cni, that is adds following cli params:
`KUBELET_NETWORK_PLUGIN="--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin"`
It's intended usage is for custom CNI configuration, e.g. manual routing tables + bridge + loopback CNI plugin outside kubespray scope. Furthermore, it's used for non-kubespray supported CNI plugins which you can install afterward. It's intended usage is for custom CNI configuration, e.g. manual routing tables + bridge + loopback CNI plugin outside kubespray scope. Furthermore, it's used for non-kubespray supported CNI plugins which you can install afterward.

View File

@@ -40,7 +40,21 @@ crio_registries:
insecure: false insecure: false
``` ```
## Note about pids_limit
For heavily mult-threaded workloads like databases, the default of 1024 for pids-limit is too low.
This parameter controls not just the number of processes but also the amount of threads
(since a thread is technically a process with shared memory). See [cri-o#1921]
In order to increase the default `pids_limit` for cri-o based deployments you need to set the `crio_pids_limit`
for your `k8s_cluster` ansible group or per node depending on the use case.
```yaml
crio_pids_limit: 4096
```
[CRI-O]: https://cri-o.io/ [CRI-O]: https://cri-o.io/
[cri-o#1921]: https://github.com/cri-o/cri-o/issues/1921
## Note about user namespaces ## Note about user namespaces

View File

@@ -64,10 +64,6 @@ Custom options to be added to the kubernetes coredns plugin.
Extra domains to be forwarded to the kubernetes coredns plugin. Extra domains to be forwarded to the kubernetes coredns plugin.
### coredns_rewrite_block
[Rewrite](https://coredns.io/plugins/rewrite/) plugin block to perform internal message rewriting.
### coredns_external_zones ### coredns_external_zones
Array of optional external zones to coredns forward queries to. It's injected into Array of optional external zones to coredns forward queries to. It's injected into

View File

@@ -12,7 +12,7 @@ Alternatively you can use the values `identity`, `aesgcm`, `aescbc` or `kms`.
| Provider | Why we have decided against the value as default | | Provider | Why we have decided against the value as default |
|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| identity | no encryption | | identity | no encryption |
| aesgcm | Must be rotated every 200k writes | | aesgcm | Must be rotated every 200k writes |
| aescbc | Not recommended due to CBC's vulnerability to padding oracle attacks. | | aescbc | Not recommended due to CBC's vulnerability to padding oracle attacks. |
| kms | Is the official recommended way, but assumes that a key management service independent of Kubernetes exists, we cannot assume this in all environments, so not a suitable default value. | | kms | Is the official recommended way, but assumes that a key management service independent of Kubernetes exists, we cannot assume this in all environments, so not a suitable default value. |

View File

@@ -10,7 +10,7 @@ dynamically from the Terraform state file.
## Local Host Configuration ## Local Host Configuration
To perform this installation, you will need a localhost to run Terraform/Ansible (laptop, VM, etc) and an account with Equinix Metal. To perform this installation, you will need a localhost to run Terraform/Ansible (laptop, VM, etc) and an account with Equinix Metal.
In this example, we are provisioning a m1.large CentOS7 OpenStack VM as the localhost for the Kubernetes installation. In this example, we're using an m1.large CentOS 7 OpenStack VM as the localhost to kickoff the Kubernetes installation.
You'll need Ansible, Git, and PIP. You'll need Ansible, Git, and PIP.
```bash ```bash

View File

@@ -25,7 +25,7 @@ etcd_metrics_port: 2381
``` ```
To create a service `etcd-metrics` and associated endpoints in the `kube-system` namespace, To create a service `etcd-metrics` and associated endpoints in the `kube-system` namespace,
define its labels in the inventory with: define it's labels in the inventory with:
```yaml ```yaml
etcd_metrics_service_labels: etcd_metrics_service_labels:

View File

@@ -1,6 +1,6 @@
# Fedora CoreOS # Fedora CoreOS
Tested with stable version 37.20230322.3.0 Tested with stable version 34.20210611.3.0
Because package installation with `rpm-ostree` requires a reboot, playbook may fail while bootstrap. Because package installation with `rpm-ostree` requires a reboot, playbook may fail while bootstrap.
Restart playbook again. Restart playbook again.

View File

@@ -54,7 +54,7 @@ listen kubernetes-apiserver-https
balance roundrobin balance roundrobin
``` ```
Note: That's an example config managed elsewhere outside Kubespray. Note: That's an example config managed elsewhere outside of Kubespray.
And the corresponding example global vars for such a "cluster-aware" And the corresponding example global vars for such a "cluster-aware"
external LB with the cluster API access modes configured in Kubespray: external LB with the cluster API access modes configured in Kubespray:
@@ -85,7 +85,7 @@ for it.
Note: TLS/SSL termination for externally accessed API endpoints' will **not** Note: TLS/SSL termination for externally accessed API endpoints' will **not**
be covered by Kubespray for that case. Make sure your external LB provides it. be covered by Kubespray for that case. Make sure your external LB provides it.
Alternatively you may specify an external load balanced VIPs in the Alternatively you may specify an externally load balanced VIPs in the
`supplementary_addresses_in_ssl_keys` list. Then, kubespray will add them into `supplementary_addresses_in_ssl_keys` list. Then, kubespray will add them into
the generated cluster certificates as well. the generated cluster certificates as well.

View File

@@ -76,6 +76,8 @@ kube_controller_feature_gates: ["RotateKubeletServerCertificate=true"]
## kube-scheduler ## kube-scheduler
kube_scheduler_bind_address: 127.0.0.1 kube_scheduler_bind_address: 127.0.0.1
kube_kubeadm_scheduler_extra_args:
profiling: false
# AppArmor-based OS # AppArmor-based OS
# kube_scheduler_feature_gates: ["AppArmor=true"] # kube_scheduler_feature_gates: ["AppArmor=true"]
@@ -117,8 +119,7 @@ Let's take a deep look to the resultant **kubernetes** configuration:
* The `anonymous-auth` (on `kube-apiserver`) is set to `true` by default. This is fine, because it is considered safe if you enable `RBAC` for the `authorization-mode`. * The `anonymous-auth` (on `kube-apiserver`) is set to `true` by default. This is fine, because it is considered safe if you enable `RBAC` for the `authorization-mode`.
* The `enable-admission-plugins` has not the `PodSecurityPolicy` admission plugin. This because it is going to be definitely removed from **kubernetes** `v1.25`. For this reason we decided to set the newest `PodSecurity` (for more details, please take a look here: <https://kubernetes.io/docs/concepts/security/pod-security-admission/>). Then, we set the `EventRateLimit` plugin, providing additional configuration files (that are automatically created under the hood and mounted inside the `kube-apiserver` container) to make it work. * The `enable-admission-plugins` has not the `PodSecurityPolicy` admission plugin. This because it is going to be definitely removed from **kubernetes** `v1.25`. For this reason we decided to set the newest `PodSecurity` (for more details, please take a look here: <https://kubernetes.io/docs/concepts/security/pod-security-admission/>). Then, we set the `EventRateLimit` plugin, providing additional configuration files (that are automatically created under the hood and mounted inside the `kube-apiserver` container) to make it work.
* The `encryption-provider-config` provide encryption at rest. This means that the `kube-apiserver` encrypt data that is going to be stored before they reach `etcd`. So the data is completely unreadable from `etcd` (in case an attacker is able to exploit this). * The `encryption-provider-config` provide encryption at rest. This means that the `kube-apiserver` encrypt data that is going to be stored before they reach `etcd`. So the data is completely unreadable from `etcd` (in case an attacker is able to exploit this).
* The `rotateCertificates` in `KubeletConfiguration` is set to `true` along with `serverTLSBootstrap`. This could be used in alternative to `tlsCertFile` and `tlsPrivateKeyFile` parameters. Additionally it automatically generates certificates by itself. By default the CSRs are approved automatically via [kubelet-csr-approver](https://github.com/postfinance/kubelet-csr-approver). You can customize approval configuration by modifying Helm values via `kubelet_csr_approver_values`. * The `rotateCertificates` in `KubeletConfiguration` is set to `true` along with `serverTLSBootstrap`. This could be used in alternative to `tlsCertFile` and `tlsPrivateKeyFile` parameters. Additionally it automatically generates certificates by itself, but you need to manually approve them or at least using an operator to do this (for more details, please take a look here: <https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/>).
See <https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/> for more information on the subject.
* If you are installing **kubernetes** in an AppArmor-based OS (eg. Debian/Ubuntu) you can enable the `AppArmor` feature gate uncommenting the lines with the comment `# AppArmor-based OS` on top. * If you are installing **kubernetes** in an AppArmor-based OS (eg. Debian/Ubuntu) you can enable the `AppArmor` feature gate uncommenting the lines with the comment `# AppArmor-based OS` on top.
* The `kubelet_systemd_hardening`, both with `kubelet_secure_addresses` setup a minimal firewall on the system. To better understand how these variables work, here's an explanatory image: * The `kubelet_systemd_hardening`, both with `kubelet_secure_addresses` setup a minimal firewall on the system. To better understand how these variables work, here's an explanatory image:
![kubelet hardening](img/kubelet-hardening.png) ![kubelet hardening](img/kubelet-hardening.png)
@@ -135,3 +136,5 @@ ansible-playbook -v cluster.yml \
``` ```
**N.B.** The `vars.yaml` contains our general cluster information (SANs, load balancer, dns, etc..) and `hardening.yaml` is the file described above. **N.B.** The `vars.yaml` contains our general cluster information (SANs, load balancer, dns, etc..) and `hardening.yaml` is the file described above.
Once completed the cluster deployment, don't forget to approve the generated certificates (check them with `kubectl get csr`, approve with `kubectl certificate approve <csr_name>`). This action is necessary because the `secureTLSBootstrap` option and `RotateKubeletServerCertificate` feature gate for `kubelet` are enabled (CIS [4.2.11](https://www.tenable.com/audits/items/CIS_Kubernetes_v1.20_v1.0.0_Level_1_Worker.audit:05af3dfbca8e0c3fb3559c6c7de29191), [4.2.12](https://www.tenable.com/audits/items/CIS_Kubernetes_v1.20_v1.0.0_Level_1_Worker.audit:5351c76f8c5bff8f98c29a5200a35435)).

View File

@@ -155,11 +155,11 @@ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/mast
Using [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport): Using [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport):
```console ```console
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/deploy.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml
``` ```
!!! tip !!! tip
For extended notes regarding deployments on bare-metal, see [Bare-metal considerations](https://github.com/kubernetes/ingress-nginx/blob/main/docs/deploy/baremetal.md). For extended notes regarding deployments on bare-metal, see [Bare-metal considerations](./baremetal.md).
### Verify installation ### Verify installation

View File

@@ -95,7 +95,7 @@
ansible.builtin.import_playbook: 3d/kubespray/cluster.yml ansible.builtin.import_playbook: 3d/kubespray/cluster.yml
``` ```
Or you could copy separate tasks from cluster.yml into your ansible repository. Or your could copy separate tasks from cluster.yml into your ansible repository.
11. Commit changes to your ansible repo. Keep in mind, that submodule folder is just a link to the git commit hash of your forked repo. 11. Commit changes to your ansible repo. Keep in mind, that submodule folder is just a link to the git commit hash of your forked repo.
@@ -170,7 +170,7 @@ If you made useful changes or fixed a bug in existent kubespray repo, use this f
git push git push
``` ```
If your branch doesn't exist on github, git will propose you to use something like If your branch doesn't exists on github, git will propose you to use something like
```ShellSession ```ShellSession
git push --set-upstream origin fixes-name-date-index git push --set-upstream origin fixes-name-date-index

Some files were not shown because too many files have changed in this diff Show More