Compare commits

..

5 Commits

Author SHA1 Message Date
Etienne Champetier
abe9b40602 Ensure we always fixup kube-proxy kubeconfig (#5524) (#5559)
When running with serial != 100%, like upgrade_cluster.yml, we need to apply this fixup each time
Problem was introduced in 05dc2b3a09

Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
(cherry picked from commit 5e9479cded)
2020-03-19 06:33:23 -07:00
Florian Ruynat
b0ccda8a42 Upgrade to Kubernetes 1.15.11 (#5578) 2020-03-19 02:57:13 -07:00
Florent Monbillard
c8dad3f6c6 Backport remove dockerproject (#5682) (#5780)
* Remove dockerproject org (#5548)

* Change dockerproject.org to download.docker.com

dockerproject.org was deprecated in 2017 and has gone down.

* Restore yum repo for containerd

Change-Id: I883bb512a2164a85865b1bd4fb569af0358c8c2b

Co-authored-by: Craig Rodrigues <rodrigc@crodrigues.org>

* remove legacy docker repo in kubernetes/preinstall before any packages installed (#5640)

* Remove dockerproject_.+_repo_.+ variables (#5662)

This 38688a4486 change replaces the
value for dockerproject_.+_repo_.+ docker variables but their new
value was previously defined in other variables. This change removes
the dockerproject_.+_repo_.+ docker variables in favor of the older
ones.

* Remove stale legacy yum docker repo /etc/yum.repos.d/docker.repo (#5569)

* Remove stale legacy yum docker repo /etc/yum.repos.d/docker.repo

* move task 'Remove legacy docker repo file' to pre-upgrade.yml

* fix upgrade procedure when in playbook (#5695)

exists role kubernetes/preinstall and not exists role container-engine

 error 'yum_repo_dir' is undefined

Co-authored-by: Matthew Mosesohn <matthew.mosesohn@gmail.com>
Co-authored-by: Craig Rodrigues <rodrigc@crodrigues.org>
Co-authored-by: Victor Morales <chipahuac@hotmail.com>

Co-authored-by: Kubernetes Prow Robot <k8s-ci-robot@users.noreply.github.com>
Co-authored-by: Matthew Mosesohn <matthew.mosesohn@gmail.com>
Co-authored-by: Craig Rodrigues <rodrigc@crodrigues.org>
Co-authored-by: Victor Morales <chipahuac@hotmail.com>
2020-03-17 07:38:22 -07:00
Etienne Champetier
5ec9ab7ec0 Upgrade to Kubernetes 1.15.6 (#5343)
Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2019-11-22 00:11:29 -08:00
Hugo Blom
73097aa39d Preparing a 2.11.1 release - kubernetes 1.15.5 (#5278)
* add checksums for 1.15.4 and 1.15.5 and set 1.15.5 to default

* Upgrade nodelocaldns to 1.15.5 (#5191)

* do not rebase from master for 2.11 release branch
2019-10-30 01:56:52 -07:00
848 changed files with 6862 additions and 43088 deletions

View File

@@ -2,8 +2,13 @@
parseable: true parseable: true
skip_list: skip_list:
# see https://docs.ansible.com/ansible-lint/rules/default_rules.html for a list of all default rules # see https://docs.ansible.com/ansible-lint/rules/default_rules.html for a list of all default rules
# The following rules throw errors.
# DO NOT add any other rules to this skip_list, instead use local `# noqa` with a comment explaining WHY it is necessary # These either still need to be corrected in the repository and the rules re-enabled or documented why they are skipped on purpose.
- '301'
- '305'
- '306'
- '404'
- '503'
# These rules are intentionally skipped: # These rules are intentionally skipped:
# #

View File

@@ -1,15 +0,0 @@
root = true
[*.{yaml,yml,yml.j2,yaml.j2}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8
[{Dockerfile}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8

View File

@@ -18,8 +18,6 @@ explain why.
- **Version of Ansible** (`ansible --version`): - **Version of Ansible** (`ansible --version`):
- **Version of Python** (`python --version`):
**Kubespray version (commit) (`git rev-parse --short HEAD`):** **Kubespray version (commit) (`git rev-parse --short HEAD`):**
@@ -27,8 +25,8 @@ explain why.
**Network plugin used**: **Network plugin used**:
**Full inventory with variables (`ansible -i inventory/sample/inventory.ini all -m debug -a "var=hostvars[inventory_hostname]"`):** **Copy of your inventory file:**
<!-- We recommend using snippets services like https://gist.github.com/ etc. -->
**Command used to invoke ansible**: **Command used to invoke ansible**:

View File

@@ -1,9 +1,9 @@
<!-- Thanks for sending a pull request! Here are some tips for you: <!-- Thanks for sending a pull request! Here are some tips for you:
1. If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide/first-contribution.md and developer guide https://git.k8s.io/community/contributors/devel/development.md 1. If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide#your-first-contribution and developer guide https://git.k8s.io/community/contributors/devel/development.md#development-guide
2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. For reference on required PR/issue labels, read here: 2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. For reference on required PR/issue labels, read here:
https://git.k8s.io/community/contributors/devel/sig-release/release.md#issuepr-kind-label https://git.k8s.io/community/contributors/devel/release.md#issue-kind-label
3. Ensure you have added or ran the appropriate tests for your PR: https://git.k8s.io/community/contributors/devel/sig-testing/testing.md 3. Ensure you have added or ran the appropriate tests for your PR: https://git.k8s.io/community/contributors/devel/testing.md
4. If you want *faster* PR reviews, read how: https://git.k8s.io/community/contributors/guide/pull-requests.md#best-practices-for-faster-reviews 4. If you want *faster* PR reviews, read how: https://git.k8s.io/community/contributors/guide/pull-requests.md#best-practices-for-faster-reviews
5. Follow the instructions for writing a release note: https://git.k8s.io/community/contributors/guide/release-notes.md 5. Follow the instructions for writing a release note: https://git.k8s.io/community/contributors/guide/release-notes.md
6. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests 6. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests

1
.gitignore vendored
View File

@@ -1,7 +1,6 @@
.vagrant .vagrant
*.retry *.retry
**/vagrant_ansible_inventory **/vagrant_ansible_inventory
*.iml
temp temp
.idea .idea
.tox .tox

View File

@@ -4,13 +4,13 @@ stages:
- deploy-part1 - deploy-part1
- moderator - moderator
- deploy-part2 - deploy-part2
- deploy-part3 - deploy-gce
- deploy-special - deploy-special
variables: variables:
KUBESPRAY_VERSION: v2.13.3
FAILFASTCI_NAMESPACE: 'kargo-ci' FAILFASTCI_NAMESPACE: 'kargo-ci'
GITLAB_REPOSITORY: 'kargo-ci/kubernetes-sigs-kubespray' GITLAB_REPOSITORY: 'kargo-ci/kubernetes-sigs-kubespray'
# DOCKER_HOST: tcp://localhost:2375
ANSIBLE_FORCE_COLOR: "true" ANSIBLE_FORCE_COLOR: "true"
MAGIC: "ci check this" MAGIC: "ci check this"
TEST_ID: "$CI_PIPELINE_ID-$CI_BUILD_ID" TEST_ID: "$CI_PIPELINE_ID-$CI_BUILD_ID"
@@ -26,36 +26,31 @@ variables:
IDEMPOT_CHECK: "false" IDEMPOT_CHECK: "false"
RESET_CHECK: "false" RESET_CHECK: "false"
UPGRADE_TEST: "false" UPGRADE_TEST: "false"
MITOGEN_ENABLE: "false" LOG_LEVEL: "-vv"
ANSIBLE_LOG_LEVEL: "-vv"
RECOVER_CONTROL_PLANE_TEST: "false"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:],kube-master[1:]"
before_script: before_script:
- ./tests/scripts/rebase.sh - ./tests/scripts/rebase.sh
- update-alternatives --install /usr/bin/python python /usr/bin/python3 1 - /usr/bin/python -m pip install -r tests/requirements.txt
- python -m pip install -r tests/requirements.txt
- mkdir -p /.ssh - mkdir -p /.ssh
.job: &job .job: &job
tags: tags:
- packet - packet
variables:
KUBESPRAY_VERSION: v2.10.0
image: quay.io/kubespray/kubespray:$KUBESPRAY_VERSION image: quay.io/kubespray/kubespray:$KUBESPRAY_VERSION
artifacts:
when: always
paths:
- cluster-dump/
.testcases: &testcases .testcases: &testcases
<<: *job <<: *job
services:
- docker:dind
before_script: before_script:
- update-alternatives --install /usr/bin/python python /usr/bin/python3 1
- ./tests/scripts/rebase.sh - ./tests/scripts/rebase.sh
- ./tests/scripts/testcases_prepare.sh - ./tests/scripts/testcases_prepare.sh
script: script:
- ./tests/scripts/testcases_run.sh - ./tests/scripts/testcases_run.sh
after_script: after_script:
- chronic ./tests/scripts/testcases_cleanup.sh - ./tests/scripts/testcases_cleanup.sh
# For failfast, at least 1 job must be defined in .gitlab-ci.yml # For failfast, at least 1 job must be defined in .gitlab-ci.yml
# Premoderated with manual actions # Premoderated with manual actions
@@ -71,6 +66,6 @@ ci-authorized:
include: include:
- .gitlab-ci/lint.yml - .gitlab-ci/lint.yml
- .gitlab-ci/shellcheck.yml - .gitlab-ci/shellcheck.yml
- .gitlab-ci/digital-ocean.yml
- .gitlab-ci/terraform.yml - .gitlab-ci/terraform.yml
- .gitlab-ci/packet.yml - .gitlab-ci/packet.yml
- .gitlab-ci/vagrant.yml

View File

@@ -0,0 +1,19 @@
---
.do_variables: &do_variables
PRIVATE_KEY: $DO_PRIVATE_KEY
CI_PLATFORM: "do"
SSH_USER: root
.do: &do
extends: .testcases
tags:
- do
do_ubuntu-canal-ha:
stage: deploy-part2
extends: .do
variables:
<<: *do_variables
when: manual
except: ['triggers']
only: ['master', /^pr-.*$/]

247
.gitlab-ci/gce.yml Normal file
View File

@@ -0,0 +1,247 @@
---
.gce_variables: &gce_variables
GCE_USER: travis
SSH_USER: $GCE_USER
CLOUD_MACHINE_TYPE: "g1-small"
CI_PLATFORM: "gce"
PRIVATE_KEY: $GCE_PRIVATE_KEY
.cache: &cache
cache:
key: "$CI_BUILD_REF_NAME"
paths:
- downloads/
- $HOME/.cache
.gce: &gce
extends: .testcases
<<: *cache
variables:
<<: *gce_variables
tags:
- gce
except: ['triggers']
only: [/^pr-.*$/]
.centos_weave_kubeadm_variables: &centos_weave_kubeadm_variables
# stage: deploy-part1
UPGRADE_TEST: "graceful"
.centos7_multus_calico_variables: &centos7_multus_calico_variables
# stage: deploy-gce
UPGRADE_TEST: "graceful"
# Builds for PRs only (premoderated by unit-tests step) and triggers (auto)
### PR JOBS PART1
gce_ubuntu18-flannel-aio:
stage: deploy-part1
<<: *gce
when: manual
### PR JOBS PART2
gce_coreos-calico-aio:
stage: deploy-gce
<<: *gce
when: on_success
gce_centos7-flannel-addons:
stage: deploy-gce
<<: *gce
when: manual
### MANUAL JOBS
gce_centos-weave-kubeadm-sep:
stage: deploy-gce
extends: .gce
variables:
<<: *centos_weave_kubeadm_variables
when: on_success
only: ['triggers']
except: []
gce_ubuntu-weave-sep:
stage: deploy-gce
<<: *gce
when: manual
only: ['triggers']
except: []
gce_coreos-calico-sep-triggers:
stage: deploy-gce
<<: *gce
when: on_success
only: ['triggers']
except: []
gce_ubuntu-canal-ha-triggers:
stage: deploy-special
<<: *gce
when: on_success
only: ['triggers']
except: []
gce_centos7-flannel-addons-triggers:
stage: deploy-gce
<<: *gce
when: on_success
only: ['triggers']
except: []
gce_ubuntu-weave-sep-triggers:
stage: deploy-gce
<<: *gce
when: on_success
only: ['triggers']
except: []
# More builds for PRs/merges (manual) and triggers (auto)
gce_ubuntu-canal-ha:
stage: deploy-special
<<: *gce
when: manual
gce_ubuntu-canal-kubeadm:
stage: deploy-gce
<<: *gce
when: manual
gce_ubuntu-canal-kubeadm-triggers:
stage: deploy-gce
<<: *gce
when: on_success
only: ['triggers']
except: []
gce_ubuntu-flannel-ha:
stage: deploy-gce
<<: *gce
when: manual
gce_centos-weave-kubeadm-triggers:
stage: deploy-gce
extends: .gce
variables:
<<: *centos_weave_kubeadm_variables
when: on_success
only: ['triggers']
except: []
gce_ubuntu-contiv-sep:
stage: deploy-special
<<: *gce
when: manual
gce_coreos-cilium:
stage: deploy-special
<<: *gce
when: manual
gce_ubuntu18-cilium-sep:
stage: deploy-special
<<: *gce
when: manual
gce_rhel7-weave:
stage: deploy-gce
<<: *gce
when: manual
gce_rhel7-weave-triggers:
stage: deploy-gce
<<: *gce
when: on_success
only: ['triggers']
except: []
gce_debian9-calico-upgrade:
stage: deploy-gce
<<: *gce
when: manual
gce_debian9-calico-triggers:
stage: deploy-gce
<<: *gce
when: on_success
only: ['triggers']
except: []
gce_coreos-canal:
stage: deploy-gce
<<: *gce
when: manual
gce_coreos-canal-triggers:
stage: deploy-gce
<<: *gce
when: on_success
only: ['triggers']
except: []
gce_rhel7-canal-sep:
stage: deploy-special
<<: *gce
when: manual
gce_rhel7-canal-sep-triggers:
stage: deploy-gce
<<: *gce
when: on_success
only: ['triggers']
except: []
gce_centos7-calico-ha:
stage: deploy-special
<<: *gce
when: manual
gce_centos7-calico-ha-triggers:
stage: deploy-gce
<<: *gce
when: on_success
only: ['triggers']
except: []
gce_centos7-kube-router:
stage: deploy-special
<<: *gce
when: manual
gce_centos7-multus-calico:
stage: deploy-gce
extends: .gce
variables:
<<: *centos7_multus_calico_variables
when: manual
gce_oracle-canal:
stage: deploy-gce
<<: *gce
when: manual
except: ['triggers']
only: ['master', /^pr-.*$/]
gce_opensuse-canal:
stage: deploy-gce
<<: *gce
when: manual
# no triggers yet https://github.com/kubernetes-incubator/kargo/issues/613
gce_coreos-alpha-weave-ha:
stage: deploy-special
<<: *gce
when: manual
gce_coreos-kube-router:
stage: deploy-special
<<: *gce
when: manual
gce_ubuntu-kube-router-sep:
stage: deploy-special
<<: *gce
when: manual

View File

@@ -2,9 +2,6 @@
yamllint: yamllint:
extends: .job extends: .job
stage: unit-tests stage: unit-tests
tags: [light]
variables:
LANG: C.UTF-8
script: script:
- yamllint --strict . - yamllint --strict .
except: ['triggers', 'master'] except: ['triggers', 'master']
@@ -12,17 +9,15 @@ yamllint:
vagrant-validate: vagrant-validate:
extends: .job extends: .job
stage: unit-tests stage: unit-tests
tags: [light]
variables:
VAGRANT_VERSION: 2.2.4
script: script:
- ./tests/scripts/vagrant-validate.sh - curl -sL https://releases.hashicorp.com/vagrant/2.2.4/vagrant_2.2.4_x86_64.deb -o /tmp/vagrant_2.2.4_x86_64.deb
- dpkg -i /tmp/vagrant_2.2.4_x86_64.deb
- vagrant validate --ignore-provider
except: ['triggers', 'master'] except: ['triggers', 'master']
ansible-lint: ansible-lint:
extends: .job extends: .job
stage: unit-tests stage: unit-tests
tags: [light]
# lint every yml/yaml file that looks like it contains Ansible plays # lint every yml/yaml file that looks like it contains Ansible plays
script: |- script: |-
grep -Rl '^- hosts: \|^ hosts: ' --include \*.yml --include \*.yaml . | xargs -P 4 -n 25 ansible-lint -v grep -Rl '^- hosts: \|^ hosts: ' --include \*.yml --include \*.yaml . | xargs -P 4 -n 25 ansible-lint -v
@@ -31,7 +26,6 @@ ansible-lint:
syntax-check: syntax-check:
extends: .job extends: .job
stage: unit-tests stage: unit-tests
tags: [light]
variables: variables:
ANSIBLE_INVENTORY: inventory/local-tests.cfg ANSIBLE_INVENTORY: inventory/local-tests.cfg
ANSIBLE_REMOTE_USER: root ANSIBLE_REMOTE_USER: root
@@ -47,30 +41,9 @@ syntax-check:
tox-inventory-builder: tox-inventory-builder:
stage: unit-tests stage: unit-tests
tags: [light]
extends: .job extends: .job
before_script:
- ./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 install -r tests/requirements.txt
script: script:
- pip3 install tox - pip install tox
- cd contrib/inventory_builder && tox - cd contrib/inventory_builder && tox
when: manual
except: ['triggers', 'master'] except: ['triggers', 'master']
markdownlint:
stage: unit-tests
tags: [light]
image: node
before_script:
- npm install -g markdownlint-cli
script:
- markdownlint README.md docs --ignore docs/_sidebar.md
ci-matrix:
stage: unit-tests
tags: [light]
image: python:3
script:
- tests/scripts/md-table/test.sh

View File

@@ -1,229 +1,122 @@
--- ---
.packet_variables: &packet_variables
CI_PLATFORM: "packet"
SSH_USER: "kubespray"
.packet: &packet .packet: &packet
extends: .testcases extends: .testcases
variables: variables:
CI_PLATFORM: "packet" <<: *packet_variables
SSH_USER: "kubespray"
tags: tags:
- packet - packet
only: [/^pr-.*$/] only: [/^pr-.*$/]
except: ['triggers'] except: ['triggers']
.test-upgrade: &test-upgrade
variables:
UPGRADE_TEST: "graceful"
packet_ubuntu18-calico-aio: packet_ubuntu18-calico-aio:
stage: deploy-part1 stage: deploy-part1
extends: .packet <<: *packet
when: on_success
# Future AIO job
packet_ubuntu20-calico-aio:
stage: deploy-part1
extends: .packet
when: on_success when: on_success
# ### PR JOBS PART2 # ### PR JOBS PART2
packet_centos7-flannel-containerd-addons-ha: packet_centos7-flannel-addons:
extends: .packet
stage: deploy-part2 stage: deploy-part2
<<: *packet
when: on_success when: on_success
variables:
MITOGEN_ENABLE: "true"
packet_centos7-crio:
extends: .packet
stage: deploy-part2
when: on_success
variables:
MITOGEN_ENABLE: "true"
packet_ubuntu18-crio:
extends: .packet
stage: deploy-part2
when: manual
variables:
MITOGEN_ENABLE: "true"
packet_ubuntu16-canal-kubeadm-ha:
stage: deploy-part2
extends: .packet
when: on_success
packet_ubuntu16-canal-sep:
stage: deploy-special
extends: .packet
when: manual
packet_ubuntu16-flannel-ha:
stage: deploy-part2
extends: .packet
when: manual
packet_ubuntu16-kube-router-sep:
stage: deploy-part2
extends: .packet
when: manual
packet_ubuntu16-kube-router-svc-proxy:
stage: deploy-part2
extends: .packet
when: manual
packet_debian10-cilium-svc-proxy:
stage: deploy-part2
extends: .packet
when: manual
packet_debian10-containerd:
stage: deploy-part2
extends: .packet
when: on_success
variables:
MITOGEN_ENABLE: "true"
packet_centos7-calico-ha-once-localhost:
stage: deploy-part2
extends: .packet
when: on_success
variables:
# This will instruct Docker not to start over TLS.
DOCKER_TLS_CERTDIR: ""
services:
- docker:19.03.9-dind
packet_centos8-kube-ovn:
stage: deploy-part2
extends: .packet
when: on_success
packet_centos8-calico:
stage: deploy-part2
extends: .packet
when: on_success
packet_fedora32-weave:
stage: deploy-part2
extends: .packet
when: on_success
packet_opensuse-canal:
stage: deploy-part2
extends: .packet
when: on_success
packet_ubuntu18-ovn4nfv:
stage: deploy-part2
extends: .packet
when: on_success
# Contiv does not work in k8s v1.16
# packet_ubuntu16-contiv-sep:
# stage: deploy-part2
# extends: .packet
# when: on_success
# ### MANUAL JOBS # ### MANUAL JOBS
packet_ubuntu16-weave-sep: packet_centos-weave-kubeadm-sep:
stage: deploy-part2 stage: deploy-part2
extends: .packet <<: *packet
when: on_success
only: ['triggers']
except: []
packet_ubuntu-weave-sep:
stage: deploy-part2
<<: *packet
when: manual when: manual
only: ['triggers']
except: []
# # More builds for PRs/merges (manual) and triggers (auto)
packet_ubuntu-canal-ha:
stage: deploy-special
<<: *packet
when: manual
packet_ubuntu-canal-kubeadm:
stage: deploy-part2
<<: *packet
when: on_success
packet_ubuntu-flannel-ha:
stage: deploy-part2
<<: *packet
when: manual
packet_ubuntu-contiv-sep:
stage: deploy-part2
<<: *packet
when: on_success
packet_ubuntu18-cilium-sep: packet_ubuntu18-cilium-sep:
stage: deploy-special stage: deploy-special
extends: .packet <<: *packet
when: manual when: manual
packet_ubuntu18-flannel-containerd-ha: packet_ubuntu18-flannel-containerd:
stage: deploy-part2 stage: deploy-part2
extends: .packet <<: *packet
when: manual when: manual
packet_ubuntu18-flannel-containerd-ha-once: packet_debian9-macvlan-sep:
stage: deploy-part2 stage: deploy-part2
extends: .packet <<: *packet
when: manual when: on_success
packet_debian9-macvlan: packet_debian9-calico-upgrade:
stage: deploy-part2 stage: deploy-part2
extends: .packet <<: *packet
when: manual when: on_success
packet_centos7-calico-ha: packet_centos7-calico-ha:
stage: deploy-part2 stage: deploy-part2
extends: .packet <<: *packet
when: manual when: manual
packet_centos7-kube-ovn:
stage: deploy-part2
<<: *packet
when: on_success
packet_centos7-kube-router: packet_centos7-kube-router:
stage: deploy-part2 stage: deploy-part2
extends: .packet <<: *packet
when: manual when: on_success
packet_centos7-multus-calico: packet_centos7-multus-calico:
stage: deploy-part2 stage: deploy-part2
extends: .packet <<: *packet
when: manual when: manual
packet_oracle7-canal-ha: packet_opensuse-canal:
stage: deploy-part2 stage: deploy-part2
extends: .packet <<: *packet
when: manual when: manual
packet_fedora31-flannel: packet_oracle-7-canal:
stage: deploy-part2 stage: deploy-part2
extends: .packet <<: *packet
when: on_success
variables:
MITOGEN_ENABLE: "true"
packet_amazon-linux-2-aio:
stage: deploy-part2
extends: .packet
when: manual when: manual
packet_fedora32-kube-ovn-containerd: packet_ubuntu-kube-router-sep:
stage: deploy-part2 stage: deploy-part2
extends: .packet <<: *packet
when: on_success when: manual
# ### PR JOBS PART3
# Long jobs (45min+)
packet_centos7-weave-upgrade-ha:
stage: deploy-part3
extends: .packet
when: on_success
variables:
UPGRADE_TEST: basic
MITOGEN_ENABLE: "false"
packet_debian9-calico-upgrade:
stage: deploy-part3
extends: .packet
when: on_success
variables:
UPGRADE_TEST: graceful
MITOGEN_ENABLE: "false"
packet_debian9-calico-upgrade-once:
stage: deploy-part3
extends: .packet
when: on_success
variables:
UPGRADE_TEST: graceful
MITOGEN_ENABLE: "false"
packet_ubuntu18-calico-ha-recover:
stage: deploy-part3
extends: .packet
when: on_success
variables:
RECOVER_CONTROL_PLANE_TEST: "true"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:],kube-master[1:]"
packet_ubuntu18-calico-ha-recover-noquorum:
stage: deploy-part3
extends: .packet
when: on_success
variables:
RECOVER_CONTROL_PLANE_TEST: "true"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[1:],kube-master[1:]"

View File

@@ -2,12 +2,11 @@
shellcheck: shellcheck:
extends: .job extends: .job
stage: unit-tests stage: unit-tests
tags: [light]
variables: variables:
SHELLCHECK_VERSION: v0.6.0 SHELLCHECK_VERSION: v0.6.0
before_script: before_script:
- ./tests/scripts/rebase.sh - ./tests/scripts/rebase.sh
- curl --silent --location "https://github.com/koalaman/shellcheck/releases/download/"${SHELLCHECK_VERSION}"/shellcheck-"${SHELLCHECK_VERSION}".linux.x86_64.tar.xz" | tar -xJv - curl --silent "https://storage.googleapis.com/shellcheck/shellcheck-"${SHELLCHECK_VERSION}".linux.x86_64.tar.xz" | tar -xJv
- cp shellcheck-"${SHELLCHECK_VERSION}"/shellcheck /usr/bin/ - cp shellcheck-"${SHELLCHECK_VERSION}"/shellcheck /usr/bin/
- shellcheck --version - shellcheck --version
script: script:

View File

@@ -3,14 +3,14 @@
.terraform_install: .terraform_install:
extends: .job extends: .job
before_script: before_script:
- update-alternatives --install /usr/bin/python python /usr/bin/python3 1
- ./tests/scripts/rebase.sh - ./tests/scripts/rebase.sh
- ./tests/scripts/testcases_prepare.sh - ./tests/scripts/testcases_prepare.sh
- ./tests/scripts/terraform_install.sh - ./tests/scripts/terraform_install.sh
# Set Ansible config # Set Ansible config
- cp ansible.cfg ~/.ansible.cfg - cp ansible.cfg ~/.ansible.cfg
# Prepare inventory # Prepare inventory
- cp contrib/terraform/$PROVIDER/sample-inventory/cluster.tfvars . - if [ "$PROVIDER" == "openstack" ]; then VARIABLEFILE="cluster.tfvars"; else VARIABLEFILE="cluster.tf"; fi
- cp contrib/terraform/$PROVIDER/sample-inventory/$VARIABLEFILE .
- ln -s contrib/terraform/$PROVIDER/hosts - ln -s contrib/terraform/$PROVIDER/hosts
- terraform init contrib/terraform/$PROVIDER - terraform init contrib/terraform/$PROVIDER
# Copy SSH keypair # Copy SSH keypair
@@ -18,29 +18,21 @@
- echo "$PACKET_PRIVATE_KEY" | base64 -d > ~/.ssh/id_rsa - echo "$PACKET_PRIVATE_KEY" | base64 -d > ~/.ssh/id_rsa
- chmod 400 ~/.ssh/id_rsa - chmod 400 ~/.ssh/id_rsa
- echo "$PACKET_PUBLIC_KEY" | base64 -d > ~/.ssh/id_rsa.pub - echo "$PACKET_PUBLIC_KEY" | base64 -d > ~/.ssh/id_rsa.pub
- mkdir -p group_vars
# Random subnet to avoid routing conflicts
- export TF_VAR_subnet_cidr="10.$(( $RANDOM % 256 )).$(( $RANDOM % 256 )).0/24"
.terraform_validate: .terraform_validate:
extends: .terraform_install extends: .terraform_install
stage: unit-tests stage: unit-tests
tags: [light]
only: ['master', /^pr-.*$/] only: ['master', /^pr-.*$/]
script: script:
- terraform validate -var-file=cluster.tfvars contrib/terraform/$PROVIDER - if [ "$PROVIDER" == "openstack" ]; then VARIABLEFILE="cluster.tfvars"; else VARIABLEFILE="cluster.tf"; fi
- terraform validate -var-file=$VARIABLEFILE contrib/terraform/$PROVIDER
- terraform fmt -check -diff contrib/terraform/$PROVIDER - terraform fmt -check -diff contrib/terraform/$PROVIDER
.terraform_apply: .terraform_apply:
extends: .terraform_install extends: .terraform_install
tags: [light] stage: deploy-part2
stage: deploy-part3
when: manual when: manual
only: [/^pr-.*$/] only: [/^pr-.*$/]
artifacts:
when: always
paths:
- cluster-dump/
variables: variables:
ANSIBLE_INVENTORY_UNPARSED_FAILED: "true" ANSIBLE_INVENTORY_UNPARSED_FAILED: "true"
ANSIBLE_INVENTORY: hosts ANSIBLE_INVENTORY: hosts
@@ -51,56 +43,56 @@
- tests/scripts/testcases_run.sh - tests/scripts/testcases_run.sh
after_script: after_script:
# Cleanup regardless of exit code # Cleanup regardless of exit code
- chronic ./tests/scripts/testcases_cleanup.sh - ./tests/scripts/testcases_cleanup.sh
tf-validate-openstack: tf-validate-openstack:
extends: .terraform_validate extends: .terraform_validate
variables: variables:
TF_VERSION: 0.12.24 TF_VERSION: 0.12.6
PROVIDER: openstack PROVIDER: openstack
CLUSTER: $CI_COMMIT_REF_NAME CLUSTER: $CI_COMMIT_REF_NAME
tf-validate-packet: tf-validate-packet:
extends: .terraform_validate extends: .terraform_validate
variables: variables:
TF_VERSION: 0.12.24 TF_VERSION: 0.11.11
PROVIDER: packet PROVIDER: packet
CLUSTER: $CI_COMMIT_REF_NAME CLUSTER: $CI_COMMIT_REF_NAME
tf-validate-aws: tf-validate-aws:
extends: .terraform_validate extends: .terraform_validate
variables: variables:
TF_VERSION: 0.12.24 TF_VERSION: 0.11.11
PROVIDER: aws PROVIDER: aws
CLUSTER: $CI_COMMIT_REF_NAME CLUSTER: $CI_COMMIT_REF_NAME
# tf-packet-ubuntu16-default: tf-packet-ubuntu16-default:
# extends: .terraform_apply extends: .terraform_apply
# variables: variables:
# TF_VERSION: 0.12.24 TF_VERSION: 0.11.11
# PROVIDER: packet PROVIDER: packet
# CLUSTER: $CI_COMMIT_REF_NAME CLUSTER: $CI_COMMIT_REF_NAME
# TF_VAR_number_of_k8s_masters: "1" TF_VAR_number_of_k8s_masters: "1"
# TF_VAR_number_of_k8s_nodes: "1" TF_VAR_number_of_k8s_nodes: "1"
# TF_VAR_plan_k8s_masters: t1.small.x86 TF_VAR_plan_k8s_masters: t1.small.x86
# TF_VAR_plan_k8s_nodes: t1.small.x86 TF_VAR_plan_k8s_nodes: t1.small.x86
# TF_VAR_facility: ewr1 TF_VAR_facility: ewr1
# TF_VAR_public_key_path: "" TF_VAR_public_key_path: ""
# TF_VAR_operating_system: ubuntu_16_04 TF_VAR_operating_system: ubuntu_16_04
#
# tf-packet-ubuntu18-default: tf-packet-ubuntu18-default:
# extends: .terraform_apply extends: .terraform_apply
# variables: variables:
# TF_VERSION: 0.12.24 TF_VERSION: 0.11.11
# PROVIDER: packet PROVIDER: packet
# CLUSTER: $CI_COMMIT_REF_NAME CLUSTER: $CI_COMMIT_REF_NAME
# TF_VAR_number_of_k8s_masters: "1" TF_VAR_number_of_k8s_masters: "1"
# TF_VAR_number_of_k8s_nodes: "1" TF_VAR_number_of_k8s_nodes: "1"
# TF_VAR_plan_k8s_masters: t1.small.x86 TF_VAR_plan_k8s_masters: t1.small.x86
# TF_VAR_plan_k8s_nodes: t1.small.x86 TF_VAR_plan_k8s_nodes: t1.small.x86
# TF_VAR_facility: ams1 TF_VAR_facility: ams1
# TF_VAR_public_key_path: "" TF_VAR_public_key_path: ""
# TF_VAR_operating_system: ubuntu_18_04 TF_VAR_operating_system: ubuntu_18_04
.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
@@ -113,87 +105,12 @@ tf-validate-aws:
OS_INTERFACE: public OS_INTERFACE: public
OS_IDENTITY_API_VERSION: "3" OS_IDENTITY_API_VERSION: "3"
# Elastx is generously donating resources for Kubespray on Openstack CI
# Contacts: @gix @bl0m1
.elastx_variables: &elastx_variables
OS_AUTH_URL: https://ops.elastx.cloud:5000
OS_PROJECT_ID: 564c6b461c6b44b1bb19cdb9c2d928e4
OS_PROJECT_NAME: kubespray_ci
OS_USER_DOMAIN_NAME: Default
OS_PROJECT_DOMAIN_ID: default
OS_USERNAME: kubespray@root314.com
OS_REGION_NAME: se-sto
OS_INTERFACE: public
OS_IDENTITY_API_VERSION: "3"
TF_VAR_router_id: "ab95917c-41fb-4881-b507-3a6dfe9403df"
# Since ELASTX is in Stockholm, Mitogen helps with latency
MITOGEN_ENABLE: "false"
# Mitogen doesn't support interpreter discovery yet
ANSIBLE_PYTHON_INTERPRETER: "/usr/bin/python3"
tf-elastx_cleanup:
stage: unit-tests
tags: [light]
image: python
variables:
<<: *elastx_variables
before_script:
- pip install -r scripts/openstack-cleanup/requirements.txt
script:
- ./scripts/openstack-cleanup/main.py
tf-elastx_ubuntu18-calico:
extends: .terraform_apply
stage: deploy-part3
when: on_success
variables:
<<: *elastx_variables
TF_VERSION: 0.12.24
PROVIDER: openstack
CLUSTER: $CI_COMMIT_REF_NAME
ANSIBLE_TIMEOUT: "60"
SSH_USER: ubuntu
TF_VAR_number_of_k8s_masters: "1"
TF_VAR_number_of_k8s_masters_no_floating_ip: "0"
TF_VAR_number_of_k8s_masters_no_floating_ip_no_etcd: "0"
TF_VAR_number_of_etcd: "0"
TF_VAR_number_of_k8s_nodes: "1"
TF_VAR_number_of_k8s_nodes_no_floating_ip: "0"
TF_VAR_number_of_gfs_nodes_no_floating_ip: "0"
TF_VAR_number_of_bastions: "0"
TF_VAR_number_of_k8s_masters_no_etcd: "0"
TF_VAR_floatingip_pool: "elx-public1"
TF_VAR_dns_nameservers: '["1.1.1.1", "8.8.8.8", "8.8.4.4"]'
TF_VAR_use_access_ip: "0"
TF_VAR_external_net: "600b8501-78cb-4155-9c9f-23dfcba88828"
TF_VAR_network_name: "ci-$CI_JOB_ID"
TF_VAR_az_list: '["sto1"]'
TF_VAR_az_list_node: '["sto1"]'
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_image: ubuntu-18.04-server-latest
TF_VAR_k8s_allowed_remote_ips: '["0.0.0.0/0"]'
tf-ovh_cleanup:
stage: unit-tests
tags: [light]
image: python
environment: ovh
variables:
<<: *ovh_variables
before_script:
- pip install -r scripts/openstack-cleanup/requirements.txt
script:
- ./scripts/openstack-cleanup/main.py
tf-ovh_ubuntu18-calico: tf-ovh_ubuntu18-calico:
extends: .terraform_apply extends: .terraform_apply
when: on_success when: on_success
environment: ovh
variables: variables:
<<: *ovh_variables <<: *ovh_variables
TF_VERSION: 0.12.24 TF_VERSION: 0.12.6
PROVIDER: openstack PROVIDER: openstack
CLUSTER: $CI_COMMIT_REF_NAME CLUSTER: $CI_COMMIT_REF_NAME
ANSIBLE_TIMEOUT: "60" ANSIBLE_TIMEOUT: "60"
@@ -215,3 +132,31 @@ tf-ovh_ubuntu18-calico:
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 18.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"]'
tf-ovh_coreos-calico:
extends: .terraform_apply
when: on_success
variables:
<<: *ovh_variables
TF_VERSION: 0.12.6
PROVIDER: openstack
CLUSTER: $CI_COMMIT_REF_NAME
ANSIBLE_TIMEOUT: "60"
SSH_USER: core
TF_VAR_number_of_k8s_masters: "0"
TF_VAR_number_of_k8s_masters_no_floating_ip: "1"
TF_VAR_number_of_k8s_masters_no_floating_ip_no_etcd: "0"
TF_VAR_number_of_etcd: "0"
TF_VAR_number_of_k8s_nodes: "0"
TF_VAR_number_of_k8s_nodes_no_floating_ip: "1"
TF_VAR_number_of_gfs_nodes_no_floating_ip: "0"
TF_VAR_number_of_bastions: "0"
TF_VAR_number_of_k8s_masters_no_etcd: "0"
TF_VAR_use_neutron: "0"
TF_VAR_floatingip_pool: "Ext-Net"
TF_VAR_external_net: "6011fbc9-4cbf-46a4-8452-6890a340b60b"
TF_VAR_network_name: "Ext-Net"
TF_VAR_flavor_k8s_master: "4d4fd037-9493-4f2b-9afe-b542b5248eac" # b2-7
TF_VAR_flavor_k8s_node: "4d4fd037-9493-4f2b-9afe-b542b5248eac" # b2-7
TF_VAR_image: "CoreOS Stable"
TF_VAR_k8s_allowed_remote_ips: '["0.0.0.0/0"]'

View File

@@ -1,54 +0,0 @@
---
molecule_tests:
tags: [c3.small.x86]
only: [/^pr-.*$/]
except: ['triggers']
image: quay.io/kubespray/vagrant:$KUBESPRAY_VERSION
services: []
stage: deploy-part1
before_script:
- 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 install -r tests/requirements.txt
- ./tests/scripts/vagrant_clean.sh
script:
- ./tests/scripts/molecule_run.sh
.vagrant:
extends: .testcases
variables:
CI_PLATFORM: "vagrant"
SSH_USER: "vagrant"
VAGRANT_DEFAULT_PROVIDER: "libvirt"
KUBESPRAY_VAGRANT_CONFIG: tests/files/${CI_JOB_NAME}.rb
tags: [c3.small.x86]
only: [/^pr-.*$/]
except: ['triggers']
image: quay.io/kubespray/vagrant:$KUBESPRAY_VERSION
services: []
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 install -r tests/requirements.txt
- ./tests/scripts/vagrant_clean.sh
script:
- ./tests/scripts/testcases_run.sh
after_script:
- chronic ./tests/scripts/testcases_cleanup.sh
vagrant_ubuntu18-flannel:
stage: deploy-part2
extends: .vagrant
when: on_success
vagrant_ubuntu18-weave-medium:
stage: deploy-part2
extends: .vagrant
when: manual
vagrant_ubuntu20-flannel:
stage: deploy-part2
extends: .vagrant
when: on_success

View File

@@ -1,2 +0,0 @@
---
MD013: false

View File

@@ -2,30 +2,10 @@
## How to become a contributor and submit your own code ## How to become a contributor and submit your own code
### Environment setup
It is recommended to use filter to manage the GitHub email notification, see [examples for setting filters to Kubernetes Github notifications](https://github.com/kubernetes/community/blob/master/communication/best-practices.md#examples-for-setting-filters-to-kubernetes-github-notifications)
To install development dependencies you can use `pip install -r tests/requirements.txt`
#### Linting
Kubespray uses `yamllint` and `ansible-lint`. To run them locally use `yamllint .` and `./tests/scripts/ansible-lint.sh`
#### Molecule
[molecule](https://github.com/ansible-community/molecule) is designed to help the development and testing of Ansible roles. In Kubespray you can run it all for all roles with `./tests/scripts/molecule_run.sh` or for a specific role (that you are working with) with `molecule test` from the role directory (`cd roles/my-role`).
When developing or debugging a role it can be useful to run `molecule create` and `molecule converge` separately. Then you can use `molecule login` to SSH into the test environment.
#### Vagrant
Vagrant with VirtualBox or libvirt driver helps you to quickly spin test clusters to test things end to end. See [README.md#vagrant](README.md)
### Contributing A Patch ### Contributing A Patch
1. Submit an issue describing your proposed change to the repo in question. 1. Submit an issue describing your proposed change to the repo in question.
2. The [repo owners](OWNERS) will respond to your issue promptly. 2. The [repo owners](OWNERS) will respond to your issue promptly.
3. Fork the desired repo, develop and test your code changes. 3. Fork the desired repo, develop and test your code changes.
4. Sign the CNCF CLA (<https://git.k8s.io/community/CLA.md#the-contributor-license-agreement>) 4. Sign the CNCF CLA (https://git.k8s.io/community/CLA.md#the-contributor-license-agreement)
5. Submit a pull request. 5. Submit a pull request.

View File

@@ -4,18 +4,15 @@ RUN mkdir /kubespray
WORKDIR /kubespray WORKDIR /kubespray
RUN apt update -y && \ RUN apt update -y && \
apt install -y \ apt install -y \
libssl-dev python3-dev sshpass apt-transport-https jq moreutils \ libssl-dev python3-dev sshpass apt-transport-https jq \
ca-certificates curl gnupg2 software-properties-common python3-pip rsync ca-certificates curl gnupg2 software-properties-common python3-pip rsync
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \ RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \
add-apt-repository \ add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \ $(lsb_release -cs) \
stable" \ stable" \
&& apt update -y && apt-get install docker-ce -y && apt update -y && apt-get install docker-ce -y
COPY . . COPY . .
RUN /usr/bin/python3 -m pip install pip -U && /usr/bin/python3 -m pip install -r tests/requirements.txt && python3 -m pip install -r requirements.txt && update-alternatives --install /usr/bin/python python /usr/bin/python3 1 RUN /usr/bin/python3 -m pip install pip -U && /usr/bin/python3 -m pip install -r tests/requirements.txt && python3 -m pip install -r requirements.txt
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.17.5/bin/linux/amd64/kubectl \ RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.14.4/bin/linux/amd64/kubectl \
&& chmod a+x kubectl && cp kubectl /usr/local/bin/kubectl && chmod a+x kubectl && cp kubectl /usr/local/bin/kubectl
# Some tools like yamllint need this
ENV LANG=C.UTF-8

View File

@@ -1,5 +1,5 @@
mitogen: mitogen:
ansible-playbook -c local mitogen.yml -vv ansible-playbook -c local mitogen.yaml -vv
clean: clean:
rm -rf dist/ rm -rf dist/
rm *.retry rm *.retry

View File

@@ -4,16 +4,18 @@ aliases:
- mattymo - mattymo
- atoms - atoms
- chadswen - chadswen
- mirwan - rsmitty
- miouge1 - bogdando
- riverzhang - bradbeam
- verwilst
- woopstar - woopstar
- luckysb - riverzhang
- holser
- smana
- verwilst
kubespray-reviewers: kubespray-reviewers:
- jjungnickel - jjungnickel
- archifleks - archifleks
- chapsuk
- mirwan
- miouge1
- holmsten - holmsten
- bozzo
- floryut
- eppo

277
README.md
View File

@@ -1,17 +1,19 @@
# 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)
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**. Deploy a Production Ready Kubernetes Cluster
============================================
If you have questions, check the [documentation](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/aws.md), GCE, [Azure](docs/azure.md), [OpenStack](docs/openstack.md), [vSphere](docs/vsphere.md), [Packet](docs/packet.md) (bare metal), Oracle Cloud Infrastructure (Experimental), or Baremetal** - Can be deployed on **AWS, GCE, Azure, OpenStack, vSphere, Packet (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**
- **Continuous integration tests** - **Continuous integration tests**
## Quick Start Quick Start
-----------
To deploy the cluster you can use : To deploy the cluster you can use :
@@ -19,35 +21,31 @@ To deploy the cluster you can use :
#### Usage #### Usage
```ShellSession # Install dependencies from ``requirements.txt``
# Install dependencies from ``requirements.txt`` sudo pip install -r requirements.txt
sudo pip3 install -r requirements.txt
# Copy ``inventory/sample`` as ``inventory/mycluster`` # Copy ``inventory/sample`` as ``inventory/mycluster``
cp -rfp inventory/sample inventory/mycluster cp -rfp inventory/sample inventory/mycluster
# Update Ansible inventory file with inventory builder # Update Ansible inventory file with inventory builder
declare -a IPS=(10.10.1.3 10.10.1.4 10.10.1.5) declare -a IPS=(10.10.1.3 10.10.1.4 10.10.1.5)
CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]} CONFIG_FILE=inventory/mycluster/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]}
# Review and change parameters under ``inventory/mycluster/group_vars`` # Review and change parameters under ``inventory/mycluster/group_vars``
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
# Deploy Kubespray with Ansible Playbook - run the playbook as root # Deploy Kubespray with Ansible Playbook - run the playbook as root
# The option `--become` is required, as for example writing SSL keys in /etc/, # The option `--become` is required, as for example writing SSL keys in /etc/,
# installing packages and interacting with various systemd daemons. # installing packages and interacting with various systemd daemons.
# Without --become the playbook will fail to run! # Without --become the playbook will fail to run!
ansible-playbook -i inventory/mycluster/hosts.yaml --become --become-user=root cluster.yml ansible-playbook -i inventory/mycluster/hosts.yml --become --become-user=root cluster.yml
```
Note: When Ansible is already installed via system packages on the control machine, other python packages installed via `sudo pip install -r requirements.txt` will go to a different directory tree (e.g. `/usr/local/lib/python2.7/dist-packages` on Ubuntu) from Ansible's (e.g. `/usr/lib/python2.7/dist-packages/ansible` still on Ubuntu). Note: When Ansible is already installed via system packages on the control machine, other python packages installed via `sudo pip install -r requirements.txt` will go to a different directory tree (e.g. `/usr/local/lib/python2.7/dist-packages` on Ubuntu) from Ansible's (e.g. `/usr/lib/python2.7/dist-packages/ansible` still on Ubuntu).
As a consequence, `ansible-playbook` command will fail with: As a consequence, `ansible-playbook` command will fail with:
```
```raw
ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path. ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.
``` ```
probably pointing on a task depending on a module present in requirements.txt (i.e. "unseal vault"). probably pointing on a task depending on a module present in requirements.txt (i.e. "unseal vault").
One way of solving this would be to uninstall the Ansible package and then, to install it via pip but it is not always possible. One way of solving this would be to uninstall the Ansible package and then, to install it via pip but it is not always possible.
@@ -58,172 +56,157 @@ A workaround consists of setting `ANSIBLE_LIBRARY` and `ANSIBLE_MODULE_UTILS` en
For Vagrant we need to install python dependencies for provisioning tasks. For Vagrant we need to install python dependencies for provisioning tasks.
Check if Python and pip are installed: Check if Python and pip are installed:
```ShellSession python -V && pip -V
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 the necessary requirements Install the necessary requirements
```ShellSession sudo pip install -r requirements.txt
sudo pip install -r requirements.txt vagrant up
vagrant up
```
## Documents Documents
---------
- [Requirements](#requirements) - [Requirements](#requirements)
- [Kubespray vs ...](docs/comparisons.md) - [Kubespray vs ...](docs/comparisons.md)
- [Getting started](docs/getting-started.md) - [Getting started](docs/getting-started.md)
- [Setting up your first cluster](docs/setting-up-your-first-cluster.md) - [Ansible inventory and tags](docs/ansible.md)
- [Ansible inventory and tags](docs/ansible.md) - [Integration with existing ansible repo](docs/integration.md)
- [Integration with existing ansible repo](docs/integration.md) - [Deployment data variables](docs/vars.md)
- [Deployment data variables](docs/vars.md) - [DNS stack](docs/dns-stack.md)
- [DNS stack](docs/dns-stack.md) - [HA mode](docs/ha-mode.md)
- [HA mode](docs/ha-mode.md) - [Network plugins](#network-plugins)
- [Network plugins](#network-plugins) - [Vagrant install](docs/vagrant.md)
- [Vagrant install](docs/vagrant.md) - [CoreOS bootstrap](docs/coreos.md)
- [Flatcar Container Linux bootstrap](docs/flatcar.md) - [Debian Jessie setup](docs/debian.md)
- [Fedora CoreOS bootstrap](docs/fcos.md) - [openSUSE setup](docs/opensuse.md)
- [Debian Jessie setup](docs/debian.md) - [Downloaded artifacts](docs/downloads.md)
- [openSUSE setup](docs/opensuse.md) - [Cloud providers](docs/cloud.md)
- [Downloaded artifacts](docs/downloads.md) - [OpenStack](docs/openstack.md)
- [Cloud providers](docs/cloud.md) - [AWS](docs/aws.md)
- [OpenStack](docs/openstack.md) - [Azure](docs/azure.md)
- [AWS](docs/aws.md) - [vSphere](docs/vsphere.md)
- [Azure](docs/azure.md) - [Packet Host](docs/packet.md)
- [vSphere](docs/vsphere.md) - [Large deployments](docs/large-deployments.md)
- [Packet Host](docs/packet.md) - [Upgrades basics](docs/upgrades.md)
- [Large deployments](docs/large-deployments.md) - [Roadmap](docs/roadmap.md)
- [Adding/replacing a node](docs/nodes.md)
- [Upgrades basics](docs/upgrades.md)
- [Air-Gap installation](docs/offline-environment.md)
- [Roadmap](docs/roadmap.md)
## Supported Linux Distributions Supported Linux Distributions
-----------------------------
- **Flatcar Container Linux by Kinvolk** - **Container Linux by CoreOS**
- **Debian** Buster, Jessie, Stretch, Wheezy - **Debian** Buster, Jessie, Stretch, Wheezy
- **Ubuntu** 16.04, 18.04, 20.04 - **Ubuntu** 16.04, 18.04
- **CentOS/RHEL** 7, 8 (experimental: see [centos 8 notes](docs/centos8.md)) - **CentOS/RHEL** 7
- **Fedora** 31, 32 - **Fedora** 28
- **Fedora CoreOS** (experimental: see [fcos Note](docs/fcos.md)) - **Fedora/CentOS** Atomic
- **openSUSE** Leap 42.3/Tumbleweed - **openSUSE** Leap 42.3/Tumbleweed
- **Oracle Linux** 7, 8 (experimental: [centos 8 notes](docs/centos8.md) apply) - **Oracle Linux** 7
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.18.9 - [kubernetes](https://github.com/kubernetes/kubernetes) v1.15.11
- [etcd](https://github.com/coreos/etcd) v3.4.3 - [etcd](https://github.com/coreos/etcd) v3.3.10
- [docker](https://www.docker.com/) v19.03 (see note) - [docker](https://www.docker.com/) v18.06 (see note)
- [containerd](https://containerd.io/) v1.2.13 - [cri-o](http://cri-o.io/) v1.11.5 (experimental: see [CRI-O Note](docs/cri-o.md). Only on centos based OS)
- [cri-o](http://cri-o.io/) v1.17 (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) v0.8.1
- [cni-plugins](https://github.com/containernetworking/plugins) v0.8.6 - [calico](https://github.com/projectcalico/calico) v3.7.3
- [calico](https://github.com/projectcalico/calico) v3.15.2 - [canal](https://github.com/projectcalico/canal) (given calico/flannel versions)
- [canal](https://github.com/projectcalico/canal) (given calico/flannel versions) - [cilium](https://github.com/cilium/cilium) v1.5.5
- [cilium](https://github.com/cilium/cilium) v1.8.3 - [contiv](https://github.com/contiv/install) v1.2.1
- [contiv](https://github.com/contiv/install) v1.2.1 - [flanneld](https://github.com/coreos/flannel) v0.11.0
- [flanneld](https://github.com/coreos/flannel) v0.12.0 - [kube-router](https://github.com/cloudnativelabs/kube-router) v0.2.5
- [kube-ovn](https://github.com/alauda/kube-ovn) v1.3.0 - [multus](https://github.com/intel/multus-cni) v3.2.1
- [kube-router](https://github.com/cloudnativelabs/kube-router) v1.0.1 - [weave](https://github.com/weaveworks/weave) v2.5.2
- [multus](https://github.com/intel/multus-cni) v3.6.0 - Application
- [ovn4nfv](https://github.com/opnfv/ovn4nfv-k8s-plugin) v1.1.0 - [cephfs-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.0-k8s1.11
- [weave](https://github.com/weaveworks/weave) v2.7.0 - [rbd-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.1-k8s1.11
- Application - [cert-manager](https://github.com/jetstack/cert-manager) v0.5.2
- [ambassador](https://github.com/datawire/ambassador): v1.5 - [coredns](https://github.com/coredns/coredns) v1.6.0
- [cephfs-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.0-k8s1.11 - [ingress-nginx](https://github.com/kubernetes/ingress-nginx) v0.25.1
- [rbd-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.1-k8s1.11
- [cert-manager](https://github.com/jetstack/cert-manager) v0.16.1
- [coredns](https://github.com/coredns/coredns) v1.6.7
- [ingress-nginx](https://github.com/kubernetes/ingress-nginx) v0.35.0
Note: The list of validated [docker versions](https://kubernetes.io/docs/setup/production-environment/container-runtimes/#docker) is 1.13.1, 17.03, 17.06, 17.09, 18.06, 18.09 and 19.03. The recommended docker version is 19.03. The 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. yum versionlock plugin or apt pin). Note: The list of validated [docker versions](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.13.md) was updated to 1.11.1, 1.12.1, 1.13.1, 17.03, 17.06, 17.09, 18.06. kubeadm now properly recognizes Docker 18.09.0 and newer, but still treats 18.06 as the default supported version. The 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. yum versionlock plugin or apt pin).
## Requirements Requirements
------------
- **Minimum required version of Kubernetes is v1.17** - **Minimum required version of Kubernetes is v1.14**
- **Ansible v2.9+, Jinja 2.11+ and python-netaddr is installed on the machine that will run Ansible commands** - **Ansible v2.7.8 (or newer, but [not 2.8.x](https://github.com/kubernetes-sigs/kubespray/issues/4778)) and python-netaddr is installed on the machine
- 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)) that will run Ansible commands**
- The target servers are configured to allow **IPv4 forwarding**. - **Jinja 2.9 (or newer) is required to run the Ansible Playbooks**
- **Your ssh key must be copied** to all the servers part of your inventory. - The target servers must have **access to the Internet** in order to pull docker images. Otherwise, additional configuration is required (See [Offline Environment](https://github.com/kubernetes-sigs/kubespray/blob/master/docs/downloads.md#offline-environment))
- The **firewalls are not managed**, you'll need to implement your own rules the way you used to. - The target servers are configured to allow **IPv4 forwarding**.
- **Your ssh key must be copied** to all the servers part of your inventory.
- The **firewalls are not managed**, you'll need to implement your own rules the way you used to.
in order to avoid any issue during deployment you should disable your firewall. in order to avoid any issue during deployment you should disable your firewall.
- If kubespray is ran from non-root user account, correct privilege escalation method - If kubespray is ran from non-root user account, correct privilege escalation method
should be configured in the target servers. Then the `ansible_become` flag should be configured in the target servers. Then the `ansible_become` flag
or command parameters `--become or -b` should be specified. or command parameters `--become or -b` should be specified.
Hardware: Hardware:
These limits are safe guarded by Kubespray. Actual requirements for your workload can differ. For a sizing guide go to the [Building Large Clusters](https://kubernetes.io/docs/setup/cluster-large/#size-of-master-and-master-components) guide. These limits are safe guarded by Kubespray. Actual requirements for your workload can differ. For a sizing guide go to the [Building Large Clusters](https://kubernetes.io/docs/setup/cluster-large/#size-of-master-and-master-components) guide.
- Master - Master
- Memory: 1500 MB - Memory: 1500 MB
- Node - Node
- Memory: 1024 MB - Memory: 1024 MB
## Network Plugins Network Plugins
---------------
You can choose between 10 network plugins. (default: `calico`, except Vagrant uses `flannel`) You can choose between 10 network plugins. (default: `calico`, except Vagrant uses `flannel`)
- [flannel](docs/flannel.md): gre/vxlan (layer 2) networking. - [flannel](docs/flannel.md): gre/vxlan (layer 2) networking.
- [Calico](https://docs.projectcalico.org/latest/introduction/) is a networking and network policy provider. Calico supports a flexible set of networking options - [calico](docs/calico.md): bgp (layer 3) networking.
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,
pods, and (if using Istio and Envoy) applications at the service mesh layer.
- [canal](https://github.com/projectcalico/canal): a composition of calico and flannel plugins. - [canal](https://github.com/projectcalico/canal): a composition of calico and flannel plugins.
- [cilium](http://docs.cilium.io/en/latest/): layer 3/4 networking (as well as layer 7 to protect and secure application protocols), supports dynamic insertion of BPF bytecode into the Linux kernel to implement security services, networking and visibility logic. - [cilium](http://docs.cilium.io/en/latest/): layer 3/4 networking (as well as layer 7 to protect and secure application protocols), supports dynamic insertion of BPF bytecode into the Linux kernel to implement security services, networking and visibility logic.
- [contiv](docs/contiv.md): supports vlan, vxlan, bgp and Cisco SDN networking. This plugin is able to - [contiv](docs/contiv.md): supports vlan, vxlan, bgp and Cisco SDN networking. This plugin is able to
apply firewall policies, segregate containers in multiple network and bridging pods onto physical networks. apply firewall policies, segregate containers in multiple network and bridging pods onto physical networks.
- [ovn4nfv](docs/ovn4nfv.md): [ovn4nfv-k8s-plugins](https://github.com/opnfv/ovn4nfv-k8s-plugin) is the network controller, OVS agent and CNI server to offer basic SFC and OVN overlay networking. - [weave](docs/weave.md): Weave is a lightweight container overlay network that doesn't require an external K/V database cluster.
- [weave](docs/weave.md): Weave is a lightweight container overlay network that doesn't require an external K/V database cluster.
(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/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/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/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/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.
The choice is defined with the variable `kube_network_plugin`. There is also an The choice is defined with the variable `kube_network_plugin`. There is also an
option to leverage built-in cloud provider networking instead. option to leverage built-in cloud provider networking instead.
See also [Network checker](docs/netcheck.md). See also [Network checker](docs/netcheck.md).
## Ingress Plugins Community docs and resources
----------------------------
- [ambassador](docs/ambassador.md): the Ambassador Ingress Controller and API gateway. - [kubernetes.io/docs/getting-started-guides/kubespray/](https://kubernetes.io/docs/getting-started-guides/kubespray/)
- [kubespray, monitoring and logging](https://github.com/gregbkr/kubernetes-kargo-logging-monitoring) by @gregbkr
- [Deploy Kubernetes w/ Ansible & Terraform](https://rsmitty.github.io/Terraform-Ansible-Kubernetes/) by @rsmitty
- [Deploy a Kubernetes Cluster with Kubespray (video)](https://www.youtube.com/watch?v=N9q51JgbWu8)
- [nginx](https://kubernetes.github.io/ingress-nginx): the NGINX Ingress Controller. Tools and projects on top of Kubespray
--------------------------------------
## Community docs and resources - [Digital Rebar Provision](https://github.com/digitalrebar/provision/blob/master/doc/integrations/ansible.rst)
- [Terraform Contrib](https://github.com/kubernetes-sigs/kubespray/tree/master/contrib/terraform)
- [kubernetes.io/docs/setup/production-environment/tools/kubespray/](https://kubernetes.io/docs/setup/production-environment/tools/kubespray/) CI Tests
- [kubespray, monitoring and logging](https://github.com/gregbkr/kubernetes-kargo-logging-monitoring) by @gregbkr --------
- [Deploy Kubernetes w/ Ansible & Terraform](https://rsmitty.github.io/Terraform-Ansible-Kubernetes/) by @rsmitty
- [Deploy a Kubernetes Cluster with Kubespray (video)](https://www.youtube.com/watch?v=CJ5G4GpqDy0)
## Tools and projects on top of Kubespray [![Build graphs](https://gitlab.com/kargo-ci/kubernetes-sigs-kubespray/badges/master/build.svg)](https://gitlab.com/kargo-ci/kubernetes-sigs-kubespray/pipelines)
- [Digital Rebar Provision](https://github.com/digitalrebar/provision/blob/v4/doc/integrations/ansible.rst)
- [Terraform Contrib](https://github.com/kubernetes-sigs/kubespray/tree/master/contrib/terraform)
## CI Tests
[![Build graphs](https://gitlab.com/kargo-ci/kubernetes-sigs-kubespray/badges/master/pipeline.svg)](https://gitlab.com/kargo-ci/kubernetes-sigs-kubespray/pipelines)
CI/end-to-end tests sponsored by: [CNCF](https://cncf.io), [Packet](https://www.packet.com/), [OVHcloud](https://www.ovhcloud.com/), [ELASTX](https://elastx.se/).
CI/end-to-end tests sponsored by Google (GCE)
See the [test matrix](docs/test_cases.md) for details. See the [test matrix](docs/test_cases.md) for details.

View File

@@ -3,46 +3,38 @@
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 1. An issue is proposing a new release with a changelog since the last release
2. At least one of the [approvers](OWNERS_ALIASES) must approve this release 2. At least one of the [OWNERS](OWNERS) must LGTM this release
3. The `kube_version_min_required` variable is set to `n-1` 3. An OWNER runs `git tag -s $VERSION` and inserts the changelog and pushes the tag with `git push $VERSION`
4. Remove hashes for [EOL versions](https://github.com/kubernetes/sig-release/blob/master/releases/patch-releases.md) of kubernetes from `*_checksums` variables. 4. The release issue is closed
5. 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 5. An announcement email is sent to `kubernetes-dev@googlegroups.com` with the subject `[ANNOUNCE] Kubespray $VERSION is released`
6. An approver creates a release branch in the form `release-X.Y`
7. 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) docker images are built and tagged
8. The `KUBESPRAY_VERSION` variable is updated in `.gitlab-ci.yml`
9. The release issue is closed
10. An announcement email is sent to `kubernetes-dev@googlegroups.com` with the subject `[ANNOUNCE] Kubespray $VERSION is released`
11. The topic of the #kubespray channel is updated with `vX.Y.Z is released! | ...`
## Major/minor releases and milestones ## Major/minor releases, merge freezes and milestones
* For major releases (vX.Y) Kubespray maintains one branch (`release-X.Y`). Minor releases (vX.Y.Z) are available only as tags. * Kubespray does not maintain stable branches for releases. Releases are tags, not
branches, and there are no backports. Therefore, there is no need for merge
freezes as well.
* Security patches and bugs might be backported. * Fixes for major releases (vX.x.0) and minor releases (vX.Y.x) are delivered
* Fixes for major releases (vX.Y) and minor releases (vX.Y.Z) are delivered
via maintenance releases (vX.Y.Z) and assigned to the corresponding open via maintenance releases (vX.Y.Z) and assigned to the corresponding open
[GitHub milestone](https://github.com/kubernetes-sigs/kubespray/milestones). milestone (vX.Y). That milestone remains open for the major/minor releases
That milestone remains open for the major/minor releases support lifetime, support lifetime, which ends once the milestone closed. Then only a next major
which ends once the milestone is closed. Then only a next major or minor release or minor release can be done.
can be done.
* Kubespray major and minor releases are bound to the given `kube_version` major/minor * Kubespray major and minor releases are bound to the given ``kube_version`` major/minor
version numbers and other components' arbitrary versions, like etcd or network plugins. version numbers and other components' arbitrary versions, like etcd or network plugins.
Older or newer component versions are not supported and not tested for the given Older or newer versions are not supported and not tested for the given release.
release (even if included in the checksum variables, like `kubeadm_checksums`).
* There is no unstable releases and no APIs, thus Kubespray doesn't follow * There is no unstable releases and no APIs, thus Kubespray doesn't follow
[semver](https://semver.org/). Every version describes only a stable release. [semver](http://semver.org/). Every version describes only a stable release.
Breaking changes, if any introduced by changed defaults or non-contrib ansible roles' Breaking changes, if any introduced by changed defaults or non-contrib ansible roles'
playbooks, shall be described in the release notes. Other breaking changes, if any in playbooks, shall be described in the release notes. Other breaking changes, if any in
the contributed addons or bound versions of Kubernetes and other components, are the contributed addons or bound versions of Kubernetes and other components, are
considered out of Kubespray scope and are up to the components' teams to deal with and considered out of Kubespray scope and are up to the components' teams to deal with and
document. document.
* Minor releases can change components' versions, but not the major `kube_version`. * Minor releases can change components' versions, but not the major ``kube_version``.
Greater `kube_version` requires a new major or minor release. For example, if Kubespray v2.0.0 Greater ``kube_version`` requires a new major or minor release. For example, if Kubespray v2.0.0
is bound to `kube_version: 1.4.x`, `calico_version: 0.22.0`, `etcd_version: v3.0.6`, is bound to ``kube_version: 1.4.x``, ``calico_version: 0.22.0``, ``etcd_version: v3.0.6``,
then Kubespray v2.1.0 may be bound to only minor changes to `kube_version`, like v1.5.1 then Kubespray v2.1.0 may be bound to only minor changes to ``kube_version``, like v1.5.1
and *any* changes to other components, like etcd v4, or calico 1.2.3. and *any* changes to other components, like etcd v4, or calico 1.2.3.
And Kubespray v3.x.x shall be bound to `kube_version: 2.x.x` respectively. And Kubespray v3.x.x shall be bound to ``kube_version: 2.x.x`` respectively.

View File

@@ -1,13 +1,13 @@
# Defined below are the security contacts for this repo. # Defined below are the security contacts for this repo.
# #
# They are the contact point for the Product Security Committee to reach out # They are the contact point for the Product Security Team to reach out
# to for triaging and handling of incoming issues. # to for triaging and handling of incoming issues.
# #
# The below names agree to abide by the # The below names agree to abide by the
# [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy) # [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy)
# and will be removed and replaced if they violate that agreement. # and will be removed and replaced if they violate that agreement.
# #
# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE
# INSTRUCTIONS AT https://kubernetes.io/security/ # INSTRUCTIONS AT https://kubernetes.io/security/
atoms atoms
mattymo mattymo

114
Vagrantfile vendored
View File

@@ -7,72 +7,63 @@ require 'fileutils'
Vagrant.require_version ">= 2.0.0" Vagrant.require_version ">= 2.0.0"
CONFIG = File.join(File.dirname(__FILE__), ENV['KUBESPRAY_VAGRANT_CONFIG'] || 'vagrant/config.rb') CONFIG = File.join(File.dirname(__FILE__), "vagrant/config.rb")
FLATCAR_URL_TEMPLATE = "https://%s.release.flatcar-linux.net/amd64-usr/current/flatcar_production_vagrant.json" COREOS_URL_TEMPLATE = "https://storage.googleapis.com/%s.release.core-os.net/amd64-usr/current/coreos_production_vagrant.json"
# Uniq disk UUID for libvirt # Uniq disk UUID for libvirt
DISK_UUID = Time.now.utc.to_i DISK_UUID = Time.now.utc.to_i
SUPPORTED_OS = { SUPPORTED_OS = {
"flatcar-stable" => {box: "flatcar-stable", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["stable"]}, "coreos-stable" => {box: "coreos-stable", user: "core", box_url: COREOS_URL_TEMPLATE % ["stable"]},
"flatcar-beta" => {box: "flatcar-beta", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["beta"]}, "coreos-alpha" => {box: "coreos-alpha", user: "core", box_url: COREOS_URL_TEMPLATE % ["alpha"]},
"flatcar-alpha" => {box: "flatcar-alpha", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["alpha"]}, "coreos-beta" => {box: "coreos-beta", user: "core", box_url: COREOS_URL_TEMPLATE % ["beta"]},
"flatcar-edge" => {box: "flatcar-edge", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["edge"]}, "ubuntu1604" => {box: "generic/ubuntu1604", user: "vagrant"},
"ubuntu1604" => {box: "generic/ubuntu1604", user: "vagrant"}, "ubuntu1804" => {box: "generic/ubuntu1804", user: "vagrant"},
"ubuntu1804" => {box: "generic/ubuntu1804", user: "vagrant"}, "centos" => {box: "centos/7", user: "vagrant"},
"ubuntu2004" => {box: "generic/ubuntu2004", user: "vagrant"}, "centos-bento" => {box: "bento/centos-7.6", user: "vagrant"},
"centos" => {box: "centos/7", user: "vagrant"}, "fedora" => {box: "fedora/28-cloud-base", user: "vagrant"},
"centos-bento" => {box: "bento/centos-7.6", user: "vagrant"}, "opensuse" => {box: "opensuse/openSUSE-15.0-x86_64", user: "vagrant"},
"centos8" => {box: "centos/8", user: "vagrant"}, "opensuse-tumbleweed" => {box: "opensuse/openSUSE-Tumbleweed-x86_64", user: "vagrant"},
"centos8-bento" => {box: "bento/centos-8", user: "vagrant"}, "oraclelinux" => {box: "generic/oracle7", user: "vagrant"},
"fedora31" => {box: "fedora/31-cloud-base", user: "vagrant"},
"fedora32" => {box: "fedora/32-cloud-base", user: "vagrant"},
"opensuse" => {box: "bento/opensuse-leap-15.1", user: "vagrant"},
"opensuse-tumbleweed" => {box: "opensuse/Tumbleweed.x86_64", user: "vagrant"},
"oraclelinux" => {box: "generic/oracle7", user: "vagrant"},
"oraclelinux8" => {box: "generic/oracle8", user: "vagrant"},
} }
# Defaults for config options defined in CONFIG
$num_instances = 3
$instance_name_prefix = "k8s"
$vm_gui = false
$vm_memory = 2048
$vm_cpus = 1
$shared_folders = {}
$forwarded_ports = {}
$subnet = "172.17.8"
$os = "ubuntu1804"
$network_plugin = "flannel"
# Setting multi_networking to true will install Multus: https://github.com/intel/multus-cni
$multi_networking = false
# The first three nodes are etcd servers
$etcd_instances = $num_instances
# The first two nodes are kube masters
$kube_master_instances = $num_instances == 1 ? $num_instances : ($num_instances - 1)
# All nodes are kube nodes
$kube_node_instances = $num_instances
# The following only works when using the libvirt provider
$kube_node_instances_with_disks = false
$kube_node_instances_with_disks_size = "20G"
$kube_node_instances_with_disks_number = 2
$override_disk_size = false
$disk_size = "20GB"
$local_path_provisioner_enabled = false
$local_path_provisioner_claim_root = "/opt/local-path-provisioner/"
$playbook = "cluster.yml"
host_vars = {}
if File.exist?(CONFIG) if File.exist?(CONFIG)
require CONFIG require CONFIG
end end
# Defaults for config options defined in CONFIG
$num_instances ||= 3
$instance_name_prefix ||= "k8s"
$vm_gui ||= false
$vm_memory ||= 2048
$vm_cpus ||= 2
$shared_folders ||= {}
$forwarded_ports ||= {}
$subnet ||= "172.18.8"
$os ||= "ubuntu1804"
$network_plugin ||= "flannel"
# Setting multi_networking to true will install Multus: https://github.com/intel/multus-cni
$multi_networking ||= false
$download_run_once ||= "True"
$download_force_cache ||= "True"
# The first three nodes are etcd servers
$etcd_instances ||= $num_instances
# The first two nodes are kube masters
$kube_master_instances ||= $num_instances == 1 ? $num_instances : ($num_instances - 1)
# All nodes are kube nodes
$kube_node_instances ||= $num_instances
# The following only works when using the libvirt provider
$kube_node_instances_with_disks ||= false
$kube_node_instances_with_disks_size ||= "20G"
$kube_node_instances_with_disks_number ||= 2
$override_disk_size ||= false
$disk_size ||= "20GB"
$local_path_provisioner_enabled ||= false
$local_path_provisioner_claim_root ||= "/opt/local-path-provisioner/"
$libvirt_nested ||= false
$playbook ||= "cluster.yml"
host_vars = {}
$box = SUPPORTED_OS[$os][:box] $box = SUPPORTED_OS[$os][:box]
# if $inventory is not set, try to use example # if $inventory is not set, try to use example
$inventory = "inventory/sample" if ! $inventory $inventory = "inventory/sample" if ! $inventory
@@ -145,8 +136,6 @@ Vagrant.configure("2") do |config|
end end
node.vm.provider :libvirt do |lv| node.vm.provider :libvirt do |lv|
lv.nested = $libvirt_nested
lv.cpu_mode = "host-model"
lv.memory = $vm_memory lv.memory = $vm_memory
lv.cpus = $vm_cpus lv.cpus = $vm_cpus
lv.default_prefix = 'kubespray' lv.default_prefix = 'kubespray'
@@ -187,24 +176,19 @@ 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"
# Disable firewalld on oraclelinux vms
if ["oraclelinux","oraclelinux8"].include? $os
node.vm.provision "shell", inline: "systemctl stop firewalld; systemctl disable firewalld"
end
host_vars[vm_name] = { host_vars[vm_name] = {
"ip": ip, "ip": ip,
"flannel_interface": "eth1", "flannel_interface": "eth1",
"kube_network_plugin": $network_plugin, "kube_network_plugin": $network_plugin,
"kube_network_plugin_multus": $multi_networking, "kube_network_plugin_multus": $multi_networking,
"download_run_once": $download_run_once, "download_run_once": "True",
"download_localhost": "False", "download_localhost": "False",
"download_cache_dir": ENV['HOME'] + "/kubespray_cache", "download_cache_dir": ENV['HOME'] + "/kubespray_cache",
# Make kubespray cache even when download_run_once is false # Make kubespray cache even when download_run_once is false
"download_force_cache": $download_force_cache, "download_force_cache": "True",
# Keeping the cache on the nodes can improve provisioning speed while debugging kubespray # Keeping the cache on the nodes can improve provisioning speed while debugging kubespray
"download_keep_remote_cache": "False", "download_keep_remote_cache": "False",
"docker_rpm_keepcache": "1", "docker_keepcache": "1",
# These two settings will put kubectl and admin.config in $inventory/artifacts # These two settings will put kubectl and admin.config in $inventory/artifacts
"kubeconfig_localhost": "True", "kubeconfig_localhost": "True",
"kubectl_localhost": "True", "kubectl_localhost": "True",
@@ -222,7 +206,7 @@ Vagrant.configure("2") do |config|
ansible.inventory_path = $ansible_inventory_path ansible.inventory_path = $ansible_inventory_path
end end
ansible.become = true ansible.become = true
ansible.limit = "all,localhost" ansible.limit = "all"
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

View File

@@ -1,2 +1,2 @@
--- ---
theme: jekyll-theme-slate theme: jekyll-theme-slate

View File

@@ -11,13 +11,11 @@ host_key_checking=False
gathering = smart gathering = smart
fact_caching = jsonfile fact_caching = jsonfile
fact_caching_connection = /tmp fact_caching_connection = /tmp
fact_caching_timeout = 7200 stdout_callback = skippy
stdout_callback = default
display_skipped_hosts = no
library = ./library library = ./library
callback_whitelist = profile_tasks callback_whitelist = profile_tasks
roles_path = roles:$VIRTUAL_ENV/usr/local/share/kubespray/roles:$VIRTUAL_ENV/usr/local/share/ansible/roles:/usr/share/kubespray/roles roles_path = roles:$VIRTUAL_ENV/usr/local/share/kubespray/roles:$VIRTUAL_ENV/usr/local/share/ansible/roles:/usr/share/kubespray/roles
deprecation_warnings=False deprecation_warnings=False
inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo, .creds, .gpg inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo, .creds
[inventory] [inventory]
ignore_patterns = artifacts, credentials ignore_patterns = artifacts, credentials

View File

@@ -1,15 +0,0 @@
---
- hosts: localhost
gather_facts: false
become: no
vars:
minimal_ansible_version: 2.8.0
ansible_connection: local
tasks:
- name: "Check ansible version >={{ minimal_ansible_version }}"
assert:
msg: "Ansible must be {{ minimal_ansible_version }} or higher"
that:
- ansible_version.string is version(minimal_ansible_version, ">=")
tags:
- check

View File

@@ -1,55 +1,44 @@
--- ---
- name: Check ansible version - hosts: localhost
import_playbook: ansible_version.yml
- hosts: all
gather_facts: false gather_facts: false
tags: always become: no
tasks: tasks:
- name: "Set up proxy environment" - name: "Check ansible version >=2.7.8"
set_fact: assert:
proxy_env: msg: "Ansible must be v2.7.8 or higher"
http_proxy: "{{ http_proxy | default ('') }}" that:
HTTP_PROXY: "{{ http_proxy | default ('') }}" - ansible_version.string is version("2.7.8", ">=")
https_proxy: "{{ https_proxy | default ('') }}" tags:
HTTPS_PROXY: "{{ https_proxy | default ('') }}" - check
no_proxy: "{{ no_proxy | default ('') }}" vars:
NO_PROXY: "{{ no_proxy | default ('') }}" ansible_connection: local
no_log: true
- hosts: bastion[0] - hosts: bastion[0]
gather_facts: False gather_facts: False
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- { role: bastion-ssh-config, tags: ["localhost", "bastion"] } - { role: bastion-ssh-config, tags: ["localhost", "bastion"]}
- hosts: k8s-cluster:etcd - hosts: k8s-cluster:etcd
strategy: linear
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
gather_facts: false gather_facts: false
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- { role: bootstrap-os, tags: bootstrap-os} - { role: bootstrap-os, tags: bootstrap-os}
- name: Gather facts
tags: always
import_playbook: facts.yml
- hosts: k8s-cluster:etcd - hosts: k8s-cluster:etcd
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- { role: kubernetes/preinstall, tags: preinstall } - { role: kubernetes/preinstall, tags: preinstall }
- { role: "container-engine", tags: "container-engine", when: deploy_container_engine|default(true) } - { role: "container-engine", tags: "container-engine", when: deploy_container_engine|default(true) }
- { role: download, tags: download, when: "not skip_downloads" } - { role: download, tags: download, when: "not skip_downloads" }
environment: "{{ proxy_env }}" environment: "{{ proxy_env }}"
- hosts: etcd - hosts: etcd
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- role: etcd - role: etcd
tags: etcd tags: etcd
vars: vars:
@@ -58,10 +47,9 @@
when: not etcd_kubeadm_enabled| default(false) when: not etcd_kubeadm_enabled| default(false)
- hosts: k8s-cluster - hosts: k8s-cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- role: etcd - role: etcd
tags: etcd tags: etcd
vars: vars:
@@ -70,68 +58,58 @@
when: not etcd_kubeadm_enabled| default(false) when: not etcd_kubeadm_enabled| default(false)
- hosts: k8s-cluster - hosts: k8s-cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- { role: kubernetes/node, tags: node } - { role: kubernetes/node, tags: node }
environment: "{{ proxy_env }}" environment: "{{ proxy_env }}"
- hosts: kube-master - hosts: kube-master
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- { role: kubernetes/master, tags: master } - { role: kubernetes/master, tags: master }
- { role: kubernetes/client, tags: client } - { role: kubernetes/client, tags: client }
- { role: kubernetes-apps/cluster_roles, tags: cluster-roles } - { role: kubernetes-apps/cluster_roles, tags: cluster-roles }
- hosts: k8s-cluster - hosts: k8s-cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- { role: kubernetes/kubeadm, tags: kubeadm} - { role: kubernetes/kubeadm, tags: kubeadm}
- { role: network_plugin, tags: network } - { role: network_plugin, tags: network }
- { role: kubernetes/node-label, tags: node-label }
- hosts: calico-rr - hosts: calico-rr
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- { role: network_plugin/calico/rr, tags: ['network', 'calico_rr'] } - { role: network_plugin/calico/rr, tags: ['network', 'calico_rr']}
- hosts: kube-master[0] - hosts: kube-master[0]
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- { role: kubernetes-apps/rotate_tokens, tags: rotate_tokens, when: "secret_changed|default(false)" } - { role: kubernetes-apps/rotate_tokens, tags: rotate_tokens, when: "secret_changed|default(false)" }
- { role: win_nodes/kubernetes_patch, tags: ["master", "win_nodes"] } - { role: win_nodes/kubernetes_patch, tags: ["master", "win_nodes"]}
- hosts: kube-master - hosts: kube-master
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- { role: kubernetes-apps/external_cloud_controller, tags: external-cloud-controller }
- { role: kubernetes-apps/network_plugin, tags: network } - { role: kubernetes-apps/network_plugin, tags: network }
- { role: kubernetes-apps/policy_controller, tags: policy-controller } - { role: kubernetes-apps/policy_controller, tags: policy-controller }
- { role: kubernetes-apps/ingress_controller, tags: ingress-controller } - { role: kubernetes-apps/ingress_controller, tags: ingress-controller }
- { role: kubernetes-apps/external_provisioner, tags: external-provisioner } - { role: kubernetes-apps/external_provisioner, tags: external-provisioner }
- hosts: kube-master - hosts: kube-master
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- { role: kubernetes-apps, tags: apps } - { role: kubernetes-apps, tags: apps }
environment: "{{ proxy_env }}" environment: "{{ proxy_env }}"
- hosts: k8s-cluster - hosts: k8s-cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}" any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
roles: roles:
- { role: kubespray-defaults } - { role: kubespray-defaults}
- { role: kubernetes/preinstall, when: "dns_mode != 'none' and resolvconf_mode == 'host_resolvconf'", tags: resolvconf, dns_late: true } - { role: kubernetes/preinstall, when: "dns_mode != 'none' and resolvconf_mode == 'host_resolvconf'", tags: resolvconf, dns_late: true }

View File

@@ -15,9 +15,8 @@ Resource Group. It will not install Kubernetes itself, this has to be done in a
## Configuration through group_vars/all ## Configuration through group_vars/all
You have to modify at least two variables in group_vars/all. The one is the **cluster_name** variable, it must be globally You have to modify at least one variable in group_vars/all, which is the **cluster_name** variable. It must be globally
unique due to some restrictions in Azure. The other one is the **ssh_public_keys** variable, it must be your ssh public unique due to some restrictions in Azure. Most other variables should be self explanatory if you have some basic Kubernetes
key to access your azure virtual machines. Most other variables should be self explanatory if you have some basic Kubernetes
experience. experience.
## Bastion host ## Bastion host
@@ -60,7 +59,6 @@ It will create the file ./inventory which can then be used with kubespray, e.g.:
```shell ```shell
$ cd kubespray-root-dir $ cd kubespray-root-dir
$ sudo pip3 install -r requirements.txt $ ansible-playbook -i contrib/azurerm/inventory -u devops --become -e "@inventory/sample/group_vars/all.yml" cluster.yml
$ ansible-playbook -i contrib/azurerm/inventory -u devops --become -e "@inventory/sample/group_vars/all/all.yml" cluster.yml
``` ```

View File

@@ -9,11 +9,18 @@ if [ "$AZURE_RESOURCE_GROUP" == "" ]; then
exit 1 exit 1
fi fi
ansible-playbook generate-templates.yml if az &>/dev/null; then
echo "azure cli 2.0 found, using it instead of 1.0"
az deployment group create --template-file ./.generated/network.json -g $AZURE_RESOURCE_GROUP ./apply-rg_2.sh "$AZURE_RESOURCE_GROUP"
az deployment group create --template-file ./.generated/storage.json -g $AZURE_RESOURCE_GROUP elif azure &>/dev/null; then
az deployment group create --template-file ./.generated/availability-sets.json -g $AZURE_RESOURCE_GROUP ansible-playbook generate-templates.yml
az deployment group create --template-file ./.generated/bastion.json -g $AZURE_RESOURCE_GROUP
az deployment group create --template-file ./.generated/masters.json -g $AZURE_RESOURCE_GROUP azure group deployment create -f ./.generated/network.json -g $AZURE_RESOURCE_GROUP
az deployment group create --template-file ./.generated/minions.json -g $AZURE_RESOURCE_GROUP azure group deployment create -f ./.generated/storage.json -g $AZURE_RESOURCE_GROUP
azure group deployment create -f ./.generated/availability-sets.json -g $AZURE_RESOURCE_GROUP
azure group deployment create -f ./.generated/bastion.json -g $AZURE_RESOURCE_GROUP
azure group deployment create -f ./.generated/masters.json -g $AZURE_RESOURCE_GROUP
azure group deployment create -f ./.generated/minions.json -g $AZURE_RESOURCE_GROUP
else
echo "Azure cli not found"
fi

19
contrib/azurerm/apply-rg_2.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -e
AZURE_RESOURCE_GROUP="$1"
if [ "$AZURE_RESOURCE_GROUP" == "" ]; then
echo "AZURE_RESOURCE_GROUP is missing"
exit 1
fi
ansible-playbook generate-templates.yml
az group deployment create --template-file ./.generated/network.json -g $AZURE_RESOURCE_GROUP
az group deployment create --template-file ./.generated/storage.json -g $AZURE_RESOURCE_GROUP
az group deployment create --template-file ./.generated/availability-sets.json -g $AZURE_RESOURCE_GROUP
az group deployment create --template-file ./.generated/bastion.json -g $AZURE_RESOURCE_GROUP
az group deployment create --template-file ./.generated/masters.json -g $AZURE_RESOURCE_GROUP
az group deployment create --template-file ./.generated/minions.json -g $AZURE_RESOURCE_GROUP

View File

@@ -9,6 +9,10 @@ if [ "$AZURE_RESOURCE_GROUP" == "" ]; then
exit 1 exit 1
fi fi
ansible-playbook generate-templates.yml if az &>/dev/null; then
echo "azure cli 2.0 found, using it instead of 1.0"
az group deployment create -g "$AZURE_RESOURCE_GROUP" --template-file ./.generated/clear-rg.json --mode Complete ./clear-rg_2.sh "$AZURE_RESOURCE_GROUP"
else
ansible-playbook generate-templates.yml
azure group deployment create -g "$AZURE_RESOURCE_GROUP" -f ./.generated/clear-rg.json -m Complete
fi

14
contrib/azurerm/clear-rg_2.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -e
AZURE_RESOURCE_GROUP="$1"
if [ "$AZURE_RESOURCE_GROUP" == "" ]; then
echo "AZURE_RESOURCE_GROUP is missing"
exit 1
fi
ansible-playbook generate-templates.yml
az group deployment create -g "$AZURE_RESOURCE_GROUP" --template-file ./.generated/clear-rg.json --mode Complete

View File

@@ -7,7 +7,7 @@ cluster_name: example
# node that can be used to access the masters and minions # node that can be used to access the masters and minions
use_bastion: false use_bastion: false
# Set this to a preferred name that will be used as the first part of the dns name for your bastotion host. For example: k8s-bastion.<azureregion>.cloudapp.azure.com. # Set this to a prefered name that will be used as the first part of the dns name for your bastotion host. For example: k8s-bastion.<azureregion>.cloudapp.azure.com.
# This is convenient when exceptions have to be configured on a firewall to allow ssh to the given bastion host. # This is convenient when exceptions have to be configured on a firewall to allow ssh to the given bastion host.
# bastion_domain_prefix: k8s-bastion # bastion_domain_prefix: k8s-bastion

View File

@@ -1,6 +1,6 @@
--- ---
- name: Query Azure VMs # noqa 301 - name: Query Azure VMs
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 # noqa 301 - name: Query Azure VMs IPs
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 # noqa 301 - name: Query Azure VMs Roles
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 # noqa 301 - name: Query Azure Load Balancer Public IP
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

@@ -69,7 +69,7 @@
# 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) # noqa 301 - 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)
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

View File

@@ -20,8 +20,6 @@
# Add range of hosts: inventory.py 10.10.1.3-10.10.1.5 # Add range of hosts: inventory.py 10.10.1.3-10.10.1.5
# Add hosts with different ip and access ip: # Add hosts with different ip and access ip:
# inventory.py 10.0.0.1,192.168.10.1 10.0.0.2,192.168.10.2 10.0.0.3,192.168.1.3 # inventory.py 10.0.0.1,192.168.10.1 10.0.0.2,192.168.10.2 10.0.0.3,192.168.1.3
# Add hosts with a specific hostname, ip, and optional access ip:
# inventory.py first,10.0.0.1,192.168.10.1 second,10.0.0.2 last,10.0.0.3
# Delete a host: inventory.py -10.10.1.3 # Delete a host: inventory.py -10.10.1.3
# Delete a host by id: inventory.py -node1 # Delete a host by id: inventory.py -node1
# #
@@ -41,14 +39,12 @@ from ruamel.yaml import YAML
import os import os
import re import re
import subprocess
import sys import sys
ROLES = ['all', 'kube-master', 'kube-node', 'etcd', 'k8s-cluster', ROLES = ['all', 'kube-master', 'kube-node', 'etcd', 'k8s-cluster',
'calico-rr'] 'calico-rr']
PROTECTED_NAMES = ROLES PROTECTED_NAMES = ROLES
AVAILABLE_COMMANDS = ['help', 'print_cfg', 'print_ips', 'print_hostnames', AVAILABLE_COMMANDS = ['help', 'print_cfg', 'print_ips', 'load']
'load']
_boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True, _boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
'0': False, 'no': False, 'false': False, 'off': False} '0': False, 'no': False, 'false': False, 'off': False}
yaml = YAML() yaml = YAML()
@@ -70,7 +66,6 @@ MASSIVE_SCALE_THRESHOLD = int(os.environ.get("SCALE_THRESHOLD", 200))
DEBUG = get_var_as_bool("DEBUG", True) DEBUG = get_var_as_bool("DEBUG", True)
HOST_PREFIX = os.environ.get("HOST_PREFIX", "node") HOST_PREFIX = os.environ.get("HOST_PREFIX", "node")
USE_REAL_HOSTNAME = get_var_as_bool("USE_REAL_HOSTNAME", False)
# Configurable as shell vars end # Configurable as shell vars end
@@ -83,8 +78,8 @@ class KubesprayInventory(object):
if self.config_file: if self.config_file:
try: try:
self.hosts_file = open(config_file, 'r') self.hosts_file = open(config_file, 'r')
self.yaml_config = yaml.load_all(self.hosts_file) self.yaml_config = yaml.load(self.hosts_file)
except OSError: except FileNotFoundError:
pass pass
if changed_hosts and changed_hosts[0] in AVAILABLE_COMMANDS: if changed_hosts and changed_hosts[0] in AVAILABLE_COMMANDS:
@@ -169,7 +164,6 @@ class KubesprayInventory(object):
# FIXME(mattymo): Fix condition where delete then add reuses highest id # FIXME(mattymo): Fix condition where delete then add reuses highest id
next_host_id = highest_host_id + 1 next_host_id = highest_host_id + 1
next_host = ""
all_hosts = existing_hosts.copy() all_hosts = existing_hosts.copy()
for host in changed_hosts: for host in changed_hosts:
@@ -194,33 +188,14 @@ class KubesprayInventory(object):
self.debug("Skipping existing host {0}.".format(ip)) self.debug("Skipping existing host {0}.".format(ip))
continue continue
if USE_REAL_HOSTNAME: next_host = "{0}{1}".format(HOST_PREFIX, next_host_id)
cmd = ("ssh -oStrictHostKeyChecking=no " next_host_id += 1
+ access_ip + " 'hostname -s'")
next_host = subprocess.check_output(cmd, shell=True)
next_host = next_host.strip().decode('ascii')
else:
next_host = "{0}{1}".format(HOST_PREFIX, next_host_id)
next_host_id += 1
all_hosts[next_host] = {'ansible_host': access_ip, all_hosts[next_host] = {'ansible_host': access_ip,
'ip': ip, 'ip': ip,
'access_ip': access_ip} 'access_ip': access_ip}
elif host[0].isalpha(): elif host[0].isalpha():
if ',' in host: raise Exception("Adding hosts by hostname is not supported.")
try:
hostname, ip, access_ip = host.split(',')
except Exception:
hostname, ip = host.split(',')
access_ip = ip
if self.exists_hostname(all_hosts, host):
self.debug("Skipping existing host {0}.".format(host))
continue
elif self.exists_ip(all_hosts, ip):
self.debug("Skipping existing host {0}.".format(ip))
continue
all_hosts[hostname] = {'ansible_host': access_ip,
'ip': ip,
'access_ip': access_ip}
return all_hosts return all_hosts
def range2ips(self, hosts): def range2ips(self, hosts):
@@ -231,14 +206,14 @@ class KubesprayInventory(object):
# Python 3.x # Python 3.x
start = int(ip_address(start_address)) start = int(ip_address(start_address))
end = int(ip_address(end_address)) end = int(ip_address(end_address))
except Exception: except:
# Python 2.7 # Python 2.7
start = int(ip_address(str(start_address))) start = int(ip_address(unicode(start_address)))
end = int(ip_address(str(end_address))) end = int(ip_address(unicode(end_address)))
return [ip_address(ip).exploded for ip in range(start, end + 1)] return [ip_address(ip).exploded for ip in range(start, end + 1)]
for host in hosts: for host in hosts:
if '-' in host and not (host.startswith('-') or host[0].isalpha()): if '-' in host and not host.startswith('-'):
start, end = host.strip().split('-') start, end = host.strip().split('-')
try: try:
reworked_hosts.extend(ips(start, end)) reworked_hosts.extend(ips(start, end))
@@ -373,8 +348,6 @@ class KubesprayInventory(object):
self.print_config() self.print_config()
elif command == 'print_ips': elif command == 'print_ips':
self.print_ips() self.print_ips()
elif command == 'print_hostnames':
self.print_hostnames()
elif command == 'load': elif command == 'load':
self.load_file(args) self.load_file(args)
else: else:
@@ -388,13 +361,11 @@ Available commands:
help - Display this message help - Display this message
print_cfg - Write inventory file to stdout print_cfg - Write inventory file to stdout
print_ips - Write a space-delimited list of IPs from "all" group print_ips - Write a space-delimited list of IPs from "all" group
print_hostnames - Write a space-delimited list of Hostnames from "all" group
Advanced usage: Advanced usage:
Add another host after initial creation: inventory.py 10.10.1.5 Add another host after initial creation: inventory.py 10.10.1.5
Add range of hosts: inventory.py 10.10.1.3-10.10.1.5 Add range of hosts: inventory.py 10.10.1.3-10.10.1.5
Add hosts with different ip and access ip: inventory.py 10.0.0.1,192.168.10.1 10.0.0.2,192.168.10.2 10.0.0.3,192.168.10.3 Add hosts with different ip and access ip: inventory.py 10.0.0.1,192.168.10.1 10.0.0.2,192.168.10.2 10.0.0.3,192.168.10.3
Add hosts with a specific hostname, ip, and optional access ip: first,10.0.0.1,192.168.10.1 second,10.0.0.2 last,10.0.0.3
Delete a host: inventory.py -10.10.1.3 Delete a host: inventory.py -10.10.1.3
Delete a host by id: inventory.py -node1 Delete a host by id: inventory.py -node1
@@ -410,9 +381,6 @@ MASSIVE_SCALE_THRESHOLD Separate K8s master and ETCD if # of nodes >= 200
def print_config(self): def print_config(self):
yaml.dump(self.yaml_config, sys.stdout) yaml.dump(self.yaml_config, sys.stdout)
def print_hostnames(self):
print(' '.join(self.yaml_config['all']['hosts'].keys()))
def print_ips(self): def print_ips(self):
ips = [] ips = []
for host, opts in self.yaml_config['all']['hosts'].items(): for host, opts in self.yaml_config['all']['hosts'].items():

View File

@@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import inventory
import mock import mock
import unittest import unittest
@@ -23,7 +22,7 @@ path = "./contrib/inventory_builder/"
if path not in sys.path: if path not in sys.path:
sys.path.append(path) sys.path.append(path)
import inventory # noqa import inventory
class TestInventory(unittest.TestCase): class TestInventory(unittest.TestCase):
@@ -44,8 +43,8 @@ class TestInventory(unittest.TestCase):
def test_get_ip_from_opts_invalid(self): def test_get_ip_from_opts_invalid(self):
optstring = "notanaddr=value something random!chars:D" optstring = "notanaddr=value something random!chars:D"
self.assertRaisesRegex(ValueError, "IP parameter not found", self.assertRaisesRegexp(ValueError, "IP parameter not found",
self.inv.get_ip_from_opts, optstring) self.inv.get_ip_from_opts, optstring)
def test_ensure_required_groups(self): def test_ensure_required_groups(self):
groups = ['group1', 'group2'] groups = ['group1', 'group2']
@@ -64,8 +63,8 @@ class TestInventory(unittest.TestCase):
def test_get_host_id_invalid(self): def test_get_host_id_invalid(self):
bad_hostnames = ['node', 'no99de', '01node', 'node.111111'] bad_hostnames = ['node', 'no99de', '01node', 'node.111111']
for hostname in bad_hostnames: for hostname in bad_hostnames:
self.assertRaisesRegex(ValueError, "Host name must end in an", self.assertRaisesRegexp(ValueError, "Host name must end in an",
self.inv.get_host_id, hostname) self.inv.get_host_id, hostname)
def test_build_hostnames_add_one(self): def test_build_hostnames_add_one(self):
changed_hosts = ['10.90.0.2'] changed_hosts = ['10.90.0.2']
@@ -193,8 +192,8 @@ class TestInventory(unittest.TestCase):
('node2', {'ansible_host': '10.90.0.3', ('node2', {'ansible_host': '10.90.0.3',
'ip': '10.90.0.3', 'ip': '10.90.0.3',
'access_ip': '10.90.0.3'})]) 'access_ip': '10.90.0.3'})])
self.assertRaisesRegex(ValueError, "Unable to find host", self.assertRaisesRegexp(ValueError, "Unable to find host",
self.inv.delete_host_by_ip, existing_hosts, ip) self.inv.delete_host_by_ip, existing_hosts, ip)
def test_purge_invalid_hosts(self): def test_purge_invalid_hosts(self):
proper_hostnames = ['node1', 'node2'] proper_hostnames = ['node1', 'node2']
@@ -310,8 +309,8 @@ class TestInventory(unittest.TestCase):
def test_range2ips_incorrect_range(self): def test_range2ips_incorrect_range(self):
host_range = ['10.90.0.4-a.9b.c.e'] host_range = ['10.90.0.4-a.9b.c.e']
self.assertRaisesRegex(Exception, "Range of ip_addresses isn't valid", self.assertRaisesRegexp(Exception, "Range of ip_addresses isn't valid",
self.inv.range2ips, host_range) self.inv.range2ips, host_range)
def test_build_hostnames_different_ips_add_one(self): def test_build_hostnames_different_ips_add_one(self):
changed_hosts = ['10.90.0.2,192.168.0.2'] changed_hosts = ['10.90.0.2,192.168.0.2']

View File

@@ -1,7 +1,7 @@
[tox] [tox]
minversion = 1.6 minversion = 1.6
skipsdist = True skipsdist = True
envlist = pep8, py33 envlist = pep8, py27
[testenv] [testenv]
whitelist_externals = py.test whitelist_externals = py.test

12
contrib/metallb/README.md Normal file
View File

@@ -0,0 +1,12 @@
# Deploy MetalLB into Kubespray/Kubernetes
```
MetalLB hooks into your Kubernetes cluster, and provides a network load-balancer implementation. In short, it allows you to create Kubernetes services of type “LoadBalancer” in clusters that dont run on a cloud provider, and thus cannot simply hook into paid products to provide load-balancers.
```
This playbook aims to automate [this](https://metallb.universe.tf/concepts/layer2/). It deploys MetalLB into kubernetes and sets up a layer 2 loadbalancer.
## Install
```
Defaults can be found in contrib/metallb/roles/provision/defaults/main.yml. You can override the defaults by copying the contents of this file to somewhere in inventory/mycluster/group_vars such as inventory/mycluster/groups_vars/k8s-cluster/addons.yml and making any adjustments as required.
ansible-playbook --ask-become -i inventory/sample/hosts.ini contrib/metallb/metallb.yml
```

1
contrib/metallb/library Symbolic link
View File

@@ -0,0 +1 @@
../../library

View File

@@ -0,0 +1,6 @@
---
- hosts: kube-master[0]
tags:
- "provision"
roles:
- { role: provision }

View File

@@ -0,0 +1,14 @@
---
metallb:
ip_range: "10.5.0.50-10.5.0.99"
protocol: "layer2"
# additional_address_pools:
# kube_service_pool:
# ip_range: "10.5.1.50-10.5.1.99"
# protocol: "layer2"
# auto_assign: false
limits:
cpu: "100m"
memory: "100Mi"
port: "7472"
version: v0.7.3

View File

@@ -0,0 +1,18 @@
---
- name: "Kubernetes Apps | Lay Down MetalLB"
become: true
template: { src: "{{ item }}.j2", dest: "{{ kube_config_dir }}/{{ item }}" }
with_items: ["metallb.yml", "metallb-config.yml"]
register: "rendering"
when:
- "inventory_hostname == groups['kube-master'][0]"
- name: "Kubernetes Apps | Install and configure MetalLB"
kube:
name: "MetalLB"
kubectl: "{{ bin_dir }}/kubectl"
filename: "{{ kube_config_dir }}/{{ item.item }}"
state: "{{ item.changed | ternary('latest','present') }}"
become: true
with_items: "{{ rendering.results }}"
when:
- "inventory_hostname == groups['kube-master'][0]"

View File

@@ -0,0 +1,21 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: loadbalanced
protocol: {{ metallb.protocol }}
addresses:
- {{ metallb.ip_range }}
{% if metallb.additional_address_pools is defined %}{% for pool in metallb.additional_address_pools %}
- name: {{ pool }}
protocol: {{ metallb.additional_address_pools[pool].protocol }}
addresses:
- {{ metallb.additional_address_pools[pool].ip_range }}
auto-assign: {{ metallb.additional_address_pools[pool].auto_assign }}
{% endfor %}
{% endif %}

View File

@@ -0,0 +1,221 @@
apiVersion: v1
kind: Namespace
metadata:
name: metallb-system
labels:
app: metallb
---
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: metallb-system
name: controller
labels:
app: metallb
---
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: metallb-system
name: speaker
labels:
app: metallb
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: metallb-system:controller
labels:
app: metallb
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: [""]
resources: ["services/status"]
verbs: ["update"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: metallb-system:speaker
labels:
app: metallb
rules:
- apiGroups: [""]
resources: ["services", "endpoints", "nodes"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: metallb-system
name: config-watcher
labels:
app: metallb
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create"]
---
## Role bindings
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: metallb-system:controller
labels:
app: metallb
subjects:
- kind: ServiceAccount
name: controller
namespace: metallb-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: metallb-system:controller
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: metallb-system:speaker
labels:
app: metallb
subjects:
- kind: ServiceAccount
name: speaker
namespace: metallb-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: metallb-system:speaker
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: metallb-system
name: config-watcher
labels:
app: metallb
subjects:
- kind: ServiceAccount
name: controller
- kind: ServiceAccount
name: speaker
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: config-watcher
---
apiVersion: apps/v1beta2
kind: DaemonSet
metadata:
namespace: metallb-system
name: speaker
labels:
app: metallb
component: speaker
spec:
selector:
matchLabels:
app: metallb
component: speaker
template:
metadata:
labels:
app: metallb
component: speaker
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "{{ metallb.port }}"
spec:
serviceAccountName: speaker
terminationGracePeriodSeconds: 0
hostNetwork: true
containers:
- name: speaker
image: metallb/speaker:{{ metallb.version }}
imagePullPolicy: IfNotPresent
args:
- --port={{ metallb.port }}
- --config=config
env:
- name: METALLB_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
ports:
- name: monitoring
containerPort: {{ metallb.port }}
resources:
limits:
cpu: {{ metallb.limits.cpu }}
memory: {{ metallb.limits.memory }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- all
add:
- net_raw
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
namespace: metallb-system
name: controller
labels:
app: metallb
component: controller
spec:
revisionHistoryLimit: 3
selector:
matchLabels:
app: metallb
component: controller
template:
metadata:
labels:
app: metallb
component: controller
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "{{ metallb.port }}"
spec:
serviceAccountName: controller
terminationGracePeriodSeconds: 0
securityContext:
runAsNonRoot: true
runAsUser: 65534 # nobody
containers:
- name: controller
image: metallb/controller:{{ metallb.version }}
imagePullPolicy: IfNotPresent
args:
- --port={{ metallb.port }}
- --config=config
ports:
- name: monitoring
containerPort: {{ metallb.port }}
resources:
limits:
cpu: {{ metallb.limits.cpu }}
memory: {{ metallb.limits.memory }}
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- all
readOnlyRootFilesystem: true
---

View File

@@ -1,5 +1,5 @@
--- ---
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
name: kubernetes-dashboard name: kubernetes-dashboard

View File

@@ -21,7 +21,7 @@ You can specify a `default_release` for apt on Debian/Ubuntu by overriding this
glusterfs_ppa_use: yes glusterfs_ppa_use: yes
glusterfs_ppa_version: "3.5" glusterfs_ppa_version: "3.5"
For Ubuntu, specify whether to use the official Gluster PPA, and which version of the PPA to use. See Gluster's [Getting Started Guide](https://docs.gluster.org/en/latest/Quick-Start-Guide/Quickstart/) for more info. For Ubuntu, specify whether to use the official Gluster PPA, and which version of the PPA to use. See Gluster's [Getting Started Guide](http://www.gluster.org/community/documentation/index.php/Getting_started_install) for more info.
## Dependencies ## Dependencies

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 503 - name: Ensure GlusterFS client will reinstall if the PPA was just added.
apt: apt:
name: "{{ item }}" name: "{{ item }}"
state: absent state: absent
@@ -18,7 +18,7 @@
- name: Ensure GlusterFS client is installed. - name: Ensure GlusterFS client is installed.
apt: apt:
name: "{{ item }}" name: "{{ item }}"
state: present state: installed
default_release: "{{ glusterfs_default_release }}" default_release: "{{ glusterfs_default_release }}"
with_items: with_items:
- glusterfs-client - glusterfs-client

View File

@@ -3,7 +3,7 @@
- name: Include OS-specific variables. - name: Include OS-specific variables.
include_vars: "{{ ansible_os_family }}.yml" include_vars: "{{ ansible_os_family }}.yml"
# Install xfs package # Instal xfs package
- name: install xfs Debian - name: install xfs Debian
apt: name=xfsprogs state=present apt: name=xfsprogs state=present
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
@@ -36,7 +36,7 @@
- "{{ gluster_brick_dir }}" - "{{ gluster_brick_dir }}"
- "{{ gluster_mount_dir }}" - "{{ gluster_mount_dir }}"
- name: Configure Gluster volume with replicas - name: Configure Gluster volume.
gluster_volume: gluster_volume:
state: present state: present
name: "{{ gluster_brick_name }}" name: "{{ gluster_brick_name }}"
@@ -46,18 +46,6 @@
host: "{{ inventory_hostname }}" host: "{{ inventory_hostname }}"
force: yes force: yes
run_once: true run_once: true
when: groups['gfs-cluster']|length > 1
- name: Configure Gluster volume without replicas
gluster_volume:
state: present
name: "{{ gluster_brick_name }}"
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 %}"
host: "{{ inventory_hostname }}"
force: yes
run_once: true
when: groups['gfs-cluster']|length <= 1
- name: Mount glusterfs to retrieve disk size - name: Mount glusterfs to retrieve disk size
mount: mount:

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 503 - name: Ensure GlusterFS will reinstall if the PPA was just added.
apt: apt:
name: "{{ item }}" name: "{{ item }}"
state: absent state: absent
@@ -19,7 +19,7 @@
- name: Ensure GlusterFS is installed. - name: Ensure GlusterFS is installed.
apt: apt:
name: "{{ item }}" name: "{{ item }}"
state: present state: installed
default_release: "{{ glusterfs_default_release }}" default_release: "{{ glusterfs_default_release }}"
with_items: with_items:
- glusterfs-server - glusterfs-server

View File

@@ -8,7 +8,7 @@
{% for host in groups['gfs-cluster'] %} {% for host in groups['gfs-cluster'] %}
{ {
"addresses": [ "addresses": [
{ {
"ip": "{{hostvars[host]['ip']|default(hostvars[host].ansible_default_ipv4['address'])}}" "ip": "{{hostvars[host]['ip']|default(hostvars[host].ansible_default_ipv4['address'])}}"
} }
], ],

View File

@@ -1,7 +1,7 @@
apiVersion: v1 apiVersion: v1
kind: PersistentVolume kind: PersistentVolume
metadata: metadata:
name: glusterfs name: glusterfs
spec: spec:
capacity: capacity:
storage: "{{ hostvars[groups['gfs-cluster'][0]].gluster_disk_size_gb }}Gi" storage: "{{ hostvars[groups['gfs-cluster'][0]].gluster_disk_size_gb }}Gi"

View File

@@ -6,7 +6,7 @@
- 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." # noqa 301 - name: "Ensure there is nothing left over."
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"

View File

@@ -13,7 +13,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 503 - name: "Load heketi topology."
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"

View File

@@ -18,7 +18,7 @@
- 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." # noqa 301 - name: "Copy configuration from pod."
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."

View File

@@ -10,10 +10,10 @@
template: template:
src: "topology.json.j2" src: "topology.json.j2"
dest: "{{ kube_config_dir }}/topology.json" dest: "{{ kube_config_dir }}/topology.json"
- name: "Copy topology configuration into container." # noqa 503 - name: "Copy topology configuration into container."
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 503 - name: "Load heketi topology."
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."

View File

@@ -1,6 +1,6 @@
{ {
"kind": "DaemonSet", "kind": "DaemonSet",
"apiVersion": "apps/v1", "apiVersion": "extensions/v1beta1",
"metadata": { "metadata": {
"name": "glusterfs", "name": "glusterfs",
"labels": { "labels": {
@@ -12,11 +12,6 @@
} }
}, },
"spec": { "spec": {
"selector": {
"matchLabels": {
"glusterfs-node": "daemonset"
}
},
"template": { "template": {
"metadata": { "metadata": {
"name": "glusterfs", "name": "glusterfs",

View File

@@ -30,7 +30,7 @@
}, },
{ {
"kind": "Deployment", "kind": "Deployment",
"apiVersion": "apps/v1", "apiVersion": "extensions/v1beta1",
"metadata": { "metadata": {
"name": "deploy-heketi", "name": "deploy-heketi",
"labels": { "labels": {
@@ -42,11 +42,6 @@
} }
}, },
"spec": { "spec": {
"selector": {
"matchLabels": {
"name": "deploy-heketi"
}
},
"replicas": 1, "replicas": 1,
"template": { "template": {
"metadata": { "metadata": {

View File

@@ -44,7 +44,7 @@
}, },
{ {
"kind": "Deployment", "kind": "Deployment",
"apiVersion": "apps/v1", "apiVersion": "extensions/v1beta1",
"metadata": { "metadata": {
"name": "heketi", "name": "heketi",
"labels": { "labels": {
@@ -55,11 +55,6 @@
} }
}, },
"spec": { "spec": {
"selector": {
"matchLabels": {
"name": "heketi"
}
},
"replicas": 1, "replicas": 1,
"template": { "template": {
"metadata": { "metadata": {

View File

@@ -16,7 +16,7 @@
{ {
"addresses": [ "addresses": [
{ {
"ip": "{{ hostvars[node].ip }}" "ip": "{{ hostvars[node]['ansible_facts']['default_ipv4']['address'] }}"
} }
], ],
"ports": [ "ports": [

View File

@@ -12,7 +12,7 @@
"{{ node }}" "{{ node }}"
], ],
"storage": [ "storage": [
"{{ hostvars[node].ip }}" "{{ hostvars[node]['ansible_facts']['default_ipv4']['address'] }}"
] ]
}, },
"zone": 1 "zone": 1

View File

@@ -22,7 +22,7 @@
ignore_errors: true ignore_errors: true
changed_when: false changed_when: false
- name: "Remove volume groups." # noqa 301 - name: "Remove volume groups."
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." # noqa 301 - name: "Remove physical volume from cluster disks."
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." # noqa 301 - name: "Remove storage class."
command: "{{ bin_dir }}/kubectl delete storageclass gluster" command: "{{ bin_dir }}/kubectl delete storageclass gluster"
ignore_errors: true ignore_errors: true
- name: "Tear down heketi." # noqa 301 - name: "Tear down heketi."
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 ignore_errors: true
- name: "Tear down heketi." # noqa 301 - name: "Tear down heketi."
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 ignore_errors: true
- 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." # noqa 301 - name: "Ensure there is nothing left over."
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." # noqa 301 - name: "Ensure there is nothing left over."
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." # noqa 301 - name: "Tear down glusterfs."
command: "{{ bin_dir }}/kubectl delete daemonset.extensions/glusterfs" command: "{{ bin_dir }}/kubectl delete daemonset.extensions/glusterfs"
ignore_errors: true ignore_errors: true
- name: "Remove heketi storage service." # noqa 301 - name: "Remove heketi storage service."
command: "{{ bin_dir }}/kubectl delete service heketi-storage-endpoints" command: "{{ bin_dir }}/kubectl delete service heketi-storage-endpoints"
ignore_errors: true ignore_errors: true
- name: "Remove heketi gluster role binding" # noqa 301 - name: "Remove heketi gluster role binding"
command: "{{ bin_dir }}/kubectl delete clusterrolebinding heketi-gluster-admin" command: "{{ bin_dir }}/kubectl delete clusterrolebinding heketi-gluster-admin"
ignore_errors: true ignore_errors: true
- name: "Remove heketi config secret" # noqa 301 - name: "Remove heketi config secret"
command: "{{ bin_dir }}/kubectl delete secret heketi-config-secret" command: "{{ bin_dir }}/kubectl delete secret heketi-config-secret"
ignore_errors: true ignore_errors: true
- name: "Remove heketi db backup" # noqa 301 - name: "Remove heketi db backup"
command: "{{ bin_dir }}/kubectl delete secret heketi-db-backup" command: "{{ bin_dir }}/kubectl delete secret heketi-db-backup"
ignore_errors: true ignore_errors: true
- name: "Remove heketi service account" # noqa 301 - name: "Remove heketi service account"
command: "{{ bin_dir }}/kubectl delete serviceaccount heketi-service-account" command: "{{ bin_dir }}/kubectl delete serviceaccount heketi-service-account"
ignore_errors: true ignore_errors: true
- name: "Get secrets" - name: "Get secrets"

View File

@@ -10,7 +10,7 @@ This project will create:
* AWS ELB in the Public Subnet for accessing the Kubernetes API from the internet * AWS ELB in the Public Subnet for accessing the Kubernetes API from the internet
**Requirements** **Requirements**
- Terraform 0.12.0 or newer - Terraform 0.8.7 or newer
**How to Use:** **How to Use:**
@@ -22,7 +22,7 @@ export TF_VAR_AWS_SECRET_ACCESS_KEY ="xxx"
export TF_VAR_AWS_SSH_KEY_NAME="yyy" export TF_VAR_AWS_SSH_KEY_NAME="yyy"
export TF_VAR_AWS_DEFAULT_REGION="zzz" export TF_VAR_AWS_DEFAULT_REGION="zzz"
``` ```
- Update `contrib/terraform/aws/terraform.tfvars` with your data. By default, the Terraform scripts use Ubuntu 18.04 LTS (Bionic) as base image. If you want to change this behaviour, see note "Using other distrib than Ubuntu" below. - Update `contrib/terraform/aws/terraform.tfvars` with your data. By default, the Terraform scripts use CoreOS as base image. If you want to change this behaviour, see note "Using other distrib than CoreOs" below.
- Create an AWS EC2 SSH Key - Create an AWS EC2 SSH Key
- Run with `terraform apply --var-file="credentials.tfvars"` or `terraform apply` depending if you exported your AWS credentials - Run with `terraform apply --var-file="credentials.tfvars"` or `terraform apply` depending if you exported your AWS credentials
@@ -41,12 +41,12 @@ ssh -F ./ssh-bastion.conf user@$ip
- Once the infrastructure is created, you can run the kubespray playbooks and supply inventory/hosts with the `-i` flag. - Once the infrastructure is created, you can run the kubespray playbooks and supply inventory/hosts with the `-i` flag.
Example (this one assumes you are using Ubuntu) Example (this one assumes you are using CoreOS)
```commandline ```commandline
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=core -b --become-user=root --flush-cache
``` ```
***Using other distrib than Ubuntu*** ***Using other distrib than CoreOs***
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. If you want to use another distribution than CoreOS, you can modify the search filters of the 'data "aws_ami" "distro"' in variables.tf.
For example, to use: For example, to use:
- Debian Jessie, replace 'data "aws_ami" "distro"' in variables.tf with - Debian Jessie, replace 'data "aws_ami" "distro"' in variables.tf with

View File

@@ -1,11 +1,11 @@
terraform { terraform {
required_version = ">= 0.12.0" required_version = ">= 0.8.7"
} }
provider "aws" { provider "aws" {
access_key = var.AWS_ACCESS_KEY_ID access_key = "${var.AWS_ACCESS_KEY_ID}"
secret_key = var.AWS_SECRET_ACCESS_KEY secret_key = "${var.AWS_SECRET_ACCESS_KEY}"
region = var.AWS_DEFAULT_REGION region = "${var.AWS_DEFAULT_REGION}"
} }
data "aws_availability_zones" "available" {} data "aws_availability_zones" "available" {}
@@ -16,32 +16,32 @@ data "aws_availability_zones" "available" {}
*/ */
module "aws-vpc" { module "aws-vpc" {
source = "./modules/vpc" source = "modules/vpc"
aws_cluster_name = var.aws_cluster_name aws_cluster_name = "${var.aws_cluster_name}"
aws_vpc_cidr_block = var.aws_vpc_cidr_block aws_vpc_cidr_block = "${var.aws_vpc_cidr_block}"
aws_avail_zones = slice(data.aws_availability_zones.available.names, 0, 2) aws_avail_zones = "${slice(data.aws_availability_zones.available.names,0,2)}"
aws_cidr_subnets_private = var.aws_cidr_subnets_private aws_cidr_subnets_private = "${var.aws_cidr_subnets_private}"
aws_cidr_subnets_public = var.aws_cidr_subnets_public aws_cidr_subnets_public = "${var.aws_cidr_subnets_public}"
default_tags = var.default_tags default_tags = "${var.default_tags}"
} }
module "aws-elb" { module "aws-elb" {
source = "./modules/elb" source = "modules/elb"
aws_cluster_name = var.aws_cluster_name aws_cluster_name = "${var.aws_cluster_name}"
aws_vpc_id = module.aws-vpc.aws_vpc_id aws_vpc_id = "${module.aws-vpc.aws_vpc_id}"
aws_avail_zones = slice(data.aws_availability_zones.available.names, 0, 2) aws_avail_zones = "${slice(data.aws_availability_zones.available.names,0,2)}"
aws_subnet_ids_public = module.aws-vpc.aws_subnet_ids_public aws_subnet_ids_public = "${module.aws-vpc.aws_subnet_ids_public}"
aws_elb_api_port = var.aws_elb_api_port aws_elb_api_port = "${var.aws_elb_api_port}"
k8s_secure_api_port = var.k8s_secure_api_port k8s_secure_api_port = "${var.k8s_secure_api_port}"
default_tags = var.default_tags default_tags = "${var.default_tags}"
} }
module "aws-iam" { module "aws-iam" {
source = "./modules/iam" source = "modules/iam"
aws_cluster_name = var.aws_cluster_name aws_cluster_name = "${var.aws_cluster_name}"
} }
/* /*
@@ -50,22 +50,22 @@ module "aws-iam" {
*/ */
resource "aws_instance" "bastion-server" { resource "aws_instance" "bastion-server" {
ami = data.aws_ami.distro.id ami = "${data.aws_ami.distro.id}"
instance_type = var.aws_bastion_size instance_type = "${var.aws_bastion_size}"
count = length(var.aws_cidr_subnets_public) count = "${length(var.aws_cidr_subnets_public)}"
associate_public_ip_address = true associate_public_ip_address = true
availability_zone = element(slice(data.aws_availability_zones.available.names, 0, 2), count.index) availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}"
subnet_id = element(module.aws-vpc.aws_subnet_ids_public, count.index) subnet_id = "${element(module.aws-vpc.aws_subnet_ids_public,count.index)}"
vpc_security_group_ids = module.aws-vpc.aws_security_group vpc_security_group_ids = ["${module.aws-vpc.aws_security_group}"]
key_name = var.AWS_SSH_KEY_NAME key_name = "${var.AWS_SSH_KEY_NAME}"
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-bastion-${count.index}", "Name", "kubernetes-${var.aws_cluster_name}-bastion-${count.index}",
"Cluster", "${var.aws_cluster_name}", "Cluster", "${var.aws_cluster_name}",
"Role", "bastion-${var.aws_cluster_name}-${count.index}" "Role", "bastion-${var.aws_cluster_name}-${count.index}"
)) ))}"
} }
/* /*
@@ -74,71 +74,71 @@ resource "aws_instance" "bastion-server" {
*/ */
resource "aws_instance" "k8s-master" { resource "aws_instance" "k8s-master" {
ami = data.aws_ami.distro.id ami = "${data.aws_ami.distro.id}"
instance_type = var.aws_kube_master_size instance_type = "${var.aws_kube_master_size}"
count = var.aws_kube_master_num count = "${var.aws_kube_master_num}"
availability_zone = element(slice(data.aws_availability_zones.available.names, 0, 2), count.index) availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}"
subnet_id = element(module.aws-vpc.aws_subnet_ids_private, count.index) subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}"
vpc_security_group_ids = module.aws-vpc.aws_security_group vpc_security_group_ids = ["${module.aws-vpc.aws_security_group}"]
iam_instance_profile = module.aws-iam.kube-master-profile iam_instance_profile = "${module.aws-iam.kube-master-profile}"
key_name = var.AWS_SSH_KEY_NAME key_name = "${var.AWS_SSH_KEY_NAME}"
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-master${count.index}", "Name", "kubernetes-${var.aws_cluster_name}-master${count.index}",
"kubernetes.io/cluster/${var.aws_cluster_name}", "member", "kubernetes.io/cluster/${var.aws_cluster_name}", "member",
"Role", "master" "Role", "master"
)) ))}"
} }
resource "aws_elb_attachment" "attach_master_nodes" { resource "aws_elb_attachment" "attach_master_nodes" {
count = var.aws_kube_master_num count = "${var.aws_kube_master_num}"
elb = module.aws-elb.aws_elb_api_id elb = "${module.aws-elb.aws_elb_api_id}"
instance = element(aws_instance.k8s-master.*.id, count.index) instance = "${element(aws_instance.k8s-master.*.id,count.index)}"
} }
resource "aws_instance" "k8s-etcd" { resource "aws_instance" "k8s-etcd" {
ami = data.aws_ami.distro.id ami = "${data.aws_ami.distro.id}"
instance_type = var.aws_etcd_size instance_type = "${var.aws_etcd_size}"
count = var.aws_etcd_num count = "${var.aws_etcd_num}"
availability_zone = element(slice(data.aws_availability_zones.available.names, 0, 2), count.index) availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}"
subnet_id = element(module.aws-vpc.aws_subnet_ids_private, count.index) subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}"
vpc_security_group_ids = module.aws-vpc.aws_security_group vpc_security_group_ids = ["${module.aws-vpc.aws_security_group}"]
key_name = var.AWS_SSH_KEY_NAME key_name = "${var.AWS_SSH_KEY_NAME}"
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-etcd${count.index}", "Name", "kubernetes-${var.aws_cluster_name}-etcd${count.index}",
"kubernetes.io/cluster/${var.aws_cluster_name}", "member", "kubernetes.io/cluster/${var.aws_cluster_name}", "member",
"Role", "etcd" "Role", "etcd"
)) ))}"
} }
resource "aws_instance" "k8s-worker" { resource "aws_instance" "k8s-worker" {
ami = data.aws_ami.distro.id ami = "${data.aws_ami.distro.id}"
instance_type = var.aws_kube_worker_size instance_type = "${var.aws_kube_worker_size}"
count = var.aws_kube_worker_num count = "${var.aws_kube_worker_num}"
availability_zone = element(slice(data.aws_availability_zones.available.names, 0, 2), count.index) availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}"
subnet_id = element(module.aws-vpc.aws_subnet_ids_private, count.index) subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}"
vpc_security_group_ids = module.aws-vpc.aws_security_group vpc_security_group_ids = ["${module.aws-vpc.aws_security_group}"]
iam_instance_profile = module.aws-iam.kube-worker-profile iam_instance_profile = "${module.aws-iam.kube-worker-profile}"
key_name = var.AWS_SSH_KEY_NAME key_name = "${var.AWS_SSH_KEY_NAME}"
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-worker${count.index}", "Name", "kubernetes-${var.aws_cluster_name}-worker${count.index}",
"kubernetes.io/cluster/${var.aws_cluster_name}", "member", "kubernetes.io/cluster/${var.aws_cluster_name}", "member",
"Role", "worker" "Role", "worker"
)) ))}"
} }
/* /*
@@ -146,16 +146,16 @@ resource "aws_instance" "k8s-worker" {
* *
*/ */
data "template_file" "inventory" { data "template_file" "inventory" {
template = file("${path.module}/templates/inventory.tpl") template = "${file("${path.module}/templates/inventory.tpl")}"
vars = { vars {
public_ip_address_bastion = join("\n", formatlist("bastion ansible_host=%s", aws_instance.bastion-server.*.public_ip)) public_ip_address_bastion = "${join("\n",formatlist("bastion ansible_host=%s" , aws_instance.bastion-server.*.public_ip))}"
connection_strings_master = join("\n", formatlist("%s ansible_host=%s", aws_instance.k8s-master.*.private_dns, aws_instance.k8s-master.*.private_ip)) connection_strings_master = "${join("\n",formatlist("%s ansible_host=%s",aws_instance.k8s-master.*.tags.Name, aws_instance.k8s-master.*.private_ip))}"
connection_strings_node = join("\n", formatlist("%s ansible_host=%s", aws_instance.k8s-worker.*.private_dns, aws_instance.k8s-worker.*.private_ip)) connection_strings_node = "${join("\n", formatlist("%s ansible_host=%s", aws_instance.k8s-worker.*.tags.Name, aws_instance.k8s-worker.*.private_ip))}"
connection_strings_etcd = join("\n", formatlist("%s ansible_host=%s", aws_instance.k8s-etcd.*.private_dns, aws_instance.k8s-etcd.*.private_ip)) connection_strings_etcd = "${join("\n",formatlist("%s ansible_host=%s", aws_instance.k8s-etcd.*.tags.Name, aws_instance.k8s-etcd.*.private_ip))}"
list_master = join("\n", aws_instance.k8s-master.*.private_dns) list_master = "${join("\n",aws_instance.k8s-master.*.tags.Name)}"
list_node = join("\n", aws_instance.k8s-worker.*.private_dns) list_node = "${join("\n",aws_instance.k8s-worker.*.tags.Name)}"
list_etcd = join("\n", aws_instance.k8s-etcd.*.private_dns) list_etcd = "${join("\n",aws_instance.k8s-etcd.*.tags.Name)}"
elb_api_fqdn = "apiserver_loadbalancer_domain_name=\"${module.aws-elb.aws_elb_api_fqdn}\"" elb_api_fqdn = "apiserver_loadbalancer_domain_name=\"${module.aws-elb.aws_elb_api_fqdn}\""
} }
} }
@@ -165,7 +165,7 @@ resource "null_resource" "inventories" {
command = "echo '${data.template_file.inventory.rendered}' > ${var.inventory_file}" command = "echo '${data.template_file.inventory.rendered}' > ${var.inventory_file}"
} }
triggers = { triggers {
template = data.template_file.inventory.rendered template = "${data.template_file.inventory.rendered}"
} }
} }

View File

@@ -1,19 +1,19 @@
resource "aws_security_group" "aws-elb" { resource "aws_security_group" "aws-elb" {
name = "kubernetes-${var.aws_cluster_name}-securitygroup-elb" name = "kubernetes-${var.aws_cluster_name}-securitygroup-elb"
vpc_id = var.aws_vpc_id vpc_id = "${var.aws_vpc_id}"
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-securitygroup-elb" "Name", "kubernetes-${var.aws_cluster_name}-securitygroup-elb"
)) ))}"
} }
resource "aws_security_group_rule" "aws-allow-api-access" { resource "aws_security_group_rule" "aws-allow-api-access" {
type = "ingress" type = "ingress"
from_port = var.aws_elb_api_port from_port = "${var.aws_elb_api_port}"
to_port = var.k8s_secure_api_port to_port = "${var.k8s_secure_api_port}"
protocol = "TCP" protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"] cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.aws-elb.id security_group_id = "${aws_security_group.aws-elb.id}"
} }
resource "aws_security_group_rule" "aws-allow-api-egress" { resource "aws_security_group_rule" "aws-allow-api-egress" {
@@ -22,19 +22,19 @@ resource "aws_security_group_rule" "aws-allow-api-egress" {
to_port = 65535 to_port = 65535
protocol = "TCP" protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"] cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.aws-elb.id security_group_id = "${aws_security_group.aws-elb.id}"
} }
# Create a new AWS ELB for K8S API # Create a new AWS ELB for K8S API
resource "aws_elb" "aws-elb-api" { resource "aws_elb" "aws-elb-api" {
name = "kubernetes-elb-${var.aws_cluster_name}" name = "kubernetes-elb-${var.aws_cluster_name}"
subnets = var.aws_subnet_ids_public subnets = ["${var.aws_subnet_ids_public}"]
security_groups = [aws_security_group.aws-elb.id] security_groups = ["${aws_security_group.aws-elb.id}"]
listener { listener {
instance_port = var.k8s_secure_api_port instance_port = "${var.k8s_secure_api_port}"
instance_protocol = "tcp" instance_protocol = "tcp"
lb_port = var.aws_elb_api_port lb_port = "${var.aws_elb_api_port}"
lb_protocol = "tcp" lb_protocol = "tcp"
} }
@@ -51,7 +51,7 @@ resource "aws_elb" "aws-elb-api" {
connection_draining = true connection_draining = true
connection_draining_timeout = 400 connection_draining_timeout = 400
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-elb-api" "Name", "kubernetes-${var.aws_cluster_name}-elb-api"
)) ))}"
} }

View File

@@ -1,7 +1,7 @@
output "aws_elb_api_id" { output "aws_elb_api_id" {
value = aws_elb.aws-elb-api.id value = "${aws_elb.aws-elb-api.id}"
} }
output "aws_elb_api_fqdn" { output "aws_elb_api_fqdn" {
value = aws_elb.aws-elb-api.dns_name value = "${aws_elb.aws-elb-api.dns_name}"
} }

View File

@@ -42,7 +42,7 @@ EOF
resource "aws_iam_role_policy" "kube-master" { resource "aws_iam_role_policy" "kube-master" {
name = "kubernetes-${var.aws_cluster_name}-master" name = "kubernetes-${var.aws_cluster_name}-master"
role = aws_iam_role.kube-master.id role = "${aws_iam_role.kube-master.id}"
policy = <<EOF policy = <<EOF
{ {
@@ -77,7 +77,7 @@ EOF
resource "aws_iam_role_policy" "kube-worker" { resource "aws_iam_role_policy" "kube-worker" {
name = "kubernetes-${var.aws_cluster_name}-node" name = "kubernetes-${var.aws_cluster_name}-node"
role = aws_iam_role.kube-worker.id role = "${aws_iam_role.kube-worker.id}"
policy = <<EOF policy = <<EOF
{ {
@@ -132,10 +132,10 @@ EOF
resource "aws_iam_instance_profile" "kube-master" { resource "aws_iam_instance_profile" "kube-master" {
name = "kube_${var.aws_cluster_name}_master_profile" name = "kube_${var.aws_cluster_name}_master_profile"
role = aws_iam_role.kube-master.name role = "${aws_iam_role.kube-master.name}"
} }
resource "aws_iam_instance_profile" "kube-worker" { resource "aws_iam_instance_profile" "kube-worker" {
name = "kube_${var.aws_cluster_name}_node_profile" name = "kube_${var.aws_cluster_name}_node_profile"
role = aws_iam_role.kube-worker.name role = "${aws_iam_role.kube-worker.name}"
} }

View File

@@ -1,7 +1,7 @@
output "kube-master-profile" { output "kube-master-profile" {
value = aws_iam_instance_profile.kube-master.name value = "${aws_iam_instance_profile.kube-master.name }"
} }
output "kube-worker-profile" { output "kube-worker-profile" {
value = aws_iam_instance_profile.kube-worker.name value = "${aws_iam_instance_profile.kube-worker.name }"
} }

View File

@@ -1,55 +1,55 @@
resource "aws_vpc" "cluster-vpc" { resource "aws_vpc" "cluster-vpc" {
cidr_block = var.aws_vpc_cidr_block cidr_block = "${var.aws_vpc_cidr_block}"
#DNS Related Entries #DNS Related Entries
enable_dns_support = true enable_dns_support = true
enable_dns_hostnames = true enable_dns_hostnames = true
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-vpc" "Name", "kubernetes-${var.aws_cluster_name}-vpc"
)) ))}"
} }
resource "aws_eip" "cluster-nat-eip" { resource "aws_eip" "cluster-nat-eip" {
count = length(var.aws_cidr_subnets_public) count = "${length(var.aws_cidr_subnets_public)}"
vpc = true vpc = true
} }
resource "aws_internet_gateway" "cluster-vpc-internetgw" { resource "aws_internet_gateway" "cluster-vpc-internetgw" {
vpc_id = aws_vpc.cluster-vpc.id vpc_id = "${aws_vpc.cluster-vpc.id}"
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-internetgw" "Name", "kubernetes-${var.aws_cluster_name}-internetgw"
)) ))}"
} }
resource "aws_subnet" "cluster-vpc-subnets-public" { resource "aws_subnet" "cluster-vpc-subnets-public" {
vpc_id = aws_vpc.cluster-vpc.id vpc_id = "${aws_vpc.cluster-vpc.id}"
count = length(var.aws_avail_zones) count = "${length(var.aws_avail_zones)}"
availability_zone = element(var.aws_avail_zones, count.index) availability_zone = "${element(var.aws_avail_zones, count.index)}"
cidr_block = element(var.aws_cidr_subnets_public, count.index) cidr_block = "${element(var.aws_cidr_subnets_public, count.index)}"
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-${element(var.aws_avail_zones, count.index)}-public", "Name", "kubernetes-${var.aws_cluster_name}-${element(var.aws_avail_zones, count.index)}-public",
"kubernetes.io/cluster/${var.aws_cluster_name}", "member" "kubernetes.io/cluster/${var.aws_cluster_name}", "member"
)) ))}"
} }
resource "aws_nat_gateway" "cluster-nat-gateway" { resource "aws_nat_gateway" "cluster-nat-gateway" {
count = length(var.aws_cidr_subnets_public) count = "${length(var.aws_cidr_subnets_public)}"
allocation_id = element(aws_eip.cluster-nat-eip.*.id, count.index) allocation_id = "${element(aws_eip.cluster-nat-eip.*.id, count.index)}"
subnet_id = element(aws_subnet.cluster-vpc-subnets-public.*.id, count.index) subnet_id = "${element(aws_subnet.cluster-vpc-subnets-public.*.id, count.index)}"
} }
resource "aws_subnet" "cluster-vpc-subnets-private" { resource "aws_subnet" "cluster-vpc-subnets-private" {
vpc_id = aws_vpc.cluster-vpc.id vpc_id = "${aws_vpc.cluster-vpc.id}"
count = length(var.aws_avail_zones) count = "${length(var.aws_avail_zones)}"
availability_zone = element(var.aws_avail_zones, count.index) availability_zone = "${element(var.aws_avail_zones, count.index)}"
cidr_block = element(var.aws_cidr_subnets_private, count.index) cidr_block = "${element(var.aws_cidr_subnets_private, count.index)}"
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-${element(var.aws_avail_zones, count.index)}-private" "Name", "kubernetes-${var.aws_cluster_name}-${element(var.aws_avail_zones, count.index)}-private"
)) ))}"
} }
#Routing in VPC #Routing in VPC
@@ -57,53 +57,53 @@ resource "aws_subnet" "cluster-vpc-subnets-private" {
#TODO: Do we need two routing tables for each subnet for redundancy or is one enough? #TODO: Do we need two routing tables for each subnet for redundancy or is one enough?
resource "aws_route_table" "kubernetes-public" { resource "aws_route_table" "kubernetes-public" {
vpc_id = aws_vpc.cluster-vpc.id vpc_id = "${aws_vpc.cluster-vpc.id}"
route { route {
cidr_block = "0.0.0.0/0" cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.cluster-vpc-internetgw.id gateway_id = "${aws_internet_gateway.cluster-vpc-internetgw.id}"
} }
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-routetable-public" "Name", "kubernetes-${var.aws_cluster_name}-routetable-public"
)) ))}"
} }
resource "aws_route_table" "kubernetes-private" { resource "aws_route_table" "kubernetes-private" {
count = length(var.aws_cidr_subnets_private) count = "${length(var.aws_cidr_subnets_private)}"
vpc_id = aws_vpc.cluster-vpc.id vpc_id = "${aws_vpc.cluster-vpc.id}"
route { route {
cidr_block = "0.0.0.0/0" cidr_block = "0.0.0.0/0"
nat_gateway_id = element(aws_nat_gateway.cluster-nat-gateway.*.id, count.index) nat_gateway_id = "${element(aws_nat_gateway.cluster-nat-gateway.*.id, count.index)}"
} }
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-routetable-private-${count.index}" "Name", "kubernetes-${var.aws_cluster_name}-routetable-private-${count.index}"
)) ))}"
} }
resource "aws_route_table_association" "kubernetes-public" { resource "aws_route_table_association" "kubernetes-public" {
count = length(var.aws_cidr_subnets_public) count = "${length(var.aws_cidr_subnets_public)}"
subnet_id = element(aws_subnet.cluster-vpc-subnets-public.*.id, count.index) subnet_id = "${element(aws_subnet.cluster-vpc-subnets-public.*.id,count.index)}"
route_table_id = aws_route_table.kubernetes-public.id route_table_id = "${aws_route_table.kubernetes-public.id}"
} }
resource "aws_route_table_association" "kubernetes-private" { resource "aws_route_table_association" "kubernetes-private" {
count = length(var.aws_cidr_subnets_private) count = "${length(var.aws_cidr_subnets_private)}"
subnet_id = element(aws_subnet.cluster-vpc-subnets-private.*.id, count.index) subnet_id = "${element(aws_subnet.cluster-vpc-subnets-private.*.id,count.index)}"
route_table_id = element(aws_route_table.kubernetes-private.*.id, count.index) route_table_id = "${element(aws_route_table.kubernetes-private.*.id,count.index)}"
} }
#Kubernetes Security Groups #Kubernetes Security Groups
resource "aws_security_group" "kubernetes" { resource "aws_security_group" "kubernetes" {
name = "kubernetes-${var.aws_cluster_name}-securitygroup" name = "kubernetes-${var.aws_cluster_name}-securitygroup"
vpc_id = aws_vpc.cluster-vpc.id vpc_id = "${aws_vpc.cluster-vpc.id}"
tags = merge(var.default_tags, map( tags = "${merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-securitygroup" "Name", "kubernetes-${var.aws_cluster_name}-securitygroup"
)) ))}"
} }
resource "aws_security_group_rule" "allow-all-ingress" { resource "aws_security_group_rule" "allow-all-ingress" {
@@ -111,8 +111,8 @@ resource "aws_security_group_rule" "allow-all-ingress" {
from_port = 0 from_port = 0
to_port = 65535 to_port = 65535
protocol = "-1" protocol = "-1"
cidr_blocks = [var.aws_vpc_cidr_block] cidr_blocks = ["${var.aws_vpc_cidr_block}"]
security_group_id = aws_security_group.kubernetes.id security_group_id = "${aws_security_group.kubernetes.id}"
} }
resource "aws_security_group_rule" "allow-all-egress" { resource "aws_security_group_rule" "allow-all-egress" {
@@ -121,7 +121,7 @@ resource "aws_security_group_rule" "allow-all-egress" {
to_port = 65535 to_port = 65535
protocol = "-1" protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.kubernetes.id security_group_id = "${aws_security_group.kubernetes.id}"
} }
resource "aws_security_group_rule" "allow-ssh-connections" { resource "aws_security_group_rule" "allow-ssh-connections" {
@@ -130,5 +130,5 @@ resource "aws_security_group_rule" "allow-ssh-connections" {
to_port = 22 to_port = 22
protocol = "TCP" protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"] cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.kubernetes.id security_group_id = "${aws_security_group.kubernetes.id}"
} }

View File

@@ -1,19 +1,19 @@
output "aws_vpc_id" { output "aws_vpc_id" {
value = aws_vpc.cluster-vpc.id value = "${aws_vpc.cluster-vpc.id}"
} }
output "aws_subnet_ids_private" { output "aws_subnet_ids_private" {
value = aws_subnet.cluster-vpc-subnets-private.*.id value = ["${aws_subnet.cluster-vpc-subnets-private.*.id}"]
} }
output "aws_subnet_ids_public" { output "aws_subnet_ids_public" {
value = aws_subnet.cluster-vpc-subnets-public.*.id value = ["${aws_subnet.cluster-vpc-subnets-public.*.id}"]
} }
output "aws_security_group" { output "aws_security_group" {
value = aws_security_group.kubernetes.*.id value = ["${aws_security_group.kubernetes.*.id}"]
} }
output "default_tags" { output "default_tags" {
value = var.default_tags value = "${var.default_tags}"
} }

View File

@@ -1,17 +1,17 @@
output "bastion_ip" { output "bastion_ip" {
value = join("\n", aws_instance.bastion-server.*.public_ip) value = "${join("\n", aws_instance.bastion-server.*.public_ip)}"
} }
output "masters" { output "masters" {
value = join("\n", aws_instance.k8s-master.*.private_ip) value = "${join("\n", aws_instance.k8s-master.*.private_ip)}"
} }
output "workers" { output "workers" {
value = join("\n", aws_instance.k8s-worker.*.private_ip) value = "${join("\n", aws_instance.k8s-worker.*.private_ip)}"
} }
output "etcd" { output "etcd" {
value = join("\n", aws_instance.k8s-etcd.*.private_ip) value = "${join("\n", aws_instance.k8s-etcd.*.private_ip)}"
} }
output "aws_elb_api_fqdn" { output "aws_elb_api_fqdn" {
@@ -19,9 +19,9 @@ output "aws_elb_api_fqdn" {
} }
output "inventory" { output "inventory" {
value = data.template_file.inventory.rendered value = "${data.template_file.inventory.rendered}"
} }
output "default_tags" { output "default_tags" {
value = var.default_tags value = "${var.default_tags}"
} }

View File

@@ -2,9 +2,9 @@
aws_cluster_name = "devtest" aws_cluster_name = "devtest"
#VPC Vars #VPC Vars
aws_vpc_cidr_block = "10.250.192.0/18" aws_vpc_cidr_block = "10.250.192.0/18"
aws_cidr_subnets_private = ["10.250.192.0/20", "10.250.208.0/20"] aws_cidr_subnets_private = ["10.250.192.0/20","10.250.208.0/20"]
aws_cidr_subnets_public = ["10.250.224.0/20", "10.250.240.0/20"] aws_cidr_subnets_public = ["10.250.224.0/20","10.250.240.0/20"]
#Bastion Host #Bastion Host
aws_bastion_size = "t2.medium" aws_bastion_size = "t2.medium"
@@ -12,24 +12,24 @@ aws_bastion_size = "t2.medium"
#Kubernetes Cluster #Kubernetes Cluster
aws_kube_master_num = 3 aws_kube_master_num = 3
aws_kube_master_size = "t2.medium" aws_kube_master_size = "t2.medium"
aws_etcd_num = 3 aws_etcd_num = 3
aws_etcd_size = "t2.medium" aws_etcd_size = "t2.medium"
aws_kube_worker_num = 4 aws_kube_worker_num = 4
aws_kube_worker_size = "t2.medium" aws_kube_worker_size = "t2.medium"
#Settings AWS ELB #Settings AWS ELB
aws_elb_api_port = 6443 aws_elb_api_port = 6443
k8s_secure_api_port = 6443 k8s_secure_api_port = 6443
kube_insecure_apiserver_address = "0.0.0.0" kube_insecure_apiserver_address = "0.0.0.0"
default_tags = { default_tags = {
# Env = "devtest" # Env = "devtest"
# Product = "kubernetes" # Product = "kubernetes"
} }
inventory_file = "../../../inventory/hosts" inventory_file = "../../../inventory/hosts"

View File

@@ -25,7 +25,7 @@ data "aws_ami" "distro" {
filter { filter {
name = "name" name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] values = ["CoreOS-stable-*"]
} }
filter { filter {
@@ -33,7 +33,7 @@ data "aws_ami" "distro" {
values = ["hvm"] values = ["hvm"]
} }
owners = ["099720109477"] # Canonical owners = ["595879546273"] #CoreOS
} }
//AWS VPC Variables //AWS VPC Variables

View File

@@ -1,11 +1,11 @@
# Kubernetes on OpenStack with Terraform # Kubernetes on Openstack with Terraform
Provision a Kubernetes cluster with [Terraform](https://www.terraform.io) on Provision a Kubernetes cluster with [Terraform](https://www.terraform.io) on
OpenStack. Openstack.
## Status ## Status
This will install a Kubernetes cluster on an OpenStack Cloud. It should work on This will install a Kubernetes cluster on an Openstack Cloud. It should work on
most modern installs of OpenStack that support the basic services. most modern installs of OpenStack that support the basic services.
### Known compatible public clouds ### Known compatible public clouds
@@ -38,16 +38,6 @@ hosts where that makes sense. You have the option of creating bastion hosts
inside the private subnet to access the nodes there. Alternatively, a node with inside the private subnet to access the nodes there. Alternatively, a node with
a floating IP can be used as a jump host to nodes without. a floating IP can be used as a jump host to nodes without.
#### Using an existing router
It is possible to use an existing router instead of creating one. To use an
existing router set the router\_id variable to the uuid of the router you wish
to use.
For example:
```
router_id = "00c542e7-6f46-4535-ae95-984c7f0391a3"
```
### Kubernetes Nodes ### Kubernetes Nodes
You can create many different kubernetes topologies by setting the number of You can create many different kubernetes topologies by setting the number of
different classes of hosts. For each class there are options for allocating different classes of hosts. For each class there are options for allocating
@@ -72,9 +62,9 @@ specify:
- Size of the non-ephemeral volumes to be attached to store the GlusterFS bricks - Size of the non-ephemeral volumes to be attached to store the GlusterFS bricks
- Other properties related to provisioning the hosts - Other properties related to provisioning the hosts
Even if you are using Flatcar Container Linux by Kinvolk for your cluster, you will still Even if you are using Container Linux by CoreOS for your cluster, you will still
need the GlusterFS VMs to be based on either Debian or RedHat based images. need the GlusterFS VMs to be based on either Debian or RedHat based images.
Flatcar Container Linux by Kinvolk cannot serve GlusterFS, but can connect to it through Container Linux by CoreOS cannot serve GlusterFS, but can connect to it through
binaries available on hyperkube v1.4.3_coreos.0 or higher. binaries available on hyperkube v1.4.3_coreos.0 or higher.
## Requirements ## Requirements
@@ -234,9 +224,7 @@ For your cluster, edit `inventory/$CLUSTER/cluster.tfvars`.
|Variable | Description | |Variable | Description |
|---------|-------------| |---------|-------------|
|`cluster_name` | All OpenStack resources will use the Terraform variable`cluster_name` (default`example`) in their name to make it easier to track. For example the first compute resource will be named`example-kubernetes-1`. | |`cluster_name` | All OpenStack resources will use the Terraform variable`cluster_name` (default`example`) in their name to make it easier to track. For example the first compute resource will be named`example-kubernetes-1`. |
|`az_list` | List of Availability Zones available in your OpenStack cluster. |
|`network_name` | The name to be given to the internal network that will be generated | |`network_name` | The name to be given to the internal network that will be generated |
|`network_dns_domain` | (Optional) The dns_domain for the internal network that will be generated |
|`dns_nameservers`| An array of DNS name server names to be used by hosts in the internal subnet. | |`dns_nameservers`| An array of DNS name server names to be used by hosts in the internal subnet. |
|`floatingip_pool` | Name of the pool from which floating IPs will be allocated | |`floatingip_pool` | Name of the pool from which floating IPs will be allocated |
|`external_net` | UUID of the external network that will be routed to | |`external_net` | UUID of the external network that will be routed to |
@@ -258,113 +246,6 @@ For your cluster, edit `inventory/$CLUSTER/cluster.tfvars`.
|`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 |
|`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 |
|`wait_for_floatingip` | Let Terraform poll the instance until the floating IP has been associated, `false` by default. | |`wait_for_floatingip` | Let Terraform poll the instance until the floating IP has been associated, `false` by default. |
|`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 |
|`gfs_root_volume_size_in_gb` | Size of the root volume for gluster, 0 to use ephemeral storage |
|`etcd_root_volume_size_in_gb` | Size of the root volume for etcd nodes, 0 to use ephemeral storage |
|`bastion_root_volume_size_in_gb` | Size of the root volume for bastions, 0 to use ephemeral storage |
|`use_server_group` | Create and use openstack nova servergroups, default: false |
|`k8s_nodes` | Map containing worker node definition, see explanation below |
##### k8s_nodes
Allows a custom defintion of worker nodes giving the operator full control over individual node flavor and
availability zone placement. To enable the use of this mode set the `number_of_k8s_nodes` and
`number_of_k8s_nodes_no_floating_ip` variables to 0. Then define your desired worker node configuration
using the `k8s_nodes` variable.
For example:
```
k8s_nodes = {
"1" = {
"az" = "sto1"
"flavor" = "83d8b44a-26a0-4f02-a981-079446926445"
"floating_ip" = true
},
"2" = {
"az" = "sto2"
"flavor" = "83d8b44a-26a0-4f02-a981-079446926445"
"floating_ip" = true
},
"3" = {
"az" = "sto3"
"flavor" = "83d8b44a-26a0-4f02-a981-079446926445"
"floating_ip" = true
}
}
```
Would result in the same configuration as:
```
number_of_k8s_nodes = 3
flavor_k8s_node = "83d8b44a-26a0-4f02-a981-079446926445"
az_list = ["sto1", "sto2", "sto3"]
```
And:
```
k8s_nodes = {
"ing-1" = {
"az" = "sto1"
"flavor" = "83d8b44a-26a0-4f02-a981-079446926445"
"floating_ip" = true
},
"ing-2" = {
"az" = "sto2"
"flavor" = "83d8b44a-26a0-4f02-a981-079446926445"
"floating_ip" = true
},
"ing-3" = {
"az" = "sto3"
"flavor" = "83d8b44a-26a0-4f02-a981-079446926445"
"floating_ip" = true
},
"big-1" = {
"az" = "sto1"
"flavor" = "3f73fc93-ec61-4808-88df-2580d94c1a9b"
"floating_ip" = false
},
"big-2" = {
"az" = "sto2"
"flavor" = "3f73fc93-ec61-4808-88df-2580d94c1a9b"
"floating_ip" = false
},
"big-3" = {
"az" = "sto3"
"flavor" = "3f73fc93-ec61-4808-88df-2580d94c1a9b"
"floating_ip" = false
},
"small-1" = {
"az" = "sto1"
"flavor" = "7a6a998f-ac7f-4fb8-a534-2175b254f75e"
"floating_ip" = false
},
"small-2" = {
"az" = "sto2"
"flavor" = "7a6a998f-ac7f-4fb8-a534-2175b254f75e"
"floating_ip" = false
},
"small-3" = {
"az" = "sto3"
"flavor" = "7a6a998f-ac7f-4fb8-a534-2175b254f75e"
"floating_ip" = false
}
}
```
Would result in three nodes in each availability zone each with their own separate naming,
flavor and floating ip configuration.
The "schema":
```
k8s_nodes = {
"key | node name suffix, must be unique" = {
"az" = string
"flavor" = string
"floating_ip" = bool
},
}
```
All values are required.
#### Terraform state files #### Terraform state files
@@ -482,7 +363,7 @@ So, either a bastion host, or at least master/node with a floating IP are requir
#### Test access #### Test access
Make sure you can connect to the hosts. Note that Flatcar Container Linux by Kinvolk will have a state `FAILED` due to Python not being present. This is okay, because Python will be installed during bootstrapping, so long as the hosts are not `UNREACHABLE`. Make sure you can connect to the hosts. Note that Container Linux by CoreOS will have a state `FAILED` due to Python not being present. This is okay, because Python will be installed during bootstrapping, so long as the hosts are not `UNREACHABLE`.
``` ```
$ ansible -i inventory/$CLUSTER/hosts -m ping all $ ansible -i inventory/$CLUSTER/hosts -m ping all
@@ -510,7 +391,7 @@ Edit `inventory/$CLUSTER/group_vars/all/all.yml`:
# Directory where the binaries will be installed # Directory where the binaries will be installed
# Default: # Default:
# bin_dir: /usr/local/bin # bin_dir: /usr/local/bin
# For Flatcar Container Linux by Kinvolk: # For Container Linux by CoreOS:
bin_dir: /opt/bin bin_dir: /opt/bin
``` ```
- and **cloud_provider**: - and **cloud_provider**:
@@ -531,17 +412,14 @@ kube_network_plugin: flannel
# Can be docker_dns, host_resolvconf or none # Can be docker_dns, host_resolvconf or none
# Default: # Default:
# resolvconf_mode: docker_dns # resolvconf_mode: docker_dns
# For Flatcar Container Linux by Kinvolk: # For Container Linux by CoreOS:
resolvconf_mode: host_resolvconf resolvconf_mode: host_resolvconf
``` ```
- Set max amount of attached cinder volume per host (default 256) - Set max amount of attached cinder volume per host (default 256)
``` ```
node_volume_attach_limit: 26 node_volume_attach_limit: 26
``` ```
- Disable access_ip, this will make all innternal cluster traffic to be sent over local network when a floating IP is attached (default this value is set to 1)
```
use_access_ip: 0
```
### Deploy Kubernetes ### Deploy Kubernetes
@@ -605,81 +483,3 @@ $ ansible-playbook --become -i inventory/$CLUSTER/hosts ./contrib/network-storag
## What's next ## What's next
Try out your new Kubernetes cluster with the [Hello Kubernetes service](https://kubernetes.io/docs/tasks/access-application-cluster/service-access-application-cluster/). Try out your new Kubernetes cluster with the [Hello Kubernetes service](https://kubernetes.io/docs/tasks/access-application-cluster/service-access-application-cluster/).
## Appendix
### Migration from `number_of_k8s_nodes*` to `k8s_nodes`
If you currently have a cluster defined using the `number_of_k8s_nodes*` variables and wish
to migrate to the `k8s_nodes` style you can do it like so:
```ShellSession
$ terraform state list
module.compute.data.openstack_images_image_v2.gfs_image
module.compute.data.openstack_images_image_v2.vm_image
module.compute.openstack_compute_floatingip_associate_v2.k8s_master[0]
module.compute.openstack_compute_floatingip_associate_v2.k8s_node[0]
module.compute.openstack_compute_floatingip_associate_v2.k8s_node[1]
module.compute.openstack_compute_floatingip_associate_v2.k8s_node[2]
module.compute.openstack_compute_instance_v2.k8s_master[0]
module.compute.openstack_compute_instance_v2.k8s_node[0]
module.compute.openstack_compute_instance_v2.k8s_node[1]
module.compute.openstack_compute_instance_v2.k8s_node[2]
module.compute.openstack_compute_keypair_v2.k8s
module.compute.openstack_compute_servergroup_v2.k8s_etcd[0]
module.compute.openstack_compute_servergroup_v2.k8s_master[0]
module.compute.openstack_compute_servergroup_v2.k8s_node[0]
module.compute.openstack_networking_secgroup_rule_v2.bastion[0]
module.compute.openstack_networking_secgroup_rule_v2.egress[0]
module.compute.openstack_networking_secgroup_rule_v2.k8s
module.compute.openstack_networking_secgroup_rule_v2.k8s_allowed_remote_ips[0]
module.compute.openstack_networking_secgroup_rule_v2.k8s_allowed_remote_ips[1]
module.compute.openstack_networking_secgroup_rule_v2.k8s_allowed_remote_ips[2]
module.compute.openstack_networking_secgroup_rule_v2.k8s_master[0]
module.compute.openstack_networking_secgroup_rule_v2.worker[0]
module.compute.openstack_networking_secgroup_rule_v2.worker[1]
module.compute.openstack_networking_secgroup_rule_v2.worker[2]
module.compute.openstack_networking_secgroup_rule_v2.worker[3]
module.compute.openstack_networking_secgroup_rule_v2.worker[4]
module.compute.openstack_networking_secgroup_v2.bastion[0]
module.compute.openstack_networking_secgroup_v2.k8s
module.compute.openstack_networking_secgroup_v2.k8s_master
module.compute.openstack_networking_secgroup_v2.worker
module.ips.null_resource.dummy_dependency
module.ips.openstack_networking_floatingip_v2.k8s_master[0]
module.ips.openstack_networking_floatingip_v2.k8s_node[0]
module.ips.openstack_networking_floatingip_v2.k8s_node[1]
module.ips.openstack_networking_floatingip_v2.k8s_node[2]
module.network.openstack_networking_network_v2.k8s[0]
module.network.openstack_networking_router_interface_v2.k8s[0]
module.network.openstack_networking_router_v2.k8s[0]
module.network.openstack_networking_subnet_v2.k8s[0]
$ terraform state mv 'module.compute.openstack_compute_floatingip_associate_v2.k8s_node[0]' 'module.compute.openstack_compute_floatingip_associate_v2.k8s_nodes["1"]'
Move "module.compute.openstack_compute_floatingip_associate_v2.k8s_node[0]" to "module.compute.openstack_compute_floatingip_associate_v2.k8s_nodes[\"1\"]"
Successfully moved 1 object(s).
$ terraform state mv 'module.compute.openstack_compute_floatingip_associate_v2.k8s_node[1]' 'module.compute.openstack_compute_floatingip_associate_v2.k8s_nodes["2"]'
Move "module.compute.openstack_compute_floatingip_associate_v2.k8s_node[1]" to "module.compute.openstack_compute_floatingip_associate_v2.k8s_nodes[\"2\"]"
Successfully moved 1 object(s).
$ terraform state mv 'module.compute.openstack_compute_floatingip_associate_v2.k8s_node[2]' 'module.compute.openstack_compute_floatingip_associate_v2.k8s_nodes["3"]'
Move "module.compute.openstack_compute_floatingip_associate_v2.k8s_node[2]" to "module.compute.openstack_compute_floatingip_associate_v2.k8s_nodes[\"3\"]"
Successfully moved 1 object(s).
$ terraform state mv 'module.compute.openstack_compute_instance_v2.k8s_node[0]' 'module.compute.openstack_compute_instance_v2.k8s_node["1"]'
Move "module.compute.openstack_compute_instance_v2.k8s_node[0]" to "module.compute.openstack_compute_instance_v2.k8s_node[\"1\"]"
Successfully moved 1 object(s).
$ terraform state mv 'module.compute.openstack_compute_instance_v2.k8s_node[1]' 'module.compute.openstack_compute_instance_v2.k8s_node["2"]'
Move "module.compute.openstack_compute_instance_v2.k8s_node[1]" to "module.compute.openstack_compute_instance_v2.k8s_node[\"2\"]"
Successfully moved 1 object(s).
$ terraform state mv 'module.compute.openstack_compute_instance_v2.k8s_node[2]' 'module.compute.openstack_compute_instance_v2.k8s_node["3"]'
Move "module.compute.openstack_compute_instance_v2.k8s_node[2]" to "module.compute.openstack_compute_instance_v2.k8s_node[\"3\"]"
Successfully moved 1 object(s).
$ terraform state mv 'module.ips.openstack_networking_floatingip_v2.k8s_node[0]' 'module.ips.openstack_networking_floatingip_v2.k8s_node["1"]'
Move "module.ips.openstack_networking_floatingip_v2.k8s_node[0]" to "module.ips.openstack_networking_floatingip_v2.k8s_node[\"1\"]"
Successfully moved 1 object(s).
$ terraform state mv 'module.ips.openstack_networking_floatingip_v2.k8s_node[1]' 'module.ips.openstack_networking_floatingip_v2.k8s_node["2"]'
Move "module.ips.openstack_networking_floatingip_v2.k8s_node[1]" to "module.ips.openstack_networking_floatingip_v2.k8s_node[\"2\"]"
Successfully moved 1 object(s).
$ terraform state mv 'module.ips.openstack_networking_floatingip_v2.k8s_node[2]' 'module.ips.openstack_networking_floatingip_v2.k8s_node["3"]'
Move "module.ips.openstack_networking_floatingip_v2.k8s_node[2]" to "module.ips.openstack_networking_floatingip_v2.k8s_node[\"3\"]"
Successfully moved 1 object(s).
```
Of course for nodes without floating ips those steps can be omitted.

View File

@@ -5,104 +5,89 @@ provider "openstack" {
module "network" { module "network" {
source = "./modules/network" source = "./modules/network"
external_net = var.external_net external_net = "${var.external_net}"
network_name = var.network_name network_name = "${var.network_name}"
subnet_cidr = var.subnet_cidr subnet_cidr = "${var.subnet_cidr}"
cluster_name = var.cluster_name cluster_name = "${var.cluster_name}"
dns_nameservers = var.dns_nameservers dns_nameservers = "${var.dns_nameservers}"
network_dns_domain = var.network_dns_domain use_neutron = "${var.use_neutron}"
use_neutron = var.use_neutron
router_id = var.router_id
} }
module "ips" { module "ips" {
source = "./modules/ips" source = "./modules/ips"
number_of_k8s_masters = var.number_of_k8s_masters number_of_k8s_masters = "${var.number_of_k8s_masters}"
number_of_k8s_masters_no_etcd = var.number_of_k8s_masters_no_etcd number_of_k8s_masters_no_etcd = "${var.number_of_k8s_masters_no_etcd}"
number_of_k8s_nodes = var.number_of_k8s_nodes number_of_k8s_nodes = "${var.number_of_k8s_nodes}"
floatingip_pool = var.floatingip_pool floatingip_pool = "${var.floatingip_pool}"
number_of_bastions = var.number_of_bastions number_of_bastions = "${var.number_of_bastions}"
external_net = var.external_net external_net = "${var.external_net}"
network_name = var.network_name network_name = "${var.network_name}"
router_id = module.network.router_id router_id = "${module.network.router_id}"
k8s_nodes = var.k8s_nodes
} }
module "compute" { module "compute" {
source = "./modules/compute" source = "./modules/compute"
cluster_name = var.cluster_name cluster_name = "${var.cluster_name}"
az_list = var.az_list az_list = "${var.az_list}"
az_list_node = var.az_list_node number_of_k8s_masters = "${var.number_of_k8s_masters}"
number_of_k8s_masters = var.number_of_k8s_masters number_of_k8s_masters_no_etcd = "${var.number_of_k8s_masters_no_etcd}"
number_of_k8s_masters_no_etcd = var.number_of_k8s_masters_no_etcd number_of_etcd = "${var.number_of_etcd}"
number_of_etcd = var.number_of_etcd number_of_k8s_masters_no_floating_ip = "${var.number_of_k8s_masters_no_floating_ip}"
number_of_k8s_masters_no_floating_ip = var.number_of_k8s_masters_no_floating_ip number_of_k8s_masters_no_floating_ip_no_etcd = "${var.number_of_k8s_masters_no_floating_ip_no_etcd}"
number_of_k8s_masters_no_floating_ip_no_etcd = var.number_of_k8s_masters_no_floating_ip_no_etcd number_of_k8s_nodes = "${var.number_of_k8s_nodes}"
number_of_k8s_nodes = var.number_of_k8s_nodes number_of_bastions = "${var.number_of_bastions}"
number_of_bastions = var.number_of_bastions number_of_k8s_nodes_no_floating_ip = "${var.number_of_k8s_nodes_no_floating_ip}"
number_of_k8s_nodes_no_floating_ip = var.number_of_k8s_nodes_no_floating_ip number_of_gfs_nodes_no_floating_ip = "${var.number_of_gfs_nodes_no_floating_ip}"
number_of_gfs_nodes_no_floating_ip = var.number_of_gfs_nodes_no_floating_ip gfs_volume_size_in_gb = "${var.gfs_volume_size_in_gb}"
k8s_nodes = var.k8s_nodes public_key_path = "${var.public_key_path}"
bastion_root_volume_size_in_gb = var.bastion_root_volume_size_in_gb image = "${var.image}"
etcd_root_volume_size_in_gb = var.etcd_root_volume_size_in_gb image_gfs = "${var.image_gfs}"
master_root_volume_size_in_gb = var.master_root_volume_size_in_gb ssh_user = "${var.ssh_user}"
node_root_volume_size_in_gb = var.node_root_volume_size_in_gb ssh_user_gfs = "${var.ssh_user_gfs}"
gfs_root_volume_size_in_gb = var.gfs_root_volume_size_in_gb flavor_k8s_master = "${var.flavor_k8s_master}"
gfs_volume_size_in_gb = var.gfs_volume_size_in_gb flavor_k8s_node = "${var.flavor_k8s_node}"
master_volume_type = var.master_volume_type flavor_etcd = "${var.flavor_etcd}"
public_key_path = var.public_key_path flavor_gfs_node = "${var.flavor_gfs_node}"
image = var.image network_name = "${var.network_name}"
image_gfs = var.image_gfs flavor_bastion = "${var.flavor_bastion}"
ssh_user = var.ssh_user k8s_master_fips = "${module.ips.k8s_master_fips}"
ssh_user_gfs = var.ssh_user_gfs k8s_master_no_etcd_fips = "${module.ips.k8s_master_no_etcd_fips}"
flavor_k8s_master = var.flavor_k8s_master k8s_node_fips = "${module.ips.k8s_node_fips}"
flavor_k8s_node = var.flavor_k8s_node bastion_fips = "${module.ips.bastion_fips}"
flavor_etcd = var.flavor_etcd bastion_allowed_remote_ips = "${var.bastion_allowed_remote_ips}"
flavor_gfs_node = var.flavor_gfs_node master_allowed_remote_ips = "${var.master_allowed_remote_ips}"
network_name = var.network_name k8s_allowed_remote_ips = "${var.k8s_allowed_remote_ips}"
flavor_bastion = var.flavor_bastion k8s_allowed_egress_ips = "${var.k8s_allowed_egress_ips}"
k8s_master_fips = module.ips.k8s_master_fips supplementary_master_groups = "${var.supplementary_master_groups}"
k8s_master_no_etcd_fips = module.ips.k8s_master_no_etcd_fips supplementary_node_groups = "${var.supplementary_node_groups}"
k8s_node_fips = module.ips.k8s_node_fips worker_allowed_ports = "${var.worker_allowed_ports}"
k8s_nodes_fips = module.ips.k8s_nodes_fips wait_for_floatingip = "${var.wait_for_floatingip}"
bastion_fips = module.ips.bastion_fips
bastion_allowed_remote_ips = var.bastion_allowed_remote_ips
master_allowed_remote_ips = var.master_allowed_remote_ips
k8s_allowed_remote_ips = var.k8s_allowed_remote_ips
k8s_allowed_egress_ips = var.k8s_allowed_egress_ips
supplementary_master_groups = var.supplementary_master_groups
supplementary_node_groups = var.supplementary_node_groups
master_allowed_ports = var.master_allowed_ports
worker_allowed_ports = var.worker_allowed_ports
wait_for_floatingip = var.wait_for_floatingip
use_access_ip = var.use_access_ip
use_server_groups = var.use_server_groups
network_id = module.network.router_id network_id = "${module.network.router_id}"
} }
output "private_subnet_id" { output "private_subnet_id" {
value = module.network.subnet_id value = "${module.network.subnet_id}"
} }
output "floating_network_id" { output "floating_network_id" {
value = var.external_net value = "${var.external_net}"
} }
output "router_id" { output "router_id" {
value = module.network.router_id value = "${module.network.router_id}"
} }
output "k8s_master_fips" { output "k8s_master_fips" {
value = concat(module.ips.k8s_master_fips, module.ips.k8s_master_no_etcd_fips) value = "${concat(module.ips.k8s_master_fips, module.ips.k8s_master_no_etcd_fips)}"
} }
output "k8s_node_fips" { output "k8s_node_fips" {
value = var.number_of_k8s_nodes > 0 ? module.ips.k8s_node_fips : [for key, value in module.ips.k8s_nodes_fips : value.address] value = "${module.ips.k8s_node_fips}"
} }
output "bastion_fips" { output "bastion_fips" {
value = module.ips.bastion_fips value = "${module.ips.bastion_fips}"
} }

View File

@@ -1,14 +1,6 @@
data "openstack_images_image_v2" "vm_image" {
name = var.image
}
data "openstack_images_image_v2" "gfs_image" {
name = var.image_gfs == "" ? var.image : var.image_gfs
}
resource "openstack_compute_keypair_v2" "k8s" { resource "openstack_compute_keypair_v2" "k8s" {
name = "kubernetes-${var.cluster_name}" name = "kubernetes-${var.cluster_name}"
public_key = chomp(file(var.public_key_path)) public_key = "${chomp(file(var.public_key_path))}"
} }
resource "openstack_networking_secgroup_v2" "k8s_master" { resource "openstack_networking_secgroup_v2" "k8s_master" {
@@ -18,43 +10,32 @@ resource "openstack_networking_secgroup_v2" "k8s_master" {
} }
resource "openstack_networking_secgroup_rule_v2" "k8s_master" { resource "openstack_networking_secgroup_rule_v2" "k8s_master" {
count = length(var.master_allowed_remote_ips) count = "${length(var.master_allowed_remote_ips)}"
direction = "ingress" direction = "ingress"
ethertype = "IPv4" ethertype = "IPv4"
protocol = "tcp" protocol = "tcp"
port_range_min = "6443" port_range_min = "6443"
port_range_max = "6443" port_range_max = "6443"
remote_ip_prefix = var.master_allowed_remote_ips[count.index] remote_ip_prefix = "${var.master_allowed_remote_ips[count.index]}"
security_group_id = openstack_networking_secgroup_v2.k8s_master.id security_group_id = "${openstack_networking_secgroup_v2.k8s_master.id}"
}
resource "openstack_networking_secgroup_rule_v2" "k8s_master_ports" {
count = length(var.master_allowed_ports)
direction = "ingress"
ethertype = "IPv4"
protocol = lookup(var.master_allowed_ports[count.index], "protocol", "tcp")
port_range_min = lookup(var.master_allowed_ports[count.index], "port_range_min")
port_range_max = lookup(var.master_allowed_ports[count.index], "port_range_max")
remote_ip_prefix = lookup(var.master_allowed_ports[count.index], "remote_ip_prefix", "0.0.0.0/0")
security_group_id = openstack_networking_secgroup_v2.k8s_master.id
} }
resource "openstack_networking_secgroup_v2" "bastion" { resource "openstack_networking_secgroup_v2" "bastion" {
name = "${var.cluster_name}-bastion" name = "${var.cluster_name}-bastion"
count = var.number_of_bastions != "" ? 1 : 0 count = "${var.number_of_bastions != "" ? 1 : 0}"
description = "${var.cluster_name} - Bastion Server" description = "${var.cluster_name} - Bastion Server"
delete_default_rules = true delete_default_rules = true
} }
resource "openstack_networking_secgroup_rule_v2" "bastion" { resource "openstack_networking_secgroup_rule_v2" "bastion" {
count = var.number_of_bastions != "" ? length(var.bastion_allowed_remote_ips) : 0 count = "${var.number_of_bastions != "" ? length(var.bastion_allowed_remote_ips) : 0}"
direction = "ingress" direction = "ingress"
ethertype = "IPv4" ethertype = "IPv4"
protocol = "tcp" protocol = "tcp"
port_range_min = "22" port_range_min = "22"
port_range_max = "22" port_range_max = "22"
remote_ip_prefix = var.bastion_allowed_remote_ips[count.index] remote_ip_prefix = "${var.bastion_allowed_remote_ips[count.index]}"
security_group_id = openstack_networking_secgroup_v2.bastion[0].id security_group_id = "${openstack_networking_secgroup_v2.bastion[count.index].id}"
} }
resource "openstack_networking_secgroup_v2" "k8s" { resource "openstack_networking_secgroup_v2" "k8s" {
@@ -66,27 +47,27 @@ resource "openstack_networking_secgroup_v2" "k8s" {
resource "openstack_networking_secgroup_rule_v2" "k8s" { resource "openstack_networking_secgroup_rule_v2" "k8s" {
direction = "ingress" direction = "ingress"
ethertype = "IPv4" ethertype = "IPv4"
remote_group_id = openstack_networking_secgroup_v2.k8s.id remote_group_id = "${openstack_networking_secgroup_v2.k8s.id}"
security_group_id = openstack_networking_secgroup_v2.k8s.id security_group_id = "${openstack_networking_secgroup_v2.k8s.id}"
} }
resource "openstack_networking_secgroup_rule_v2" "k8s_allowed_remote_ips" { resource "openstack_networking_secgroup_rule_v2" "k8s_allowed_remote_ips" {
count = length(var.k8s_allowed_remote_ips) count = "${length(var.k8s_allowed_remote_ips)}"
direction = "ingress" direction = "ingress"
ethertype = "IPv4" ethertype = "IPv4"
protocol = "tcp" protocol = "tcp"
port_range_min = "22" port_range_min = "22"
port_range_max = "22" port_range_max = "22"
remote_ip_prefix = var.k8s_allowed_remote_ips[count.index] remote_ip_prefix = "${var.k8s_allowed_remote_ips[count.index]}"
security_group_id = openstack_networking_secgroup_v2.k8s.id security_group_id = "${openstack_networking_secgroup_v2.k8s.id}"
} }
resource "openstack_networking_secgroup_rule_v2" "egress" { resource "openstack_networking_secgroup_rule_v2" "egress" {
count = length(var.k8s_allowed_egress_ips) count = "${length(var.k8s_allowed_egress_ips)}"
direction = "egress" direction = "egress"
ethertype = "IPv4" ethertype = "IPv4"
remote_ip_prefix = var.k8s_allowed_egress_ips[count.index] remote_ip_prefix = "${var.k8s_allowed_egress_ips[count.index]}"
security_group_id = openstack_networking_secgroup_v2.k8s.id security_group_id = "${openstack_networking_secgroup_v2.k8s.id}"
} }
resource "openstack_networking_secgroup_v2" "worker" { resource "openstack_networking_secgroup_v2" "worker" {
@@ -96,66 +77,35 @@ resource "openstack_networking_secgroup_v2" "worker" {
} }
resource "openstack_networking_secgroup_rule_v2" "worker" { resource "openstack_networking_secgroup_rule_v2" "worker" {
count = length(var.worker_allowed_ports) count = "${length(var.worker_allowed_ports)}"
direction = "ingress" direction = "ingress"
ethertype = "IPv4" ethertype = "IPv4"
protocol = lookup(var.worker_allowed_ports[count.index], "protocol", "tcp") protocol = "${lookup(var.worker_allowed_ports[count.index], "protocol", "tcp")}"
port_range_min = lookup(var.worker_allowed_ports[count.index], "port_range_min") port_range_min = "${lookup(var.worker_allowed_ports[count.index], "port_range_min")}"
port_range_max = lookup(var.worker_allowed_ports[count.index], "port_range_max") port_range_max = "${lookup(var.worker_allowed_ports[count.index], "port_range_max")}"
remote_ip_prefix = lookup(var.worker_allowed_ports[count.index], "remote_ip_prefix", "0.0.0.0/0") remote_ip_prefix = "${lookup(var.worker_allowed_ports[count.index], "remote_ip_prefix", "0.0.0.0/0")}"
security_group_id = openstack_networking_secgroup_v2.worker.id security_group_id = "${openstack_networking_secgroup_v2.worker.id}"
}
resource "openstack_compute_servergroup_v2" "k8s_master" {
count = "%{if var.use_server_groups}1%{else}0%{endif}"
name = "k8s-master-srvgrp"
policies = ["anti-affinity"]
}
resource "openstack_compute_servergroup_v2" "k8s_node" {
count = "%{if var.use_server_groups}1%{else}0%{endif}"
name = "k8s-node-srvgrp"
policies = ["anti-affinity"]
}
resource "openstack_compute_servergroup_v2" "k8s_etcd" {
count = "%{if var.use_server_groups}1%{else}0%{endif}"
name = "k8s-etcd-srvgrp"
policies = ["anti-affinity"]
} }
resource "openstack_compute_instance_v2" "bastion" { resource "openstack_compute_instance_v2" "bastion" {
name = "${var.cluster_name}-bastion-${count.index + 1}" name = "${var.cluster_name}-bastion-${count.index+1}"
count = var.number_of_bastions count = "${var.number_of_bastions}"
image_name = var.image image_name = "${var.image}"
flavor_id = var.flavor_bastion flavor_id = "${var.flavor_bastion}"
key_pair = openstack_compute_keypair_v2.k8s.name key_pair = "${openstack_compute_keypair_v2.k8s.name}"
dynamic "block_device" {
for_each = var.bastion_root_volume_size_in_gb > 0 ? [var.image] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
source_type = "image"
volume_size = var.bastion_root_volume_size_in_gb
boot_index = 0
destination_type = "volume"
delete_on_termination = true
}
}
network { network {
name = var.network_name name = "${var.network_name}"
} }
security_groups = [openstack_networking_secgroup_v2.k8s.name, security_groups = ["${openstack_networking_secgroup_v2.k8s.name}",
element(openstack_networking_secgroup_v2.bastion.*.name, count.index), "${element(openstack_networking_secgroup_v2.bastion.*.name, count.index)}",
] ]
metadata = { metadata = {
ssh_user = var.ssh_user ssh_user = "${var.ssh_user}"
kubespray_groups = "bastion" kubespray_groups = "bastion"
depends_on = var.network_id depends_on = "${var.network_id}"
use_access_ip = var.use_access_ip
} }
provisioner "local-exec" { provisioner "local-exec" {
@@ -164,454 +114,233 @@ resource "openstack_compute_instance_v2" "bastion" {
} }
resource "openstack_compute_instance_v2" "k8s_master" { resource "openstack_compute_instance_v2" "k8s_master" {
name = "${var.cluster_name}-k8s-master-${count.index + 1}" name = "${var.cluster_name}-k8s-master-${count.index+1}"
count = var.number_of_k8s_masters count = "${var.number_of_k8s_masters}"
availability_zone = element(var.az_list, count.index) availability_zone = "${element(var.az_list, count.index)}"
image_name = var.image image_name = "${var.image}"
flavor_id = var.flavor_k8s_master flavor_id = "${var.flavor_k8s_master}"
key_pair = openstack_compute_keypair_v2.k8s.name key_pair = "${openstack_compute_keypair_v2.k8s.name}"
dynamic "block_device" {
for_each = var.master_root_volume_size_in_gb > 0 ? [var.image] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
source_type = "image"
volume_size = var.master_root_volume_size_in_gb
volume_type = var.master_volume_type
boot_index = 0
destination_type = "volume"
delete_on_termination = true
}
}
network { network {
name = var.network_name name = "${var.network_name}"
} }
security_groups = [openstack_networking_secgroup_v2.k8s_master.name, security_groups = ["${openstack_networking_secgroup_v2.k8s_master.name}",
openstack_networking_secgroup_v2.k8s.name, "${openstack_networking_secgroup_v2.k8s.name}",
] ]
dynamic "scheduler_hints" {
for_each = var.use_server_groups ? [openstack_compute_servergroup_v2.k8s_master[0]] : []
content {
group = openstack_compute_servergroup_v2.k8s_master[0].id
}
}
metadata = { metadata = {
ssh_user = var.ssh_user ssh_user = "${var.ssh_user}"
kubespray_groups = "etcd,kube-master,${var.supplementary_master_groups},k8s-cluster,vault" kubespray_groups = "etcd,kube-master,${var.supplementary_master_groups},k8s-cluster,vault"
depends_on = var.network_id depends_on = "${var.network_id}"
use_access_ip = var.use_access_ip
} }
provisioner "local-exec" { provisioner "local-exec" {
command = "sed s/USER/${var.ssh_user}/ ../../contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${element(concat(var.bastion_fips, var.k8s_master_fips), 0)}/ > group_vars/no-floating.yml" command = "sed s/USER/${var.ssh_user}/ ../../contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${element( concat(var.bastion_fips, var.k8s_master_fips), 0)}/ > group_vars/no-floating.yml"
} }
} }
resource "openstack_compute_instance_v2" "k8s_master_no_etcd" { resource "openstack_compute_instance_v2" "k8s_master_no_etcd" {
name = "${var.cluster_name}-k8s-master-ne-${count.index + 1}" name = "${var.cluster_name}-k8s-master-ne-${count.index+1}"
count = var.number_of_k8s_masters_no_etcd count = "${var.number_of_k8s_masters_no_etcd}"
availability_zone = element(var.az_list, count.index) availability_zone = "${element(var.az_list, count.index)}"
image_name = var.image image_name = "${var.image}"
flavor_id = var.flavor_k8s_master flavor_id = "${var.flavor_k8s_master}"
key_pair = openstack_compute_keypair_v2.k8s.name key_pair = "${openstack_compute_keypair_v2.k8s.name}"
dynamic "block_device" {
for_each = var.master_root_volume_size_in_gb > 0 ? [var.image] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
source_type = "image"
volume_size = var.master_root_volume_size_in_gb
volume_type = var.master_volume_type
boot_index = 0
destination_type = "volume"
delete_on_termination = true
}
}
network { network {
name = var.network_name name = "${var.network_name}"
} }
security_groups = [openstack_networking_secgroup_v2.k8s_master.name, security_groups = ["${openstack_networking_secgroup_v2.k8s_master.name}",
openstack_networking_secgroup_v2.k8s.name, "${openstack_networking_secgroup_v2.k8s.name}",
] ]
dynamic "scheduler_hints" {
for_each = var.use_server_groups ? [openstack_compute_servergroup_v2.k8s_master[0]] : []
content {
group = openstack_compute_servergroup_v2.k8s_master[0].id
}
}
metadata = { metadata = {
ssh_user = var.ssh_user ssh_user = "${var.ssh_user}"
kubespray_groups = "kube-master,${var.supplementary_master_groups},k8s-cluster,vault" kubespray_groups = "kube-master,${var.supplementary_master_groups},k8s-cluster,vault"
depends_on = var.network_id depends_on = "${var.network_id}"
use_access_ip = var.use_access_ip
} }
provisioner "local-exec" { provisioner "local-exec" {
command = "sed s/USER/${var.ssh_user}/ ../../contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${element(concat(var.bastion_fips, var.k8s_master_fips), 0)}/ > group_vars/no-floating.yml" command = "sed s/USER/${var.ssh_user}/ ../../contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${element( concat(var.bastion_fips, var.k8s_master_fips), 0)}/ > group_vars/no-floating.yml"
} }
} }
resource "openstack_compute_instance_v2" "etcd" { resource "openstack_compute_instance_v2" "etcd" {
name = "${var.cluster_name}-etcd-${count.index + 1}" name = "${var.cluster_name}-etcd-${count.index+1}"
count = var.number_of_etcd count = "${var.number_of_etcd}"
availability_zone = element(var.az_list, count.index) availability_zone = "${element(var.az_list, count.index)}"
image_name = var.image image_name = "${var.image}"
flavor_id = var.flavor_etcd flavor_id = "${var.flavor_etcd}"
key_pair = openstack_compute_keypair_v2.k8s.name key_pair = "${openstack_compute_keypair_v2.k8s.name}"
dynamic "block_device" {
for_each = var.etcd_root_volume_size_in_gb > 0 ? [var.image] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
source_type = "image"
volume_size = var.etcd_root_volume_size_in_gb
boot_index = 0
destination_type = "volume"
delete_on_termination = true
}
}
network { network {
name = var.network_name name = "${var.network_name}"
} }
security_groups = [openstack_networking_secgroup_v2.k8s.name] security_groups = ["${openstack_networking_secgroup_v2.k8s.name}"]
dynamic "scheduler_hints" {
for_each = var.use_server_groups ? [openstack_compute_servergroup_v2.k8s_etcd[0]] : []
content {
group = openstack_compute_servergroup_v2.k8s_etcd[0].id
}
}
metadata = { metadata = {
ssh_user = var.ssh_user ssh_user = "${var.ssh_user}"
kubespray_groups = "etcd,vault,no-floating" kubespray_groups = "etcd,vault,no-floating"
depends_on = var.network_id depends_on = "${var.network_id}"
use_access_ip = var.use_access_ip
} }
} }
resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip" { resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip" {
name = "${var.cluster_name}-k8s-master-nf-${count.index + 1}" name = "${var.cluster_name}-k8s-master-nf-${count.index+1}"
count = var.number_of_k8s_masters_no_floating_ip count = "${var.number_of_k8s_masters_no_floating_ip}"
availability_zone = element(var.az_list, count.index) availability_zone = "${element(var.az_list, count.index)}"
image_name = var.image image_name = "${var.image}"
flavor_id = var.flavor_k8s_master flavor_id = "${var.flavor_k8s_master}"
key_pair = openstack_compute_keypair_v2.k8s.name key_pair = "${openstack_compute_keypair_v2.k8s.name}"
dynamic "block_device" {
for_each = var.master_root_volume_size_in_gb > 0 ? [var.image] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
source_type = "image"
volume_size = var.master_root_volume_size_in_gb
volume_type = var.master_volume_type
boot_index = 0
destination_type = "volume"
delete_on_termination = true
}
}
network { network {
name = var.network_name name = "${var.network_name}"
} }
security_groups = [openstack_networking_secgroup_v2.k8s_master.name, security_groups = ["${openstack_networking_secgroup_v2.k8s_master.name}",
openstack_networking_secgroup_v2.k8s.name, "${openstack_networking_secgroup_v2.k8s.name}",
] ]
dynamic "scheduler_hints" {
for_each = var.use_server_groups ? [openstack_compute_servergroup_v2.k8s_master[0]] : []
content {
group = openstack_compute_servergroup_v2.k8s_master[0].id
}
}
metadata = { metadata = {
ssh_user = var.ssh_user ssh_user = "${var.ssh_user}"
kubespray_groups = "etcd,kube-master,${var.supplementary_master_groups},k8s-cluster,vault,no-floating" kubespray_groups = "etcd,kube-master,${var.supplementary_master_groups},k8s-cluster,vault,no-floating"
depends_on = var.network_id depends_on = "${var.network_id}"
use_access_ip = var.use_access_ip
} }
} }
resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip_no_etcd" { resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip_no_etcd" {
name = "${var.cluster_name}-k8s-master-ne-nf-${count.index + 1}" name = "${var.cluster_name}-k8s-master-ne-nf-${count.index+1}"
count = var.number_of_k8s_masters_no_floating_ip_no_etcd count = "${var.number_of_k8s_masters_no_floating_ip_no_etcd}"
availability_zone = element(var.az_list, count.index) availability_zone = "${element(var.az_list, count.index)}"
image_name = var.image image_name = "${var.image}"
flavor_id = var.flavor_k8s_master flavor_id = "${var.flavor_k8s_master}"
key_pair = openstack_compute_keypair_v2.k8s.name key_pair = "${openstack_compute_keypair_v2.k8s.name}"
dynamic "block_device" {
for_each = var.master_root_volume_size_in_gb > 0 ? [var.image] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
source_type = "image"
volume_size = var.master_root_volume_size_in_gb
volume_type = var.master_volume_type
boot_index = 0
destination_type = "volume"
delete_on_termination = true
}
}
network { network {
name = var.network_name name = "${var.network_name}"
} }
security_groups = [openstack_networking_secgroup_v2.k8s_master.name, security_groups = ["${openstack_networking_secgroup_v2.k8s_master.name}",
openstack_networking_secgroup_v2.k8s.name, "${openstack_networking_secgroup_v2.k8s.name}",
] ]
dynamic "scheduler_hints" {
for_each = var.use_server_groups ? [openstack_compute_servergroup_v2.k8s_master[0]] : []
content {
group = openstack_compute_servergroup_v2.k8s_master[0].id
}
}
metadata = { metadata = {
ssh_user = var.ssh_user ssh_user = "${var.ssh_user}"
kubespray_groups = "kube-master,${var.supplementary_master_groups},k8s-cluster,vault,no-floating" kubespray_groups = "kube-master,${var.supplementary_master_groups},k8s-cluster,vault,no-floating"
depends_on = var.network_id depends_on = "${var.network_id}"
use_access_ip = var.use_access_ip
} }
} }
resource "openstack_compute_instance_v2" "k8s_node" { resource "openstack_compute_instance_v2" "k8s_node" {
name = "${var.cluster_name}-k8s-node-${count.index + 1}" name = "${var.cluster_name}-k8s-node-${count.index+1}"
count = var.number_of_k8s_nodes count = "${var.number_of_k8s_nodes}"
availability_zone = element(var.az_list_node, count.index) availability_zone = "${element(var.az_list, count.index)}"
image_name = var.image image_name = "${var.image}"
flavor_id = var.flavor_k8s_node flavor_id = "${var.flavor_k8s_node}"
key_pair = openstack_compute_keypair_v2.k8s.name key_pair = "${openstack_compute_keypair_v2.k8s.name}"
dynamic "block_device" {
for_each = var.node_root_volume_size_in_gb > 0 ? [var.image] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
source_type = "image"
volume_size = var.node_root_volume_size_in_gb
boot_index = 0
destination_type = "volume"
delete_on_termination = true
}
}
network { network {
name = var.network_name name = "${var.network_name}"
} }
security_groups = [openstack_networking_secgroup_v2.k8s.name, security_groups = ["${openstack_networking_secgroup_v2.k8s.name}",
openstack_networking_secgroup_v2.worker.name, "${openstack_networking_secgroup_v2.worker.name}",
] ]
dynamic "scheduler_hints" {
for_each = var.use_server_groups ? [openstack_compute_servergroup_v2.k8s_node[0]] : []
content {
group = openstack_compute_servergroup_v2.k8s_node[0].id
}
}
metadata = { metadata = {
ssh_user = var.ssh_user ssh_user = "${var.ssh_user}"
kubespray_groups = "kube-node,k8s-cluster,${var.supplementary_node_groups}" kubespray_groups = "kube-node,k8s-cluster,${var.supplementary_node_groups}"
depends_on = var.network_id depends_on = "${var.network_id}"
use_access_ip = var.use_access_ip
} }
provisioner "local-exec" { provisioner "local-exec" {
command = "sed s/USER/${var.ssh_user}/ ../../contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${element(concat(var.bastion_fips, var.k8s_node_fips), 0)}/ > group_vars/no-floating.yml" command = "sed s/USER/${var.ssh_user}/ ../../contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${element( concat(var.bastion_fips, var.k8s_node_fips), 0)}/ > group_vars/no-floating.yml"
} }
} }
resource "openstack_compute_instance_v2" "k8s_node_no_floating_ip" { resource "openstack_compute_instance_v2" "k8s_node_no_floating_ip" {
name = "${var.cluster_name}-k8s-node-nf-${count.index + 1}" name = "${var.cluster_name}-k8s-node-nf-${count.index+1}"
count = var.number_of_k8s_nodes_no_floating_ip count = "${var.number_of_k8s_nodes_no_floating_ip}"
availability_zone = element(var.az_list_node, count.index) availability_zone = "${element(var.az_list, count.index)}"
image_name = var.image image_name = "${var.image}"
flavor_id = var.flavor_k8s_node flavor_id = "${var.flavor_k8s_node}"
key_pair = openstack_compute_keypair_v2.k8s.name key_pair = "${openstack_compute_keypair_v2.k8s.name}"
dynamic "block_device" {
for_each = var.node_root_volume_size_in_gb > 0 ? [var.image] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
source_type = "image"
volume_size = var.node_root_volume_size_in_gb
boot_index = 0
destination_type = "volume"
delete_on_termination = true
}
}
network { network {
name = var.network_name name = "${var.network_name}"
} }
security_groups = [openstack_networking_secgroup_v2.k8s.name, security_groups = ["${openstack_networking_secgroup_v2.k8s.name}",
openstack_networking_secgroup_v2.worker.name, "${openstack_networking_secgroup_v2.worker.name}",
] ]
dynamic "scheduler_hints" {
for_each = var.use_server_groups ? [openstack_compute_servergroup_v2.k8s_node[0]] : []
content {
group = openstack_compute_servergroup_v2.k8s_node[0].id
}
}
metadata = { metadata = {
ssh_user = var.ssh_user ssh_user = "${var.ssh_user}"
kubespray_groups = "kube-node,k8s-cluster,no-floating,${var.supplementary_node_groups}" kubespray_groups = "kube-node,k8s-cluster,no-floating,${var.supplementary_node_groups}"
depends_on = var.network_id depends_on = "${var.network_id}"
use_access_ip = var.use_access_ip
}
}
resource "openstack_compute_instance_v2" "k8s_nodes" {
for_each = var.number_of_k8s_nodes == 0 && var.number_of_k8s_nodes_no_floating_ip == 0 ? var.k8s_nodes : {}
name = "${var.cluster_name}-k8s-node-${each.key}"
availability_zone = each.value.az
image_name = var.image
flavor_id = each.value.flavor
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.node_root_volume_size_in_gb > 0 ? [var.image] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
source_type = "image"
volume_size = var.node_root_volume_size_in_gb
boot_index = 0
destination_type = "volume"
delete_on_termination = true
}
}
network {
name = var.network_name
}
security_groups = [openstack_networking_secgroup_v2.k8s.name,
openstack_networking_secgroup_v2.worker.name,
]
dynamic "scheduler_hints" {
for_each = var.use_server_groups ? [openstack_compute_servergroup_v2.k8s_node[0]] : []
content {
group = openstack_compute_servergroup_v2.k8s_node[0].id
}
}
metadata = {
ssh_user = var.ssh_user
kubespray_groups = "kube-node,k8s-cluster,%{if each.value.floating_ip == false}no-floating,%{endif}${var.supplementary_node_groups}"
depends_on = var.network_id
use_access_ip = var.use_access_ip
}
provisioner "local-exec" {
command = "%{if each.value.floating_ip}sed s/USER/${var.ssh_user}/ ../../contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${element(concat(var.bastion_fips, [for key, value in var.k8s_nodes_fips : value.address]), 0)}/ > group_vars/no-floating.yml%{else}true%{endif}"
}
}
resource "openstack_compute_instance_v2" "glusterfs_node_no_floating_ip" {
name = "${var.cluster_name}-gfs-node-nf-${count.index + 1}"
count = var.number_of_gfs_nodes_no_floating_ip
availability_zone = element(var.az_list, count.index)
image_name = var.image_gfs
flavor_id = var.flavor_gfs_node
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.gfs_root_volume_size_in_gb > 0 ? [var.image] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
source_type = "image"
volume_size = var.gfs_root_volume_size_in_gb
boot_index = 0
destination_type = "volume"
delete_on_termination = true
}
}
network {
name = var.network_name
}
security_groups = [openstack_networking_secgroup_v2.k8s.name]
dynamic "scheduler_hints" {
for_each = var.use_server_groups ? [openstack_compute_servergroup_v2.k8s_node[0]] : []
content {
group = openstack_compute_servergroup_v2.k8s_node[0].id
}
}
metadata = {
ssh_user = var.ssh_user_gfs
kubespray_groups = "gfs-cluster,network-storage,no-floating"
depends_on = var.network_id
use_access_ip = var.use_access_ip
} }
} }
resource "openstack_compute_floatingip_associate_v2" "bastion" { resource "openstack_compute_floatingip_associate_v2" "bastion" {
count = var.number_of_bastions count = "${var.number_of_bastions}"
floating_ip = var.bastion_fips[count.index] floating_ip = "${var.bastion_fips[count.index]}"
instance_id = element(openstack_compute_instance_v2.bastion.*.id, count.index) instance_id = "${element(openstack_compute_instance_v2.bastion.*.id, count.index)}"
wait_until_associated = var.wait_for_floatingip wait_until_associated = "${var.wait_for_floatingip}"
} }
resource "openstack_compute_floatingip_associate_v2" "k8s_master" { resource "openstack_compute_floatingip_associate_v2" "k8s_master" {
count = var.number_of_k8s_masters count = "${var.number_of_k8s_masters}"
instance_id = element(openstack_compute_instance_v2.k8s_master.*.id, count.index) instance_id = "${element(openstack_compute_instance_v2.k8s_master.*.id, count.index)}"
floating_ip = var.k8s_master_fips[count.index] floating_ip = "${var.k8s_master_fips[count.index]}"
wait_until_associated = var.wait_for_floatingip wait_until_associated = "${var.wait_for_floatingip}"
} }
resource "openstack_compute_floatingip_associate_v2" "k8s_master_no_etcd" { resource "openstack_compute_floatingip_associate_v2" "k8s_master_no_etcd" {
count = var.master_root_volume_size_in_gb == 0 ? var.number_of_k8s_masters_no_etcd : 0 count = "${var.number_of_k8s_masters_no_etcd}"
instance_id = element(openstack_compute_instance_v2.k8s_master_no_etcd.*.id, count.index) instance_id = "${element(openstack_compute_instance_v2.k8s_master_no_etcd.*.id, count.index)}"
floating_ip = var.k8s_master_no_etcd_fips[count.index] floating_ip = "${var.k8s_master_no_etcd_fips[count.index]}"
} }
resource "openstack_compute_floatingip_associate_v2" "k8s_node" { resource "openstack_compute_floatingip_associate_v2" "k8s_node" {
count = var.node_root_volume_size_in_gb == 0 ? var.number_of_k8s_nodes : 0 count = "${var.number_of_k8s_nodes}"
floating_ip = var.k8s_node_fips[count.index] floating_ip = "${var.k8s_node_fips[count.index]}"
instance_id = element(openstack_compute_instance_v2.k8s_node[*].id, count.index) instance_id = "${element(openstack_compute_instance_v2.k8s_node.*.id, count.index)}"
wait_until_associated = var.wait_for_floatingip wait_until_associated = "${var.wait_for_floatingip}"
}
resource "openstack_compute_floatingip_associate_v2" "k8s_nodes" {
for_each = var.number_of_k8s_nodes == 0 && var.number_of_k8s_nodes_no_floating_ip == 0 ? { for key, value in var.k8s_nodes : key => value if value.floating_ip } : {}
floating_ip = var.k8s_nodes_fips[each.key].address
instance_id = openstack_compute_instance_v2.k8s_nodes[each.key].id
wait_until_associated = var.wait_for_floatingip
} }
resource "openstack_blockstorage_volume_v2" "glusterfs_volume" { resource "openstack_blockstorage_volume_v2" "glusterfs_volume" {
name = "${var.cluster_name}-glusterfs_volume-${count.index + 1}" name = "${var.cluster_name}-glusterfs_volume-${count.index+1}"
count = var.gfs_root_volume_size_in_gb == 0 ? var.number_of_gfs_nodes_no_floating_ip : 0 count = "${var.number_of_gfs_nodes_no_floating_ip}"
description = "Non-ephemeral volume for GlusterFS" description = "Non-ephemeral volume for GlusterFS"
size = var.gfs_volume_size_in_gb size = "${var.gfs_volume_size_in_gb}"
}
resource "openstack_compute_instance_v2" "glusterfs_node_no_floating_ip" {
name = "${var.cluster_name}-gfs-node-nf-${count.index+1}"
count = "${var.number_of_gfs_nodes_no_floating_ip}"
availability_zone = "${element(var.az_list, count.index)}"
image_name = "${var.image_gfs}"
flavor_id = "${var.flavor_gfs_node}"
key_pair = "${openstack_compute_keypair_v2.k8s.name}"
network {
name = "${var.network_name}"
}
security_groups = ["${openstack_networking_secgroup_v2.k8s.name}"]
metadata = {
ssh_user = "${var.ssh_user_gfs}"
kubespray_groups = "gfs-cluster,network-storage,no-floating"
depends_on = "${var.network_id}"
}
} }
resource "openstack_compute_volume_attach_v2" "glusterfs_volume" { resource "openstack_compute_volume_attach_v2" "glusterfs_volume" {
count = var.gfs_root_volume_size_in_gb == 0 ? var.number_of_gfs_nodes_no_floating_ip : 0 count = "${var.number_of_gfs_nodes_no_floating_ip}"
instance_id = element(openstack_compute_instance_v2.glusterfs_node_no_floating_ip.*.id, count.index) instance_id = "${element(openstack_compute_instance_v2.glusterfs_node_no_floating_ip.*.id, count.index)}"
volume_id = element(openstack_blockstorage_volume_v2.glusterfs_volume.*.id, count.index) volume_id = "${element(openstack_blockstorage_volume_v2.glusterfs_volume.*.id, count.index)}"
} }

View File

@@ -1,11 +1,7 @@
variable "cluster_name" {} variable "cluster_name" {}
variable "az_list" { variable "az_list" {
type = list(string) type = "list"
}
variable "az_list_node" {
type = list(string)
} }
variable "number_of_k8s_masters" {} variable "number_of_k8s_masters" {}
@@ -26,20 +22,8 @@ variable "number_of_bastions" {}
variable "number_of_gfs_nodes_no_floating_ip" {} variable "number_of_gfs_nodes_no_floating_ip" {}
variable "bastion_root_volume_size_in_gb" {}
variable "etcd_root_volume_size_in_gb" {}
variable "master_root_volume_size_in_gb" {}
variable "node_root_volume_size_in_gb" {}
variable "gfs_root_volume_size_in_gb" {}
variable "gfs_volume_size_in_gb" {} variable "gfs_volume_size_in_gb" {}
variable "master_volume_type" {}
variable "public_key_path" {} variable "public_key_path" {}
variable "image" {} variable "image" {}
@@ -67,43 +51,37 @@ variable "network_id" {
} }
variable "k8s_master_fips" { variable "k8s_master_fips" {
type = list type = "list"
} }
variable "k8s_master_no_etcd_fips" { variable "k8s_master_no_etcd_fips" {
type = list type = "list"
} }
variable "k8s_node_fips" { variable "k8s_node_fips" {
type = list type = "list"
}
variable "k8s_nodes_fips" {
type = map
} }
variable "bastion_fips" { variable "bastion_fips" {
type = list type = "list"
} }
variable "bastion_allowed_remote_ips" { variable "bastion_allowed_remote_ips" {
type = list type = "list"
} }
variable "master_allowed_remote_ips" { variable "master_allowed_remote_ips" {
type = list type = "list"
} }
variable "k8s_allowed_remote_ips" { variable "k8s_allowed_remote_ips" {
type = list type = "list"
} }
variable "k8s_allowed_egress_ips" { variable "k8s_allowed_egress_ips" {
type = list type = "list"
} }
variable "k8s_nodes" {}
variable "wait_for_floatingip" {} variable "wait_for_floatingip" {}
variable "supplementary_master_groups" { variable "supplementary_master_groups" {
@@ -114,16 +92,6 @@ variable "supplementary_node_groups" {
default = "" default = ""
} }
variable "master_allowed_ports" {
type = list
}
variable "worker_allowed_ports" { variable "worker_allowed_ports" {
type = list type = "list"
}
variable "use_access_ip" {}
variable "use_server_groups" {
type = bool
} }

View File

@@ -1,36 +1,29 @@
resource "null_resource" "dummy_dependency" { resource "null_resource" "dummy_dependency" {
triggers = { triggers = {
dependency_id = var.router_id dependency_id = "${var.router_id}"
} }
} }
resource "openstack_networking_floatingip_v2" "k8s_master" { resource "openstack_networking_floatingip_v2" "k8s_master" {
count = var.number_of_k8s_masters count = "${var.number_of_k8s_masters}"
pool = var.floatingip_pool pool = "${var.floatingip_pool}"
depends_on = [null_resource.dummy_dependency] depends_on = ["null_resource.dummy_dependency"]
} }
resource "openstack_networking_floatingip_v2" "k8s_master_no_etcd" { resource "openstack_networking_floatingip_v2" "k8s_master_no_etcd" {
count = var.number_of_k8s_masters_no_etcd count = "${var.number_of_k8s_masters_no_etcd}"
pool = var.floatingip_pool pool = "${var.floatingip_pool}"
depends_on = [null_resource.dummy_dependency] depends_on = ["null_resource.dummy_dependency"]
} }
resource "openstack_networking_floatingip_v2" "k8s_node" { resource "openstack_networking_floatingip_v2" "k8s_node" {
count = var.number_of_k8s_nodes count = "${var.number_of_k8s_nodes}"
pool = var.floatingip_pool pool = "${var.floatingip_pool}"
depends_on = [null_resource.dummy_dependency] depends_on = ["null_resource.dummy_dependency"]
} }
resource "openstack_networking_floatingip_v2" "bastion" { resource "openstack_networking_floatingip_v2" "bastion" {
count = var.number_of_bastions count = "${var.number_of_bastions}"
pool = var.floatingip_pool pool = "${var.floatingip_pool}"
depends_on = [null_resource.dummy_dependency] depends_on = ["null_resource.dummy_dependency"]
} }
resource "openstack_networking_floatingip_v2" "k8s_nodes" {
for_each = var.number_of_k8s_nodes == 0 ? { for key, value in var.k8s_nodes : key => value if value.floating_ip } : {}
pool = var.floatingip_pool
depends_on = [null_resource.dummy_dependency]
}

View File

@@ -1,19 +1,15 @@
output "k8s_master_fips" { output "k8s_master_fips" {
value = openstack_networking_floatingip_v2.k8s_master[*].address value = "${openstack_networking_floatingip_v2.k8s_master[*].address}"
} }
output "k8s_master_no_etcd_fips" { output "k8s_master_no_etcd_fips" {
value = openstack_networking_floatingip_v2.k8s_master_no_etcd[*].address value = "${openstack_networking_floatingip_v2.k8s_master_no_etcd[*].address}"
} }
output "k8s_node_fips" { output "k8s_node_fips" {
value = openstack_networking_floatingip_v2.k8s_node[*].address value = "${openstack_networking_floatingip_v2.k8s_node[*].address}"
}
output "k8s_nodes_fips" {
value = openstack_networking_floatingip_v2.k8s_nodes
} }
output "bastion_fips" { output "bastion_fips" {
value = openstack_networking_floatingip_v2.bastion[*].address value = "${openstack_networking_floatingip_v2.bastion[*].address}"
} }

View File

@@ -15,5 +15,3 @@ variable "network_name" {}
variable "router_id" { variable "router_id" {
default = "" default = ""
} }
variable "k8s_nodes" {}

View File

@@ -1,33 +1,27 @@
resource "openstack_networking_router_v2" "k8s" { resource "openstack_networking_router_v2" "k8s" {
name = "${var.cluster_name}-router" name = "${var.cluster_name}-router"
count = var.use_neutron == 1 && var.router_id == null ? 1 : 0 count = "${var.use_neutron}"
admin_state_up = "true" admin_state_up = "true"
external_network_id = var.external_net external_network_id = "${var.external_net}"
}
data "openstack_networking_router_v2" "k8s" {
router_id = var.router_id
count = var.use_neutron == 1 && var.router_id != null ? 1 : 0
} }
resource "openstack_networking_network_v2" "k8s" { resource "openstack_networking_network_v2" "k8s" {
name = var.network_name name = "${var.network_name}"
count = var.use_neutron count = "${var.use_neutron}"
dns_domain = var.network_dns_domain != null ? var.network_dns_domain : null
admin_state_up = "true" admin_state_up = "true"
} }
resource "openstack_networking_subnet_v2" "k8s" { resource "openstack_networking_subnet_v2" "k8s" {
name = "${var.cluster_name}-internal-network" name = "${var.cluster_name}-internal-network"
count = var.use_neutron count = "${var.use_neutron}"
network_id = openstack_networking_network_v2.k8s[count.index].id network_id = "${openstack_networking_network_v2.k8s[count.index].id}"
cidr = var.subnet_cidr cidr = "${var.subnet_cidr}"
ip_version = 4 ip_version = 4
dns_nameservers = var.dns_nameservers dns_nameservers = "${var.dns_nameservers}"
} }
resource "openstack_networking_router_interface_v2" "k8s" { resource "openstack_networking_router_interface_v2" "k8s" {
count = var.use_neutron count = "${var.use_neutron}"
router_id = "%{if openstack_networking_router_v2.k8s != []}${openstack_networking_router_v2.k8s[count.index].id}%{else}${var.router_id}%{endif}" router_id = "${openstack_networking_router_v2.k8s[count.index].id}"
subnet_id = openstack_networking_subnet_v2.k8s[count.index].id subnet_id = "${openstack_networking_subnet_v2.k8s[count.index].id}"
} }

View File

@@ -1,11 +1,11 @@
output "router_id" { output "router_id" {
value = "%{if var.use_neutron == 1} ${var.router_id == null ? element(concat(openstack_networking_router_v2.k8s.*.id, [""]), 0) : var.router_id} %{else} %{endif}" value = "${element(concat(openstack_networking_router_v2.k8s.*.id, list("")), 0)}"
} }
output "router_internal_port_id" { output "router_internal_port_id" {
value = element(concat(openstack_networking_router_interface_v2.k8s.*.id, [""]), 0) value = "${element(concat(openstack_networking_router_interface_v2.k8s.*.id, list("")), 0)}"
} }
output "subnet_id" { output "subnet_id" {
value = element(concat(openstack_networking_subnet_v2.k8s.*.id, [""]), 0) value = "${element(concat(openstack_networking_subnet_v2.k8s.*.id, list("")), 0)}"
} }

View File

@@ -2,16 +2,12 @@ variable "external_net" {}
variable "network_name" {} variable "network_name" {}
variable "network_dns_domain" {}
variable "cluster_name" {} variable "cluster_name" {}
variable "dns_nameservers" { variable "dns_nameservers" {
type = list type = "list"
} }
variable "subnet_cidr" {} variable "subnet_cidr" {}
variable "use_neutron" {} variable "use_neutron" {}
variable "router_id" {}

View File

@@ -1,9 +1,6 @@
# your Kubernetes cluster name here # your Kubernetes cluster name here
cluster_name = "i-didnt-read-the-docs" cluster_name = "i-didnt-read-the-docs"
# list of availability zones available in your OpenStack cluster
#az_list = ["nova"]
# SSH key to use for access to nodes # SSH key to use for access to nodes
public_key_path = "~/.ssh/id_rsa.pub" public_key_path = "~/.ssh/id_rsa.pub"

View File

@@ -3,14 +3,8 @@ variable "cluster_name" {
} }
variable "az_list" { variable "az_list" {
description = "List of Availability Zones to use for masters in your OpenStack cluster" description = "List of Availability Zones available in your OpenStack cluster"
type = list(string) type = "list"
default = ["nova"]
}
variable "az_list_node" {
description = "List of Availability Zones to use for nodes in your OpenStack cluster"
type = list(string)
default = ["nova"] default = ["nova"]
} }
@@ -50,34 +44,10 @@ variable "number_of_gfs_nodes_no_floating_ip" {
default = 0 default = 0
} }
variable "bastion_root_volume_size_in_gb" {
default = 0
}
variable "etcd_root_volume_size_in_gb" {
default = 0
}
variable "master_root_volume_size_in_gb" {
default = 0
}
variable "node_root_volume_size_in_gb" {
default = 0
}
variable "gfs_root_volume_size_in_gb" {
default = 0
}
variable "gfs_volume_size_in_gb" { variable "gfs_volume_size_in_gb" {
default = 75 default = 75
} }
variable "master_volume_type" {
default = "Default"
}
variable "public_key_path" { variable "public_key_path" {
description = "The path of the ssh pub key" description = "The path of the ssh pub key"
default = "~/.ssh/id_rsa.pub" default = "~/.ssh/id_rsa.pub"
@@ -85,12 +55,12 @@ variable "public_key_path" {
variable "image" { variable "image" {
description = "the image to use" description = "the image to use"
default = "" default = "ubuntu-14.04"
} }
variable "image_gfs" { variable "image_gfs" {
description = "Glance image to use for GlusterFS" description = "Glance image to use for GlusterFS"
default = "" default = "ubuntu-16.04"
} }
variable "ssh_user" { variable "ssh_user" {
@@ -133,12 +103,6 @@ variable "network_name" {
default = "internal" default = "internal"
} }
variable "network_dns_domain" {
description = "dns_domain for the internal network"
type = string
default = null
}
variable "use_neutron" { variable "use_neutron" {
description = "Use neutron" description = "Use neutron"
default = 1 default = 1
@@ -146,13 +110,13 @@ variable "use_neutron" {
variable "subnet_cidr" { variable "subnet_cidr" {
description = "Subnet CIDR block." description = "Subnet CIDR block."
type = string type = "string"
default = "10.0.0.0/24" default = "10.0.0.0/24"
} }
variable "dns_nameservers" { variable "dns_nameservers" {
description = "An array of DNS name server names used by hosts in this subnet." description = "An array of DNS name server names used by hosts in this subnet."
type = list type = "list"
default = [] default = []
} }
@@ -182,36 +146,30 @@ variable "supplementary_node_groups" {
variable "bastion_allowed_remote_ips" { variable "bastion_allowed_remote_ips" {
description = "An array of CIDRs allowed to SSH to hosts" description = "An array of CIDRs allowed to SSH to hosts"
type = list(string) type = "list"
default = ["0.0.0.0/0"] default = ["0.0.0.0/0"]
} }
variable "master_allowed_remote_ips" { variable "master_allowed_remote_ips" {
description = "An array of CIDRs allowed to access API of masters" description = "An array of CIDRs allowed to access API of masters"
type = list(string) type = "list"
default = ["0.0.0.0/0"] default = ["0.0.0.0/0"]
} }
variable "k8s_allowed_remote_ips" { variable "k8s_allowed_remote_ips" {
description = "An array of CIDRs allowed to SSH to hosts" description = "An array of CIDRs allowed to SSH to hosts"
type = list(string) type = "list"
default = [] default = []
} }
variable "k8s_allowed_egress_ips" { variable "k8s_allowed_egress_ips" {
description = "An array of CIDRs allowed for egress traffic" description = "An array of CIDRs allowed for egress traffic"
type = list(string) type = "list"
default = ["0.0.0.0/0"] default = ["0.0.0.0/0"]
} }
variable "master_allowed_ports" {
type = list
default = []
}
variable "worker_allowed_ports" { variable "worker_allowed_ports" {
type = list type = "list"
default = [ default = [
{ {
@@ -222,21 +180,3 @@ variable "worker_allowed_ports" {
}, },
] ]
} }
variable "use_access_ip" {
default = 1
}
variable "use_server_groups" {
default = false
}
variable "router_id" {
description = "uuid of an externally defined router to use"
default = null
}
variable "k8s_nodes" {
default = {}
}

View File

@@ -38,7 +38,7 @@ now six total etcd replicas.
## SSH Key Setup ## SSH Key Setup
An SSH keypair is required so Ansible can access the newly provisioned nodes (bare metal Packet hosts). By default, the public SSH key defined in cluster.tfvars will be installed in authorized_key on the newly provisioned nodes (~/.ssh/id_rsa.pub). Terraform will upload this public key and then it will be distributed out to all the nodes. If you have already set this public key in Packet (i.e. via the portal), then set the public keyfile name in cluster.tfvars to blank to prevent the duplicate key from being uploaded which will cause an error. An SSH keypair is required so Ansible can access the newly provisioned nodes (bare metal Packet hosts). By default, the public SSH key defined in cluster.tf will be installed in authorized_key on the newly provisioned nodes (~/.ssh/id_rsa.pub). Terraform will upload this public key and then it will be distributed out to all the nodes. If you have already set this public key in Packet (i.e. via the portal), then set the public keyfile name in cluster.tf to blank to prevent the duplicate key from being uploaded which will cause an error.
If you don't already have a keypair generated (~/.ssh/id_rsa and ~/.ssh/id_rsa.pub), then a new keypair can be generated with the command: If you don't already have a keypair generated (~/.ssh/id_rsa and ~/.ssh/id_rsa.pub), then a new keypair can be generated with the command:
@@ -72,7 +72,7 @@ If someone gets this key, they can startup/shutdown hosts in your project!
For more information on how to generate an API key or find your project ID, please see: For more information on how to generate an API key or find your project ID, please see:
https://support.packet.com/kb/articles/api-integrations https://support.packet.com/kb/articles/api-integrations
The Packet Project ID associated with the key will be set later in cluster.tfvars. The Packet Project ID associated with the key will be set later in cluster.tf.
For more information about the API, please see: For more information about the API, please see:
https://www.packet.com/developers/api/ https://www.packet.com/developers/api/
@@ -88,7 +88,7 @@ Note that to deploy several clusters within the same project you need to use [te
The construction of the cluster is driven by values found in The construction of the cluster is driven by values found in
[variables.tf](variables.tf). [variables.tf](variables.tf).
For your cluster, edit `inventory/$CLUSTER/cluster.tfvars`. For your cluster, edit `inventory/$CLUSTER/cluster.tf`.
The `cluster_name` is used to set a tag on each server deployed as part of this cluster. The `cluster_name` is used to set a tag on each server deployed as part of this cluster.
This helps when identifying which hosts are associated with each cluster. This helps when identifying which hosts are associated with each cluster.
@@ -138,7 +138,7 @@ This should finish fairly quickly telling you Terraform has successfully initial
You can apply the Terraform configuration to your cluster with the following command You can apply the Terraform configuration to your cluster with the following command
issued from your cluster's inventory directory (`inventory/$CLUSTER`): issued from your cluster's inventory directory (`inventory/$CLUSTER`):
```ShellSession ```ShellSession
$ terraform apply -var-file=cluster.tfvars ../../contrib/terraform/packet $ terraform apply -var-file=cluster.tf ../../contrib/terraform/packet
$ export ANSIBLE_HOST_KEY_CHECKING=False $ export ANSIBLE_HOST_KEY_CHECKING=False
$ ansible-playbook -i hosts ../../cluster.yml $ ansible-playbook -i hosts ../../cluster.yml
``` ```
@@ -147,7 +147,7 @@ $ ansible-playbook -i hosts ../../cluster.yml
You can destroy your new cluster with the following command issued from the cluster's inventory directory: You can destroy your new cluster with the following command issued from the cluster's inventory directory:
```ShellSession ```ShellSession
$ terraform destroy -var-file=cluster.tfvars ../../contrib/terraform/packet $ terraform destroy -var-file=cluster.tf ../../contrib/terraform/packet
``` ```
If you've started the Ansible run, it may also be a good idea to do some manual cleanup: If you've started the Ansible run, it may also be a good idea to do some manual cleanup:
@@ -176,7 +176,7 @@ If you have deployed and destroyed a previous iteration of your cluster, you wil
#### Test access #### Test access
Make sure you can connect to the hosts. Note that Flatcar Container Linux by Kinvolk will have a state `FAILED` due to Python not being present. This is okay, because Python will be installed during bootstrapping, so long as the hosts are not `UNREACHABLE`. Make sure you can connect to the hosts. Note that Container Linux by CoreOS will have a state `FAILED` due to Python not being present. This is okay, because Python will be installed during bootstrapping, so long as the hosts are not `UNREACHABLE`.
``` ```
$ ansible -i inventory/$CLUSTER/hosts -m ping all $ ansible -i inventory/$CLUSTER/hosts -m ping all

View File

@@ -4,60 +4,59 @@ provider "packet" {
} }
resource "packet_ssh_key" "k8s" { resource "packet_ssh_key" "k8s" {
count = var.public_key_path != "" ? 1 : 0 count = "${var.public_key_path != "" ? 1 : 0}"
name = "kubernetes-${var.cluster_name}" name = "kubernetes-${var.cluster_name}"
public_key = chomp(file(var.public_key_path)) public_key = "${chomp(file(var.public_key_path))}"
} }
resource "packet_device" "k8s_master" { resource "packet_device" "k8s_master" {
depends_on = [packet_ssh_key.k8s] depends_on = ["packet_ssh_key.k8s"]
count = var.number_of_k8s_masters count = "${var.number_of_k8s_masters}"
hostname = "${var.cluster_name}-k8s-master-${count.index + 1}" hostname = "${var.cluster_name}-k8s-master-${count.index+1}"
plan = var.plan_k8s_masters plan = "${var.plan_k8s_masters}"
facilities = [var.facility] facilities = ["${var.facility}"]
operating_system = var.operating_system operating_system = "${var.operating_system}"
billing_cycle = var.billing_cycle billing_cycle = "${var.billing_cycle}"
project_id = var.packet_project_id project_id = "${var.packet_project_id}"
tags = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-master", "etcd", "kube-node"] tags = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-master", "etcd", "kube-node"]
} }
resource "packet_device" "k8s_master_no_etcd" { resource "packet_device" "k8s_master_no_etcd" {
depends_on = [packet_ssh_key.k8s] depends_on = ["packet_ssh_key.k8s"]
count = var.number_of_k8s_masters_no_etcd count = "${var.number_of_k8s_masters_no_etcd}"
hostname = "${var.cluster_name}-k8s-master-${count.index + 1}" hostname = "${var.cluster_name}-k8s-master-${count.index+1}"
plan = var.plan_k8s_masters_no_etcd plan = "${var.plan_k8s_masters_no_etcd}"
facilities = [var.facility] facilities = ["${var.facility}"]
operating_system = var.operating_system operating_system = "${var.operating_system}"
billing_cycle = var.billing_cycle billing_cycle = "${var.billing_cycle}"
project_id = var.packet_project_id project_id = "${var.packet_project_id}"
tags = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-master"] tags = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-master"]
} }
resource "packet_device" "k8s_etcd" { resource "packet_device" "k8s_etcd" {
depends_on = [packet_ssh_key.k8s] depends_on = ["packet_ssh_key.k8s"]
count = var.number_of_etcd count = "${var.number_of_etcd}"
hostname = "${var.cluster_name}-etcd-${count.index + 1}" hostname = "${var.cluster_name}-etcd-${count.index+1}"
plan = var.plan_etcd plan = "${var.plan_etcd}"
facilities = [var.facility] facilities = ["${var.facility}"]
operating_system = var.operating_system operating_system = "${var.operating_system}"
billing_cycle = var.billing_cycle billing_cycle = "${var.billing_cycle}"
project_id = var.packet_project_id project_id = "${var.packet_project_id}"
tags = ["cluster-${var.cluster_name}", "etcd"] tags = ["cluster-${var.cluster_name}", "etcd"]
} }
resource "packet_device" "k8s_node" { resource "packet_device" "k8s_node" {
depends_on = [packet_ssh_key.k8s] depends_on = ["packet_ssh_key.k8s"]
count = var.number_of_k8s_nodes count = "${var.number_of_k8s_nodes}"
hostname = "${var.cluster_name}-k8s-node-${count.index + 1}" hostname = "${var.cluster_name}-k8s-node-${count.index+1}"
plan = var.plan_k8s_nodes plan = "${var.plan_k8s_nodes}"
facilities = [var.facility] facilities = ["${var.facility}"]
operating_system = var.operating_system operating_system = "${var.operating_system}"
billing_cycle = var.billing_cycle billing_cycle = "${var.billing_cycle}"
project_id = var.packet_project_id project_id = "${var.packet_project_id}"
tags = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-node"] tags = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-node"]
} }

View File

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

View File

@@ -54,4 +54,3 @@ variable "number_of_etcd" {
variable "number_of_k8s_nodes" { variable "number_of_k8s_nodes" {
default = 0 default = 0
} }

View File

@@ -1,4 +0,0 @@
terraform {
required_version = ">= 0.12"
}

View File

@@ -73,7 +73,7 @@ def iterresources(filenames):
# In version 4 the structure changes so we need to iterate # In version 4 the structure changes so we need to iterate
# each instance inside the resource branch. # each instance inside the resource branch.
for resource in state['resources']: for resource in state['resources']:
name = resource['provider'].split('.')[-1] name = resource['module'].split('.')[-1]
for instance in resource['instances']: for instance in resource['instances']:
key = "{}.{}".format(resource['type'], resource['name']) key = "{}.{}".format(resource['type'], resource['name'])
if 'index_key' in instance: if 'index_key' in instance:
@@ -182,9 +182,6 @@ def parse_list(source, prefix, sep='.'):
def parse_bool(string_form): def parse_bool(string_form):
if type(string_form) is bool:
return string_form
token = string_form.lower()[0] token = string_form.lower()[0]
if token == 't': if token == 't':
@@ -213,7 +210,7 @@ def packet_device(resource, tfvars=None):
'state': raw_attrs['state'], 'state': raw_attrs['state'],
# ansible # ansible
'ansible_ssh_host': raw_attrs['network.0.address'], 'ansible_ssh_host': raw_attrs['network.0.address'],
'ansible_ssh_user': 'root', # Use root by default in packet 'ansible_ssh_user': 'root', # it's always "root" on Packet
# generic # generic
'ipv4_address': raw_attrs['network.0.address'], 'ipv4_address': raw_attrs['network.0.address'],
'public_ipv4': raw_attrs['network.0.address'], 'public_ipv4': raw_attrs['network.0.address'],
@@ -223,10 +220,6 @@ def packet_device(resource, tfvars=None):
'provider': 'packet', 'provider': 'packet',
} }
if raw_attrs['operating_system'] == 'flatcar_stable':
# For Flatcar set the ssh_user to core
attrs.update({'ansible_ssh_user': 'core'})
# add groups based on attrs # add groups based on attrs
groups.append('packet_operating_system=' + attrs['operating_system']) groups.append('packet_operating_system=' + attrs['operating_system'])
groups.append('packet_locked=%s' % attrs['locked']) groups.append('packet_locked=%s' % attrs['locked'])
@@ -319,7 +312,9 @@ def openstack_host(resource, module_name):
# attrs specific to Mantl # attrs specific to Mantl
attrs.update({ attrs.update({
'role': attrs['metadata'].get('role', 'none') 'consul_dc': _clean_dc(attrs['metadata'].get('dc', module_name)),
'role': attrs['metadata'].get('role', 'none'),
'ansible_python_interpreter': attrs['metadata'].get('python_bin','python')
}) })
# add groups based on attrs # add groups based on attrs
@@ -329,6 +324,10 @@ def openstack_host(resource, module_name):
for item in list(attrs['metadata'].items())) for item in list(attrs['metadata'].items()))
groups.append('os_region=' + attrs['region']) groups.append('os_region=' + attrs['region'])
# groups specific to Mantl
groups.append('role=' + attrs['metadata'].get('role', 'none'))
groups.append('dc=' + attrs['consul_dc'])
# groups specific to kubespray # groups specific to kubespray
for group in attrs['metadata'].get('kubespray_groups', "").split(","): for group in attrs['metadata'].get('kubespray_groups', "").split(","):
groups.append(group) groups.append(group)
@@ -340,20 +339,14 @@ def iter_host_ips(hosts, ips):
'''Update hosts that have an entry in the floating IP list''' '''Update hosts that have an entry in the floating IP list'''
for host in hosts: for host in hosts:
host_id = host[1]['id'] host_id = host[1]['id']
if host_id in ips: if host_id in ips:
ip = ips[host_id] ip = ips[host_id]
host[1].update({ host[1].update({
'access_ip_v4': ip, 'access_ip_v4': ip,
'access_ip': ip, 'access_ip': ip,
'public_ipv4': ip, 'public_ipv4': ip,
'ansible_ssh_host': ip, 'ansible_ssh_host': ip,
}) })
if 'use_access_ip' in host[1]['metadata'] and host[1]['metadata']['use_access_ip'] == "0":
host[1].pop('access_ip')
yield host yield host

View File

@@ -13,7 +13,7 @@
/usr/local/share/ca-certificates/vault-ca.crt /usr/local/share/ca-certificates/vault-ca.crt
{%- elif ansible_os_family == "RedHat" -%} {%- elif ansible_os_family == "RedHat" -%}
/etc/pki/ca-trust/source/anchors/vault-ca.crt /etc/pki/ca-trust/source/anchors/vault-ca.crt
{%- elif ansible_os_family in ["Flatcar Container Linux by Kinvolk"] -%} {%- elif ansible_os_family in ["CoreOS", "Container Linux by CoreOS"] -%}
/etc/ssl/certs/vault-ca.pem /etc/ssl/certs/vault-ca.pem
{%- endif %} {%- endif %}
@@ -23,9 +23,9 @@
dest: "{{ ca_cert_path }}" dest: "{{ ca_cert_path }}"
register: vault_ca_cert register: vault_ca_cert
- name: bootstrap/ca_trust | update ca-certificates (Debian/Ubuntu/Flatcar) - name: bootstrap/ca_trust | update ca-certificates (Debian/Ubuntu/CoreOS)
command: update-ca-certificates command: update-ca-certificates
when: vault_ca_cert.changed and ansible_os_family in ["Debian", "Flatcar Container Linux by Kinvolk"] when: vault_ca_cert.changed and ansible_os_family in ["Debian", "CoreOS", "Container Linux by CoreOS"]
- name: bootstrap/ca_trust | update ca-certificates (RedHat) - name: bootstrap/ca_trust | update ca-certificates (RedHat)
command: update-ca-trust extract command: update-ca-trust extract

View File

@@ -6,11 +6,11 @@
- name: bootstrap/start_vault_temp | Start single node Vault with file backend - name: bootstrap/start_vault_temp | Start single node Vault with file backend
command: > command: >
docker run -d --cap-add=IPC_LOCK --name {{ vault_temp_container_name }} docker run -d --cap-add=IPC_LOCK --name {{ vault_temp_container_name }}
-p {{ vault_port }}:{{ vault_port }} -p {{ vault_port }}:{{ vault_port }}
-e 'VAULT_LOCAL_CONFIG={{ vault_temp_config|to_json }}' -e 'VAULT_LOCAL_CONFIG={{ vault_temp_config|to_json }}'
-v /etc/vault:/etc/vault -v /etc/vault:/etc/vault
{{ vault_image_repo }}:{{ vault_version }} server {{ vault_image_repo }}:{{ vault_version }} server
- name: bootstrap/start_vault_temp | Start again single node Vault with file backend - name: bootstrap/start_vault_temp | Start again single node Vault with file backend
command: docker start {{ vault_temp_container_name }} command: docker start {{ vault_temp_container_name }}

View File

@@ -21,9 +21,9 @@
- name: bootstrap/sync_secrets | Print out warning message if secrets are not available and vault is initialized - name: bootstrap/sync_secrets | Print out warning message if secrets are not available and vault is initialized
pause: pause:
prompt: > prompt: >
Vault orchestration may not be able to proceed. The Vault cluster is initialized, but Vault orchestration may not be able to proceed. The Vault cluster is initialzed, but
'root_token' or 'unseal_keys' were not found in {{ vault_secrets_dir }}. These are 'root_token' or 'unseal_keys' were not found in {{ vault_secrets_dir }}. These are
needed for many vault orchestration steps. needed for many vault orchestration steps.
when: vault_cluster_is_initialized and not vault_secrets_available when: vault_cluster_is_initialized and not vault_secrets_available
- name: bootstrap/sync_secrets | Cat root_token from a vault host - name: bootstrap/sync_secrets | Cat root_token from a vault host

View File

@@ -25,6 +25,6 @@
- name: check_etcd | Fail if etcd is not available and needed - name: check_etcd | Fail if etcd is not available and needed
fail: fail:
msg: > msg: >
Unable to start Vault cluster! Etcd is not available at Unable to start Vault cluster! Etcd is not available at
{{ vault_etcd_url.split(',') | first }} however it is needed by Vault as a backend. {{ vault_etcd_url.split(',') | first }} however it is needed by Vault as a backend.
when: vault_etcd_needed|d() and not vault_etcd_available when: vault_etcd_needed|d() and not vault_etcd_available

View File

@@ -36,7 +36,6 @@
{{ etcd_access_addresses.split(',') | first }}/v3alpha/kv/range {{ etcd_access_addresses.split(',') | first }}/v3alpha/kv/range
register: vault_etcd_exists register: vault_etcd_exists
retries: 4 retries: 4
until: vault_etcd_exists.status == 200
delay: "{{ retry_stagger | random + 3 }}" delay: "{{ retry_stagger | random + 3 }}"
run_once: true run_once: true
when: not vault_is_running and vault_etcd_available when: not vault_is_running and vault_etcd_available
@@ -46,7 +45,7 @@
set_fact: set_fact:
vault_cluster_is_initialized: >- vault_cluster_is_initialized: >-
{{ vault_is_initialized or {{ vault_is_initialized or
hostvars[item]['vault_is_initialized'] or hostvars[item]['vault_is_initialized'] or
('value' in vault_etcd_exists.stdout|default('')) }} ('value' in vault_etcd_exists.stdout|default('')) }}
with_items: "{{ groups.vault }}" with_items: "{{ groups.vault }}"
run_once: true run_once: true

View File

@@ -6,9 +6,9 @@
ca_cert: "{{ vault_cert_dir }}/ca.pem" ca_cert: "{{ vault_cert_dir }}/ca.pem"
name: "{{ create_role_name }}" name: "{{ create_role_name }}"
rules: >- rules: >-
{%- if create_role_policy_rules|d("default") == "default" -%} {%- if create_role_policy_rules|d("default") == "default" -%}
{{ {{
{ 'path': { { 'path': {
create_role_mount_path + '/issue/' + create_role_name: {'policy': 'write'}, create_role_mount_path + '/issue/' + create_role_name: {'policy': 'write'},
create_role_mount_path + '/roles/' + create_role_name: {'policy': 'read'} create_role_mount_path + '/roles/' + create_role_name: {'policy': 'read'}
}} | to_json + '\n' }} | to_json + '\n'
@@ -24,13 +24,13 @@
ca_cert: "{{ vault_cert_dir }}/ca.pem" ca_cert: "{{ vault_cert_dir }}/ca.pem"
secret: "{{ create_role_mount_path }}/roles/{{ create_role_name }}" secret: "{{ create_role_mount_path }}/roles/{{ create_role_name }}"
data: | data: |
{%- if create_role_options|d("default") == "default" -%} {%- if create_role_options|d("default") == "default" -%}
{ {
allow_any_name: true allow_any_name: true
} }
{%- else -%} {%- else -%}
{{ create_role_options | to_json }} {{ create_role_options | to_json }}
{%- endif -%} {%- endif -%}
## Userpass based auth method ## Userpass based auth method

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