mirror of
https://github.com/kubernetes-sigs/kubespray.git
synced 2025-12-14 22:04:43 +03:00
Compare commits
362 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29cfe2b8eb | ||
|
|
b0eecc0bce | ||
|
|
5cba8b1614 | ||
|
|
860bafa62d | ||
|
|
fa35cc02a7 | ||
|
|
b4d067e2ed | ||
|
|
7d3f54e940 | ||
|
|
51d9e2f9b1 | ||
|
|
941aaf93fd | ||
|
|
68b3ee8ac1 | ||
|
|
55da185dfe | ||
|
|
f33aafefa2 | ||
|
|
8f2ad2e2f7 | ||
|
|
980ac28d60 | ||
|
|
fde234fda7 | ||
|
|
de26988e05 | ||
|
|
173314d9f1 | ||
|
|
e181530333 | ||
|
|
366fb084ef | ||
|
|
34e883e6e2 | ||
|
|
22236bfab7 | ||
|
|
24d28de979 | ||
|
|
86365d61e3 | ||
|
|
370a0635fa | ||
|
|
db2ca014cb | ||
|
|
f0f8379e1b | ||
|
|
815eebf1d7 | ||
|
|
95cf18ff00 | ||
|
|
696fcaf391 | ||
|
|
6ff5ccc938 | ||
|
|
f8a18fcaca | ||
|
|
961c1be53e | ||
|
|
eda1dcb7f6 | ||
|
|
5e0140d62c | ||
|
|
717fe3cf3a | ||
|
|
32d80ca438 | ||
|
|
2a9aead50e | ||
|
|
9fda84b1c9 | ||
|
|
42702dc1a3 | ||
|
|
40e35b3fa6 | ||
|
|
b15d41a96a | ||
|
|
7da2083986 | ||
|
|
37df9a10ff | ||
|
|
0f845fb350 | ||
|
|
23b8998701 | ||
|
|
401d441c10 | ||
|
|
f7aea8ed89 | ||
|
|
a9b67d586b | ||
|
|
b1fbead531 | ||
|
|
b06826e88a | ||
|
|
57fef8f75e | ||
|
|
f599a4a859 | ||
|
|
e44b0727d5 | ||
|
|
18cee65c4b | ||
|
|
f779cb93d6 | ||
|
|
aec5080a47 | ||
|
|
80418a44d5 | ||
|
|
257c20f39e | ||
|
|
050de3ab7b | ||
|
|
f1498d4b53 | ||
|
|
18d19d9ed4 | ||
|
|
61d7d1459a | ||
|
|
6924c6e5a3 | ||
|
|
85c851f519 | ||
|
|
5cd7d1a3c9 | ||
|
|
8b67159239 | ||
|
|
4f70da2731 | ||
|
|
db5040e6ea | ||
|
|
97764921ed | ||
|
|
a6853cb79d | ||
|
|
8c15db53b2 | ||
|
|
0200138a5d | ||
|
|
14af98ebdc | ||
|
|
8a5434419b | ||
|
|
8a406be48a | ||
|
|
feac802456 | ||
|
|
076f254a67 | ||
|
|
bc3a8a0039 | ||
|
|
45d151a69d | ||
|
|
bd014c409b | ||
|
|
08421aad3d | ||
|
|
1c25ed669c | ||
|
|
a005d19f6f | ||
|
|
471589f1f4 | ||
|
|
b0ee1f6cc6 | ||
|
|
79128dcd6b | ||
|
|
dd7e1469e9 | ||
|
|
186ec13579 | ||
|
|
2c4e6b65d7 | ||
|
|
108a6297e9 | ||
|
|
94d4ce5a6f | ||
|
|
81da231b1e | ||
|
|
1a87dcd9b9 | ||
|
|
a1fff30bd9 | ||
|
|
81d57fe658 | ||
|
|
3118437e10 | ||
|
|
65e461a7c0 | ||
|
|
c672681ce5 | ||
|
|
d332a254ee | ||
|
|
f3c072f6b6 | ||
|
|
3debb8aab5 | ||
|
|
aada6e7e40 | ||
|
|
ac60786c6f | ||
|
|
db33dc6938 | ||
|
|
9dfb25cafd | ||
|
|
df8d2285b6 | ||
|
|
af6456d1ea | ||
|
|
6f57f7dd2f | ||
|
|
fd2ff675c3 | ||
|
|
bec23c8a41 | ||
|
|
faaff8bd72 | ||
|
|
8031c6c1e7 | ||
|
|
9d8fc8caad | ||
|
|
d1b1add176 | ||
|
|
a51b729817 | ||
|
|
19bc79b1a6 | ||
|
|
d2fa3c7796 | ||
|
|
03cac2109c | ||
|
|
932935ecc7 | ||
|
|
e01118d36d | ||
|
|
dea9304968 | ||
|
|
2864e13ff9 | ||
|
|
a8c5a0afdc | ||
|
|
0ba336b04e | ||
|
|
89f1223f64 | ||
|
|
8bc0710073 | ||
|
|
fb591bf232 | ||
|
|
a43e0d3f95 | ||
|
|
f16cc1f08d | ||
|
|
8712bddcbe | ||
|
|
99dbc6d780 | ||
|
|
75e4cc2fd9 | ||
|
|
81cb302399 | ||
|
|
3bcdf46937 | ||
|
|
1cf6a99df4 | ||
|
|
a5d165dc85 | ||
|
|
f18e77f1db | ||
|
|
2fc02ed456 | ||
|
|
9db61c45ed | ||
|
|
8cb54cd74d | ||
|
|
a3f1ce25f8 | ||
|
|
3c7f682e90 | ||
|
|
8984096f35 | ||
|
|
1ce7831f6d | ||
|
|
46f6c09d21 | ||
|
|
6fe2248314 | ||
|
|
cb4f797d32 | ||
|
|
eb40ac163f | ||
|
|
27ec548b88 | ||
|
|
637f09f140 | ||
|
|
9b0f57a0a6 | ||
|
|
5f02068f90 | ||
|
|
7f74906d33 | ||
|
|
56523812d3 | ||
|
|
602b2d198a | ||
|
|
4d95bb1421 | ||
|
|
184ac6a4e6 | ||
|
|
10e0fe86fb | ||
|
|
7e1645845f | ||
|
|
f255ce3f02 | ||
|
|
07ecef86e3 | ||
|
|
3bc4b4c174 | ||
|
|
da089b5fca | ||
|
|
d4f094cc11 | ||
|
|
494a6512b8 | ||
|
|
3732c3a9b1 | ||
|
|
f6a63d88a7 | ||
|
|
86cc703c75 | ||
|
|
4dba34bd02 | ||
|
|
b0437516c1 | ||
|
|
da015e0249 | ||
|
|
554857da97 | ||
|
|
9bf23fa43b | ||
|
|
42287066d3 | ||
|
|
a1ff1de975 | ||
|
|
1bfbc5bbc4 | ||
|
|
c5b4d3ceaa | ||
|
|
8fc9c5d025 | ||
|
|
42bba66c02 | ||
|
|
53bc80bb59 | ||
|
|
771ce96e6d | ||
|
|
fc456ff0cd | ||
|
|
b4f70db878 | ||
|
|
5707f79b33 | ||
|
|
0a2f4edfc6 | ||
|
|
56fa46716e | ||
|
|
b74abe56fd | ||
|
|
62aecd1e4a | ||
|
|
973afef96e | ||
|
|
a235605d2c | ||
|
|
023108a733 | ||
|
|
75d1be8272 | ||
|
|
a44235d11b | ||
|
|
7abf6a6958 | ||
|
|
0d0b1fdf82 | ||
|
|
b710c72f04 | ||
|
|
678c316d01 | ||
|
|
bc6de32faf | ||
|
|
7cf8ad4dc7 | ||
|
|
02ec72fa40 | ||
|
|
d22634a597 | ||
|
|
4132cee687 | ||
|
|
f3df0d5f4a | ||
|
|
1d285e654d | ||
|
|
dc6ad64ec7 | ||
|
|
92bfcf0467 | ||
|
|
54b1fe83f3 | ||
|
|
5337cff179 | ||
|
|
1be788f785 | ||
|
|
8afbf339f7 | ||
|
|
8c935dfb50 | ||
|
|
66c5ed8406 | ||
|
|
4087e97505 | ||
|
|
da50ed0936 | ||
|
|
fbbfff3795 | ||
|
|
fb9103acd3 | ||
|
|
49d921cf91 | ||
|
|
fe29c97ae8 | ||
|
|
2abb6c8689 | ||
|
|
a3ca441998 | ||
|
|
9cf503acb1 | ||
|
|
1cbdd7ed5c | ||
|
|
428e52e0d1 | ||
|
|
70dc222719 | ||
|
|
69f796f0c7 | ||
|
|
5826f0810c | ||
|
|
de9443a694 | ||
|
|
99c5f7e013 | ||
|
|
d9dedc2cd5 | ||
|
|
23ae6027ab | ||
|
|
781b5691c9 | ||
|
|
fd9bbcb157 | ||
|
|
e0410661fa | ||
|
|
8ef754678a | ||
|
|
161a8f55fa | ||
|
|
7481cc31e1 | ||
|
|
b15b6e834f | ||
|
|
76640cf1a1 | ||
|
|
374ea7b81d | ||
|
|
46bef931e9 | ||
|
|
a36e9ae690 | ||
|
|
728155a2a1 | ||
|
|
cdf9a9f4fc | ||
|
|
29307740dd | ||
|
|
a038d62644 | ||
|
|
20c7e31ea3 | ||
|
|
65065e7fdf | ||
|
|
352297cf8d | ||
|
|
a67a50f9c0 | ||
|
|
324bc41097 | ||
|
|
c81b443d93 | ||
|
|
dc16ab92f4 | ||
|
|
53032a6695 | ||
|
|
d90a5f291b | ||
|
|
3b7791501e | ||
|
|
f2b8a3614d | ||
|
|
e89b47c7ee | ||
|
|
2aa66eb12d | ||
|
|
4c8b93e5b9 | ||
|
|
216631bf02 | ||
|
|
c7f3123e28 | ||
|
|
f599c2a691 | ||
|
|
bc7d1f36ea | ||
|
|
80fa294a31 | ||
|
|
465dfd68bc | ||
|
|
73f45fbe94 | ||
|
|
d270678bda | ||
|
|
de028814e5 | ||
|
|
b5406b752d | ||
|
|
6025981ceb | ||
|
|
4348e78b24 | ||
|
|
e2f9adc2ff | ||
|
|
f67a24499b | ||
|
|
5c704552d8 | ||
|
|
d83ea51101 | ||
|
|
fa6027e8f0 | ||
|
|
2849191e67 | ||
|
|
0559eec681 | ||
|
|
a3a7fe7c8e | ||
|
|
9b2d176617 | ||
|
|
7a3547e4d1 | ||
|
|
e6fb686156 | ||
|
|
5e80603bbb | ||
|
|
c8d95a1586 | ||
|
|
27a99e0a3f | ||
|
|
3cc351dff9 | ||
|
|
23c9071c30 | ||
|
|
14141ec137 | ||
|
|
5bec2edaf7 | ||
|
|
f504d0ea99 | ||
|
|
3b7797b1a1 | ||
|
|
aa63eb6196 | ||
|
|
23aa3e4638 | ||
|
|
56ae3bfec2 | ||
|
|
4d5c4a13cb | ||
|
|
69a8f91512 | ||
|
|
fa791cc344 | ||
|
|
456f743470 | ||
|
|
ab6f0012cc | ||
|
|
4afbf51d32 | ||
|
|
d62684b617 | ||
|
|
a8dfcbbfc7 | ||
|
|
bbdc6210f5 | ||
|
|
c7f6ed1495 | ||
|
|
818aa7aeb1 | ||
|
|
045acc724b | ||
|
|
d540560619 | ||
|
|
797bfd85b0 | ||
|
|
07cb8ebef7 | ||
|
|
54416cabfd | ||
|
|
3617ae31f6 | ||
|
|
4f05d801c3 | ||
|
|
956afcb33f | ||
|
|
6347419233 | ||
|
|
0c7a50fe1e | ||
|
|
7423932510 | ||
|
|
b41530ba5d | ||
|
|
29e916508c | ||
|
|
b45f3f0004 | ||
|
|
2a5721b4d4 | ||
|
|
e30a703c8e | ||
|
|
333f1a4a40 | ||
|
|
84b278021a | ||
|
|
1e470b0473 | ||
|
|
0ef3a7914c | ||
|
|
a3fff1e438 | ||
|
|
4bc204925a | ||
|
|
5d9946184a | ||
|
|
5ba169a612 | ||
|
|
872b37f751 | ||
|
|
8485136f9a | ||
|
|
ff1bc739f1 | ||
|
|
594a0e7f1b | ||
|
|
8e28ba38d2 | ||
|
|
73c2ff17dd | ||
|
|
13f225e6ae | ||
|
|
3f62492a15 | ||
|
|
5e3bd2dff1 | ||
|
|
787a9c74fa | ||
|
|
14749df6f3 | ||
|
|
2db2898112 | ||
|
|
3776000fc4 | ||
|
|
f0572e59e7 | ||
|
|
6217184c7f | ||
|
|
044dcbaed0 | ||
|
|
8a5eae94ea | ||
|
|
bf3c6aeed1 | ||
|
|
f3fbf995ca | ||
|
|
03bded2b6b | ||
|
|
d5c0829d61 | ||
|
|
00369303de | ||
|
|
1f1479c0a7 | ||
|
|
e67f848abc | ||
|
|
560f50d3cd | ||
|
|
3f45122d0d | ||
|
|
50bdaa573c | ||
|
|
24b6698cc9 | ||
|
|
73885d3b9e | ||
|
|
f29387316f | ||
|
|
d6fd0d2aca | ||
|
|
e814da1eec | ||
|
|
e029a09345 |
@@ -3,14 +3,25 @@ parseable: true
|
||||
skip_list:
|
||||
# see https://docs.ansible.com/ansible-lint/rules/default_rules.html for a list of all default rules
|
||||
# The following rules throw errors.
|
||||
# These either still need to be corrected in the repository and the rules re-enabled or they are skipped on purpose.
|
||||
- '204'
|
||||
- '206'
|
||||
# These either still need to be corrected in the repository and the rules re-enabled or documented why they are skipped on purpose.
|
||||
- '301'
|
||||
- '302'
|
||||
- '303'
|
||||
- '305'
|
||||
- '306'
|
||||
- '404'
|
||||
- '502'
|
||||
- '503'
|
||||
- '504'
|
||||
|
||||
# These rules are intentionally skipped:
|
||||
#
|
||||
# [E204]: "Lines should be no longer than 160 chars"
|
||||
# This could be re-enabled with a major rewrite in the future.
|
||||
# For now, there's not enough value gain from strictly limiting line length.
|
||||
# (Disabled in May 2019)
|
||||
- '204'
|
||||
|
||||
# [E701]: "meta/main.yml should contain relevant info"
|
||||
# Roles in Kubespray are not intended to be used/imported by Ansible Galaxy.
|
||||
# While it can be useful to have these metadata available, they are also available in the existing documentation.
|
||||
# (Disabled in May 2019)
|
||||
- '701'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
stages:
|
||||
- unit-tests
|
||||
- moderator
|
||||
- deploy-part1
|
||||
- moderator
|
||||
- deploy-part2
|
||||
- deploy-gce
|
||||
- deploy-special
|
||||
@@ -30,14 +30,15 @@ variables:
|
||||
|
||||
before_script:
|
||||
- ./tests/scripts/rebase.sh
|
||||
- /usr/bin/python -m pip install -r tests/requirements.txt
|
||||
- update-alternatives --install /usr/bin/python python /usr/bin/python3 1
|
||||
- python -m pip install -r tests/requirements.txt
|
||||
- mkdir -p /.ssh
|
||||
|
||||
.job: &job
|
||||
tags:
|
||||
- packet
|
||||
variables:
|
||||
KUBESPRAY_VERSION: v2.9.0
|
||||
KUBESPRAY_VERSION: v2.11.2
|
||||
image: quay.io/kubespray/kubespray:$KUBESPRAY_VERSION
|
||||
|
||||
.testcases: &testcases
|
||||
@@ -45,6 +46,7 @@ before_script:
|
||||
services:
|
||||
- docker:dind
|
||||
before_script:
|
||||
- update-alternatives --install /usr/bin/python python /usr/bin/python3 1
|
||||
- ./tests/scripts/rebase.sh
|
||||
- ./tests/scripts/testcases_prepare.sh
|
||||
script:
|
||||
@@ -60,11 +62,11 @@ ci-authorized:
|
||||
script:
|
||||
- /bin/sh scripts/premoderator.sh
|
||||
except: ['triggers', 'master']
|
||||
# Disable ci moderator
|
||||
only: []
|
||||
|
||||
include:
|
||||
- .gitlab-ci/lint.yml
|
||||
- .gitlab-ci/shellcheck.yml
|
||||
- .gitlab-ci/gce.yml
|
||||
- .gitlab-ci/digital-ocean.yml
|
||||
- .gitlab-ci/terraform.yml
|
||||
- .gitlab-ci/packet.yml
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
.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-.*$/]
|
||||
@@ -20,6 +20,8 @@
|
||||
<<: *gce_variables
|
||||
tags:
|
||||
- gce
|
||||
except: ['triggers']
|
||||
only: [/^pr-.*$/]
|
||||
|
||||
.centos_weave_kubeadm_variables: ¢os_weave_kubeadm_variables
|
||||
# stage: deploy-part1
|
||||
@@ -36,8 +38,6 @@ gce_ubuntu18-flannel-aio:
|
||||
stage: deploy-part1
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: [/^pr-.*$/]
|
||||
|
||||
### PR JOBS PART2
|
||||
|
||||
@@ -45,15 +45,11 @@ gce_coreos-calico-aio:
|
||||
stage: deploy-gce
|
||||
<<: *gce
|
||||
when: on_success
|
||||
except: ['triggers']
|
||||
only: [/^pr-.*$/]
|
||||
|
||||
gce_centos7-flannel-addons:
|
||||
stage: deploy-gce
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: [/^pr-.*$/]
|
||||
|
||||
### MANUAL JOBS
|
||||
|
||||
@@ -64,36 +60,42 @@ gce_centos-weave-kubeadm-sep:
|
||||
<<: *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)
|
||||
|
||||
@@ -102,27 +104,23 @@ gce_ubuntu-canal-ha:
|
||||
stage: deploy-special
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
gce_ubuntu-canal-kubeadm:
|
||||
stage: deploy-gce
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
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
|
||||
except: ['triggers']
|
||||
|
||||
gce_centos-weave-kubeadm-triggers:
|
||||
stage: deploy-gce
|
||||
@@ -131,99 +129,87 @@ gce_centos-weave-kubeadm-triggers:
|
||||
<<: *centos_weave_kubeadm_variables
|
||||
when: on_success
|
||||
only: ['triggers']
|
||||
except: []
|
||||
|
||||
gce_ubuntu-contiv-sep:
|
||||
stage: deploy-special
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
gce_coreos-cilium:
|
||||
stage: deploy-special
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
gce_ubuntu18-cilium-sep:
|
||||
stage: deploy-special
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
gce_rhel7-weave:
|
||||
stage: deploy-gce
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
gce_rhel7-weave-triggers:
|
||||
stage: deploy-gce
|
||||
<<: *gce
|
||||
when: on_success
|
||||
only: ['triggers']
|
||||
except: []
|
||||
|
||||
gce_debian9-calico-upgrade:
|
||||
stage: deploy-gce
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
gce_debian9-calico-triggers:
|
||||
stage: deploy-gce
|
||||
<<: *gce
|
||||
when: on_success
|
||||
only: ['triggers']
|
||||
except: []
|
||||
|
||||
gce_coreos-canal:
|
||||
stage: deploy-gce
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
gce_coreos-canal-triggers:
|
||||
stage: deploy-gce
|
||||
<<: *gce
|
||||
when: on_success
|
||||
only: ['triggers']
|
||||
except: []
|
||||
|
||||
gce_rhel7-canal-sep:
|
||||
stage: deploy-special
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
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
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
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
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
gce_centos7-multus-calico:
|
||||
stage: deploy-gce
|
||||
@@ -231,6 +217,11 @@ gce_centos7-multus-calico:
|
||||
variables:
|
||||
<<: *centos7_multus_calico_variables
|
||||
when: manual
|
||||
|
||||
gce_oracle-canal:
|
||||
stage: deploy-gce
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
@@ -238,27 +229,19 @@ gce_opensuse-canal:
|
||||
stage: deploy-gce
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
# no triggers yet https://github.com/kubernetes-incubator/kargo/issues/613
|
||||
gce_coreos-alpha-weave-ha:
|
||||
stage: deploy-special
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
gce_coreos-kube-router:
|
||||
stage: deploy-special
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
gce_ubuntu-kube-router-sep:
|
||||
stage: deploy-special
|
||||
<<: *gce
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
@@ -2,10 +2,21 @@
|
||||
yamllint:
|
||||
extends: .job
|
||||
stage: unit-tests
|
||||
variables:
|
||||
LANG: C.UTF-8
|
||||
script:
|
||||
- yamllint --strict .
|
||||
except: ['triggers', 'master']
|
||||
|
||||
vagrant-validate:
|
||||
extends: .job
|
||||
stage: unit-tests
|
||||
script:
|
||||
- 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']
|
||||
|
||||
ansible-lint:
|
||||
extends: .job
|
||||
stage: unit-tests
|
||||
@@ -33,8 +44,20 @@ syntax-check:
|
||||
tox-inventory-builder:
|
||||
stage: unit-tests
|
||||
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:
|
||||
- pip install tox
|
||||
- pip3 install tox
|
||||
- cd contrib/inventory_builder && tox
|
||||
when: manual
|
||||
except: ['triggers', 'master']
|
||||
|
||||
markdownlint:
|
||||
stage: unit-tests
|
||||
image: node
|
||||
before_script:
|
||||
- npm install -g markdownlint-cli
|
||||
script:
|
||||
- markdownlint README.md docs --ignore docs/_sidebar.md
|
||||
|
||||
@@ -1,123 +1,126 @@
|
||||
---
|
||||
.packet_variables: &packet_variables
|
||||
CI_PLATFORM: "packet"
|
||||
SSH_USER: "kubespray"
|
||||
|
||||
.packet: &packet
|
||||
extends: .testcases
|
||||
variables:
|
||||
<<: *packet_variables
|
||||
CI_PLATFORM: "packet"
|
||||
SSH_USER: "kubespray"
|
||||
tags:
|
||||
- packet
|
||||
|
||||
.test-upgrade: &test-upgrade
|
||||
variables:
|
||||
UPGRADE_TEST: "graceful"
|
||||
only: [/^pr-.*$/]
|
||||
except: ['triggers']
|
||||
|
||||
packet_ubuntu18-calico-aio:
|
||||
stage: deploy-part1
|
||||
<<: *packet
|
||||
extends: .packet
|
||||
when: on_success
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
# ### PR JOBS PART2
|
||||
|
||||
packet_centos7-flannel-addons:
|
||||
extends: .packet
|
||||
stage: deploy-part2
|
||||
<<: *packet
|
||||
when: on_success
|
||||
except: ['triggers']
|
||||
only: [/^pr-.*$/]
|
||||
|
||||
# ### MANUAL JOBS
|
||||
|
||||
packet_centos-weave-kubeadm-sep:
|
||||
stage: deploy-part2
|
||||
<<: *packet
|
||||
extends: .packet
|
||||
when: on_success
|
||||
only: ['triggers']
|
||||
variables:
|
||||
UPGRADE_TEST: basic
|
||||
|
||||
packet_ubuntu-weave-sep:
|
||||
stage: deploy-part2
|
||||
<<: *packet
|
||||
extends: .packet
|
||||
when: manual
|
||||
only: ['triggers']
|
||||
|
||||
# # More builds for PRs/merges (manual) and triggers (auto)
|
||||
|
||||
packet_ubuntu-canal-ha:
|
||||
stage: deploy-special
|
||||
<<: *packet
|
||||
extends: .packet
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
packet_ubuntu-canal-kubeadm:
|
||||
stage: deploy-part2
|
||||
<<: *packet
|
||||
extends: .packet
|
||||
when: on_success
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
packet_ubuntu-flannel-ha:
|
||||
stage: deploy-part2
|
||||
<<: *packet
|
||||
when: on_success
|
||||
except: ['triggers']
|
||||
|
||||
packet_ubuntu-contiv-sep:
|
||||
stage: deploy-special
|
||||
<<: *packet
|
||||
extends: .packet
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
# Contiv does not work in k8s v1.16
|
||||
# packet_ubuntu-contiv-sep:
|
||||
# stage: deploy-part2
|
||||
# extends: .packet
|
||||
# when: on_success
|
||||
|
||||
packet_ubuntu18-cilium-sep:
|
||||
stage: deploy-special
|
||||
<<: *packet
|
||||
extends: .packet
|
||||
when: manual
|
||||
|
||||
packet_ubuntu18-flannel-containerd:
|
||||
stage: deploy-part2
|
||||
extends: .packet
|
||||
when: manual
|
||||
|
||||
packet_debian9-macvlan-sep:
|
||||
stage: deploy-part2
|
||||
extends: .packet
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
packet_debian9-calico-upgrade:
|
||||
stage: deploy-part2
|
||||
<<: *packet
|
||||
extends: .packet
|
||||
when: on_success
|
||||
variables:
|
||||
UPGRADE_TEST: graceful
|
||||
|
||||
packet_debian10-containerd:
|
||||
stage: deploy-part2
|
||||
extends: .packet
|
||||
when: on_success
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
packet_centos7-calico-ha:
|
||||
stage: deploy-part2
|
||||
<<: *packet
|
||||
extends: .packet
|
||||
when: manual
|
||||
|
||||
packet_centos7-kube-ovn:
|
||||
stage: deploy-part2
|
||||
extends: .packet
|
||||
when: on_success
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
packet_centos7-kube-router:
|
||||
stage: deploy-special
|
||||
<<: *packet
|
||||
stage: deploy-part2
|
||||
extends: .packet
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
packet_centos7-multus-calico:
|
||||
stage: deploy-part2
|
||||
<<: *packet
|
||||
extends: .packet
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
packet_opensuse-canal:
|
||||
stage: deploy-part2
|
||||
<<: *packet
|
||||
extends: .packet
|
||||
when: manual
|
||||
|
||||
packet_oracle-7-canal:
|
||||
stage: deploy-part2
|
||||
extends: .packet
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
packet_ubuntu-kube-router-sep:
|
||||
stage: deploy-special
|
||||
<<: *packet
|
||||
stage: deploy-part2
|
||||
extends: .packet
|
||||
when: manual
|
||||
|
||||
packet_amazon-linux-2-aio:
|
||||
stage: deploy-part2
|
||||
extends: .packet
|
||||
when: manual
|
||||
except: ['triggers']
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
@@ -3,131 +3,92 @@
|
||||
.terraform_install:
|
||||
extends: .job
|
||||
before_script:
|
||||
- update-alternatives --install /usr/bin/python python /usr/bin/python3 1
|
||||
- ./tests/scripts/rebase.sh
|
||||
- ./tests/scripts/testcases_prepare.sh
|
||||
- ./tests/scripts/terraform_install.sh
|
||||
# Set Ansible config
|
||||
- cp ansible.cfg ~/.ansible.cfg
|
||||
# Install Terraform
|
||||
- apt-get install -y unzip
|
||||
- curl https://releases.hashicorp.com/terraform/${TF_VERSION}/terraform_${TF_VERSION}_linux_amd64.zip > /tmp/terraform.zip
|
||||
- unzip /tmp/terraform.zip && mv ./terraform /usr/local/bin/ && terraform --version
|
||||
# Prepare inventory
|
||||
- cp -LRp contrib/terraform/$PROVIDER/sample-inventory inventory/$CLUSTER
|
||||
- cd inventory/$CLUSTER
|
||||
- ln -s ../../contrib/terraform/$PROVIDER/hosts
|
||||
- terraform init ../../contrib/terraform/$PROVIDER
|
||||
- cp contrib/terraform/$PROVIDER/sample-inventory/cluster.tfvars .
|
||||
- ln -s contrib/terraform/$PROVIDER/hosts
|
||||
- terraform init contrib/terraform/$PROVIDER
|
||||
# Copy SSH keypair
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "$PACKET_PRIVATE_KEY" | base64 -d > ~/.ssh/id_rsa
|
||||
- chmod 400 ~/.ssh/id_rsa
|
||||
- echo "$PACKET_PUBLIC_KEY" | base64 -d > ~/.ssh/id_rsa.pub
|
||||
only: ['master', /^pr-.*$/]
|
||||
|
||||
.terraform_validate:
|
||||
extends: .terraform_install
|
||||
stage: unit-tests
|
||||
only: ['master', /^pr-.*$/]
|
||||
script:
|
||||
- terraform validate -var-file=cluster.tf ../../contrib/terraform/$PROVIDER
|
||||
- terraform fmt -check -diff ../../contrib/terraform/$PROVIDER
|
||||
- terraform validate -var-file=cluster.tfvars contrib/terraform/$PROVIDER
|
||||
- terraform fmt -check -diff contrib/terraform/$PROVIDER
|
||||
|
||||
.terraform_apply:
|
||||
extends: .terraform_install
|
||||
stage: deploy-part2
|
||||
when: manual
|
||||
only: [/^pr-.*$/]
|
||||
variables:
|
||||
ANSIBLE_INVENTORY_UNPARSED_FAILED: "true"
|
||||
ANSIBLE_INVENTORY: hosts
|
||||
CI_PLATFORM: tf
|
||||
TF_VAR_ssh_user: $SSH_USER
|
||||
TF_VAR_cluster_name: $CI_JOB_ID
|
||||
script:
|
||||
- terraform apply -auto-approve ../../contrib/terraform/$PROVIDER
|
||||
- ansible-playbook -i hosts ../../cluster.yml --become
|
||||
- tests/scripts/testcases_run.sh
|
||||
after_script:
|
||||
# Cleanup regardless of exit code
|
||||
- cd inventory/$CLUSTER
|
||||
- terraform destroy -auto-approve ../../contrib/terraform/$PROVIDER
|
||||
- ./tests/scripts/testcases_cleanup.sh
|
||||
|
||||
tf-validate-openstack:
|
||||
extends: .terraform_validate
|
||||
variables:
|
||||
TF_VERSION: 0.11.11
|
||||
TF_VERSION: 0.12.12
|
||||
PROVIDER: openstack
|
||||
CLUSTER: $CI_COMMIT_REF_NAME
|
||||
|
||||
tf-validate-packet:
|
||||
extends: .terraform_validate
|
||||
variables:
|
||||
TF_VERSION: 0.11.11
|
||||
TF_VERSION: 0.12.12
|
||||
PROVIDER: packet
|
||||
CLUSTER: $CI_COMMIT_REF_NAME
|
||||
|
||||
tf-validate-aws:
|
||||
extends: .terraform_validate
|
||||
variables:
|
||||
TF_VERSION: 0.11.11
|
||||
TF_VERSION: 0.12.12
|
||||
PROVIDER: aws
|
||||
CLUSTER: $CI_COMMIT_REF_NAME
|
||||
|
||||
tf-packet-ubuntu16-default:
|
||||
extends: .terraform_apply
|
||||
variables:
|
||||
TF_VERSION: 0.11.11
|
||||
PROVIDER: packet
|
||||
CLUSTER: $CI_COMMIT_REF_NAME
|
||||
TF_VAR_cluster_name: $CI_COMMIT_REF_SLUG
|
||||
TF_VAR_number_of_k8s_masters: "1"
|
||||
TF_VAR_number_of_k8s_nodes: "1"
|
||||
TF_VAR_plan_k8s_masters: t1.small.x86
|
||||
TF_VAR_plan_k8s_nodes: t1.small.x86
|
||||
TF_VAR_facility: ewr1
|
||||
TF_VAR_public_key_path: ""
|
||||
TF_VAR_operating_system: ubuntu_16_04
|
||||
|
||||
tf-packet-ubuntu18-default:
|
||||
extends: .terraform_apply
|
||||
variables:
|
||||
TF_VERSION: 0.11.11
|
||||
PROVIDER: packet
|
||||
CLUSTER: $CI_COMMIT_REF_NAME
|
||||
TF_VAR_cluster_name: $CI_COMMIT_REF_SLUG
|
||||
TF_VAR_number_of_k8s_masters: "1"
|
||||
TF_VAR_number_of_k8s_nodes: "1"
|
||||
TF_VAR_plan_k8s_masters: t1.small.x86
|
||||
TF_VAR_plan_k8s_nodes: t1.small.x86
|
||||
TF_VAR_facility: ams1
|
||||
TF_VAR_public_key_path: ""
|
||||
TF_VAR_operating_system: ubuntu_18_04
|
||||
|
||||
.ovh_variables: &ovh_variables
|
||||
OS_AUTH_URL: https://auth.cloud.ovh.net/v3
|
||||
OS_PROJECT_ID: 8d3cd5d737d74227ace462dee0b903fe
|
||||
OS_PROJECT_NAME: "9361447987648822"
|
||||
OS_USER_DOMAIN_NAME: Default
|
||||
OS_PROJECT_DOMAIN_ID: default
|
||||
OS_USERNAME: 8XuhBMfkKVrk
|
||||
OS_REGION_NAME: UK1
|
||||
OS_INTERFACE: public
|
||||
OS_IDENTITY_API_VERSION: "3"
|
||||
|
||||
tf-apply-ovh:
|
||||
extends: .terraform_apply
|
||||
variables:
|
||||
<<: *ovh_variables
|
||||
TF_VERSION: 0.11.11
|
||||
PROVIDER: openstack
|
||||
CLUSTER: $CI_COMMIT_REF_NAME
|
||||
ANSIBLE_TIMEOUT: "60"
|
||||
TF_VAR_cluster_name: $CI_COMMIT_REF_SLUG
|
||||
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: "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_k8s_allowed_remote_ips: '["0.0.0.0/0"]'
|
||||
# tf-packet-ubuntu16-default:
|
||||
# extends: .terraform_apply
|
||||
# variables:
|
||||
# TF_VERSION: 0.12.12
|
||||
# PROVIDER: packet
|
||||
# CLUSTER: $CI_COMMIT_REF_NAME
|
||||
# TF_VAR_number_of_k8s_masters: "1"
|
||||
# TF_VAR_number_of_k8s_nodes: "1"
|
||||
# TF_VAR_plan_k8s_masters: t1.small.x86
|
||||
# TF_VAR_plan_k8s_nodes: t1.small.x86
|
||||
# TF_VAR_facility: ewr1
|
||||
# TF_VAR_public_key_path: ""
|
||||
# TF_VAR_operating_system: ubuntu_16_04
|
||||
#
|
||||
# tf-packet-ubuntu18-default:
|
||||
# extends: .terraform_apply
|
||||
# variables:
|
||||
# TF_VERSION: 0.12.12
|
||||
# PROVIDER: packet
|
||||
# CLUSTER: $CI_COMMIT_REF_NAME
|
||||
# TF_VAR_number_of_k8s_masters: "1"
|
||||
# TF_VAR_number_of_k8s_nodes: "1"
|
||||
# TF_VAR_plan_k8s_masters: t1.small.x86
|
||||
# TF_VAR_plan_k8s_nodes: t1.small.x86
|
||||
# TF_VAR_facility: ams1
|
||||
# TF_VAR_public_key_path: ""
|
||||
# TF_VAR_operating_system: ubuntu_18_04
|
||||
|
||||
2
.markdownlint.yaml
Normal file
2
.markdownlint.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
MD013: false
|
||||
11
Dockerfile
11
Dockerfile
@@ -4,8 +4,8 @@ RUN mkdir /kubespray
|
||||
WORKDIR /kubespray
|
||||
RUN apt update -y && \
|
||||
apt install -y \
|
||||
libssl-dev python-dev sshpass apt-transport-https jq \
|
||||
ca-certificates curl gnupg2 software-properties-common python-pip
|
||||
libssl-dev python3-dev sshpass apt-transport-https jq moreutils \
|
||||
ca-certificates curl gnupg2 software-properties-common python3-pip rsync
|
||||
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \
|
||||
add-apt-repository \
|
||||
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
|
||||
@@ -13,6 +13,9 @@ RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - &&
|
||||
stable" \
|
||||
&& apt update -y && apt-get install docker-ce -y
|
||||
COPY . .
|
||||
RUN /usr/bin/python -m pip install pip -U && /usr/bin/python -m pip install -r tests/requirements.txt && python -m pip install -r requirements.txt
|
||||
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.13.5/bin/linux/amd64/kubectl \
|
||||
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 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
|
||||
|
||||
# Some tools like yamllint need this
|
||||
ENV LANG=C.UTF-8
|
||||
|
||||
@@ -4,17 +4,12 @@ aliases:
|
||||
- mattymo
|
||||
- atoms
|
||||
- chadswen
|
||||
- rsmitty
|
||||
- bogdando
|
||||
- bradbeam
|
||||
- woopstar
|
||||
- mirwan
|
||||
- miouge1
|
||||
- riverzhang
|
||||
- holser
|
||||
- smana
|
||||
- verwilst
|
||||
- woopstar
|
||||
kubespray-reviewers:
|
||||
- jjungnickel
|
||||
- archifleks
|
||||
- chapsuk
|
||||
- mirwan
|
||||
- miouge1
|
||||
- holmsten
|
||||
|
||||
91
README.md
91
README.md
@@ -1,7 +1,6 @@
|
||||

