Compare commits

..

16 Commits

Author SHA1 Message Date
Max Gautier
12a65c45e9 Refactor check_galaxy + fix version (#10729) (#10891)
* Remove checks for docs using exact tags

Instead use a more generic documentation for installing kubespray as a
collection from git.

* Check that we upgraded galaxy.yml to next version

This is only intented to check for human error. The version in galaxy
should be the next (which does not mean the same if we're on master or a
release branch).

* Set collection version to KUBESPRAY_NEXT_VERSION
2024-02-06 04:07:46 -08:00
Max Gautier
1f4ca14029 Add patches versions checksums (runc, containerd) (#10878)
Make runc 1.1.12 and containerd 1.7.13 default
2024-02-05 09:16:32 -08:00
Max Gautier
e14ab338bf kubernetes: add hashes for 1.24.15, 1.24.16, 1.24.17 (#10823)
Make kubernetes 1.26.13 default
2024-01-22 18:29:35 +01:00
bo.jiang
d8a8fb03a2 Fix hardcoded pod infra version
Signed-off-by: bo.jiang <bo.jiang@daocloud.io>
2024-01-22 17:23:42 +01:00
Max Gautier
a0c142f2e7 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:13 +01:00
Kay Yan
774d824d0b bump vagrant 2.3.7 (#10789) 2024-01-11 14:59:56 +01:00
Max Gautier
336b323954 fix(multus): loop_control template error when item is None (#10347) (#10726)
Co-authored-by: Nicolas Goudry <nicolas-goudry@users.noreply.github.com>
2023-12-18 12:03:49 +01:00
Max Gautier
7dcbe415f8 [2.22] Add hashes for kubernetes 1.26.11, 1.26.10 (#10704)
* [kubernetes] Add hashes for kubernetes 1.26.11, 1.26.10

Make kubernetes 1.26.11 default

* Workaround for yaml/pyyaml#601

* Convert exoscale tf provider to new version (#10646)

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

* Update 0040-verify-settings.yml (#10699)

remove embedded template

* 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: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>
Co-authored-by: piwinkler <9642809+piwinkler@users.noreply.github.com>
Co-authored-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>
2023-12-12 07:27:35 +01:00
Boris Barnier
d65e4e61a7 Add hashes for kubernetes version 1.25.14
Signed-off-by: Boris Barnier <bozzo@users.noreply.github.com>
2023-09-19 11:45:53 +02:00
Boris Barnier
f2a364e375 Add hashes for kubernetes version 1.26.6, 1.26.7, 1.26.8 & 1.26.9
Signed-off-by: Boris Barnier <bozzo@users.noreply.github.com>
2023-09-19 11:45:53 +02:00
Kay Yan
2cf23e3104 Don't search filesystem mounts in docker build step (#10131) (#10194)
Limit find cmd to /usr/ where __pycache__ files are located

Co-authored-by: Mateusz Mojsiejuk <m@fishface.se>
2023-06-06 10:16:12 -07:00
Kay Yan
200e0d54a2 Rebasechanges from upstream (#10128) (#10186)
Co-authored-by: Daniel Strufe <2900921+dabeck@users.noreply.github.com>
2023-06-04 23:40:43 -07:00
Kay Yan
fc28bfc336 Fix metrics-server for k8s 1.26 (#10183) (#10187)
Co-authored-by: Mohamed Omar Zaian <mohamedzaian@gmail.com>
2023-06-04 21:46:42 -07:00
Kay Yan
733ac8ffa9 fix-dockerfile (#10181) 2023-06-02 02:34:53 -07:00
Alexander
70450a4882 update README for v2.22.0 (#10180) 2023-06-02 01:00:53 -07:00
Jeroen Rijken
71349c9a17 [2.22] MetalLB backport (#10164)
* Update MetalLB deployment, wait for resource.

Signed-off-by: Jeroen Rijken <jeroen.rijken@xs4all.nl>

* yml to yaml, add basic test for metallb

Signed-off-by: Jeroen Rijken <jeroen.rijken@xs4all.nl>

---------

Signed-off-by: Jeroen Rijken <jeroen.rijken@xs4all.nl>
2023-06-01 19:57:45 -07:00
791 changed files with 9025 additions and 13491 deletions

View File

@@ -7,33 +7,34 @@ skip_list:
# These rules are intentionally skipped: # These rules are intentionally skipped:
# #
# [E204]: "Lines should be no longer than 160 chars"
# This could be re-enabled with a major rewrite in the future.
# For now, there's not enough value gain from strictly limiting line length.
# (Disabled in May 2019)
- '204'
# [E701]: "meta/main.yml should contain relevant info"
# Roles in Kubespray are not intended to be used/imported by Ansible Galaxy.
# While it can be useful to have these metadata available, they are also available in the existing documentation.
# (Disabled in May 2019)
- '701'
# [role-name] "meta/main.yml" Role name role-name does not match ``^+$`` pattern # [role-name] "meta/main.yml" Role name role-name does not match ``^+$`` pattern
# Meta roles in Kubespray don't need proper names # Meta roles in Kubespray don't need proper names
# (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] # [fqcn-builtins]
# Roles in kubespray don't need fully qualified collection names # Roles in kubespray don't need fully qualified collection names
# (Disabled in Feb 2023) # (Disabled in Feb 2023)
- 'fqcn-builtins' - 'fqcn-builtins'
# We use template in names
- 'name[template]'
# No changed-when on commands
# (Disabled in June 2023 after ansible upgrade; FIXME)
- 'no-changed-when'
# Disable run-once check with free strategy
# (Disabled in June 2023 after ansible upgrade; FIXME)
- 'run-once[task]'
exclude_paths: exclude_paths:
# Generated files # Generated files
- tests/files/custom_cni/cilium.yaml - tests/files/custom_cni/cilium.yaml
- venv
- .github

View File

@@ -1,8 +0,0 @@
# This file contains ignores rule violations for ansible-lint
inventory/sample/group_vars/k8s_cluster/k8s-cluster.yml jinja[spacing]
roles/kubernetes/control-plane/defaults/main/kube-proxy.yml jinja[spacing]
roles/kubernetes/control-plane/defaults/main/main.yml jinja[spacing]
roles/kubernetes/kubeadm/defaults/main.yml jinja[spacing]
roles/kubernetes/node/defaults/main.yml jinja[spacing]
roles/kubernetes/preinstall/defaults/main.yml jinja[spacing]
roles/kubespray-defaults/defaults/main/main.yml jinja[spacing]

1
.gitattributes vendored
View File

@@ -1 +0,0 @@
docs/_sidebar.md linguist-generated=true

44
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@@ -0,0 +1,44 @@
---
name: Bug Report
about: Report a bug encountered while operating Kubernetes
labels: kind/bug
---
<!--
Please, be ready for followup questions, and please respond in a timely
manner. If we can't reproduce a bug or think a feature already exists, we
might close your issue. If we're wrong, PLEASE feel free to reopen it and
explain why.
-->
**Environment**:
- **Cloud provider or hardware configuration:**
- **OS (`printf "$(uname -srm)\n$(cat /etc/os-release)\n"`):**
- **Version of Ansible** (`ansible --version`):
- **Version of Python** (`python --version`):
**Kubespray version (commit) (`git rev-parse --short HEAD`):**
**Network plugin used**:
**Full inventory with variables (`ansible -i inventory/sample/inventory.ini all -m debug -a "var=hostvars[inventory_hostname]"`):**
<!-- We recommend using snippets services like https://gist.github.com/ etc. -->
**Command used to invoke ansible**:
**Output of ansible run**:
<!-- We recommend using snippets services like https://gist.github.com/ etc. -->
**Anything else do we need to know**:
<!-- By running scripts/collect-info.yaml you can get a lot of useful informations.
Script can be started by:
ansible-playbook -i <inventory_file_path> -u <ssh_user> -e ansible_ssh_user=<ssh_user> -b --become-user=root -e dir=`pwd` scripts/collect-info.yaml
(If you using CoreOS remember to add '-e ansible_python_interpreter=/opt/bin/python').
After running this command you can find logs in `pwd`/logs.tar.gz. You can even upload somewhere entire file and paste link here.-->

View File

@@ -1,124 +0,0 @@
---
name: Bug Report
description: Report a bug encountered while using Kubespray
labels: kind/bug
body:
- type: markdown
attributes:
value: |
Please, be ready for followup questions, and please respond in a timely
manner. If we can't reproduce a bug or think a feature already exists, we
might close your issue. If we're wrong, PLEASE feel free to reopen it and
explain why.
- type: textarea
id: problem
attributes:
label: What happened?
description: |
Please provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner.
validations:
required: true
- type: textarea
id: expected
attributes:
label: What did you expect to happen?
validations:
required: true
- type: textarea
id: repro
attributes:
label: How can we reproduce it (as minimally and precisely as possible)?
validations:
required: true
- type: markdown
attributes:
value: '### Environment'
- type: textarea
id: os
attributes:
label: OS
placeholder: 'printf "$(uname -srm)\n$(cat /etc/os-release)\n"'
validations:
required: true
- type: textarea
id: ansible_version
attributes:
label: Version of Ansible
placeholder: 'ansible --version'
validations:
required: true
- type: input
id: python_version
attributes:
label: Version of Python
placeholder: 'python --version'
validations:
required: true
- type: input
id: kubespray_version
attributes:
label: Version of Kubespray (commit)
placeholder: 'git rev-parse --short HEAD'
validations:
required: true
- type: dropdown
id: network_plugin
attributes:
label: Network plugin used
options:
- calico
- cilium
- cni
- custom_cni
- flannel
- kube-ovn
- kube-router
- macvlan
- meta
- multus
- ovn4nfv
- weave
validations:
required: true
- type: textarea
id: inventory
attributes:
label: Full inventory with variables
placeholder: 'ansible -i inventory/sample/inventory.ini all -m debug -a "var=hostvars[inventory_hostname]"'
description: We recommend using snippets services like https://gist.github.com/ etc.
validations:
required: true
- type: input
id: ansible_command
attributes:
label: Command used to invoke ansible
validations:
required: true
- type: textarea
id: ansible_output
attributes:
label: Output of ansible run
description: We recommend using snippets services like https://gist.github.com/ etc.
validations:
required: true
- type: textarea
id: anything_else
attributes:
label: Anything else we need to know
description: |
By running scripts/collect-info.yaml you can get a lot of useful informations.
Script can be started by:
ansible-playbook -i <inventory_file_path> -u <ssh_user> -e ansible_ssh_user=<ssh_user> -b --become-user=root -e dir=`pwd` scripts/collect-info.yaml
(If you using CoreOS remember to add '-e ansible_python_interpreter=/opt/bin/python').
After running this command you can find logs in `pwd`/logs.tar.gz. You can even upload somewhere entire file and paste link here

View File

@@ -1,5 +0,0 @@
---
contact_links:
- name: Support Request
url: https://kubernetes.slack.com/channels/kubespray
about: Support request or question relating to Kubernetes

11
.github/ISSUE_TEMPLATE/enhancement.md vendored Normal file
View File

@@ -0,0 +1,11 @@
---
name: Enhancement Request
about: Suggest an enhancement to the Kubespray project
labels: kind/feature
---
<!-- Please only use this template for submitting enhancement requests -->
**What would you like to be added**:
**Why is this needed**:

View File

@@ -1,20 +0,0 @@
---
name: Enhancement Request
description: Suggest an enhancement to the Kubespray project
labels: kind/feature
body:
- type: markdown
attributes:
value: Please only use this template for submitting enhancement requests
- type: textarea
id: what
attributes:
label: What would you like to be added
validations:
required: true
- type: textarea
id: why
attributes:
label: Why is this needed
validations:
required: true

20
.github/ISSUE_TEMPLATE/failing-test.md vendored Normal file
View File

@@ -0,0 +1,20 @@
---
name: Failing Test
about: Report test failures in Kubespray CI jobs
labels: kind/failing-test
---
<!-- Please only use this template for submitting reports about failing tests in Kubespray CI jobs -->
**Which jobs are failing**:
**Which test(s) are failing**:
**Since when has it been failing**:
**Testgrid link**:
**Reason for failure**:
**Anything else we need to know**:

View File

@@ -1,41 +0,0 @@
---
name: Failing Test
description: Report test failures in Kubespray CI jobs
labels: kind/failing-test
body:
- type: markdown
attributes:
value: Please only use this template for submitting reports about failing tests in Kubespray CI jobs
- type: textarea
id: failing_jobs
attributes:
label: Which jobs are failing ?
validations:
required: true
- type: textarea
id: failing_tests
attributes:
label: Which tests are failing ?
validations:
required: true
- type: input
id: since_when
attributes:
label: Since when has it been failing ?
validations:
required: true
- type: textarea
id: failure_reason
attributes:
label: Reason for failure
description: If you don't know and have no guess, just put "Unknown"
validations:
required: true
- type: textarea
id: anything_else
attributes:
label: Anything else we need to know

18
.github/ISSUE_TEMPLATE/support.md vendored Normal file
View File

@@ -0,0 +1,18 @@
---
name: Support Request
about: Support request or question relating to Kubespray
labels: kind/support
---
<!--
STOP -- PLEASE READ!
GitHub is not the right place for support requests.
If you're looking for help, check [Stack Overflow](https://stackoverflow.com/questions/tagged/kubespray) and the [troubleshooting guide](https://kubernetes.io/docs/tasks/debug-application-cluster/troubleshooting/).
You can also post your question on the [Kubernetes Slack](http://slack.k8s.io/) or the [Discuss Kubernetes](https://discuss.kubernetes.io/) forum.
If the matter is security related, please disclose it privately via https://kubernetes.io/security/.
-->

View File

@@ -1,7 +0,0 @@
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
labels: [ "dependencies" ]

4
.gitignore vendored
View File

@@ -3,8 +3,6 @@
**/vagrant_ansible_inventory **/vagrant_ansible_inventory
*.iml *.iml
temp temp
contrib/offline/container-images
contrib/offline/container-images.tar.gz
contrib/offline/offline-files contrib/offline/offline-files
contrib/offline/offline-files.tar.gz contrib/offline/offline-files.tar.gz
.idea .idea
@@ -13,7 +11,7 @@ contrib/offline/offline-files.tar.gz
.cache .cache
*.bak *.bak
*.tfstate *.tfstate
*.tfstate*backup *.tfstate.backup
*.lock.hcl *.lock.hcl
.terraform/ .terraform/
contrib/terraform/aws/credentials.tfvars contrib/terraform/aws/credentials.tfvars

View File

@@ -9,7 +9,7 @@ stages:
- deploy-special - deploy-special
variables: variables:
KUBESPRAY_VERSION: v2.25.0 KUBESPRAY_VERSION: v2.21.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"
@@ -33,12 +33,16 @@ variables:
MITOGEN_ENABLE: "false" MITOGEN_ENABLE: "false"
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.3.7
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}"
before_script: before_script:
- ./tests/scripts/rebase.sh - ./tests/scripts/rebase.sh
- update-alternatives --install /usr/bin/python python /usr/bin/python3 1
- python -m pip uninstall -y ansible ansible-base ansible-core
- PIP_CONSTRAINT=tests/constraints.txt python -m pip install -r tests/requirements-${ANSIBLE_MAJOR_VERSION}.txt
- mkdir -p /.ssh - mkdir -p /.ssh
.job: &job .job: &job
@@ -53,7 +57,6 @@ before_script:
.testcases: &testcases .testcases: &testcases
<<: *job <<: *job
retry: 1 retry: 1
interruptible: true
before_script: before_script:
- update-alternatives --install /usr/bin/python python /usr/bin/python3 1 - update-alternatives --install /usr/bin/python python /usr/bin/python3 1
- ./tests/scripts/rebase.sh - ./tests/scripts/rebase.sh

View File

@@ -27,14 +27,6 @@ ansible-lint:
- ansible-lint -v - ansible-lint -v
except: ['triggers', 'master'] except: ['triggers', 'master']
jinja-syntax-check:
extends: .job
stage: unit-tests
tags: [light]
script:
- "find -name '*.j2' -exec tests/scripts/check-templates.py {} +"
except: ['triggers', 'master']
syntax-check: syntax-check:
extends: .job extends: .job
stage: unit-tests stage: unit-tests
@@ -75,6 +67,10 @@ tox-inventory-builder:
extends: .job extends: .job
before_script: before_script:
- ./tests/scripts/rebase.sh - ./tests/scripts/rebase.sh
- apt-get update && apt-get install -y python3-pip
- update-alternatives --install /usr/bin/python python /usr/bin/python3 10
- python -m pip uninstall -y ansible ansible-base ansible-core
- PIP_CONSTRAINT=tests/constraints.txt python -m pip install -r tests/requirements.txt
script: script:
- pip3 install tox - pip3 install tox
- cd contrib/inventory_builder && tox - cd contrib/inventory_builder && tox
@@ -89,14 +85,6 @@ markdownlint:
script: script:
- markdownlint $(find . -name '*.md' | grep -vF './.git') --ignore docs/_sidebar.md --ignore contrib/dind/README.md - markdownlint $(find . -name '*.md' | grep -vF './.git') --ignore docs/_sidebar.md --ignore contrib/dind/README.md
generate-sidebar:
extends: .job
stage: unit-tests
tags: [light]
script:
- scripts/gen_docs_sidebar.sh
- git diff --exit-code
check-readme-versions: check-readme-versions:
stage: unit-tests stage: unit-tests
tags: [light] tags: [light]

View File

@@ -9,6 +9,10 @@
stage: deploy-part1 stage: deploy-part1
before_script: before_script:
- tests/scripts/rebase.sh - tests/scripts/rebase.sh
- apt-get update && apt-get install -y python3-pip
- update-alternatives --install /usr/bin/python python /usr/bin/python3 10
- python -m pip uninstall -y ansible ansible-base ansible-core
- PIP_CONSTRAINT=tests/constraints.txt python -m pip install -r tests/requirements.txt
- ./tests/scripts/vagrant_clean.sh - ./tests/scripts/vagrant_clean.sh
script: script:
- ./tests/scripts/molecule_run.sh - ./tests/scripts/molecule_run.sh
@@ -54,30 +58,29 @@ molecule_cri-o:
stage: deploy-part2 stage: deploy-part2
script: script:
- ./tests/scripts/molecule_run.sh -i container-engine/cri-o - ./tests/scripts/molecule_run.sh -i container-engine/cri-o
allow_failure: true
when: on_success when: on_success
# Stage 3 container engines don't get as much attention so allow them to fail # Stage 3 container engines don't get as much attention so allow them to fail
molecule_kata: molecule_kata:
extends: .molecule extends: .molecule
stage: deploy-part3 stage: deploy-part3
allow_failure: true
script: script:
- ./tests/scripts/molecule_run.sh -i container-engine/kata-containers - ./tests/scripts/molecule_run.sh -i container-engine/kata-containers
when: manual when: on_success
# FIXME: this test is broken (perma-failing)
molecule_gvisor: molecule_gvisor:
extends: .molecule extends: .molecule
stage: deploy-part3 stage: deploy-part3
allow_failure: true
script: script:
- ./tests/scripts/molecule_run.sh -i container-engine/gvisor - ./tests/scripts/molecule_run.sh -i container-engine/gvisor
when: manual when: on_success
# FIXME: this test is broken (perma-failing)
molecule_youki: molecule_youki:
extends: .molecule extends: .molecule
stage: deploy-part3 stage: deploy-part3
allow_failure: true
script: script:
- ./tests/scripts/molecule_run.sh -i container-engine/youki - ./tests/scripts/molecule_run.sh -i container-engine/youki
when: manual when: on_success
# FIXME: this test is broken (perma-failing)

View File

@@ -23,55 +23,50 @@
allow_failure: true allow_failure: true
extends: .packet extends: .packet
packet_cleanup_old: # The ubuntu20-calico-aio jobs are meant as early stages to prevent running the full CI if something is horribly broken
stage: deploy-part1 packet_ubuntu20-calico-aio:
extends: .packet_periodic
script:
- cd tests
- make cleanup-packet
after_script: []
# The ubuntu20-calico-all-in-one jobs are meant as early stages to prevent running the full CI if something is horribly broken
packet_ubuntu20-calico-all-in-one:
stage: deploy-part1 stage: deploy-part1
extends: .packet_pr extends: .packet_pr
when: on_success when: on_success
variables: variables:
RESET_CHECK: "true" RESET_CHECK: "true"
packet_ubuntu20-calico-aio-ansible-2_11:
stage: deploy-part1
extends: .packet_periodic
when: on_success
variables:
ANSIBLE_MAJOR_VERSION: "2.11"
RESET_CHECK: "true"
# ### PR JOBS PART2 # ### PR JOBS PART2
packet_ubuntu20-all-in-one-docker: packet_ubuntu18-aio-docker:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: on_success when: on_success
packet_ubuntu20-calico-all-in-one-hardening: packet_ubuntu20-aio-docker:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: on_success when: on_success
packet_ubuntu22-all-in-one-docker: packet_ubuntu20-calico-aio-hardening:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: on_success when: on_success
packet_ubuntu22-calico-all-in-one: packet_ubuntu18-calico-aio:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: on_success when: on_success
packet_ubuntu24-all-in-one-docker: packet_ubuntu22-aio-docker:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: on_success when: on_success
packet_ubuntu24-calico-all-in-one: packet_ubuntu22-calico-aio:
stage: deploy-part2
extends: .packet_pr
when: on_success
packet_ubuntu24-calico-etcd-datastore:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: on_success when: on_success
@@ -85,9 +80,8 @@ packet_almalinux8-crio:
extends: .packet_pr extends: .packet_pr
stage: deploy-part2 stage: deploy-part2
when: on_success when: on_success
allow_failure: true
packet_ubuntu20-crio: packet_ubuntu18-crio:
extends: .packet_pr extends: .packet_pr
stage: deploy-part2 stage: deploy-part2
when: manual when: manual
@@ -97,7 +91,7 @@ packet_fedora37-crio:
stage: deploy-part2 stage: deploy-part2
when: manual when: manual
packet_ubuntu20-flannel-ha: packet_ubuntu16-flannel-ha:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: manual when: manual
@@ -127,21 +121,6 @@ packet_debian11-docker:
extends: .packet_pr extends: .packet_pr
when: on_success when: on_success
packet_debian12-calico:
stage: deploy-part2
extends: .packet_pr
when: on_success
packet_debian12-docker:
stage: deploy-part2
extends: .packet_pr
when: on_success
packet_debian12-cilium:
stage: deploy-part2
extends: .packet_periodic
when: on_success
packet_centos7-calico-ha-once-localhost: packet_centos7-calico-ha-once-localhost:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
@@ -154,7 +133,7 @@ packet_centos7-calico-ha-once-localhost:
packet_almalinux8-kube-ovn: packet_almalinux8-kube-ovn:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_periodic
when: on_success when: on_success
packet_almalinux8-calico: packet_almalinux8-calico:
@@ -184,11 +163,6 @@ packet_almalinux8-docker:
extends: .packet_pr extends: .packet_pr
when: on_success when: on_success
packet_amazon-linux-2-all-in-one:
stage: deploy-part2
extends: .packet_pr
when: on_success
packet_fedora38-docker-weave: packet_fedora38-docker-weave:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
@@ -198,21 +172,26 @@ packet_fedora38-docker-weave:
packet_opensuse-docker-cilium: packet_opensuse-docker-cilium:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: on_success when: manual
# ### MANUAL JOBS # ### MANUAL JOBS
packet_ubuntu20-docker-weave-sep: packet_ubuntu16-docker-weave-sep:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: manual when: manual
packet_ubuntu20-cilium-sep: packet_ubuntu18-cilium-sep:
stage: deploy-special stage: deploy-special
extends: .packet_pr extends: .packet_pr
when: manual when: manual
packet_ubuntu20-flannel-ha-once: packet_ubuntu18-flannel-ha:
stage: deploy-part2
extends: .packet_pr
when: manual
packet_ubuntu18-flannel-ha-once:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
when: manual when: manual
@@ -255,6 +234,11 @@ packet_fedora37-calico-swap-selinux:
extends: .packet_pr extends: .packet_pr
when: manual when: manual
packet_amazon-linux-2-aio:
stage: deploy-part2
extends: .packet_pr
when: manual
packet_almalinux8-calico-nodelocaldns-secondary: packet_almalinux8-calico-nodelocaldns-secondary:
stage: deploy-part2 stage: deploy-part2
extends: .packet_pr extends: .packet_pr
@@ -275,11 +259,6 @@ packet_debian11-kubelet-csr-approver:
extends: .packet_pr extends: .packet_pr
when: manual when: manual
packet_debian12-custom-cni-helm:
stage: deploy-part2
extends: .packet_pr
when: manual
# ### PR JOBS PART3 # ### PR JOBS PART3
# Long jobs (45min+) # Long jobs (45min+)
@@ -330,18 +309,18 @@ packet_debian11-calico-upgrade-once:
variables: variables:
UPGRADE_TEST: graceful UPGRADE_TEST: graceful
packet_ubuntu20-calico-ha-recover: packet_ubuntu18-calico-ha-recover:
stage: deploy-part3 stage: deploy-part3
extends: .packet_periodic extends: .packet_periodic
when: on_success when: on_success
variables: variables:
RECOVER_CONTROL_PLANE_TEST: "true" RECOVER_CONTROL_PLANE_TEST: "true"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:]:kube_control_plane[1:]" RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:],kube_control_plane[1:]"
packet_ubuntu20-calico-ha-recover-noquorum: packet_ubuntu18-calico-ha-recover-noquorum:
stage: deploy-part3 stage: deploy-part3
extends: .packet_periodic extends: .packet_periodic
when: on_success when: on_success
variables: variables:
RECOVER_CONTROL_PLANE_TEST: "true" RECOVER_CONTROL_PLANE_TEST: "true"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[1:]:kube_control_plane[1:]" RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[1:],kube_control_plane[1:]"

View File

@@ -100,13 +100,21 @@ tf-validate-upcloud:
PROVIDER: upcloud PROVIDER: upcloud
CLUSTER: $CI_COMMIT_REF_NAME CLUSTER: $CI_COMMIT_REF_NAME
tf-validate-nifcloud: # tf-packet-ubuntu16-default:
extends: .terraform_validate # extends: .terraform_apply
variables: # variables:
TF_VERSION: $TERRAFORM_VERSION # TF_VERSION: $TERRAFORM_VERSION
PROVIDER: nifcloud # PROVIDER: packet
# CLUSTER: $CI_COMMIT_REF_NAME
# tf-packet-ubuntu20-default: # TF_VAR_number_of_k8s_masters: "1"
# TF_VAR_number_of_k8s_nodes: "1"
# TF_VAR_plan_k8s_masters: t1.small.x86
# TF_VAR_plan_k8s_nodes: t1.small.x86
# TF_VAR_metro: ny
# TF_VAR_public_key_path: ""
# TF_VAR_operating_system: ubuntu_16_04
#
# tf-packet-ubuntu18-default:
# extends: .terraform_apply # extends: .terraform_apply
# variables: # variables:
# TF_VERSION: $TERRAFORM_VERSION # TF_VERSION: $TERRAFORM_VERSION
@@ -118,7 +126,7 @@ tf-validate-nifcloud:
# TF_VAR_plan_k8s_nodes: t1.small.x86 # TF_VAR_plan_k8s_nodes: t1.small.x86
# TF_VAR_metro: am # TF_VAR_metro: am
# TF_VAR_public_key_path: "" # TF_VAR_public_key_path: ""
# TF_VAR_operating_system: ubuntu_20_04 # TF_VAR_operating_system: ubuntu_18_04
.ovh_variables: &ovh_variables .ovh_variables: &ovh_variables
OS_AUTH_URL: https://auth.cloud.ovh.net/v3 OS_AUTH_URL: https://auth.cloud.ovh.net/v3
@@ -156,7 +164,7 @@ tf-elastx_cleanup:
script: script:
- ./scripts/openstack-cleanup/main.py - ./scripts/openstack-cleanup/main.py
tf-elastx_ubuntu20-calico: tf-elastx_ubuntu18-calico:
extends: .terraform_apply extends: .terraform_apply
stage: deploy-part3 stage: deploy-part3
when: on_success when: on_success
@@ -186,7 +194,7 @@ tf-elastx_ubuntu20-calico:
TF_VAR_az_list_node: '["sto1"]' TF_VAR_az_list_node: '["sto1"]'
TF_VAR_flavor_k8s_master: 3f73fc93-ec61-4808-88df-2580d94c1a9b # v1-standard-2 TF_VAR_flavor_k8s_master: 3f73fc93-ec61-4808-88df-2580d94c1a9b # v1-standard-2
TF_VAR_flavor_k8s_node: 3f73fc93-ec61-4808-88df-2580d94c1a9b # v1-standard-2 TF_VAR_flavor_k8s_node: 3f73fc93-ec61-4808-88df-2580d94c1a9b # v1-standard-2
TF_VAR_image: ubuntu-20.04-server-latest TF_VAR_image: ubuntu-18.04-server-latest
TF_VAR_k8s_allowed_remote_ips: '["0.0.0.0/0"]' TF_VAR_k8s_allowed_remote_ips: '["0.0.0.0/0"]'
# OVH voucher expired, commenting job until things are sorted out # OVH voucher expired, commenting job until things are sorted out
@@ -203,7 +211,7 @@ tf-elastx_ubuntu20-calico:
# script: # script:
# - ./scripts/openstack-cleanup/main.py # - ./scripts/openstack-cleanup/main.py
# tf-ovh_ubuntu20-calico: # tf-ovh_ubuntu18-calico:
# extends: .terraform_apply # extends: .terraform_apply
# when: on_success # when: on_success
# environment: ovh # environment: ovh
@@ -229,5 +237,5 @@ tf-elastx_ubuntu20-calico:
# TF_VAR_network_name: "Ext-Net" # TF_VAR_network_name: "Ext-Net"
# TF_VAR_flavor_k8s_master: "defa64c3-bd46-43b4-858a-d93bbae0a229" # s1-8 # TF_VAR_flavor_k8s_master: "defa64c3-bd46-43b4-858a-d93bbae0a229" # s1-8
# TF_VAR_flavor_k8s_node: "defa64c3-bd46-43b4-858a-d93bbae0a229" # s1-8 # TF_VAR_flavor_k8s_node: "defa64c3-bd46-43b4-858a-d93bbae0a229" # s1-8
# TF_VAR_image: "Ubuntu 20.04" # TF_VAR_image: "Ubuntu 18.04"
# TF_VAR_k8s_allowed_remote_ips: '["0.0.0.0/0"]' # TF_VAR_k8s_allowed_remote_ips: '["0.0.0.0/0"]'

View File

@@ -13,19 +13,28 @@
image: $PIPELINE_IMAGE image: $PIPELINE_IMAGE
services: [] services: []
before_script: before_script:
- apt-get update && apt-get install -y python3-pip
- update-alternatives --install /usr/bin/python python /usr/bin/python3 10
- python -m pip uninstall -y ansible ansible-base ansible-core
- PIP_CONSTRAINT=tests/constraints.txt python -m pip install -r tests/requirements.txt
- ./tests/scripts/vagrant_clean.sh - ./tests/scripts/vagrant_clean.sh
script: script:
- ./tests/scripts/testcases_run.sh - ./tests/scripts/testcases_run.sh
after_script: after_script:
- chronic ./tests/scripts/testcases_cleanup.sh - chronic ./tests/scripts/testcases_cleanup.sh
allow_failure: true
vagrant_ubuntu20-calico-dual-stack: vagrant_ubuntu18-calico-dual-stack:
stage: deploy-part2 stage: deploy-part2
extends: .vagrant extends: .vagrant
when: manual when: on_success
# FIXME: this test if broken (perma-failing)
vagrant_ubuntu20-weave-medium: vagrant_ubuntu18-flannel:
stage: deploy-part2
extends: .vagrant
when: on_success
vagrant_ubuntu18-weave-medium:
stage: deploy-part2 stage: deploy-part2
extends: .vagrant extends: .vagrant
when: manual when: manual
@@ -41,13 +50,13 @@ vagrant_ubuntu20-flannel-collection:
extends: .vagrant extends: .vagrant
when: on_success when: on_success
vagrant_ubuntu20-kube-router-sep: vagrant_ubuntu16-kube-router-sep:
stage: deploy-part2 stage: deploy-part2
extends: .vagrant extends: .vagrant
when: manual when: manual
# Service proxy test fails connectivity testing # Service proxy test fails connectivity testing
vagrant_ubuntu20-kube-router-svc-proxy: vagrant_ubuntu16-kube-router-svc-proxy:
stage: deploy-part2 stage: deploy-part2
extends: .vagrant extends: .vagrant
when: manual when: manual
@@ -55,8 +64,7 @@ vagrant_ubuntu20-kube-router-svc-proxy:
vagrant_fedora37-kube-router: vagrant_fedora37-kube-router:
stage: deploy-part2 stage: deploy-part2
extends: .vagrant extends: .vagrant
when: manual when: on_success
# FIXME: this test if broken (perma-failing)
vagrant_centos7-kube-router: vagrant_centos7-kube-router:
stage: deploy-part2 stage: deploy-part2

View File

@@ -1,5 +1,6 @@
--- ---
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0 rev: v3.4.0
hooks: hooks:
@@ -24,14 +25,14 @@ repos:
rev: v0.11.0 rev: v0.11.0
hooks: hooks:
- id: markdownlint - id: markdownlint
args: [-r, "~MD013,~MD029"] args: [ -r, "~MD013,~MD029" ]
exclude: "^.git" exclude: "^.git"
- repo: https://github.com/jumanjihouse/pre-commit-hooks - repo: https://github.com/jumanjihouse/pre-commit-hooks
rev: 3.0.0 rev: 3.0.0
hooks: hooks:
- id: shellcheck - id: shellcheck
args: [--severity, "error"] args: [ --severity, "error" ]
exclude: "^.git" exclude: "^.git"
files: "\\.sh$" files: "\\.sh$"
@@ -63,23 +64,8 @@ repos:
language: script language: script
pass_filenames: false pass_filenames: false
- id: generate-docs-sidebar
name: generate-docs-sidebar
entry: scripts/gen_docs_sidebar.sh
language: script
pass_filenames: false
- id: ci-matrix - id: ci-matrix
name: ci-matrix name: ci-matrix
entry: tests/scripts/md-table/test.sh entry: tests/scripts/md-table/test.sh
language: script language: script
pass_filenames: false pass_filenames: false
- id: jinja-syntax-check
name: jinja-syntax-check
entry: tests/scripts/check-templates.py
language: python
types:
- jinja
additional_dependencies:
- Jinja2

View File

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

View File

@@ -1 +0,0 @@
# See our release notes on [GitHub](https://github.com/kubernetes-sigs/kubespray/releases)

View File

@@ -12,7 +12,6 @@ To install development dependencies you can set up a python virtual env with the
virtualenv venv virtualenv venv
source venv/bin/activate source venv/bin/activate
pip install -r tests/requirements.txt pip install -r tests/requirements.txt
ansible-galaxy install -r tests/requirements.yml
``` ```
#### Linting #### Linting

View File

@@ -1,46 +1,13 @@
# syntax=docker/dockerfile:1
# Use imutable image tags rather than mutable tags (like ubuntu:22.04) # Use imutable image tags rather than mutable tags (like ubuntu:22.04)
FROM ubuntu:22.04@sha256:149d67e29f765f4db62aa52161009e99e389544e25a8f43c8c89d4a445a7ca37 FROM ubuntu:jammy-20230308
# 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 \ DEBIAN_FRONTEND=noninteractive \
PYTHONDONTWRITEBYTECODE=1 PYTHONDONTWRITEBYTECODE=1
WORKDIR /kubespray WORKDIR /kubespray
# hadolint ignore=DL3008
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
apt-get update -q \
&& apt-get install -yq --no-install-recommends \
curl \
python3 \
python3-pip \
sshpass \
vim \
rsync \
openssh-client \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /var/log/*
RUN --mount=type=bind,source=requirements.txt,target=requirements.txt \
--mount=type=cache,sharing=locked,id=pipcache,mode=0777,target=/root/.cache/pip \
pip install --no-compile --no-cache-dir -r requirements.txt \
&& find /usr -type d -name '*__pycache__' -prune -exec rm -rf {} \;
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN --mount=type=bind,source=roles/kubespray-defaults/defaults/main/main.yml,target=roles/kubespray-defaults/defaults/main/main.yml \
KUBE_VERSION=$(sed -n 's/^kube_version: //p' roles/kubespray-defaults/defaults/main/main.yml) \
OS_ARCHITECTURE=$(dpkg --print-architecture) \
&& curl -L "https://dl.k8s.io/release/${KUBE_VERSION}/bin/linux/${OS_ARCHITECTURE}/kubectl" -o /usr/local/bin/kubectl \
&& echo "$(curl -L "https://dl.k8s.io/release/${KUBE_VERSION}/bin/linux/${OS_ARCHITECTURE}/kubectl.sha256")" /usr/local/bin/kubectl | sha256sum --check \
&& chmod a+x /usr/local/bin/kubectl
COPY *.yml ./ COPY *.yml ./
COPY *.cfg ./ COPY *.cfg ./
COPY roles ./roles COPY roles ./roles
@@ -50,3 +17,28 @@ COPY library ./library
COPY extra_playbooks ./extra_playbooks COPY extra_playbooks ./extra_playbooks
COPY playbooks ./playbooks COPY playbooks ./playbooks
COPY plugins ./plugins COPY plugins ./plugins
RUN apt update -q \
&& apt install -yq --no-install-recommends \
curl \
python3 \
python3-pip \
sshpass \
vim \
rsync \
openssh-client \
&& pip install --no-compile --no-cache-dir \
ansible==5.7.1 \
ansible-core==2.12.5 \
cryptography==3.4.8 \
jinja2==3.1.2 \
netaddr==0.8.0 \
jmespath==1.0.1 \
MarkupSafe==2.1.2 \
ruamel.yaml==0.17.21 \
&& 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 \
&& 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 /usr/local/bin/kubectl \
&& rm -rf /var/lib/apt/lists/* /var/log/* \
&& find /usr -type d -name '*__pycache__' -prune -exec rm -rf {} \;

View File

@@ -1,24 +1,30 @@
aliases: aliases:
kubespray-approvers: kubespray-approvers:
- cristicalin
- floryut
- liupeng0518
- mzaian
- oomichi
- yankay
kubespray-reviewers:
- cyclinder
- erikjiang
- mrfreezeex
- mzaian
- vannten
- yankay
kubespray-emeritus_approvers:
- ant31
- atoms
- chadswen
- luckysb
- mattymo - mattymo
- chadswen
- mirwan
- miouge1 - miouge1
- luckysb
- floryut
- oomichi
- cristicalin
- liupeng0518
- yankay
- mzaian
kubespray-reviewers:
- holmsten
- bozzo
- eppo
- oomichi
- jayonlau
- cristicalin
- liupeng0518
- yankay
- cyclinder
- mzaian
- mrfreezeex
kubespray-emeritus_approvers:
- riverzhang - riverzhang
- atoms
- ant31
- woopstar - woopstar

164
README.md
View File

@@ -1,5 +1,3 @@
TEST CI
# Deploy a Production Ready Kubernetes Cluster # Deploy a Production Ready Kubernetes Cluster
![Kubernetes Logo](https://raw.githubusercontent.com/kubernetes-sigs/kubespray/master/docs/img/kubernetes-logo.png) ![Kubernetes Logo](https://raw.githubusercontent.com/kubernetes-sigs/kubespray/master/docs/img/kubernetes-logo.png)
@@ -7,7 +5,7 @@ TEST CI
If you have questions, check the documentation at [kubespray.io](https://kubespray.io) and join us on the [kubernetes slack](https://kubernetes.slack.com), channel **\#kubespray**. If you have questions, check the documentation at [kubespray.io](https://kubespray.io) and join us on the [kubernetes slack](https://kubernetes.slack.com), channel **\#kubespray**.
You can get your invite [here](http://slack.k8s.io/) You can get your invite [here](http://slack.k8s.io/)
- Can be deployed on **[AWS](docs/cloud_providers/aws.md), GCE, [Azure](docs/cloud_providers/azure.md), [OpenStack](docs/cloud_providers/openstack.md), [vSphere](docs/cloud_providers/vsphere.md), [Equinix Metal](docs/cloud_providers/equinix-metal.md) (bare metal), Oracle Cloud Infrastructure (Experimental), or Baremetal** - Can be deployed on **[AWS](docs/aws.md), GCE, [Azure](docs/azure.md), [OpenStack](docs/openstack.md), [vSphere](docs/vsphere.md), [Equinix Metal](docs/equinix-metal.md) (bare metal), Oracle Cloud Infrastructure (Experimental), or Baremetal**
- **Highly available** cluster - **Highly available** cluster
- **Composable** (Choice of the network plugin for instance) - **Composable** (Choice of the network plugin for instance)
- Supports most popular **Linux distributions** - Supports most popular **Linux distributions**
@@ -21,7 +19,7 @@ Below are several ways to use Kubespray to deploy a Kubernetes cluster.
#### Usage #### Usage
Install Ansible according to [Ansible installation guide](/docs/ansible/ansible.md#installing-ansible) Install Ansible according to [Ansible installation guide](/docs/ansible.md#installing-ansible)
then run the following steps: then run the following steps:
```ShellSession ```ShellSession
@@ -36,7 +34,7 @@ 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 Kubernetes cluster with Ansible Playbook - run the playbook as root # 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/, # The option `--become` is required, as for example cleaning up SSL keys in /etc/,
# uninstalling old packages and interacting with various systemd daemons. # uninstalling old packages and interacting with various systemd daemons.
# Without --become the playbook will fail to run! # Without --become the playbook will fail to run!
@@ -77,18 +75,18 @@ 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.25.0 git checkout v2.22.2
docker pull quay.io/kubespray/kubespray:v2.25.0 docker pull quay.io/kubespray/kubespray:v2.22.2
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.25.0 bash quay.io/kubespray/kubespray:v2.22.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 #### Collection
See [here](docs/ansible/ansible_collection.md) if you wish to use this repository as an Ansible collection See [here](docs/ansible_collection.md) if you wish to use this repository as an Ansible collection
### Vagrant ### Vagrant
@@ -101,7 +99,7 @@ python -V && pip -V
If this returns the version of the software, you're good to go. If not, download and install Python from here <https://www.python.org/downloads/source/> If this returns the version of the software, you're good to go. If not, download and install Python from here <https://www.python.org/downloads/source/>
Install Ansible according to [Ansible installation guide](/docs/ansible/ansible.md#installing-ansible) Install Ansible according to [Ansible installation guide](/docs/ansible.md#installing-ansible)
then run the following step: then run the following step:
```ShellSession ```ShellSession
@@ -111,79 +109,80 @@ vagrant up
## Documents ## Documents
- [Requirements](#requirements) - [Requirements](#requirements)
- [Kubespray vs ...](docs/getting_started/comparisons.md) - [Kubespray vs ...](docs/comparisons.md)
- [Getting started](docs/getting_started/getting-started.md) - [Getting started](docs/getting-started.md)
- [Setting up your first cluster](docs/getting_started/setting-up-your-first-cluster.md) - [Setting up your first cluster](docs/setting-up-your-first-cluster.md)
- [Ansible inventory and tags](docs/ansible/ansible.md) - [Ansible inventory and tags](docs/ansible.md)
- [Integration with existing ansible repo](docs/operations/integration.md) - [Integration with existing ansible repo](docs/integration.md)
- [Deployment data variables](docs/ansible/vars.md) - [Deployment data variables](docs/vars.md)
- [DNS stack](docs/advanced/dns-stack.md) - [DNS stack](docs/dns-stack.md)
- [HA mode](docs/operations/ha-mode.md) - [HA mode](docs/ha-mode.md)
- [Network plugins](#network-plugins) - [Network plugins](#network-plugins)
- [Vagrant install](docs/developers/vagrant.md) - [Vagrant install](docs/vagrant.md)
- [Flatcar Container Linux bootstrap](docs/operating_systems/flatcar.md) - [Flatcar Container Linux bootstrap](docs/flatcar.md)
- [Fedora CoreOS bootstrap](docs/operating_systems/fcos.md) - [Fedora CoreOS bootstrap](docs/fcos.md)
- [openSUSE setup](docs/operating_systems/opensuse.md) - [Debian Jessie setup](docs/debian.md)
- [Downloaded artifacts](docs/advanced/downloads.md) - [openSUSE setup](docs/opensuse.md)
- [Cloud providers](docs/cloud_providers/cloud.md) - [Downloaded artifacts](docs/downloads.md)
- [OpenStack](docs/cloud_providers/openstack.md) - [Cloud providers](docs/cloud.md)
- [AWS](docs/cloud_providers/aws.md) - [OpenStack](docs/openstack.md)
- [Azure](docs/cloud_providers/azure.md) - [AWS](docs/aws.md)
- [vSphere](docs/cloud_providers/vsphere.md) - [Azure](docs/azure.md)
- [Equinix Metal](docs/cloud_providers/equinix-metal.md) - [vSphere](docs/vsphere.md)
- [Large deployments](docs/operations/large-deployments.md) - [Equinix Metal](docs/equinix-metal.md)
- [Adding/replacing a node](docs/operations/nodes.md) - [Large deployments](docs/large-deployments.md)
- [Upgrades basics](docs/operations/upgrades.md) - [Adding/replacing a node](docs/nodes.md)
- [Air-Gap installation](docs/operations/offline-environment.md) - [Upgrades basics](docs/upgrades.md)
- [NTP](docs/advanced/ntp.md) - [Air-Gap installation](docs/offline-environment.md)
- [Hardening](docs/operations/hardening.md) - [NTP](docs/ntp.md)
- [Mirror](docs/operations/mirror.md) - [Hardening](docs/hardening.md)
- [Roadmap](docs/roadmap/roadmap.md) - [Mirror](docs/mirror.md)
- [Roadmap](docs/roadmap.md)
## Supported Linux Distributions ## Supported Linux Distributions
- **Flatcar Container Linux by Kinvolk** - **Flatcar Container Linux by Kinvolk**
- **Debian** Bookworm, Bullseye, Buster - **Debian** Bullseye, Buster
- **Ubuntu** 20.04, 22.04 - **Ubuntu** 16.04, 18.04, 20.04, 22.04
- **CentOS/RHEL** 7, [8, 9](docs/operating_systems/centos.md#centos-8) - **CentOS/RHEL** 7, [8, 9](docs/centos.md#centos-8)
- **Fedora** 37, 38 - **Fedora** 37, 38
- **Fedora CoreOS** (see [fcos Note](docs/operating_systems/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/operating_systems/centos.md#centos-8) - **Oracle Linux** 7, [8, 9](docs/centos.md#centos-8)
- **Alma Linux** [8, 9](docs/operating_systems/centos.md#centos-8) - **Alma Linux** [8, 9](docs/centos.md#centos-8)
- **Rocky Linux** [8, 9](docs/operating_systems/centos.md#centos-8) - **Rocky Linux** [8, 9](docs/centos.md#centos-8)
- **Kylin Linux Advanced Server V10** (experimental: see [kylin linux notes](docs/operating_systems/kylinlinux.md)) - **Kylin Linux Advanced Server V10** (experimental: see [kylin linux notes](docs/kylinlinux.md))
- **Amazon Linux 2** (experimental: see [amazon linux notes](docs/operating_systems/amazonlinux.md)) - **Amazon Linux 2** (experimental: see [amazon linux notes](docs/amazonlinux.md))
- **UOS Linux** (experimental: see [uos linux notes](docs/operating_systems/uoslinux.md)) - **UOS Linux** (experimental: see [uos linux notes](docs/uoslinux.md))
- **openEuler** (experimental: see [openEuler notes](docs/operating_systems/openeuler.md)) - **openEuler** (experimental: see [openEuler notes](docs/openeuler.md))
Note: Upstart/SysV init based OS types are not supported. Note: Upstart/SysV init based OS types are not supported.
## Supported Components ## Supported Components
- Core - Core
- [kubernetes](https://github.com/kubernetes/kubernetes) v1.29.5 - [kubernetes](https://github.com/kubernetes/kubernetes) v1.26.13
- [etcd](https://github.com/etcd-io/etcd) v3.5.12 - [etcd](https://github.com/etcd-io/etcd) v3.5.6
- [docker](https://www.docker.com/) v24.0 (see [Note](#container-runtime-notes)) - [docker](https://www.docker.com/) v20.10 (see note)
- [containerd](https://containerd.io/) v1.7.16 - [containerd](https://containerd.io/) v1.7.13
- [cri-o](http://cri-o.io/) v1.29.1 (experimental: see [CRI-O Note](docs/CRI/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.27.3 - [calico](https://github.com/projectcalico/calico) v3.25.1
- [cilium](https://github.com/cilium/cilium) v1.15.4 - [cilium](https://github.com/cilium/cilium) v1.13.0
- [flannel](https://github.com/flannel-io/flannel) v0.22.0 - [flannel](https://github.com/flannel-io/flannel) v0.21.4
- [kube-ovn](https://github.com/alauda/kube-ovn) v1.11.5 - [kube-ovn](https://github.com/alauda/kube-ovn) v1.10.7
- [kube-router](https://github.com/cloudnativelabs/kube-router) v2.0.0 - [kube-router](https://github.com/cloudnativelabs/kube-router) v1.5.1
- [multus](https://github.com/k8snetworkplumbingwg/multus-cni) v3.8 - [multus](https://github.com/k8snetworkplumbingwg/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.8.0 - [kube-vip](https://github.com/kube-vip/kube-vip) v0.5.12
- Application - Application
- [cert-manager](https://github.com/jetstack/cert-manager) v1.13.2 - [cert-manager](https://github.com/jetstack/cert-manager) v1.11.1
- [coredns](https://github.com/coredns/coredns) v1.11.1 - [coredns](https://github.com/coredns/coredns) v1.9.3
- [ingress-nginx](https://github.com/kubernetes/ingress-nginx) v1.10.1 - [ingress-nginx](https://github.com/kubernetes/ingress-nginx) v1.7.1
- [krew](https://github.com/kubernetes-sigs/krew) v0.4.4 - [krew](https://github.com/kubernetes-sigs/krew) v0.4.3
- [argocd](https://argoproj.github.io/) v2.11.0 - [argocd](https://argoproj.github.io/) v2.7.2
- [helm](https://helm.sh/) v3.14.2 - [helm](https://helm.sh/) v3.12.0
- [metallb](https://metallb.universe.tf/) v0.13.9 - [metallb](https://metallb.universe.tf/) v0.13.9
- [registry](https://github.com/distribution/distribution) v2.8.1 - [registry](https://github.com/distribution/distribution) v2.8.1
- Storage Plugin - Storage Plugin
@@ -191,22 +190,21 @@ Note: Upstart/SysV init based OS types are not supported.
- [rbd-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.1-k8s1.11 - [rbd-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.1-k8s1.11
- [aws-ebs-csi-plugin](https://github.com/kubernetes-sigs/aws-ebs-csi-driver) v0.5.0 - [aws-ebs-csi-plugin](https://github.com/kubernetes-sigs/aws-ebs-csi-driver) v0.5.0
- [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.29.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.9.2 - [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.24 - [local-path-provisioner](https://github.com/rancher/local-path-provisioner) v0.0.23
- [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
- [node-feature-discovery](https://github.com/kubernetes-sigs/node-feature-discovery) v0.14.2
## Container Runtime Notes ## Container Runtime Notes
- Supported Docker versions are 18.09, 19.03, 20.10, 23.0 and 24.0. The *recommended* Docker version is 24.0. `Kubelet` might break on docker's non-standard version numbering (it no longer uses semantic versioning). To ensure auto-updates don't break your cluster look into e.g. the YUM ``versionlock`` plugin or ``apt pin``). - Supported Docker versions are 18.09, 19.03 and 20.10. The *recommended* Docker version is 20.10. `Kubelet` might break on docker's non-standard version numbering (it no longer uses semantic versioning). To ensure auto-updates don't break your cluster look into e.g. the YUM ``versionlock`` plugin or ``apt pin``).
- The cri-o version should be aligned with the respective kubernetes version (i.e. kube_version=1.20.x, crio_version=1.20) - The cri-o version should be aligned with the respective kubernetes version (i.e. kube_version=1.20.x, crio_version=1.20)
## Requirements ## Requirements
- **Minimum required version of Kubernetes is v1.28** - **Minimum required version of Kubernetes is v1.24**
- **Ansible v2.14+, 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/operations/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.
@@ -227,41 +225,41 @@ These limits are safeguarded by Kubespray. Actual requirements for your workload
You can choose among ten network plugins. (default: `calico`, except Vagrant uses `flannel`) You can choose among ten network plugins. (default: `calico`, except Vagrant uses `flannel`)
- [flannel](docs/CNI/flannel.md): gre/vxlan (layer 2) networking. - [flannel](docs/flannel.md): gre/vxlan (layer 2) networking.
- [Calico](https://docs.tigera.io/calico/latest/about/) is a networking and network policy provider. Calico supports a flexible set of networking options - [Calico](https://docs.projectcalico.org/latest/introduction/) is a networking and network policy provider. Calico supports a flexible set of networking options
designed to give you the most efficient networking across a range of situations, including non-overlay designed to give you the most efficient networking across a range of situations, including non-overlay
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.
- [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/CNI/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.
(Please refer to `weave` [troubleshooting documentation](https://www.weave.works/docs/net/latest/troubleshooting/)). (Please refer to `weave` [troubleshooting documentation](https://www.weave.works/docs/net/latest/troubleshooting/)).
- [kube-ovn](docs/CNI/kube-ovn.md): Kube-OVN integrates the OVN-based Network Virtualization with Kubernetes. It offers an advanced Container Network Fabric for Enterprises. - [kube-ovn](docs/kube-ovn.md): Kube-OVN integrates the OVN-based Network Virtualization with Kubernetes. It offers an advanced Container Network Fabric for Enterprises.
- [kube-router](docs/CNI/kube-router.md): Kube-router is a L3 CNI for Kubernetes networking aiming to provide operational - [kube-router](docs/kube-router.md): Kube-router is a L3 CNI for Kubernetes networking aiming to provide operational
simplicity and high performance: it uses IPVS to provide Kube Services Proxy (if setup to replace kube-proxy), simplicity and high performance: it uses IPVS to provide Kube Services Proxy (if setup to replace kube-proxy),
iptables for network policies, and BGP for ods L3 networking (with optionally BGP peering with out-of-cluster BGP peers). iptables for network policies, and BGP for ods L3 networking (with optionally BGP peering with out-of-cluster BGP peers).
It can also optionally advertise routes to Kubernetes cluster Pods CIDRs, ClusterIPs, ExternalIPs and LoadBalancerIPs. It can also optionally advertise routes to Kubernetes cluster Pods CIDRs, ClusterIPs, ExternalIPs and LoadBalancerIPs.
- [macvlan](docs/CNI/macvlan.md): Macvlan is a Linux network driver. Pods have their own unique Mac and Ip address, connected directly the physical (layer 2) network. - [macvlan](docs/macvlan.md): Macvlan is a Linux network driver. Pods have their own unique Mac and Ip address, connected directly the physical (layer 2) network.
- [multus](docs/CNI/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. - [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. 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/advanced/netcheck.md). See also [Network checker](docs/netcheck.md).
## Ingress Plugins ## Ingress Plugins
- [nginx](https://kubernetes.github.io/ingress-nginx): the NGINX Ingress Controller. - [nginx](https://kubernetes.github.io/ingress-nginx): the NGINX Ingress Controller.
- [metallb](docs/ingress/metallb.md): the MetalLB bare-metal service LoadBalancer provider. - [metallb](docs/metallb.md): the MetalLB bare-metal service LoadBalancer provider.
## Community docs and resources ## Community docs and resources
@@ -282,4 +280,4 @@ See also [Network checker](docs/advanced/netcheck.md).
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/).
See the [test matrix](docs/developers/test_cases.md) for details. See the [test matrix](docs/test_cases.md) for details.

View File

@@ -3,19 +3,17 @@
The Kubespray Project is released on an as-needed basis. The process is as follows: The Kubespray Project is released on an as-needed basis. The process is as follows:
1. An issue is proposing a new release with a changelog since the last release. Please see [a good sample issue](https://github.com/kubernetes-sigs/kubespray/issues/8325) 1. An issue is proposing a new release with a changelog since the last release. Please see [a good sample issue](https://github.com/kubernetes-sigs/kubespray/issues/8325)
1. At least one of the [approvers](OWNERS_ALIASES) must approve this release 2. At least one of the [approvers](OWNERS_ALIASES) must approve this release
1. (Only for major releases) The `kube_version_min_required` variable is set to `n-1` 3. The `kube_version_min_required` variable is set to `n-1`
1. (Only for major releases) Remove hashes for [EOL versions](https://github.com/kubernetes/website/blob/main/content/en/releases/patch-releases.md) of kubernetes from `*_checksums` variables. 4. Remove hashes for [EOL versions](https://github.com/kubernetes/website/blob/main/content/en/releases/patch-releases.md) of kubernetes from `*_checksums` variables.
1. Create the release note with [Kubernetes Release Notes Generator](https://github.com/kubernetes/release/blob/master/cmd/release-notes/README.md). See the following `Release note creation` section for the details. 5. Create the release note with [Kubernetes Release Notes Generator](https://github.com/kubernetes/release/blob/master/cmd/release-notes/README.md). See the following `Release note creation` section for the details.
1. An approver creates [new release in GitHub](https://github.com/kubernetes-sigs/kubespray/releases/new) using a version and tag name like `vX.Y.Z` and attaching the release notes 6. An approver creates [new release in GitHub](https://github.com/kubernetes-sigs/kubespray/releases/new) using a version and tag name like `vX.Y.Z` and attaching the release notes
1. (Only for major releases) An approver creates a release branch in the form `release-X.Y` 7. An approver creates a release branch in the form `release-X.Y`
1. (For major releases) On the `master` branch: bump the version in `galaxy.yml` to the next expected major release (X.y.0 with y = Y + 1), make a Pull Request. 8. The corresponding version of [quay.io/kubespray/kubespray:vX.Y.Z](https://quay.io/repository/kubespray/kubespray) and [quay.io/kubespray/vagrant:vX.Y.Z](https://quay.io/repository/kubespray/vagrant) container images are built and tagged. See the following `Container image creation` section for the details.
1. (For minor releases) On the `release-X.Y` branch: bump the version in `galaxy.yml` to the next expected minor release (X.Y.z with z = Z + 1), make a Pull Request. 9. The `KUBESPRAY_VERSION` variable is updated in `.gitlab-ci.yml`
1. The corresponding version of [quay.io/kubespray/kubespray:vX.Y.Z](https://quay.io/repository/kubespray/kubespray) and [quay.io/kubespray/vagrant:vX.Y.Z](https://quay.io/repository/kubespray/vagrant) container images are built and tagged. See the following `Container image creation` section for the details. 10. The release issue is closed
1. (Only for major releases) The `KUBESPRAY_VERSION` in `.gitlab-ci.yml` is upgraded to the version we just released # TODO clarify this, this variable is for testing upgrades. 11. An announcement email is sent to `dev@kubernetes.io` with the subject `[ANNOUNCE] Kubespray $VERSION is released`
1. The release issue is closed 12. The topic of the #kubespray channel is updated with `vX.Y.Z is released! | ...`
1. An announcement email is sent to `dev@kubernetes.io` with the subject `[ANNOUNCE] Kubespray $VERSION is released`
1. The topic of the #kubespray channel is updated with `vX.Y.Z is released! | ...`
## Major/minor releases and milestones ## Major/minor releases and milestones

41
Vagrantfile vendored
View File

@@ -19,17 +19,16 @@ SUPPORTED_OS = {
"flatcar-beta" => {box: "flatcar-beta", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["beta"]}, "flatcar-beta" => {box: "flatcar-beta", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["beta"]},
"flatcar-alpha" => {box: "flatcar-alpha", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["alpha"]}, "flatcar-alpha" => {box: "flatcar-alpha", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["alpha"]},
"flatcar-edge" => {box: "flatcar-edge", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["edge"]}, "flatcar-edge" => {box: "flatcar-edge", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["edge"]},
"ubuntu1604" => {box: "generic/ubuntu1604", user: "vagrant"},
"ubuntu1804" => {box: "generic/ubuntu1804", user: "vagrant"},
"ubuntu2004" => {box: "generic/ubuntu2004", user: "vagrant"}, "ubuntu2004" => {box: "generic/ubuntu2004", user: "vagrant"},
"ubuntu2204" => {box: "generic/ubuntu2204", user: "vagrant"},
"ubuntu2404" => {box: "bento/ubuntu-24.04", user: "vagrant"},
"centos" => {box: "centos/7", user: "vagrant"}, "centos" => {box: "centos/7", user: "vagrant"},
"centos-bento" => {box: "bento/centos-7.6", user: "vagrant"}, "centos-bento" => {box: "bento/centos-7.6", user: "vagrant"},
"centos8" => {box: "centos/8", user: "vagrant"}, "centos8" => {box: "centos/8", user: "vagrant"},
"centos8-bento" => {box: "bento/centos-8", user: "vagrant"}, "centos8-bento" => {box: "bento/centos-8", user: "vagrant"},
"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: "rockylinux/8", user: "vagrant"}, "rockylinux8" => {box: "generic/rocky8", user: "vagrant"},
"rockylinux9" => {box: "rockylinux/9", user: "vagrant"},
"fedora37" => {box: "fedora/37-cloud-base", user: "vagrant"}, "fedora37" => {box: "fedora/37-cloud-base", user: "vagrant"},
"fedora38" => {box: "fedora/38-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"},
@@ -38,8 +37,6 @@ SUPPORTED_OS = {
"oraclelinux8" => {box: "generic/oracle8", user: "vagrant"}, "oraclelinux8" => {box: "generic/oracle8", user: "vagrant"},
"rhel7" => {box: "generic/rhel7", user: "vagrant"}, "rhel7" => {box: "generic/rhel7", user: "vagrant"},
"rhel8" => {box: "generic/rhel8", user: "vagrant"}, "rhel8" => {box: "generic/rhel8", user: "vagrant"},
"debian11" => {box: "debian/bullseye64", user: "vagrant"},
"debian12" => {box: "debian/bookworm64", user: "vagrant"},
} }
if File.exist?(CONFIG) if File.exist?(CONFIG)
@@ -56,7 +53,7 @@ $shared_folders ||= {}
$forwarded_ports ||= {} $forwarded_ports ||= {}
$subnet ||= "172.18.8" $subnet ||= "172.18.8"
$subnet_ipv6 ||= "fd3c:b398:0698:0756" $subnet_ipv6 ||= "fd3c:b398:0698:0756"
$os ||= "ubuntu2004" $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/k8snetworkplumbingwg/multus-cni
$multi_networking ||= "False" $multi_networking ||= "False"
@@ -81,10 +78,7 @@ $libvirt_nested ||= false
$ansible_verbosity ||= false $ansible_verbosity ||= false
$ansible_tags ||= ENV['VAGRANT_ANSIBLE_TAGS'] || "" $ansible_tags ||= ENV['VAGRANT_ANSIBLE_TAGS'] || ""
$vagrant_dir ||= File.join(File.dirname(__FILE__), ".vagrant")
$playbook ||= "cluster.yml" $playbook ||= "cluster.yml"
$extra_vars ||= {}
host_vars = {} host_vars = {}
@@ -103,7 +97,7 @@ $inventory = File.absolute_path($inventory, File.dirname(__FILE__))
# if $inventory has a hosts.ini file use it, otherwise copy over # if $inventory has a hosts.ini file use it, otherwise copy over
# vars etc to where vagrant expects dynamic inventory to be # vars etc to where vagrant expects dynamic inventory to be
if ! File.exist?(File.join(File.dirname($inventory), "hosts.ini")) if ! File.exist?(File.join(File.dirname($inventory), "hosts.ini"))
$vagrant_ansible = File.join(File.absolute_path($vagrant_dir), "provisioners", "ansible") $vagrant_ansible = File.join(File.dirname(__FILE__), ".vagrant", "provisioners", "ansible")
FileUtils.mkdir_p($vagrant_ansible) if ! File.exist?($vagrant_ansible) FileUtils.mkdir_p($vagrant_ansible) if ! File.exist?($vagrant_ansible)
$vagrant_inventory = File.join($vagrant_ansible,"inventory") $vagrant_inventory = File.join($vagrant_ansible,"inventory")
FileUtils.rm_f($vagrant_inventory) FileUtils.rm_f($vagrant_inventory)
@@ -189,14 +183,6 @@ Vagrant.configure("2") do |config|
lv.storage :file, :device => "hd#{driverletters[d]}", :path => "disk-#{i}-#{d}-#{DISK_UUID}.disk", :size => $kube_node_instances_with_disks_size, :bus => "scsi" lv.storage :file, :device => "hd#{driverletters[d]}", :path => "disk-#{i}-#{d}-#{DISK_UUID}.disk", :size => $kube_node_instances_with_disks_size, :bus => "scsi"
end end
end end
node.vm.provider :virtualbox do |vb|
# always make /dev/sd{a/b/c} so that CI can ensure that
# virtualbox and libvirt will have the same devices to use for OSDs
(1..$kube_node_instances_with_disks_number).each do |d|
vb.customize ['createhd', '--filename', "disk-#{i}-#{driverletters[d]}-#{DISK_UUID}.disk", '--size', $kube_node_instances_with_disks_size] # 10GB disk
vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', d, '--device', 0, '--type', 'hdd', '--medium', "disk-#{i}-#{driverletters[d]}-#{DISK_UUID}.disk", '--nonrotational', 'on', '--mtype', 'normal']
end
end
end end
if $expose_docker_tcp if $expose_docker_tcp
@@ -233,8 +219,8 @@ Vagrant.configure("2") do |config|
# Disable swap for each vm # Disable swap for each vm
node.vm.provision "shell", inline: "swapoff -a" node.vm.provision "shell", inline: "swapoff -a"
# ubuntu2004 and ubuntu2204 have IPv6 explicitly disabled. This undoes that. # ubuntu1804 and ubuntu2004 have IPv6 explicitly disabled. This undoes that.
if ["ubuntu2004", "ubuntu2204"].include? $os if ["ubuntu1804", "ubuntu2004"].include? $os
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
@@ -247,15 +233,8 @@ Vagrant.configure("2") do |config|
SHELL SHELL
end end
# Rockylinux boxes needs UEFI
if ["rockylinux8", "rockylinux9"].include? $os
config.vm.provider "libvirt" do |domain|
domain.loader = "/usr/share/OVMF/x64/OVMF_CODE.fd"
end
end
# Disable firewalld on oraclelinux/redhat vms # Disable firewalld on oraclelinux/redhat vms
if ["oraclelinux","oraclelinux8","rhel7","rhel8","rockylinux8"].include? $os if ["oraclelinux","oraclelinux8","rhel7","rhel8"].include? $os
node.vm.provision "shell", inline: "systemctl stop firewalld; systemctl disable firewalld" node.vm.provision "shell", inline: "systemctl stop firewalld; systemctl disable firewalld"
end end
@@ -277,8 +256,7 @@ Vagrant.configure("2") do |config|
"kubectl_localhost": "True", "kubectl_localhost": "True",
"local_path_provisioner_enabled": "#{$local_path_provisioner_enabled}", "local_path_provisioner_enabled": "#{$local_path_provisioner_enabled}",
"local_path_provisioner_claim_root": "#{$local_path_provisioner_claim_root}", "local_path_provisioner_claim_root": "#{$local_path_provisioner_claim_root}",
"ansible_ssh_user": SUPPORTED_OS[$os][:user], "ansible_ssh_user": SUPPORTED_OS[$os][:user]
"unsafe_show_logs": "True"
} }
# Only execute the Ansible provisioner once, when all the machines are up and ready. # Only execute the Ansible provisioner once, when all the machines are up and ready.
@@ -297,7 +275,6 @@ Vagrant.configure("2") do |config|
ansible.host_key_checking = false ansible.host_key_checking = false
ansible.raw_arguments = ["--forks=#{$num_instances}", "--flush-cache", "-e ansible_become_pass=vagrant"] ansible.raw_arguments = ["--forks=#{$num_instances}", "--flush-cache", "-e ansible_become_pass=vagrant"]
ansible.host_vars = host_vars ansible.host_vars = host_vars
ansible.extra_vars = $extra_vars
if $ansible_tags != "" if $ansible_tags != ""
ansible.tags = [$ansible_tags] ansible.tags = [$ansible_tags]
end end

View File

@@ -1,6 +1,6 @@
[ssh_connection] [ssh_connection]
pipelining=True pipelining=True
ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o ConnectionAttempts=100 -o UserKnownHostsFile=/dev/null ansible_ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o ConnectionAttempts=100 -o UserKnownHostsFile=/dev/null
#control_path = ~/.ssh/ansible-%%r@%%h:%%p #control_path = ~/.ssh/ansible-%%r@%%h:%%p
[defaults] [defaults]
# https://github.com/ansible/ansible/issues/56930 (to ignore group names with - and .) # https://github.com/ansible/ansible/issues/56930 (to ignore group names with - and .)

View File

@@ -39,7 +39,7 @@ class SearchEC2Tags(object):
hosts[group] = [] hosts[group] = []
tag_key = "kubespray-role" tag_key = "kubespray-role"
tag_value = ["*"+group+"*"] tag_value = ["*"+group+"*"]
region = os.environ['AWS_REGION'] region = os.environ['REGION']
ec2 = boto3.resource('ec2', region) ec2 = boto3.resource('ec2', region)
filters = [{'Name': 'tag:'+tag_key, 'Values': tag_value}, {'Name': 'instance-state-name', 'Values': ['running']}] filters = [{'Name': 'tag:'+tag_key, 'Values': tag_value}, {'Name': 'instance-state-name', 'Values': ['running']}]
@@ -67,11 +67,6 @@ class SearchEC2Tags(object):
if node_labels_tag: if node_labels_tag:
ansible_host['node_labels'] = dict([ label.strip().split('=') for label in node_labels_tag[0]['Value'].split(',') ]) ansible_host['node_labels'] = dict([ label.strip().split('=') for label in node_labels_tag[0]['Value'].split(',') ])
##Set when instance actually has node_taints
node_taints_tag = list(filter(lambda t: t['Key'] == 'kubespray-node-taints', instance.tags))
if node_taints_tag:
ansible_host['node_taints'] = list([ taint.strip() for taint in node_taints_tag[0]['Value'].split(',') ])
hosts[group].append(dns_name) hosts[group].append(dns_name)
hosts['_meta']['hostvars'][dns_name] = ansible_host hosts['_meta']['hostvars'][dns_name] = ansible_host

View File

@@ -49,7 +49,7 @@ If you need to delete all resources from a resource group, simply call:
## Installing Ansible and the dependencies ## Installing Ansible and the dependencies
Install Ansible according to [Ansible installation guide](/docs/ansible/ansible.md#installing-ansible) Install Ansible according to [Ansible installation guide](/docs/ansible.md#installing-ansible)
## Generating an inventory for kubespray ## Generating an inventory for kubespray

View File

@@ -1,6 +1,5 @@
--- ---
- name: Generate Azure inventory - hosts: localhost
hosts: localhost
gather_facts: False gather_facts: False
roles: roles:
- generate-inventory - generate-inventory

View File

@@ -1,6 +1,5 @@
--- ---
- name: Generate Azure inventory - hosts: localhost
hosts: localhost
gather_facts: False gather_facts: False
roles: roles:
- generate-inventory_2 - generate-inventory_2

View File

@@ -1,6 +1,5 @@
--- ---
- name: Generate Azure templates - hosts: localhost
hosts: localhost
gather_facts: False gather_facts: False
roles: roles:
- generate-templates - generate-templates

View File

@@ -1,6 +1,6 @@
--- ---
- name: Query Azure VMs - name: Query Azure VMs # noqa 301
command: azure vm list-ip-address --json {{ azure_resource_group }} command: azure vm list-ip-address --json {{ azure_resource_group }}
register: vm_list_cmd register: vm_list_cmd

View File

@@ -1,14 +1,14 @@
--- ---
- name: Query Azure VMs IPs - name: Query Azure VMs IPs # noqa 301
command: az vm list-ip-addresses -o json --resource-group {{ azure_resource_group }} command: az vm list-ip-addresses -o json --resource-group {{ azure_resource_group }}
register: vm_ip_list_cmd register: vm_ip_list_cmd
- name: Query Azure VMs Roles - name: Query Azure VMs Roles # noqa 301
command: az vm list -o json --resource-group {{ azure_resource_group }} command: az vm list -o json --resource-group {{ azure_resource_group }}
register: vm_list_cmd register: vm_list_cmd
- name: Query Azure Load Balancer Public IP - name: Query Azure Load Balancer Public IP # noqa 301
command: az network public-ip show -o json -g {{ azure_resource_group }} -n kubernetes-api-pubip command: az network public-ip show -o json -g {{ azure_resource_group }} -n kubernetes-api-pubip
register: lb_pubip_cmd register: lb_pubip_cmd

View File

@@ -24,14 +24,14 @@ bastionIPAddressName: bastion-pubip
disablePasswordAuthentication: true disablePasswordAuthentication: true
sshKeyPath: "/home/{{ admin_username }}/.ssh/authorized_keys" sshKeyPath: "/home/{{admin_username}}/.ssh/authorized_keys"
imageReference: imageReference:
publisher: "OpenLogic" publisher: "OpenLogic"
offer: "CentOS" offer: "CentOS"
sku: "7.5" sku: "7.5"
version: "latest" version: "latest"
imageReferenceJson: "{{ imageReference | to_json }}" imageReferenceJson: "{{imageReference|to_json}}"
storageAccountName: "sa{{ nameSuffix | replace('-', '') }}" storageAccountName: "sa{{nameSuffix | replace('-', '')}}"
storageAccountType: "{{ azure_storage_account_type | default('Standard_LRS') }}" storageAccountType: "{{ azure_storage_account_type | default('Standard_LRS') }}"

View File

@@ -1,11 +1,9 @@
--- ---
- name: Create nodes as docker containers - hosts: localhost
hosts: localhost
gather_facts: False gather_facts: False
roles: roles:
- { role: dind-host } - { role: dind-host }
- name: Customize each node containers - hosts: containers
hosts: containers
roles: roles:
- { role: dind-cluster } - { role: dind-cluster }

View File

@@ -1,9 +1,9 @@
--- ---
- name: Set_fact distro_setup - name: set_fact distro_setup
set_fact: set_fact:
distro_setup: "{{ distro_settings[node_distro] }}" distro_setup: "{{ distro_settings[node_distro] }}"
- name: Set_fact other distro settings - name: set_fact other distro settings
set_fact: set_fact:
distro_user: "{{ distro_setup['user'] }}" distro_user: "{{ distro_setup['user'] }}"
distro_ssh_service: "{{ distro_setup['ssh_service'] }}" distro_ssh_service: "{{ distro_setup['ssh_service'] }}"
@@ -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:
@@ -66,8 +66,8 @@
dest: "/etc/sudoers.d/{{ distro_user }}" dest: "/etc/sudoers.d/{{ distro_user }}"
mode: 0640 mode: 0640
- name: "Add my pubkey to {{ distro_user }} user authorized keys" - name: Add my pubkey to "{{ distro_user }}" user authorized keys
ansible.posix.authorized_key: authorized_key:
user: "{{ distro_user }}" user: "{{ distro_user }}"
state: present state: present
key: "{{ lookup('file', lookup('env', 'HOME') + '/.ssh/id_rsa.pub') }}" key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"

View File

@@ -1,9 +1,9 @@
--- ---
- name: Set_fact distro_setup - name: set_fact distro_setup
set_fact: set_fact:
distro_setup: "{{ distro_settings[node_distro] }}" distro_setup: "{{ distro_settings[node_distro] }}"
- name: Set_fact other distro settings - name: set_fact other distro settings
set_fact: set_fact:
distro_image: "{{ distro_setup['image'] }}" distro_image: "{{ distro_setup['image'] }}"
distro_init: "{{ distro_setup['init'] }}" distro_init: "{{ distro_setup['init'] }}"
@@ -13,7 +13,7 @@
distro_agetty_svc: "{{ distro_setup['agetty_svc'] }}" distro_agetty_svc: "{{ distro_setup['agetty_svc'] }}"
- name: Create dind node containers from "containers" inventory section - name: Create dind node containers from "containers" inventory section
community.docker.docker_container: docker_container:
image: "{{ distro_image }}" image: "{{ distro_image }}"
name: "{{ item }}" name: "{{ item }}"
state: started state: started
@@ -53,7 +53,7 @@
{{ distro_raw_setup_done }} && echo SKIPPED && exit 0 {{ distro_raw_setup_done }} && echo SKIPPED && exit 0
until [ "$(readlink /proc/1/exe)" = "{{ distro_pid1_exe }}" ] ; do sleep 1; done until [ "$(readlink /proc/1/exe)" = "{{ distro_pid1_exe }}" ] ; do sleep 1; done
{{ distro_raw_setup }} {{ distro_raw_setup }}
delegate_to: "{{ item._ansible_item_label | default(item.item) }}" delegate_to: "{{ item._ansible_item_label|default(item.item) }}"
with_items: "{{ containers.results }}" with_items: "{{ containers.results }}"
register: result register: result
changed_when: result.stdout.find("SKIPPED") < 0 changed_when: result.stdout.find("SKIPPED") < 0
@@ -63,25 +63,26 @@
until test -S /var/run/dbus/system_bus_socket; do sleep 1; done until test -S /var/run/dbus/system_bus_socket; do sleep 1; done
systemctl disable {{ distro_agetty_svc }} systemctl disable {{ distro_agetty_svc }}
systemctl stop {{ distro_agetty_svc }} systemctl stop {{ distro_agetty_svc }}
delegate_to: "{{ item._ansible_item_label | default(item.item) }}" delegate_to: "{{ item._ansible_item_label|default(item.item) }}"
with_items: "{{ containers.results }}" with_items: "{{ containers.results }}"
changed_when: false changed_when: false
# Running systemd-machine-id-setup doesn't create a unique id for each node container on Debian, # Running systemd-machine-id-setup doesn't create a unique id for each node container on Debian,
# handle manually # handle manually
- name: Re-create unique machine-id (as we may just get what comes in the docker image), needed by some CNIs for mac address seeding (notably weave) - name: Re-create unique machine-id (as we may just get what comes in the docker image), needed by some CNIs for mac address seeding (notably weave) # noqa 301
raw: | raw: |
echo {{ item | hash('sha1') }} > /etc/machine-id.new echo {{ item | hash('sha1') }} > /etc/machine-id.new
mv -b /etc/machine-id.new /etc/machine-id mv -b /etc/machine-id.new /etc/machine-id
cmp /etc/machine-id /etc/machine-id~ || true cmp /etc/machine-id /etc/machine-id~ || true
systemctl daemon-reload systemctl daemon-reload
delegate_to: "{{ item._ansible_item_label | default(item.item) }}" delegate_to: "{{ item._ansible_item_label|default(item.item) }}"
with_items: "{{ containers.results }}" with_items: "{{ containers.results }}"
- name: Early hack image install to adapt for DIND - name: Early hack image install to adapt for DIND
# noqa 302 - this task uses the raw module intentionally
raw: | raw: |
rm -fv /usr/bin/udevadm /usr/sbin/udevadm rm -fv /usr/bin/udevadm /usr/sbin/udevadm
delegate_to: "{{ item._ansible_item_label | default(item.item) }}" delegate_to: "{{ item._ansible_item_label|default(item.item) }}"
with_items: "{{ containers.results }}" with_items: "{{ containers.results }}"
register: result register: result
changed_when: result.stdout.find("removed") >= 0 changed_when: result.stdout.find("removed") >= 0

View File

@@ -1,27 +1,21 @@
[tox] [tox]
minversion = 1.6 minversion = 1.6
skipsdist = True skipsdist = True
envlist = pep8 envlist = pep8, py33
[testenv] [testenv]
allowlist_externals = py.test whitelist_externals = py.test
usedevelop = True usedevelop = True
deps = deps =
-r{toxinidir}/requirements.txt -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
setenv = VIRTUAL_ENV={envdir} setenv = VIRTUAL_ENV={envdir}
passenv = passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY
http_proxy
HTTP_PROXY
https_proxy
HTTPS_PROXY
no_proxy
NO_PROXY
commands = pytest -vv #{posargs:./tests} commands = pytest -vv #{posargs:./tests}
[testenv:pep8] [testenv:pep8]
usedevelop = False usedevelop = False
allowlist_externals = bash whitelist_externals = bash
commands = commands =
bash -c "find {toxinidir}/* -type f -name '*.py' -print0 | xargs -0 flake8" bash -c "find {toxinidir}/* -type f -name '*.py' -print0 | xargs -0 flake8"

View File

@@ -1,9 +1,8 @@
--- ---
- name: Prepare Hypervisor to later install kubespray VMs - hosts: localhost
hosts: localhost
gather_facts: False gather_facts: False
become: yes become: yes
vars: vars:
bootstrap_os: none - bootstrap_os: none
roles: roles:
- { role: kvm-setup } - kvm-setup

View File

@@ -22,9 +22,9 @@
- ntp - ntp
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
- name: Create deployment user if required # Create deployment user if required
include_tasks: user.yml - include: user.yml
when: k8s_deployment_user is defined when: k8s_deployment_user is defined
- name: Set proper sysctl values # Set proper sysctl values
import_tasks: sysctl.yml - include: sysctl.yml

View File

@@ -1,6 +1,6 @@
--- ---
- name: Load br_netfilter module - name: Load br_netfilter module
community.general.modprobe: modprobe:
name: br_netfilter name: br_netfilter
state: present state: present
register: br_netfilter register: br_netfilter
@@ -25,7 +25,7 @@
- name: Enable net.ipv4.ip_forward in sysctl - name: Enable net.ipv4.ip_forward in sysctl
ansible.posix.sysctl: sysctl:
name: net.ipv4.ip_forward name: net.ipv4.ip_forward
value: 1 value: 1
sysctl_file: "{{ sysctl_file_path }}" sysctl_file: "{{ sysctl_file_path }}"
@@ -33,7 +33,7 @@
reload: yes reload: yes
- name: Set bridge-nf-call-{arptables,iptables} to 0 - name: Set bridge-nf-call-{arptables,iptables} to 0
ansible.posix.sysctl: sysctl:
name: "{{ item }}" name: "{{ item }}"
state: present state: present
value: 0 value: 0

View File

@@ -1,9 +1,8 @@
--- ---
- name: Check ansible version - name: Check ansible version
import_playbook: kubernetes_sigs.kubespray.ansible_version import_playbook: ansible_version.yml
- name: Install mitogen - hosts: localhost
hosts: localhost
strategy: linear strategy: linear
vars: vars:
mitogen_version: 0.3.2 mitogen_version: 0.3.2
@@ -20,25 +19,24 @@
- "{{ playbook_dir }}/plugins/mitogen" - "{{ playbook_dir }}/plugins/mitogen"
- "{{ playbook_dir }}/dist" - "{{ playbook_dir }}/dist"
- name: Download mitogen release - name: download mitogen release
get_url: get_url:
url: "{{ mitogen_url }}" url: "{{ mitogen_url }}"
dest: "{{ playbook_dir }}/dist/mitogen_{{ mitogen_version }}.tar.gz" dest: "{{ playbook_dir }}/dist/mitogen_{{ mitogen_version }}.tar.gz"
validate_certs: true validate_certs: true
mode: 0644
- name: Extract archive - name: extract archive
unarchive: unarchive:
src: "{{ playbook_dir }}/dist/mitogen_{{ mitogen_version }}.tar.gz" src: "{{ playbook_dir }}/dist/mitogen_{{ mitogen_version }}.tar.gz"
dest: "{{ playbook_dir }}/dist/" dest: "{{ playbook_dir }}/dist/"
- name: Copy plugin - name: copy plugin
ansible.posix.synchronize: synchronize:
src: "{{ playbook_dir }}/dist/mitogen-{{ mitogen_version }}/" src: "{{ playbook_dir }}/dist/mitogen-{{ mitogen_version }}/"
dest: "{{ playbook_dir }}/plugins/mitogen" dest: "{{ playbook_dir }}/plugins/mitogen"
- name: Add strategy to ansible.cfg - name: add strategy to ansible.cfg
community.general.ini_file: ini_file:
path: ansible.cfg path: ansible.cfg
mode: 0644 mode: 0644
section: "{{ item.section | d('defaults') }}" section: "{{ item.section | d('defaults') }}"

View File

@@ -1,29 +1,24 @@
--- ---
- name: Bootstrap hosts - hosts: gfs-cluster
hosts: gfs-cluster
gather_facts: false gather_facts: false
vars: vars:
ansible_ssh_pipelining: false ansible_ssh_pipelining: false
roles: roles:
- { role: bootstrap-os, tags: bootstrap-os} - { role: bootstrap-os, tags: bootstrap-os}
- name: Gather facts - hosts: all
hosts: all
gather_facts: true gather_facts: true
- name: Install glusterfs server - hosts: gfs-cluster
hosts: gfs-cluster
vars: vars:
ansible_ssh_pipelining: true ansible_ssh_pipelining: true
roles: roles:
- { role: glusterfs/server } - { role: glusterfs/server }
- name: Install glusterfs servers - hosts: k8s_cluster
hosts: k8s_cluster
roles: roles:
- { role: glusterfs/client } - { role: glusterfs/client }
- name: Configure Kubernetes to use glusterfs - hosts: kube_control_plane[0]
hosts: kube_control_plane[0]
roles: roles:
- { role: kubernetes-pv } - { role: kubernetes-pv }

View File

@@ -6,12 +6,12 @@ galaxy_info:
description: GlusterFS installation for Linux. description: GlusterFS installation for Linux.
company: "Midwestern Mac, LLC" company: "Midwestern Mac, LLC"
license: "license (BSD, MIT)" license: "license (BSD, MIT)"
min_ansible_version: "2.0" min_ansible_version: 2.0
platforms: platforms:
- name: EL - name: EL
versions: versions:
- "6" - 6
- "7" - 7
- name: Ubuntu - name: Ubuntu
versions: versions:
- precise - precise

View File

@@ -3,19 +3,14 @@
# hyperkube and needs to be installed as part of the system. # hyperkube and needs to be installed as part of the system.
# Setup/install tasks. # Setup/install tasks.
- name: Setup RedHat distros for glusterfs - include: setup-RedHat.yml
include_tasks: setup-RedHat.yml
when: ansible_os_family == 'RedHat' and groups['gfs-cluster'] is defined when: ansible_os_family == 'RedHat' and groups['gfs-cluster'] is defined
- name: Setup Debian distros for glusterfs - include: setup-Debian.yml
include_tasks: setup-Debian.yml
when: ansible_os_family == 'Debian' and groups['gfs-cluster'] is defined when: ansible_os_family == 'Debian' and groups['gfs-cluster'] is defined
- name: Ensure Gluster mount directories exist. - name: Ensure Gluster mount directories exist.
file: file: "path={{ item }} state=directory mode=0775"
path: "{{ item }}"
state: directory
mode: 0775
with_items: with_items:
- "{{ gluster_mount_dir }}" - "{{ gluster_mount_dir }}"
when: ansible_os_family in ["Debian","RedHat"] and groups['gfs-cluster'] is defined when: ansible_os_family in ["Debian","RedHat"] and groups['gfs-cluster'] is defined

View File

@@ -7,7 +7,7 @@
register: glusterfs_ppa_added register: glusterfs_ppa_added
when: glusterfs_ppa_use when: glusterfs_ppa_use
- name: Ensure GlusterFS client will reinstall if the PPA was just added. # noqa no-handler - name: Ensure GlusterFS client will reinstall if the PPA was just added. # noqa 503
apt: apt:
name: "{{ item }}" name: "{{ item }}"
state: absent state: absent

View File

@@ -1,14 +1,10 @@
--- ---
- name: Install Prerequisites - name: Install Prerequisites
package: package: name={{ item }} state=present
name: "{{ item }}"
state: present
with_items: with_items:
- "centos-release-gluster{{ glusterfs_default_release }}" - "centos-release-gluster{{ glusterfs_default_release }}"
- name: Install Packages - name: Install Packages
package: package: name={{ item }} state=present
name: "{{ item }}"
state: present
with_items: with_items:
- glusterfs-client - glusterfs-client

View File

@@ -6,12 +6,12 @@ galaxy_info:
description: GlusterFS installation for Linux. description: GlusterFS installation for Linux.
company: "Midwestern Mac, LLC" company: "Midwestern Mac, LLC"
license: "license (BSD, MIT)" license: "license (BSD, MIT)"
min_ansible_version: "2.0" min_ansible_version: 2.0
platforms: platforms:
- name: EL - name: EL
versions: versions:
- "6" - 6
- "7" - 7
- name: Ubuntu - name: Ubuntu
versions: versions:
- precise - precise

View File

@@ -4,97 +4,78 @@
include_vars: "{{ ansible_os_family }}.yml" include_vars: "{{ ansible_os_family }}.yml"
# Install xfs package # Install xfs package
- name: Install xfs Debian - name: install xfs Debian
apt: apt: name=xfsprogs state=present
name: xfsprogs
state: present
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
- name: Install xfs RedHat - name: install xfs RedHat
package: package: name=xfsprogs state=present
name: xfsprogs
state: present
when: ansible_os_family == "RedHat" when: ansible_os_family == "RedHat"
# Format external volumes in xfs # Format external volumes in xfs
- name: Format volumes in xfs - name: Format volumes in xfs
community.general.filesystem: filesystem: "fstype=xfs dev={{ disk_volume_device_1 }}"
fstype: xfs
dev: "{{ disk_volume_device_1 }}"
# Mount external volumes # Mount external volumes
- name: Mounting new xfs filesystem - name: mounting new xfs filesystem
ansible.posix.mount: mount: "name={{ gluster_volume_node_mount_dir }} src={{ disk_volume_device_1 }} fstype=xfs state=mounted"
name: "{{ gluster_volume_node_mount_dir }}"
src: "{{ disk_volume_device_1 }}"
fstype: xfs
state: mounted
# Setup/install tasks. # Setup/install tasks.
- name: Setup RedHat distros for glusterfs - include: setup-RedHat.yml
include_tasks: setup-RedHat.yml
when: ansible_os_family == 'RedHat' when: ansible_os_family == 'RedHat'
- name: Setup Debian distros for glusterfs - include: setup-Debian.yml
include_tasks: setup-Debian.yml
when: ansible_os_family == 'Debian' when: ansible_os_family == 'Debian'
- name: Ensure GlusterFS is started and enabled at boot. - name: Ensure GlusterFS is started and enabled at boot.
service: service: "name={{ glusterfs_daemon }} state=started enabled=yes"
name: "{{ glusterfs_daemon }}"
state: started
enabled: yes
- name: Ensure Gluster brick and mount directories exist. - name: Ensure Gluster brick and mount directories exist.
file: file: "path={{ item }} state=directory mode=0775"
path: "{{ item }}"
state: directory
mode: 0775
with_items: with_items:
- "{{ gluster_brick_dir }}" - "{{ gluster_brick_dir }}"
- "{{ gluster_mount_dir }}" - "{{ gluster_mount_dir }}"
- name: Configure Gluster volume with replicas - name: Configure Gluster volume with replicas
gluster.gluster.gluster_volume: gluster_volume:
state: present state: present
name: "{{ gluster_brick_name }}" name: "{{ gluster_brick_name }}"
brick: "{{ gluster_brick_dir }}" brick: "{{ gluster_brick_dir }}"
replicas: "{{ groups['gfs-cluster'] | length }}" replicas: "{{ groups['gfs-cluster'] | length }}"
cluster: "{% for item in groups['gfs-cluster'] -%}{{ hostvars[item]['ip'] | default(hostvars[item].ansible_default_ipv4['address']) }}{% if not loop.last %},{% endif %}{%- endfor %}" cluster: "{% for item in groups['gfs-cluster'] -%}{{ hostvars[item]['ip']|default(hostvars[item].ansible_default_ipv4['address']) }}{% if not loop.last %},{% endif %}{%- endfor %}"
host: "{{ inventory_hostname }}" host: "{{ inventory_hostname }}"
force: yes force: yes
run_once: true run_once: true
when: groups['gfs-cluster'] | length > 1 when: groups['gfs-cluster']|length > 1
- name: Configure Gluster volume without replicas - name: Configure Gluster volume without replicas
gluster.gluster.gluster_volume: gluster_volume:
state: present state: present
name: "{{ gluster_brick_name }}" name: "{{ gluster_brick_name }}"
brick: "{{ gluster_brick_dir }}" brick: "{{ gluster_brick_dir }}"
cluster: "{% for item in groups['gfs-cluster'] -%}{{ hostvars[item]['ip'] | default(hostvars[item].ansible_default_ipv4['address']) }}{% if not loop.last %},{% endif %}{%- endfor %}" cluster: "{% for item in groups['gfs-cluster'] -%}{{ hostvars[item]['ip']|default(hostvars[item].ansible_default_ipv4['address']) }}{% if not loop.last %},{% endif %}{%- endfor %}"
host: "{{ inventory_hostname }}" host: "{{ inventory_hostname }}"
force: yes force: yes
run_once: true run_once: true
when: groups['gfs-cluster'] | length <= 1 when: groups['gfs-cluster']|length <= 1
- name: Mount glusterfs to retrieve disk size - name: Mount glusterfs to retrieve disk size
ansible.posix.mount: mount:
name: "{{ gluster_mount_dir }}" name: "{{ gluster_mount_dir }}"
src: "{{ ip | default(ansible_default_ipv4['address']) }}:/gluster" src: "{{ ip|default(ansible_default_ipv4['address']) }}:/gluster"
fstype: glusterfs fstype: glusterfs
opts: "defaults,_netdev" opts: "defaults,_netdev"
state: mounted state: mounted
when: groups['gfs-cluster'] is defined and inventory_hostname == groups['gfs-cluster'][0] when: groups['gfs-cluster'] is defined and inventory_hostname == groups['gfs-cluster'][0]
- name: Get Gluster disk size - name: Get Gluster disk size
setup: setup: filter=ansible_mounts
filter: ansible_mounts
register: mounts_data register: mounts_data
when: groups['gfs-cluster'] is defined and inventory_hostname == groups['gfs-cluster'][0] when: groups['gfs-cluster'] is defined and inventory_hostname == groups['gfs-cluster'][0]
- name: Set Gluster disk size to variable - name: Set Gluster disk size to variable
set_fact: set_fact:
gluster_disk_size_gb: "{{ (mounts_data.ansible_facts.ansible_mounts | selectattr('mount', 'equalto', gluster_mount_dir) | map(attribute='size_total') | first | int / (1024 * 1024 * 1024)) | int }}" gluster_disk_size_gb: "{{ (mounts_data.ansible_facts.ansible_mounts | selectattr('mount', 'equalto', gluster_mount_dir) | map(attribute='size_total') | first | int / (1024*1024*1024)) | int }}"
when: groups['gfs-cluster'] is defined and inventory_hostname == groups['gfs-cluster'][0] when: groups['gfs-cluster'] is defined and inventory_hostname == groups['gfs-cluster'][0]
- name: Create file on GlusterFS - name: Create file on GlusterFS
@@ -105,9 +86,9 @@
when: groups['gfs-cluster'] is defined and inventory_hostname == groups['gfs-cluster'][0] when: groups['gfs-cluster'] is defined and inventory_hostname == groups['gfs-cluster'][0]
- name: Unmount glusterfs - name: Unmount glusterfs
ansible.posix.mount: mount:
name: "{{ gluster_mount_dir }}" name: "{{ gluster_mount_dir }}"
fstype: glusterfs fstype: glusterfs
src: "{{ ip | default(ansible_default_ipv4['address']) }}:/gluster" src: "{{ ip|default(ansible_default_ipv4['address']) }}:/gluster"
state: unmounted state: unmounted
when: groups['gfs-cluster'] is defined and inventory_hostname == groups['gfs-cluster'][0] when: groups['gfs-cluster'] is defined and inventory_hostname == groups['gfs-cluster'][0]

View File

@@ -7,7 +7,7 @@
register: glusterfs_ppa_added register: glusterfs_ppa_added
when: glusterfs_ppa_use when: glusterfs_ppa_use
- name: Ensure GlusterFS will reinstall if the PPA was just added. # noqa no-handler - name: Ensure GlusterFS will reinstall if the PPA was just added. # noqa 503
apt: apt:
name: "{{ item }}" name: "{{ item }}"
state: absent state: absent

View File

@@ -1,15 +1,11 @@
--- ---
- name: Install Prerequisites - name: Install Prerequisites
package: package: name={{ item }} state=present
name: "{{ item }}"
state: present
with_items: with_items:
- "centos-release-gluster{{ glusterfs_default_release }}" - "centos-release-gluster{{ glusterfs_default_release }}"
- name: Install Packages - name: Install Packages
package: package: name={{ item }} state=present
name: "{{ item }}"
state: present
with_items: with_items:
- glusterfs-server - glusterfs-server
- glusterfs-client - glusterfs-client

View File

@@ -18,6 +18,6 @@
kubectl: "{{ bin_dir }}/kubectl" kubectl: "{{ bin_dir }}/kubectl"
resource: "{{ item.item.type }}" resource: "{{ item.item.type }}"
filename: "{{ kube_config_dir }}/{{ item.item.dest }}" filename: "{{ kube_config_dir }}/{{ item.item.dest }}"
state: "{{ item.changed | ternary('latest', 'present') }}" state: "{{ item.changed | ternary('latest','present') }}"
with_items: "{{ gluster_pv.results }}" with_items: "{{ gluster_pv.results }}"
when: inventory_hostname == groups['kube_control_plane'][0] and groups['gfs-cluster'] is defined when: inventory_hostname == groups['kube_control_plane'][0] and groups['gfs-cluster'] is defined

View File

@@ -1,11 +1,9 @@
--- ---
- name: Tear down heketi - hosts: kube_control_plane[0]
hosts: kube_control_plane[0]
roles: roles:
- { role: tear-down } - { role: tear-down }
- name: Teardown disks in heketi - hosts: heketi-node
hosts: heketi-node
become: yes become: yes
roles: roles:
- { role: tear-down-disks } - { role: tear-down-disks }

View File

@@ -1,11 +1,9 @@
--- ---
- name: Prepare heketi install - hosts: heketi-node
hosts: heketi-node
roles: roles:
- { role: prepare } - { role: prepare }
- name: Provision heketi - hosts: kube_control_plane[0]
hosts: kube_control_plane[0]
tags: tags:
- "provision" - "provision"
roles: roles:

View File

@@ -5,7 +5,7 @@
- "dm_snapshot" - "dm_snapshot"
- "dm_mirror" - "dm_mirror"
- "dm_thin_pool" - "dm_thin_pool"
community.general.modprobe: modprobe:
name: "{{ item }}" name: "{{ item }}"
state: "present" state: "present"

View File

@@ -1,3 +1,3 @@
--- ---
- name: "Stop port forwarding" - name: "stop port forwarding"
command: "killall " command: "killall "

View File

@@ -7,9 +7,9 @@
- name: "Bootstrap heketi." - name: "Bootstrap heketi."
when: when:
- "(initial_heketi_state.stdout | from_json | json_query(\"items[?kind=='Service']\")) | length == 0" - "(initial_heketi_state.stdout|from_json|json_query(\"items[?kind=='Service']\"))|length == 0"
- "(initial_heketi_state.stdout | from_json | json_query(\"items[?kind=='Deployment']\")) | length == 0" - "(initial_heketi_state.stdout|from_json|json_query(\"items[?kind=='Deployment']\"))|length == 0"
- "(initial_heketi_state.stdout | from_json | json_query(\"items[?kind=='Pod']\")) | length == 0" - "(initial_heketi_state.stdout|from_json|json_query(\"items[?kind=='Pod']\"))|length == 0"
include_tasks: "bootstrap/deploy.yml" include_tasks: "bootstrap/deploy.yml"
# Prepare heketi topology # Prepare heketi topology
@@ -20,11 +20,11 @@
- name: "Ensure heketi bootstrap pod is up." - name: "Ensure heketi bootstrap pod is up."
assert: assert:
that: "(initial_heketi_pod.stdout | from_json | json_query('items[*]')) | length == 1" that: "(initial_heketi_pod.stdout|from_json|json_query('items[*]'))|length == 1"
- name: Store the initial heketi pod name - name: Store the initial heketi pod name
set_fact: set_fact:
initial_heketi_pod_name: "{{ initial_heketi_pod.stdout | from_json | json_query(\"items[*].metadata.name | [0]\") }}" initial_heketi_pod_name: "{{ initial_heketi_pod.stdout|from_json|json_query(\"items[*].metadata.name|[0]\") }}"
- name: "Test heketi topology." - name: "Test heketi topology."
changed_when: false changed_when: false
@@ -32,7 +32,7 @@
command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology info --json" command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology info --json"
- name: "Load heketi topology." - name: "Load heketi topology."
when: "heketi_topology.stdout | from_json | json_query(\"clusters[*].nodes[*]\") | flatten | length == 0" when: "heketi_topology.stdout|from_json|json_query(\"clusters[*].nodes[*]\")|flatten|length == 0"
include_tasks: "bootstrap/topology.yml" include_tasks: "bootstrap/topology.yml"
# Provision heketi database volume # Provision heketi database volume
@@ -58,7 +58,7 @@
service_query: "items[?metadata.name=='heketi-storage-endpoints' && kind=='Service']" service_query: "items[?metadata.name=='heketi-storage-endpoints' && kind=='Service']"
job_query: "items[?metadata.name=='heketi-storage-copy-job' && kind=='Job']" job_query: "items[?metadata.name=='heketi-storage-copy-job' && kind=='Job']"
when: when:
- "heketi_storage_state.stdout | from_json | json_query(secret_query) | length == 0" - "heketi_storage_state.stdout|from_json|json_query(secret_query)|length == 0"
- "heketi_storage_state.stdout | from_json | json_query(endpoints_query) | length == 0" - "heketi_storage_state.stdout|from_json|json_query(endpoints_query)|length == 0"
- "heketi_storage_state.stdout | from_json | json_query(service_query) | length == 0" - "heketi_storage_state.stdout|from_json|json_query(service_query)|length == 0"
- "heketi_storage_state.stdout | from_json | json_query(job_query) | length == 0" - "heketi_storage_state.stdout|from_json|json_query(job_query)|length == 0"

View File

@@ -17,11 +17,11 @@
register: "initial_heketi_state" register: "initial_heketi_state"
vars: vars:
initial_heketi_state: { stdout: "{}" } initial_heketi_state: { stdout: "{}" }
pods_query: "items[?kind=='Pod'].status.conditions | [0][?type=='Ready'].status | [0]" pods_query: "items[?kind=='Pod'].status.conditions|[0][?type=='Ready'].status|[0]"
deployments_query: "items[?kind=='Deployment'].status.conditions | [0][?type=='Available'].status | [0]" deployments_query: "items[?kind=='Deployment'].status.conditions|[0][?type=='Available'].status|[0]"
command: "{{ bin_dir }}/kubectl get services,deployments,pods --selector=deploy-heketi --output=json" command: "{{ bin_dir }}/kubectl get services,deployments,pods --selector=deploy-heketi --output=json"
until: until:
- "initial_heketi_state.stdout | from_json | json_query(pods_query) == 'True'" - "initial_heketi_state.stdout|from_json|json_query(pods_query) == 'True'"
- "initial_heketi_state.stdout | from_json | json_query(deployments_query) == 'True'" - "initial_heketi_state.stdout|from_json|json_query(deployments_query) == 'True'"
retries: 60 retries: 60
delay: 5 delay: 5

View File

@@ -15,10 +15,10 @@
service_query: "items[?metadata.name=='heketi-storage-endpoints' && kind=='Service']" service_query: "items[?metadata.name=='heketi-storage-endpoints' && kind=='Service']"
job_query: "items[?metadata.name=='heketi-storage-copy-job' && kind=='Job']" job_query: "items[?metadata.name=='heketi-storage-copy-job' && kind=='Job']"
when: when:
- "heketi_storage_state.stdout | from_json | json_query(secret_query) | length == 0" - "heketi_storage_state.stdout|from_json|json_query(secret_query)|length == 0"
- "heketi_storage_state.stdout | from_json | json_query(endpoints_query) | length == 0" - "heketi_storage_state.stdout|from_json|json_query(endpoints_query)|length == 0"
- "heketi_storage_state.stdout | from_json | json_query(service_query) | length == 0" - "heketi_storage_state.stdout|from_json|json_query(service_query)|length == 0"
- "heketi_storage_state.stdout | from_json | json_query(job_query) | length == 0" - "heketi_storage_state.stdout|from_json|json_query(job_query)|length == 0"
register: "heketi_storage_result" register: "heketi_storage_result"
- name: "Get state of heketi database copy job." - name: "Get state of heketi database copy job."
command: "{{ bin_dir }}/kubectl get jobs --output=json" command: "{{ bin_dir }}/kubectl get jobs --output=json"
@@ -28,6 +28,6 @@
heketi_storage_state: { stdout: "{}" } heketi_storage_state: { stdout: "{}" }
job_query: "items[?metadata.name=='heketi-storage-copy-job' && kind=='Job' && status.succeeded==1]" job_query: "items[?metadata.name=='heketi-storage-copy-job' && kind=='Job' && status.succeeded==1]"
until: until:
- "heketi_storage_state.stdout | from_json | json_query(job_query) | length == 1" - "heketi_storage_state.stdout|from_json|json_query(job_query)|length == 1"
retries: 60 retries: 60
delay: 5 delay: 5

View File

@@ -5,10 +5,10 @@
changed_when: false changed_when: false
- name: "Delete bootstrap Heketi." - name: "Delete bootstrap Heketi."
command: "{{ bin_dir }}/kubectl delete all,service,jobs,deployment,secret --selector=\"deploy-heketi\"" command: "{{ bin_dir }}/kubectl delete all,service,jobs,deployment,secret --selector=\"deploy-heketi\""
when: "heketi_resources.stdout | from_json | json_query('items[*]') | length > 0" when: "heketi_resources.stdout|from_json|json_query('items[*]')|length > 0"
- name: "Ensure there is nothing left over." - name: "Ensure there is nothing left over." # noqa 301
command: "{{ bin_dir }}/kubectl get all,service,jobs,deployment,secret --selector=\"deploy-heketi\" -o=json" command: "{{ bin_dir }}/kubectl get all,service,jobs,deployment,secret --selector=\"deploy-heketi\" -o=json"
register: "heketi_result" register: "heketi_result"
until: "heketi_result.stdout | from_json | json_query('items[*]') | length == 0" until: "heketi_result.stdout|from_json|json_query('items[*]')|length == 0"
retries: 60 retries: 60
delay: 5 delay: 5

View File

@@ -14,7 +14,7 @@
- name: "Copy topology configuration into container." - name: "Copy topology configuration into container."
changed_when: false changed_when: false
command: "{{ bin_dir }}/kubectl cp {{ kube_config_dir }}/topology.json {{ initial_heketi_pod_name }}:/tmp/topology.json" command: "{{ bin_dir }}/kubectl cp {{ kube_config_dir }}/topology.json {{ initial_heketi_pod_name }}:/tmp/topology.json"
- name: "Load heketi topology." # noqa no-handler - name: "Load heketi topology." # noqa 503
when: "render.changed" when: "render.changed"
command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology load --json=/tmp/topology.json" command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology load --json=/tmp/topology.json"
register: "load_heketi" register: "load_heketi"
@@ -22,6 +22,6 @@
changed_when: false changed_when: false
register: "heketi_topology" register: "heketi_topology"
command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology info --json" command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology info --json"
until: "heketi_topology.stdout | from_json | json_query(\"clusters[*].nodes[*].devices[?state=='online'].id\") | flatten | length == groups['heketi-node'] | length" until: "heketi_topology.stdout|from_json|json_query(\"clusters[*].nodes[*].devices[?state=='online'].id\")|flatten|length == groups['heketi-node']|length"
retries: 60 retries: 60
delay: 5 delay: 5

View File

@@ -6,19 +6,19 @@
- name: "Get heketi volumes." - name: "Get heketi volumes."
changed_when: false changed_when: false
command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} volume info {{ volume_id }} --json" command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} volume info {{ volume_id }} --json"
with_items: "{{ heketi_volumes.stdout | from_json | json_query(\"volumes[*]\") }}" with_items: "{{ heketi_volumes.stdout|from_json|json_query(\"volumes[*]\") }}"
loop_control: { loop_var: "volume_id" } loop_control: { loop_var: "volume_id" }
register: "volumes_information" register: "volumes_information"
- name: "Test heketi database volume." - name: "Test heketi database volume."
set_fact: { heketi_database_volume_exists: true } set_fact: { heketi_database_volume_exists: true }
with_items: "{{ volumes_information.results }}" with_items: "{{ volumes_information.results }}"
loop_control: { loop_var: "volume_information" } loop_control: { loop_var: "volume_information" }
vars: { volume: "{{ volume_information.stdout | from_json }}" } vars: { volume: "{{ volume_information.stdout|from_json }}" }
when: "volume.name == 'heketidbstorage'" when: "volume.name == 'heketidbstorage'"
- name: "Provision database volume." - name: "Provision database volume."
command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} setup-openshift-heketi-storage" command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} setup-openshift-heketi-storage"
when: "heketi_database_volume_exists is undefined" when: "heketi_database_volume_exists is undefined"
- name: "Copy configuration from pod." - name: "Copy configuration from pod." # noqa 301
become: true become: true
command: "{{ bin_dir }}/kubectl cp {{ initial_heketi_pod_name }}:/heketi-storage.json {{ kube_config_dir }}/heketi-storage-bootstrap.json" command: "{{ bin_dir }}/kubectl cp {{ initial_heketi_pod_name }}:/heketi-storage.json {{ kube_config_dir }}/heketi-storage-bootstrap.json"
- name: "Get heketi volume ids." - name: "Get heketi volume ids."
@@ -28,14 +28,14 @@
- name: "Get heketi volumes." - name: "Get heketi volumes."
changed_when: false changed_when: false
command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} volume info {{ volume_id }} --json" command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} volume info {{ volume_id }} --json"
with_items: "{{ heketi_volumes.stdout | from_json | json_query(\"volumes[*]\") }}" with_items: "{{ heketi_volumes.stdout|from_json|json_query(\"volumes[*]\") }}"
loop_control: { loop_var: "volume_id" } loop_control: { loop_var: "volume_id" }
register: "volumes_information" register: "volumes_information"
- name: "Test heketi database volume." - name: "Test heketi database volume."
set_fact: { heketi_database_volume_created: true } set_fact: { heketi_database_volume_created: true }
with_items: "{{ volumes_information.results }}" with_items: "{{ volumes_information.results }}"
loop_control: { loop_var: "volume_information" } loop_control: { loop_var: "volume_information" }
vars: { volume: "{{ volume_information.stdout | from_json }}" } vars: { volume: "{{ volume_information.stdout|from_json }}" }
when: "volume.name == 'heketidbstorage'" when: "volume.name == 'heketidbstorage'"
- name: "Ensure heketi database volume exists." - name: "Ensure heketi database volume exists."
assert: { that: "heketi_database_volume_created is defined", msg: "Heketi database volume does not exist." } assert: { that: "heketi_database_volume_created is defined", msg: "Heketi database volume does not exist." }

View File

@@ -23,8 +23,8 @@
changed_when: false changed_when: false
vars: vars:
daemonset_state: { stdout: "{}" } daemonset_state: { stdout: "{}" }
ready: "{{ daemonset_state.stdout | from_json | json_query(\"status.numberReady\") }}" ready: "{{ daemonset_state.stdout|from_json|json_query(\"status.numberReady\") }}"
desired: "{{ daemonset_state.stdout | from_json | json_query(\"status.desiredNumberScheduled\") }}" desired: "{{ daemonset_state.stdout|from_json|json_query(\"status.desiredNumberScheduled\") }}"
until: "ready | int >= 3" until: "ready | int >= 3"
retries: 60 retries: 60
delay: 5 delay: 5

View File

@@ -5,7 +5,7 @@
changed_when: false changed_when: false
- name: "Assign storage label" - name: "Assign storage label"
when: "label_present.stdout_lines | length == 0" when: "label_present.stdout_lines|length == 0"
command: "{{ bin_dir }}/kubectl label node {{ node }} storagenode=glusterfs" command: "{{ bin_dir }}/kubectl label node {{ node }} storagenode=glusterfs"
- name: Get storage nodes again - name: Get storage nodes again
@@ -15,5 +15,5 @@
- name: Ensure the label has been set - name: Ensure the label has been set
assert: assert:
that: "label_present | length > 0" that: "label_present|length > 0"
msg: "Node {{ node }} has not been assigned with label storagenode=glusterfs." msg: "Node {{ node }} has not been assigned with label storagenode=glusterfs."

View File

@@ -24,11 +24,11 @@
deployments_query: "items[?kind=='Deployment'].status.conditions|[0][?type=='Available'].status|[0]" deployments_query: "items[?kind=='Deployment'].status.conditions|[0][?type=='Available'].status|[0]"
command: "{{ bin_dir }}/kubectl get deployments,pods --selector=glusterfs --output=json" command: "{{ bin_dir }}/kubectl get deployments,pods --selector=glusterfs --output=json"
until: until:
- "heketi_state.stdout | from_json | json_query(pods_query) == 'True'" - "heketi_state.stdout|from_json|json_query(pods_query) == 'True'"
- "heketi_state.stdout | from_json | json_query(deployments_query) == 'True'" - "heketi_state.stdout|from_json|json_query(deployments_query) == 'True'"
retries: 60 retries: 60
delay: 5 delay: 5
- name: Set the Heketi pod name - name: Set the Heketi pod name
set_fact: set_fact:
heketi_pod_name: "{{ heketi_state.stdout | from_json | json_query(\"items[?kind=='Pod'].metadata.name|[0]\") }}" heketi_pod_name: "{{ heketi_state.stdout|from_json|json_query(\"items[?kind=='Pod'].metadata.name|[0]\") }}"

View File

@@ -12,7 +12,7 @@
- name: "Render storage class configuration." - name: "Render storage class configuration."
become: true become: true
vars: vars:
endpoint_address: "{{ (heketi_service.stdout | from_json).spec.clusterIP }}" endpoint_address: "{{ (heketi_service.stdout|from_json).spec.clusterIP }}"
template: template:
src: "storageclass.yml.j2" src: "storageclass.yml.j2"
dest: "{{ kube_config_dir }}/storageclass.yml" dest: "{{ kube_config_dir }}/storageclass.yml"

View File

@@ -11,16 +11,16 @@
src: "topology.json.j2" src: "topology.json.j2"
dest: "{{ kube_config_dir }}/topology.json" dest: "{{ kube_config_dir }}/topology.json"
mode: 0644 mode: 0644
- name: "Copy topology configuration into container." # noqa no-handler - name: "Copy topology configuration into container." # noqa 503
when: "rendering.changed" when: "rendering.changed"
command: "{{ bin_dir }}/kubectl cp {{ kube_config_dir }}/topology.json {{ heketi_pod_name }}:/tmp/topology.json" command: "{{ bin_dir }}/kubectl cp {{ kube_config_dir }}/topology.json {{ heketi_pod_name }}:/tmp/topology.json"
- name: "Load heketi topology." # noqa no-handler - name: "Load heketi topology." # noqa 503
when: "rendering.changed" when: "rendering.changed"
command: "{{ bin_dir }}/kubectl exec {{ heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology load --json=/tmp/topology.json" command: "{{ bin_dir }}/kubectl exec {{ heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology load --json=/tmp/topology.json"
- name: "Get heketi topology." - name: "Get heketi topology."
register: "heketi_topology" register: "heketi_topology"
changed_when: false changed_when: false
command: "{{ bin_dir }}/kubectl exec {{ heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology info --json" command: "{{ bin_dir }}/kubectl exec {{ heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology info --json"
until: "heketi_topology.stdout | from_json | json_query(\"clusters[*].nodes[*].devices[?state=='online'].id\") | flatten | length == groups['heketi-node'] | length" until: "heketi_topology.stdout|from_json|json_query(\"clusters[*].nodes[*].devices[?state=='online'].id\")|flatten|length == groups['heketi-node']|length"
retries: 60 retries: 60
delay: 5 delay: 5

View File

@@ -22,7 +22,7 @@
ignore_errors: true # noqa ignore-errors ignore_errors: true # noqa ignore-errors
changed_when: false changed_when: false
- name: "Remove volume groups." - name: "Remove volume groups." # noqa 301
environment: environment:
PATH: "{{ ansible_env.PATH }}:/sbin" # Make sure we can workaround RH / CentOS conservative path management PATH: "{{ ansible_env.PATH }}:/sbin" # Make sure we can workaround RH / CentOS conservative path management
become: true become: true
@@ -30,7 +30,7 @@
with_items: "{{ volume_groups.stdout_lines }}" with_items: "{{ volume_groups.stdout_lines }}"
loop_control: { loop_var: "volume_group" } loop_control: { loop_var: "volume_group" }
- name: "Remove physical volume from cluster disks." - name: "Remove physical volume from cluster disks." # noqa 301
environment: environment:
PATH: "{{ ansible_env.PATH }}:/sbin" # Make sure we can workaround RH / CentOS conservative path management PATH: "{{ ansible_env.PATH }}:/sbin" # Make sure we can workaround RH / CentOS conservative path management
become: true become: true

View File

@@ -1,43 +1,43 @@
--- ---
- name: Remove storage class. - name: Remove storage class. # noqa 301
command: "{{ bin_dir }}/kubectl delete storageclass gluster" command: "{{ bin_dir }}/kubectl delete storageclass gluster"
ignore_errors: true # noqa ignore-errors ignore_errors: true # noqa ignore-errors
- name: Tear down heketi. - name: Tear down heketi. # noqa 301
command: "{{ bin_dir }}/kubectl delete all,service,jobs,deployment,secret --selector=\"glusterfs=heketi-pod\"" command: "{{ bin_dir }}/kubectl delete all,service,jobs,deployment,secret --selector=\"glusterfs=heketi-pod\""
ignore_errors: true # noqa ignore-errors ignore_errors: true # noqa ignore-errors
- name: Tear down heketi. - name: Tear down heketi. # noqa 301
command: "{{ bin_dir }}/kubectl delete all,service,jobs,deployment,secret --selector=\"glusterfs=heketi-deployment\"" command: "{{ bin_dir }}/kubectl delete all,service,jobs,deployment,secret --selector=\"glusterfs=heketi-deployment\""
ignore_errors: true # noqa ignore-errors ignore_errors: true # noqa ignore-errors
- name: Tear down bootstrap. - name: Tear down bootstrap.
include_tasks: "../../provision/tasks/bootstrap/tear-down.yml" include_tasks: "../../provision/tasks/bootstrap/tear-down.yml"
- name: Ensure there is nothing left over. - name: Ensure there is nothing left over. # noqa 301
command: "{{ bin_dir }}/kubectl get all,service,jobs,deployment,secret --selector=\"glusterfs=heketi-pod\" -o=json" command: "{{ bin_dir }}/kubectl get all,service,jobs,deployment,secret --selector=\"glusterfs=heketi-pod\" -o=json"
register: "heketi_result" register: "heketi_result"
until: "heketi_result.stdout | from_json | json_query('items[*]') | length == 0" until: "heketi_result.stdout|from_json|json_query('items[*]')|length == 0"
retries: 60 retries: 60
delay: 5 delay: 5
- name: Ensure there is nothing left over. - name: Ensure there is nothing left over. # noqa 301
command: "{{ bin_dir }}/kubectl get all,service,jobs,deployment,secret --selector=\"glusterfs=heketi-deployment\" -o=json" command: "{{ bin_dir }}/kubectl get all,service,jobs,deployment,secret --selector=\"glusterfs=heketi-deployment\" -o=json"
register: "heketi_result" register: "heketi_result"
until: "heketi_result.stdout | from_json | json_query('items[*]') | length == 0" until: "heketi_result.stdout|from_json|json_query('items[*]')|length == 0"
retries: 60 retries: 60
delay: 5 delay: 5
- name: Tear down glusterfs. - name: Tear down glusterfs. # noqa 301
command: "{{ bin_dir }}/kubectl delete daemonset.extensions/glusterfs" command: "{{ bin_dir }}/kubectl delete daemonset.extensions/glusterfs"
ignore_errors: true # noqa ignore-errors ignore_errors: true # noqa ignore-errors
- name: Remove heketi storage service. - name: Remove heketi storage service. # noqa 301
command: "{{ bin_dir }}/kubectl delete service heketi-storage-endpoints" command: "{{ bin_dir }}/kubectl delete service heketi-storage-endpoints"
ignore_errors: true # noqa ignore-errors ignore_errors: true # noqa ignore-errors
- name: Remove heketi gluster role binding - name: Remove heketi gluster role binding # noqa 301
command: "{{ bin_dir }}/kubectl delete clusterrolebinding heketi-gluster-admin" command: "{{ bin_dir }}/kubectl delete clusterrolebinding heketi-gluster-admin"
ignore_errors: true # noqa ignore-errors ignore_errors: true # noqa ignore-errors
- name: Remove heketi config secret - name: Remove heketi config secret # noqa 301
command: "{{ bin_dir }}/kubectl delete secret heketi-config-secret" command: "{{ bin_dir }}/kubectl delete secret heketi-config-secret"
ignore_errors: true # noqa ignore-errors ignore_errors: true # noqa ignore-errors
- name: Remove heketi db backup - name: Remove heketi db backup # noqa 301
command: "{{ bin_dir }}/kubectl delete secret heketi-db-backup" command: "{{ bin_dir }}/kubectl delete secret heketi-db-backup"
ignore_errors: true # noqa ignore-errors ignore_errors: true # noqa ignore-errors
- name: Remove heketi service account - name: Remove heketi service account # noqa 301
command: "{{ bin_dir }}/kubectl delete serviceaccount heketi-service-account" command: "{{ bin_dir }}/kubectl delete serviceaccount heketi-service-account"
ignore_errors: true # noqa ignore-errors ignore_errors: true # noqa ignore-errors
- name: Get secrets - name: Get secrets
@@ -46,6 +46,6 @@
changed_when: false changed_when: false
- name: Remove heketi storage secret - name: Remove heketi storage secret
vars: { storage_query: "items[?metadata.annotations.\"kubernetes.io/service-account.name\"=='heketi-service-account'].metadata.name|[0]" } vars: { storage_query: "items[?metadata.annotations.\"kubernetes.io/service-account.name\"=='heketi-service-account'].metadata.name|[0]" }
command: "{{ bin_dir }}/kubectl delete secret {{ secrets.stdout | from_json | json_query(storage_query) }}" command: "{{ bin_dir }}/kubectl delete secret {{ secrets.stdout|from_json|json_query(storage_query) }}"
when: "storage_query is defined" when: "storage_query is defined"
ignore_errors: true # noqa ignore-errors ignore_errors: true # noqa ignore-errors

View File

@@ -5,17 +5,13 @@
Container image collecting script for offline deployment Container image collecting script for offline deployment
This script has two features: This script has two features:
(1) Get container images from an environment which is deployed online, or set IMAGES_FROM_FILE (1) Get container images from an environment which is deployed online.
environment variable to get images from a file (e.g. temp/images.list after running the
./generate_list.sh script).
(2) Deploy local container registry and register the container images to the registry. (2) Deploy local container registry and register the container images to the registry.
Step(1) should be done online site as a preparation, then we bring the gotten images Step(1) should be done online site as a preparation, then we bring the gotten images
to the target offline environment. if images are from a private registry, to the target offline environment. if images are from a private registry,
you need to set `PRIVATE_REGISTRY` environment variable. you need to set `PRIVATE_REGISTRY` environment variable.
Then we will run step(2) for registering the images to local registry, or to an existing Then we will run step(2) for registering the images to local registry.
registry set by the `DESTINATION_REGISTRY` environment variable. By default, the local registry
will run on port 5000. This can be changed with the `REGISTRY_PORT` environment variable
Step(1) can be operated with: Step(1) can be operated with:
@@ -31,7 +27,7 @@ manage-offline-container-images.sh register
## generate_list.sh ## generate_list.sh
This script generates the list of downloaded files and the list of container images by `roles/kubespray-defaults/defaults/main/download.yml` file. This script generates the list of downloaded files and the list of container images by `roles/download/defaults/main.yml` file.
Run this script will execute `generate_list.yml` playbook in kubespray root directory and generate four files, Run this script will execute `generate_list.yml` playbook in kubespray root directory and generate four files,
all downloaded files url in files.list, all container images in images.list, jinja2 templates in *.template. all downloaded files url in files.list, all container images in images.list, jinja2 templates in *.template.

View File

@@ -5,7 +5,7 @@ CURRENT_DIR=$(cd $(dirname $0); pwd)
TEMP_DIR="${CURRENT_DIR}/temp" TEMP_DIR="${CURRENT_DIR}/temp"
REPO_ROOT_DIR="${CURRENT_DIR%/contrib/offline}" REPO_ROOT_DIR="${CURRENT_DIR%/contrib/offline}"
: ${DOWNLOAD_YML:="roles/kubespray-defaults/defaults/main/download.yml"} : ${DOWNLOAD_YML:="roles/download/defaults/main.yml"}
mkdir -p ${TEMP_DIR} mkdir -p ${TEMP_DIR}
@@ -19,7 +19,7 @@ sed -n '/^downloads:/,/download_defaults:/p' ${REPO_ROOT_DIR}/${DOWNLOAD_YML} \
| sed 'N;s#\n# #g' | tr ' ' ':' | sed 's/\"//g' > ${TEMP_DIR}/images.list.template | sed 'N;s#\n# #g' | tr ' ' ':' | sed 's/\"//g' > ${TEMP_DIR}/images.list.template
# add kube-* images to images list template # add kube-* images to images list template
# Those container images are downloaded by kubeadm, then roles/kubespray-defaults/defaults/main/download.yml # Those container images are downloaded by kubeadm, then roles/download/defaults/main.yml
# doesn't contain those images. That is reason why here needs to put those images into the # doesn't contain those images. That is reason why here needs to put those images into the
# list separately. # list separately.
KUBE_IMAGES="kube-apiserver kube-controller-manager kube-scheduler kube-proxy" KUBE_IMAGES="kube-apiserver kube-controller-manager kube-scheduler kube-proxy"

View File

@@ -1,6 +1,5 @@
--- ---
- name: Collect container images for offline deployment - hosts: localhost
hosts: localhost
become: no become: no
roles: roles:
@@ -12,11 +11,9 @@
tasks: tasks:
# Generate files.list and images.list files from templates. # Generate files.list and images.list files from templates.
- name: Collect container images for offline deployment - template:
template:
src: ./contrib/offline/temp/{{ item }}.list.template src: ./contrib/offline/temp/{{ item }}.list.template
dest: ./contrib/offline/temp/{{ item }}.list dest: ./contrib/offline/temp/{{ item }}.list
mode: 0644
with_items: with_items:
- files - files
- images - images

View File

@@ -12,40 +12,27 @@ RETRY_COUNT=5
function create_container_image_tar() { function create_container_image_tar() {
set -e set -e
if [ -z "${IMAGES_FROM_FILE}" ]; then IMAGES=$(kubectl describe pods --all-namespaces | grep " Image:" | awk '{print $2}' | sort | uniq)
echo "Getting images from current \"$(kubectl config current-context)\"" # NOTE: etcd and pause cannot be seen as pods.
# The pause image is used for --pod-infra-container-image option of kubelet.
IMAGES=$(mktemp --suffix=-images) EXT_IMAGES=$(kubectl cluster-info dump | egrep "quay.io/coreos/etcd:|registry.k8s.io/pause:" | sed s@\"@@g)
trap 'rm -f "${IMAGES}"' EXIT IMAGES="${IMAGES} ${EXT_IMAGES}"
kubectl describe cronjobs,jobs,pods --all-namespaces | grep " Image:" | awk '{print $2}' | sort | uniq > "${IMAGES}"
# NOTE: etcd and pause cannot be seen as pods.
# The pause image is used for --pod-infra-container-image option of kubelet.
kubectl cluster-info dump | grep -E "quay.io/coreos/etcd:|registry.k8s.io/pause:" | sed s@\"@@g >> "${IMAGES}"
else
echo "Getting images from file \"${IMAGES_FROM_FILE}\""
if [ ! -f "${IMAGES_FROM_FILE}" ]; then
echo "${IMAGES_FROM_FILE} is not a file"
exit 1
fi
IMAGES=$(realpath $IMAGES_FROM_FILE)
fi
rm -f ${IMAGE_TAR_FILE} rm -f ${IMAGE_TAR_FILE}
rm -rf ${IMAGE_DIR} rm -rf ${IMAGE_DIR}
mkdir ${IMAGE_DIR} mkdir ${IMAGE_DIR}
cd ${IMAGE_DIR} cd ${IMAGE_DIR}
sudo ${runtime} pull registry:latest sudo docker pull registry:latest
sudo ${runtime} save -o registry-latest.tar registry:latest sudo docker save -o registry-latest.tar registry:latest
while read -r image for image in ${IMAGES}
do do
FILE_NAME="$(echo ${image} | sed s@"/"@"-"@g | sed s/":"/"-"/g | sed -E 's/\@.*//g')".tar FILE_NAME="$(echo ${image} | sed s@"/"@"-"@g | sed s/":"/"-"/g)".tar
set +e set +e
for step in $(seq 1 ${RETRY_COUNT}) for step in $(seq 1 ${RETRY_COUNT})
do do
sudo ${runtime} pull ${image} sudo docker pull ${image}
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
break break
fi fi
@@ -55,26 +42,24 @@ function create_container_image_tar() {
fi fi
done done
set -e set -e
sudo ${runtime} save -o ${FILE_NAME} ${image} sudo docker save -o ${FILE_NAME} ${image}
# NOTE: Here removes the following repo parts from each image # NOTE: Here removes the following repo parts from each image
# so that these parts will be replaced with Kubespray. # so that these parts will be replaced with Kubespray.
# - kube_image_repo: "registry.k8s.io" # - kube_image_repo: "registry.k8s.io"
# - gcr_image_repo: "gcr.io" # - gcr_image_repo: "gcr.io"
# - ghcr_image_repo: "ghcr.io"
# - docker_image_repo: "docker.io" # - docker_image_repo: "docker.io"
# - quay_image_repo: "quay.io" # - quay_image_repo: "quay.io"
FIRST_PART=$(echo ${image} | awk -F"/" '{print $1}') FIRST_PART=$(echo ${image} | awk -F"/" '{print $1}')
if [ "${FIRST_PART}" = "registry.k8s.io" ] || if [ "${FIRST_PART}" = "registry.k8s.io" ] ||
[ "${FIRST_PART}" = "gcr.io" ] || [ "${FIRST_PART}" = "gcr.io" ] ||
[ "${FIRST_PART}" = "ghcr.io" ] ||
[ "${FIRST_PART}" = "docker.io" ] || [ "${FIRST_PART}" = "docker.io" ] ||
[ "${FIRST_PART}" = "quay.io" ] || [ "${FIRST_PART}" = "quay.io" ] ||
[ "${FIRST_PART}" = "${PRIVATE_REGISTRY}" ]; then [ "${FIRST_PART}" = "${PRIVATE_REGISTRY}" ]; then
image=$(echo ${image} | sed s@"${FIRST_PART}/"@@ | sed -E 's/\@.*/\n/g') image=$(echo ${image} | sed s@"${FIRST_PART}/"@@)
fi fi
echo "${FILE_NAME} ${image}" >> ${IMAGE_LIST} echo "${FILE_NAME} ${image}" >> ${IMAGE_LIST}
done < "${IMAGES}" done
cd .. cd ..
sudo chown ${USER} ${IMAGE_DIR}/* sudo chown ${USER} ${IMAGE_DIR}/*
@@ -87,16 +72,6 @@ function create_container_image_tar() {
} }
function register_container_images() { function register_container_images() {
create_registry=false
REGISTRY_PORT=${REGISTRY_PORT:-"5000"}
if [ -z "${DESTINATION_REGISTRY}" ]; then
echo "DESTINATION_REGISTRY not set, will create local registry"
create_registry=true
DESTINATION_REGISTRY="$(hostname):${REGISTRY_PORT}"
fi
echo "Images will be pushed to ${DESTINATION_REGISTRY}"
if [ ! -f ${IMAGE_TAR_FILE} ]; then if [ ! -f ${IMAGE_TAR_FILE} ]; then
echo "${IMAGE_TAR_FILE} should exist." echo "${IMAGE_TAR_FILE} should exist."
exit 1 exit 1
@@ -106,47 +81,39 @@ function register_container_images() {
fi fi
# To avoid "http: server gave http response to https client" error. # To avoid "http: server gave http response to https client" error.
LOCALHOST_NAME=$(hostname)
if [ -d /etc/docker/ ]; then if [ -d /etc/docker/ ]; then
set -e set -e
# Ubuntu18.04, RHEL7/CentOS7 # Ubuntu18.04, RHEL7/CentOS7
cp ${CURRENT_DIR}/docker-daemon.json ${TEMP_DIR}/docker-daemon.json cp ${CURRENT_DIR}/docker-daemon.json ${TEMP_DIR}/docker-daemon.json
sed -i s@"HOSTNAME"@"$(hostname)"@ ${TEMP_DIR}/docker-daemon.json sed -i s@"HOSTNAME"@"${LOCALHOST_NAME}"@ ${TEMP_DIR}/docker-daemon.json
sudo cp ${TEMP_DIR}/docker-daemon.json /etc/docker/daemon.json sudo cp ${TEMP_DIR}/docker-daemon.json /etc/docker/daemon.json
elif [ -d /etc/containers/ ]; then elif [ -d /etc/containers/ ]; then
set -e set -e
# RHEL8/CentOS8 # RHEL8/CentOS8
cp ${CURRENT_DIR}/registries.conf ${TEMP_DIR}/registries.conf cp ${CURRENT_DIR}/registries.conf ${TEMP_DIR}/registries.conf
sed -i s@"HOSTNAME"@"$(hostname)"@ ${TEMP_DIR}/registries.conf sed -i s@"HOSTNAME"@"${LOCALHOST_NAME}"@ ${TEMP_DIR}/registries.conf
sudo cp ${TEMP_DIR}/registries.conf /etc/containers/registries.conf sudo cp ${TEMP_DIR}/registries.conf /etc/containers/registries.conf
else else
echo "runtime package(docker-ce, podman, nerctl, etc.) should be installed" echo "docker package(docker-ce, etc.) should be installed"
exit 1 exit 1
fi fi
tar -zxvf ${IMAGE_TAR_FILE} tar -zxvf ${IMAGE_TAR_FILE}
sudo docker load -i ${IMAGE_DIR}/registry-latest.tar
if [ "${create_registry}" ]; then set +e
sudo ${runtime} load -i ${IMAGE_DIR}/registry-latest.tar sudo docker container inspect registry >/dev/null 2>&1
set +e if [ $? -ne 0 ]; then
sudo docker run --restart=always -d -p 5000:5000 --name registry registry:latest
sudo ${runtime} container inspect registry >/dev/null 2>&1
if [ $? -ne 0 ]; then
sudo ${runtime} run --restart=always -d -p "${REGISTRY_PORT}":"${REGISTRY_PORT}" --name registry registry:latest
fi
set -e
fi fi
set -e
while read -r line; do while read -r line; do
file_name=$(echo ${line} | awk '{print $1}') file_name=$(echo ${line} | awk '{print $1}')
raw_image=$(echo ${line} | awk '{print $2}') raw_image=$(echo ${line} | awk '{print $2}')
new_image="${DESTINATION_REGISTRY}/${raw_image}" new_image="${LOCALHOST_NAME}:5000/${raw_image}"
load_image=$(sudo ${runtime} load -i ${IMAGE_DIR}/${file_name} | head -n1) org_image=$(sudo docker load -i ${IMAGE_DIR}/${file_name} | head -n1 | awk '{print $3}')
org_image=$(echo "${load_image}" | awk '{print $3}') image_id=$(sudo docker image inspect ${org_image} | grep "\"Id\":" | awk -F: '{print $3}'| sed s/'\",'//)
# special case for tags containing the digest when using docker or podman as the container runtime
if [ "${org_image}" == "ID:" ]; then
org_image=$(echo "${load_image}" | awk '{print $4}')
fi
image_id=$(sudo ${runtime} image inspect ${org_image} | grep "\"Id\":" | awk -F: '{print $3}'| sed s/'\",'//)
if [ -z "${file_name}" ]; then if [ -z "${file_name}" ]; then
echo "Failed to get file_name for line ${line}" echo "Failed to get file_name for line ${line}"
exit 1 exit 1
@@ -163,48 +130,32 @@ function register_container_images() {
echo "Failed to get image_id for file ${file_name}" echo "Failed to get image_id for file ${file_name}"
exit 1 exit 1
fi fi
sudo ${runtime} load -i ${IMAGE_DIR}/${file_name} sudo docker load -i ${IMAGE_DIR}/${file_name}
sudo ${runtime} tag ${image_id} ${new_image} sudo docker tag ${image_id} ${new_image}
sudo ${runtime} push ${new_image} sudo docker push ${new_image}
done <<< "$(cat ${IMAGE_LIST})" done <<< "$(cat ${IMAGE_LIST})"
echo "Succeeded to register container images to local registry." echo "Succeeded to register container images to local registry."
echo "Please specify \"${DESTINATION_REGISTRY}\" for the following options in your inventry:" echo "Please specify ${LOCALHOST_NAME}:5000 for the following options in your inventry:"
echo "- kube_image_repo" echo "- kube_image_repo"
echo "- gcr_image_repo" echo "- gcr_image_repo"
echo "- docker_image_repo" echo "- docker_image_repo"
echo "- quay_image_repo" echo "- quay_image_repo"
} }
# get runtime command
if command -v nerdctl 1>/dev/null 2>&1; then
runtime="nerdctl"
elif command -v podman 1>/dev/null 2>&1; then
runtime="podman"
elif command -v docker 1>/dev/null 2>&1; then
runtime="docker"
else
echo "No supported container runtime found"
exit 1
fi
if [ "${OPTION}" == "create" ]; then if [ "${OPTION}" == "create" ]; then
create_container_image_tar create_container_image_tar
elif [ "${OPTION}" == "register" ]; then elif [ "${OPTION}" == "register" ]; then
register_container_images register_container_images
else else
echo "This script has two features:" echo "This script has two features:"
echo "(1) Get container images from an environment which is deployed online, or set IMAGES_FROM_FILE" echo "(1) Get container images from an environment which is deployed online."
echo " environment variable to get images from a file (e.g. temp/images.list after running the"
echo " ./generate_list.sh script)."
echo "(2) Deploy local container registry and register the container images to the registry." echo "(2) Deploy local container registry and register the container images to the registry."
echo "" echo ""
echo "Step(1) should be done online site as a preparation, then we bring" echo "Step(1) should be done online site as a preparation, then we bring"
echo "the gotten images to the target offline environment. if images are from" echo "the gotten images to the target offline environment. if images are from"
echo "a private registry, you need to set PRIVATE_REGISTRY environment variable." echo "a private registry, you need to set PRIVATE_REGISTRY environment variable."
echo "Then we will run step(2) for registering the images to local registry, or to an existing" echo "Then we will run step(2) for registering the images to local registry."
echo "registry set by the DESTINATION_REGISTRY environment variable. By default, the local registry"
echo "will run on port 5000. This can be changed with the REGISTRY_PORT environment variable"
echo "" echo ""
echo "${IMAGE_TAR_FILE} is created to contain your container images." echo "${IMAGE_TAR_FILE} is created to contain your container images."
echo "Please keep this file and bring it to your offline environment." echo "Please keep this file and bring it to your offline environment."

View File

@@ -17,12 +17,7 @@ rm -rf "${OFFLINE_FILES_DIR}"
rm "${OFFLINE_FILES_ARCHIVE}" rm "${OFFLINE_FILES_ARCHIVE}"
mkdir "${OFFLINE_FILES_DIR}" mkdir "${OFFLINE_FILES_DIR}"
while read -r url; do wget -x -P "${OFFLINE_FILES_DIR}" -i "${FILES_LIST}"
if ! wget -x -P "${OFFLINE_FILES_DIR}" "${url}"; then
exit 1
fi
done < "${FILES_LIST}"
tar -czvf "${OFFLINE_FILES_ARCHIVE}" "${OFFLINE_FILES_DIR_NAME}" tar -czvf "${OFFLINE_FILES_ARCHIVE}" "${OFFLINE_FILES_DIR_NAME}"
[ -n "$NO_HTTP_SERVER" ] && echo "skip to run nginx" && exit 0 [ -n "$NO_HTTP_SERVER" ] && echo "skip to run nginx" && exit 0
@@ -43,7 +38,7 @@ sudo "${runtime}" container inspect nginx >/dev/null 2>&1
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
sudo "${runtime}" run \ sudo "${runtime}" run \
--restart=always -d -p ${NGINX_PORT}:80 \ --restart=always -d -p ${NGINX_PORT}:80 \
--volume "${OFFLINE_FILES_DIR}":/usr/share/nginx/html/download \ --volume "${OFFLINE_FILES_DIR}:/usr/share/nginx/html/download" \
--volume "${CURRENT_DIR}"/nginx.conf:/etc/nginx/nginx.conf \ --volume "$(pwd)"/nginx.conf:/etc/nginx/nginx.conf \
--name nginx nginx:alpine --name nginx nginx:alpine
fi fi

View File

@@ -1,5 +1,4 @@
--- ---
- name: Disable firewalld/ufw - hosts: all
hosts: all
roles: roles:
- { role: prepare } - { role: prepare }

View File

@@ -1,8 +1,5 @@
--- ---
- name: Disable firewalld and ufw - block:
when:
- disable_service_firewall is defined and disable_service_firewall
block:
- name: List services - name: List services
service_facts: service_facts:
@@ -12,7 +9,7 @@
state: stopped state: stopped
enabled: no enabled: no
when: when:
"'firewalld.service' in services and services['firewalld.service'].status != 'not-found'" "'firewalld.service' in services"
- name: Disable service ufw - name: Disable service ufw
systemd: systemd:
@@ -20,4 +17,7 @@
state: stopped state: stopped
enabled: no enabled: no
when: when:
"'ufw.service' in services and services['ufw.service'].status != 'not-found'" "'ufw.service' in services"
when:
- disable_service_firewall is defined and disable_service_firewall

View File

@@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners # See the OWNERS docs at https://go.k8s.io/owners
approvers: approvers:
- holmsten
- miouge1 - miouge1

View File

@@ -50,32 +50,70 @@ Example (this one assumes you are using Ubuntu)
ansible-playbook -i ./inventory/hosts ./cluster.yml -e ansible_user=ubuntu -b --become-user=root --flush-cache ansible-playbook -i ./inventory/hosts ./cluster.yml -e ansible_user=ubuntu -b --become-user=root --flush-cache
``` ```
## Using other distrib than Ubuntu*** ***Using other distrib than Ubuntu***
If you want to use another distribution than Ubuntu 18.04 (Bionic) LTS, you can modify the search filters of the 'data "aws_ami" "distro"' in variables.tf.
To leverage a Linux distribution other than Ubuntu 18.04 (Bionic) LTS for your Terraform configurations, you can adjust the AMI search filters within the 'data "aws_ami" "distro"' block by utilizing variables in your `terraform.tfvars` file. This approach ensures a flexible configuration that adapts to various Linux distributions without directly modifying the core Terraform files. For example, to use:
### Example Usages - Debian Jessie, replace 'data "aws_ami" "distro"' in variables.tf with
- **Debian Jessie**: To configure the usage of Debian Jessie, insert the subsequent lines into your `terraform.tfvars`: ```ini
data "aws_ami" "distro" {
most_recent = true
```hcl filter {
ami_name_pattern = "debian-jessie-amd64-hvm-*" name = "name"
ami_owners = ["379101102735"] values = ["debian-jessie-amd64-hvm-*"]
``` }
- **Ubuntu 16.04**: To utilize Ubuntu 16.04 instead, apply the following configuration in your `terraform.tfvars`: filter {
name = "virtualization-type"
values = ["hvm"]
}
```hcl owners = ["379101102735"]
ami_name_pattern = "ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-*" }
ami_owners = ["099720109477"] ```
```
- **Centos 7**: For employing Centos 7, incorporate these lines into your `terraform.tfvars`: - Ubuntu 16.04, replace 'data "aws_ami" "distro"' in variables.tf with
```hcl ```ini
ami_name_pattern = "dcos-centos7-*" data "aws_ami" "distro" {
ami_owners = ["688023202711"] most_recent = true
```
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"]
}
```
- Centos 7, replace 'data "aws_ami" "distro"' in variables.tf with
```ini
data "aws_ami" "distro" {
most_recent = true
filter {
name = "name"
values = ["dcos-centos7-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["688023202711"]
}
```
## Connecting to Kubernetes ## Connecting to Kubernetes

View File

@@ -20,38 +20,20 @@ variable "aws_cluster_name" {
description = "Name of AWS Cluster" description = "Name of AWS Cluster"
} }
variable "ami_name_pattern" {
description = "The name pattern to use for AMI lookup"
type = string
default = "debian-10-amd64-*"
}
variable "ami_virtualization_type" {
description = "The virtualization type to use for AMI lookup"
type = string
default = "hvm"
}
variable "ami_owners" {
description = "The owners to use for AMI lookup"
type = list(string)
default = ["136693071363"]
}
data "aws_ami" "distro" { data "aws_ami" "distro" {
most_recent = true most_recent = true
filter { filter {
name = "name" name = "name"
values = [var.ami_name_pattern] values = ["debian-10-amd64-*"]
} }
filter { filter {
name = "virtualization-type" name = "virtualization-type"
values = [var.ami_virtualization_type] values = ["hvm"]
} }
owners = var.ami_owners owners = ["136693071363"] # Debian-10
} }
//AWS VPC Variables //AWS VPC Variables

View File

@@ -35,7 +35,7 @@ now six total etcd replicas.
## Requirements ## Requirements
- [Install Terraform](https://www.terraform.io/intro/getting-started/install.html) - [Install Terraform](https://www.terraform.io/intro/getting-started/install.html)
- [Install Ansible dependencies](/docs/ansible/ansible.md#installing-ansible) - [Install Ansible dependencies](/docs/ansible.md#installing-ansible)
- Account with Equinix Metal - Account with Equinix Metal
- An SSH key pair - An SSH key pair

View File

@@ -7,7 +7,7 @@ terraform {
required_providers { required_providers {
equinix = { equinix = {
source = "equinix/equinix" source = "equinix/equinix"
version = "1.24.0" version = "~> 1.14"
} }
} }
} }

View File

@@ -1,5 +0,0 @@
*.tfstate*
.terraform.lock.hcl
.terraform
sample-inventory/inventory.ini

View File

@@ -1,137 +0,0 @@
# Kubernetes on NIFCLOUD with Terraform
Provision a Kubernetes cluster on [NIFCLOUD](https://pfs.nifcloud.com/) using Terraform and Kubespray
## Overview
The setup looks like following
```text
Kubernetes cluster
+----------------------------+
+---------------+ | +--------------------+ |
| | | | +--------------------+ |
| API server LB +---------> | | | |
| | | | | Control Plane/etcd | |
+---------------+ | | | node(s) | |
| +-+ | |
| +--------------------+ |
| ^ |
| | |
| v |
| +--------------------+ |
| | +--------------------+ |
| | | | |
| | | Worker | |
| | | node(s) | |
| +-+ | |
| +--------------------+ |
+----------------------------+
```
## Requirements
* Terraform 1.3.7
## Quickstart
### Export Variables
* Your NIFCLOUD credentials:
```bash
export NIFCLOUD_ACCESS_KEY_ID=<YOUR ACCESS KEY>
export NIFCLOUD_SECRET_ACCESS_KEY=<YOUR SECRET ACCESS KEY>
```
* The SSH KEY used to connect to the instance:
* FYI: [Cloud Help(SSH Key)](https://pfs.nifcloud.com/help/ssh.htm)
```bash
export TF_VAR_SSHKEY_NAME=<YOUR SSHKEY NAME>
```
* The IP address to connect to bastion server:
```bash
export TF_VAR_working_instance_ip=$(curl ifconfig.me)
```
### Create The Infrastructure
* Run terraform:
```bash
terraform init
terraform apply -var-file ./sample-inventory/cluster.tfvars
```
### Setup The Kubernetes
* Generate cluster configuration file:
```bash
./generate-inventory.sh > sample-inventory/inventory.ini
* Export Variables:
```bash
BASTION_IP=$(terraform output -json | jq -r '.kubernetes_cluster.value.bastion_info | to_entries[].value.public_ip')
API_LB_IP=$(terraform output -json | jq -r '.kubernetes_cluster.value.control_plane_lb')
CP01_IP=$(terraform output -json | jq -r '.kubernetes_cluster.value.control_plane_info | to_entries[0].value.private_ip')
export ANSIBLE_SSH_ARGS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ProxyCommand=\"ssh root@${BASTION_IP} -W %h:%p\""
```
* Set ssh-agent"
```bash
eval `ssh-agent`
ssh-add <THE PATH TO YOUR SSH KEY>
```
* Run cluster.yml playbook:
```bash
cd ./../../../
ansible-playbook -i contrib/terraform/nifcloud/inventory/inventory.ini cluster.yml
```
### Connecting to Kubernetes
* [Install kubectl](https://kubernetes.io/docs/tasks/tools/) on the localhost
* Fetching kubeconfig file:
```bash
mkdir -p ~/.kube
scp -o ProxyCommand="ssh root@${BASTION_IP} -W %h:%p" root@${CP01_IP}:/etc/kubernetes/admin.conf ~/.kube/config
```
* Rewrite /etc/hosts
```bash
sudo echo "${API_LB_IP} lb-apiserver.kubernetes.local" >> /etc/hosts
```
* Run kubectl
```bash
kubectl get node
```
## Variables
* `region`: Region where to run the cluster
* `az`: Availability zone where to run the cluster
* `private_ip_bn`: Private ip address of bastion server
* `private_network_cidr`: Subnet of private network
* `instances_cp`: Machine to provision as Control Plane. Key of this object will be used as part of the machine' name
* `private_ip`: private ip address of machine
* `instances_wk`: Machine to provision as Worker Node. Key of this object will be used as part of the machine' name
* `private_ip`: private ip address of machine
* `instance_key_name`: The key name of the Key Pair to use for the instance
* `instance_type_bn`: The instance type of bastion server
* `instance_type_wk`: The instance type of worker node
* `instance_type_cp`: The instance type of control plane
* `image_name`: OS image used for the instance
* `working_instance_ip`: The IP address to connect to bastion server
* `accounting_type`: Accounting type. (1: monthly, 2: pay per use)

View File

@@ -1,64 +0,0 @@
#!/bin/bash
#
# Generates a inventory file based on the terraform output.
# After provisioning a cluster, simply run this command and supply the terraform state file
# Default state file is terraform.tfstate
#
set -e
TF_OUT=$(terraform output -json)
CONTROL_PLANES=$(jq -r '.kubernetes_cluster.value.control_plane_info | to_entries[]' <(echo "${TF_OUT}"))
WORKERS=$(jq -r '.kubernetes_cluster.value.worker_info | to_entries[]' <(echo "${TF_OUT}"))
mapfile -t CONTROL_PLANE_NAMES < <(jq -r '.key' <(echo "${CONTROL_PLANES}"))
mapfile -t WORKER_NAMES < <(jq -r '.key' <(echo "${WORKERS}"))
API_LB=$(jq -r '.kubernetes_cluster.value.control_plane_lb' <(echo "${TF_OUT}"))
echo "[all]"
# Generate control plane hosts
i=1
for name in "${CONTROL_PLANE_NAMES[@]}"; do
private_ip=$(jq -r '. | select( .key=='"\"${name}\""' ) | .value.private_ip' <(echo "${CONTROL_PLANES}"))
echo "${name} ansible_user=root ansible_host=${private_ip} access_ip=${private_ip} ip=${private_ip} etcd_member_name=etcd${i}"
i=$(( i + 1 ))
done
# Generate worker hosts
for name in "${WORKER_NAMES[@]}"; do
private_ip=$(jq -r '. | select( .key=='"\"${name}\""' ) | .value.private_ip' <(echo "${WORKERS}"))
echo "${name} ansible_user=root ansible_host=${private_ip} access_ip=${private_ip} ip=${private_ip}"
done
API_LB=$(jq -r '.kubernetes_cluster.value.control_plane_lb' <(echo "${TF_OUT}"))
echo ""
echo "[all:vars]"
echo "upstream_dns_servers=['8.8.8.8','8.8.4.4']"
echo "loadbalancer_apiserver={'address':'${API_LB}','port':'6443'}"
echo ""
echo "[kube_control_plane]"
for name in "${CONTROL_PLANE_NAMES[@]}"; do
echo "${name}"
done
echo ""
echo "[etcd]"
for name in "${CONTROL_PLANE_NAMES[@]}"; do
echo "${name}"
done
echo ""
echo "[kube_node]"
for name in "${WORKER_NAMES[@]}"; do
echo "${name}"
done
echo ""
echo "[k8s_cluster:children]"
echo "kube_control_plane"
echo "kube_node"

View File

@@ -1,36 +0,0 @@
provider "nifcloud" {
region = var.region
}
module "kubernetes_cluster" {
source = "./modules/kubernetes-cluster"
availability_zone = var.az
prefix = "dev"
private_network_cidr = var.private_network_cidr
instance_key_name = var.instance_key_name
instances_cp = var.instances_cp
instances_wk = var.instances_wk
image_name = var.image_name
instance_type_bn = var.instance_type_bn
instance_type_cp = var.instance_type_cp
instance_type_wk = var.instance_type_wk
private_ip_bn = var.private_ip_bn
additional_lb_filter = [var.working_instance_ip]
}
resource "nifcloud_security_group_rule" "ssh_from_bastion" {
security_group_names = [
module.kubernetes_cluster.security_group_name.bastion
]
type = "IN"
from_port = 22
to_port = 22
protocol = "TCP"
cidr_ip = var.working_instance_ip
}

View File

@@ -1,301 +0,0 @@
#################################################
##
## Local variables
##
locals {
# e.g. east-11 is 11
az_num = reverse(split("-", var.availability_zone))[0]
# e.g. east-11 is e11
az_short_name = "${substr(reverse(split("-", var.availability_zone))[1], 0, 1)}${local.az_num}"
# Port used by the protocol
port_ssh = 22
port_kubectl = 6443
port_kubelet = 10250
# calico: https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements#network-requirements
port_bgp = 179
port_vxlan = 4789
port_etcd = 2379
}
#################################################
##
## General
##
# data
data "nifcloud_image" "this" {
image_name = var.image_name
}
# private lan
resource "nifcloud_private_lan" "this" {
private_lan_name = "${var.prefix}lan"
availability_zone = var.availability_zone
cidr_block = var.private_network_cidr
accounting_type = var.accounting_type
}
#################################################
##
## Bastion
##
resource "nifcloud_security_group" "bn" {
group_name = "${var.prefix}bn"
description = "${var.prefix} bastion"
availability_zone = var.availability_zone
}
resource "nifcloud_instance" "bn" {
instance_id = "${local.az_short_name}${var.prefix}bn01"
security_group = nifcloud_security_group.bn.group_name
instance_type = var.instance_type_bn
user_data = templatefile("${path.module}/templates/userdata.tftpl", {
private_ip_address = var.private_ip_bn
ssh_port = local.port_ssh
hostname = "${local.az_short_name}${var.prefix}bn01"
})
availability_zone = var.availability_zone
accounting_type = var.accounting_type
image_id = data.nifcloud_image.this.image_id
key_name = var.instance_key_name
network_interface {
network_id = "net-COMMON_GLOBAL"
}
network_interface {
network_id = nifcloud_private_lan.this.network_id
ip_address = "static"
}
# The image_id changes when the OS image type is demoted from standard to public.
lifecycle {
ignore_changes = [
image_id,
user_data,
]
}
}
#################################################
##
## Control Plane
##
resource "nifcloud_security_group" "cp" {
group_name = "${var.prefix}cp"
description = "${var.prefix} control plane"
availability_zone = var.availability_zone
}
resource "nifcloud_instance" "cp" {
for_each = var.instances_cp
instance_id = "${local.az_short_name}${var.prefix}${each.key}"
security_group = nifcloud_security_group.cp.group_name
instance_type = var.instance_type_cp
user_data = templatefile("${path.module}/templates/userdata.tftpl", {
private_ip_address = each.value.private_ip
ssh_port = local.port_ssh
hostname = "${local.az_short_name}${var.prefix}${each.key}"
})
availability_zone = var.availability_zone
accounting_type = var.accounting_type
image_id = data.nifcloud_image.this.image_id
key_name = var.instance_key_name
network_interface {
network_id = "net-COMMON_GLOBAL"
}
network_interface {
network_id = nifcloud_private_lan.this.network_id
ip_address = "static"
}
# The image_id changes when the OS image type is demoted from standard to public.
lifecycle {
ignore_changes = [
image_id,
user_data,
]
}
}
resource "nifcloud_load_balancer" "this" {
load_balancer_name = "${local.az_short_name}${var.prefix}cp"
accounting_type = var.accounting_type
balancing_type = 1 // Round-Robin
load_balancer_port = local.port_kubectl
instance_port = local.port_kubectl
instances = [for v in nifcloud_instance.cp : v.instance_id]
filter = concat(
[for k, v in nifcloud_instance.cp : v.public_ip],
[for k, v in nifcloud_instance.wk : v.public_ip],
var.additional_lb_filter,
)
filter_type = 1 // Allow
}
#################################################
##
## Worker
##
resource "nifcloud_security_group" "wk" {
group_name = "${var.prefix}wk"
description = "${var.prefix} worker"
availability_zone = var.availability_zone
}
resource "nifcloud_instance" "wk" {
for_each = var.instances_wk
instance_id = "${local.az_short_name}${var.prefix}${each.key}"
security_group = nifcloud_security_group.wk.group_name
instance_type = var.instance_type_wk
user_data = templatefile("${path.module}/templates/userdata.tftpl", {
private_ip_address = each.value.private_ip
ssh_port = local.port_ssh
hostname = "${local.az_short_name}${var.prefix}${each.key}"
})
availability_zone = var.availability_zone
accounting_type = var.accounting_type
image_id = data.nifcloud_image.this.image_id
key_name = var.instance_key_name
network_interface {
network_id = "net-COMMON_GLOBAL"
}
network_interface {
network_id = nifcloud_private_lan.this.network_id
ip_address = "static"
}
# The image_id changes when the OS image type is demoted from standard to public.
lifecycle {
ignore_changes = [
image_id,
user_data,
]
}
}
#################################################
##
## Security Group Rule: Kubernetes
##
# ssh
resource "nifcloud_security_group_rule" "ssh_from_bastion" {
security_group_names = [
nifcloud_security_group.wk.group_name,
nifcloud_security_group.cp.group_name,
]
type = "IN"
from_port = local.port_ssh
to_port = local.port_ssh
protocol = "TCP"
source_security_group_name = nifcloud_security_group.bn.group_name
}
# kubectl
resource "nifcloud_security_group_rule" "kubectl_from_worker" {
security_group_names = [
nifcloud_security_group.cp.group_name,
]
type = "IN"
from_port = local.port_kubectl
to_port = local.port_kubectl
protocol = "TCP"
source_security_group_name = nifcloud_security_group.wk.group_name
}
# kubelet
resource "nifcloud_security_group_rule" "kubelet_from_worker" {
security_group_names = [
nifcloud_security_group.cp.group_name,
]
type = "IN"
from_port = local.port_kubelet
to_port = local.port_kubelet
protocol = "TCP"
source_security_group_name = nifcloud_security_group.wk.group_name
}
resource "nifcloud_security_group_rule" "kubelet_from_control_plane" {
security_group_names = [
nifcloud_security_group.wk.group_name,
]
type = "IN"
from_port = local.port_kubelet
to_port = local.port_kubelet
protocol = "TCP"
source_security_group_name = nifcloud_security_group.cp.group_name
}
#################################################
##
## Security Group Rule: calico
##
# vslan
resource "nifcloud_security_group_rule" "vxlan_from_control_plane" {
security_group_names = [
nifcloud_security_group.wk.group_name,
]
type = "IN"
from_port = local.port_vxlan
to_port = local.port_vxlan
protocol = "UDP"
source_security_group_name = nifcloud_security_group.cp.group_name
}
resource "nifcloud_security_group_rule" "vxlan_from_worker" {
security_group_names = [
nifcloud_security_group.cp.group_name,
]
type = "IN"
from_port = local.port_vxlan
to_port = local.port_vxlan
protocol = "UDP"
source_security_group_name = nifcloud_security_group.wk.group_name
}
# bgp
resource "nifcloud_security_group_rule" "bgp_from_control_plane" {
security_group_names = [
nifcloud_security_group.wk.group_name,
]
type = "IN"
from_port = local.port_bgp
to_port = local.port_bgp
protocol = "TCP"
source_security_group_name = nifcloud_security_group.cp.group_name
}
resource "nifcloud_security_group_rule" "bgp_from_worker" {
security_group_names = [
nifcloud_security_group.cp.group_name,
]
type = "IN"
from_port = local.port_bgp
to_port = local.port_bgp
protocol = "TCP"
source_security_group_name = nifcloud_security_group.wk.group_name
}
# etcd
resource "nifcloud_security_group_rule" "etcd_from_worker" {
security_group_names = [
nifcloud_security_group.cp.group_name,
]
type = "IN"
from_port = local.port_etcd
to_port = local.port_etcd
protocol = "TCP"
source_security_group_name = nifcloud_security_group.wk.group_name
}

View File

@@ -1,48 +0,0 @@
output "control_plane_lb" {
description = "The DNS name of LB for control plane"
value = nifcloud_load_balancer.this.dns_name
}
output "security_group_name" {
description = "The security group used in the cluster"
value = {
bastion = nifcloud_security_group.bn.group_name,
control_plane = nifcloud_security_group.cp.group_name,
worker = nifcloud_security_group.wk.group_name,
}
}
output "private_network_id" {
description = "The private network used in the cluster"
value = nifcloud_private_lan.this.id
}
output "bastion_info" {
description = "The basion information in cluster"
value = { (nifcloud_instance.bn.instance_id) : {
instance_id = nifcloud_instance.bn.instance_id,
unique_id = nifcloud_instance.bn.unique_id,
private_ip = nifcloud_instance.bn.private_ip,
public_ip = nifcloud_instance.bn.public_ip,
} }
}
output "worker_info" {
description = "The worker information in cluster"
value = { for v in nifcloud_instance.wk : v.instance_id => {
instance_id = v.instance_id,
unique_id = v.unique_id,
private_ip = v.private_ip,
public_ip = v.public_ip,
} }
}
output "control_plane_info" {
description = "The control plane information in cluster"
value = { for v in nifcloud_instance.cp : v.instance_id => {
instance_id = v.instance_id,
unique_id = v.unique_id,
private_ip = v.private_ip,
public_ip = v.public_ip,
} }
}

View File

@@ -1,45 +0,0 @@
#!/bin/bash
#################################################
##
## IP Address
##
configure_private_ip_address () {
cat << EOS > /etc/netplan/01-netcfg.yaml
network:
version: 2
renderer: networkd
ethernets:
ens192:
dhcp4: yes
dhcp6: yes
dhcp-identifier: mac
ens224:
dhcp4: no
dhcp6: no
addresses: [${private_ip_address}]
EOS
netplan apply
}
configure_private_ip_address
#################################################
##
## SSH
##
configure_ssh_port () {
sed -i 's/^#*Port [0-9]*/Port ${ssh_port}/' /etc/ssh/sshd_config
}
configure_ssh_port
#################################################
##
## Hostname
##
hostnamectl set-hostname ${hostname}
#################################################
##
## Disable swap files genereated by systemd-gpt-auto-generator
##
systemctl mask "dev-sda3.swap"

View File

@@ -1,9 +0,0 @@
terraform {
required_version = ">=1.3.7"
required_providers {
nifcloud = {
source = "nifcloud/nifcloud"
version = ">= 1.8.0, < 2.0.0"
}
}
}

View File

@@ -1,81 +0,0 @@
variable "availability_zone" {
description = "The availability zone"
type = string
}
variable "prefix" {
description = "The prefix for the entire cluster"
type = string
validation {
condition = length(var.prefix) <= 5
error_message = "Must be a less than 5 character long."
}
}
variable "private_network_cidr" {
description = "The subnet of private network"
type = string
validation {
condition = can(cidrnetmask(var.private_network_cidr))
error_message = "Must be a valid IPv4 CIDR block address."
}
}
variable "private_ip_bn" {
description = "Private IP of bastion server"
type = string
}
variable "instances_cp" {
type = map(object({
private_ip = string
}))
}
variable "instances_wk" {
type = map(object({
private_ip = string
}))
}
variable "instance_key_name" {
description = "The key name of the Key Pair to use for the instance"
type = string
}
variable "instance_type_bn" {
description = "The instance type of bastion server"
type = string
}
variable "instance_type_wk" {
description = "The instance type of worker"
type = string
}
variable "instance_type_cp" {
description = "The instance type of control plane"
type = string
}
variable "image_name" {
description = "The name of image"
type = string
}
variable "additional_lb_filter" {
description = "Additional LB filter"
type = list(string)
}
variable "accounting_type" {
type = string
default = "1"
validation {
condition = anytrue([
var.accounting_type == "1", // Monthly
var.accounting_type == "2", // Pay per use
])
error_message = "Must be a 1 or 2."
}
}

View File

@@ -1,3 +0,0 @@
output "kubernetes_cluster" {
value = module.kubernetes_cluster
}

View File

@@ -1,22 +0,0 @@
region = "jp-west-1"
az = "west-11"
instance_key_name = "deployerkey"
instance_type_bn = "e-medium"
instance_type_cp = "e-medium"
instance_type_wk = "e-medium"
private_network_cidr = "192.168.30.0/24"
instances_cp = {
"cp01" : { private_ip : "192.168.30.11/24" }
"cp02" : { private_ip : "192.168.30.12/24" }
"cp03" : { private_ip : "192.168.30.13/24" }
}
instances_wk = {
"wk01" : { private_ip : "192.168.30.21/24" }
"wk02" : { private_ip : "192.168.30.22/24" }
}
private_ip_bn = "192.168.30.10/24"
image_name = "Ubuntu Server 22.04 LTS"

View File

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

View File

@@ -1,9 +0,0 @@
terraform {
required_version = ">=1.3.7"
required_providers {
nifcloud = {
source = "nifcloud/nifcloud"
version = "1.8.0"
}
}
}

View File

@@ -1,77 +0,0 @@
variable "region" {
description = "The region"
type = string
}
variable "az" {
description = "The availability zone"
type = string
}
variable "private_ip_bn" {
description = "Private IP of bastion server"
type = string
}
variable "private_network_cidr" {
description = "The subnet of private network"
type = string
validation {
condition = can(cidrnetmask(var.private_network_cidr))
error_message = "Must be a valid IPv4 CIDR block address."
}
}
variable "instances_cp" {
type = map(object({
private_ip = string
}))
}
variable "instances_wk" {
type = map(object({
private_ip = string
}))
}
variable "instance_key_name" {
description = "The key name of the Key Pair to use for the instance"
type = string
}
variable "instance_type_bn" {
description = "The instance type of bastion server"
type = string
}
variable "instance_type_wk" {
description = "The instance type of worker"
type = string
}
variable "instance_type_cp" {
description = "The instance type of control plane"
type = string
}
variable "image_name" {
description = "The name of image"
type = string
}
variable "working_instance_ip" {
description = "The IP address to connect to bastion server."
type = string
}
variable "accounting_type" {
type = string
default = "2"
validation {
condition = anytrue([
var.accounting_type == "1", // Monthly
var.accounting_type == "2", // Pay per use
])
error_message = "Must be a 1 or 2."
}
}

View File

@@ -1,5 +1,5 @@
.terraform .terraform
*.tfvars *.tfvars
!sample-inventory/cluster.tfvars !sample-inventory\/cluster.tfvars
*.tfstate *.tfstate
*.tfstate.backup *.tfstate.backup

View File

@@ -24,7 +24,6 @@ most modern installs of OpenStack that support the basic services.
- [Ultimum](https://ultimum.io/) - [Ultimum](https://ultimum.io/)
- [VexxHost](https://vexxhost.com/) - [VexxHost](https://vexxhost.com/)
- [Zetta](https://www.zetta.io/) - [Zetta](https://www.zetta.io/)
- [Cloudify](https://www.cloudify.ro/en)
## Approach ## Approach
@@ -98,10 +97,9 @@ binaries available on hyperkube v1.4.3_coreos.0 or higher.
## Module Architecture ## Module Architecture
The configuration is divided into four modules: The configuration is divided into three modules:
- Network - Network
- Loadbalancer
- IPs - IPs
- Compute - Compute
@@ -271,18 +269,11 @@ For your cluster, edit `inventory/$CLUSTER/cluster.tfvars`.
|`supplementary_master_groups` | To add ansible groups to the masters, such as `kube_node` for tainting them as nodes, empty by default. | |`supplementary_master_groups` | To add ansible groups to the masters, such as `kube_node` for tainting them as nodes, empty by default. |
|`supplementary_node_groups` | To add ansible groups to the nodes, such as `kube_ingress` for running ingress controller pods, empty by default. | |`supplementary_node_groups` | To add ansible groups to the nodes, such as `kube_ingress` for running ingress controller pods, empty by default. |
|`bastion_allowed_remote_ips` | List of CIDR allowed to initiate a SSH connection, `["0.0.0.0/0"]` by default | |`bastion_allowed_remote_ips` | List of CIDR allowed to initiate a SSH connection, `["0.0.0.0/0"]` by default |
|`bastion_allowed_remote_ipv6_ips` | List of IPv6 CIDR allowed to initiate a SSH connection, `["::/0"]` by default |
|`master_allowed_remote_ips` | List of CIDR blocks allowed to initiate an API connection, `["0.0.0.0/0"]` by default | |`master_allowed_remote_ips` | List of CIDR blocks allowed to initiate an API connection, `["0.0.0.0/0"]` by default |
|`master_allowed_remote_ipv6_ips` | List of IPv6 CIDR blocks allowed to initiate an API connection, `["::/0"]` by default |
|`bastion_allowed_ports` | List of ports to open on bastion node, `[]` by default | |`bastion_allowed_ports` | List of ports to open on bastion node, `[]` by default |
|`bastion_allowed_ports_ipv6` | List of ports to open on bastion node for IPv6 CIDR blocks, `[]` by default |
|`k8s_allowed_remote_ips` | List of CIDR allowed to initiate a SSH connection, empty by default | |`k8s_allowed_remote_ips` | List of CIDR allowed to initiate a SSH connection, empty by default |
|`k8s_allowed_remote_ips_ipv6` | List of IPv6 CIDR allowed to initiate a SSH connection, empty by default |
|`k8s_allowed_egress_ipv6_ips` | List of IPv6 CIDRs allowed for egress traffic, `["::/0"]` by default |
|`worker_allowed_ports` | List of ports to open on worker nodes, `[{ "protocol" = "tcp", "port_range_min" = 30000, "port_range_max" = 32767, "remote_ip_prefix" = "0.0.0.0/0"}]` by default | |`worker_allowed_ports` | List of ports to open on worker nodes, `[{ "protocol" = "tcp", "port_range_min" = 30000, "port_range_max" = 32767, "remote_ip_prefix" = "0.0.0.0/0"}]` by default |
|`worker_allowed_ports_ipv6` | List of ports to open on worker nodes for IPv6 CIDR blocks, `[{ "protocol" = "tcp", "port_range_min" = 30000, "port_range_max" = 32767, "remote_ip_prefix" = "::/0"}]` by default |
|`master_allowed_ports` | List of ports to open on master nodes, expected format is `[{ "protocol" = "tcp", "port_range_min" = 443, "port_range_max" = 443, "remote_ip_prefix" = "0.0.0.0/0"}]`, empty by default | |`master_allowed_ports` | List of ports to open on master nodes, expected format is `[{ "protocol" = "tcp", "port_range_min" = 443, "port_range_max" = 443, "remote_ip_prefix" = "0.0.0.0/0"}]`, empty by default |
|`master_allowed_ports_ipv6` | List of ports to open on master nodes for IPv6 CIDR blocks, expected format is `[{ "protocol" = "tcp", "port_range_min" = 443, "port_range_max" = 443, "remote_ip_prefix" = "::/0"}]`, empty by default |
|`node_root_volume_size_in_gb` | Size of the root volume for nodes, 0 to use ephemeral storage | |`node_root_volume_size_in_gb` | Size of the root volume for nodes, 0 to use ephemeral storage |
|`master_root_volume_size_in_gb` | Size of the root volume for masters, 0 to use ephemeral storage | |`master_root_volume_size_in_gb` | Size of the root volume for masters, 0 to use ephemeral storage |
|`master_volume_type` | Volume type of the root volume for control_plane, 'Default' by default | |`master_volume_type` | Volume type of the root volume for control_plane, 'Default' by default |
@@ -299,10 +290,6 @@ For your cluster, edit `inventory/$CLUSTER/cluster.tfvars`.
|`force_null_port_security` | Set `null` instead of `true` or `false` for `port_security`. `false` by default | |`force_null_port_security` | Set `null` instead of `true` or `false` for `port_security`. `false` by default |
|`k8s_nodes` | Map containing worker node definition, see explanation below | |`k8s_nodes` | Map containing worker node definition, see explanation below |
|`k8s_masters` | Map containing master node definition, see explanation for k8s_nodes and `sample-inventory/cluster.tfvars` | |`k8s_masters` | Map containing master node definition, see explanation for k8s_nodes and `sample-inventory/cluster.tfvars` |
| `k8s_master_loadbalancer_enabled`| Enable and use an Octavia load balancer for the K8s master nodes |
| `k8s_master_loadbalancer_listener_port` | Define via which port the K8s Api should be exposed. `6443` by default |
| `k8s_master_loadbalancer_server_port` | Define via which port the K8S api is available on the mas. `6443` by default |
| `k8s_master_loadbalancer_public_ip` | Specify if an existing floating IP should be used for the load balancer. A new floating IP is assigned by default |
##### k8s_nodes ##### k8s_nodes
@@ -331,7 +318,6 @@ k8s_nodes:
mount_path: string # Path to where the partition should be mounted mount_path: string # Path to where the partition should be mounted
partition_start: string # Where the partition should start (e.g. 10GB ). Note, if you set the partition_start to 0 there will be no space left for the root partition partition_start: string # Where the partition should start (e.g. 10GB ). Note, if you set the partition_start to 0 there will be no space left for the root partition
partition_end: string # Where the partition should end (e.g. 10GB or -1 for end of volume) partition_end: string # Where the partition should end (e.g. 10GB or -1 for end of volume)
netplan_critical_dhcp_interface: string # Name of interface to set the dhcp flag critical = true, to circumvent [this issue](https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1776013).
``` ```
For example: For example:
@@ -619,7 +605,7 @@ Edit `inventory/$CLUSTER/group_vars/k8s_cluster/k8s_cluster.yml`:
- Set variable **kube_network_plugin** to your desired networking plugin. - Set variable **kube_network_plugin** to your desired networking plugin.
- **flannel** works out-of-the-box - **flannel** works out-of-the-box
- **calico** requires [configuring OpenStack Neutron ports](/docs/cloud_providers/openstack.md) to allow service and pod subnets - **calico** requires [configuring OpenStack Neutron ports](/docs/openstack.md) to allow service and pod subnets
```yml ```yml
# Choose network plugin (calico, weave or flannel) # Choose network plugin (calico, weave or flannel)

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