|
||||
# Deploy a Production Ready Kubernetes Cluster
|
||||
|
||||
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/)
|
||||
@@ -12,8 +11,7 @@ You can get your invite [here](http://slack.k8s.io/)
|
||||
- Supports most popular **Linux distributions**
|
||||
- **Continuous integration tests**
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
## Quick Start
|
||||
|
||||
To deploy the cluster you can use :
|
||||
|
||||
@@ -21,6 +19,7 @@ To deploy the cluster you can use :
|
||||
|
||||
#### Usage
|
||||
|
||||
```ShellSession
|
||||
# Install dependencies from ``requirements.txt``
|
||||
sudo pip install -r requirements.txt
|
||||
|
||||
@@ -29,23 +28,26 @@ To deploy the cluster you can use :
|
||||
|
||||
# Update Ansible inventory file with inventory builder
|
||||
declare -a IPS=(10.10.1.3 10.10.1.4 10.10.1.5)
|
||||
CONFIG_FILE=inventory/mycluster/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]}
|
||||
CONFIG_FILE=inventory/mycluster/inventory.ini python3 contrib/inventory_builder/inventory.py ${IPS[@]}
|
||||
|
||||
# Review and change parameters under ``inventory/mycluster/group_vars``
|
||||
cat inventory/mycluster/group_vars/all/all.yml
|
||||
cat inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml
|
||||
|
||||
# Deploy Kubespray with Ansible Playbook - run the playbook as root
|
||||
# The option `-b` 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.
|
||||
# Without -b the playbook will fail to run!
|
||||
ansible-playbook -i inventory/mycluster/hosts.yml --become --become-user=root cluster.yml
|
||||
# Without --become the playbook will fail to run!
|
||||
ansible-playbook -i inventory/mycluster/inventory.ini --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).
|
||||
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.
|
||||
```
|
||||
|
||||
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.
|
||||
@@ -56,16 +58,19 @@ A workaround consists of setting `ANSIBLE_LIBRARY` and `ANSIBLE_MODULE_UTILS` en
|
||||
For Vagrant we need to install python dependencies for provisioning tasks.
|
||||
Check if Python and pip are installed:
|
||||
|
||||
```ShellSession
|
||||
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/>
|
||||
Install the necessary requirements
|
||||
|
||||
```ShellSession
|
||||
sudo pip install -r requirements.txt
|
||||
vagrant up
|
||||
```
|
||||
|
||||
Documents
|
||||
---------
|
||||
## Documents
|
||||
|
||||
- [Requirements](#requirements)
|
||||
- [Kubespray vs ...](docs/comparisons.md)
|
||||
@@ -91,8 +96,7 @@ Documents
|
||||
- [Upgrades basics](docs/upgrades.md)
|
||||
- [Roadmap](docs/roadmap.md)
|
||||
|
||||
Supported Linux Distributions
|
||||
-----------------------------
|
||||
## Supported Linux Distributions
|
||||
|
||||
- **Container Linux by CoreOS**
|
||||
- **Debian** Buster, Jessie, Stretch, Wheezy
|
||||
@@ -101,40 +105,41 @@ Supported Linux Distributions
|
||||
- **Fedora** 28
|
||||
- **Fedora/CentOS** Atomic
|
||||
- **openSUSE** Leap 42.3/Tumbleweed
|
||||
- **Oracle Linux** 7
|
||||
|
||||
Note: Upstart/SysV init based OS types are not supported.
|
||||
|
||||
Supported Components
|
||||
--------------------
|
||||
## Supported Components
|
||||
|
||||
- Core
|
||||
- [kubernetes](https://github.com/kubernetes/kubernetes) v1.14.1
|
||||
- [etcd](https://github.com/coreos/etcd) v3.2.26
|
||||
- [kubernetes](https://github.com/kubernetes/kubernetes) v1.16.11
|
||||
- [etcd](https://github.com/coreos/etcd) v3.3.12
|
||||
- [docker](https://www.docker.com/) v18.06 (see note)
|
||||
- [cri-o](http://cri-o.io/) v1.11.5 (experimental: see [CRI-O Note](docs/cri-o.md). Only on centos based OS)
|
||||
- [containerd](https://containerd.io/) v1.2.13
|
||||
- [cri-o](http://cri-o.io/) v1.14.0 (experimental: see [CRI-O Note](docs/cri-o.md). Only on centos based OS)
|
||||
- Network Plugin
|
||||
- [calico](https://github.com/projectcalico/calico) v3.4.0
|
||||
- [cni-plugins](https://github.com/containernetworking/plugins) v0.8.6
|
||||
- [calico](https://github.com/projectcalico/calico) v3.7.3
|
||||
- [canal](https://github.com/projectcalico/canal) (given calico/flannel versions)
|
||||
- [cilium](https://github.com/cilium/cilium) v1.3.0
|
||||
- [cilium](https://github.com/cilium/cilium) v1.5.5
|
||||
- [contiv](https://github.com/contiv/install) v1.2.1
|
||||
- [flanneld](https://github.com/coreos/flannel) v0.11.0
|
||||
- [kube-router](https://github.com/cloudnativelabs/kube-router) v0.2.5
|
||||
- [multus](https://github.com/intel/multus-cni) v3.1.autoconf
|
||||
- [weave](https://github.com/weaveworks/weave) v2.5.1
|
||||
- [multus](https://github.com/intel/multus-cni) v3.2.1
|
||||
- [weave](https://github.com/weaveworks/weave) v2.5.2
|
||||
- Application
|
||||
- [cephfs-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.0-k8s1.11
|
||||
- [rbd-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.1-k8s1.11
|
||||
- [cert-manager](https://github.com/jetstack/cert-manager) v0.5.2
|
||||
- [coredns](https://github.com/coredns/coredns) v1.5.0
|
||||
- [ingress-nginx](https://github.com/kubernetes/ingress-nginx) v0.21.0
|
||||
- [cert-manager](https://github.com/jetstack/cert-manager) v0.11.0
|
||||
- [coredns](https://github.com/coredns/coredns) v1.6.0
|
||||
- [ingress-nginx](https://github.com/kubernetes/ingress-nginx) v0.26.1
|
||||
|
||||
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).
|
||||
Note: The list of validated [docker versions](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.16.md) was updated to 1.13.1, 17.03, 17.06, 17.09, 18.06, 18.09. 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
|
||||
|
||||
- **Ansible v2.7.8 (or newer) and python-netaddr is installed on the machine
|
||||
that will run Ansible commands**
|
||||
- **Minimum required version of Kubernetes is v1.15**
|
||||
- **Ansible v2.7.16 and python-netaddr is installed on the machine that will run Ansible commands**
|
||||
- **Jinja 2.9 (or newer) is required to run the Ansible Playbooks**
|
||||
- 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 target servers are configured to allow **IPv4 forwarding**.
|
||||
@@ -153,10 +158,9 @@ These limits are safe guarded by Kubespray. Actual requirements for your workloa
|
||||
- Node
|
||||
- Memory: 1024 MB
|
||||
|
||||
Network Plugins
|
||||
---------------
|
||||
## Network Plugins
|
||||
|
||||
You can choose between 6 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.
|
||||
|
||||
@@ -170,35 +174,36 @@ You can choose between 6 network plugins. (default: `calico`, except Vagrant use
|
||||
apply firewall policies, segregate containers in multiple network and bridging pods onto physical networks.
|
||||
|
||||
- [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](http://docs.weave.works/weave/latest_release/troubleshooting.html)).
|
||||
(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-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),
|
||||
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.
|
||||
|
||||
- [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.
|
||||
|
||||
The choice is defined with the variable `kube_network_plugin`. There is also an
|
||||
option to leverage built-in cloud provider networking instead.
|
||||
See also [Network checker](docs/netcheck.md).
|
||||
|
||||
Community docs and resources
|
||||
----------------------------
|
||||
## Community docs and resources
|
||||
|
||||
- [kubernetes.io/docs/getting-started-guides/kubespray/](https://kubernetes.io/docs/getting-started-guides/kubespray/)
|
||||
- [kubernetes.io/docs/setup/production-environment/tools/kubespray/](https://kubernetes.io/docs/setup/production-environment/tools/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)
|
||||
|
||||
Tools and projects on top of Kubespray
|
||||
--------------------------------------
|
||||
## Tools and projects on top of Kubespray
|
||||
|
||||
- [Digital Rebar Provision](https://github.com/digitalrebar/provision/blob/master/doc/integrations/ansible.rst)
|
||||
- [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
|
||||
--------
|
||||
## CI Tests
|
||||
|
||||
[](https://gitlab.com/kargo-ci/kubernetes-sigs-kubespray/pipelines)
|
||||
|
||||
|
||||
17
RELEASE.md
17
RELEASE.md
@@ -3,16 +3,19 @@
|
||||
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
|
||||
2. At least one of the [OWNERS](OWNERS) must LGTM this release
|
||||
3. An OWNER runs `git tag -s $VERSION` and inserts the changelog and pushes the tag with `git push $VERSION`
|
||||
4. The release issue is closed
|
||||
5. An announcement email is sent to `kubernetes-dev@googlegroups.com` with the subject `[ANNOUNCE] Kubespray $VERSION is released`
|
||||
2. At least one of the [approvers](OWNERS_ALIASES) must approve this release
|
||||
3. 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
|
||||
4. An approver creates a release branch in the form `release-vX.Y`
|
||||
5. The corresponding version of [quay.io/kubespray/kubespray:vX.Y.Z](https://quay.io/repository/kubespray/kubespray) docker image is built and tagged
|
||||
6. The `KUBESPRAY_VERSION` variable is updated in `.gitlab-ci.yml`
|
||||
7. The release issue is closed
|
||||
8. An announcement email is sent to `kubernetes-dev@googlegroups.com` with the subject `[ANNOUNCE] Kubespray $VERSION is released`
|
||||
|
||||
## Major/minor releases, merge freezes and milestones
|
||||
|
||||
* 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.
|
||||
* Kubespray maintains one branch for major releases (vX.Y). Minor releases are available only as tags.
|
||||
|
||||
* Security patches and bugs might be backported.
|
||||
|
||||
* Fixes for major releases (vX.x.0) and minor releases (vX.Y.x) are delivered
|
||||
via maintenance releases (vX.Y.Z) and assigned to the corresponding open
|
||||
|
||||
17
Vagrantfile
vendored
17
Vagrantfile
vendored
@@ -21,10 +21,11 @@ SUPPORTED_OS = {
|
||||
"ubuntu1604" => {box: "generic/ubuntu1604", user: "vagrant"},
|
||||
"ubuntu1804" => {box: "generic/ubuntu1804", user: "vagrant"},
|
||||
"centos" => {box: "centos/7", user: "vagrant"},
|
||||
"centos-bento" => {box: "bento/centos-7.5", user: "vagrant"},
|
||||
"centos-bento" => {box: "bento/centos-7.6", user: "vagrant"},
|
||||
"fedora" => {box: "fedora/28-cloud-base", user: "vagrant"},
|
||||
"opensuse" => {box: "opensuse/openSUSE-15.0-x86_64", user: "vagrant"},
|
||||
"opensuse-tumbleweed" => {box: "opensuse/openSUSE-Tumbleweed-x86_64", user: "vagrant"},
|
||||
"oraclelinux" => {box: "generic/oracle7", user: "vagrant"},
|
||||
}
|
||||
|
||||
# Defaults for config options defined in CONFIG
|
||||
@@ -180,9 +181,17 @@ Vagrant.configure("2") do |config|
|
||||
"flannel_interface": "eth1",
|
||||
"kube_network_plugin": $network_plugin,
|
||||
"kube_network_plugin_multus": $multi_networking,
|
||||
"docker_keepcache": "1",
|
||||
"download_run_once": "False",
|
||||
"download_run_once": "True",
|
||||
"download_localhost": "False",
|
||||
"download_cache_dir": ENV['HOME'] + "/kubespray_cache",
|
||||
# Make kubespray cache even when download_run_once is false
|
||||
"download_force_cache": "True",
|
||||
# Keeping the cache on the nodes can improve provisioning speed while debugging kubespray
|
||||
"download_keep_remote_cache": "False",
|
||||
"docker_keepcache": "1",
|
||||
# These two settings will put kubectl and admin.config in $inventory/artifacts
|
||||
"kubeconfig_localhost": "True",
|
||||
"kubectl_localhost": "True",
|
||||
"local_path_provisioner_enabled": "#{$local_path_provisioner_enabled}",
|
||||
"local_path_provisioner_claim_root": "#{$local_path_provisioner_claim_root}",
|
||||
"ansible_ssh_user": SUPPORTED_OS[$os][:user]
|
||||
@@ -197,7 +206,7 @@ Vagrant.configure("2") do |config|
|
||||
ansible.inventory_path = $ansible_inventory_path
|
||||
end
|
||||
ansible.become = true
|
||||
ansible.limit = "all"
|
||||
ansible.limit = "all,localhost"
|
||||
ansible.host_key_checking = false
|
||||
ansible.raw_arguments = ["--forks=#{$num_instances}", "--flush-cache", "-e ansible_become_pass=vagrant"]
|
||||
ansible.host_vars = host_vars
|
||||
|
||||
@@ -4,6 +4,8 @@ ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o ConnectionAttempts=100
|
||||
#control_path = ~/.ssh/ansible-%%r@%%h:%%p
|
||||
[defaults]
|
||||
strategy_plugins = plugins/mitogen/ansible_mitogen/plugins/strategy
|
||||
# https://github.com/ansible/ansible/issues/56930 (to ignore group names with - and .)
|
||||
force_valid_group_names = ignore
|
||||
|
||||
host_key_checking=False
|
||||
gathering = smart
|
||||
@@ -14,6 +16,6 @@ library = ./library
|
||||
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
|
||||
deprecation_warnings=False
|
||||
inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo, .creds
|
||||
inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo, .creds, .gpg
|
||||
[inventory]
|
||||
ignore_patterns = artifacts, credentials
|
||||
|
||||
46
cluster.yml
46
cluster.yml
@@ -19,27 +19,14 @@
|
||||
- { role: kubespray-defaults}
|
||||
- { role: bastion-ssh-config, tags: ["localhost", "bastion"]}
|
||||
|
||||
- hosts: k8s-cluster:etcd:calico-rr
|
||||
- hosts: k8s-cluster:etcd
|
||||
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||
gather_facts: false
|
||||
roles:
|
||||
- { role: kubespray-defaults}
|
||||
- { role: bootstrap-os, tags: bootstrap-os}
|
||||
|
||||
- hosts: k8s-cluster:etcd:calico-rr
|
||||
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||
vars:
|
||||
ansible_ssh_pipelining: true
|
||||
gather_facts: false
|
||||
pre_tasks:
|
||||
- name: gather facts from all instances
|
||||
setup:
|
||||
delegate_to: "{{item}}"
|
||||
delegate_facts: true
|
||||
with_items: "{{ groups['k8s-cluster'] + groups['etcd'] + groups['calico-rr']|default([]) }}"
|
||||
run_once: true
|
||||
|
||||
- hosts: k8s-cluster:etcd:calico-rr
|
||||
- hosts: k8s-cluster:etcd
|
||||
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||
roles:
|
||||
- { role: kubespray-defaults}
|
||||
@@ -52,13 +39,23 @@
|
||||
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||
roles:
|
||||
- { role: kubespray-defaults}
|
||||
- { role: etcd, tags: etcd, etcd_cluster_setup: true, etcd_events_cluster_setup: "{{ etcd_events_cluster_enabled }}" }
|
||||
- role: etcd
|
||||
tags: etcd
|
||||
vars:
|
||||
etcd_cluster_setup: true
|
||||
etcd_events_cluster_setup: "{{ etcd_events_cluster_enabled }}"
|
||||
when: not etcd_kubeadm_enabled| default(false)
|
||||
|
||||
- hosts: k8s-cluster:calico-rr
|
||||
- hosts: k8s-cluster
|
||||
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||
roles:
|
||||
- { role: kubespray-defaults}
|
||||
- { role: etcd, tags: etcd, etcd_cluster_setup: false, etcd_events_cluster_setup: false }
|
||||
- role: etcd
|
||||
tags: etcd
|
||||
vars:
|
||||
etcd_cluster_setup: false
|
||||
etcd_events_cluster_setup: false
|
||||
when: not etcd_kubeadm_enabled| default(false)
|
||||
|
||||
- hosts: k8s-cluster
|
||||
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||
@@ -81,6 +78,13 @@
|
||||
- { role: kubespray-defaults}
|
||||
- { role: kubernetes/kubeadm, tags: kubeadm}
|
||||
- { role: network_plugin, tags: network }
|
||||
- { role: kubernetes/node-label }
|
||||
|
||||
- hosts: calico-rr
|
||||
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||
roles:
|
||||
- { role: kubespray-defaults}
|
||||
- { role: network_plugin/calico/rr, tags: ['network', 'calico_rr']}
|
||||
|
||||
- hosts: kube-master[0]
|
||||
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||
@@ -98,12 +102,6 @@
|
||||
- { role: kubernetes-apps/ingress_controller, tags: ingress-controller }
|
||||
- { role: kubernetes-apps/external_provisioner, tags: external-provisioner }
|
||||
|
||||
- hosts: calico-rr
|
||||
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||
roles:
|
||||
- { role: kubespray-defaults}
|
||||
- { role: network_plugin/calico/rr, tags: network }
|
||||
|
||||
- hosts: kube-master
|
||||
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||
roles:
|
||||
|
||||
@@ -42,8 +42,11 @@ class SearchEC2Tags(object):
|
||||
region = os.environ['REGION']
|
||||
|
||||
ec2 = boto3.resource('ec2', region)
|
||||
|
||||
instances = ec2.instances.filter(Filters=[{'Name': 'tag:'+tag_key, 'Values': tag_value}, {'Name': 'instance-state-name', 'Values': ['running']}])
|
||||
filters = [{'Name': 'tag:'+tag_key, 'Values': tag_value}, {'Name': 'instance-state-name', 'Values': ['running']}]
|
||||
cluster_name = os.getenv('CLUSTER_NAME')
|
||||
if cluster_name:
|
||||
filters.append({'Name': 'tag-key', 'Values': ['kubernetes.io/cluster/'+cluster_name]})
|
||||
instances = ec2.instances.filter(Filters=filters)
|
||||
for instance in instances:
|
||||
|
||||
##Suppose default vpc_visibility is private
|
||||
|
||||
@@ -7,7 +7,7 @@ cluster_name: example
|
||||
# node that can be used to access the masters and minions
|
||||
use_bastion: false
|
||||
|
||||
# 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.
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
command: azure vm list-ip-address --json {{ azure_resource_group }}
|
||||
register: vm_list_cmd
|
||||
|
||||
- set_fact:
|
||||
- name: Set vm_list
|
||||
set_fact:
|
||||
vm_list: "{{ vm_list_cmd.stdout }}"
|
||||
|
||||
- name: Generate inventory
|
||||
template: src=inventory.j2 dest="{{playbook_dir}}/inventory"
|
||||
template:
|
||||
src: inventory.j2
|
||||
dest: "{{ playbook_dir }}/inventory"
|
||||
|
||||
@@ -8,9 +8,22 @@
|
||||
command: az vm list -o json --resource-group {{ azure_resource_group }}
|
||||
register: vm_list_cmd
|
||||
|
||||
- set_fact:
|
||||
- name: Query Azure Load Balancer Public IP
|
||||
command: az network public-ip show -o json -g {{ azure_resource_group }} -n kubernetes-api-pubip
|
||||
register: lb_pubip_cmd
|
||||
|
||||
- name: Set VM IP, roles lists and load balancer public IP
|
||||
set_fact:
|
||||
vm_ip_list: "{{ vm_ip_list_cmd.stdout }}"
|
||||
vm_roles_list: "{{ vm_list_cmd.stdout }}"
|
||||
lb_pubip: "{{ lb_pubip_cmd.stdout }}"
|
||||
|
||||
- name: Generate inventory
|
||||
template: src=inventory.j2 dest="{{playbook_dir}}/inventory"
|
||||
template:
|
||||
src: inventory.j2
|
||||
dest: "{{ playbook_dir }}/inventory"
|
||||
|
||||
- name: Generate Load Balancer variables
|
||||
template:
|
||||
src: loadbalancer_vars.j2
|
||||
dest: "{{ playbook_dir }}/loadbalancer_vars.yml"
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
## External LB example config
|
||||
apiserver_loadbalancer_domain_name: {{ lb_pubip.dnsSettings.fqdn }}
|
||||
loadbalancer_apiserver:
|
||||
address: {{ lb_pubip.ipAddress }}
|
||||
port: 6443
|
||||
|
||||
## Internal loadbalancers for apiservers
|
||||
loadbalancer_apiserver_localhost: false
|
||||
@@ -29,7 +29,7 @@ sshKeyPath: "/home/{{admin_username}}/.ssh/authorized_keys"
|
||||
imageReference:
|
||||
publisher: "OpenLogic"
|
||||
offer: "CentOS"
|
||||
sku: "7.2"
|
||||
sku: "7.5"
|
||||
version: "latest"
|
||||
imageReferenceJson: "{{imageReference|to_json}}"
|
||||
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
---
|
||||
- set_fact:
|
||||
- name: Set base_dir
|
||||
set_fact:
|
||||
base_dir: "{{ playbook_dir }}/.generated/"
|
||||
|
||||
- file: path={{base_dir}} state=directory recurse=true
|
||||
- name: Create base_dir
|
||||
file:
|
||||
path: "{{ base_dir }}"
|
||||
state: directory
|
||||
recurse: true
|
||||
|
||||
- template: src={{item}} dest="{{base_dir}}/{{item}}"
|
||||
- name: Store json files in base_dir
|
||||
template:
|
||||
src: "{{ item }}"
|
||||
dest: "{{ base_dir }}/{{ item }}"
|
||||
with_items:
|
||||
- network.json
|
||||
- storage.json
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
# 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.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 by id: inventory.py -node1
|
||||
#
|
||||
@@ -44,7 +46,8 @@ import sys
|
||||
ROLES = ['all', 'kube-master', 'kube-node', 'etcd', 'k8s-cluster',
|
||||
'calico-rr']
|
||||
PROTECTED_NAMES = ROLES
|
||||
AVAILABLE_COMMANDS = ['help', 'print_cfg', 'print_ips', 'load']
|
||||
AVAILABLE_COMMANDS = ['help', 'print_cfg', 'print_ips', 'print_hostnames',
|
||||
'load']
|
||||
_boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
|
||||
'0': False, 'no': False, 'false': False, 'off': False}
|
||||
yaml = YAML()
|
||||
@@ -59,6 +62,7 @@ def get_var_as_bool(name, default):
|
||||
|
||||
|
||||
CONFIG_FILE = os.environ.get("CONFIG_FILE", "./inventory/sample/hosts.yaml")
|
||||
KUBE_MASTERS = int(os.environ.get("KUBE_MASTERS_MASTERS", 2))
|
||||
# Reconfigures cluster distribution at scale
|
||||
SCALE_THRESHOLD = int(os.environ.get("SCALE_THRESHOLD", 50))
|
||||
MASSIVE_SCALE_THRESHOLD = int(os.environ.get("SCALE_THRESHOLD", 200))
|
||||
@@ -78,7 +82,7 @@ class KubesprayInventory(object):
|
||||
try:
|
||||
self.hosts_file = open(config_file, 'r')
|
||||
self.yaml_config = yaml.load(self.hosts_file)
|
||||
except FileNotFoundError:
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
if changed_hosts and changed_hosts[0] in AVAILABLE_COMMANDS:
|
||||
@@ -96,9 +100,10 @@ class KubesprayInventory(object):
|
||||
etcd_hosts_count = 3 if len(self.hosts.keys()) >= 3 else 1
|
||||
self.set_etcd(list(self.hosts.keys())[:etcd_hosts_count])
|
||||
if len(self.hosts) >= SCALE_THRESHOLD:
|
||||
self.set_kube_master(list(self.hosts.keys())[etcd_hosts_count:5])
|
||||
self.set_kube_master(list(self.hosts.keys())[
|
||||
etcd_hosts_count:(etcd_hosts_count + KUBE_MASTERS)])
|
||||
else:
|
||||
self.set_kube_master(list(self.hosts.keys())[:2])
|
||||
self.set_kube_master(list(self.hosts.keys())[:KUBE_MASTERS])
|
||||
self.set_kube_node(self.hosts.keys())
|
||||
if len(self.hosts) >= SCALE_THRESHOLD:
|
||||
self.set_calico_rr(list(self.hosts.keys())[:etcd_hosts_count])
|
||||
@@ -192,8 +197,21 @@ class KubesprayInventory(object):
|
||||
'ip': ip,
|
||||
'access_ip': access_ip}
|
||||
elif host[0].isalpha():
|
||||
raise Exception("Adding hosts by hostname is not supported.")
|
||||
|
||||
if ',' in host:
|
||||
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
|
||||
|
||||
def range2ips(self, hosts):
|
||||
@@ -204,10 +222,10 @@ class KubesprayInventory(object):
|
||||
# Python 3.x
|
||||
start = int(ip_address(start_address))
|
||||
end = int(ip_address(end_address))
|
||||
except:
|
||||
except Exception:
|
||||
# Python 2.7
|
||||
start = int(ip_address(unicode(start_address)))
|
||||
end = int(ip_address(unicode(end_address)))
|
||||
start = int(ip_address(str(start_address)))
|
||||
end = int(ip_address(str(end_address)))
|
||||
return [ip_address(ip).exploded for ip in range(start, end + 1)]
|
||||
|
||||
for host in hosts:
|
||||
@@ -346,6 +364,8 @@ class KubesprayInventory(object):
|
||||
self.print_config()
|
||||
elif command == 'print_ips':
|
||||
self.print_ips()
|
||||
elif command == 'print_hostnames':
|
||||
self.print_hostnames()
|
||||
elif command == 'load':
|
||||
self.load_file(args)
|
||||
else:
|
||||
@@ -359,11 +379,13 @@ Available commands:
|
||||
help - Display this message
|
||||
print_cfg - Write inventory file to stdout
|
||||
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:
|
||||
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 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 by id: inventory.py -node1
|
||||
|
||||
@@ -379,6 +401,9 @@ MASSIVE_SCALE_THRESHOLD Separate K8s master and ETCD if # of nodes >= 200
|
||||
def print_config(self):
|
||||
yaml.dump(self.yaml_config, sys.stdout)
|
||||
|
||||
def print_hostnames(self):
|
||||
print(' '.join(self.yaml_config['all']['hosts'].keys()))
|
||||
|
||||
def print_ips(self):
|
||||
ips = []
|
||||
for host, opts in self.yaml_config['all']['hosts'].items():
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import inventory
|
||||
import mock
|
||||
import unittest
|
||||
|
||||
@@ -22,7 +23,7 @@ path = "./contrib/inventory_builder/"
|
||||
if path not in sys.path:
|
||||
sys.path.append(path)
|
||||
|
||||
import inventory
|
||||
import inventory # noqa
|
||||
|
||||
|
||||
class TestInventory(unittest.TestCase):
|
||||
@@ -43,7 +44,7 @@ class TestInventory(unittest.TestCase):
|
||||
|
||||
def test_get_ip_from_opts_invalid(self):
|
||||
optstring = "notanaddr=value something random!chars:D"
|
||||
self.assertRaisesRegexp(ValueError, "IP parameter not found",
|
||||
self.assertRaisesRegex(ValueError, "IP parameter not found",
|
||||
self.inv.get_ip_from_opts, optstring)
|
||||
|
||||
def test_ensure_required_groups(self):
|
||||
@@ -63,7 +64,7 @@ class TestInventory(unittest.TestCase):
|
||||
def test_get_host_id_invalid(self):
|
||||
bad_hostnames = ['node', 'no99de', '01node', 'node.111111']
|
||||
for hostname in bad_hostnames:
|
||||
self.assertRaisesRegexp(ValueError, "Host name must end in an",
|
||||
self.assertRaisesRegex(ValueError, "Host name must end in an",
|
||||
self.inv.get_host_id, hostname)
|
||||
|
||||
def test_build_hostnames_add_one(self):
|
||||
@@ -192,7 +193,7 @@ class TestInventory(unittest.TestCase):
|
||||
('node2', {'ansible_host': '10.90.0.3',
|
||||
'ip': '10.90.0.3',
|
||||
'access_ip': '10.90.0.3'})])
|
||||
self.assertRaisesRegexp(ValueError, "Unable to find host",
|
||||
self.assertRaisesRegex(ValueError, "Unable to find host",
|
||||
self.inv.delete_host_by_ip, existing_hosts, ip)
|
||||
|
||||
def test_purge_invalid_hosts(self):
|
||||
@@ -309,7 +310,7 @@ class TestInventory(unittest.TestCase):
|
||||
|
||||
def test_range2ips_incorrect_range(self):
|
||||
host_range = ['10.90.0.4-a.9b.c.e']
|
||||
self.assertRaisesRegexp(Exception, "Range of ip_addresses isn't valid",
|
||||
self.assertRaisesRegex(Exception, "Range of ip_addresses isn't valid",
|
||||
self.inv.range2ips, host_range)
|
||||
|
||||
def test_build_hostnames_different_ips_add_one(self):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[tox]
|
||||
minversion = 1.6
|
||||
skipsdist = True
|
||||
envlist = pep8, py27
|
||||
envlist = pep8, py33
|
||||
|
||||
[testenv]
|
||||
whitelist_externals = py.test
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
```
|
||||
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 don’t 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/tutorial/layer2/tutorial). It deploys MetalLB into kubernetes and sets up a layer 2 loadbalancer.
|
||||
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,6 +1,12 @@
|
||||
---
|
||||
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"
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
---
|
||||
- name: "Kubernetes Apps | Check cluster settings for MetalLB"
|
||||
fail:
|
||||
msg: "MetalLB require kube_proxy_strict_arp = true, see https://github.com/danderson/metallb/issues/153#issuecomment-518651132"
|
||||
when:
|
||||
- "kube_proxy_mode == 'ipvs' and not kube_proxy_strict_arp"
|
||||
- name: "Kubernetes Apps | Lay Down MetalLB"
|
||||
become: true
|
||||
template: { src: "{{ item }}.j2", dest: "{{ kube_config_dir }}/{{ item }}" }
|
||||
|
||||
@@ -8,6 +8,14 @@ data:
|
||||
config: |
|
||||
address-pools:
|
||||
- name: loadbalanced
|
||||
protocol: layer2
|
||||
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 %}
|
||||
|
||||
@@ -115,7 +115,7 @@ roleRef:
|
||||
kind: Role
|
||||
name: config-watcher
|
||||
---
|
||||
apiVersion: apps/v1beta2
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
namespace: metallb-system
|
||||
@@ -169,7 +169,7 @@ spec:
|
||||
- net_raw
|
||||
|
||||
---
|
||||
apiVersion: apps/v1beta2
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
namespace: metallb-system
|
||||
|
||||
15
contrib/misc/clusteradmin-rbac.yml
Normal file
15
contrib/misc/clusteradmin-rbac.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: kubernetes-dashboard
|
||||
labels:
|
||||
k8s-app: kubernetes-dashboard
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kubernetes-dashboard
|
||||
namespace: kube-system
|
||||
@@ -21,7 +21,7 @@ You can specify a `default_release` for apt on Debian/Ubuntu by overriding this
|
||||
glusterfs_ppa_use: yes
|
||||
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](http://www.gluster.org/community/documentation/index.php/Getting_started_install) 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](https://docs.gluster.org/en/latest/Quick-Start-Guide/Quickstart/) for more info.
|
||||
|
||||
## Dependencies
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
- name: Include OS-specific variables.
|
||||
include_vars: "{{ ansible_os_family }}.yml"
|
||||
|
||||
# Instal xfs package
|
||||
# Install xfs package
|
||||
- name: install xfs Debian
|
||||
apt: name=xfsprogs state=present
|
||||
when: ansible_os_family == "Debian"
|
||||
@@ -36,7 +36,7 @@
|
||||
- "{{ gluster_brick_dir }}"
|
||||
- "{{ gluster_mount_dir }}"
|
||||
|
||||
- name: Configure Gluster volume.
|
||||
- name: Configure Gluster volume with replicas
|
||||
gluster_volume:
|
||||
state: present
|
||||
name: "{{ gluster_brick_name }}"
|
||||
@@ -46,6 +46,18 @@
|
||||
host: "{{ inventory_hostname }}"
|
||||
force: yes
|
||||
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
|
||||
mount:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
- name: Kubernetes Apps | Lay Down k8s GlusterFS Endpoint and PV
|
||||
template: src={{item.file}} dest={{kube_config_dir}}/{{item.dest}}
|
||||
template:
|
||||
src: "{{ item.file }}"
|
||||
dest: "{{ kube_config_dir }}/{{ item.dest }}"
|
||||
with_items:
|
||||
- { file: glusterfs-kubernetes-endpoint.json.j2, type: ep, dest: glusterfs-kubernetes-endpoint.json}
|
||||
- { file: glusterfs-kubernetes-pv.yml.j2, type: pv, dest: glusterfs-kubernetes-pv.yml}
|
||||
|
||||
@@ -14,3 +14,5 @@ ansible-playbook --ask-become -i inventory/sample/k8s_heketi_inventory.yml contr
|
||||
```
|
||||
ansible-playbook --ask-become -i inventory/sample/k8s_heketi_inventory.yml contrib/network-storage/heketi/heketi-tear-down.yml
|
||||
```
|
||||
|
||||
Add `--extra-vars "heketi_remove_lvm=true"` to the command above to remove LVM packages from the system
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
register: "initial_heketi_state"
|
||||
changed_when: false
|
||||
command: "{{ bin_dir }}/kubectl get services,deployments,pods --selector=deploy-heketi --output=json"
|
||||
|
||||
- name: "Bootstrap heketi."
|
||||
when:
|
||||
- "(initial_heketi_state.stdout|from_json|json_query(\"items[?kind=='Service']\"))|length == 0"
|
||||
@@ -16,15 +17,20 @@
|
||||
register: "initial_heketi_pod"
|
||||
command: "{{ bin_dir }}/kubectl get pods --selector=deploy-heketi=pod,glusterfs=heketi-pod,name=deploy-heketi --output=json"
|
||||
changed_when: false
|
||||
|
||||
- name: "Ensure heketi bootstrap pod is up."
|
||||
assert:
|
||||
that: "(initial_heketi_pod.stdout|from_json|json_query('items[*]'))|length == 1"
|
||||
- set_fact:
|
||||
|
||||
- name: Store the initial heketi pod name
|
||||
set_fact:
|
||||
initial_heketi_pod_name: "{{ initial_heketi_pod.stdout|from_json|json_query(\"items[*].metadata.name|[0]\") }}"
|
||||
|
||||
- name: "Test heketi topology."
|
||||
changed_when: false
|
||||
register: "heketi_topology"
|
||||
command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology info --json"
|
||||
|
||||
- name: "Load heketi topology."
|
||||
when: "heketi_topology.stdout|from_json|json_query(\"clusters[*].nodes[*]\")|flatten|length == 0"
|
||||
include_tasks: "bootstrap/topology.yml"
|
||||
@@ -42,6 +48,7 @@
|
||||
command: "{{ bin_dir }}/kubectl get secrets,endpoints,services,jobs --output=json"
|
||||
changed_when: false
|
||||
register: "heketi_storage_state"
|
||||
|
||||
# ensure endpoints actually exist before trying to move database data to it
|
||||
- name: "Create heketi storage."
|
||||
include_tasks: "bootstrap/storage.yml"
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
---
|
||||
- register: "label_present"
|
||||
- name: Get storage nodes
|
||||
register: "label_present"
|
||||
command: "{{ bin_dir }}/kubectl get node --selector=storagenode=glusterfs,kubernetes.io/hostname={{ node }} --ignore-not-found=true"
|
||||
changed_when: false
|
||||
|
||||
- name: "Assign storage label"
|
||||
when: "label_present.stdout_lines|length == 0"
|
||||
command: "{{ bin_dir }}/kubectl label node {{ node }} storagenode=glusterfs"
|
||||
- register: "label_present"
|
||||
|
||||
- name: Get storage nodes again
|
||||
register: "label_present"
|
||||
command: "{{ bin_dir }}/kubectl get node --selector=storagenode=glusterfs,kubernetes.io/hostname={{ node }} --ignore-not-found=true"
|
||||
changed_when: false
|
||||
- assert: { that: "label_present|length > 0", msg: "Node {{ node }} has not been assigned with label storagenode=glusterfs." }
|
||||
|
||||
- name: Ensure the label has been set
|
||||
assert:
|
||||
that: "label_present|length > 0"
|
||||
msg: "Node {{ node }} has not been assigned with label storagenode=glusterfs."
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
---
|
||||
- name: "Kubernetes Apps | Lay Down Heketi"
|
||||
become: true
|
||||
template: { src: "heketi-deployment.json.j2", dest: "{{ kube_config_dir }}/heketi-deployment.json" }
|
||||
template:
|
||||
src: "heketi-deployment.json.j2"
|
||||
dest: "{{ kube_config_dir }}/heketi-deployment.json"
|
||||
register: "rendering"
|
||||
|
||||
- name: "Kubernetes Apps | Install and configure Heketi"
|
||||
kube:
|
||||
name: "GlusterFS"
|
||||
kubectl: "{{ bin_dir }}/kubectl"
|
||||
filename: "{{ kube_config_dir }}/heketi-deployment.json"
|
||||
state: "{{ rendering.changed | ternary('latest', 'present') }}"
|
||||
|
||||
- name: "Ensure heketi is up and running."
|
||||
changed_when: false
|
||||
register: "heketi_state"
|
||||
vars:
|
||||
heketi_state: { stdout: "{}" }
|
||||
heketi_state:
|
||||
stdout: "{}"
|
||||
pods_query: "items[?kind=='Pod'].status.conditions|[0][?type=='Ready'].status|[0]"
|
||||
deployments_query: "items[?kind=='Deployment'].status.conditions|[0][?type=='Available'].status|[0]"
|
||||
command: "{{ bin_dir }}/kubectl get deployments,pods --selector=glusterfs --output=json"
|
||||
@@ -22,5 +27,7 @@
|
||||
- "heketi_state.stdout|from_json|json_query(deployments_query) == 'True'"
|
||||
retries: 60
|
||||
delay: 5
|
||||
- set_fact:
|
||||
|
||||
- name: Set the Heketi pod name
|
||||
set_fact:
|
||||
heketi_pod_name: "{{ heketi_state.stdout|from_json|json_query(\"items[?kind=='Pod'].metadata.name|[0]\") }}"
|
||||
|
||||
@@ -1,31 +1,44 @@
|
||||
---
|
||||
- register: "clusterrolebinding_state"
|
||||
- name: Get clusterrolebindings
|
||||
register: "clusterrolebinding_state"
|
||||
command: "{{ bin_dir }}/kubectl get clusterrolebinding heketi-gluster-admin -o=name --ignore-not-found=true"
|
||||
changed_when: false
|
||||
|
||||
- name: "Kubernetes Apps | Deploy cluster role binding."
|
||||
when: "clusterrolebinding_state.stdout == \"\""
|
||||
command: "{{ bin_dir }}/kubectl create clusterrolebinding heketi-gluster-admin --clusterrole=edit --serviceaccount=default:heketi-service-account"
|
||||
- register: "clusterrolebinding_state"
|
||||
|
||||
- name: Get clusterrolebindings again
|
||||
register: "clusterrolebinding_state"
|
||||
command: "{{ bin_dir }}/kubectl get clusterrolebinding heketi-gluster-admin -o=name --ignore-not-found=true"
|
||||
changed_when: false
|
||||
- assert:
|
||||
|
||||
- name: Make sure that clusterrolebindings are present now
|
||||
assert:
|
||||
that: "clusterrolebinding_state.stdout != \"\""
|
||||
msg: "Cluster role binding is not present."
|
||||
|
||||
- register: "secret_state"
|
||||
- name: Get the heketi-config-secret secret
|
||||
register: "secret_state"
|
||||
command: "{{ bin_dir }}/kubectl get secret heketi-config-secret -o=name --ignore-not-found=true"
|
||||
changed_when: false
|
||||
|
||||
- name: "Render Heketi secret configuration."
|
||||
become: true
|
||||
template:
|
||||
src: "heketi.json.j2"
|
||||
dest: "{{ kube_config_dir }}/heketi.json"
|
||||
|
||||
- name: "Deploy Heketi config secret"
|
||||
when: "secret_state.stdout == \"\""
|
||||
command: "{{ bin_dir }}/kubectl create secret generic heketi-config-secret --from-file={{ kube_config_dir }}/heketi.json"
|
||||
- register: "secret_state"
|
||||
|
||||
- name: Get the heketi-config-secret secret again
|
||||
register: "secret_state"
|
||||
command: "{{ bin_dir }}/kubectl get secret heketi-config-secret -o=name --ignore-not-found=true"
|
||||
changed_when: false
|
||||
- assert:
|
||||
|
||||
- name: Make sure the heketi-config-secret secret exists now
|
||||
assert:
|
||||
that: "secret_state.stdout != \"\""
|
||||
msg: "Heketi config secret is not present."
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"kind": "DaemonSet",
|
||||
"apiVersion": "extensions/v1beta1",
|
||||
"apiVersion": "apps/v1",
|
||||
"metadata": {
|
||||
"name": "glusterfs",
|
||||
"labels": {
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "Deployment",
|
||||
"apiVersion": "extensions/v1beta1",
|
||||
"apiVersion": "apps/v1",
|
||||
"metadata": {
|
||||
"name": "deploy-heketi",
|
||||
"labels": {
|
||||
@@ -56,7 +56,7 @@
|
||||
"serviceAccountName": "heketi-service-account",
|
||||
"containers": [
|
||||
{
|
||||
"image": "heketi/heketi:7",
|
||||
"image": "heketi/heketi:9",
|
||||
"imagePullPolicy": "Always",
|
||||
"name": "deploy-heketi",
|
||||
"env": [
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "Deployment",
|
||||
"apiVersion": "extensions/v1beta1",
|
||||
"apiVersion": "apps/v1",
|
||||
"metadata": {
|
||||
"name": "heketi",
|
||||
"labels": {
|
||||
@@ -68,7 +68,7 @@
|
||||
"serviceAccountName": "heketi-service-account",
|
||||
"containers": [
|
||||
{
|
||||
"image": "heketi/heketi:7",
|
||||
"image": "heketi/heketi:9",
|
||||
"imagePullPolicy": "Always",
|
||||
"name": "heketi",
|
||||
"env": [
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
{
|
||||
"addresses": [
|
||||
{
|
||||
"ip": "{{ hostvars[node]['ansible_facts']['default_ipv4']['address'] }}"
|
||||
"ip": "{{ hostvars[node].ip }}"
|
||||
}
|
||||
],
|
||||
"ports": [
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"{{ node }}"
|
||||
],
|
||||
"storage": [
|
||||
"{{ hostvars[node]['ansible_facts']['default_ipv4']['address'] }}"
|
||||
"{{ hostvars[node].ip }}"
|
||||
]
|
||||
},
|
||||
"zone": 1
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
---
|
||||
heketi_remove_lvm: false
|
||||
@@ -14,6 +14,8 @@
|
||||
when: "ansible_os_family == 'Debian'"
|
||||
|
||||
- name: "Get volume group information."
|
||||
environment:
|
||||
PATH: "{{ ansible_env.PATH }}:/sbin" # Make sure we can workaround RH / CentOS conservative path management
|
||||
become: true
|
||||
shell: "pvs {{ disk_volume_device_1 }} --option vg_name | tail -n+2"
|
||||
register: "volume_groups"
|
||||
@@ -21,12 +23,16 @@
|
||||
changed_when: false
|
||||
|
||||
- name: "Remove volume groups."
|
||||
environment:
|
||||
PATH: "{{ ansible_env.PATH }}:/sbin" # Make sure we can workaround RH / CentOS conservative path management
|
||||
become: true
|
||||
command: "vgremove {{ volume_group }} --yes"
|
||||
with_items: "{{ volume_groups.stdout_lines }}"
|
||||
loop_control: { loop_var: "volume_group" }
|
||||
|
||||
- name: "Remove physical volume from cluster disks."
|
||||
environment:
|
||||
PATH: "{{ ansible_env.PATH }}:/sbin" # Make sure we can workaround RH / CentOS conservative path management
|
||||
become: true
|
||||
command: "pvremove {{ disk_volume_device_1 }} --yes"
|
||||
ignore_errors: true
|
||||
@@ -36,11 +42,11 @@
|
||||
yum:
|
||||
name: "lvm2"
|
||||
state: "absent"
|
||||
when: "ansible_os_family == 'RedHat'"
|
||||
when: "ansible_os_family == 'RedHat' and heketi_remove_lvm"
|
||||
|
||||
- name: "Remove lvm utils (Debian)"
|
||||
become: true
|
||||
apt:
|
||||
name: "lvm2"
|
||||
state: "absent"
|
||||
when: "ansible_os_family == 'Debian'"
|
||||
when: "ansible_os_family == 'Debian' and heketi_remove_lvm"
|
||||
|
||||
@@ -10,7 +10,7 @@ This project will create:
|
||||
* AWS ELB in the Public Subnet for accessing the Kubernetes API from the internet
|
||||
|
||||
**Requirements**
|
||||
- Terraform 0.8.7 or newer
|
||||
- Terraform 0.12.0 or newer
|
||||
|
||||
**How to Use:**
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
terraform {
|
||||
required_version = ">= 0.8.7"
|
||||
required_version = ">= 0.12.0"
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
@@ -16,7 +16,7 @@ data "aws_availability_zones" "available" {}
|
||||
*/
|
||||
|
||||
module "aws-vpc" {
|
||||
source = "modules/vpc"
|
||||
source = "./modules/vpc"
|
||||
|
||||
aws_cluster_name = "${var.aws_cluster_name}"
|
||||
aws_vpc_cidr_block = "${var.aws_vpc_cidr_block}"
|
||||
@@ -27,7 +27,7 @@ module "aws-vpc" {
|
||||
}
|
||||
|
||||
module "aws-elb" {
|
||||
source = "modules/elb"
|
||||
source = "./modules/elb"
|
||||
|
||||
aws_cluster_name = "${var.aws_cluster_name}"
|
||||
aws_vpc_id = "${module.aws-vpc.aws_vpc_id}"
|
||||
@@ -39,7 +39,7 @@ module "aws-elb" {
|
||||
}
|
||||
|
||||
module "aws-iam" {
|
||||
source = "modules/iam"
|
||||
source = "./modules/iam"
|
||||
|
||||
aws_cluster_name = "${var.aws_cluster_name}"
|
||||
}
|
||||
@@ -57,7 +57,7 @@ resource "aws_instance" "bastion-server" {
|
||||
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)}"
|
||||
|
||||
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}"
|
||||
|
||||
@@ -82,7 +82,7 @@ resource "aws_instance" "k8s-master" {
|
||||
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)}"
|
||||
|
||||
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}"
|
||||
key_name = "${var.AWS_SSH_KEY_NAME}"
|
||||
@@ -109,7 +109,7 @@ resource "aws_instance" "k8s-etcd" {
|
||||
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)}"
|
||||
|
||||
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}"
|
||||
|
||||
@@ -129,7 +129,7 @@ resource "aws_instance" "k8s-worker" {
|
||||
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)}"
|
||||
|
||||
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}"
|
||||
key_name = "${var.AWS_SSH_KEY_NAME}"
|
||||
@@ -148,7 +148,7 @@ resource "aws_instance" "k8s-worker" {
|
||||
data "template_file" "inventory" {
|
||||
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))}"
|
||||
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.*.tags.Name, aws_instance.k8s-worker.*.private_ip))}"
|
||||
@@ -165,7 +165,7 @@ resource "null_resource" "inventories" {
|
||||
command = "echo '${data.template_file.inventory.rendered}' > ${var.inventory_file}"
|
||||
}
|
||||
|
||||
triggers {
|
||||
triggers = {
|
||||
template = "${data.template_file.inventory.rendered}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ resource "aws_security_group_rule" "aws-allow-api-egress" {
|
||||
# Create a new AWS ELB for K8S API
|
||||
resource "aws_elb" "aws-elb-api" {
|
||||
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}"]
|
||||
|
||||
listener {
|
||||
|
||||
@@ -3,15 +3,15 @@ output "aws_vpc_id" {
|
||||
}
|
||||
|
||||
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" {
|
||||
value = ["${aws_subnet.cluster-vpc-subnets-public.*.id}"]
|
||||
value = aws_subnet.cluster-vpc-subnets-public.*.id
|
||||
}
|
||||
|
||||
output "aws_security_group" {
|
||||
value = ["${aws_security_group.kubernetes.*.id}"]
|
||||
value = aws_security_group.kubernetes.*.id
|
||||
}
|
||||
|
||||
output "default_tags" {
|
||||
|
||||
1
contrib/terraform/openstack/.gitignore
vendored
1
contrib/terraform/openstack/.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
.terraform
|
||||
*.tfvars
|
||||
!sample-inventory\/cluster.tfvars
|
||||
*.tfstate
|
||||
*.tfstate.backup
|
||||
|
||||
@@ -16,14 +16,13 @@ most modern installs of OpenStack that support the basic services.
|
||||
- [ELASTX](https://elastx.se/)
|
||||
- [EnterCloudSuite](https://www.entercloudsuite.com/)
|
||||
- [FugaCloud](https://fuga.cloud/)
|
||||
- [Open Telekom Cloud](https://cloud.telekom.de/) : requires to set the variable `wait_for_floatingip = "true"` in your cluster.tfvars
|
||||
- [OVH](https://www.ovh.com/)
|
||||
- [Rackspace](https://www.rackspace.com/)
|
||||
- [Ultimum](https://ultimum.io/)
|
||||
- [VexxHost](https://vexxhost.com/)
|
||||
- [Zetta](https://www.zetta.io/)
|
||||
|
||||
### Known incompatible public clouds
|
||||
- T-Systems / Open Telekom Cloud: requires `wait_until_associated`
|
||||
|
||||
## Approach
|
||||
The terraform configuration inspects variables found in
|
||||
@@ -70,7 +69,7 @@ binaries available on hyperkube v1.4.3_coreos.0 or higher.
|
||||
|
||||
## Requirements
|
||||
|
||||
- [Install Terraform](https://www.terraform.io/intro/getting-started/install.html)
|
||||
- [Install Terraform](https://www.terraform.io/intro/getting-started/install.html) 0.12 or later
|
||||
- [Install Ansible](http://docs.ansible.com/ansible/latest/intro_installation.html)
|
||||
- you already have a suitable OS image in Glance
|
||||
- you already have a floating IP pool created
|
||||
@@ -220,12 +219,14 @@ set OS_PROJECT_DOMAIN_NAME=Default
|
||||
The construction of the cluster is driven by values found in
|
||||
[variables.tf](variables.tf).
|
||||
|
||||
For your cluster, edit `inventory/$CLUSTER/cluster.tf`.
|
||||
For your cluster, edit `inventory/$CLUSTER/cluster.tfvars`.
|
||||
|
||||
|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`. |
|
||||
|`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_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. |
|
||||
|`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 |
|
||||
@@ -246,6 +247,13 @@ For your cluster, edit `inventory/$CLUSTER/cluster.tf`.
|
||||
|`master_allowed_remote_ips` | List of CIDR blocks allowed to initiate an API connection, `["0.0.0.0/0"]` 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 |
|
||||
|`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 |
|
||||
|
||||
#### Terraform state files
|
||||
|
||||
@@ -276,7 +284,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
|
||||
issued from your cluster's inventory directory (`inventory/$CLUSTER`):
|
||||
```ShellSession
|
||||
$ terraform apply -var-file=cluster.tf ../../contrib/terraform/openstack
|
||||
$ terraform apply -var-file=cluster.tfvars ../../contrib/terraform/openstack
|
||||
```
|
||||
|
||||
if you chose to create a bastion host, this script will create
|
||||
@@ -290,7 +298,7 @@ pick it up automatically.
|
||||
You can destroy your new cluster with the following command issued from the cluster's inventory directory:
|
||||
|
||||
```ShellSession
|
||||
$ terraform destroy -var-file=cluster.tf ../../contrib/terraform/openstack
|
||||
$ terraform destroy -var-file=cluster.tfvars ../../contrib/terraform/openstack
|
||||
```
|
||||
|
||||
If you've started the Ansible run, it may also be a good idea to do some manual cleanup:
|
||||
@@ -325,6 +333,30 @@ $ ssh-add ~/.ssh/id_rsa
|
||||
|
||||
If you have deployed and destroyed a previous iteration of your cluster, you will need to clear out any stale keys from your SSH "known hosts" file ( `~/.ssh/known_hosts`).
|
||||
|
||||
#### Metadata variables
|
||||
|
||||
The [python script](../terraform.py) that reads the
|
||||
generated`.tfstate` file to generate a dynamic inventory recognizes
|
||||
some variables within a "metadata" block, defined in a "resource"
|
||||
block (example):
|
||||
|
||||
```
|
||||
resource "openstack_compute_instance_v2" "example" {
|
||||
...
|
||||
metadata {
|
||||
ssh_user = "ubuntu"
|
||||
prefer_ipv6 = true
|
||||
python_bin = "/usr/bin/python3"
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
As the example shows, these let you define the SSH username for
|
||||
Ansible, a Python binary which is needed by Ansible if
|
||||
`/usr/bin/python` doesn't exist, and whether the IPv6 address of the
|
||||
instance should be preferred over IPv4.
|
||||
|
||||
#### Bastion host
|
||||
|
||||
Bastion access will be determined by:
|
||||
@@ -391,6 +423,14 @@ kube_network_plugin: flannel
|
||||
# For Container Linux by CoreOS:
|
||||
resolvconf_mode: host_resolvconf
|
||||
```
|
||||
- Set max amount of attached cinder volume per host (default 256)
|
||||
```
|
||||
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
|
||||
|
||||
|
||||
@@ -3,18 +3,19 @@ provider "openstack" {
|
||||
}
|
||||
|
||||
module "network" {
|
||||
source = "modules/network"
|
||||
source = "./modules/network"
|
||||
|
||||
external_net = "${var.external_net}"
|
||||
network_name = "${var.network_name}"
|
||||
subnet_cidr = "${var.subnet_cidr}"
|
||||
cluster_name = "${var.cluster_name}"
|
||||
dns_nameservers = "${var.dns_nameservers}"
|
||||
network_dns_domain = "${var.network_dns_domain}"
|
||||
use_neutron = "${var.use_neutron}"
|
||||
}
|
||||
|
||||
module "ips" {
|
||||
source = "modules/ips"
|
||||
source = "./modules/ips"
|
||||
|
||||
number_of_k8s_masters = "${var.number_of_k8s_masters}"
|
||||
number_of_k8s_masters_no_etcd = "${var.number_of_k8s_masters_no_etcd}"
|
||||
@@ -27,7 +28,7 @@ module "ips" {
|
||||
}
|
||||
|
||||
module "compute" {
|
||||
source = "modules/compute"
|
||||
source = "./modules/compute"
|
||||
|
||||
cluster_name = "${var.cluster_name}"
|
||||
az_list = "${var.az_list}"
|
||||
@@ -40,6 +41,11 @@ module "compute" {
|
||||
number_of_bastions = "${var.number_of_bastions}"
|
||||
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}"
|
||||
bastion_root_volume_size_in_gb = "${var.bastion_root_volume_size_in_gb}"
|
||||
etcd_root_volume_size_in_gb = "${var.etcd_root_volume_size_in_gb}"
|
||||
master_root_volume_size_in_gb = "${var.master_root_volume_size_in_gb}"
|
||||
node_root_volume_size_in_gb = "${var.node_root_volume_size_in_gb}"
|
||||
gfs_root_volume_size_in_gb = "${var.gfs_root_volume_size_in_gb}"
|
||||
gfs_volume_size_in_gb = "${var.gfs_volume_size_in_gb}"
|
||||
public_key_path = "${var.public_key_path}"
|
||||
image = "${var.image}"
|
||||
@@ -63,6 +69,9 @@ module "compute" {
|
||||
supplementary_master_groups = "${var.supplementary_master_groups}"
|
||||
supplementary_node_groups = "${var.supplementary_node_groups}"
|
||||
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}"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
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" {
|
||||
name = "kubernetes-${var.cluster_name}"
|
||||
public_key = "${chomp(file(var.public_key_path))}"
|
||||
@@ -22,20 +30,20 @@ resource "openstack_networking_secgroup_rule_v2" "k8s_master" {
|
||||
|
||||
resource "openstack_networking_secgroup_v2" "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"
|
||||
delete_default_rules = true
|
||||
}
|
||||
|
||||
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"
|
||||
ethertype = "IPv4"
|
||||
protocol = "tcp"
|
||||
port_range_min = "22"
|
||||
port_range_max = "22"
|
||||
remote_ip_prefix = "${var.bastion_allowed_remote_ips[count.index]}"
|
||||
security_group_id = "${openstack_networking_secgroup_v2.bastion.id}"
|
||||
security_group_id = "${openstack_networking_secgroup_v2.bastion[count.index].id}"
|
||||
}
|
||||
|
||||
resource "openstack_networking_secgroup_v2" "k8s" {
|
||||
@@ -87,9 +95,27 @@ resource "openstack_networking_secgroup_rule_v2" "worker" {
|
||||
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" {
|
||||
name = "${var.cluster_name}-bastion-${count.index+1}"
|
||||
count = "${var.number_of_bastions}"
|
||||
count = "${var.bastion_root_volume_size_in_gb == 0 ? var.number_of_bastions : 0}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_bastion}"
|
||||
key_pair = "${openstack_compute_keypair_v2.k8s.name}"
|
||||
@@ -99,23 +125,60 @@ resource "openstack_compute_instance_v2" "bastion" {
|
||||
}
|
||||
|
||||
security_groups = ["${openstack_networking_secgroup_v2.k8s.name}",
|
||||
"${openstack_networking_secgroup_v2.bastion.name}",
|
||||
"${element(openstack_networking_secgroup_v2.bastion.*.name, count.index)}",
|
||||
]
|
||||
|
||||
metadata = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "bastion"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
command = "sed s/USER/${var.ssh_user}/ contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${var.bastion_fips[0]}/ > contrib/terraform/group_vars/no-floating.yml"
|
||||
command = "sed s/USER/${var.ssh_user}/ ../../contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${var.bastion_fips[0]}/ > group_vars/no-floating.yml"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "bastion_custom_volume_size" {
|
||||
name = "${var.cluster_name}-bastion-${count.index+1}"
|
||||
count = "${var.bastion_root_volume_size_in_gb > 0 ? var.number_of_bastions : 0}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_bastion}"
|
||||
key_pair = "${openstack_compute_keypair_v2.k8s.name}"
|
||||
|
||||
block_device {
|
||||
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 {
|
||||
name = "${var.network_name}"
|
||||
}
|
||||
|
||||
security_groups = ["${openstack_networking_secgroup_v2.k8s.name}",
|
||||
"${element(openstack_networking_secgroup_v2.bastion.*.name, count.index)}",
|
||||
]
|
||||
|
||||
metadata = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "bastion"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
command = "sed s/USER/${var.ssh_user}/ ../../contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${var.bastion_fips[0]}/ > group_vars/no-floating.yml"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "k8s_master" {
|
||||
name = "${var.cluster_name}-k8s-master-${count.index+1}"
|
||||
count = "${var.number_of_k8s_masters}"
|
||||
count = "${var.master_root_volume_size_in_gb == 0 ? var.number_of_k8s_masters : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_master}"
|
||||
@@ -129,20 +192,72 @@ resource "openstack_compute_instance_v2" "k8s_master" {
|
||||
"${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 = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "etcd,kube-master,${var.supplementary_master_groups},k8s-cluster,vault"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
|
||||
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)}/ > contrib/terraform/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_custom_volume_size" {
|
||||
name = "${var.cluster_name}-k8s-master-${count.index+1}"
|
||||
count = "${var.master_root_volume_size_in_gb > 0 ? var.number_of_k8s_masters : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_master}"
|
||||
key_pair = "${openstack_compute_keypair_v2.k8s.name}"
|
||||
|
||||
block_device {
|
||||
uuid = "${data.openstack_images_image_v2.vm_image.id}"
|
||||
source_type = "image"
|
||||
volume_size = "${var.master_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_master.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 = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "etcd,kube-master,${var.supplementary_master_groups},k8s-cluster,vault"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "k8s_master_no_etcd" {
|
||||
name = "${var.cluster_name}-k8s-master-ne-${count.index+1}"
|
||||
count = "${var.number_of_k8s_masters_no_etcd}"
|
||||
count = "${var.master_root_volume_size_in_gb == 0 ? var.number_of_k8s_masters_no_etcd : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_master}"
|
||||
@@ -156,20 +271,72 @@ resource "openstack_compute_instance_v2" "k8s_master_no_etcd" {
|
||||
"${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 = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "kube-master,${var.supplementary_master_groups},k8s-cluster,vault"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
|
||||
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)}/ > contrib/terraform/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_custom_volume_size" {
|
||||
name = "${var.cluster_name}-k8s-master-ne-${count.index+1}"
|
||||
count = "${var.master_root_volume_size_in_gb > 0 ? var.number_of_k8s_masters_no_etcd : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_master}"
|
||||
key_pair = "${openstack_compute_keypair_v2.k8s.name}"
|
||||
|
||||
block_device {
|
||||
uuid = "${data.openstack_images_image_v2.vm_image.id}"
|
||||
source_type = "image"
|
||||
volume_size = "${var.master_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_master.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 = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "kube-master,${var.supplementary_master_groups},k8s-cluster,vault"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "etcd" {
|
||||
name = "${var.cluster_name}-etcd-${count.index+1}"
|
||||
count = "${var.number_of_etcd}"
|
||||
count = "${var.etcd_root_volume_size_in_gb == 0 ? var.number_of_etcd : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_etcd}"
|
||||
@@ -181,16 +348,62 @@ resource "openstack_compute_instance_v2" "etcd" {
|
||||
|
||||
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 = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "etcd,vault,no-floating"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "etcd_custom_volume_size" {
|
||||
name = "${var.cluster_name}-etcd-${count.index+1}"
|
||||
count = "${var.etcd_root_volume_size_in_gb > 0 ? var.number_of_etcd : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_etcd}"
|
||||
key_pair = "${openstack_compute_keypair_v2.k8s.name}"
|
||||
|
||||
block_device {
|
||||
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 {
|
||||
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_etcd[0]] : []
|
||||
content {
|
||||
group = "${openstack_compute_servergroup_v2.k8s_etcd[0].id}"
|
||||
}
|
||||
}
|
||||
|
||||
metadata = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "etcd,vault,no-floating"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip" {
|
||||
name = "${var.cluster_name}-k8s-master-nf-${count.index+1}"
|
||||
count = "${var.number_of_k8s_masters_no_floating_ip}"
|
||||
count = "${var.master_root_volume_size_in_gb == 0 ? var.number_of_k8s_masters_no_floating_ip : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_master}"
|
||||
@@ -204,16 +417,64 @@ resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip" {
|
||||
"${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 = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "etcd,kube-master,${var.supplementary_master_groups},k8s-cluster,vault,no-floating"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip_custom_volume_size" {
|
||||
name = "${var.cluster_name}-k8s-master-nf-${count.index+1}"
|
||||
count = "${var.master_root_volume_size_in_gb > 0 ? var.number_of_k8s_masters_no_floating_ip : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_master}"
|
||||
key_pair = "${openstack_compute_keypair_v2.k8s.name}"
|
||||
|
||||
block_device {
|
||||
uuid = "${data.openstack_images_image_v2.vm_image.id}"
|
||||
source_type = "image"
|
||||
volume_size = "${var.master_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_master.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 = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "etcd,kube-master,${var.supplementary_master_groups},k8s-cluster,vault,no-floating"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip_no_etcd" {
|
||||
name = "${var.cluster_name}-k8s-master-ne-nf-${count.index+1}"
|
||||
count = "${var.number_of_k8s_masters_no_floating_ip_no_etcd}"
|
||||
count = "${var.master_root_volume_size_in_gb == 0 ? var.number_of_k8s_masters_no_floating_ip_no_etcd : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_master}"
|
||||
@@ -227,16 +488,64 @@ resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip_no_etcd" {
|
||||
"${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 = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "kube-master,${var.supplementary_master_groups},k8s-cluster,vault,no-floating"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip_no_etcd_custom_volume_size" {
|
||||
name = "${var.cluster_name}-k8s-master-ne-nf-${count.index+1}"
|
||||
count = "${var.master_root_volume_size_in_gb > 0 ? var.number_of_k8s_masters_no_floating_ip_no_etcd : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_master}"
|
||||
key_pair = "${openstack_compute_keypair_v2.k8s.name}"
|
||||
|
||||
block_device {
|
||||
uuid = "${data.openstack_images_image_v2.vm_image.id}"
|
||||
source_type = "image"
|
||||
volume_size = "${var.master_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_master.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 = {
|
||||
ssh_user = "${var.ssh_user}"
|
||||
kubespray_groups = "kube-master,${var.supplementary_master_groups},k8s-cluster,vault,no-floating"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "k8s_node" {
|
||||
name = "${var.cluster_name}-k8s-node-${count.index+1}"
|
||||
count = "${var.number_of_k8s_nodes}"
|
||||
count = "${var.node_root_volume_size_in_gb == 0 ? var.number_of_k8s_nodes : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_node}"
|
||||
@@ -250,20 +559,72 @@ resource "openstack_compute_instance_v2" "k8s_node" {
|
||||
"${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,${var.supplementary_node_groups}"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
|
||||
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)}/ > contrib/terraform/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_custom_volume_size" {
|
||||
name = "${var.cluster_name}-k8s-node-${count.index+1}"
|
||||
count = "${var.node_root_volume_size_in_gb > 0 ? var.number_of_k8s_nodes : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_node}"
|
||||
key_pair = "${openstack_compute_keypair_v2.k8s.name}"
|
||||
|
||||
block_device {
|
||||
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,${var.supplementary_node_groups}"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "k8s_node_no_floating_ip" {
|
||||
name = "${var.cluster_name}-k8s-node-nf-${count.index+1}"
|
||||
count = "${var.number_of_k8s_nodes_no_floating_ip}"
|
||||
count = "${var.node_root_volume_size_in_gb == 0 ? var.number_of_k8s_nodes_no_floating_ip : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_node}"
|
||||
@@ -277,47 +638,132 @@ resource "openstack_compute_instance_v2" "k8s_node_no_floating_ip" {
|
||||
"${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,no-floating,${var.supplementary_node_groups}"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_instance_v2" "k8s_node_no_floating_ip_custom_volume_size" {
|
||||
name = "${var.cluster_name}-k8s-node-nf-${count.index+1}"
|
||||
count = "${var.node_root_volume_size_in_gb > 0 ? var.number_of_k8s_nodes_no_floating_ip : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_k8s_node}"
|
||||
key_pair = "${openstack_compute_keypair_v2.k8s.name}"
|
||||
|
||||
block_device {
|
||||
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,no-floating,${var.supplementary_node_groups}"
|
||||
depends_on = "${var.network_id}"
|
||||
use_access_ip = "${var.use_access_ip}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "openstack_compute_floatingip_associate_v2" "bastion" {
|
||||
count = "${var.number_of_bastions}"
|
||||
count = "${var.bastion_root_volume_size_in_gb == 0 ? var.number_of_bastions : 0}"
|
||||
floating_ip = "${var.bastion_fips[count.index]}"
|
||||
instance_id = "${element(openstack_compute_instance_v2.bastion.*.id, count.index)}"
|
||||
wait_until_associated = "${var.wait_for_floatingip}"
|
||||
}
|
||||
|
||||
resource "openstack_compute_floatingip_associate_v2" "bastion_custom_volume_size" {
|
||||
count = "${var.bastion_root_volume_size_in_gb > 0 ? var.number_of_bastions : 0}"
|
||||
floating_ip = "${var.bastion_fips[count.index]}"
|
||||
instance_id = "${element(openstack_compute_instance_v2.bastion_custom_volume_size.*.id, count.index)}"
|
||||
wait_until_associated = "${var.wait_for_floatingip}"
|
||||
}
|
||||
|
||||
resource "openstack_compute_floatingip_associate_v2" "k8s_master" {
|
||||
count = "${var.number_of_k8s_masters}"
|
||||
count = "${var.master_root_volume_size_in_gb == 0 ? var.number_of_k8s_masters : 0}"
|
||||
instance_id = "${element(openstack_compute_instance_v2.k8s_master.*.id, count.index)}"
|
||||
floating_ip = "${var.k8s_master_fips[count.index]}"
|
||||
wait_until_associated = "${var.wait_for_floatingip}"
|
||||
}
|
||||
|
||||
resource "openstack_compute_floatingip_associate_v2" "k8s_master_custom_volume_size" {
|
||||
count = "${var.master_root_volume_size_in_gb > 0 ? var.number_of_k8s_masters : 0}"
|
||||
instance_id = "${element(openstack_compute_instance_v2.k8s_master_custom_volume_size.*.id, count.index)}"
|
||||
floating_ip = "${var.k8s_master_fips[count.index]}"
|
||||
wait_until_associated = "${var.wait_for_floatingip}"
|
||||
}
|
||||
|
||||
resource "openstack_compute_floatingip_associate_v2" "k8s_master_no_etcd" {
|
||||
count = "${var.number_of_k8s_masters_no_etcd}"
|
||||
count = "${var.master_root_volume_size_in_gb == 0 ? var.number_of_k8s_masters_no_etcd : 0}"
|
||||
instance_id = "${element(openstack_compute_instance_v2.k8s_master_no_etcd.*.id, count.index)}"
|
||||
floating_ip = "${var.k8s_master_no_etcd_fips[count.index]}"
|
||||
}
|
||||
|
||||
resource "openstack_compute_floatingip_associate_v2" "k8s_master_no_etcd_custom_volume_size" {
|
||||
count = "${var.master_root_volume_size_in_gb > 0 ? var.number_of_k8s_masters_no_etcd : 0}"
|
||||
instance_id = "${element(openstack_compute_instance_v2.k8s_master_no_etcd_custom_volume_size.*.id, count.index)}"
|
||||
floating_ip = "${var.k8s_master_no_etcd_fips[count.index]}"
|
||||
}
|
||||
|
||||
resource "openstack_compute_floatingip_associate_v2" "k8s_node" {
|
||||
count = "${var.number_of_k8s_nodes}"
|
||||
count = "${var.node_root_volume_size_in_gb == 0 ? var.number_of_k8s_nodes : 0}"
|
||||
floating_ip = "${var.k8s_node_fips[count.index]}"
|
||||
instance_id = "${element(openstack_compute_instance_v2.k8s_node.*.id, count.index)}"
|
||||
wait_until_associated = "${var.wait_for_floatingip}"
|
||||
}
|
||||
|
||||
resource "openstack_compute_floatingip_associate_v2" "k8s_node_custom_volume_size" {
|
||||
count = "${var.node_root_volume_size_in_gb > 0 ? var.number_of_k8s_nodes : 0}"
|
||||
floating_ip = "${var.k8s_node_fips[count.index]}"
|
||||
instance_id = "${element(openstack_compute_instance_v2.k8s_node_custom_volume_size.*.id, count.index)}"
|
||||
wait_until_associated = "${var.wait_for_floatingip}"
|
||||
}
|
||||
|
||||
resource "openstack_blockstorage_volume_v2" "glusterfs_volume" {
|
||||
name = "${var.cluster_name}-glusterfs_volume-${count.index+1}"
|
||||
count = "${var.number_of_gfs_nodes_no_floating_ip}"
|
||||
count = "${var.gfs_root_volume_size_in_gb == 0 ? var.number_of_gfs_nodes_no_floating_ip : 0}"
|
||||
description = "Non-ephemeral volume for GlusterFS"
|
||||
size = "${var.gfs_volume_size_in_gb}"
|
||||
}
|
||||
|
||||
resource "openstack_blockstorage_volume_v2" "glusterfs_volume_custom_volume_size" {
|
||||
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}"
|
||||
description = "Non-ephemeral volume for GlusterFS"
|
||||
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}"
|
||||
count = "${var.gfs_root_volume_size_in_gb == 0 ? var.number_of_gfs_nodes_no_floating_ip : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image_gfs}"
|
||||
flavor_id = "${var.flavor_gfs_node}"
|
||||
@@ -329,15 +775,67 @@ resource "openstack_compute_instance_v2" "glusterfs_node_no_floating_ip" {
|
||||
|
||||
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_instance_v2" "glusterfs_node_no_floating_ip_custom_volume_size" {
|
||||
name = "${var.cluster_name}-gfs-node-nf-${count.index+1}"
|
||||
count = "${var.gfs_root_volume_size_in_gb > 0 ? var.number_of_gfs_nodes_no_floating_ip : 0}"
|
||||
availability_zone = "${element(var.az_list, count.index)}"
|
||||
image_name = "${var.image}"
|
||||
flavor_id = "${var.flavor_gfs_node}"
|
||||
key_pair = "${openstack_compute_keypair_v2.k8s.name}"
|
||||
|
||||
block_device {
|
||||
uuid = "${data.openstack_images_image_v2.gfs_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_volume_attach_v2" "glusterfs_volume" {
|
||||
count = "${var.number_of_gfs_nodes_no_floating_ip}"
|
||||
count = "${var.gfs_root_volume_size_in_gb == 0 ? var.number_of_gfs_nodes_no_floating_ip : 0}"
|
||||
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)}"
|
||||
}
|
||||
|
||||
resource "openstack_compute_volume_attach_v2" "glusterfs_volume_custom_root_volume_size" {
|
||||
count = "${var.gfs_root_volume_size_in_gb > 0 ? var.number_of_gfs_nodes_no_floating_ip : 0}"
|
||||
instance_id = "${element(openstack_compute_instance_v2.glusterfs_node_no_floating_ip_custom_volume_size.*.id, count.index)}"
|
||||
volume_id = "${element(openstack_blockstorage_volume_v2.glusterfs_volume_custom_volume_size.*.id, count.index)}"
|
||||
}
|
||||
|
||||
@@ -22,6 +22,16 @@ variable "number_of_bastions" {}
|
||||
|
||||
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 "public_key_path" {}
|
||||
@@ -82,6 +92,8 @@ variable "k8s_allowed_egress_ips" {
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "wait_for_floatingip" {}
|
||||
|
||||
variable "supplementary_master_groups" {
|
||||
default = ""
|
||||
}
|
||||
@@ -93,3 +105,9 @@ variable "supplementary_node_groups" {
|
||||
variable "worker_allowed_ports" {
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "use_access_ip" {}
|
||||
|
||||
variable "use_server_groups" {
|
||||
type = bool
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
resource "null_resource" "dummy_dependency" {
|
||||
triggers {
|
||||
triggers = {
|
||||
dependency_id = "${var.router_id}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
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" {
|
||||
value = ["${openstack_networking_floatingip_v2.k8s_master_no_etcd.*.address}"]
|
||||
value = "${openstack_networking_floatingip_v2.k8s_master_no_etcd[*].address}"
|
||||
}
|
||||
|
||||
output "k8s_node_fips" {
|
||||
value = ["${openstack_networking_floatingip_v2.k8s_node.*.address}"]
|
||||
value = "${openstack_networking_floatingip_v2.k8s_node[*].address}"
|
||||
}
|
||||
|
||||
output "bastion_fips" {
|
||||
value = ["${openstack_networking_floatingip_v2.bastion.*.address}"]
|
||||
value = "${openstack_networking_floatingip_v2.bastion[*].address}"
|
||||
}
|
||||
|
||||
@@ -8,13 +8,14 @@ resource "openstack_networking_router_v2" "k8s" {
|
||||
resource "openstack_networking_network_v2" "k8s" {
|
||||
name = "${var.network_name}"
|
||||
count = "${var.use_neutron}"
|
||||
dns_domain = var.network_dns_domain != null ? "${var.network_dns_domain}" : null
|
||||
admin_state_up = "true"
|
||||
}
|
||||
|
||||
resource "openstack_networking_subnet_v2" "k8s" {
|
||||
name = "${var.cluster_name}-internal-network"
|
||||
count = "${var.use_neutron}"
|
||||
network_id = "${openstack_networking_network_v2.k8s.id}"
|
||||
network_id = "${openstack_networking_network_v2.k8s[count.index].id}"
|
||||
cidr = "${var.subnet_cidr}"
|
||||
ip_version = 4
|
||||
dns_nameservers = "${var.dns_nameservers}"
|
||||
@@ -22,6 +23,6 @@ resource "openstack_networking_subnet_v2" "k8s" {
|
||||
|
||||
resource "openstack_networking_router_interface_v2" "k8s" {
|
||||
count = "${var.use_neutron}"
|
||||
router_id = "${openstack_networking_router_v2.k8s.id}"
|
||||
subnet_id = "${openstack_networking_subnet_v2.k8s.id}"
|
||||
router_id = "${openstack_networking_router_v2.k8s[count.index].id}"
|
||||
subnet_id = "${openstack_networking_subnet_v2.k8s[count.index].id}"
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ variable "external_net" {}
|
||||
|
||||
variable "network_name" {}
|
||||
|
||||
variable "network_dns_domain" {}
|
||||
|
||||
variable "cluster_name" {}
|
||||
|
||||
variable "dns_nameservers" {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# your Kubernetes cluster name here
|
||||
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
|
||||
public_key_path = "~/.ssh/id_rsa.pub"
|
||||
|
||||
@@ -44,6 +44,26 @@ variable "number_of_gfs_nodes_no_floating_ip" {
|
||||
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" {
|
||||
default = 75
|
||||
}
|
||||
@@ -55,12 +75,12 @@ variable "public_key_path" {
|
||||
|
||||
variable "image" {
|
||||
description = "the image to use"
|
||||
default = "ubuntu-14.04"
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "image_gfs" {
|
||||
description = "Glance image to use for GlusterFS"
|
||||
default = "ubuntu-16.04"
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "ssh_user" {
|
||||
@@ -103,6 +123,12 @@ variable "network_name" {
|
||||
default = "internal"
|
||||
}
|
||||
|
||||
variable "network_dns_domain" {
|
||||
description = "dns_domain for the internal network"
|
||||
type = "string"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "use_neutron" {
|
||||
description = "Use neutron"
|
||||
default = 1
|
||||
@@ -125,6 +151,11 @@ variable "floatingip_pool" {
|
||||
default = "external"
|
||||
}
|
||||
|
||||
variable "wait_for_floatingip" {
|
||||
description = "Terraform will poll the instance until the floating IP has been associated."
|
||||
default = "false"
|
||||
}
|
||||
|
||||
variable "external_net" {
|
||||
description = "uuid of the external/public network"
|
||||
}
|
||||
@@ -175,3 +206,11 @@ variable "worker_allowed_ports" {
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
variable "use_access_ip" {
|
||||
default = 1
|
||||
}
|
||||
|
||||
variable "use_server_groups" {
|
||||
default = false
|
||||
}
|
||||
@@ -38,7 +38,7 @@ now six total etcd replicas.
|
||||
|
||||
## 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.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.
|
||||
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.
|
||||
|
||||
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:
|
||||
https://support.packet.com/kb/articles/api-integrations
|
||||
|
||||
The Packet Project ID associated with the key will be set later in cluster.tf.
|
||||
The Packet Project ID associated with the key will be set later in cluster.tfvars.
|
||||
|
||||
For more information about the API, please see:
|
||||
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
|
||||
[variables.tf](variables.tf).
|
||||
|
||||
For your cluster, edit `inventory/$CLUSTER/cluster.tf`.
|
||||
For your cluster, edit `inventory/$CLUSTER/cluster.tfvars`.
|
||||
|
||||
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.
|
||||
@@ -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
|
||||
issued from your cluster's inventory directory (`inventory/$CLUSTER`):
|
||||
```ShellSession
|
||||
$ terraform apply -var-file=cluster.tf ../../contrib/terraform/packet
|
||||
$ terraform apply -var-file=cluster.tfvars ../../contrib/terraform/packet
|
||||
$ export ANSIBLE_HOST_KEY_CHECKING=False
|
||||
$ 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:
|
||||
|
||||
```ShellSession
|
||||
$ terraform destroy -var-file=cluster.tf ../../contrib/terraform/packet
|
||||
$ terraform destroy -var-file=cluster.tfvars ../../contrib/terraform/packet
|
||||
```
|
||||
|
||||
If you've started the Ansible run, it may also be a good idea to do some manual cleanup:
|
||||
|
||||
@@ -4,59 +4,60 @@ provider "packet" {
|
||||
}
|
||||
|
||||
resource "packet_ssh_key" "k8s" {
|
||||
count = "${var.public_key_path != "" ? 1 : 0}"
|
||||
count = var.public_key_path != "" ? 1 : 0
|
||||
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" {
|
||||
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}"
|
||||
plan = "${var.plan_k8s_masters}"
|
||||
facilities = ["${var.facility}"]
|
||||
operating_system = "${var.operating_system}"
|
||||
billing_cycle = "${var.billing_cycle}"
|
||||
project_id = "${var.packet_project_id}"
|
||||
plan = var.plan_k8s_masters
|
||||
facilities = [var.facility]
|
||||
operating_system = var.operating_system
|
||||
billing_cycle = var.billing_cycle
|
||||
project_id = var.packet_project_id
|
||||
tags = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-master", "etcd", "kube-node"]
|
||||
}
|
||||
|
||||
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}"
|
||||
plan = "${var.plan_k8s_masters_no_etcd}"
|
||||
facilities = ["${var.facility}"]
|
||||
operating_system = "${var.operating_system}"
|
||||
billing_cycle = "${var.billing_cycle}"
|
||||
project_id = "${var.packet_project_id}"
|
||||
plan = var.plan_k8s_masters_no_etcd
|
||||
facilities = [var.facility]
|
||||
operating_system = var.operating_system
|
||||
billing_cycle = var.billing_cycle
|
||||
project_id = var.packet_project_id
|
||||
tags = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-master"]
|
||||
}
|
||||
|
||||
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}"
|
||||
plan = "${var.plan_etcd}"
|
||||
facilities = ["${var.facility}"]
|
||||
operating_system = "${var.operating_system}"
|
||||
billing_cycle = "${var.billing_cycle}"
|
||||
project_id = "${var.packet_project_id}"
|
||||
plan = var.plan_etcd
|
||||
facilities = [var.facility]
|
||||
operating_system = var.operating_system
|
||||
billing_cycle = var.billing_cycle
|
||||
project_id = var.packet_project_id
|
||||
tags = ["cluster-${var.cluster_name}", "etcd"]
|
||||
}
|
||||
|
||||
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}"
|
||||
plan = "${var.plan_k8s_nodes}"
|
||||
facilities = ["${var.facility}"]
|
||||
operating_system = "${var.operating_system}"
|
||||
billing_cycle = "${var.billing_cycle}"
|
||||
project_id = "${var.packet_project_id}"
|
||||
plan = var.plan_k8s_nodes
|
||||
facilities = [var.facility]
|
||||
operating_system = var.operating_system
|
||||
billing_cycle = var.billing_cycle
|
||||
project_id = var.packet_project_id
|
||||
tags = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-node"]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
output "k8s_masters" {
|
||||
value = "${packet_device.k8s_master.*.access_public_ipv4}"
|
||||
value = packet_device.k8s_master.*.access_public_ipv4
|
||||
}
|
||||
|
||||
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" {
|
||||
value = "${packet_device.k8s_etcd.*.access_public_ipv4}"
|
||||
value = packet_device.k8s_etcd.*.access_public_ipv4
|
||||
}
|
||||
|
||||
output "k8s_nodes" {
|
||||
value = "${packet_device.k8s_node.*.access_public_ipv4}"
|
||||
value = packet_device.k8s_node.*.access_public_ipv4
|
||||
}
|
||||
|
||||
|
||||
@@ -54,3 +54,4 @@ variable "number_of_etcd" {
|
||||
variable "number_of_k8s_nodes" {
|
||||
default = 0
|
||||
}
|
||||
|
||||
|
||||
4
contrib/terraform/packet/versions.tf
Normal file
4
contrib/terraform/packet/versions.tf
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
terraform {
|
||||
required_version = ">= 0.12"
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright 2015 Cisco Systems, Inc.
|
||||
#
|
||||
@@ -20,15 +20,15 @@
|
||||
Dynamic inventory for Terraform - finds all `.tfstate` files below the working
|
||||
directory and generates an inventory based on them.
|
||||
"""
|
||||
from __future__ import unicode_literals, print_function
|
||||
import argparse
|
||||
from collections import defaultdict
|
||||
import random
|
||||
from functools import wraps
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
VERSION = '0.3.0pre'
|
||||
VERSION = '0.4.0pre'
|
||||
|
||||
|
||||
def tfstates(root=None):
|
||||
@@ -38,15 +38,58 @@ def tfstates(root=None):
|
||||
if os.path.splitext(name)[-1] == '.tfstate':
|
||||
yield os.path.join(dirpath, name)
|
||||
|
||||
def convert_to_v3_structure(attributes, prefix=''):
|
||||
""" Convert the attributes from v4 to v3
|
||||
Receives a dict and return a dictionary """
|
||||
result = {}
|
||||
if isinstance(attributes, str):
|
||||
# In the case when we receive a string (e.g. values for security_groups)
|
||||
return {'{}{}'.format(prefix, random.randint(1,10**10)): attributes}
|
||||
for key, value in attributes.items():
|
||||
if isinstance(value, list):
|
||||
if len(value):
|
||||
result['{}{}.#'.format(prefix, key, hash)] = len(value)
|
||||
for i, v in enumerate(value):
|
||||
result.update(convert_to_v3_structure(v, '{}{}.{}.'.format(prefix, key, i)))
|
||||
elif isinstance(value, dict):
|
||||
result['{}{}.%'.format(prefix, key)] = len(value)
|
||||
for k, v in value.items():
|
||||
result['{}{}.{}'.format(prefix, key, k)] = v
|
||||
else:
|
||||
result['{}{}'.format(prefix, key)] = value
|
||||
return result
|
||||
|
||||
def iterresources(filenames):
|
||||
for filename in filenames:
|
||||
with open(filename, 'r') as json_file:
|
||||
state = json.load(json_file)
|
||||
tf_version = state['version']
|
||||
if tf_version == 3:
|
||||
for module in state['modules']:
|
||||
name = module['path'][-1]
|
||||
for key, resource in module['resources'].items():
|
||||
yield name, key, resource
|
||||
elif tf_version == 4:
|
||||
# In version 4 the structure changes so we need to iterate
|
||||
# each instance inside the resource branch.
|
||||
for resource in state['resources']:
|
||||
name = resource['provider'].split('.')[-1]
|
||||
for instance in resource['instances']:
|
||||
key = "{}.{}".format(resource['type'], resource['name'])
|
||||
if 'index_key' in instance:
|
||||
key = "{}.{}".format(key, instance['index_key'])
|
||||
data = {}
|
||||
data['type'] = resource['type']
|
||||
data['provider'] = resource['provider']
|
||||
data['depends_on'] = instance.get('depends_on', [])
|
||||
data['primary'] = {'attributes': convert_to_v3_structure(instance['attributes'])}
|
||||
if 'id' in instance['attributes']:
|
||||
data['primary']['id'] = instance['attributes']['id']
|
||||
data['primary']['meta'] = instance['attributes'].get('meta',{})
|
||||
yield name, key, data
|
||||
else:
|
||||
raise KeyError('tfstate version %d not supported' % tf_version)
|
||||
|
||||
|
||||
## READ RESOURCES
|
||||
PARSERS = {}
|
||||
@@ -109,7 +152,7 @@ def calculate_mantl_vars(func):
|
||||
|
||||
|
||||
def _parse_prefix(source, prefix, sep='.'):
|
||||
for compkey, value in source.items():
|
||||
for compkey, value in list(source.items()):
|
||||
try:
|
||||
curprefix, rest = compkey.split(sep, 1)
|
||||
except ValueError:
|
||||
@@ -127,7 +170,7 @@ def parse_attr_list(source, prefix, sep='.'):
|
||||
idx, key = compkey.split(sep, 1)
|
||||
attrs[idx][key] = value
|
||||
|
||||
return attrs.values()
|
||||
return list(attrs.values())
|
||||
|
||||
|
||||
def parse_dict(source, prefix, sep='.'):
|
||||
@@ -139,6 +182,9 @@ def parse_list(source, prefix, sep='.'):
|
||||
|
||||
|
||||
def parse_bool(string_form):
|
||||
if type(string_form) is bool:
|
||||
return string_form
|
||||
|
||||
token = string_form.lower()[0]
|
||||
|
||||
if token == 't':
|
||||
@@ -167,7 +213,7 @@ def packet_device(resource, tfvars=None):
|
||||
'state': raw_attrs['state'],
|
||||
# ansible
|
||||
'ansible_ssh_host': raw_attrs['network.0.address'],
|
||||
'ansible_ssh_user': 'root', # it's always "root" on Packet
|
||||
'ansible_ssh_user': 'root', # Use root by default in packet
|
||||
# generic
|
||||
'ipv4_address': raw_attrs['network.0.address'],
|
||||
'public_ipv4': raw_attrs['network.0.address'],
|
||||
@@ -177,6 +223,10 @@ def packet_device(resource, tfvars=None):
|
||||
'provider': 'packet',
|
||||
}
|
||||
|
||||
if raw_attrs['operating_system'] == 'coreos_stable':
|
||||
# For CoreOS set the ssh_user to core
|
||||
attrs.update({'ansible_ssh_user': 'core'})
|
||||
|
||||
# add groups based on attrs
|
||||
groups.append('packet_operating_system=' + attrs['operating_system'])
|
||||
groups.append('packet_locked=%s' % attrs['locked'])
|
||||
@@ -239,6 +289,12 @@ def openstack_host(resource, module_name):
|
||||
attrs['private_ipv4'] = raw_attrs['network.0.fixed_ip_v4']
|
||||
|
||||
try:
|
||||
if 'metadata.prefer_ipv6' in raw_attrs and raw_attrs['metadata.prefer_ipv6'] == "1":
|
||||
attrs.update({
|
||||
'ansible_ssh_host': re.sub("[\[\]]", "", raw_attrs['access_ip_v6']),
|
||||
'publicly_routable': True,
|
||||
})
|
||||
else:
|
||||
attrs.update({
|
||||
'ansible_ssh_host': raw_attrs['access_ip_v4'],
|
||||
'publicly_routable': True,
|
||||
@@ -252,9 +308,9 @@ def openstack_host(resource, module_name):
|
||||
if 'metadata.ssh_user' in raw_attrs:
|
||||
attrs['ansible_ssh_user'] = raw_attrs['metadata.ssh_user']
|
||||
|
||||
if 'volume.#' in raw_attrs.keys() and int(raw_attrs['volume.#']) > 0:
|
||||
if 'volume.#' in list(raw_attrs.keys()) and int(raw_attrs['volume.#']) > 0:
|
||||
device_index = 1
|
||||
for key, value in raw_attrs.items():
|
||||
for key, value in list(raw_attrs.items()):
|
||||
match = re.search("^volume.*.device$", key)
|
||||
if match:
|
||||
attrs['disk_volume_device_'+str(device_index)] = value
|
||||
@@ -272,7 +328,7 @@ def openstack_host(resource, module_name):
|
||||
groups.append('os_image=' + attrs['image']['name'])
|
||||
groups.append('os_flavor=' + attrs['flavor']['name'])
|
||||
groups.extend('os_metadata_%s=%s' % item
|
||||
for item in attrs['metadata'].items())
|
||||
for item in list(attrs['metadata'].items()))
|
||||
groups.append('os_region=' + attrs['region'])
|
||||
|
||||
# groups specific to Mantl
|
||||
@@ -290,14 +346,20 @@ def iter_host_ips(hosts, ips):
|
||||
'''Update hosts that have an entry in the floating IP list'''
|
||||
for host in hosts:
|
||||
host_id = host[1]['id']
|
||||
|
||||
if host_id in ips:
|
||||
ip = ips[host_id]
|
||||
|
||||
host[1].update({
|
||||
'access_ip_v4': ip,
|
||||
'access_ip': ip,
|
||||
'public_ipv4': 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
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
/usr/local/share/ca-certificates/vault-ca.crt
|
||||
{%- elif ansible_os_family == "RedHat" -%}
|
||||
/etc/pki/ca-trust/source/anchors/vault-ca.crt
|
||||
{%- elif ansible_os_family in ["CoreOS", "Container Linux by CoreOS"] -%}
|
||||
{%- elif ansible_os_family in ["Coreos", "Container Linux by CoreOS", "Flatcar", "Flatcar Container Linux by Kinvolk"] -%}
|
||||
/etc/ssl/certs/vault-ca.pem
|
||||
{%- endif %}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
- name: bootstrap/ca_trust | update ca-certificates (Debian/Ubuntu/CoreOS)
|
||||
command: update-ca-certificates
|
||||
when: vault_ca_cert.changed and ansible_os_family in ["Debian", "CoreOS", "Container Linux by CoreOS"]
|
||||
when: vault_ca_cert.changed and ansible_os_family in ["Debian", "CoreOS", "Coreos", "Container Linux by CoreOS", "Flatcar", "Flatcar Container Linux by Kinvolk"]
|
||||
|
||||
- name: bootstrap/ca_trust | update ca-certificates (RedHat)
|
||||
command: update-ca-trust extract
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
- name: bootstrap/sync_secrets | Print out warning message if secrets are not available and vault is initialized
|
||||
pause:
|
||||
prompt: >
|
||||
Vault orchestration may not be able to proceed. The Vault cluster is initialzed, but
|
||||
Vault orchestration may not be able to proceed. The Vault cluster is initialized, but
|
||||
'root_token' or 'unseal_keys' were not found in {{ vault_secrets_dir }}. These are
|
||||
needed for many vault orchestration steps.
|
||||
when: vault_cluster_is_initialized and not vault_secrets_available
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* [Getting started](/docs/getting-started.md)
|
||||
* [Ansible](docs/ansible.md)
|
||||
* [Variables](/docs/vars.md)
|
||||
* [Ansible](/docs/ansible.md)
|
||||
* Operations
|
||||
* [Integration](docs/integration.md)
|
||||
* [Upgrades](/docs/upgrades.md)
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
Ansible variables
|
||||
===============
|
||||
# Ansible variables
|
||||
|
||||
## Inventory
|
||||
|
||||
Inventory
|
||||
-------------
|
||||
The inventory is composed of 3 groups:
|
||||
|
||||
* **kube-node** : list of kubernetes nodes where the pods will run.
|
||||
@@ -14,7 +12,7 @@ Note: do not modify the children of _k8s-cluster_, like putting
|
||||
the _etcd_ group into the _k8s-cluster_, unless you are certain
|
||||
to do that and you have it fully contained in the latter:
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
k8s-cluster ⊂ etcd => kube-node ∩ etcd = etcd
|
||||
```
|
||||
|
||||
@@ -32,7 +30,7 @@ There are also two special groups:
|
||||
|
||||
Below is a complete inventory example:
|
||||
|
||||
```
|
||||
```ini
|
||||
## Configure 'ip' variable to bind kubernetes services on a
|
||||
## different ip than the default iface
|
||||
node1 ansible_host=95.54.0.12 ip=10.3.0.1
|
||||
@@ -63,8 +61,7 @@ kube-node
|
||||
kube-master
|
||||
```
|
||||
|
||||
Group vars and overriding variables precedence
|
||||
----------------------------------------------
|
||||
## Group vars and overriding variables precedence
|
||||
|
||||
The group variables to control main deployment options are located in the directory ``inventory/sample/group_vars``.
|
||||
Optional variables are located in the `inventory/sample/group_vars/all.yml`.
|
||||
@@ -97,8 +94,8 @@ block vars (only for tasks in block) | Kubespray overrides for internal roles' l
|
||||
task vars (only for the task) | Unused for roles, but only for helper scripts
|
||||
**extra vars** (always win precedence) | override with ``ansible-playbook -e @foo.yml``
|
||||
|
||||
Ansible tags
|
||||
------------
|
||||
## Ansible tags
|
||||
|
||||
The following tags are defined in playbooks:
|
||||
|
||||
| Tag name | Used for
|
||||
@@ -145,21 +142,25 @@ Note: Use the ``bash scripts/gen_tags.sh`` command to generate a list of all
|
||||
tags found in the codebase. New tags will be listed with the empty "Used for"
|
||||
field.
|
||||
|
||||
Example commands
|
||||
----------------
|
||||
## Example commands
|
||||
|
||||
Example command to filter and apply only DNS configuration tasks and skip
|
||||
everything else related to host OS configuration and downloading images of containers:
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
ansible-playbook -i inventory/sample/hosts.ini cluster.yml --tags preinstall,facts --skip-tags=download,bootstrap-os
|
||||
```
|
||||
|
||||
And this play only removes the K8s cluster DNS resolver IP from hosts' /etc/resolv.conf files:
|
||||
```
|
||||
|
||||
```ShellSession
|
||||
ansible-playbook -i inventory/sample/hosts.ini -e dns_mode='none' cluster.yml --tags resolvconf
|
||||
```
|
||||
|
||||
And this prepares all container images locally (at the ansible runner node) without installing
|
||||
or upgrading related stuff or trying to upload container to K8s cluster nodes:
|
||||
```
|
||||
|
||||
```ShellSession
|
||||
ansible-playbook -i inventory/sample/hosts.ini cluster.yml \
|
||||
-e download_run_once=true -e download_localhost=true \
|
||||
--tags download --skip-tags upload,upgrade
|
||||
@@ -167,14 +168,14 @@ ansible-playbook -i inventory/sample/hosts.ini cluster.yml \
|
||||
|
||||
Note: use `--tags` and `--skip-tags` wise and only if you're 100% sure what you're doing.
|
||||
|
||||
Bastion host
|
||||
--------------
|
||||
## Bastion host
|
||||
|
||||
If you prefer to not make your nodes publicly accessible (nodes with private IPs only),
|
||||
you can use a so called *bastion* host to connect to your nodes. To specify and use a bastion,
|
||||
simply add a line to your inventory, where you have to replace x.x.x.x with the public IP of the
|
||||
bastion host.
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
[bastion]
|
||||
bastion ansible_host=x.x.x.x
|
||||
```
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
## Architecture compatibility
|
||||
# Architecture compatibility
|
||||
|
||||
The following table shows the impact of the CPU architecture on compatible features:
|
||||
|
||||
- amd64: Cluster using only x86/amd64 CPUs
|
||||
- arm64: Cluster using only arm64 CPUs
|
||||
- amd64 + arm64: Cluster with a mix of x86/amd64 and arm64 CPUs
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
Atomic host bootstrap
|
||||
=====================
|
||||
# Atomic host bootstrap
|
||||
|
||||
Atomic host testing has been done with the network plugin flannel. Change the inventory var `kube_network_plugin: flannel`.
|
||||
|
||||
Note: Flannel is the only plugin that has currently been tested with atomic
|
||||
|
||||
### Vagrant
|
||||
## Vagrant
|
||||
|
||||
* For bootstrapping with Vagrant, use box centos/atomic-host or fedora/atomic-host
|
||||
* Update VagrantFile variable `local_release_dir` to `/var/vagrant/temp`.
|
||||
* Update `vm_memory = 2048` and `vm_cpus = 2`
|
||||
* Networking on vagrant hosts has to be brought up manually once they are booted.
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
vagrant ssh
|
||||
sudo /sbin/ifup enp0s8
|
||||
```
|
||||
|
||||
* For users of vagrant-libvirt download centos/atomic-host qcow2 format from https://wiki.centos.org/SpecialInterestGroup/Atomic/Download/
|
||||
* For users of vagrant-libvirt download fedora/atomic-host qcow2 format from https://getfedora.org/en/atomic/download/
|
||||
* For users of vagrant-libvirt download centos/atomic-host qcow2 format from <https://wiki.centos.org/SpecialInterestGroup/Atomic/Download/>
|
||||
* For users of vagrant-libvirt download fedora/atomic-host qcow2 format from <https://dl.fedoraproject.org/pub/alt/atomic/stable/>
|
||||
|
||||
Then you can proceed to [cluster deployment](#run-deployment)
|
||||
|
||||
17
docs/aws.md
17
docs/aws.md
@@ -1,11 +1,10 @@
|
||||
AWS
|
||||
===============
|
||||
# AWS
|
||||
|
||||
To deploy kubespray on [AWS](https://aws.amazon.com/) uncomment the `cloud_provider` option in `group_vars/all.yml` and set it to `'aws'`. Refer to the [Kubespray Configuration](#kubespray-configuration) for customizing the provider.
|
||||
|
||||
Prior to creating your instances, you **must** ensure that you have created IAM roles and policies for both "kubernetes-master" and "kubernetes-node". You can find the IAM policies [here](https://github.com/kubernetes-sigs/kubespray/tree/master/contrib/aws_iam/). See the [IAM Documentation](https://aws.amazon.com/documentation/iam/) if guidance is needed on how to set these up. When you bring your instances online, associate them with the respective IAM role. Nodes that are only to be used for Etcd do not need a role.
|
||||
|
||||
You would also need to tag the resources in your VPC accordingly for the aws provider to utilize them. Tag the subnets, route tables and all instances that kubernetes will be run on with key `kubernetes.io/cluster/$cluster_name` (`$cluster_name` must be a unique identifier for the cluster). Tag the subnets that must be targetted by external ELBs with the key `kubernetes.io/role/elb` and internal ELBs with the key `kubernetes.io/role/internal-elb`.
|
||||
You would also need to tag the resources in your VPC accordingly for the aws provider to utilize them. Tag the subnets, route tables and all instances that kubernetes will be run on with key `kubernetes.io/cluster/$cluster_name` (`$cluster_name` must be a unique identifier for the cluster). Tag the subnets that must be targeted by external ELBs with the key `kubernetes.io/role/elb` and internal ELBs with the key `kubernetes.io/role/internal-elb`.
|
||||
|
||||
Make sure your VPC has both DNS Hostnames support and Private DNS enabled.
|
||||
|
||||
@@ -13,11 +12,13 @@ The next step is to make sure the hostnames in your `inventory` file are identic
|
||||
|
||||
You can now create your cluster!
|
||||
|
||||
### Dynamic Inventory ###
|
||||
## Dynamic Inventory
|
||||
|
||||
There is also a dynamic inventory script for AWS that can be used if desired. However, be aware that it makes some certain assumptions about how you'll create your inventory. It also does not handle all use cases and groups that we may use as part of more advanced deployments. Additions welcome.
|
||||
|
||||
This will produce an inventory that is passed into Ansible that looks like the following:
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"_meta": {
|
||||
"hostvars": {
|
||||
@@ -48,15 +49,18 @@ This will produce an inventory that is passed into Ansible that looks like the f
|
||||
```
|
||||
|
||||
Guide:
|
||||
|
||||
- Create instances in AWS as needed.
|
||||
- Either during or after creation, add tags to the instances with a key of `kubespray-role` and a value of `kube-master`, `etcd`, or `kube-node`. You can also share roles like `kube-master, etcd`
|
||||
- Copy the `kubespray-aws-inventory.py` script from `kubespray/contrib/aws_inventory` to the `kubespray/inventory` directory.
|
||||
- Set the following AWS credentials and info as environment variables in your terminal:
|
||||
```
|
||||
|
||||
```ShellSession
|
||||
export AWS_ACCESS_KEY_ID="xxxxx"
|
||||
export AWS_SECRET_ACCESS_KEY="yyyyy"
|
||||
export REGION="us-east-2"
|
||||
```
|
||||
|
||||
- We will now create our cluster. There will be either one or two small changes. The first is that we will specify `-i inventory/kubespray-aws-inventory.py` as our inventory script. The other is conditional. If your AWS instances are public facing, you can set the `VPC_VISIBILITY` variable to `public` and that will result in public IP and DNS names being passed into the inventory. This causes your cluster.yml command to look like `VPC_VISIBILITY="public" ansible-playbook ... cluster.yml`
|
||||
|
||||
## Kubespray configuration
|
||||
@@ -75,4 +79,3 @@ aws_kubernetes_cluster_id|string|KubernetesClusterID is the cluster id we'll use
|
||||
aws_disable_security_group_ingress|bool|The aws provider creates an inbound rule per load balancer on the node security group. However, this can run into the AWS security group rule limit of 50 if many LoadBalancers are created. This flag disables the automatic ingress creation. It requires that the user has setup a rule that allows inbound traffic on kubelet ports from the local VPC subnet (so load balancers can access it). E.g. 10.82.0.0/16 30000-32000.
|
||||
aws_elb_security_group|string|Only in Kubelet version >= 1.7 : AWS has a hard limit of 500 security groups. For large clusters creating a security group for each ELB can cause the max number of security groups to be reached. If this is set instead of creating a new Security group for each ELB this security group will be used instead.
|
||||
aws_disable_strict_zone_check|bool|During the instantiation of an new AWS cloud provider, the detected region is validated against a known set of regions. In a non-standard, AWS like environment (e.g. Eucalyptus), this check may be undesirable. Setting this to true will disable the check and provide a warning that the check was skipped. Please note that this is an experimental feature and work-in-progress for the moment.
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
Azure
|
||||
===============
|
||||
# Azure
|
||||
|
||||
To deploy Kubernetes on [Azure](https://azure.microsoft.com) uncomment the `cloud_provider` option in `group_vars/all.yml` and set it to `'azure'`.
|
||||
|
||||
@@ -7,68 +6,77 @@ All your instances are required to run in a resource group and a routing table h
|
||||
|
||||
Not all features are supported yet though, for a list of the current status have a look [here](https://github.com/colemickens/azure-kubernetes-status)
|
||||
|
||||
### Parameters
|
||||
## Parameters
|
||||
|
||||
Before creating the instances you must first set the `azure_` variables in the `group_vars/all.yml` file.
|
||||
|
||||
All of the values can be retrieved using the azure cli tool which can be downloaded here: https://docs.microsoft.com/en-gb/azure/xplat-cli-install
|
||||
All of the values can be retrieved using the azure cli tool which can be downloaded here: <https://docs.microsoft.com/en-gb/azure/xplat-cli-install>
|
||||
After installation you have to run `azure login` to get access to your account.
|
||||
|
||||
### azure\_tenant\_id + azure\_subscription\_id
|
||||
|
||||
#### azure\_tenant\_id + azure\_subscription\_id
|
||||
run `azure account show` to retrieve your subscription id and tenant id:
|
||||
`azure_tenant_id` -> Tenant ID field
|
||||
`azure_subscription_id` -> ID field
|
||||
|
||||
### azure\_location
|
||||
|
||||
#### azure\_location
|
||||
The region your instances are located, can be something like `westeurope` or `westcentralus`. A full list of region names can be retrieved via `azure location list`
|
||||
|
||||
### azure\_resource\_group
|
||||
|
||||
#### azure\_resource\_group
|
||||
The name of the resource group your instances are in, can be retrieved via `azure group list`
|
||||
|
||||
#### azure\_vnet\_name
|
||||
### azure\_vnet\_name
|
||||
|
||||
The name of the virtual network your instances are in, can be retrieved via `azure network vnet list`
|
||||
|
||||
#### azure\_subnet\_name
|
||||
The name of the subnet your instances are in, can be retrieved via `azure network vnet subnet list RESOURCE_GROUP VNET_NAME`
|
||||
### azure\_subnet\_name
|
||||
|
||||
The name of the subnet your instances are in, can be retrieved via `azure network vnet subnet list --resource-group RESOURCE_GROUP --vnet-name VNET_NAME`
|
||||
|
||||
### azure\_security\_group\_name
|
||||
|
||||
#### azure\_security\_group\_name
|
||||
The name of the network security group your instances are in, can be retrieved via `azure network nsg list`
|
||||
|
||||
#### azure\_aad\_client\_id + azure\_aad\_client\_secret
|
||||
### azure\_aad\_client\_id + azure\_aad\_client\_secret
|
||||
|
||||
These will have to be generated first:
|
||||
|
||||
- Create an Azure AD Application with:
|
||||
`azure ad app create --name kubernetes --identifier-uris http://kubernetes --home-page http://example.com --password CLIENT_SECRET`
|
||||
The name, identifier-uri, home-page and the password can be choosen
|
||||
`azure ad app create --display-name kubernetes --identifier-uris http://kubernetes --homepage http://example.com --password CLIENT_SECRET`
|
||||
display name, identifier-uri, homepage and the password can be chosen
|
||||
Note the AppId in the output.
|
||||
- Create Service principal for the application with:
|
||||
`azure ad sp create --applicationId AppId`
|
||||
`azure ad sp create --id AppId`
|
||||
This is the AppId from the last command
|
||||
- Create the role assignment with:
|
||||
`azure role assignment create --spn http://kubernetes -o "Owner" -c /subscriptions/SUBSCRIPTION_ID`
|
||||
`azure role assignment create --role "Owner" --assignee http://kubernetes --subscription SUBSCRIPTION_ID`
|
||||
|
||||
azure\_aad\_client\_id must be set to the AppId, azure\_aad\_client\_secret is your choosen secret.
|
||||
azure\_aad\_client\_id must be set to the AppId, azure\_aad\_client\_secret is your chosen secret.
|
||||
|
||||
### azure\_loadbalancer\_sku
|
||||
|
||||
#### azure\_loadbalancer\_sku
|
||||
Sku of Load Balancer and Public IP. Candidate values are: basic and standard.
|
||||
|
||||
#### azure\_exclude\_master\_from\_standard\_lb
|
||||
### azure\_exclude\_master\_from\_standard\_lb
|
||||
|
||||
azure\_exclude\_master\_from\_standard\_lb excludes master nodes from `standard` load balancer.
|
||||
|
||||
#### azure\_disable\_outbound\_snat
|
||||
### azure\_disable\_outbound\_snat
|
||||
|
||||
azure\_disable\_outbound\_snat disables the outbound SNAT for public load balancer rules. It should only be set when azure\_exclude\_master\_from\_standard\_lb is `standard`.
|
||||
|
||||
#### azure\_primary\_availability\_set\_name
|
||||
### azure\_primary\_availability\_set\_name
|
||||
|
||||
(Optional) The name of the availability set that should be used as the load balancer backend .If this is set, the Azure
|
||||
cloudprovider will only add nodes from that availability set to the load balancer backend pool. If this is not set, and
|
||||
multiple agent pools (availability sets) are used, then the cloudprovider will try to add all nodes to a single backend
|
||||
pool which is forbidden. In other words, if you use multiple agent pools (availability sets), you MUST set this field.
|
||||
|
||||
#### azure\_use\_instance\_metadata
|
||||
Use instance metadata service where possible
|
||||
### azure\_use\_instance\_metadata
|
||||
|
||||
Use instance metadata service where possible
|
||||
|
||||
## Provisioning Azure with Resource Group Templates
|
||||
|
||||
|
||||
@@ -1,82 +1,83 @@
|
||||
Calico
|
||||
===========
|
||||
# Calico
|
||||
|
||||
N.B. **Version 2.6.5 upgrade to 3.1.1 is upgrading etcd store to etcdv3**
|
||||
|
||||
---
|
||||
**N.B. Version 2.6.5 upgrade to 3.1.1 is upgrading etcd store to etcdv3**
|
||||
If you create automated backups of etcdv2 please switch for creating etcdv3 backups, as kubernetes and calico now uses etcdv3
|
||||
After migration you can check `/tmp/calico_upgrade/` directory for converted items to etcdv3.
|
||||
**PLEASE TEST upgrade before upgrading production cluster.**
|
||||
---
|
||||
|
||||
Check if the calico-node container is running
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
docker ps | grep calico
|
||||
```
|
||||
|
||||
The **calicoctl** command allows to check the status of the network workloads.
|
||||
|
||||
* Check the status of Calico nodes
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
calicoctl node status
|
||||
```
|
||||
|
||||
or for versions prior to *v1.0.0*:
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
calicoctl status
|
||||
```
|
||||
|
||||
* Show the configured network subnet for containers
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
calicoctl get ippool -o wide
|
||||
```
|
||||
|
||||
or for versions prior to *v1.0.0*:
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
calicoctl pool show
|
||||
```
|
||||
|
||||
* Show the workloads (ip addresses of containers and their located)
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
calicoctl get workloadEndpoint -o wide
|
||||
```
|
||||
|
||||
and
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
calicoctl get hostEndpoint -o wide
|
||||
```
|
||||
|
||||
or for versions prior *v1.0.0*:
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
calicoctl endpoint show --detail
|
||||
```
|
||||
|
||||
##### Optional : Define network backend
|
||||
## Configuration
|
||||
|
||||
### Optional : Define network backend
|
||||
|
||||
In some cases you may want to define Calico network backend. Allowed values are 'bird', 'gobgp' or 'none'. Bird is a default value.
|
||||
|
||||
To re-define you need to edit the inventory and add a group variable `calico_network_backend`
|
||||
|
||||
```
|
||||
```yml
|
||||
calico_network_backend: none
|
||||
```
|
||||
|
||||
##### Optional : Define the default pool CIDR
|
||||
### Optional : Define the default pool CIDR
|
||||
|
||||
By default, `kube_pods_subnet` is used as the IP range CIDR for the default IP Pool.
|
||||
In some cases you may want to add several pools and not have them considered by Kubernetes as external (which means that they must be within or equal to the range defined in `kube_pods_subnet`), it starts with the default IP Pool of which IP range CIDR can by defined in group_vars (k8s-cluster/k8s-net-calico.yml):
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
calico_pool_cidr: 10.233.64.0/20
|
||||
```
|
||||
|
||||
##### Optional : BGP Peering with border routers
|
||||
### Optional : BGP Peering with border routers
|
||||
|
||||
In some cases you may want to route the pods subnet and so NAT is not needed on the nodes.
|
||||
For instance if you have a cluster spread on different locations and you want your pods to talk each other no matter where they are located.
|
||||
@@ -84,11 +85,11 @@ The following variables need to be set:
|
||||
`peer_with_router` to enable the peering with the datacenter's border router (default value: false).
|
||||
you'll need to edit the inventory and add a hostvar `local_as` by node.
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
node1 ansible_ssh_host=95.54.0.12 local_as=xxxxxx
|
||||
```
|
||||
|
||||
##### Optional : Defining BGP peers
|
||||
### Optional : Defining BGP peers
|
||||
|
||||
Peers can be defined using the `peers` variable (see docs/calico_peer_example examples).
|
||||
In order to define global peers, the `peers` variable can be defined in group_vars with the "scope" attribute of each global peer set to "global".
|
||||
@@ -97,16 +98,17 @@ NB: Ansible's `hash_behaviour` is by default set to "replace", thus defining bot
|
||||
|
||||
Since calico 3.4, Calico supports advertising Kubernetes service cluster IPs over BGP, just as it advertises pod IPs.
|
||||
This can be enabled by setting the following variable as follow in group_vars (k8s-cluster/k8s-net-calico.yml)
|
||||
```
|
||||
|
||||
```yml
|
||||
calico_advertise_cluster_ips: true
|
||||
```
|
||||
|
||||
##### Optional : Define global AS number
|
||||
### Optional : Define global AS number
|
||||
|
||||
Optional parameter `global_as_num` defines Calico global AS number (`/calico/bgp/v1/global/as_num` etcd key).
|
||||
It defaults to "64512".
|
||||
|
||||
##### Optional : BGP Peering with route reflectors
|
||||
### Optional : BGP Peering with route reflectors
|
||||
|
||||
At large scale you may want to disable full node-to-node mesh in order to
|
||||
optimize your BGP topology and improve `calico-node` containers' start times.
|
||||
@@ -114,20 +116,20 @@ optimize your BGP topology and improve `calico-node` containers' start times.
|
||||
To do so you can deploy BGP route reflectors and peer `calico-node` with them as
|
||||
recommended here:
|
||||
|
||||
* https://hub.docker.com/r/calico/routereflector/
|
||||
* https://docs.projectcalico.org/v3.1/reference/private-cloud/l3-interconnect-fabric
|
||||
* <https://hub.docker.com/r/calico/routereflector/>
|
||||
* <https://docs.projectcalico.org/v3.1/reference/private-cloud/l3-interconnect-fabric>
|
||||
|
||||
You need to edit your inventory and add:
|
||||
|
||||
* `calico-rr` group with nodes in it. At the moment it's incompatible with
|
||||
`kube-node` due to BGP port conflict with `calico-node` container. So you
|
||||
should not have nodes in both `calico-rr` and `kube-node` groups.
|
||||
* `calico-rr` group with nodes in it. `calico-rr` can be combined with
|
||||
`kube-node` and/or `kube-master`. `calico-rr` group also must be a child
|
||||
group of `k8s-cluster` group.
|
||||
* `cluster_id` by route reflector node/group (see details
|
||||
[here](https://hub.docker.com/r/calico/routereflector/))
|
||||
|
||||
Here's an example of Kubespray inventory with route reflectors:
|
||||
Here's an example of Kubespray inventory with standalone route reflectors:
|
||||
|
||||
```
|
||||
```ini
|
||||
[all]
|
||||
rr0 ansible_ssh_host=10.210.1.10 ip=10.210.1.10
|
||||
rr1 ansible_ssh_host=10.210.1.11 ip=10.210.1.11
|
||||
@@ -154,6 +156,7 @@ node5
|
||||
[k8s-cluster:children]
|
||||
kube-node
|
||||
kube-master
|
||||
calico-rr
|
||||
|
||||
[calico-rr]
|
||||
rr0
|
||||
@@ -176,35 +179,35 @@ The inventory above will deploy the following topology assuming that calico's
|
||||
|
||||

|
||||
|
||||
##### Optional : Define default endpoint to host action
|
||||
|
||||
By default Calico blocks traffic from endpoints to the host itself by using an iptables DROP action. When using it in kubernetes the action has to be changed to RETURN (default in kubespray) or ACCEPT (see https://github.com/projectcalico/felix/issues/660 and https://github.com/projectcalico/calicoctl/issues/1389). Otherwise all network packets from pods (with hostNetwork=False) to services endpoints (with hostNetwork=True) within the same node are dropped.
|
||||
### Optional : Define default endpoint to host action
|
||||
|
||||
By default Calico blocks traffic from endpoints to the host itself by using an iptables DROP action. When using it in kubernetes the action has to be changed to RETURN (default in kubespray) or ACCEPT (see <https://github.com/projectcalico/felix/issues/660> and <https://github.com/projectcalico/calicoctl/issues/1389).> Otherwise all network packets from pods (with hostNetwork=False) to services endpoints (with hostNetwork=True) within the same node are dropped.
|
||||
|
||||
To re-define default action please set the following variable in your inventory:
|
||||
```
|
||||
|
||||
```yml
|
||||
calico_endpoint_to_host_action: "ACCEPT"
|
||||
```
|
||||
|
||||
##### Optional : Define address on which Felix will respond to health requests
|
||||
## Optional : Define address on which Felix will respond to health requests
|
||||
|
||||
Since Calico 3.2.0, HealthCheck default behavior changed from listening on all interfaces to just listening on localhost.
|
||||
|
||||
To re-define health host please set the following variable in your inventory:
|
||||
```
|
||||
|
||||
```yml
|
||||
calico_healthhost: "0.0.0.0"
|
||||
```
|
||||
|
||||
Cloud providers configuration
|
||||
=============================
|
||||
## Cloud providers configuration
|
||||
|
||||
Please refer to the official documentation, for example [GCE configuration](http://docs.projectcalico.org/v1.5/getting-started/docker/installation/gce) requires a security rule for calico ip-ip tunnels. Note, calico is always configured with ``ipip: true`` if the cloud provider was defined.
|
||||
|
||||
##### Optional : Ignore kernel's RPF check setting
|
||||
### Optional : Ignore kernel's RPF check setting
|
||||
|
||||
By default the felix agent(calico-node) will abort if the Kernel RPF setting is not 'strict'. If you want Calico to ignore the Kernel setting:
|
||||
|
||||
```
|
||||
```yml
|
||||
calico_node_ignorelooserpf: true
|
||||
```
|
||||
|
||||
@@ -212,7 +215,7 @@ Note that in OpenStack you must allow `ipip` traffic in your security groups,
|
||||
otherwise you will experience timeouts.
|
||||
To do this you must add a rule which allows it, for example:
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
neutron security-group-rule-create --protocol 4 --direction egress k8s-a0tp4t
|
||||
neutron security-group-rule-create --protocol 4 --direction igress k8s-a0tp4t
|
||||
```
|
||||
|
||||
102
docs/cinder-csi.md
Normal file
102
docs/cinder-csi.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Cinder CSI Driver
|
||||
|
||||
Cinder CSI driver allows you to provision volumes over an OpenStack deployment. The Kubernetes historic in-tree cloud provider is deprecated and will be removed in future versions.
|
||||
|
||||
To enable Cinder CSI driver, uncomment the `cinder_csi_enabled` option in `group_vars/all/openstack.yml` and set it to `true`.
|
||||
|
||||
To set the number of replicas for the Cinder CSI controller, you can change `cinder_csi_controller_replicas` option in `group_vars/all/openstack.yml`.
|
||||
|
||||
You need to source the OpenStack credentials you use to deploy your machines that will host Kubernetes: `source path/to/your/openstack-rc` or `. path/to/your/openstack-rc`.
|
||||
|
||||
Make sure the hostnames in your `inventory` file are identical to your instance names in OpenStack. Otherwise [cinder](https://docs.openstack.org/cinder/latest/) won't work as expected.
|
||||
|
||||
If you want to deploy the cinder provisioner used with Cinder CSI Driver, you should set `persistent_volumes_enabled` in `group_vars/k8s-cluster/k8s-cluster.yml` to `true`.
|
||||
|
||||
You can now run the kubespray playbook (cluster.yml) to deploy Kubernetes over OpenStack with Cinder CSI Driver enabled.
|
||||
|
||||
## Usage example
|
||||
|
||||
To check if Cinder CSI Driver works properly, see first that the cinder-csi pods are running:
|
||||
|
||||
```ShellSession
|
||||
$ kubectl -n kube-system get pods | grep cinder
|
||||
csi-cinder-controllerplugin-7f8bf99785-cpb5v 5/5 Running 0 100m
|
||||
csi-cinder-nodeplugin-rm5x2 2/2 Running 0 100m
|
||||
```
|
||||
|
||||
Check the associated storage class (if you enabled persistent_volumes):
|
||||
|
||||
```ShellSession
|
||||
$ kubectl get storageclass
|
||||
NAME PROVISIONER AGE
|
||||
cinder-csi cinder.csi.openstack.org 100m
|
||||
```
|
||||
|
||||
You can run a PVC and an Nginx Pod using this file `nginx.yaml`:
|
||||
|
||||
```yml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: csi-pvc-cinderplugin
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
storageClassName: cinder-csi
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: nginx
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/www/html
|
||||
name: csi-data-cinderplugin
|
||||
volumes:
|
||||
- name: csi-data-cinderplugin
|
||||
persistentVolumeClaim:
|
||||
claimName: csi-pvc-cinderplugin
|
||||
readOnly: false
|
||||
```
|
||||
|
||||
Apply this conf to your cluster: ```kubectl apply -f nginx.yml```
|
||||
|
||||
You should see the PVC provisioned and bound:
|
||||
|
||||
```ShellSession
|
||||
$ kubectl get pvc
|
||||
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
|
||||
csi-pvc-cinderplugin Bound pvc-f21ad0a1-5b7b-405e-a462-48da5cb76beb 1Gi RWO cinder-csi 8s
|
||||
```
|
||||
|
||||
And the volume mounted to the Nginx Pod (wait until the Pod is Running):
|
||||
|
||||
```ShellSession
|
||||
kubectl exec -it nginx -- df -h | grep /var/lib/www/html
|
||||
/dev/vdb 976M 2.6M 958M 1% /var/lib/www/html
|
||||
```
|
||||
|
||||
## Compatibility with in-tree cloud provider
|
||||
|
||||
It is not necessary to enable OpenStack as a cloud provider for Cinder CSI Driver to work.
|
||||
Though, you can run both the in-tree openstack cloud provider and the Cinder CSI Driver at the same time. The storage class provisioners associated to each one of them are differently named.
|
||||
|
||||
## Cinder v2 support
|
||||
|
||||
For the moment, only Cinder v3 is supported by the CSI Driver.
|
||||
|
||||
## More info
|
||||
|
||||
For further information about the Cinder CSI Driver, you can refer to this page: [Cloud Provider OpenStack](https://github.com/kubernetes/cloud-provider-openstack/blob/master/docs/using-cinder-csi-plugin.md).
|
||||
@@ -1,13 +1,13 @@
|
||||
Cloud providers
|
||||
==============
|
||||
# Cloud providers
|
||||
|
||||
#### Provisioning
|
||||
## Provisioning
|
||||
|
||||
You can deploy instances in your cloud environment in several different ways. Examples include Terraform, Ansible (ec2 and gce modules), and manual creation.
|
||||
|
||||
#### Deploy kubernetes
|
||||
## Deploy kubernetes
|
||||
|
||||
With ansible-playbook command
|
||||
```
|
||||
|
||||
```ShellSession
|
||||
ansible-playbook -u smana -e ansible_ssh_user=admin -e cloud_provider=[aws|gce] -b --become-user=root -i inventory/single.cfg cluster.yml
|
||||
```
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
Kubespray vs [Kops](https://github.com/kubernetes/kops)
|
||||
---------------
|
||||
# Comparaison
|
||||
|
||||
## Kubespray vs [Kops](https://github.com/kubernetes/kops)
|
||||
|
||||
Kubespray runs on bare metal and most clouds, using Ansible as its substrate for
|
||||
provisioning and orchestration. Kops performs the provisioning and orchestration
|
||||
@@ -10,8 +11,7 @@ however, is more tightly integrated with the unique features of the clouds it
|
||||
supports so it could be a better choice if you know that you will only be using
|
||||
one platform for the foreseeable future.
|
||||
|
||||
Kubespray vs [Kubeadm](https://github.com/kubernetes/kubeadm)
|
||||
------------------
|
||||
## Kubespray vs [Kubeadm](https://github.com/kubernetes/kubeadm)
|
||||
|
||||
Kubeadm provides domain Knowledge of Kubernetes clusters' life cycle
|
||||
management, including self-hosted layouts, dynamic discovery services and so
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
Contiv
|
||||
======
|
||||
# Contiv
|
||||
|
||||
Here is the [Contiv documentation](http://contiv.github.io/documents/).
|
||||
|
||||
@@ -10,7 +9,6 @@ There are two ways to manage Contiv:
|
||||
* a web UI managed by the api proxy service
|
||||
* a CLI named `netctl`
|
||||
|
||||
|
||||
### Interfaces
|
||||
|
||||
#### The Web Interface
|
||||
@@ -27,7 +25,6 @@ contiv_generate_certificate: true
|
||||
|
||||
The default credentials to log in are: admin/admin.
|
||||
|
||||
|
||||
#### The Command Line Interface
|
||||
|
||||
The second way to modify the Contiv configuration is to use the CLI. To do this, you have to connect to the server and export an environment variable to tell netctl how to connect to the cluster:
|
||||
@@ -44,7 +41,6 @@ contiv_netmaster_port: 9999
|
||||
|
||||
The CLI doesn't use the authentication process needed by the web interface.
|
||||
|
||||
|
||||
### Network configuration
|
||||
|
||||
The default configuration uses VXLAN to create an overlay. Two networks are created by default:
|
||||
|
||||
@@ -6,6 +6,7 @@ Example with Ansible:
|
||||
Before running the cluster playbook you must satisfy the following requirements:
|
||||
|
||||
General CoreOS Pre-Installation Notes:
|
||||
|
||||
- Ensure that the bin_dir is set to `/opt/bin`
|
||||
- ansible_python_interpreter should be `/opt/bin/python`. This will be laid down by the bootstrap task.
|
||||
- The default resolvconf_mode setting of `docker_dns` **does not** work for CoreOS. This is because we do not edit the systemd service file for docker on CoreOS nodes. Instead, just use the `host_resolvconf` mode. It should work out of the box.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
CRI-O
|
||||
===============
|
||||
# CRI-O
|
||||
|
||||
[CRI-O] is a lightweight container runtime for Kubernetes.
|
||||
Kubespray supports basic functionality for using CRI-O as the default container runtime in a cluster.
|
||||
@@ -10,14 +9,14 @@ Kubespray supports basic functionality for using CRI-O as the default container
|
||||
|
||||
_To use CRI-O instead of Docker, set the following variables:_
|
||||
|
||||
#### all.yml
|
||||
## all.yml
|
||||
|
||||
```yaml
|
||||
download_container: false
|
||||
skip_downloads: false
|
||||
```
|
||||
|
||||
#### k8s-cluster.yml
|
||||
## k8s-cluster.yml
|
||||
|
||||
```yaml
|
||||
etcd_deployment_type: host
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
Debian Jessie
|
||||
===============
|
||||
# Debian Jessie
|
||||
|
||||
Debian Jessie installation Notes:
|
||||
|
||||
@@ -9,7 +8,7 @@ Debian Jessie installation Notes:
|
||||
|
||||
to /etc/default/grub. Then update with
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
sudo update-grub
|
||||
sudo update-grub2
|
||||
sudo reboot
|
||||
@@ -23,7 +22,7 @@ Debian Jessie installation Notes:
|
||||
|
||||
- Add the Ansible repository and install Ansible to get a proper version
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
sudo add-apt-repository ppa:ansible/ansible
|
||||
sudo apt-get update
|
||||
sudo apt-get install ansible
|
||||
@@ -34,5 +33,4 @@ Debian Jessie installation Notes:
|
||||
|
||||
```sudo apt-get install python-jinja2=2.8-1~bpo8+1 python-netaddr```
|
||||
|
||||
|
||||
Now you can continue with [Preparing your deployment](getting-started.md#starting-custom-deployment)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
K8s DNS stack by Kubespray
|
||||
======================
|
||||
# K8s DNS stack by Kubespray
|
||||
|
||||
For K8s cluster nodes, Kubespray configures a [Kubernetes DNS](http://kubernetes.io/docs/admin/dns/)
|
||||
[cluster add-on](http://releases.k8s.io/master/cluster/addons/README.md)
|
||||
@@ -9,78 +8,89 @@ to serve as an authoritative DNS server for a given ``dns_domain`` and its
|
||||
Other nodes in the inventory, like external storage nodes or a separate etcd cluster
|
||||
node group, considered non-cluster and left up to the user to configure DNS resolve.
|
||||
|
||||
|
||||
DNS variables
|
||||
=============
|
||||
## DNS variables
|
||||
|
||||
There are several global variables which can be used to modify DNS settings:
|
||||
|
||||
#### ndots
|
||||
### ndots
|
||||
|
||||
ndots value to be used in ``/etc/resolv.conf``
|
||||
|
||||
It is important to note that multiple search domains combined with high ``ndots``
|
||||
values lead to poor performance of DNS stack, so please choose it wisely.
|
||||
|
||||
#### searchdomains
|
||||
### searchdomains
|
||||
|
||||
Custom search domains to be added in addition to the cluster search domains (``default.svc.{{ dns_domain }}, svc.{{ dns_domain }}``).
|
||||
|
||||
Most Linux systems limit the total number of search domains to 6 and the total length of all search domains
|
||||
to 256 characters. Depending on the length of ``dns_domain``, you're limitted to less then the total limit.
|
||||
to 256 characters. Depending on the length of ``dns_domain``, you're limited to less than the total limit.
|
||||
|
||||
Please note that ``resolvconf_mode: docker_dns`` will automatically add your systems search domains as
|
||||
additional search domains. Please take this into the accounts for the limits.
|
||||
|
||||
#### nameservers
|
||||
### nameservers
|
||||
|
||||
This variable is only used by ``resolvconf_mode: host_resolvconf``. These nameservers are added to the hosts
|
||||
``/etc/resolv.conf`` *after* ``upstream_dns_servers`` and thus serve as backup nameservers. If this variable
|
||||
is not set, a default resolver is chosen (depending on cloud provider or 8.8.8.8 when no cloud provider is specified).
|
||||
|
||||
#### upstream_dns_servers
|
||||
### upstream_dns_servers
|
||||
|
||||
DNS servers to be added *after* the cluster DNS. Used by all ``resolvconf_mode`` modes. These serve as backup
|
||||
DNS servers in early cluster deployment when no cluster DNS is available yet.
|
||||
|
||||
DNS modes supported by Kubespray
|
||||
============================
|
||||
## DNS modes supported by Kubespray
|
||||
|
||||
You can modify how Kubespray sets up DNS for your cluster with the variables ``dns_mode`` and ``resolvconf_mode``.
|
||||
|
||||
## dns_mode
|
||||
### dns_mode
|
||||
|
||||
``dns_mode`` configures how Kubespray will setup cluster DNS. There are four modes available:
|
||||
|
||||
#### coredns (default)
|
||||
#### dns_mode: coredns (default)
|
||||
|
||||
This installs CoreDNS as the default cluster DNS for all queries.
|
||||
|
||||
#### coredns_dual
|
||||
#### dns_mode: coredns_dual
|
||||
|
||||
This installs CoreDNS as the default cluster DNS for all queries, plus a secondary CoreDNS stack.
|
||||
|
||||
#### manual
|
||||
#### dns_mode: manual
|
||||
|
||||
This does not install coredns, but allows you to specify
|
||||
`manual_dns_server`, which will be configured on nodes for handling Pod DNS.
|
||||
Use this method if you plan to install your own DNS server in the cluster after
|
||||
initial deployment.
|
||||
|
||||
#### none
|
||||
#### dns_mode: none
|
||||
|
||||
This does not install any of DNS solution at all. This basically disables cluster DNS completely and
|
||||
leaves you with a non functional cluster.
|
||||
|
||||
## resolvconf_mode
|
||||
|
||||
``resolvconf_mode`` configures how Kubespray will setup DNS for ``hostNetwork: true`` PODs and non-k8s containers.
|
||||
There are three modes available:
|
||||
|
||||
#### docker_dns (default)
|
||||
### resolvconf_mode: docker_dns (default)
|
||||
|
||||
This sets up the docker daemon with additional --dns/--dns-search/--dns-opt flags.
|
||||
|
||||
The following nameservers are added to the docker daemon (in the same order as listed here):
|
||||
|
||||
* cluster nameserver (depends on dns_mode)
|
||||
* content of optional upstream_dns_servers variable
|
||||
* host system nameservers (read from hosts /etc/resolv.conf)
|
||||
|
||||
The following search domains are added to the docker daemon (in the same order as listed here):
|
||||
|
||||
* cluster domains (``default.svc.{{ dns_domain }}``, ``svc.{{ dns_domain }}``)
|
||||
* content of optional searchdomains variable
|
||||
* host system search domains (read from hosts /etc/resolv.conf)
|
||||
|
||||
The following dns options are added to the docker daemon
|
||||
|
||||
* ndots:{{ ndots }}
|
||||
* timeout:2
|
||||
* attempts:2
|
||||
@@ -96,8 +106,9 @@ DNS queries to the cluster DNS will timeout after a few seconds, resulting in th
|
||||
used as a backup nameserver. After cluster DNS is running, all queries will be answered by the cluster DNS
|
||||
servers, which in turn will forward queries to the system nameserver if required.
|
||||
|
||||
#### host_resolvconf
|
||||
This activates the classic Kubespray behaviour that modifies the hosts ``/etc/resolv.conf`` file and dhclient
|
||||
#### resolvconf_mode: host_resolvconf
|
||||
|
||||
This activates the classic Kubespray behavior that modifies the hosts ``/etc/resolv.conf`` file and dhclient
|
||||
configuration to point to the cluster dns server (either coredns or coredns_dual, depending on dns_mode).
|
||||
|
||||
As cluster DNS is not available on early deployment stage, this mode is split into 2 stages. In the first
|
||||
@@ -108,19 +119,21 @@ the other nameservers as backups.
|
||||
Also note, existing records will be purged from the `/etc/resolv.conf`,
|
||||
including resolvconf's base/head/cloud-init config files and those that come from dhclient.
|
||||
|
||||
#### none
|
||||
#### resolvconf_mode: none
|
||||
|
||||
Does nothing regarding ``/etc/resolv.conf``. This leaves you with a cluster that works as expected in most cases.
|
||||
The only exception is that ``hostNetwork: true`` PODs and non-k8s managed containers will not be able to resolve
|
||||
cluster service names.
|
||||
|
||||
## Nodelocal DNS cache
|
||||
Setting ``enable_nodelocaldns`` to ``true`` will make pods reach out to the dns (core-dns) caching agent running on the same node, thereby avoiding iptables DNAT rules and connection tracking. The local caching agent will query kube-dns / core-dns (depending on what main DNS plugin is configured in your cluster) for cache misses of cluster hostnames(cluster.local suffix by default).
|
||||
|
||||
Setting ``enable_nodelocaldns`` to ``true`` will make pods reach out to the dns (core-dns) caching agent running on the same node, thereby avoiding iptables DNAT rules and connection tracking. The local caching agent will query core-dns (depending on what main DNS plugin is configured in your cluster) for cache misses of cluster hostnames(cluster.local suffix by default).
|
||||
|
||||
More information on the rationale behind this implementation can be found [here](https://github.com/kubernetes/enhancements/blob/master/keps/sig-network/0030-nodelocal-dns-cache.md).
|
||||
|
||||
**As per the 2.10 release, Nodelocal DNS cache is enabled by default.**
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
## Limitations
|
||||
|
||||
* Kubespray has yet ways to configure Kubedns addon to forward requests SkyDns can
|
||||
not answer with authority to arbitrary recursive resolvers. This task is left
|
||||
@@ -129,9 +142,7 @@ Limitations
|
||||
|
||||
* There is
|
||||
[no way to specify a custom value](https://github.com/kubernetes/kubernetes/issues/33554)
|
||||
for the SkyDNS ``ndots`` param via an
|
||||
[option for KubeDNS](https://github.com/kubernetes/kubernetes/blob/master/cmd/kube-dns/app/options/options.go)
|
||||
add-on, while SkyDNS supports it though.
|
||||
for the SkyDNS ``ndots`` param.
|
||||
|
||||
* the ``searchdomains`` have a limitation of a 6 names and 256 chars
|
||||
length. Due to default ``svc, default.svc`` subdomains, the actual
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
Downloading binaries and containers
|
||||
===================================
|
||||
# Downloading binaries and containers
|
||||
|
||||
Kubespray supports several download/upload modes. The default is:
|
||||
|
||||
* Each node downloads binaries and container images on its own, which is
|
||||
``download_run_once: False``.
|
||||
* Each node downloads binaries and container images on its own, which is ``download_run_once: False``.
|
||||
* For K8s apps, pull policy is ``k8s_image_pull_policy: IfNotPresent``.
|
||||
* For system managed containers, like kubelet or etcd, pull policy is
|
||||
``download_always_pull: False``, which is pull if only the wanted repo and
|
||||
tag/sha256 digest differs from that the host has.
|
||||
* For system managed containers, like kubelet or etcd, pull policy is ``download_always_pull: False``, which is pull if only the wanted repo and tag/sha256 digest differs from that the host has.
|
||||
|
||||
There is also a "pull once, push many" mode as well:
|
||||
|
||||
* Override the ``download_run_once: True`` to download container images only once
|
||||
then push to cluster nodes in batches. The default delegate node
|
||||
for pushing images is the first `kube-master`.
|
||||
* If your ansible runner node (aka the admin node) have password-less sudo and
|
||||
docker enabled, you may want to define the ``download_localhost: True``, which
|
||||
makes that node a delegate for pushing images while running the deployment with
|
||||
ansible. This maybe the case if cluster nodes cannot access each over via ssh
|
||||
or you want to use local docker images as a cache for multiple clusters.
|
||||
* Setting ``download_run_once: True`` will make kubespray download container images and binaries only once and then push them to the cluster nodes. The default download delegate node is the first `kube-master`.
|
||||
* Set ``download_localhost: True`` to make localhost the download delegate. This can be useful if cluster nodes cannot access external addresses. To use this requires that docker is installed and running on the ansible master and that the current user is either in the docker group or can do passwordless sudo, to be able to access docker.
|
||||
|
||||
NOTE: When `download_run_once` is true and `download_localhost` is false, all downloads will be done on the delegate node, including downloads for container images that are not required on that node. As a consequence, the storage required on that node will probably be more than if download_run_once was false, because all images will be loaded into the docker instance on that node, instead of just the images required for that node.
|
||||
|
||||
On caching:
|
||||
|
||||
* When `download_run_once` is `True`, all downloaded files will be cached locally in `download_cache_dir`, which defaults to `/tmp/kubespray_cache`. On subsequent provisioning runs, this local cache will be used to provision the nodes, minimizing bandwidth usage and improving provisioning time. Expect about 800MB of disk space to be used on the ansible node for the cache. Disk space required for the image cache on the kubernetes nodes is a much as is needed for the largest image, which is currently slightly less than 150MB.
|
||||
* By default, if `download_run_once` is false, kubespray will not retrieve the downloaded images and files from the remote node to the local cache, or use that cache to pre-provision those nodes. To force the use of the cache, set `download_force_cache` to `True`.
|
||||
* By default, cached images that are used to pre-provision the remote nodes will be deleted from the remote nodes after use, to save disk space. Setting download_keep_remote_cache will prevent the files from being deleted. This can be useful while developing kubespray, as it can decrease provisioning times. As a consequence, the required storage for images on the remote nodes will increase from 150MB to about 550MB, which is currently the combined size of all required container images.
|
||||
|
||||
Container images and binary files are described by the vars like ``foo_version``,
|
||||
``foo_download_url``, ``foo_checksum`` for binaries and ``foo_image_repo``,
|
||||
@@ -29,15 +27,16 @@ Container images may be defined by its repo and tag, for example:
|
||||
`andyshinn/dnsmasq:2.72`. Or by repo and tag and sha256 digest:
|
||||
`andyshinn/dnsmasq@sha256:7c883354f6ea9876d176fe1d30132515478b2859d6fc0cbf9223ffdc09168193`.
|
||||
|
||||
Note, the sha256 digest and the image tag must be both specified and correspond
|
||||
Note, the SHA256 digest and the image tag must be both specified and correspond
|
||||
to each other. The given example above is represented by the following vars:
|
||||
```
|
||||
|
||||
```yaml
|
||||
dnsmasq_digest_checksum: 7c883354f6ea9876d176fe1d30132515478b2859d6fc0cbf9223ffdc09168193
|
||||
dnsmasq_image_repo: andyshinn/dnsmasq
|
||||
dnsmasq_image_tag: '2.72'
|
||||
```
|
||||
The full list of available vars may be found in the download's ansible role defaults.
|
||||
Those also allow to specify custom urls and local repositories for binaries and container
|
||||
|
||||
The full list of available vars may be found in the download's ansible role defaults. Those also allow to specify custom urls and local repositories for binaries and container
|
||||
images as well. See also the DNS stack docs for the related intranet configuration,
|
||||
so the hosts can resolve those urls and repos.
|
||||
|
||||
@@ -46,7 +45,7 @@ so the hosts can resolve those urls and repos.
|
||||
In case your servers don't have access to internet (for example when deploying on premises with security constraints), you'll have, first, to setup the appropriate proxies/caches/mirrors and/or internal repositories and registries and, then, adapt the following variables to fit your environment before deploying:
|
||||
|
||||
* At least `foo_image_repo` and `foo_download_url` as described before (i.e. in case of use of proxies to registries and binaries repositories, checksums and versions do not necessarily need to be changed).
|
||||
NB: Regarding `foo_image_repo`, when using insecure registries/proxies, you will certainly have to append them to the `docker_insecure_registries` variable in group_vars/all/docker.yml
|
||||
NOTE: Regarding `foo_image_repo`, when using insecure registries/proxies, you will certainly have to append them to the `docker_insecure_registries` variable in group_vars/all/docker.yml
|
||||
* `pyrepo_index` (and optionally `pyrepo_cert`)
|
||||
* Depending on the `container_manager`
|
||||
* When `container_manager=docker`, `docker_foo_repo_base_url`, `docker_foo_repo_gpgkey`, `dockerproject_bar_repo_base_url` and `dockerproject_bar_repo_gpgkey` (where `foo` is the distribution and `bar` is system package manager)
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
Flannel
|
||||
==============
|
||||
# Flannel
|
||||
|
||||
* Flannel configuration file should have been created there
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
cat /run/flannel/subnet.env
|
||||
FLANNEL_NETWORK=10.233.0.0/18
|
||||
FLANNEL_SUBNET=10.233.16.1/24
|
||||
@@ -13,7 +12,7 @@ FLANNEL_IPMASQ=false
|
||||
|
||||
* Check if the network interface has been created
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
ip a show dev flannel.1
|
||||
4: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default
|
||||
link/ether e2:f3:a7:0f:bf:cb brd ff:ff:ff:ff:ff:ff
|
||||
@@ -25,7 +24,7 @@ ip a show dev flannel.1
|
||||
|
||||
* Try to run a container and check its ip address
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
kubectl run test --image=busybox --command -- tail -f /dev/null
|
||||
replicationcontroller "test" created
|
||||
|
||||
@@ -33,7 +32,7 @@ kubectl describe po test-34ozs | grep ^IP
|
||||
IP: 10.233.16.2
|
||||
```
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
kubectl exec test-34ozs -- ip a show dev eth0
|
||||
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue
|
||||
link/ether 02:42:0a:e9:2b:03 brd ff:ff:ff:ff:ff:ff
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
Getting started
|
||||
===============
|
||||
# Getting started
|
||||
|
||||
Building your own inventory
|
||||
---------------------------
|
||||
## Building your own inventory
|
||||
|
||||
Ansible inventory can be stored in 3 formats: YAML, JSON, or INI-like. There is
|
||||
an example inventory located
|
||||
@@ -18,55 +16,65 @@ certain threshold. Run `python3 contrib/inventory_builder/inventory.py help` hel
|
||||
|
||||
Example inventory generator usage:
|
||||
|
||||
```ShellSession
|
||||
cp -r inventory/sample inventory/mycluster
|
||||
declare -a IPS=(10.10.1.3 10.10.1.4 10.10.1.5)
|
||||
CONFIG_FILE=inventory/mycluster/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]}
|
||||
```
|
||||
|
||||
Then use `inventory/mycluster/hosts.yml` as inventory file.
|
||||
|
||||
Starting custom deployment
|
||||
--------------------------
|
||||
## Starting custom deployment
|
||||
|
||||
Once you have an inventory, you may want to customize deployment data vars
|
||||
and start the deployment:
|
||||
|
||||
**IMPORTANT**: Edit my\_inventory/groups\_vars/\*.yaml to override data vars:
|
||||
|
||||
```ShellSession
|
||||
ansible-playbook -i inventory/mycluster/hosts.yml cluster.yml -b -v \
|
||||
--private-key=~/.ssh/private_key
|
||||
```
|
||||
|
||||
See more details in the [ansible guide](ansible.md).
|
||||
|
||||
Adding nodes
|
||||
------------
|
||||
### Adding nodes
|
||||
|
||||
You may want to add worker, master or etcd nodes to your existing cluster. This can be done by re-running the `cluster.yml` playbook, or you can target the bare minimum needed to get kubelet installed on the worker and talking to your masters. This is especially helpful when doing something like autoscaling your clusters.
|
||||
|
||||
- Add the new worker node to your inventory in the appropriate group (or utilize a [dynamic inventory](https://docs.ansible.com/ansible/intro_dynamic_inventory.html)).
|
||||
- Run the ansible-playbook command, substituting `cluster.yml` for `scale.yml`:
|
||||
|
||||
```ShellSession
|
||||
ansible-playbook -i inventory/mycluster/hosts.yml scale.yml -b -v \
|
||||
--private-key=~/.ssh/private_key
|
||||
|
||||
Remove nodes
|
||||
------------
|
||||
|
||||
You may want to remove **worker** nodes to your existing cluster. This can be done by re-running the `remove-node.yml` playbook. First, all nodes will be drained, then stop some kubernetes services and delete some certificates, and finally execute the kubectl command to delete these nodes. This can be combined with the add node function, This is generally helpful when doing something like autoscaling your clusters. Of course if a node is not working, you can remove the node and install it again.
|
||||
|
||||
Add worker nodes to the list under kube-node if you want to delete them (or utilize a [dynamic inventory](https://docs.ansible.com/ansible/intro_dynamic_inventory.html)).
|
||||
|
||||
ansible-playbook -i inventory/mycluster/hosts.yml remove-node.yml -b -v \
|
||||
--private-key=~/.ssh/private_key
|
||||
|
||||
Use `--extra-vars "node=<nodename>,<nodename2>"` to select the node you want to delete.
|
||||
```
|
||||
|
||||
### Remove nodes
|
||||
|
||||
You may want to remove **master**, **worker**, or **etcd** nodes from your
|
||||
existing cluster. This can be done by re-running the `remove-node.yml`
|
||||
playbook. First, all specified nodes will be drained, then stop some
|
||||
kubernetes services and delete some certificates,
|
||||
and finally execute the kubectl command to delete these nodes.
|
||||
This can be combined with the add node function. This is generally helpful
|
||||
when doing something like autoscaling your clusters. Of course, if a node
|
||||
is not working, you can remove the node and install it again.
|
||||
|
||||
Use `--extra-vars "node=<nodename>,<nodename2>"` to select the node(s) you want to delete.
|
||||
|
||||
```ShellSession
|
||||
ansible-playbook -i inventory/mycluster/hosts.yml remove-node.yml -b -v \
|
||||
--private-key=~/.ssh/private_key \
|
||||
--extra-vars "node=nodename,nodename2"
|
||||
```
|
||||
|
||||
Connecting to Kubernetes
|
||||
------------------------
|
||||
If a node is completely unreachable by ssh, add `--extra-vars reset_nodes=no`
|
||||
to skip the node reset step. If one node is unavailable, but others you wish
|
||||
to remove are able to connect via SSH, you could set reset_nodes=no as a host
|
||||
var in inventory.
|
||||
|
||||
## Connecting to Kubernetes
|
||||
|
||||
By default, Kubespray configures kube-master hosts with insecure access to
|
||||
kube-apiserver via port 8080. A kubeconfig file is not necessary in this case,
|
||||
@@ -88,8 +96,7 @@ file yourself.
|
||||
For more information on kubeconfig and accessing a Kubernetes cluster, refer to
|
||||
the Kubernetes [documentation](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/).
|
||||
|
||||
Accessing Kubernetes Dashboard
|
||||
------------------------------
|
||||
## Accessing Kubernetes Dashboard
|
||||
|
||||
As of kubernetes-dashboard v1.7.x:
|
||||
|
||||
@@ -106,8 +113,7 @@ Or you can run 'kubectl proxy' from your local machine to access dashboard in yo
|
||||
|
||||
It is recommended to access dashboard from behind a gateway (like Ingress Controller) that enforces an authentication token. Details and other access options here: <https://github.com/kubernetes/dashboard/wiki/Accessing-Dashboard---1.7.X-and-above>
|
||||
|
||||
Accessing Kubernetes API
|
||||
------------------------
|
||||
## Accessing Kubernetes API
|
||||
|
||||
The main client of Kubernetes is `kubectl`. It is installed on each kube-master
|
||||
host and can optionally be configured on your ansible host by setting
|
||||
@@ -118,7 +124,9 @@ host and can optionally be configured on your ansible host by setting
|
||||
|
||||
You can see a list of nodes by running the following commands:
|
||||
|
||||
```ShellSession
|
||||
cd inventory/mycluster/artifacts
|
||||
./kubectl.sh get nodes
|
||||
```
|
||||
|
||||
If desired, copy admin.conf to ~/.kube/config.
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
HA endpoints for K8s
|
||||
====================
|
||||
# HA endpoints for K8s
|
||||
|
||||
The following components require a highly available endpoints:
|
||||
|
||||
* etcd cluster,
|
||||
* kube-apiserver service instances.
|
||||
|
||||
The latter relies on a 3rd side reverse proxy, like Nginx or HAProxy, to
|
||||
achieve the same goal.
|
||||
|
||||
Etcd
|
||||
----
|
||||
## Etcd
|
||||
|
||||
The etcd clients (kube-api-masters) are configured with the list of all etcd peers. If the etcd-cluster has multiple instances, it's configured in HA already.
|
||||
|
||||
Kube-apiserver
|
||||
--------------
|
||||
## Kube-apiserver
|
||||
|
||||
K8s components require a loadbalancer to access the apiservers via a reverse
|
||||
proxy. Kubespray includes support for an nginx-based proxy that resides on each
|
||||
@@ -50,7 +49,8 @@ provides access for external clients, while the internal LB accepts client
|
||||
connections only to the localhost.
|
||||
Given a frontend `VIP` address and `IP1, IP2` addresses of backends, here is
|
||||
an example configuration for a HAProxy service acting as an external LB:
|
||||
```
|
||||
|
||||
```raw
|
||||
listen kubernetes-apiserver-https
|
||||
bind <VIP>:8383
|
||||
option ssl-hello-chk
|
||||
@@ -66,7 +66,8 @@ listen kubernetes-apiserver-https
|
||||
|
||||
And the corresponding example global vars for such a "cluster-aware"
|
||||
external LB with the cluster API access modes configured in Kubespray:
|
||||
```
|
||||
|
||||
```yml
|
||||
apiserver_loadbalancer_domain_name: "my-apiserver-lb.example.com"
|
||||
loadbalancer_apiserver:
|
||||
address: <VIP>
|
||||
@@ -102,13 +103,14 @@ exclusive to `loadbalancer_apiserver_localhost`.
|
||||
Access API endpoints are evaluated automatically, as the following:
|
||||
|
||||
| Endpoint type | kube-master | non-master | external |
|
||||
|------------------------------|----------------|---------------------|---------------------|
|
||||
| Local LB (default) | https://bip:sp | https://lc:nsp | https://m[0].aip:sp |
|
||||
| Local LB + Unmanaged here LB | https://bip:sp | https://lc:nsp | https://ext |
|
||||
| External LB, no internal | https://bip:sp | https://lb:lp | https://lb:lp |
|
||||
| No ext/int LB | https://bip:sp | https://m[0].aip:sp | https://m[0].aip:sp |
|
||||
|------------------------------|------------------|-------------------------|-----------------------|
|
||||
| Local LB (default) | `https://bip:sp` | `https://lc:nsp` | `https://m[0].aip:sp` |
|
||||
| Local LB + Unmanaged here LB | `https://bip:sp` | `https://lc:nsp` | `https://ext` |
|
||||
| External LB, no internal | `https://bip:sp` | `<https://lb:lp>` | `https://lb:lp` |
|
||||
| No ext/int LB | `https://bip:sp` | `<https://m[0].aip:sp>` | `https://m[0].aip:sp` |
|
||||
|
||||
Where:
|
||||
|
||||
* `m[0]` - the first node in the `kube-master` group;
|
||||
* `lb` - LB FQDN, `apiserver_loadbalancer_domain_name`;
|
||||
* `ext` - Externally load balanced VIP:port and FQDN, not managed by Kubespray;
|
||||
@@ -132,16 +134,19 @@ Kubespray, the masters' APIs are accessed via the insecure endpoint, which
|
||||
consists of the local `kube_apiserver_insecure_bind_address` and
|
||||
`kube_apiserver_insecure_port`.
|
||||
|
||||
Optional configurations
|
||||
------------------------
|
||||
## Optional configurations
|
||||
|
||||
### ETCD with a LB
|
||||
|
||||
In order to use an external loadbalancing (L4/TCP or L7 w/ SSL Passthrough VIP), the following variables need to be overridden in group_vars
|
||||
|
||||
* `etcd_access_addresses`
|
||||
* `etcd_client_url`
|
||||
* `etcd_cert_alt_names`
|
||||
* `etcd_cert_alt_ips`
|
||||
|
||||
#### Example of a VIP w/ FQDN
|
||||
|
||||
```yaml
|
||||
etcd_access_addresses: https://etcd.example.com:2379
|
||||
etcd_client_url: https://etcd.example.com:2379
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
|
||||
2. Add **forked repo** as submodule to desired folder in your existent ansible repo(for example 3d/kubespray):
|
||||
```git submodule add https://github.com/YOUR_GITHUB/kubespray.git kubespray```
|
||||
Git will create _.gitmodules_ file in your existent ansible repo:
|
||||
```
|
||||
Git will create `.gitmodules` file in your existent ansible repo:
|
||||
|
||||
```ini
|
||||
[submodule "3d/kubespray"]
|
||||
path = 3d/kubespray
|
||||
url = https://github.com/YOUR_GITHUB/kubespray.git
|
||||
@@ -21,7 +22,8 @@
|
||||
```git remote add upstream https://github.com/kubernetes-sigs/kubespray.git```
|
||||
|
||||
5. Sync your master branch with upstream:
|
||||
```
|
||||
|
||||
```ShellSession
|
||||
git checkout master
|
||||
git fetch upstream
|
||||
git merge upstream/master
|
||||
@@ -33,19 +35,21 @@
|
||||
***Never*** use master branch of your repository for your commits.
|
||||
|
||||
7. Modify path to library and roles in your ansible.cfg file (role naming should be uniq, you may have to rename your existent roles if they have same names as kubespray project):
|
||||
```
|
||||
|
||||
```ini
|
||||
...
|
||||
library = 3d/kubespray/library/
|
||||
roles_path = 3d/kubespray/roles/
|
||||
...
|
||||
```
|
||||
|
||||
8. Copy and modify configs from kubespray `group_vars` folder to corresponging `group_vars` folder in your existent project.
|
||||
8. Copy and modify configs from kubespray `group_vars` folder to corresponding `group_vars` folder in your existent project.
|
||||
You could rename *all.yml* config to something else, i.e. *kubespray.yml* and create corresponding group in your inventory file, which will include all hosts groups related to kubernetes setup.
|
||||
|
||||
9. Modify your ansible inventory file by adding mapping of your existent groups (if any) to kubespray naming.
|
||||
For example:
|
||||
```
|
||||
|
||||
```ini
|
||||
...
|
||||
#Kargo groups:
|
||||
[kube-node:children]
|
||||
@@ -65,54 +69,62 @@ You could rename *all.yml* config to something else, i.e. *kubespray.yml* and cr
|
||||
[kubespray:children]
|
||||
kubernetes
|
||||
```
|
||||
|
||||
* Last entry here needed to apply kubespray.yml config file, renamed from all.yml of kubespray project.
|
||||
|
||||
10. Now you can include kubespray tasks in you existent playbooks by including cluster.yml file:
|
||||
```
|
||||
|
||||
```yml
|
||||
- name: Include kubespray tasks
|
||||
include: 3d/kubespray/cluster.yml
|
||||
```
|
||||
|
||||
Or your could copy separate tasks from cluster.yml into your ansible repository.
|
||||
|
||||
11. Commit changes to your ansible repo. Keep in mind, that submodule folder is just a link to the git commit hash of your forked repo.
|
||||
When you update your "work" branch you need to commit changes to ansible repo as well.
|
||||
Other members of your team should use ```git submodule sync```, ```git submodule update --init``` to get actual code from submodule.
|
||||
|
||||
# Contributing
|
||||
## Contributing
|
||||
|
||||
If you made useful changes or fixed a bug in existent kubespray repo, use this flow for PRs to original kubespray repo.
|
||||
|
||||
0. Sign the [CNCF CLA](https://git.k8s.io/community/CLA.md).
|
||||
1. Sign the [CNCF CLA](https://git.k8s.io/community/CLA.md).
|
||||
|
||||
1. Change working directory to git submodule directory (3d/kubespray).
|
||||
2. Change working directory to git submodule directory (3d/kubespray).
|
||||
|
||||
2. Setup desired user.name and user.email for submodule.
|
||||
3. Setup desired user.name and user.email for submodule.
|
||||
If kubespray is only one submodule in your repo you could use something like:
|
||||
```git submodule foreach --recursive 'git config user.name "First Last" && git config user.email "your-email-addres@used.for.cncf"'```
|
||||
|
||||
3. Sync with upstream master:
|
||||
```
|
||||
4. Sync with upstream master:
|
||||
|
||||
```ShellSession
|
||||
git fetch upstream
|
||||
git merge upstream/master
|
||||
git push origin master
|
||||
```
|
||||
4. Create new branch for the specific fixes that you want to contribute:
|
||||
|
||||
5. Create new branch for the specific fixes that you want to contribute:
|
||||
```git checkout -b fixes-name-date-index```
|
||||
Branch name should be self explaining to you, adding date and/or index will help you to track/delete your old PRs.
|
||||
|
||||
5. Find git hash of your commit in "work" repo and apply it to newly created "fix" repo:
|
||||
```
|
||||
6. Find git hash of your commit in "work" repo and apply it to newly created "fix" repo:
|
||||
|
||||
```ShellSession
|
||||
git cherry-pick <COMMIT_HASH>
|
||||
```
|
||||
6. If your have several temporary-stage commits - squash them using [```git rebase -i```](http://eli.thegreenplace.net/2014/02/19/squashing-github-pull-requests-into-a-single-commit)
|
||||
|
||||
7. If your have several temporary-stage commits - squash them using [```git rebase -i```](http://eli.thegreenplace.net/2014/02/19/squashing-github-pull-requests-into-a-single-commit)
|
||||
Also you could use interactive rebase (```git rebase -i HEAD~10```) to delete commits which you don't want to contribute into original repo.
|
||||
|
||||
7. When your changes is in place, you need to check upstream repo one more time because it could be changed during your work.
|
||||
8. When your changes is in place, you need to check upstream repo one more time because it could be changed during your work.
|
||||
Check that you're on correct branch:
|
||||
```git status```
|
||||
And pull changes from upstream (if any):
|
||||
```git pull --rebase upstream master```
|
||||
|
||||
8. Now push your changes to your **fork** repo with ```git push```. If your branch doesn't exists on github, git will propose you to use something like ```git push --set-upstream origin fixes-name-date-index```.
|
||||
9. Now push your changes to your **fork** repo with ```git push```. If your branch doesn't exists on github, git will propose you to use something like ```git push --set-upstream origin fixes-name-date-index```.
|
||||
|
||||
9. Open you forked repo in browser, on the main page you will see proposition to create pull request for your newly created branch. Check proposed diff of your PR. If something is wrong you could safely delete "fix" branch on github using ```git push origin --delete fixes-name-date-index```, ```git branch -D fixes-name-date-index``` and start whole process from the beginning.
|
||||
10. Open you forked repo in browser, on the main page you will see proposition to create pull request for your newly created branch. Check proposed diff of your PR. If something is wrong you could safely delete "fix" branch on github using ```git push origin --delete fixes-name-date-index```, ```git branch -D fixes-name-date-index``` and start whole process from the beginning.
|
||||
If everything is fine - add description about your changes (what they do and why they're needed) and confirm pull request creation.
|
||||
|
||||
49
docs/kube-ovn.md
Normal file
49
docs/kube-ovn.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Kube-OVN
|
||||
|
||||
Kube-OVN integrates the OVN-based Network Virtualization with Kubernetes. It offers an advanced Container Network Fabric for Enterprises.
|
||||
|
||||
For more information please check [Kube-OVN documentation](https://github.com/alauda/kube-ovn)
|
||||
|
||||
## How to use it
|
||||
|
||||
Enable kube-ovn in `group_vars/k8s-cluster/k8s-cluster.yml`
|
||||
|
||||
```yml
|
||||
...
|
||||
kube_network_plugin: kube-ovn
|
||||
...
|
||||
```
|
||||
|
||||
## Verifying kube-ovn install
|
||||
|
||||
Kube-OVN run ovn and controller in `kube-ovn` namespace
|
||||
|
||||
* Check the status of kube-ovn pods
|
||||
|
||||
```ShellSession
|
||||
# From the CLI
|
||||
kubectl get pod -n kube-ovn
|
||||
|
||||
# Output
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
kube-ovn-cni-49lsm 1/1 Running 0 2d20h
|
||||
kube-ovn-cni-9db8f 1/1 Running 0 2d20h
|
||||
kube-ovn-cni-wftdk 1/1 Running 0 2d20h
|
||||
kube-ovn-controller-68d7bb48bd-7tnvg 1/1 Running 0 2d21h
|
||||
ovn-central-6675dbb7d9-d7z8m 1/1 Running 0 4d16h
|
||||
ovs-ovn-hqn8p 1/1 Running 0 4d16h
|
||||
ovs-ovn-hvpl8 1/1 Running 0 4d16h
|
||||
ovs-ovn-r5frh 1/1 Running 0 4d16h
|
||||
```
|
||||
|
||||
* Check the default and node subnet
|
||||
|
||||
```ShellSession
|
||||
# From the CLI
|
||||
kubectl get subnet
|
||||
|
||||
# Output
|
||||
NAME PROTOCOL CIDR PRIVATE NAT
|
||||
join IPv4 100.64.0.0/16 false false
|
||||
ovn-default IPv4 10.16.0.0/16 false true
|
||||
```
|
||||
@@ -1,5 +1,4 @@
|
||||
Kube-router
|
||||
===========
|
||||
# Kube-router
|
||||
|
||||
Kube-router is a L3 CNI provider, as such it will setup IPv4 routing between
|
||||
nodes to provide Pods' networks reachability.
|
||||
@@ -12,7 +11,7 @@ Kube-router runs its pods as a `DaemonSet` in the `kube-system` namespace:
|
||||
|
||||
* Check the status of kube-router pods
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
# From the CLI
|
||||
kubectl get pod --namespace=kube-system -l k8s-app=kube-router -owide
|
||||
|
||||
@@ -29,7 +28,7 @@ kube-router-x2xs7 1/1 Running 0 2d 192.168.186.10 my
|
||||
|
||||
* Peek at kube-router container logs:
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
# From the CLI
|
||||
kubectl logs --namespace=kube-system -l k8s-app=kube-router | grep Peer.Up
|
||||
|
||||
@@ -56,24 +55,24 @@ You need to `kubectl exec -it ...` into a kube-router container to use these, se
|
||||
|
||||
## Kube-router configuration
|
||||
|
||||
|
||||
You can change the default configuration by overriding `kube_router_...` variables
|
||||
(as found at `roles/network_plugin/kube-router/defaults/main.yml`),
|
||||
these are named to follow `kube-router` command-line options as per
|
||||
<https://www.kube-router.io/docs/user-guide/#try-kube-router-with-cluster-installers>.
|
||||
|
||||
## Advanced BGP Capabilities
|
||||
https://github.com/cloudnativelabs/kube-router#advanced-bgp-capabilities
|
||||
|
||||
<https://github.com/cloudnativelabs/kube-router#advanced-bgp-capabilities>
|
||||
|
||||
If you have other networking devices or SDN systems that talk BGP, kube-router will fit in perfectly.
|
||||
From a simple full node-to-node mesh to per-node peering configurations, most routing needs can be attained.
|
||||
The configuration is Kubernetes native (annotations) just like the rest of kube-router.
|
||||
|
||||
For more details please refer to the https://github.com/cloudnativelabs/kube-router/blob/master/docs/bgp.md.
|
||||
For more details please refer to the <https://github.com/cloudnativelabs/kube-router/blob/master/docs/bgp.md.>
|
||||
|
||||
Next options will set up annotations for kube-router, using `kubectl annotate` command.
|
||||
|
||||
```
|
||||
```yml
|
||||
kube_router_annotations_master: []
|
||||
kube_router_annotations_node: []
|
||||
kube_router_annotations_all: []
|
||||
|
||||
@@ -26,7 +26,7 @@ By default the normal behavior looks like:
|
||||
> etcd in 6-7 seconds or even longer when etcd cannot commit data to quorum
|
||||
> nodes.
|
||||
|
||||
# Failure
|
||||
## Failure
|
||||
|
||||
Kubelet will try to make `nodeStatusUpdateRetry` post attempts. Currently
|
||||
`nodeStatusUpdateRetry` is constantly set to 5 in
|
||||
@@ -50,7 +50,7 @@ Kube proxy has a watcher over API. Once pods are evicted, Kube proxy will
|
||||
notice and will update iptables of the node. It will remove endpoints from
|
||||
services so pods from failed node won't be accessible anymore.
|
||||
|
||||
# Recommendations for different cases
|
||||
## Recommendations for different cases
|
||||
|
||||
## Fast Update and Fast Reaction
|
||||
|
||||
|
||||
41
docs/macvlan.md
Normal file
41
docs/macvlan.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Macvlan
|
||||
|
||||
## How to use it
|
||||
|
||||
* Enable macvlan in `group_vars/k8s-cluster/k8s-cluster.yml`
|
||||
|
||||
```yml
|
||||
...
|
||||
kube_network_plugin: macvlan
|
||||
...
|
||||
```
|
||||
|
||||
* Adjust the `macvlan_interface` in `group_vars/k8s-cluster/k8s-net-macvlan.yml` or by host in the `host.yml` file:
|
||||
|
||||
```yml
|
||||
all:
|
||||
hosts:
|
||||
node1:
|
||||
ip: 10.2.2.1
|
||||
access_ip: 10.2.2.1
|
||||
ansible_host: 10.2.2.1
|
||||
macvlan_interface: ens5
|
||||
```
|
||||
|
||||
## Issue encountered
|
||||
|
||||
* Service DNS
|
||||
|
||||
reply from unexpected source:
|
||||
|
||||
add `kube_proxy_masquerade_all: true` in `group_vars/all/all.yml`
|
||||
|
||||
* Disable nodelocaldns
|
||||
|
||||
The nodelocal dns IP is not reacheable.
|
||||
|
||||
Disable it in `sample/group_vars/k8s-cluster/k8s-cluster.yml`
|
||||
|
||||
```yml
|
||||
enable_nodelocaldns: false
|
||||
```
|
||||
@@ -1,5 +1,4 @@
|
||||
Multus
|
||||
===========
|
||||
# Multus
|
||||
|
||||
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
|
||||
@@ -10,17 +9,19 @@ See [multus documentation](https://github.com/intel/multus-cni).
|
||||
## Multus installation
|
||||
|
||||
Since Multus itself does not implement networking, it requires a master plugin, which is specified through the variable `kube_network_plugin`. To enable Multus an additional variable `kube_network_plugin_multus` must be set to `true`. For example,
|
||||
```
|
||||
|
||||
```yml
|
||||
kube_network_plugin: calico
|
||||
kube_network_plugin_multus: true
|
||||
```
|
||||
|
||||
will install Multus and Calico and configure Multus to use Calico as the primary network plugin.
|
||||
|
||||
## Using Multus
|
||||
|
||||
Once Multus is installed, you can create CNI configurations (as a CRD objects) for additional networks, in this case a macvlan CNI configuration is defined. You may replace the config field with any valid CNI configuration where the CNI binary is available on the nodes.
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
cat <<EOF | kubectl create -f -
|
||||
apiVersion: "k8s.cni.cncf.io/v1"
|
||||
kind: NetworkAttachmentDefinition
|
||||
@@ -48,7 +49,7 @@ EOF
|
||||
|
||||
You may then create a pod with and additional interface that connects to this network using annotations. The annotation correlates to the name in the NetworkAttachmentDefinition above.
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
cat <<EOF | kubectl create -f -
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
@@ -66,8 +67,8 @@ EOF
|
||||
|
||||
You may now inspect the pod and see that there is an additional interface configured:
|
||||
|
||||
```
|
||||
$ kubectl exec -it samplepod -- ip a
|
||||
```ShellSession
|
||||
kubectl exec -it samplepod -- ip a
|
||||
```
|
||||
|
||||
For more details on how to use Multus, please visit https://github.com/intel/multus-cni
|
||||
For more details on how to use Multus, please visit <https://github.com/intel/multus-cni>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
Network Checker Application
|
||||
===========================
|
||||
# Network Checker Application
|
||||
|
||||
With the ``deploy_netchecker`` var enabled (defaults to false), Kubespray deploys a
|
||||
Network Checker Application from the 3rd side `l23network/k8s-netchecker` docker
|
||||
@@ -14,14 +13,17 @@ logs.
|
||||
|
||||
To get the most recent and cluster-wide network connectivity report, run from
|
||||
any of the cluster nodes:
|
||||
```
|
||||
|
||||
```ShellSession
|
||||
curl http://localhost:31081/api/v1/connectivity_check
|
||||
```
|
||||
|
||||
Note that Kubespray does not invoke the check but only deploys the application, if
|
||||
requested.
|
||||
|
||||
There are related application specific variables:
|
||||
```
|
||||
|
||||
```yml
|
||||
netchecker_port: 31081
|
||||
agent_report_interval: 15
|
||||
netcheck_namespace: default
|
||||
@@ -33,7 +35,7 @@ combination of the ``netcheck_namespace.dns_domain`` vars, for example the
|
||||
to the non default namespace, make sure as well to adjust the ``searchdomains`` var
|
||||
so the resulting search domain records to contain that namespace, like:
|
||||
|
||||
```
|
||||
```yml
|
||||
search: foospace.cluster.local default.cluster.local ...
|
||||
nameserver: ...
|
||||
```
|
||||
|
||||
@@ -5,6 +5,9 @@ To deploy kubespray on [OpenStack](https://www.openstack.org/) uncomment the `cl
|
||||
|
||||
After that make sure to source in your OpenStack credentials like you would do when using `nova-client` or `neutron-client` by using `source path/to/your/openstack-rc` or `. path/to/your/openstack-rc`.
|
||||
|
||||
For those who prefer to pass the OpenStack CA certificate as a string, one can
|
||||
base64 encode the cacert file and store it in the variable `openstack_cacert`.
|
||||
|
||||
The next step is to make sure the hostnames in your `inventory` file are identical to your instance names in OpenStack.
|
||||
Otherwise [cinder](https://wiki.openstack.org/wiki/Cinder) won't work as expected.
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
openSUSE Leap 15.0 and Tumbleweed
|
||||
===============
|
||||
# openSUSE Leap 15.0 and Tumbleweed
|
||||
|
||||
openSUSE Leap installation Notes:
|
||||
|
||||
- Install Ansible
|
||||
|
||||
```
|
||||
```ShellSession
|
||||
sudo zypper ref
|
||||
sudo zypper -n install ansible
|
||||
|
||||
@@ -15,5 +14,4 @@ openSUSE Leap installation Notes:
|
||||
|
||||
```sudo zypper -n install python-Jinja2 python-netaddr```
|
||||
|
||||
|
||||
Now you can continue with [Preparing your deployment](getting-started.md#starting-custom-deployment)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
Packet
|
||||
===============
|
||||
# Packet
|
||||
|
||||
Kubespray provides support for bare metal deployments using the [Packet bare metal cloud](http://www.packet.com).
|
||||
Deploying upon bare metal allows Kubernetes to run at locations where an existing public or private cloud might not exist such
|
||||
@@ -37,10 +36,11 @@ Terraform is required to deploy the bare metal infrastructure. The steps below a
|
||||
[More terraform installation options are available.](https://learn.hashicorp.com/terraform/getting-started/install.html)
|
||||
|
||||
Grab the latest version of Terraform and install it.
|
||||
|
||||
```bash
|
||||
echo "https://releases.hashicorp.com/terraform/$(curl -s https://checkpoint-api.hashicorp.com/v1/check/terraform | jq -r -M '.current_version')/terraform_$(curl -s https://checkpoint-api.hashicorp.com/v1/check/terraform | jq -r -M '.current_version')_darwin_amd64.zip"
|
||||
sudo yum install unzip
|
||||
sudo unzip terraform_0.11.11_linux_amd64.zip -d /usr/local/bin/
|
||||
sudo unzip terraform_0.12.12_linux_amd64.zip -d /usr/local/bin/
|
||||
```
|
||||
|
||||
## Download Kubespray
|
||||
@@ -67,8 +67,9 @@ Details about the cluster, such as the name, as well as the authentication token
|
||||
for Packet need to be defined. To find these values see [Packet API Integration](https://support.packet.com/kb/articles/api-integrations)
|
||||
|
||||
```bash
|
||||
vi cluster.tf
|
||||
vi cluster.tfvars
|
||||
```
|
||||
|
||||
* cluster_name = alpha
|
||||
* packet_project_id = ABCDEFGHIJKLMNOPQRSTUVWXYZ123456
|
||||
* public_key_path = 12345678-90AB-CDEF-GHIJ-KLMNOPQRSTUV
|
||||
@@ -84,7 +85,7 @@ terraform init ../../contrib/terraform/packet/
|
||||
Run Terraform to deploy the hardware.
|
||||
|
||||
```bash
|
||||
terraform apply -var-file=cluster.tf ../../contrib/terraform/packet
|
||||
terraform apply -var-file=cluster.tfvars ../../contrib/terraform/packet
|
||||
```
|
||||
|
||||
## Run Kubespray Playbooks
|
||||
@@ -94,4 +95,3 @@ With the bare metal infrastructure deployed, Kubespray can now install Kubernete
|
||||
```bash
|
||||
ansible-playbook --become -i inventory/alpha/hosts cluster.yml
|
||||
```
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user