Compare commits

...

272 Commits

Author SHA1 Message Date
rtsp
c91a05f330 debian: Fix test failed after bullseye release (#7888)
(cherry picked from commit 79166496f3)
2021-10-29 07:46:51 -07:00
Utku Ozdemir
a583a2d9aa Implement drain fallback with --disable-eviction to ignore PDBs
Signed-off-by: Utku Ozdemir <uoz@protonmail.com>
2021-10-29 07:46:51 -07:00
Vitaliy D
713abf29ca Update vSphere CPI (#7840)
Backport of #7838

Changes:
  * ClusterRole updated according to the latest manifests from
    https://github.com/kubernetes/cloud-provider-vsphere
  * vSphere CPI/CSI default versions bumped and
    tested successfully on K8S 1.21.1
  * vSphere documentation updated

Signed-off-by: Vitaliy D <vi7alya@gmail.com>
2021-07-30 06:03:37 -07:00
Kenichi Omichi
247d062c02 [2.16] Fix how to get image ID on offline deployment (#7829)
* Add error handling for registorying images (#7787)

When running the script, I faced the following error but it was
difficult to know the root problem due to lack of error handling.

  docker tag" requires exactly 2 arguments.
  See 'docker tag --help'.

  Usage:  docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

  Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE

To investigate such errors easily, this adds an error handling.

* Fix how to get image ID on offline deployment (#7808)

Previously IDs of container images were gotten from tar files of container
images but that way was wrong. If multiple json files are contained in a
tar file, the script got multiple IDs and tried to pass these IDs on
`docker tag` command. Then the command was failed.

This updates the script to get image IDs from `docker image inspect` command
to fix this issue.
In addition, this adds a check a registry container exists already or not
before deploying registry container to avoid a container conflict failure.
2021-07-28 00:01:35 -07:00
Kenichi Omichi
9fa051780e [2.16] Disable OVH CI until voucher situation is cleared up (#7824) (#7831)
* Disable OVH CI until  voucher situation is cleared up (#7824)

* Allow failure on tf-elax_ubuntu18-calico (#7814)

tf-elax_ubuntu18-calico is so flake today. The test job is failed
due to SSH connectivity check error after deploying virtual machines
which are used for Kubernetes nodes.
This allows failure on the job to see the test situation without
pull request merger failures.

Co-authored-by: Maxime Guyot <Miouge1@users.noreply.github.com>
2021-07-27 06:16:45 -07:00
Florian Ruynat
bcf695913f Fix Oracle yum disabled repository file after EPEL install (#7639) 2021-05-25 08:30:23 -07:00
Catblade
23cd1d41fb Minor spelling edits (#7640)
Minor spelling edits.  Was reading your documentation.
2021-05-24 23:48:22 -07:00
rptaylor
62f5369237 Remove warning about Docker-only support (#7626) 2021-05-20 00:01:05 -07:00
Fatih Sarhan
59fc17f4e3 Override the default value of containerd's root, state, and oom_score (#7622)
* Override the default value of containerd's root, state, and oom_score configurations

* Add tests data for containerd_storage_dir, containerd_state_dir and containerd_oom_score variables
2021-05-19 08:24:53 -07:00
rptaylor
26c1d42fff add note on download_localhost (#7623)
It can be counterintuitive for the downloaded files to show up on local host when download_localhost is false, this explains the reason.
2021-05-19 05:04:51 -07:00
Florian Ruynat
c1aa755a3c Fix missing broken_etcd filter in recover control plane task (#7619) 2021-05-18 10:29:04 -07:00
Kenichi Omichi
b3d9f2b4a2 Add contrib playbook to disable service firewall (#7431)
Basically we need to make necessary TCP/UDP ports open.
However the necessary ports are so many, and sometimes it is difficult
to figure out that is due to firewall issues or not if facing deployment
issues.
To distinguish a root problem on such situation, this adds contrib
playbook to disable the service firewall for Kubespray development
and test.
2021-05-18 06:45:30 -07:00
Pavel Martynov
29c2fbdbc1 Fix cloud_resolver type from str to list (issue #7605) (#7606) 2021-05-18 06:41:30 -07:00
Pavel Martynov
4b9f98f933 Fix pull_by_digest variable type to boolean instead of str (#7612) 2021-05-18 06:29:31 -07:00
Cristian Calin
e9870b8d25 add support for using ansible 2.10.x for deploying kubespray (#7600)
* add support for using ansible 2.10.x for deploying kubespray

* move dns-autoscaler-clusterrole{binding}.yml to files/ folder

* note that ansible 2.10 is now experimentally supported

* coredns: move files to templates like before #4341
2021-05-18 05:39:31 -07:00
Muzi Li
e0c74fa082 Update nerdctl version to 0.8.1 (#7617) 2021-05-17 11:07:30 -07:00
Cristian Calin
5b93a97281 remove experimental note about CentOS 8 and derivatives (#7615) 2021-05-16 12:07:59 -07:00
Florian Ruynat
bdf74c6749 Set default version to 1.20.7 2021-05-14 09:48:06 -07:00
Florian Ruynat
d6f9a8d752 Update hashes with 1.21.1/1.20.7/1.19.11 2021-05-14 09:48:06 -07:00
Cristian Calin
e357d8678c update README about supported OSes (#7608) 2021-05-14 00:06:05 -07:00
tkob
b1b407a0b4 Replace map in Terraform scripts with tomap (#7576) (#7578)
* Replace map in Terraform scripts with tomap (#7576)

* Fix Terraform linter warnings (#7576)
2021-05-12 07:34:17 -07:00
Sergey
6c3d1649a6 fixed MarkupSafe version to 1.1.1 (#7607) 2021-05-12 06:52:17 -07:00
Cristian Calin
14cf3e138b Support Calico advertisement of MetalLB LoadBalancer IPs (#7593)
* add initial MetalLB docs

* metallb allow disabling the deployment of the metallb speaker

* calico>=3.18 allow using calico to advertise service loadbalancer IPs

* Document the use of MetalLB and Calico

* clean MetalLB docs
2021-05-12 05:22:17 -07:00
emiran-orange
afbabebfd5 Enables Calico serviceAccount token monitoring and update of /etc/cni/net.d/calico-kubeconfig if need be. (#7586)
Since K8S 1.21, BoundServiceAccountTokenVolume feature gate is in beta stage, thus activated by default (anyone who follows CSI guidelines has enabled AllAlpha and faced the issue before 1.21).
With this feature, SA tokens are regenerated every hour.
As a consequence for Calico CNI, token in /etc/cni/net.d/calico-kubeconfig copied from /var/run/secrets/kubernetes.io/serviceaccount in install-cni initContainer expires after one hour and any pod creation fails due to unauthorization.
Calico pods need to be restarted so that /etc/cni/net.d/calico-kubeconfig is updated with the new SA token.
2021-05-11 08:47:36 -07:00
Cristian Calin
8c0a2741ae allow overriding calico peers names and avoid ipv6 naming issues (#7591) 2021-05-11 07:05:36 -07:00
muzi502
1d078e1119 Add script for generate download files and images list (#7561)
Fix coredns image repo and tag typo for #7570
2021-05-11 00:39:36 -07:00
Cristian Calin
d90baa8601 add containerd support for Amazon Linux 2 (#7595) 2021-05-10 19:25:36 -07:00
muzi502
d5660cd37c Fix reset cluster task failed (#7597) 2021-05-10 17:25:36 -07:00
Cristian Calin
63cec45597 Add Amazon to the check for supported distributions (#7589) 2021-05-10 16:17:36 -07:00
Hari Hud
f07e24db8f Cleanup duplicate task in etcd role (#7598)
* Remove the duplicate task in etcd role

* Remove inessential delegate_to
2021-05-10 16:11:36 -07:00
Cristian Calin
5d5be3e96a bump calico 3.18 to v3.18.3 (#7592) 2021-05-10 00:34:51 -07:00
Hari Hud
6e7649360f Ignore error when ipvsadm utility not found on node (#7587) 2021-05-07 13:37:04 -07:00
Cedric Hnyda
1dd38721b3 Add external_openstack_enable_ingress_hostname option for openstack (#7572)
Signed-off-by: Cedric Hnyda <cedric.hnyda@itera.io>
2021-05-04 00:33:11 -07:00
Eugene Artemenko
6a001e4971 Add suport of Vsphere CSI driver 2.X versions (#7480) 2021-05-04 00:05:11 -07:00
Samuel Liu
96e6a6ac3f Add krew support (#7464)
* Add krew support

* Add reset for krew

* Update install krew(local)

* ansible lint

* yamllint

* fix krew default vars

* fix kubectl_localhost mode

* replace include

* fix e206
2021-05-03 07:16:03 -07:00
bac-w
2556eb2733 Upgrade cilium role (#7521)
* Upgrade cilium roles

* Del old test result

* Add hubble ui examples

* Refactor hubble metrics

* Markdown fix pipeline errors

* yamllint check and fix

* refactor install from https://github.com/kubernetes-sigs/kubespray/pull/7520

* Docs syntax change (fix)

* Cilium set default 1.8.9

* Update cilium version in Readme
2021-04-30 08:09:59 -07:00
Florian Ruynat
d29ea386d6 Fix issue with api token wait check not working (#7566) 2021-04-30 07:47:59 -07:00
MRoci
a0ee569091 change coredns image name to coredns/coredns and prefix v to tag (#7570)
follow new naming conventions for gcr's coredns image.
starting from 1.21 kubeadm assumes it to be `coredns/coredns`:
this causes the kubeadm deployment being unable to pull image, beacuse `v`
was also added in image tag, until the role `kubernetes-apps` ovverides
it with the old name, which is only compatible with <=1.7.

Backward comptability with kubeadm <=1.20 is mantained checking
kubernetes version and falling back to old names (`coredns:1.xx`) when
the version is less than 1.21
2021-04-30 07:43:58 -07:00
holmesb
3f4eb9be08 Fixes issue #7573 - Made Calico permissions compatible with v3.18.x (see https://github.com/projectcalico/calico/issues/4557). Specifically, granted watch to custom resources blockaffinities, ipamblocks & ipamhandles (#7575) 2021-04-30 07:25:59 -07:00
muzi502
5ea2d1eb67 Add image_arch in flannel image tag (#7560)
* Add image_arch variable when download flannel image

* Fix flannel image tag typo with image arch
2021-04-29 17:51:57 -07:00
Florian Ruynat
ffc38a2237 Fix busybox for tests to reduce dockerhub calls (#7571) 2021-04-29 17:39:57 -07:00
Cristian Calin
360aff4a57 Rename ansible groups to use _ instead of - (#7552)
* rename ansible groups to use _ instead of -

k8s-cluster -> k8s_cluster
k8s-node -> k8s_node
calico-rr -> calico_rr
no-floating -> no_floating

Note: kube-node,k8s-cluster groups in upgrade CI
      need clean-up after v2.16 is tagged

* ensure old groups are mapped to the new ones
2021-04-29 05:20:50 -07:00
Sergey
d26191373a add default empty value for etc_hosts_localhosts_dict_target (#7567) 2021-04-28 11:34:50 -07:00
Cristian Calin
4c06aa98b5 crio: add supported versions 1.20 and 1.21 and align default with k8s version (#7562)
* crio: add supported versions 1.20 and 1.21 and align default with k8s version

* cri-o: drop versions 1.17 and 1.18 from version matrix

* update note on cri-o version alignment
2021-04-28 11:30:51 -07:00
muzi502
1b267b6599 Fix calico-kube-controller becomes Error for canal (#7564) 2021-04-28 11:26:52 -07:00
Cristian Calin
dd6efb73f7 Calico new versions v3.17.4 and v3.18.2 (#7563)
* calico: upgrade from v3.17.3 to v3.17.4

* calico: upgrade from v3.18.1 to v3.18.2
2021-04-28 08:22:50 -07:00
Samuel Liu
dfeed1c1a4 Modify the commented config info (#7558) 2021-04-27 15:45:28 -07:00
harihud
0071e3c99c Update main.yml (#7557) 2021-04-27 15:41:27 -07:00
muzi502
0feec14b15 Update Dockerfile for reduce image size (#7556)
* Update Dockerfile for reduce image size

* Remove KUBE_VERSION form Dockerfile
2021-04-26 23:33:37 -07:00
faruryo
975f84494c Fix calico-kube-controller becomes Error (#7548)
Change mode so that calico-kube-controllers can be read because it was changed to run as non-root
https://github.com/projectcalico/kube-controllers/pull/566
2021-04-26 15:37:03 -07:00
Florian Ruynat
7c86734d2e Add cri-o 1.20/1.21 (#7544) 2021-04-26 09:21:16 -07:00
Cristian Calin
8665e1de87 Fix cri-o support for Oracle and AlmaLinux (#7541) 2021-04-26 09:11:02 -07:00
Florian Ruynat
c16efc9ab8 Fix Opensuse not working with ansible_distribution (#7551) 2021-04-26 08:37:02 -07:00
muzi502
324c95d37f Fix some docs.ansible.com url typo (#7550) 2021-04-26 08:33:02 -07:00
muzi502
69806e0a46 Add nerdctl cli tool for containerd user (#7500)
* Add nerdctl cli tool for containerd user

* Add nerdctl enable option

* Add nerdctl enable option and update nerdctl version to 0.8.0
2021-04-25 23:47:01 -07:00
Cristian Calin
ad15a4b755 Bump calico versions (#7543)
* add calico 3.16.10 hashes

* drop old calico version 3.16.9
2021-04-24 12:37:01 -07:00
Cristian Calin
002a4b03a4 Drop calico 3.15 (#7545)
* calico: drop support for version 3.15

* drop check for calico version >= 3.3, we are at 3.16 minimum now

* we moved to calico 3.16+ so we can default to /opt/cni/bin/install
2021-04-23 23:43:14 -07:00
muzi502
96476430a3 Update cni-plugins and kubernetes version in README.md (#7540) 2021-04-22 23:54:02 -07:00
Cristian Calin
73db44b00c Initial AlmaLinux support (#7538)
* AlmaLinux: ansible>2.9.19 is needed to know about AlmaLinux

* AlmaLinux: identify as a centos derrivative

* AlmaLinux: add AlmaLinux to checks for CentOS

* Use ansible_os_family to compare family and not distribution
2021-04-22 23:50:03 -07:00
Florian Ruynat
b32d25942d Minor update to cni-plugins and kube-router 2021-04-22 06:47:42 -07:00
Florian Ruynat
fce705a92b Helm minor update to 3.5.4 2021-04-22 06:47:42 -07:00
Florian Ruynat
6164c90f70 Update kube-ovn to 1.6.2 2021-04-22 06:47:42 -07:00
Cristian Calin
e036b899a3 update calico default version in README.md (#7537) 2021-04-22 06:41:41 -07:00
Samuel Liu
8c7b90ebbf add ingress controller class (#7522) 2021-04-22 00:22:38 -07:00
Ian Martin
38d9d2ea0e Ambassador can watch multiple namespaces (#7516)
* Ambassador can watch multiple namespaces

* update variable name per PR review
2021-04-22 00:22:31 -07:00
Cristian Calin
384d30b675 add support for configuring cri-o pids_limit (#7525) 2021-04-21 10:55:51 -07:00
Cristian Calin
add61868c6 Add Calico v3.17.3 and v3.18.1 (#7524)
* add hashes for calico v3.17.3

* add hashes for claico v3.18.1

* bump default calico version to v3.17.3

* calico crds are missing yaml separator breaking kdd
2021-04-21 10:45:51 -07:00
Florian Ruynat
b599f3084f Fix OpenStack StyleGuide rule H216 (On by default in latest version) (#7535)
ref: b921c4de51
2021-04-21 09:04:11 -07:00
Xachman
a7493e26e1 add enablerepo: amzn2extra-docker for docker install on aws 2 (#7507) 2021-04-21 07:24:10 -07:00
Kenichi Omichi
ae3a1d7c01 Fix keepcache values of yum_repository (#7506)
As the official document[1], the parameter keepcache should be
'0' or '1' as string. To avoid the following warning message,
this fixes the parameter value:

  [WARNING]: The value False (type bool) in a string field was
  converted to u'False' (type string). If this does not look
  like what you expect, quote the entire value to ensure it
  does not change.

https://docs.ansible.com/ansible/latest/collections/ansible/builtin/yum_repository_module.html
2021-04-21 07:20:11 -07:00
Mathieu Parent
e39e3d5c26 Fix OpenId Connect example prefixes (#7527)
Fixes "mapping values are not allowed in this context
2021-04-20 17:32:10 -07:00
holmesb
1e7d48846a Fixes issue #7528 - allow configuring CALICO_STARTUP_LOGLEVEL via a new variable: calico_node_startup_loglevel (#7530)
Signed-off-by: Brendan Holmes <5072156+holmesb@users.noreply.github.com>
2021-04-20 15:37:42 -07:00
Florian Ruynat
6001edeecd Cleanup hashes and 1.18 hooks (#7534) 2021-04-20 15:34:33 -07:00
Frank Ritchie
ce0b7834ff Refactor cilium_ipsec_enabled check (#7520)
This is a followup to

https://github.com/kubernetes-sigs/kubespray/pull/7413

Although the code worked there was a desire for a better solution.
Hopefully people will be happy with this alternative.
2021-04-19 02:06:36 -07:00
Cristian Klein
3ac92689f0 exoscale: Rework EIP access from workers (#7337)
Context: Load-balancing in Exoscale is performed by associating many
workers with the same EIP. This works, however, the workers cannot access
themselves via the EIP, which is needed at least for cert-managers
"self-test".

Problem: The old iptables based workaround felt fragile and disappointed
me at least once.

New solution: Add the EIP to a loopback interface on each worker.
2021-04-16 03:22:22 -07:00
Florian Ruynat
1c0836946f Update default Kubernetes version to 1.20.6 2021-04-15 22:26:22 -07:00
Florian Ruynat
bccbe323b7 Add new kubernetes hashes (1.19.10, 1.20.6) 2021-04-15 22:26:22 -07:00
Samuel Liu
d73249a793 Add bash-completion package (#7510) 2021-04-15 08:33:50 -07:00
Florian Ruynat
cd9a03f86c Update some docker defaults (#7499) 2021-04-14 15:13:07 -07:00
muzi502
b47c21c683 Remove some bash completion file when reset cluster (#7502) 2021-04-14 11:07:09 -07:00
Florian Ruynat
6de5303e3f Fix sample inventory (offline template) (#7498) 2021-04-14 03:28:43 -07:00
Krystian Młynek
2a2fb68b2f Add missing proxy environment in crio_repo.yml (#7492) 2021-04-13 01:20:51 -07:00
Samuel Liu
844ebb7838 fix offline mode (#7493)
* fix offline mode

* add offline messages
2021-04-13 00:46:50 -07:00
Etienne Champetier
332cc1cd58 Check if python netaddr and recent enough jinja are installed (#7486)
CentOS 7 provides up to date Ansible with really old jinja version

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-04-13 00:43:01 -07:00
Peter Zhang
e7ce83016e correct a wrong word (#7484)
* correct a wrong word

* correct a wrong word
2021-04-13 00:42:50 -07:00
Etienne Champetier
bf6a39eb84 Add auto_renew_certificates_systemd_calendar (#7490)
This allow to configure when K8S certificates renewal runs

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-04-12 09:47:45 -07:00
Florian Ruynat
42382e2cde Update Terraform/Vagrant + increase tf_ovh retries (#7477) 2021-04-12 09:47:39 -07:00
Zachary Chang
f8e4650791 Fix typo (#7489) 2021-04-12 09:43:38 -07:00
Etienne Champetier
e444b3c140 Regenerate apiserver.crt on all control-plane nodes (#7463)
We were regenerating only the cert of the first node
While at it speed up the check step

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-04-12 09:17:38 -07:00
emiran-orange
d56ac216f4 Use kubeadm_feature_gates instead of kube_feature_gates to leverage kubeadm feature gates and not to interfere with k8s components feature gates (#7447) 2021-04-12 01:05:59 -07:00
Zhong Jianxin
420a412234 Add containerd_extra_args (#7461)
* Add containerd_extra_args

This is useful for custom containerd config, e.g. auth

Signed-off-by: Zhong Jianxin <azuwis@gmail.com>

* Make containerd config.toml mode 0640

It may contain sensitive information like password

Signed-off-by: Zhong Jianxin <azuwis@gmail.com>
2021-04-12 01:02:00 -07:00
Samuel Liu
90c643f3ab format ansible output (#7482) 2021-04-11 00:37:59 -07:00
Mathieu Parent
1d4e380231 Remove containerd_runtimes var in k8s-cluster.yml (#7476)
Also set in all/containerd.yml
2021-04-09 10:25:17 -07:00
Florian Ruynat
6d293ba899 Update hashes with 1.21.0 (#7478) 2021-04-09 08:05:05 -07:00
Florian Ruynat
aa086e5407 Remove dead code from kubeadm-etcd (#7470) 2021-04-09 01:10:47 -07:00
Sergey
cce0940e1f add CI test for auto_renew_certificates (#7472)
* add CI test for auto_renew_certificates

* change timer value

fix typo error in rotate cert script
2021-04-09 00:42:47 -07:00
Florian Ruynat
daed3e5b6a Use v2.15.1 as base image for CI (#7466) 2021-04-08 12:28:02 -07:00
Samuel Liu
e2a7f3e2ab remove-node roles: fix kubectl absolute path (#7469)
* kubelet absolute path

* kubelet absolute path
2021-04-08 12:24:02 -07:00
Kenichi Omichi
5a351b4b00 Add condition for audit_webhook_mode batch (#7444)
According to the document[1], audit-webhook-batch-max-size and
audit-webhook-batch-max-wait are used only in the batch mode.
This adds a condition to avoid unnecessary writting on the config.

[1]: https://kubernetes.io/docs/tasks/debug-application-cluster/audit/#batching
2021-04-08 07:52:56 -07:00
Frank Ritchie
6f2abbf79c Move cilium kvstore settings to configmap (#7462)
This PR is to move the cilium kvstore options to the configmap
rather than specifying them in the deployment as args. This
is not technically necessary but keeping all the options in
one place is probably not a bad idea.

Tested with cilium 1.9.5.
2021-04-08 07:32:56 -07:00
Florian Ruynat
bef1e628ac Fix issue with 'latest' in containerd version (#7459) 2021-04-07 08:33:53 -07:00
Samuel Liu
7340a163a4 fix scale (#7449) 2021-04-07 01:35:53 -07:00
Frank Ritchie
a6622b176b Update cilium_ipsec_enabled check (#7413)
When attempting a fresh install without cilium_ipsec_enabled I ran
into the following error:

failed: [k8m01] (item={'name': 'cilium', 'file': 'cilium-secret.yml', 'type': 'secret', 'when': 'cilium_ipsec_enabled'}) =>
{"ansible_loop_var": "item", "changed": false, "item": {"file": "cilium-secret.yml", "name": "cilium", "type": "secret",
"when": "cilium_ipsec_enabled"},"msg": "AnsibleUndefinedVariable: 'cilium_ipsec_key' is undefined"}

Moving the when condition from the item level to the task level solved
the issue.
2021-04-06 06:17:33 -07:00
Maciej Wereski
771a5e26bb Add KubeSchedulerConfiguration for k8s 1.19 and up (#7351)
* Add KubeSchedulerConfiguration for k8s 1.19 and up

With release of version 1.19.0 of kubernetes KubeSchedulerConfiguration
was graduated to beta. It allows to extend different stages of
scheduling with profiles. Such effect is achieved by using plugins and
extensions.

This patch adds KubeSchedulerConfiguration for versions 1.19 and later.
Configuration is set to k8s defaults or to kubespray vars. Moving those
defaults to new vars will be done in following patch.

Signed-off-by: Maciej Wereski <m.wereski@partner.samsung.com>

* KubeSchedulerConfiguration: add defaults

Signed-off-by: Maciej Wereski <m.wereski@partner.samsung.com>
2021-04-06 00:35:35 -07:00
Necatican Yıldırım
be278f9dba Add documentation for audit webhook variables (#7434)
* Add documentation for audit webhook variables

* Enclose the value of  audit_webhook_server_url in a codeblock

* Add default value for audit_webhook_batch_max_wait
2021-04-05 13:51:19 -07:00
Florian Ruynat
6479e26904 Replace deprecated 'with_dict' with 'loop' (#7442) 2021-04-05 13:45:19 -07:00
Florian Ruynat
1c7053c9d8 Fix CI template for etcd recover jobs (kube-master rename) (#7441) 2021-04-05 13:41:19 -07:00
Maxime Lavandier
596d0289f8 Remove calico-rr from local inventory hosts file (#7439) 2021-04-05 05:24:12 -07:00
Samuel Liu
7df7054bdc remove local lb privileged (#7437) 2021-04-05 05:22:14 -07:00
dsy3502
5377aac936 fix typo (#7436) 2021-04-05 01:20:19 -07:00
Necatican Yıldırım
ceb6c172ad Crun v0.19 support (#7433)
* Add support for crun v0.19

* Change default crun version to v0.19
2021-04-05 01:20:13 -07:00
Samuel Liu
7f52c1d3a2 reset roles need flush iptables:raw (#7426) 2021-04-05 01:16:13 -07:00
Kenichi Omichi
af1e16b934 Remove old note related to offline installation (#7429)
The PR https://github.com/kubernetes-sigs/kubespray/pull/6927 has been
merged and the issue https://github.com/kubernetes-sigs/kubespray/issues/6233
was fixed.
This removes unnecessary note for the above PR.
2021-04-02 09:48:11 -07:00
Daniil Muidinov
2257181ca8 Set containerd version to 1.4.4 (#7398)
* Set containerd version to 1.4.3

* Set containerd version to 1.4.4

Co-authored-by: Barry Melbourne <9964974+bmelbourne@users.noreply.github.com>
2021-04-01 23:20:11 -07:00
orange-llajeanne
7e75d48cc4 local provisioner 'useNodeNameOnly' option can be configured (#7421) 2021-04-01 16:54:11 -07:00
Pasquale Toscano
6330db89a7 Update KataContainers to 1.12.1 (#7427) 2021-04-01 08:55:21 -07:00
Frank Ritchie
f05d6b3711 Add cilium_ipam_mode variable (#7418)
Starting with Cilium v1.9 the default ipam mode has changed to "Cluster
Scope". See:

https://docs.cilium.io/en/v1.9/concepts/networking/ipam/

With this ipam mode Cilium handles assigning subnets to nodes to use
for pod ip addresses. The default Kubespray deploy uses the Kube
Controller Manager for this (the --allocate-node-cidrs
kube-controller-manager flag is set). This makes the proper ipam mode
for kubespray using cilium v1.9+ "kubernetes".

Tested with Cilium 1.9.5.

This PR also mounts the cilium-config ConfigMap for this variable
to be read properly.

In the future we can probably remove the kvstore and kvstore-opt
Cilium Operator args since they can be in the ConfigMap. I will tackle
that after this merges.
2021-04-01 07:33:22 -07:00
Helmut Januschka
cce9d3125d Update k8s-certs-renew.sh.j2 (#7422)
fix undefinedElse
2021-03-31 00:00:58 -07:00
Etienne Champetier
e381ce57e2 Remove left over nodes_to_drain (#7412)
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-29 16:17:56 -07:00
Fernando
5dbce6a2bd add support for custom calico port (#7419) 2021-03-29 08:38:45 -07:00
Frank Ritchie
5b0e88339a Update cilium-operator clusterrole (#7416)
When upgrading cilium from 1.8.8 to 1.9.5 I ran into the following
error:

level=error msg="Unable to update CRD" error="customresourcedefinitions.apiextensions.k8s.io
\"ciliumnodes.cilium.io\" is forbidden: User \"system:serviceaccount:kube-system:cilium-operator\"
cannot update resource \"customresourcedefinitions\" in API group \"apiextensions.k8s.io\" at the
cluster scope" name=CiliumNode/v2 subsys=k8s

The fix was to add the update verb to the clusterrole. I also added
create to match the clusterrole created by the cilium helm chart.
2021-03-29 00:04:51 -07:00
Samuel Liu
db43891f2b remove unused handlers in cilium roles (#7414) 2021-03-29 00:04:44 -07:00
Terry
f72063e7c2 Remove DNSSEC config management in bootstrap-debian.yml (#7408)
DNSSEC is off by default on ubuntu/bionic64 (18.04) as per resolved.conf(5).
These tasks are artefacts of obsolete infra configuration, and no longer needed.

Further removing these tasks resolves the issue that the tasks always reports
'changed' and bounces systemd-resolved unneccesarily, even if there was no
actual modification of /etc/systemd/resolved.conf.
2021-03-29 00:00:45 -07:00
Etienne Champetier
36a3a78952 Fix remove-node by removing jq usage (#7405)
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-26 08:48:43 -07:00
Etienne Champetier
2d1597bf10 Fix k8s-certs-renew for k8s < 1.20 (#7410)
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-26 08:44:44 -07:00
Anthony Rabbito
edfa3e9b14 Correct Jinja Syntax for etcd-unsupported-arch (#6919)
`-%` causes `etcd-unsupported-arch: arm64` to print on COL 1 instead of
COL 6.

Signed-off-by: anthr76 <hello@anthonyrabbito.com>
2021-03-26 02:10:43 -07:00
Kaleb Elwert
6fa3565dac Allow connecting to bastion via non-standard SSH port (#7396)
* Allow connecting to bastion via non-standard port

* Fix bastion connection when ansible_port is not provided
2021-03-26 00:48:43 -07:00
rptaylor
7dec8e5caa specify runAsGroup, allow safe sysctls by default (#7399) 2021-03-25 08:03:30 -07:00
Kenichi Omichi
49abf6007a Add cryptography installation (#7404)
To avoid ModuleNotFoundError due to no module named 'setuptools_rust',
this adds cryptography installation to requirements.txt.

Created by jfc-evs originally as https://github.com/kubernetes-sigs/kubespray/pull/7264
2021-03-25 05:15:29 -07:00
Etienne Champetier
f0cdf71ccb Remove vault (#7400)
* Remove contrib/vault

This is marked as broken since 2018 / 3dcb914607
This still reference apiserver.pem, not used since ddffdb63bf

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>

* Finish nuking vault from the codebase

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-24 09:26:08 -07:00
Boris Barnier
8655b92e93 Set Kube-router version to 1.2.0 (#7402)
See: `https://github.com/cloudnativelabs/kube-router/releases/tag/v1.2.0`
2021-03-24 09:22:07 -07:00
Jacky Wu
e1c6992c55 fix: correct hardcoded macvlan template, use var macvlan_interface. (#7401) 2021-03-24 01:46:06 -07:00
Kenichi Omichi
486b223e01 Replace kube-master with kube_control_plane (#7256)
This replaces kube-master with kube_control_plane because of [1]:

  The Kubernetes project is moving away from wording that is
  considered offensive. A new working group WG Naming was created
  to track this work, and the word "master" was declared as offensive.
  A proposal was formalized for replacing the word "master" with
  "control plane". This means it should be removed from source code,
  documentation, and user-facing configuration from Kubernetes and
  its sub-projects.

NOTE: The reason why this changes it to kube_control_plane not
      kube-control-plane is for valid group names on ansible.

[1]: https://github.com/kubernetes/enhancements/blob/master/keps/sig-cluster-lifecycle/kubeadm/2067-rename-master-label-taint/README.md#motivation
2021-03-23 17:26:05 -07:00
Qasim Sarfraz
d53fd29e34 Add support for cilium ipsec (#7342)
* Add support for cilium ipsec

* Fix typo for bpffs
2021-03-23 13:46:06 -07:00
Maciej Wereski
4f89bfac48 MetalLB: bump to v0.9.6 (#7397)
Signed-off-by: Maciej Wereski <m.wereski@partner.samsung.com>
2021-03-23 13:42:06 -07:00
p53
5fee96b404 Fix cinder cert permissions (#7384)
* Fix permissions of cinder cert

* Change runuser for external_cloud_controller to kube user with id 999, part of 999 - kube-cert group
2021-03-23 11:03:37 -07:00
Samuel Liu
12873f916b download_file for kata (#7393) 2021-03-23 01:39:36 -07:00
Etienne Champetier
efa180392b Auto renew control plane certificates (#7358)
While at it remove force_certificate_regeneration
This boolean only forced the renewal of the apiserver certs
Either manually use k8s-certs-renew.sh or set auto_renew_certificates

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-22 11:22:48 -07:00
Florian Ruynat
6d9ed398e3 Set default k8s version to 1.20.5 2021-03-19 10:04:34 -07:00
Florian Ruynat
6d3dbb43a4 Update hashes for 1.20.5/1.19.9/1.18.17 2021-03-19 10:04:34 -07:00
Necatican Yıldırım
811f546ea6 Download crun using download_file.yml (#7370)
* Add crun download_url and checksum

* Change versioning format to crun native versioning

* Download crun using download_file.yml

* Get crun version from download defaults

* Delegate crun binary copy task to crun role
2021-03-19 08:40:33 -07:00
Florian Ruynat
ead8a4e4de Fix calico crds missing 3.16.9 (#7386) 2021-03-19 06:58:34 -07:00
Florian Ruynat
05f132c136 Update CNI (calico, kubeovn, multus) and Helm 2021-03-18 17:20:36 -07:00
Florian Ruynat
5f2c8ac38f Update nodelocaldns to 1.17.1 2021-03-18 17:20:36 -07:00
Florian Ruynat
14511053aa Update docker to 20.10.5 2021-03-18 17:20:36 -07:00
LuciferInLove
8353532a09 Added experimental cri-o support for Amazon Linux 2 (#7353)
* Added experimental cri-o support for Amazon Linux 2

* Fixed dependencies order
2021-03-18 17:16:37 -07:00
Erwan Miran
1c62af0c95 Download Calico KDD CRDs (#7372)
* Download Calico KDD CRDs

* Replace kustomize with lineinfile and use ansible assemble module

* Replace find+lineinfile by sed in shell module to avoid nested loop

* add condition on sed

* use block for kdd tasks + remove supernumerary kdd manifest apply in start "Start Calico resources"
2021-03-18 17:06:36 -07:00
Mikael Johansson
f103ac7640 Change default OCCM internal and public networks variables to empty lists (#7380)
Signed-off-by: Mikael Johansson <mik.json@gmail.com>
2021-03-18 16:52:36 -07:00
Samuel Liu
274e06a48d add etcd max snapshot and wals (#7382) 2021-03-18 16:48:36 -07:00
zhangshj-inspur
a39f306184 correct a wrong word (#7383) 2021-03-18 00:55:19 -07:00
Maciej Wereski
69d11daef6 Upgrade openSUSE Leap to 15.2 (#7331)
15.1 has reached EOL on 2021-02-02.

Signed-off-by: Maciej Wereski <m.wereski@partner.samsung.com>
2021-03-17 09:12:56 -07:00
Etienne Champetier
057e8b4358 Fixup one more missing kubespray-defaults (#7375)
"The error was: 'proxy_disable_env' is undefined\n\nThe error appears to
be in '<censored>scale.yml': line 72, column 7"

Fixes 067db686f6

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-15 07:09:05 -07:00
Florian Ruynat
18c0e54e4f Add most_recent = true while retrieving the latest image (#7376) 2021-03-15 07:05:06 -07:00
Kenichi Omichi
85007fa9a7 Update upgrades.md (#7361)
upgrades.md explains how to do upgrade from v1.4.3 to v1.4.6 as an
example. The versions are a little old, and the doc readers would
have a concern the upgrade works fine or not.
This updates versions after verifying the way works fine by hands.
2021-03-15 03:59:05 -07:00
Ewnetu Bayuh Lakew
5c5bf41afe Terraform support for UpCloud (#7360)
* terraform support for UpCloud

* terraform support for UpCloud

* terraform support for UpCloud

* terraform support for UpCloud

* terraform support for UpCloud

* terraform support for UpCloud

* terraform support for UpCloud

* Updates to README.md and main.tf files

* formatting and updating readme

* added a .terraform_validate CI job

* fixed format issue

* added sample inventory

* added symbolic link to group_vars

* added missing tf variables and minor fixes

* added text formatting

* minor formatting fixes
2021-03-15 01:41:04 -07:00
Robin Opletal
5dba53a223 Fix dynamic inventory link (#7367) 2021-03-11 06:46:22 -08:00
Victor Morales
2bcd9eb9e9 Bump crun to 0.18 version (#7364) 2021-03-11 00:00:24 -08:00
Lennart Jern
5a54db2f3c Check for dummy kernel module (#7348)
The dummy module is needed for nodelocaldns.
2021-03-09 08:07:00 -08:00
Sergey Mikhaltsov
b47542b003 disable gather_facts for correctly work via bastion (#7265) 2021-03-09 01:47:00 -08:00
Etienne Champetier
14b63ede8c Fixup kubelet.conf to point to kubelet-client-current.pem (#7347)
c9c0c01de0 only fix the problem for new clusters

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-08 23:55:00 -08:00
Maciej
b07c5966a6 ansible and jinja2 updates (#7357)
* Update ansible to v2.9.18

Signed-off-by: Maciej Wereski <m.wereski@partner.samsung.com>

* Update jinja2 to v2.11.3

Signed-off-by: Maciej Wereski <m.wereski@partner.samsung.com>
2021-03-08 11:42:59 -08:00
François Hernandez
c7db72e1da Add nodeselector and tolerations for metallb (#7334)
* add nodeselector and tolerations for metallb

* remove unnecessary commented lines in metallb template

* set default speaker toleration to match original manifest
2021-03-08 07:57:42 -08:00
Victor Morales
dc5df57c26 Add privileged_without_host_devices support (#7343)
When privileged is enabled for a container, all the `/dev/*` block
devices from the host are mounted into the guest. The
`privileged_without_host_devices` flag prevents host devices from
being passed to privileged containers.

More information:
* https://github.com/containerd/cri/pull/1225
* 1d0f68156b
2021-03-08 00:17:44 -08:00
Etienne Champetier
a9c97e5253 Delete misnammed kubeadm-version.yml
The important action in kubeadm-version.yml is the templating of the configuration,
not finding / setting the version

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-04 23:42:22 -08:00
Etienne Champetier
53e5ef6b4e Always backup both certs and kubeconfig
There are no reasons not to backup during upgrade

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-04 23:42:22 -08:00
Etienne Champetier
8800b5c01d Remove rotate_tokens logic
kubeadm never rotates sa.key/sa.pub, so there is no need to delete tokens/restart pods

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-04 23:42:22 -08:00
Etienne Champetier
280036fad6 Remove admin.conf removal
kubeadm is the default for a long time now,
and admin.conf is created by it, so let kubeadm handle it

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-04 23:42:22 -08:00
Etienne Champetier
a6e1f5ece9 Remove useless call to 'kubeadm version'
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-04 23:42:22 -08:00
Etienne Champetier
fedd671d68 Remove pre kubeadm cert migration tasks
apiserver.pem is not used since ddffdb63bf

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-04 23:42:22 -08:00
Du9L.com
b7c22659e3 kubeadm-config.v1beta2.yaml.j2: etcd log level arg (#7339)
According to [etcd's docs](https://etcd.io/docs/v3.4.0/op-guide/configuration/#--log-package-levels), argument 'log-package-levels' should not contain underscores.
2021-03-03 11:39:50 -08:00
Etienne Champetier
c9c0c01de0 Stop using kubeadm to update server in kubeconfigs (#7338)
Using `kubeadm init phase kubeconfig all` breaks kubelet client certificate rotation
as we are missing `kubeadm init phase kubelet-finalize all` to point to `kubelet-client-current.pem`

kubeconfig format is stable so let's just use lineinfile,
this will avoid other future breakage

This revert to the logic before 6fe2248314

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-03 09:39:20 -08:00
Etienne Champetier
e442b1d2b9 Add kube-ipvs0/nodelocaldns to NetworkManager unmanaged-devices (#7315)
On CentOS 8 they seem to be ignored by default, but better be extra safe
This also make it easy to exclude other network plugin interfaces

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-03-03 07:27:20 -08:00
yydzhou
e9f4ff227e fix master node taint removal bug (#7336)
code improvement
2021-03-03 05:35:20 -08:00
Florian Ruynat
668bbe0528 Update Kubernetes dashboard and metrics-server 2021-03-02 08:33:19 -08:00
Florian Ruynat
e045a45e48 Update docker & docker-cli to 20.10.4 2021-03-02 08:33:19 -08:00
Sergey
2c9fc18903 template crun manifest (#7305)
add missing else to if inline
2021-03-02 01:57:19 -08:00
Emil
d4eecac108 add option to use calico with azure when using calico in vxlan (#7300) 2021-03-02 01:03:19 -08:00
Kenichi Omichi
ef351e0234 Update dashboard_enabled on sample (#7316)
Since https://github.com/kubernetes-sigs/kubespray/pull/6804
dashboard_enabled has been false by default.
However we forgot to update it on sample inventory and it made
confusion.
This updates the sample inventory.
2021-03-02 00:59:19 -08:00
Florian Ruynat
05adeed1fa Fix recover-control-plane undefined 'proxy_disable_env' variable (#7326) 2021-03-01 13:38:16 -08:00
stress-t
15f1b19136 Fix: added string to bool conversion for use_localhost_as_kube api load balancer (#7324) 2021-03-01 11:53:36 -08:00
wangxf
154fa45422 fix: the filename </etc/vault> is Duplicate in the reset role. (#7313) 2021-03-01 11:53:25 -08:00
Florian Ruynat
e35becebf8 Move centos7-crio CI job to centos8 (#7327) 2021-03-01 09:57:26 -08:00
Viktor
bdd36c2d34 Update default exoscale master with more RAM (#7328)
The default master size for exoscale is 2cpu and 2GB ram.
I have found this to be too low, so this increases it to
2cpu and 4GB ram.
2021-03-01 09:41:25 -08:00
Jakub Krzywda
0a0156c946 Vsphere (#7306)
* Add terraform scripts for vSphere

* Fixup: Add terraform scripts for vSphere

* Add inventory generation

* Use machines var to provide IPs

* Add README file

* Add default.tfvars file

* Fix newlines at the end of files

* Remove master.count and worker.count variables

* Fixup cloud-init formatting

* Fixes after initial review

* Add warning about disabled DHCP

* Fixes after second review

* Add sample-inventory
2021-02-26 04:20:15 -08:00
Florian Ruynat
100d9333ca Add configmaps to local-path-provisioner CR (#7323) 2021-02-25 16:22:17 -08:00
Sergey Mikhaltsov
a4cc416511 use external_openstack_lbaas_use_octavia for template openstack-cloud… (#7298)
* use external_openstack_lbaas_use_octavia for template openstack-cloud-config

* Delete external_openstack_lbaas_use_octavia from default values. Added description and default values of variables to docs

* markdown fix

* make this simple

* set external_openstack_lbaas_use_octavia in default values

* duplicated variable in doc
2021-02-25 11:25:25 -08:00
Kenichi Omichi
2ea5793782 Replace KUBE_MASTERS with KUBE_CONTROL_HOSTS (#7257)
This replaces KUBE_MASTERS with KUBE_CONTROL_HOSTS because of [1]:

```
  The Kubernetes project is moving away from wording that is
  considered offensive. A new working group WG Naming was created
  to track this work, and the word "master" was declared as offensive.
  A proposal was formalized for replacing the word "master" with
  "control plane". This means it should be removed from source code,
  documentation, and user-facing configuration from Kubernetes and
  its sub-projects.
```

[1]: https://github.com/kubernetes/enhancements/blob/master/keps/sig-cluster-lifecycle/kubeadm/2067-rename-master-label-taint/README.md#motivation
2021-02-23 10:00:03 -08:00
Kenichi Omichi
0ddf915027 Update Ansible to v2.9.17 (#7291)
This updates Ansible version to the latest stable version 2.9.17.
2021-02-23 09:54:03 -08:00
Etienne Champetier
067db686f6 Fix proxy usage when *_PROXY are present in environment (#7309)
Since a790935d02 all proxy users
should be properly configured

Now when you have *_PROXY vars in your environment it can leads to failure
if NO_PROXY is not correct, or to persistent configuration changes
as seen with kubeadm in 1c5391dda7

Instead of playing constant whack-a-bug, inject empty *_PROXY vars everywhere
at the play level, and override at the task level when needed

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-02-23 09:44:02 -08:00
Etienne Champetier
ed2b4b805e Fix reset when using containerd (#7308)
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-02-22 12:44:03 -08:00
Hugo Blom
8375aa72e2 [Openstack] Update Cinder CSI driver to v1.20.0 (#7280)
* update Cinder CSI to v1.19.0

* Update Cinder CSI to v1.20
2021-02-22 10:09:42 -08:00
Florian Ruynat
6334e4bd84 Set Kubernetes default version to 1.20.4 2021-02-22 08:45:42 -08:00
Florian Ruynat
86ce8aac85 Add hashes for Kubernetes 1.18.16/1.19.8/1.20.4 2021-02-22 08:45:42 -08:00
Florian Ruynat
de46f86137 Minor update to cilium and calico 2021-02-22 08:45:42 -08:00
FedericoHeichou
5616b08229 Adding else in the inline if-expression (#7292)
Fix "AnsibleUndefinedVariable: the inline if-expression on line xx evaluated to false and no else section was defined."
2021-02-20 02:05:41 -08:00
Hugo Blom
8682a57ea3 use image id instad of name (#7293) 2021-02-19 09:16:25 -08:00
Etienne Champetier
662a37ab4f Fix "api is up" check (#7295)
Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-02-19 09:12:25 -08:00
Sergey
42947c9840 return the ability to update calico from 3.x.x version (#7290)
version check fixed
2021-02-17 00:07:06 -08:00
Etienne Champetier
3749729d5a Remove calico-upgrade leftovers (#7282)
This is dead code since 28073c76ac

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-02-16 11:24:58 -08:00
Etienne Champetier
fb8b075110 facts.yaml: reduce the number of setup calls by ~7x (#7286)
Before this commit, we were gathering:
1 !all
7 network
7 hardware

After we are gathering:
1 !all
1 network
1 hardware

ansible_distribution_major_version is gathered by '!all'

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-02-16 09:34:58 -08:00
Etienne Champetier
1c5391dda7 Ensure kubeadm doesn't use proxy (#7275)
* Move proxy_env to kubespray-defaults/defaults

There is no reasons to use set_facts here

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>

* Ensure kubeadm doesn't use proxy

*_proxy variables might be present in the environment (/etc/environment, bash profile, ...)
When this is the case we end up with those proxy configuration in /etc/kubernetes/manifests/kube-*.yaml manifests

We cannot unset env variables, but kubeadm is nice enough to ignore empty vars
93d288e2a4/cmd/kubeadm/app/util/env.go (L27)

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-02-16 08:44:58 -08:00
Hugo Blom
f2d10e9465 allow users to set image_uuid instead of name, this allows the use of openstack community images (#7283) 2021-02-16 07:05:06 -08:00
stress-t
796d3fb975 Improving PR 6473 (#7259) 2021-02-16 05:19:05 -08:00
Etienne Champetier
5c04bdd52b Fixup cri-o metacopy mount options (#7287)
Ubuntu 18.04 crio package ships with 'mountopt = "nodev,metacopy=on"'
even if GA kernel is 4.15 (HWE Kernel can be more recent)

Fedora package ships without metacopy=on

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-02-15 20:51:07 -08:00
Hugo Blom
17143dbc51 write openstack controller manifests with correct perms (#7284) 2021-02-15 00:53:05 -08:00
Hugo Blom
1c8bba36db make sure worker rules is applied on workers (#7279) 2021-02-12 12:43:05 -08:00
Etienne Champetier
95b329b64d bootstrap-os: match on os-release ID / VARIANT_ID (#7269)
This fixes deployment with CentOS 8 Streams and make detection more reliable

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-02-11 08:14:16 -08:00
Etienne Champetier
de1d9df787 Only use stat get_checksum: yes when needed (#7270)
By default Ansible stat module compute checksum, list extended attributes and find mime type
To find all stat invocations that really use one of those:
git grep -F stat. | grep -vE 'stat.(islnk|exists|lnk_source|writeable)'

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
2021-02-10 05:36:59 -08:00
Cristian Calin
6450207713 add containerd.io to dpkg_selection (#7273)
`containerd.io` is the companion package of `docker-ce` and is the
proper package name. This is needed to avoid apt upgrade/dist-upgrade
from breaking kubernetes.
2021-02-10 04:48:59 -08:00
Florian Ruynat
edc4bb4a49 Update kube-ovn to 1.6.0 (#7240) 2021-02-10 02:25:01 -08:00
Sergey
a21ee33180 fix typo error in role ingress-nginx (#7272) 2021-02-09 07:53:13 -08:00
Takashi IIGUNI
bcaa31ae33 fix: Restart network doesn't work on Fedora CoreOS (#7271)
Running remove-node.yml tasks for clean up cluster on Fedora CoreOS.
The task failed to restart network daemon (task name: "reset | Restart network").
Fedora CoreOS is essentially using NetworkManager, but this task returns network.

Signed-off-by: Takashi IIGUNI <iiguni.tks@gmail.com>
2021-02-09 06:35:04 -08:00
David Louks
0cc1726781 Remove deletion of coredns deployment. (#7211)
* Add unique annotation on coredns deployment and only remove existing deployment if annotation is missing.

* Ignore errors when gathering coredns deployment details to handle case where it doesn't exist yet

* Remove run_once, deletegate_to and add to when statement
2021-02-09 06:02:40 -08:00
David Louks
aad78840a0 Updated etcd cert check tasks to detect when new cert gen is required (#7219)
* Added force_etcd_cert_refresh var to maintain existing functionality. Broke out etcd node cert syncing from member and admin cert sync logic. Now first etcd will sync node certs to other etcd members on every run to keep all etcds up to date after adding additional worker nodes to the cluster

* Updated etcd cert check tasks to better detect when new certificates need to be generated

* Move usage of force_etcd_cert_refresh var to gen_certs fact set

* Force etcd cert generation per server if force_etcd_cert_refresh is set to true

* Include gathering of node certs even if k8s-cluster member and in etcd group.

* Removed run_once due to when statement
2021-02-09 01:53:22 -08:00
Vyacheslav
e3ab665e90 Update main.yml (#7267)
````
TASK [bootstrap-os : Enable RHEL 8 repos] ***************************************************************************************************************************************************************************************************
fatal: [node6]: FAILED! => {"changed": false, "msg": "This system has no repositories available through subscriptions"}
fatal: [node7]: FAILED! => {"changed": false, "msg": "This system has no repositories available through subscriptions"}
fatal: [node1]: FAILED! => {"changed": false, "msg": "This system has no repositories available through subscriptions"}


root@node1:/kubespray# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.5 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
root@node1:/kubespray#
```
2021-02-08 10:25:37 -08:00
Geonju Kim
1a91792e7c Change the owner of /etc/crictl.yaml to root (#7254) 2021-02-05 09:28:53 -08:00
Mathieu Parent
670c37b428 Update Helm version to 3.5.2 (#7248)
Helm v3.5.2 is a security (patch) release. Users are strongly
recommended to update to this release. It fixes two security issues in
upstream dependencies and one security issue in the Helm codebase.

See https://github.com/helm/helm/releases/tag/v3.5.2
2021-02-05 08:16:52 -08:00
Arian van Putten
040dacd5cd roles/docker: Make repokey fingerprint overrideable (#7247)
This makes the docker role work the same as the containerd role.
Being able to override this is needed when you have your own debian
repository. E.g. when performing an airgapped installation
2021-02-05 07:44:52 -08:00
Maciej
59541de437 Vagrantfile: always recreate inventory symlink (#7245)
Fixes 7244

Signed-off-by: Maciej Wereski <m.wereski@partner.samsung.com>
2021-02-05 00:50:52 -08:00
petruha
fc8551bcba Run containerd related tasks on OracleLinux. (#7250) 2021-02-05 00:46:52 -08:00
Matt Calvert
c2c97c36bc Add in tests for Calico with dual-stack networking 2021-02-05 00:04:52 -08:00
Matt Calvert
211fdde742 Add IPv6 libvirt details to the Vagrantfile 2021-02-05 00:04:52 -08:00
Matt Calvert
366cbb3e6f Ensure we gather IPv6 facts 2021-02-05 00:04:52 -08:00
Matt Calvert
a318624fad Auto-add IPv6DualStack featureGate
When enable_dual_stack_networks is set, we need to make sure
IPv6DualStack=true is set too, otherwise we end up with
a broken cluster.
2021-02-05 00:04:52 -08:00
Matt Calvert
3cf5981146 Switch to use upstream kube_feature_gates logic 2021-02-05 00:04:52 -08:00
Matt Calvert
4cc065e66d Changes to support Dual Stack networking 2021-02-05 00:04:52 -08:00
Florian Ruynat
ba731ed145 Update docker packages to 19.03.15 and 20.10.3 (#7243) 2021-02-04 13:20:53 -08:00
Cristian Klein
b77460ec34 contrib/terraform/exoscale: Rework SSH public keys (#7242)
* contrib/terraform/exoscale: Rework SSH public keys

Exoscale has a few limitations with `exoscale_ssh_keypair` resources.
Creating several clusters with these scripts may lead to an error like:

```
Error: API error ParamError 431 (InvalidParameterValueException 4350): The key pair "lj-sc-ssh-key" already has this fingerprint
```

This patch reworks handling of SSH public keys. Specifically, we rely on
the more cloud-agnostic way of configuring SSH public keys via
`cloud-init`.

* contrib/terraform/exoscale: terraform fmt

* contrib/terraform/exoscale: Add terraform validate

* contrib/terraform/exoscale: Inline public SSH keys

The Terraform scripts need to install some SSH key, so that Kubespray
(i.e., the "Ansible part") can take over. Initially, we pointed the
Terraform scripts to `~/.ssh/id_rsa.pub`. This proved to be suboptimal:
Operators sharing responbility for a cluster risk unnecessarily replacing resources.

Therefore, it has been determined that it's best to inline the public
SSH keys. The chosen variable `ssh_public_keys` provides some uniformity
with `contrib/azurerm`.

* Fix Terraform Exoscale test

* Fix Terraform 0.14 test
2021-02-03 07:32:28 -08:00
forselli-stratio
88bee6c68e Fix ansible calico route reflector tasks in calico role (#7224)
* Fix calico-rr tasks

* revert stdin only when it's already a string
2021-02-03 07:22:29 -08:00
Sebastian Schmid
1f84d6344b local-path-provisioner change default version to v0.0.19 and update config template (#7238)
* update local-path-storage config template to version v0.0.19

* changes local_path_provisioner image tag to v0.0.19

* removes copy paste example from rancher local-path-provisioner repo
2021-02-03 06:50:28 -08:00
Kenichi Omichi
699fbd64ab Move recover_control_plane/master to control-plane (#7236)
According to the following recommendation, this moves the directory
to control-plane:

The Kubernetes project is moving away from wording that is considered
offensive. A new working group WG Naming was created to track this work,
and the word "master" was declared as offensive. A proposal was formalized
for replacing the word "master" with "control plane".
2021-02-03 02:06:29 -08:00
Maciej
b42bf39fb7 MetalLB: bump to v0.9.5 (#7241)
Signed-off-by: Maciej Wereski <m.wereski@partner.samsung.com>
2021-02-03 01:02:28 -08:00
Lennart Jern
5368d51d63 Mention docker image in readme (#7239) 2021-02-02 09:16:28 -08:00
Kenichi Omichi
c5db012c9a Move kubernetes/master to kubernetes/control-plane (#7218)
This is a small step to replace "master" with "control-plane" in
Kubespray project.
2021-02-01 07:15:49 -08:00
Sander Cornelissen
b70d986bfa Ensure when use_oracle_public_repo is set to false the public Oracle Linux yum repos are not set (#7228) 2021-01-29 03:59:41 -08:00
Felix Breuer
973628fc1b FIX: Bastion undefined variable (#7227)
Fixes the following error when using Bastion Node with the sample config.
```
fatal: [bastion]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'bastion'\n\nThe error appears to be in '/home/felix/inovex/kubespray/roles/bastion-ssh-config/tasks/main.yml': line 2, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n---\n- name: set bastion host IP\n  ^ here\n"}
```
2021-01-28 10:07:37 -08:00
Robin Elfrink
91fea7c956 Fix unintended SIGPIPEs. (#7214) 2021-01-27 01:07:40 -08:00
David Louks
d378d789cf Add retries to drain during upgrade. Allow leaving nodes cordoned after drain failure. Allow continuing upgrade if drain fails. (#7206) 2021-01-26 11:10:31 -08:00
Florian Ruynat
9007d6621a Update nginx, minor weave and misc CI tools (vagrant/terraform) (#7215) 2021-01-26 08:22:34 -08:00
Ryler Hockenbury
774ec49396 Update azure cloud config (#7208)
* Allow configureable vni and port for flannel overlay

* additional options for azure cloud config
2021-01-26 07:24:35 -08:00
Jorik Jonker
bba55faae8 calico: fix NetworkManager check (#7169)
Previous check for presence of NM assumed "systemctl show
NetworkManager" would exit with a nonzero status code, which seems not
the case anymore with recent Flatcar Container Linux.

This new check also checks the activeness of network manager, as
`is-active` implies presence.

Signed-off-by Jorik Jonker <jorik@kippendief.biz>
2021-01-25 23:52:34 -08:00
Etienne Champetier
8f2b0772f9 containerd,docker: stop installing extras repo on CentOS/RHEL (#7203)
This was introduced in 143e2272ff
Extra repo is enabled by default in CentOS, and is not the right repo for EL8
Instead of adding a CentOS repo to RHEL, enable the needed RHEL repos with rhsm_repository

For RHEL 7, we need the "extras" repo for container-selinux
For RHEL 8, we need the "appstream" repo for container-selinux, ipvsadm and socat

Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2021-01-25 03:12:54 -08:00
Samuel Liu
1a409dc7ae Add download bin tasks (#7131)
* Add downlaod bin tasks

* Add tags never and etcd

* yamllint
2021-01-22 20:41:39 -08:00
Fredrik Liv
404ea0270e Added terraform support for Exoscale (#7141)
* Added terraform support for Exoscale

* Fixed markdown lint error on exoscale terraform
2021-01-22 20:37:39 -08:00
Florian Ruynat
ef939dee74 Add missing 'ingress-controller' tag to alb (#7204) 2021-01-22 19:11:39 -08:00
Etienne Champetier
f1576eabb1 Calico: fixup check when ipipMode / vxlanMode is not present (#7195)
calicoctl.sh get ipPool default-pool -o json
{
  "kind": "IPPool",
  "apiVersion": "projectcalico.org/v3",
  "metadata": {
    "name": "default-pool",
...
  },
  "spec": {
    "cidr": "10.233.64.0/18",
    "ipipMode": "Always",
    "natOutgoing": true,
    "blockSize": 24,
    "nodeSelector": "all()"
  }
}

Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2021-01-21 20:39:26 -08:00
Etienne Champetier
49c4345c9a preinstall: etcd group might not exists (#7202)
fixes 8c1821228d

Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2021-01-21 14:31:02 -08:00
Maxime Guyot
f94182f77d Add cleanup of openstack network ports in CI (#7201) 2021-01-21 12:51:02 -08:00
Florian Ruynat
222a77dfe7 Change node-role.kubernetes.io from master to control-plane (#7183) 2021-01-21 08:13:03 -08:00
Andrea Zonca
24ceee134e Document the terraform option master_allowed_ports (#7196)
Implemented in #6547
2021-01-21 07:55:06 -08:00
Rick Haan
04c8a73889 Check kube-apiserver up on all masters before upgrade (#7193)
Only checking the kubernetes api on the first master when upgrading is not enough.
Each master needs to be checked before it's upgrade.

Signed-off-by: Rick Haan <rickhaan94@gmail.com>
2021-01-20 01:42:03 -08:00
Florian Ruynat
9a75501152 Promote node.k8s.io API groups from v1beta1 to v1 2021-01-19 08:57:45 -08:00
Florian Ruynat
f6fbbc17a4 Cleanup old checks for k8s 1.18 (#7192) 2021-01-19 08:43:45 -08:00
Florian Ruynat
15dc3868c3 Update Weave to 2.8.0 (#7181) 2021-01-19 08:35:48 -08:00
takmori_tech
2525d7aff8 Update main.yml (#7175)
Fix issue #7129. Calico image tags support multiarch on quay.io.
2021-01-19 05:59:46 -08:00
Etienne Champetier
a5d2137ed9 containerd: ensure containerd is really started and enabled
Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2021-01-19 05:55:45 -08:00
Etienne Champetier
a8e51e686e containerd,docker: use apt_repository instead of action
yum_repository expect really different params, so nothing to factor here
Ubuntu is not an ansible_os_family, the OS family for Ubuntu is Debian
Check for ansible_pkg_mgr == apt

Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2021-01-19 05:55:45 -08:00
Etienne Champetier
a2429ef64d containerd,docker: use apt_key instead of action
we don't need rpm_key, so nothing to factor here
Ubuntu is not an ansible_os_family, the OS family for Ubuntu is Debian
Check for ansible_pkg_mgr == apt

Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2021-01-19 05:55:45 -08:00
Etienne Champetier
1b88678cf3 containerd: use package instead of action
Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2021-01-19 05:55:45 -08:00
Etienne Champetier
0e96852159 docker: use package instead of action, cleanup
Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2021-01-19 05:55:45 -08:00
Etienne Champetier
19a61d838f containerd: use copy to set apt pin
Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2021-01-19 05:55:45 -08:00
Etienne Champetier
4eec302e86 preinstall: use package instead of action, use state: present
Before this commit we were upgrading base os packages on each run

Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2021-01-19 05:55:45 -08:00
Etienne Champetier
f3885aa589 docker: stop using apt force
Here the desciption from Ansible docs
Corresponds to the --force-yes to apt-get and implies allow_unauthenticated: yes
This option will disable checking both the packages' signatures and the certificates of the web servers they are downloaded from.
This option *is not* the equivalent of passing the -f flag to apt-get on the command line
**This is a destructive operation with the potential to destroy your system, and it should almost never be used.** Please also see man apt-get for more information.

Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
2021-01-19 05:55:45 -08:00
Florian Ruynat
b493c81ce8 Update metrics-server to 0.4.1 (#7188) 2021-01-19 05:45:44 -08:00
Florian Ruynat
9ef62194c3 Update bunch of dependencies (#7187) 2021-01-19 05:41:45 -08:00
Florian Ruynat
91ee4aa542 Decrease docker dependency (#7172) 2021-01-18 01:41:44 -08:00
Sergey
e3caff833c Add prompt to upgrade node or delay before upgrade (#7168)
* Add prompt to upgrade node or delay before upgrade

* add docs
2021-01-17 23:53:43 -08:00
Sergey
b2995e4ec4 Adding other masters sequentially, not in parallel (#7166) 2021-01-15 17:19:43 -08:00
David Louks
ccd3aeebbc Remove ignore_errors from drain tasks and enable retires (#7151)
* Remove ignore_errors from drain tasks and enable retires

* Fix lint error by checking if stdout length is not 0, ie string is not empty.
2021-01-15 13:17:43 -08:00
Florian Ruynat
7a033a1d55 Add hashes and update default K8S version to 1.20.2 (#7171) 2021-01-15 12:43:09 -08:00
Maxime Guyot
1652d8bf4b Use Kubespray v2.15.0 as base image for CI (#7165) 2021-01-15 08:25:52 -08:00
Guangwen Feng
c85f275bdb Fix typo (#7164)
Signed-off-by: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
2021-01-15 02:19:52 -08:00
558 changed files with 7493 additions and 7752 deletions

View File

@@ -8,7 +8,7 @@ stages:
- deploy-special
variables:
KUBESPRAY_VERSION: v2.14.1
KUBESPRAY_VERSION: v2.15.1
FAILFASTCI_NAMESPACE: 'kargo-ci'
GITLAB_REPOSITORY: 'kargo-ci/kubernetes-sigs-kubespray'
ANSIBLE_FORCE_COLOR: "true"
@@ -30,7 +30,9 @@ variables:
MITOGEN_ENABLE: "false"
ANSIBLE_LOG_LEVEL: "-vv"
RECOVER_CONTROL_PLANE_TEST: "false"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:],kube-master[1:]"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:],kube_control_plane[1:]"
TERRAFORM_14_VERSION: 0.14.10
TERRAFORM_13_VERSION: 0.13.6
before_script:
- ./tests/scripts/rebase.sh

View File

@@ -14,7 +14,7 @@ vagrant-validate:
stage: unit-tests
tags: [light]
variables:
VAGRANT_VERSION: 2.2.10
VAGRANT_VERSION: 2.2.15
script:
- ./tests/scripts/vagrant-validate.sh
except: ['triggers', 'master']

View File

@@ -42,12 +42,10 @@ packet_centos7-flannel-containerd-addons-ha:
variables:
MITOGEN_ENABLE: "true"
packet_centos7-crio:
packet_centos8-crio:
extends: .packet_pr
stage: deploy-part2
when: on_success
variables:
MITOGEN_ENABLE: "true"
packet_ubuntu18-crio:
extends: .packet_pr
@@ -225,7 +223,7 @@ packet_ubuntu18-calico-ha-recover:
when: on_success
variables:
RECOVER_CONTROL_PLANE_TEST: "true"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:],kube-master[1:]"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:],kube_control_plane[1:]"
packet_ubuntu18-calico-ha-recover-noquorum:
stage: deploy-part3
@@ -233,4 +231,4 @@ packet_ubuntu18-calico-ha-recover-noquorum:
when: on_success
variables:
RECOVER_CONTROL_PLANE_TEST: "true"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[1:],kube-master[1:]"
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[1:],kube_control_plane[1:]"

View File

@@ -53,73 +53,92 @@
# Cleanup regardless of exit code
- chronic ./tests/scripts/testcases_cleanup.sh
tf-validate-openstack:
extends: .terraform_validate
variables:
TF_VERSION: 0.12.29
PROVIDER: openstack
CLUSTER: $CI_COMMIT_REF_NAME
tf-validate-packet:
extends: .terraform_validate
variables:
TF_VERSION: 0.12.29
PROVIDER: packet
CLUSTER: $CI_COMMIT_REF_NAME
tf-validate-aws:
extends: .terraform_validate
variables:
TF_VERSION: 0.12.29
PROVIDER: aws
CLUSTER: $CI_COMMIT_REF_NAME
tf-0.13.x-validate-openstack:
extends: .terraform_validate
variables:
TF_VERSION: 0.13.5
TF_VERSION: $TERRAFORM_13_VERSION
PROVIDER: openstack
CLUSTER: $CI_COMMIT_REF_NAME
tf-0.13.x-validate-packet:
extends: .terraform_validate
variables:
TF_VERSION: 0.13.5
TF_VERSION: $TERRAFORM_13_VERSION
PROVIDER: packet
CLUSTER: $CI_COMMIT_REF_NAME
tf-0.13.x-validate-aws:
extends: .terraform_validate
variables:
TF_VERSION: 0.13.5
TF_VERSION: $TERRAFORM_13_VERSION
PROVIDER: aws
CLUSTER: $CI_COMMIT_REF_NAME
tf-0.13.x-validate-exoscale:
extends: .terraform_validate
variables:
TF_VERSION: $TERRAFORM_13_VERSION
PROVIDER: exoscale
tf-0.13.x-validate-vsphere:
extends: .terraform_validate
variables:
TF_VERSION: $TERRAFORM_13_VERSION
PROVIDER: vsphere
CLUSTER: $CI_COMMIT_REF_NAME
tf-0.13.x-validate-upcloud:
extends: .terraform_validate
variables:
TF_VERSION: $TERRAFORM_13_VERSION
PROVIDER: upcloud
CLUSTER: $CI_COMMIT_REF_NAME
tf-0.14.x-validate-openstack:
extends: .terraform_validate
variables:
TF_VERSION: 0.14.3
TF_VERSION: $TERRAFORM_14_VERSION
PROVIDER: openstack
CLUSTER: $CI_COMMIT_REF_NAME
tf-0.14.x-validate-packet:
extends: .terraform_validate
variables:
TF_VERSION: 0.14.3
TF_VERSION: $TERRAFORM_14_VERSION
PROVIDER: packet
CLUSTER: $CI_COMMIT_REF_NAME
tf-0.14.x-validate-aws:
extends: .terraform_validate
variables:
TF_VERSION: 0.14.3
TF_VERSION: $TERRAFORM_14_VERSION
PROVIDER: aws
CLUSTER: $CI_COMMIT_REF_NAME
tf-0.14.x-validate-exoscale:
extends: .terraform_validate
variables:
TF_VERSION: $TERRAFORM_14_VERSION
PROVIDER: exoscale
tf-0.14.x-validate-vsphere:
extends: .terraform_validate
variables:
TF_VERSION: $TERRAFORM_14_VERSION
PROVIDER: vsphere
CLUSTER: $CI_COMMIT_REF_NAME
tf-0.14.x-validate-upcloud:
extends: .terraform_validate
variables:
TF_VERSION: $TERRAFORM_14_VERSION
PROVIDER: upcloud
CLUSTER: $CI_COMMIT_REF_NAME
# tf-packet-ubuntu16-default:
# extends: .terraform_apply
# variables:
# TF_VERSION: 0.12.29
# TF_VERSION: $TERRAFORM_14_VERSION
# PROVIDER: packet
# CLUSTER: $CI_COMMIT_REF_NAME
# TF_VAR_number_of_k8s_masters: "1"
@@ -133,7 +152,7 @@ tf-0.14.x-validate-aws:
# tf-packet-ubuntu18-default:
# extends: .terraform_apply
# variables:
# TF_VERSION: 0.12.29
# TF_VERSION: $TERRAFORM_14_VERSION
# PROVIDER: packet
# CLUSTER: $CI_COMMIT_REF_NAME
# TF_VAR_number_of_k8s_masters: "1"
@@ -188,9 +207,10 @@ tf-elastx_ubuntu18-calico:
extends: .terraform_apply
stage: deploy-part3
when: on_success
allow_failure: true
variables:
<<: *elastx_variables
TF_VERSION: 0.12.29
TF_VERSION: $TERRAFORM_14_VERSION
PROVIDER: openstack
CLUSTER: $CI_COMMIT_REF_NAME
ANSIBLE_TIMEOUT: "60"
@@ -216,44 +236,45 @@ tf-elastx_ubuntu18-calico:
TF_VAR_image: ubuntu-18.04-server-latest
TF_VAR_k8s_allowed_remote_ips: '["0.0.0.0/0"]'
# OVH voucher expired, commenting job until things are sorted out
tf-ovh_cleanup:
stage: unit-tests
tags: [light]
image: python
environment: ovh
variables:
<<: *ovh_variables
before_script:
- pip install -r scripts/openstack-cleanup/requirements.txt
script:
- ./scripts/openstack-cleanup/main.py
# tf-ovh_cleanup:
# stage: unit-tests
# tags: [light]
# image: python
# environment: ovh
# variables:
# <<: *ovh_variables
# before_script:
# - pip install -r scripts/openstack-cleanup/requirements.txt
# script:
# - ./scripts/openstack-cleanup/main.py
tf-ovh_ubuntu18-calico:
extends: .terraform_apply
when: on_success
environment: ovh
variables:
<<: *ovh_variables
TF_VERSION: 0.12.29
PROVIDER: openstack
CLUSTER: $CI_COMMIT_REF_NAME
ANSIBLE_TIMEOUT: "60"
SSH_USER: ubuntu
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-ovh_ubuntu18-calico:
# extends: .terraform_apply
# when: on_success
# environment: ovh
# variables:
# <<: *ovh_variables
# TF_VERSION: $TERRAFORM_14_VERSION
# PROVIDER: openstack
# CLUSTER: $CI_COMMIT_REF_NAME
# ANSIBLE_TIMEOUT: "60"
# SSH_USER: ubuntu
# 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"]'

View File

@@ -38,6 +38,11 @@ molecule_tests:
after_script:
- chronic ./tests/scripts/testcases_cleanup.sh
vagrant_ubuntu18-calico-dual-stack:
stage: deploy-part2
extends: .vagrant
when: on_success
vagrant_ubuntu18-flannel:
stage: deploy-part2
extends: .vagrant

View File

@@ -1,25 +1,30 @@
# Use imutable image tags rather than mutable tags (like ubuntu:18.04)
FROM ubuntu:bionic-20200807
ENV KUBE_VERSION=v1.19.7
RUN mkdir /kubespray
WORKDIR /kubespray
RUN apt update -y && \
apt install -y \
RUN apt update -y \
&& apt install -y \
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 \
ca-certificates curl gnupg2 software-properties-common python3-pip rsync \
&& rm -rf /var/lib/apt/lists/*
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 \
$(lsb_release -cs) \
stable" \
&& apt update -y && apt-get install docker-ce -y
COPY . .
RUN /usr/bin/python3 -m pip install pip -U && /usr/bin/python3 -m pip install -r tests/requirements.txt && python3 -m pip install -r requirements.txt && update-alternatives --install /usr/bin/python python /usr/bin/python3 1
&& apt update -y && apt-get install --no-install-recommends -y docker-ce \
&& rm -rf /var/lib/apt/lists/*
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$KUBE_VERSION/bin/linux/amd64/kubectl \
&& chmod a+x kubectl && cp kubectl /usr/local/bin/kubectl
WORKDIR /kubespray
COPY . .
RUN /usr/bin/python3 -m pip install pip -U \
&& /usr/bin/python3 -m pip install -r tests/requirements.txt \
&& python3 -m pip install -r requirements.txt \
&& update-alternatives --install /usr/bin/python python /usr/bin/python3 1
RUN KUBE_VERSION=$(sed -n 's/^kube_version: //p' roles/kubespray-defaults/defaults/main.yaml) \
&& curl -LO https://storage.googleapis.com/kubernetes-release/release/$KUBE_VERSION/bin/linux/amd64/kubectl \
&& chmod a+x kubectl \
&& mv kubectl /usr/local/bin/kubectl
# Some tools like yamllint need this
ENV LANG=C.UTF-8

View File

@@ -32,7 +32,7 @@ CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inv
# 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
cat inventory/mycluster/group_vars/k8s_cluster/k8s_cluster.yml
# Deploy Kubespray with Ansible Playbook - run the playbook as root
# The option `--become` is required, as for example writing SSL keys in /etc/,
@@ -48,11 +48,23 @@ As a consequence, `ansible-playbook` command will fail with:
ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.
```
probably pointing on a task depending on a module present in requirements.txt (i.e. "unseal vault").
probably pointing on a task depending on a module present in requirements.txt.
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.
A workaround consists of setting `ANSIBLE_LIBRARY` and `ANSIBLE_MODULE_UTILS` environment variables respectively to the `ansible/modules` and `ansible/module_utils` subdirectories of pip packages installation location, which can be found in the Location field of the output of `pip show [package]` before executing `ansible-playbook`.
A simple way to ensure you get all the correct version of Ansible is to use the [pre-built docker image from Quay](https://quay.io/repository/kubespray/kubespray?tab=tags).
You will then need to use [bind mounts](https://docs.docker.com/storage/bind-mounts/) to get the inventory and ssh key into the container, like this:
```ShellSession
docker pull quay.io/kubespray/kubespray:v2.15.1
docker run --rm -it --mount type=bind,source="$(pwd)"/inventory/sample,dst=/inventory \
--mount type=bind,source="${HOME}"/.ssh/id_rsa,dst=/root/.ssh/id_rsa \
quay.io/kubespray/kubespray:v2.15.1 bash
# Inside the container you may now run the kubespray playbooks:
ansible-playbook -i /inventory/inventory.ini --private-key /root/.ssh/id_rsa cluster.yml
```
### Vagrant
For Vagrant we need to install python dependencies for provisioning tasks.
@@ -105,49 +117,55 @@ vagrant up
- **Flatcar Container Linux by Kinvolk**
- **Debian** Buster, Jessie, Stretch, Wheezy
- **Ubuntu** 16.04, 18.04, 20.04
- **CentOS/RHEL** 7, 8 (experimental: see [centos 8 notes](docs/centos8.md))
- **CentOS/RHEL** 7, [8](docs/centos8.md)
- **Fedora** 32, 33
- **Fedora CoreOS** (experimental: see [fcos Note](docs/fcos.md))
- **openSUSE** Leap 42.3/Tumbleweed
- **Oracle Linux** 7, 8 (experimental: [centos 8 notes](docs/centos8.md) apply)
- **openSUSE** Leap 15.x/Tumbleweed
- **Oracle Linux** 7, [8](docs/centos8.md)
- **Alma Linux** [8](docs/centos8.md)
- **Amazon Linux 2** (experimental: see [amazon linux notes](docs/amazonlinux.md)
Note: Upstart/SysV init based OS types are not supported.
## Supported Components
- Core
- [kubernetes](https://github.com/kubernetes/kubernetes) v1.19.7
- [kubernetes](https://github.com/kubernetes/kubernetes) v1.20.7
- [etcd](https://github.com/coreos/etcd) v3.4.13
- [docker](https://www.docker.com/) v19.03 (see note)
- [containerd](https://containerd.io/) v1.3.9
- [cri-o](http://cri-o.io/) v1.19 (experimental: see [CRI-O Note](docs/cri-o.md). Only on fedora, ubuntu and centos based OS)
- [containerd](https://containerd.io/) v1.4.4
- [cri-o](http://cri-o.io/) v1.20 (experimental: see [CRI-O Note](docs/cri-o.md). Only on fedora, ubuntu and centos based OS)
- Network Plugin
- [cni-plugins](https://github.com/containernetworking/plugins) v0.9.0
- [calico](https://github.com/projectcalico/calico) v3.16.5
- [cni-plugins](https://github.com/containernetworking/plugins) v0.9.1
- [calico](https://github.com/projectcalico/calico) v3.17.4
- [canal](https://github.com/projectcalico/canal) (given calico/flannel versions)
- [cilium](https://github.com/cilium/cilium) v1.8.6
- [cilium](https://github.com/cilium/cilium) v1.8.9
- [flanneld](https://github.com/coreos/flannel) v0.13.0
- [kube-ovn](https://github.com/alauda/kube-ovn) v1.5.2
- [kube-router](https://github.com/cloudnativelabs/kube-router) v1.1.1
- [multus](https://github.com/intel/multus-cni) v3.6.0
- [kube-ovn](https://github.com/alauda/kube-ovn) v1.6.2
- [kube-router](https://github.com/cloudnativelabs/kube-router) v1.2.2
- [multus](https://github.com/intel/multus-cni) v3.7.0
- [ovn4nfv](https://github.com/opnfv/ovn4nfv-k8s-plugin) v1.1.0
- [weave](https://github.com/weaveworks/weave) v2.7.0
- [weave](https://github.com/weaveworks/weave) v2.8.1
- Application
- [ambassador](https://github.com/datawire/ambassador): v1.5
- [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.16.1
- [coredns](https://github.com/coredns/coredns) v1.7.0
- [ingress-nginx](https://github.com/kubernetes/ingress-nginx) v0.41.2
- [ingress-nginx](https://github.com/kubernetes/ingress-nginx) v0.43.0
Note: The list of available docker version is 18.09, 19.03 and 20.10. The recommended docker version is 19.03. The kubelet might break on docker's non-standard version numbering (it no longer uses semantic versioning). To ensure auto-updates don't break your cluster look into e.g. yum versionlock plugin or apt pin).
## Container Runtime Notes
- The list of available docker version is 18.09, 19.03 and 20.10. The recommended docker version is 19.03. The kubelet might break on docker's non-standard version numbering (it no longer uses semantic versioning). To ensure auto-updates don't break your cluster look into e.g. yum versionlock plugin or apt pin).
- The cri-o version should be aligned with the respective kubernetes version (i.e. kube_version=1.20.x, crio_version=1.20)
## Requirements
- **Minimum required version of Kubernetes is v1.18**
- **Ansible v2.9.x, Jinja 2.11+ and python-netaddr is installed on the machine that will run Ansible commands, Ansible 2.10.x is not supported for now**
- **Minimum required version of Kubernetes is v1.19**
- **Ansible v2.9.x, Jinja 2.11+ and python-netaddr is installed on the machine that will run Ansible commands, Ansible 2.10.x is experimentally supported for now**
- The target servers must have **access to the Internet** in order to pull docker images. Otherwise, additional configuration is required (See [Offline Environment](docs/offline-environment.md))
- The target servers are configured to allow **IPv4 forwarding**.
- If using IPv6 for pods and services, the target servers are configured to allow **IPv6 forwarding**.
- The **firewalls are not managed**, you'll need to implement your own rules the way you used to.
in order to avoid any issue during deployment you should disable your firewall.
- If kubespray is ran from non-root user account, correct privilege escalation method
@@ -203,6 +221,8 @@ See also [Network checker](docs/netcheck.md).
- [nginx](https://kubernetes.github.io/ingress-nginx): the NGINX Ingress Controller.
- [metallb](docs/metallb.md): the MetalLB bare-metal service LoadBalancer provider.
## Community docs and resources
- [kubernetes.io/docs/setup/production-environment/tools/kubespray/](https://kubernetes.io/docs/setup/production-environment/tools/kubespray/)

28
Vagrantfile vendored
View File

@@ -28,7 +28,7 @@ SUPPORTED_OS = {
"centos8-bento" => {box: "bento/centos-8", user: "vagrant"},
"fedora32" => {box: "fedora/32-cloud-base", user: "vagrant"},
"fedora33" => {box: "fedora/33-cloud-base", user: "vagrant"},
"opensuse" => {box: "bento/opensuse-leap-15.1", user: "vagrant"},
"opensuse" => {box: "bento/opensuse-leap-15.2", user: "vagrant"},
"opensuse-tumbleweed" => {box: "opensuse/Tumbleweed.x86_64", user: "vagrant"},
"oraclelinux" => {box: "generic/oracle7", user: "vagrant"},
"oraclelinux8" => {box: "generic/oracle8", user: "vagrant"},
@@ -49,6 +49,7 @@ $vm_cpus ||= 2
$shared_folders ||= {}
$forwarded_ports ||= {}
$subnet ||= "172.18.8"
$subnet_ipv6 ||= "fd3c:b398:0698:0756"
$os ||= "ubuntu1804"
$network_plugin ||= "flannel"
# Setting multi_networking to true will install Multus: https://github.com/intel/multus-cni
@@ -85,9 +86,9 @@ $inventory = File.absolute_path($inventory, File.dirname(__FILE__))
if ! File.exist?(File.join(File.dirname($inventory), "hosts.ini"))
$vagrant_ansible = File.join(File.dirname(__FILE__), ".vagrant", "provisioners", "ansible")
FileUtils.mkdir_p($vagrant_ansible) if ! File.exist?($vagrant_ansible)
if ! File.exist?(File.join($vagrant_ansible,"inventory"))
FileUtils.ln_s($inventory, File.join($vagrant_ansible,"inventory"))
end
$vagrant_inventory = File.join($vagrant_ansible,"inventory")
FileUtils.rm_f($vagrant_inventory)
FileUtils.ln_s($inventory, $vagrant_inventory)
end
if Vagrant.has_plugin?("vagrant-proxyconf")
@@ -194,11 +195,22 @@ Vagrant.configure("2") do |config|
end
ip = "#{$subnet}.#{i+100}"
node.vm.network :private_network, ip: ip
node.vm.network :private_network, ip: ip,
:libvirt__guest_ipv6 => 'yes',
:libvirt__ipv6_address => "#{$subnet_ipv6}::#{i+100}",
:libvirt__ipv6_prefix => "64",
:libvirt__forward_mode => "none",
:libvirt__dhcp_enabled => false
# Disable swap for each vm
node.vm.provision "shell", inline: "swapoff -a"
# ubuntu1804 and ubuntu2004 have IPv6 explicitly disabled. This undoes that.
if ["ubuntu1804", "ubuntu2004"].include? $os
node.vm.provision "shell", inline: "rm -f /etc/modprobe.d/local.conf"
node.vm.provision "shell", inline: "sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf /etc/sysctl.conf"
end
# Disable firewalld on oraclelinux/redhat vms
if ["oraclelinux","oraclelinux8","rhel7","rhel8"].include? $os
node.vm.provision "shell", inline: "systemctl stop firewalld; systemctl disable firewalld"
@@ -241,9 +253,9 @@ Vagrant.configure("2") do |config|
#ansible.tags = ['download']
ansible.groups = {
"etcd" => ["#{$instance_name_prefix}-[1:#{$etcd_instances}]"],
"kube-master" => ["#{$instance_name_prefix}-[1:#{$kube_master_instances}]"],
"kube-node" => ["#{$instance_name_prefix}-[1:#{$kube_node_instances}]"],
"k8s-cluster:children" => ["kube-master", "kube-node"],
"kube_control_plane" => ["#{$instance_name_prefix}-[1:#{$kube_master_instances}]"],
"kube_node" => ["#{$instance_name_prefix}-[1:#{$kube_node_instances}]"],
"k8s_cluster:children" => ["kube_control_plane", "kube_node"],
}
end
end

View File

@@ -4,7 +4,7 @@
become: no
vars:
minimal_ansible_version: 2.9.0
maximal_ansible_version: 2.10.0
maximal_ansible_version: 2.11.0
ansible_connection: local
tasks:
- name: "Check {{ minimal_ansible_version }} <= Ansible version < {{ maximal_ansible_version }}"
@@ -15,3 +15,18 @@
- ansible_version.string is version(maximal_ansible_version, "<")
tags:
- check
- name: "Check that python netaddr is installed"
assert:
msg: "Python netaddr is not present"
that: "'127.0.0.1' | ipaddr"
tags:
- check
# CentOS 7 provides too old jinja version
- name: "Check that jinja is not too old (install via pip)"
assert:
msg: "Your Jinja version is too old, install via pip"
that: "{% set test %}It works{% endset %}{{ test == 'It works' }}"
tags:
- check

View File

@@ -2,16 +2,21 @@
- name: Check ansible version
import_playbook: ansible_version.yml
- name: Ensure compatibility with old groups
import_playbook: legacy_groups.yml
- hosts: bastion[0]
gather_facts: False
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: bastion-ssh-config, tags: ["localhost", "bastion"] }
- hosts: k8s-cluster:etcd
- hosts: k8s_cluster:etcd
strategy: linear
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
gather_facts: false
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: bootstrap-os, tags: bootstrap-os}
@@ -20,9 +25,10 @@
tags: always
import_playbook: facts.yml
- hosts: k8s-cluster:etcd
- hosts: k8s_cluster:etcd
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes/preinstall, tags: preinstall }
@@ -32,6 +38,7 @@
- hosts: etcd
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- role: etcd
@@ -41,9 +48,10 @@
etcd_events_cluster_setup: "{{ etcd_events_cluster_enabled }}"
when: not etcd_kubeadm_enabled| default(false)
- hosts: k8s-cluster
- hosts: k8s_cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- role: etcd
@@ -53,49 +61,54 @@
etcd_events_cluster_setup: false
when: not etcd_kubeadm_enabled| default(false)
- hosts: k8s-cluster
- hosts: k8s_cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes/node, tags: node }
- hosts: kube-master
- hosts: kube_control_plane
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes/master, tags: master }
- { role: kubernetes/control-plane, tags: master }
- { role: kubernetes/client, tags: client }
- { role: kubernetes-apps/cluster_roles, tags: cluster-roles }
- hosts: k8s-cluster
- hosts: k8s_cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes/kubeadm, tags: kubeadm}
- { role: network_plugin, tags: network }
- { role: kubernetes/node-label, tags: node-label }
- hosts: calico-rr
- hosts: calico_rr
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: network_plugin/calico/rr, tags: ['network', 'calico_rr'] }
- hosts: kube-master[0]
- hosts: kube_control_plane[0]
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes-apps/rotate_tokens, tags: rotate_tokens, when: "secret_changed|default(false)" }
- { role: win_nodes/kubernetes_patch, tags: ["master", "win_nodes"] }
- hosts: kube-master
- hosts: kube_control_plane
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes-apps/external_cloud_controller, tags: external-cloud-controller }
@@ -104,16 +117,18 @@
- { role: kubernetes-apps/ingress_controller, tags: ingress-controller }
- { role: kubernetes-apps/external_provisioner, tags: external-provisioner }
- hosts: kube-master
- hosts: kube_control_plane
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes-apps, tags: apps }
- hosts: k8s-cluster
- hosts: k8s_cluster
gather_facts: False
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
environment: "{{ proxy_disable_env }}"
roles:
- { role: kubespray-defaults }
- { role: kubernetes/preinstall, when: "dns_mode != 'none' and resolvconf_mode == 'host_resolvconf'", tags: resolvconf, dns_late: true }

View File

@@ -35,7 +35,7 @@ class SearchEC2Tags(object):
hosts['_meta'] = { 'hostvars': {} }
##Search ec2 three times to find nodes of each group type. Relies on kubespray-role key/value.
for group in ["kube-master", "kube-node", "etcd"]:
for group in ["kube_control_plane", "kube_node", "etcd"]:
hosts[group] = []
tag_key = "kubespray-role"
tag_value = ["*"+group+"*"]
@@ -70,7 +70,7 @@ class SearchEC2Tags(object):
hosts[group].append(dns_name)
hosts['_meta']['hostvars'][dns_name] = ansible_host
hosts['k8s-cluster'] = {'children':['kube-master', 'kube-node']}
hosts['k8s_cluster'] = {'children':['kube_control_plane', 'kube_node']}
print(json.dumps(hosts, sort_keys=True, indent=2))
SearchEC2Tags()

View File

@@ -7,9 +7,9 @@
{% endif %}
{% endfor %}
[kube-master]
[kube_control_plane]
{% for vm in vm_list %}
{% if 'kube-master' in vm.tags.roles %}
{% if 'kube_control_plane' in vm.tags.roles %}
{{ vm.name }}
{% endif %}
{% endfor %}
@@ -21,13 +21,13 @@
{% endif %}
{% endfor %}
[kube-node]
[kube_node]
{% for vm in vm_list %}
{% if 'kube-node' in vm.tags.roles %}
{% if 'kube_node' in vm.tags.roles %}
{{ vm.name }}
{% endif %}
{% endfor %}
[k8s-cluster:children]
kube-node
kube-master
[k8s_cluster:children]
kube_node
kube_control_plane

View File

@@ -7,9 +7,9 @@
{% endif %}
{% endfor %}
[kube-master]
[kube_control_plane]
{% for vm in vm_roles_list %}
{% if 'kube-master' in vm.tags.roles %}
{% if 'kube_control_plane' in vm.tags.roles %}
{{ vm.name }}
{% endif %}
{% endfor %}
@@ -21,14 +21,14 @@
{% endif %}
{% endfor %}
[kube-node]
[kube_node]
{% for vm in vm_roles_list %}
{% if 'kube-node' in vm.tags.roles %}
{% if 'kube_node' in vm.tags.roles %}
{{ vm.name }}
{% endif %}
{% endfor %}
[k8s-cluster:children]
kube-node
kube-master
[k8s_cluster:children]
kube_node
kube_control_plane

View File

@@ -144,7 +144,7 @@
"[concat('Microsoft.Network/networkInterfaces/', 'master-{{i}}-nic')]"
],
"tags": {
"roles": "kube-master,etcd"
"roles": "kube_control_plane,etcd"
},
"apiVersion": "{{apiVersion}}",
"properties": {

View File

@@ -61,7 +61,7 @@
"[concat('Microsoft.Network/networkInterfaces/', 'minion-{{i}}-nic')]"
],
"tags": {
"roles": "kube-node"
"roles": "kube_node"
},
"apiVersion": "{{apiVersion}}",
"properties": {

View File

@@ -46,7 +46,7 @@ test_distro() {
pass_or_fail "$prefix: netcheck" || return 1
}
NODES=($(egrep ^kube-node hosts))
NODES=($(egrep ^kube_node hosts))
NETCHECKER_HOST=localhost
: ${OUTPUT_DIR:=./out}

View File

@@ -44,8 +44,8 @@ import re
import subprocess
import sys
ROLES = ['all', 'kube-master', 'kube-node', 'etcd', 'k8s-cluster',
'calico-rr']
ROLES = ['all', 'kube_control_plane', 'kube_node', 'etcd', 'k8s_cluster',
'calico_rr']
PROTECTED_NAMES = ROLES
AVAILABLE_COMMANDS = ['help', 'print_cfg', 'print_ips', 'print_hostnames',
'load']
@@ -63,7 +63,9 @@ 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", 2))
# Remove the reference of KUBE_MASTERS after some deprecation cycles.
KUBE_CONTROL_HOSTS = int(os.environ.get("KUBE_CONTROL_HOSTS",
os.environ.get("KUBE_MASTERS", 2)))
# Reconfigures cluster distribution at scale
SCALE_THRESHOLD = int(os.environ.get("SCALE_THRESHOLD", 50))
MASSIVE_SCALE_THRESHOLD = int(os.environ.get("MASSIVE_SCALE_THRESHOLD", 200))
@@ -102,10 +104,11 @@ 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:(etcd_hosts_count + KUBE_MASTERS)])
self.set_kube_control_plane(list(self.hosts.keys())[
etcd_hosts_count:(etcd_hosts_count + KUBE_CONTROL_HOSTS)])
else:
self.set_kube_master(list(self.hosts.keys())[:KUBE_MASTERS])
self.set_kube_control_plane(
list(self.hosts.keys())[:KUBE_CONTROL_HOSTS])
self.set_kube_node(self.hosts.keys())
if len(self.hosts) >= SCALE_THRESHOLD:
self.set_calico_rr(list(self.hosts.keys())[:etcd_hosts_count])
@@ -266,7 +269,7 @@ class KubesprayInventory(object):
def purge_invalid_hosts(self, hostnames, protected_names=[]):
for role in self.yaml_config['all']['children']:
if role != 'k8s-cluster' and self.yaml_config['all']['children'][role]['hosts']: # noqa
if role != 'k8s_cluster' and self.yaml_config['all']['children'][role]['hosts']: # noqa
all_hosts = self.yaml_config['all']['children'][role]['hosts'].copy() # noqa
for host in all_hosts.keys():
if host not in hostnames and host not in protected_names:
@@ -287,52 +290,54 @@ class KubesprayInventory(object):
if self.yaml_config['all']['hosts'] is None:
self.yaml_config['all']['hosts'] = {host: None}
self.yaml_config['all']['hosts'][host] = opts
elif group != 'k8s-cluster:children':
elif group != 'k8s_cluster:children':
if self.yaml_config['all']['children'][group]['hosts'] is None:
self.yaml_config['all']['children'][group]['hosts'] = {
host: None}
else:
self.yaml_config['all']['children'][group]['hosts'][host] = None # noqa
def set_kube_master(self, hosts):
def set_kube_control_plane(self, hosts):
for host in hosts:
self.add_host_to_group('kube-master', host)
self.add_host_to_group('kube_control_plane', host)
def set_all(self, hosts):
for host, opts in hosts.items():
self.add_host_to_group('all', host, opts)
def set_k8s_cluster(self):
k8s_cluster = {'children': {'kube-master': None, 'kube-node': None}}
self.yaml_config['all']['children']['k8s-cluster'] = k8s_cluster
k8s_cluster = {'children': {'kube_control_plane': None,
'kube_node': None}}
self.yaml_config['all']['children']['k8s_cluster'] = k8s_cluster
def set_calico_rr(self, hosts):
for host in hosts:
if host in self.yaml_config['all']['children']['kube-master']:
self.debug("Not adding {0} to calico-rr group because it "
"conflicts with kube-master group".format(host))
if host in self.yaml_config['all']['children']['kube_control_plane']: # noqa
self.debug("Not adding {0} to calico_rr group because it "
"conflicts with kube_control_plane "
"group".format(host))
continue
if host in self.yaml_config['all']['children']['kube-node']:
self.debug("Not adding {0} to calico-rr group because it "
"conflicts with kube-node group".format(host))
if host in self.yaml_config['all']['children']['kube_node']:
self.debug("Not adding {0} to calico_rr group because it "
"conflicts with kube_node group".format(host))
continue
self.add_host_to_group('calico-rr', host)
self.add_host_to_group('calico_rr', host)
def set_kube_node(self, hosts):
for host in hosts:
if len(self.yaml_config['all']['hosts']) >= SCALE_THRESHOLD:
if host in self.yaml_config['all']['children']['etcd']['hosts']: # noqa
self.debug("Not adding {0} to kube-node group because of "
self.debug("Not adding {0} to kube_node group because of "
"scale deployment and host is in etcd "
"group.".format(host))
continue
if len(self.yaml_config['all']['hosts']) >= MASSIVE_SCALE_THRESHOLD: # noqa
if host in self.yaml_config['all']['children']['kube-master']['hosts']: # noqa
self.debug("Not adding {0} to kube-node group because of "
"scale deployment and host is in kube-master "
"group.".format(host))
if host in self.yaml_config['all']['children']['kube_control_plane']['hosts']: # noqa
self.debug("Not adding {0} to kube_node group because of "
"scale deployment and host is in "
"kube_control_plane group.".format(host))
continue
self.add_host_to_group('kube-node', host)
self.add_host_to_group('kube_node', host)
def set_etcd(self, hosts):
for host in hosts:
@@ -402,9 +407,9 @@ Configurable env vars:
DEBUG Enable debug printing. Default: True
CONFIG_FILE File to write config to Default: ./inventory/sample/hosts.yaml
HOST_PREFIX Host prefix for generated hosts. Default: node
KUBE_MASTERS Set the number of kube-masters. Default: 2
KUBE_CONTROL_HOSTS Set the number of kube-control-planes. Default: 2
SCALE_THRESHOLD Separate ETCD role if # of nodes >= 50
MASSIVE_SCALE_THRESHOLD Separate K8s master and ETCD if # of nodes >= 200
MASSIVE_SCALE_THRESHOLD Separate K8s control-plane and ETCD if # of nodes >= 200
''' # noqa
print(help_text)

View File

@@ -13,8 +13,8 @@
# under the License.
import inventory
import mock
import unittest
from unittest import mock
from collections import OrderedDict
import sys
@@ -222,11 +222,11 @@ class TestInventory(unittest.TestCase):
self.inv.yaml_config['all']['children'][group]['hosts'].get(host),
None)
def test_set_kube_master(self):
group = 'kube-master'
def test_set_kube_control_plane(self):
group = 'kube_control_plane'
host = 'node1'
self.inv.set_kube_master([host])
self.inv.set_kube_control_plane([host])
self.assertIn(
host, self.inv.yaml_config['all']['children'][group]['hosts'])
@@ -241,8 +241,8 @@ class TestInventory(unittest.TestCase):
self.inv.yaml_config['all']['hosts'].get(host), opt)
def test_set_k8s_cluster(self):
group = 'k8s-cluster'
expected_hosts = ['kube-node', 'kube-master']
group = 'k8s_cluster'
expected_hosts = ['kube_node', 'kube_control_plane']
self.inv.set_k8s_cluster()
for host in expected_hosts:
@@ -251,7 +251,7 @@ class TestInventory(unittest.TestCase):
self.inv.yaml_config['all']['children'][group]['children'])
def test_set_kube_node(self):
group = 'kube-node'
group = 'kube_node'
host = 'node1'
self.inv.set_kube_node([host])
@@ -275,12 +275,12 @@ class TestInventory(unittest.TestCase):
self.inv.set_all(hosts)
self.inv.set_etcd(list(hosts.keys())[0:3])
self.inv.set_kube_master(list(hosts.keys())[0:2])
self.inv.set_kube_control_plane(list(hosts.keys())[0:2])
self.inv.set_kube_node(hosts.keys())
for h in range(3):
self.assertFalse(
list(hosts.keys())[h] in
self.inv.yaml_config['all']['children']['kube-node']['hosts'])
self.inv.yaml_config['all']['children']['kube_node']['hosts'])
def test_scale_scenario_two(self):
num_nodes = 500
@@ -291,12 +291,12 @@ class TestInventory(unittest.TestCase):
self.inv.set_all(hosts)
self.inv.set_etcd(list(hosts.keys())[0:3])
self.inv.set_kube_master(list(hosts.keys())[3:5])
self.inv.set_kube_control_plane(list(hosts.keys())[3:5])
self.inv.set_kube_node(hosts.keys())
for h in range(5):
self.assertFalse(
list(hosts.keys())[h] in
self.inv.yaml_config['all']['children']['kube-node']['hosts'])
self.inv.yaml_config['all']['children']['kube_node']['hosts'])
def test_range2ips_range(self):
changed_hosts = ['10.90.0.2', '10.90.0.4-10.90.0.6', '10.90.0.8']

View File

@@ -15,10 +15,10 @@
roles:
- { role: glusterfs/server }
- hosts: k8s-cluster
- hosts: k8s_cluster
roles:
- { role: glusterfs/client }
- hosts: kube-master[0]
- hosts: kube_control_plane[0]
roles:
- { role: kubernetes-pv }

View File

@@ -14,7 +14,7 @@
# gfs_node2 ansible_ssh_host=95.54.0.19 # disk_volume_device_1=/dev/vdc ip=10.3.0.8
# gfs_node3 ansible_ssh_host=95.54.0.20 # disk_volume_device_1=/dev/vdc ip=10.3.0.9
# [kube-master]
# [kube_control_plane]
# node1
# node2
@@ -23,16 +23,16 @@
# node2
# node3
# [kube-node]
# [kube_node]
# node2
# node3
# node4
# node5
# node6
# [k8s-cluster:children]
# kube-node
# kube-master
# [k8s_cluster:children]
# kube_node
# kube_control_plane
# [gfs-cluster]
# gfs_node1

View File

@@ -8,7 +8,7 @@ Installs and configures GlusterFS on Linux.
For GlusterFS to connect between servers, TCP ports `24007`, `24008`, and `24009`/`49152`+ (that port, plus an additional incremented port for each additional server in the cluster; the latter if GlusterFS is version 3.4+), and TCP/UDP port `111` must be open. You can open these using whatever firewall you wish (this can easily be configured using the `geerlingguy.firewall` role).
This role performs basic installation and setup of Gluster, but it does not configure or mount bricks (volumes), since that step is easier to do in a series of plays in your own playbook. Ansible 1.9+ includes the [`gluster_volume`](https://docs.ansible.com/gluster_volume_module.html) module to ease the management of Gluster volumes.
This role performs basic installation and setup of Gluster, but it does not configure or mount bricks (volumes), since that step is easier to do in a series of plays in your own playbook. Ansible 1.9+ includes the [`gluster_volume`](https://docs.ansible.com/ansible/latest/collections/gluster/gluster/gluster_volume_module.html) module to ease the management of Gluster volumes.
## Role Variables

View File

@@ -8,7 +8,7 @@
- { file: glusterfs-kubernetes-pv.yml.j2, type: pv, dest: glusterfs-kubernetes-pv.yml}
- { file: glusterfs-kubernetes-endpoint-svc.json.j2, type: svc, dest: glusterfs-kubernetes-endpoint-svc.json}
register: gluster_pv
when: inventory_hostname == groups['kube-master'][0] and groups['gfs-cluster'] is defined and hostvars[groups['gfs-cluster'][0]].gluster_disk_size_gb is defined
when: inventory_hostname == groups['kube_control_plane'][0] and groups['gfs-cluster'] is defined and hostvars[groups['gfs-cluster'][0]].gluster_disk_size_gb is defined
- name: Kubernetes Apps | Set GlusterFS endpoint and PV
kube:
@@ -19,4 +19,4 @@
filename: "{{ kube_config_dir }}/{{ item.item.dest }}"
state: "{{ item.changed | ternary('latest','present') }}"
with_items: "{{ gluster_pv.results }}"
when: inventory_hostname == groups['kube-master'][0] and groups['gfs-cluster'] is defined
when: inventory_hostname == groups['kube_control_plane'][0] and groups['gfs-cluster'] is defined

View File

@@ -1,5 +1,5 @@
---
- hosts: kube-master[0]
- hosts: kube_control_plane[0]
roles:
- { role: tear-down }

View File

@@ -3,7 +3,7 @@
roles:
- { role: prepare }
- hosts: kube-master[0]
- hosts: kube_control_plane[0]
tags:
- "provision"
roles:

View File

@@ -3,17 +3,17 @@ all:
heketi_admin_key: "11elfeinhundertundelf"
heketi_user_key: "!!einseinseins"
children:
k8s-cluster:
k8s_cluster:
vars:
kubelet_fail_swap_on: false
children:
kube-master:
kube_control_plane:
hosts:
node1:
etcd:
hosts:
node2:
kube-node:
kube_node:
hosts: &kube_nodes
node1:
node2:

View File

@@ -1,4 +1,8 @@
# Container image collecting script for offline deployment
# Offline deployment
## manage-offline-container-images.sh
Container image collecting script for offline deployment
This script has two features:
(1) Get container images from an environment which is deployed online.
@@ -19,3 +23,21 @@ Step(2) can be operated with:
```shell
manage-offline-container-images.sh register
```
## generate_list.sh
This script generates the list of downloaded files and the list of container images by `roles/download/defaults/main.yml` file.
Run this script will generates three files, all downloaded files url in files.list, all container images in images.list, all component version in generate.sh.
```shell
bash generate_list.sh
tree temp
temp
├── files.list
├── generate.sh
└── images.list
0 directories, 3 files
```
In some cases you may want to update some component version, you can edit `generate.sh` file, then run `bash generate.sh | grep 'https' > files.list` to update file.list or run `bash generate.sh | grep -v 'https'> images.list` to update images.list.

View File

@@ -0,0 +1,57 @@
#!/bin/bash
set -eo pipefail
CURRENT_DIR=$(cd $(dirname $0); pwd)
TEMP_DIR="${CURRENT_DIR}/temp"
REPO_ROOT_DIR="${CURRENT_DIR%/contrib/offline}"
: ${IMAGE_ARCH:="amd64"}
: ${ANSIBLE_SYSTEM:="linux"}
: ${ANSIBLE_ARCHITECTURE:="x86_64"}
: ${DOWNLOAD_YML:="roles/download/defaults/main.yml"}
: ${KUBE_VERSION_YAML:="roles/kubespray-defaults/defaults/main.yaml"}
mkdir -p ${TEMP_DIR}
# ARCH used in convert {%- if image_arch != 'amd64' -%}-{{ image_arch }}{%- endif -%} to {{arch}}
if [ "${IMAGE_ARCH}" != "amd64" ]; then ARCH="${IMAGE_ARCH}"; fi
cat > ${TEMP_DIR}/generate.sh << EOF
arch=${ARCH}
image_arch=${IMAGE_ARCH}
ansible_system=${ANSIBLE_SYSTEM}
ansible_architecture=${ANSIBLE_ARCHITECTURE}
EOF
# generate all component version by $DOWNLOAD_YML
grep 'kube_version:' ${REPO_ROOT_DIR}/${KUBE_VERSION_YAML} \
| sed 's/: /=/g' >> ${TEMP_DIR}/generate.sh
grep '_version:' ${REPO_ROOT_DIR}/${DOWNLOAD_YML} \
| sed 's/: /=/g;s/{{/${/g;s/}}/}/g' | tr -d ' ' >> ${TEMP_DIR}/generate.sh
sed -i 's/kube_major_version=.*/kube_major_version=${kube_version%.*}/g' ${TEMP_DIR}/generate.sh
sed -i 's/crictl_version=.*/crictl_version=${kube_version%.*}.0/g' ${TEMP_DIR}/generate.sh
# generate all download files url
grep 'download_url:' ${REPO_ROOT_DIR}/${DOWNLOAD_YML} \
| sed 's/: /=/g;s/ //g;s/{{/${/g;s/}}/}/g;s/|lower//g;s/^.*_url=/echo /g' >> ${TEMP_DIR}/generate.sh
# generate all images list
grep -E '_repo:|_tag:' ${REPO_ROOT_DIR}/${DOWNLOAD_YML} \
| sed "s#{%- if image_arch != 'amd64' -%}-{{ image_arch }}{%- endif -%}#{{arch}}#g" \
| sed 's/: /=/g;s/{{/${/g;s/}}/}/g' | tr -d ' ' >> ${TEMP_DIR}/generate.sh
sed -n '/^downloads:/,/download_defaults:/p' ${REPO_ROOT_DIR}/${DOWNLOAD_YML} \
| sed -n "s/repo: //p;s/tag: //p" | tr -d ' ' | sed 's/{{/${/g;s/}}/}/g' \
| sed 'N;s#\n# #g' | tr ' ' ':' | sed 's/^/echo /g' >> ${TEMP_DIR}/generate.sh
# special handling for https://github.com/kubernetes-sigs/kubespray/pull/7570
sed -i 's#^coredns_image_repo=.*#coredns_image_repo=${kube_image_repo}$(if printf "%s\\n%s\\n" v1.21 ${kube_version%.*} | sort --check=quiet --version-sort; then echo -n /coredns/coredns;else echo -n /coredns; fi)#' ${TEMP_DIR}/generate.sh
sed -i 's#^coredns_image_tag=.*#coredns_image_tag=$(if printf "%s\\n%s\\n" v1.21 ${kube_version%.*} | sort --check=quiet --version-sort; then echo -n ${coredns_version};else echo -n ${coredns_version/v/}; fi)#' ${TEMP_DIR}/generate.sh
# add kube-* images to images list
KUBE_IMAGES="kube-apiserver kube-controller-manager kube-scheduler kube-proxy"
echo "${KUBE_IMAGES}" | tr ' ' '\n' | xargs -L1 -I {} \
echo 'echo ${kube_image_repo}/{}:${kube_version}' >> ${TEMP_DIR}/generate.sh
# print files.list and images.list
bash ${TEMP_DIR}/generate.sh | grep 'https' | sort > ${TEMP_DIR}/files.list
bash ${TEMP_DIR}/generate.sh | grep -v 'https' | sort > ${TEMP_DIR}/images.list

View File

@@ -100,15 +100,35 @@ function register_container_images() {
tar -zxvf ${IMAGE_TAR_FILE}
sudo docker load -i ${IMAGE_DIR}/registry-latest.tar
sudo docker run --restart=always -d -p 5000:5000 --name registry registry:latest
set +e
sudo docker container inspect registry >/dev/null 2>&1
if [ $? -ne 0 ]; then
sudo docker run --restart=always -d -p 5000:5000 --name registry registry:latest
fi
set -e
while read -r line; do
file_name=$(echo ${line} | awk '{print $1}')
org_image=$(echo ${line} | awk '{print $2}')
new_image="${LOCALHOST_NAME}:5000/${org_image}"
image_id=$(tar -tf ${IMAGE_DIR}/${file_name} | grep "\.json" | grep -v manifest.json | sed s/"\.json"//)
raw_image=$(echo ${line} | awk '{print $2}')
new_image="${LOCALHOST_NAME}:5000/${raw_image}"
org_image=$(sudo docker load -i ${IMAGE_DIR}/${file_name} | head -n1 | awk '{print $3}')
image_id=$(sudo docker image inspect ${org_image} | grep "\"Id\":" | awk -F: '{print $3}'| sed s/'\",'//)
if [ -z "${file_name}" ]; then
echo "Failed to get file_name for line ${line}"
exit 1
fi
if [ -z "${raw_image}" ]; then
echo "Failed to get raw_image for line ${line}"
exit 1
fi
if [ -z "${org_image}" ]; then
echo "Failed to get org_image for line ${line}"
exit 1
fi
if [ -z "${image_id}" ]; then
echo "Failed to get image_id for file ${file_name}"
exit 1
fi
sudo docker load -i ${IMAGE_DIR}/${file_name}
sudo docker tag ${image_id} ${new_image}
sudo docker push ${new_image}

View File

@@ -0,0 +1,4 @@
---
- hosts: all
roles:
- { role: prepare }

View File

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

View File

@@ -0,0 +1,23 @@
---
- block:
- name: List services
service_facts:
- name: Disable service firewalld
systemd:
name: firewalld
state: stopped
enabled: no
when:
"'firewalld.service' in services"
- name: Disable service ufw
systemd:
name: ufw
state: stopped
enabled: no
when:
"'ufw.service' in services"
when:
- disable_service_firewall

View File

@@ -51,7 +51,7 @@ export SKIP_PIP_INSTALL=1
%doc %{_docdir}/%{name}/inventory/sample/hosts.ini
%config %{_sysconfdir}/%{name}/ansible.cfg
%config %{_sysconfdir}/%{name}/inventory/sample/group_vars/all.yml
%config %{_sysconfdir}/%{name}/inventory/sample/group_vars/k8s-cluster.yml
%config %{_sysconfdir}/%{name}/inventory/sample/group_vars/k8s_cluster.yml
%license %{_docdir}/%{name}/LICENSE
%{python2_sitelib}/%{srcname}-%{release}-py%{python2_version}.egg-info
%{_datarootdir}/%{name}/roles/

View File

@@ -122,7 +122,7 @@ You can use the following set of commands to get the kubeconfig file from your n
```commandline
# Get the controller's IP address.
CONTROLLER_HOST_NAME=$(cat ./inventory/hosts | grep "\[kube-master\]" -A 1 | tail -n 1)
CONTROLLER_HOST_NAME=$(cat ./inventory/hosts | grep "\[kube_control_plane\]" -A 1 | tail -n 1)
CONTROLLER_IP=$(cat ./inventory/hosts | grep $CONTROLLER_HOST_NAME | grep ansible_host | cut -d'=' -f2)
# Get the hostname of the load balancer.

View File

@@ -61,11 +61,11 @@ resource "aws_instance" "bastion-server" {
key_name = var.AWS_SSH_KEY_NAME
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-bastion-${count.index}",
"Cluster", var.aws_cluster_name,
"Role", "bastion-${var.aws_cluster_name}-${count.index}"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-bastion-${count.index}"
Cluster = var.aws_cluster_name
Role = "bastion-${var.aws_cluster_name}-${count.index}"
}))
}
/*
@@ -84,14 +84,14 @@ resource "aws_instance" "k8s-master" {
vpc_security_group_ids = module.aws-vpc.aws_security_group
iam_instance_profile = module.aws-iam.kube-master-profile
iam_instance_profile = module.aws-iam.kube_control_plane-profile
key_name = var.AWS_SSH_KEY_NAME
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-master${count.index}",
"kubernetes.io/cluster/${var.aws_cluster_name}", "member",
"Role", "master"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-master${count.index}"
"kubernetes.io/cluster/${var.aws_cluster_name}" = "member"
Role = "master"
}))
}
resource "aws_elb_attachment" "attach_master_nodes" {
@@ -113,11 +113,11 @@ resource "aws_instance" "k8s-etcd" {
key_name = var.AWS_SSH_KEY_NAME
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-etcd${count.index}",
"kubernetes.io/cluster/${var.aws_cluster_name}", "member",
"Role", "etcd"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-etcd${count.index}"
"kubernetes.io/cluster/${var.aws_cluster_name}" = "member"
Role = "etcd"
}))
}
resource "aws_instance" "k8s-worker" {
@@ -134,11 +134,11 @@ resource "aws_instance" "k8s-worker" {
iam_instance_profile = module.aws-iam.kube-worker-profile
key_name = var.AWS_SSH_KEY_NAME
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-worker${count.index}",
"kubernetes.io/cluster/${var.aws_cluster_name}", "member",
"Role", "worker"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-worker${count.index}"
"kubernetes.io/cluster/${var.aws_cluster_name}" = "member"
Role = "worker"
}))
}
/*

View File

@@ -2,9 +2,9 @@ resource "aws_security_group" "aws-elb" {
name = "kubernetes-${var.aws_cluster_name}-securitygroup-elb"
vpc_id = var.aws_vpc_id
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-securitygroup-elb"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-securitygroup-elb"
}))
}
resource "aws_security_group_rule" "aws-allow-api-access" {
@@ -51,7 +51,7 @@ resource "aws_elb" "aws-elb-api" {
connection_draining = true
connection_draining_timeout = 400
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-elb-api"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-elb-api"
}))
}

View File

@@ -1,6 +1,6 @@
#Add AWS Roles for Kubernetes
resource "aws_iam_role" "kube-master" {
resource "aws_iam_role" "kube_control_plane" {
name = "kubernetes-${var.aws_cluster_name}-master"
assume_role_policy = <<EOF
@@ -40,9 +40,9 @@ EOF
#Add AWS Policies for Kubernetes
resource "aws_iam_role_policy" "kube-master" {
resource "aws_iam_role_policy" "kube_control_plane" {
name = "kubernetes-${var.aws_cluster_name}-master"
role = aws_iam_role.kube-master.id
role = aws_iam_role.kube_control_plane.id
policy = <<EOF
{
@@ -130,9 +130,9 @@ EOF
#Create AWS Instance Profiles
resource "aws_iam_instance_profile" "kube-master" {
resource "aws_iam_instance_profile" "kube_control_plane" {
name = "kube_${var.aws_cluster_name}_master_profile"
role = aws_iam_role.kube-master.name
role = aws_iam_role.kube_control_plane.name
}
resource "aws_iam_instance_profile" "kube-worker" {

View File

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

View File

@@ -5,9 +5,9 @@ resource "aws_vpc" "cluster-vpc" {
enable_dns_support = true
enable_dns_hostnames = true
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-vpc"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-vpc"
}))
}
resource "aws_eip" "cluster-nat-eip" {
@@ -18,9 +18,9 @@ resource "aws_eip" "cluster-nat-eip" {
resource "aws_internet_gateway" "cluster-vpc-internetgw" {
vpc_id = aws_vpc.cluster-vpc.id
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-internetgw"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-internetgw"
}))
}
resource "aws_subnet" "cluster-vpc-subnets-public" {
@@ -29,10 +29,10 @@ resource "aws_subnet" "cluster-vpc-subnets-public" {
availability_zone = element(var.aws_avail_zones, count.index)
cidr_block = element(var.aws_cidr_subnets_public, count.index)
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-${element(var.aws_avail_zones, count.index)}-public",
"kubernetes.io/cluster/${var.aws_cluster_name}", "member"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-${element(var.aws_avail_zones, count.index)}-public"
"kubernetes.io/cluster/${var.aws_cluster_name}" = "member"
}))
}
resource "aws_nat_gateway" "cluster-nat-gateway" {
@@ -47,9 +47,9 @@ resource "aws_subnet" "cluster-vpc-subnets-private" {
availability_zone = element(var.aws_avail_zones, count.index)
cidr_block = element(var.aws_cidr_subnets_private, count.index)
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-${element(var.aws_avail_zones, count.index)}-private"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-${element(var.aws_avail_zones, count.index)}-private"
}))
}
#Routing in VPC
@@ -64,9 +64,9 @@ resource "aws_route_table" "kubernetes-public" {
gateway_id = aws_internet_gateway.cluster-vpc-internetgw.id
}
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-routetable-public"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-routetable-public"
}))
}
resource "aws_route_table" "kubernetes-private" {
@@ -78,9 +78,9 @@ resource "aws_route_table" "kubernetes-private" {
nat_gateway_id = element(aws_nat_gateway.cluster-nat-gateway.*.id, count.index)
}
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-routetable-private-${count.index}"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-routetable-private-${count.index}"
}))
}
resource "aws_route_table_association" "kubernetes-public" {
@@ -101,9 +101,9 @@ resource "aws_security_group" "kubernetes" {
name = "kubernetes-${var.aws_cluster_name}-securitygroup"
vpc_id = aws_vpc.cluster-vpc.id
tags = merge(var.default_tags, map(
"Name", "kubernetes-${var.aws_cluster_name}-securitygroup"
))
tags = merge(var.default_tags, tomap({
Name = "kubernetes-${var.aws_cluster_name}-securitygroup"
}))
}
resource "aws_security_group_rule" "allow-all-ingress" {

View File

@@ -7,11 +7,11 @@ ${public_ip_address_bastion}
[bastion]
${public_ip_address_bastion}
[kube-master]
[kube_control_plane]
${list_master}
[kube-node]
[kube_node]
${list_node}
@@ -19,10 +19,10 @@ ${list_node}
${list_etcd}
[k8s-cluster:children]
kube-node
kube-master
[k8s_cluster:children]
kube_node
kube_control_plane
[k8s-cluster:vars]
[k8s_cluster:vars]
${elb_api_fqdn}

View File

@@ -0,0 +1,154 @@
# Kubernetes on Exoscale with Terraform
Provision a Kubernetes cluster on [Exoscale](https://www.exoscale.com/) using Terraform and Kubespray
## Overview
The setup looks like following
```text
Kubernetes cluster
+-----------------------+
+---------------+ | +--------------+ |
| | | | +--------------+ |
| API server LB +---------> | | | |
| | | | | Master/etcd | |
+---------------+ | | | node(s) | |
| +-+ | |
| +--------------+ |
| ^ |
| | |
| v |
+---------------+ | +--------------+ |
| | | | +--------------+ |
| Ingress LB +---------> | | | |
| | | | | Worker | |
+---------------+ | | | node(s) | |
| +-+ | |
| +--------------+ |
+-----------------------+
```
## Requirements
* Terraform 0.13.0 or newer
*0.12 also works if you modify the provider block to include version and remove all `versions.tf` files*
## Quickstart
NOTE: *Assumes you are at the root of the kubespray repo*
Copy the sample inventory for your cluster and copy the default terraform variables.
```bash
CLUSTER=my-exoscale-cluster
cp -r inventory/sample inventory/$CLUSTER
cp contrib/terraform/exoscale/default.tfvars inventory/$CLUSTER/
cd inventory/$CLUSTER
```
Edit `default.tfvars` to match your setup. You MUST, at the very least, change `ssh_public_keys`.
```bash
# Ensure $EDITOR points to your favorite editor, e.g., vim, emacs, VS Code, etc.
$EDITOR default.tfvars
```
For authentication you can use the credentials file `~/.cloudstack.ini` or `./cloudstack.ini`.
The file should look like something like this:
```ini
[cloudstack]
key = <API key>
secret = <API secret>
```
Follow the [Exoscale IAM Quick-start](https://community.exoscale.com/documentation/iam/quick-start/) to learn how to generate API keys.
### Encrypted credentials
To have the credentials encrypted at rest, you can use [sops](https://github.com/mozilla/sops) and only decrypt the credentials at runtime.
```bash
cat << EOF > cloudstack.ini
[cloudstack]
key =
secret =
EOF
sops --encrypt --in-place --pgp <PGP key fingerprint> cloudstack.ini
sops cloudstack.ini
```
Run terraform to create the infrastructure
```bash
terraform init ../../contrib/terraform/exoscale
terraform apply -var-file default.tfvars ../../contrib/terraform/exoscale
```
If your cloudstack credentials file is encrypted using sops, run the following:
```bash
terraform init ../../contrib/terraform/exoscale
sops exec-file -no-fifo cloudstack.ini 'CLOUDSTACK_CONFIG={} terraform apply -var-file default.tfvars ../../contrib/terraform/exoscale'
```
You should now have a inventory file named `inventory.ini` that you can use with kubespray.
You can now copy your inventory file and use it with kubespray to set up a cluster.
You can type `terraform output` to find out the IP addresses of the nodes, as well as control-plane and data-plane load-balancer.
It is a good idea to check that you have basic SSH connectivity to the nodes. You can do that by:
```bash
ansible -i inventory.ini -m ping all
```
Example to use this with the default sample inventory:
```bash
ansible-playbook -i inventory.ini ../../cluster.yml -b -v
```
## Teardown
The Kubernetes cluster cannot create any load-balancers or disks, hence, teardown is as simple as Terraform destroy:
```bash
terraform destroy -var-file default.tfvars ../../contrib/terraform/exoscale
```
## Variables
### Required
* `ssh_public_keys`: List of public SSH keys to install on all machines
* `zone`: The zone where to run the cluster
* `machines`: Machines to provision. Key of this object will be used as the name of the machine
* `node_type`: The role of this node *(master|worker)*
* `size`: The size to use
* `boot_disk`: The boot disk to use
* `image_name`: Name of the image
* `root_partition_size`: Size *(in GB)* for the root partition
* `ceph_partition_size`: Size *(in GB)* for the partition for rook to use as ceph storage. *(Set to 0 to disable)*
* `node_local_partition_size`: Size *(in GB)* for the partition for node-local-storage. *(Set to 0 to disable)*
* `ssh_whitelist`: List of IP ranges (CIDR) that will be allowed to ssh to the nodes
* `api_server_whitelist`: List of IP ranges (CIDR) that will be allowed to connect to the API server
* `nodeport_whitelist`: List of IP ranges (CIDR) that will be allowed to connect to the kubernetes nodes on port 30000-32767 (kubernetes nodeports)
### Optional
* `prefix`: Prefix to use for all resources, required to be unique for all clusters in the same project *(Defaults to `default`)*
An example variables file can be found `default.tfvars`
## Known limitations
### Only single disk
Since Exoscale doesn't support additional disks to be mounted onto an instance, this script has the ability to create partitions for [Rook](https://rook.io/) and [node-local-storage](https://kubernetes.io/docs/concepts/storage/volumes/#local).
### No Kubernetes API
The current solution doesn't use the [Exoscale Kubernetes cloud controller](https://github.com/exoscale/exoscale-cloud-controller-manager).
This means that we need to set up a HTTP(S) loadbalancer in front of all workers and set the Ingress controller to DaemonSet mode.

View File

@@ -0,0 +1,65 @@
prefix = "default"
zone = "ch-gva-2"
inventory_file = "inventory.ini"
ssh_public_keys = [
# Put your public SSH key here
"ssh-rsa I-did-not-read-the-docs",
"ssh-rsa I-did-not-read-the-docs 2",
]
machines = {
"master-0" : {
"node_type" : "master",
"size" : "Medium",
"boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50,
"node_local_partition_size" : 0,
"ceph_partition_size" : 0
}
},
"worker-0" : {
"node_type" : "worker",
"size" : "Large",
"boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50,
"node_local_partition_size" : 0,
"ceph_partition_size" : 0
}
},
"worker-1" : {
"node_type" : "worker",
"size" : "Large",
"boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50,
"node_local_partition_size" : 0,
"ceph_partition_size" : 0
}
},
"worker-2" : {
"node_type" : "worker",
"size" : "Large",
"boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50,
"node_local_partition_size" : 0,
"ceph_partition_size" : 0
}
}
}
nodeport_whitelist = [
"0.0.0.0/0"
]
ssh_whitelist = [
"0.0.0.0/0"
]
api_server_whitelist = [
"0.0.0.0/0"
]

View File

@@ -0,0 +1,49 @@
provider "exoscale" {}
module "kubernetes" {
source = "./modules/kubernetes-cluster"
prefix = var.prefix
machines = var.machines
ssh_public_keys = var.ssh_public_keys
ssh_whitelist = var.ssh_whitelist
api_server_whitelist = var.api_server_whitelist
nodeport_whitelist = var.nodeport_whitelist
}
#
# Generate ansible inventory
#
data "template_file" "inventory" {
template = file("${path.module}/templates/inventory.tpl")
vars = {
connection_strings_master = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s ip=%s etcd_member_name=etcd%d",
keys(module.kubernetes.master_ip_addresses),
values(module.kubernetes.master_ip_addresses).*.public_ip,
values(module.kubernetes.master_ip_addresses).*.private_ip,
range(1, length(module.kubernetes.master_ip_addresses) + 1)))
connection_strings_worker = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s ip=%s",
keys(module.kubernetes.worker_ip_addresses),
values(module.kubernetes.worker_ip_addresses).*.public_ip,
values(module.kubernetes.worker_ip_addresses).*.private_ip))
list_master = join("\n", keys(module.kubernetes.master_ip_addresses))
list_worker = join("\n", keys(module.kubernetes.worker_ip_addresses))
api_lb_ip_address = module.kubernetes.control_plane_lb_ip_address
}
}
resource "null_resource" "inventories" {
provisioner "local-exec" {
command = "echo '${data.template_file.inventory.rendered}' > ${var.inventory_file}"
}
triggers = {
template = data.template_file.inventory.rendered
}
}

View File

@@ -0,0 +1,193 @@
data "exoscale_compute_template" "os_image" {
for_each = var.machines
zone = var.zone
name = each.value.boot_disk.image_name
}
data "exoscale_compute" "master_nodes" {
for_each = exoscale_compute.master
id = each.value.id
# Since private IP address is not assigned until the nics are created we need this
depends_on = [exoscale_nic.master_private_network_nic]
}
data "exoscale_compute" "worker_nodes" {
for_each = exoscale_compute.worker
id = each.value.id
# Since private IP address is not assigned until the nics are created we need this
depends_on = [exoscale_nic.worker_private_network_nic]
}
resource "exoscale_network" "private_network" {
zone = var.zone
name = "${var.prefix}-network"
start_ip = cidrhost(var.private_network_cidr, 1)
# cidr -1 = Broadcast address
# cidr -2 = DHCP server address (exoscale specific)
end_ip = cidrhost(var.private_network_cidr, -3)
netmask = cidrnetmask(var.private_network_cidr)
}
resource "exoscale_compute" "master" {
for_each = {
for name, machine in var.machines :
name => machine
if machine.node_type == "master"
}
display_name = "${var.prefix}-${each.key}"
template_id = data.exoscale_compute_template.os_image[each.key].id
size = each.value.size
disk_size = each.value.boot_disk.root_partition_size + each.value.boot_disk.node_local_partition_size + each.value.boot_disk.ceph_partition_size
state = "Running"
zone = var.zone
security_groups = [exoscale_security_group.master_sg.name]
user_data = templatefile(
"${path.module}/templates/cloud-init.tmpl",
{
eip_ip_address = exoscale_ipaddress.ingress_controller_lb.ip_address
node_local_partition_size = each.value.boot_disk.node_local_partition_size
ceph_partition_size = each.value.boot_disk.ceph_partition_size
root_partition_size = each.value.boot_disk.root_partition_size
node_type = "master"
ssh_public_keys = var.ssh_public_keys
}
)
}
resource "exoscale_compute" "worker" {
for_each = {
for name, machine in var.machines :
name => machine
if machine.node_type == "worker"
}
display_name = "${var.prefix}-${each.key}"
template_id = data.exoscale_compute_template.os_image[each.key].id
size = each.value.size
disk_size = each.value.boot_disk.root_partition_size + each.value.boot_disk.node_local_partition_size + each.value.boot_disk.ceph_partition_size
state = "Running"
zone = var.zone
security_groups = [exoscale_security_group.worker_sg.name]
user_data = templatefile(
"${path.module}/templates/cloud-init.tmpl",
{
eip_ip_address = exoscale_ipaddress.ingress_controller_lb.ip_address
node_local_partition_size = each.value.boot_disk.node_local_partition_size
ceph_partition_size = each.value.boot_disk.ceph_partition_size
root_partition_size = each.value.boot_disk.root_partition_size
node_type = "worker"
ssh_public_keys = var.ssh_public_keys
}
)
}
resource "exoscale_nic" "master_private_network_nic" {
for_each = exoscale_compute.master
compute_id = each.value.id
network_id = exoscale_network.private_network.id
}
resource "exoscale_nic" "worker_private_network_nic" {
for_each = exoscale_compute.worker
compute_id = each.value.id
network_id = exoscale_network.private_network.id
}
resource "exoscale_security_group" "master_sg" {
name = "${var.prefix}-master-sg"
description = "Security group for Kubernetes masters"
}
resource "exoscale_security_group_rules" "master_sg_rules" {
security_group_id = exoscale_security_group.master_sg.id
# SSH
ingress {
protocol = "TCP"
cidr_list = var.ssh_whitelist
ports = ["22"]
}
# Kubernetes API
ingress {
protocol = "TCP"
cidr_list = var.api_server_whitelist
ports = ["6443"]
}
}
resource "exoscale_security_group" "worker_sg" {
name = "${var.prefix}-worker-sg"
description = "security group for kubernetes worker nodes"
}
resource "exoscale_security_group_rules" "worker_sg_rules" {
security_group_id = exoscale_security_group.worker_sg.id
# SSH
ingress {
protocol = "TCP"
cidr_list = var.ssh_whitelist
ports = ["22"]
}
# HTTP(S)
ingress {
protocol = "TCP"
cidr_list = ["0.0.0.0/0"]
ports = ["80", "443"]
}
# Kubernetes Nodeport
ingress {
protocol = "TCP"
cidr_list = var.nodeport_whitelist
ports = ["30000-32767"]
}
}
resource "exoscale_ipaddress" "ingress_controller_lb" {
zone = var.zone
healthcheck_mode = "http"
healthcheck_port = 80
healthcheck_path = "/healthz"
healthcheck_interval = 10
healthcheck_timeout = 2
healthcheck_strikes_ok = 2
healthcheck_strikes_fail = 3
}
resource "exoscale_secondary_ipaddress" "ingress_controller_lb" {
for_each = exoscale_compute.worker
compute_id = each.value.id
ip_address = exoscale_ipaddress.ingress_controller_lb.ip_address
}
resource "exoscale_ipaddress" "control_plane_lb" {
zone = var.zone
healthcheck_mode = "tcp"
healthcheck_port = 6443
healthcheck_interval = 10
healthcheck_timeout = 2
healthcheck_strikes_ok = 2
healthcheck_strikes_fail = 3
}
resource "exoscale_secondary_ipaddress" "control_plane_lb" {
for_each = exoscale_compute.master
compute_id = each.value.id
ip_address = exoscale_ipaddress.control_plane_lb.ip_address
}

View File

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

View File

@@ -0,0 +1,52 @@
#cloud-config
%{ if ceph_partition_size > 0 || node_local_partition_size > 0}
bootcmd:
- [ cloud-init-per, once, move-second-header, sgdisk, --move-second-header, /dev/vda ]
%{ if node_local_partition_size > 0 }
# Create partition for node local storage
- [ cloud-init-per, once, create-node-local-part, parted, --script, /dev/vda, 'mkpart extended ext4 ${root_partition_size}GB %{ if ceph_partition_size == 0 }-1%{ else }${root_partition_size + node_local_partition_size}GB%{ endif }' ]
- [ cloud-init-per, once, create-fs-node-local-part, mkfs.ext4, /dev/vda2 ]
%{ endif }
%{ if ceph_partition_size > 0 }
# Create partition for rook to use for ceph
- [ cloud-init-per, once, create-ceph-part, parted, --script, /dev/vda, 'mkpart extended ${root_partition_size + node_local_partition_size}GB -1' ]
%{ endif }
%{ endif }
ssh_authorized_keys:
%{ for ssh_public_key in ssh_public_keys ~}
- ${ssh_public_key}
%{ endfor ~}
write_files:
- path: /etc/netplan/eth1.yaml
content: |
network:
version: 2
ethernets:
eth1:
dhcp4: true
%{ if node_type == "worker" }
# TODO: When a VM is seen as healthy and is added to the EIP loadbalancer
# pool it no longer can send traffic back to itself via the EIP IP
# address.
# Remove this if it ever gets solved.
- path: /etc/netplan/20-eip-fix.yaml
content: |
network:
version: 2
ethernets:
"lo:0":
match:
name: lo
dhcp4: false
addresses:
- ${eip_ip_address}/32
%{ endif }
runcmd:
- netplan apply
%{ if node_local_partition_size > 0 }
- mkdir -p /mnt/disks/node-local-storage
- chown nobody:nogroup /mnt/disks/node-local-storage
- mount /dev/vda2 /mnt/disks/node-local-storage
%{ endif }

View File

@@ -0,0 +1,42 @@
variable "zone" {
type = string
# This is currently the only zone that is supposed to be supporting
# so called "managed private networks".
# See: https://www.exoscale.com/syslog/introducing-managed-private-networks
default = "ch-gva-2"
}
variable "prefix" {}
variable "machines" {
type = map(object({
node_type = string
size = string
boot_disk = object({
image_name = string
root_partition_size = number
ceph_partition_size = number
node_local_partition_size = number
})
}))
}
variable "ssh_public_keys" {
type = list(string)
}
variable "ssh_whitelist" {
type = list(string)
}
variable "api_server_whitelist" {
type = list(string)
}
variable "nodeport_whitelist" {
type = list(string)
}
variable "private_network_cidr" {
default = "172.0.10.0/24"
}

View File

@@ -0,0 +1,9 @@
terraform {
required_providers {
exoscale = {
source = "exoscale/exoscale"
version = ">= 0.21"
}
}
required_version = ">= 0.13"
}

View File

@@ -0,0 +1,15 @@
output "master_ips" {
value = module.kubernetes.master_ip_addresses
}
output "worker_ips" {
value = module.kubernetes.worker_ip_addresses
}
output "ingress_controller_lb_ip_address" {
value = module.kubernetes.ingress_controller_lb_ip_address
}
output "control_plane_lb_ip_address" {
value = module.kubernetes.control_plane_lb_ip_address
}

View File

@@ -0,0 +1,65 @@
prefix = "default"
zone = "ch-gva-2"
inventory_file = "inventory.ini"
ssh_public_keys = [
# Put your public SSH key here
"ssh-rsa I-did-not-read-the-docs",
"ssh-rsa I-did-not-read-the-docs 2",
]
machines = {
"master-0" : {
"node_type" : "master",
"size" : "Small",
"boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50,
"node_local_partition_size" : 0,
"ceph_partition_size" : 0
}
},
"worker-0" : {
"node_type" : "worker",
"size" : "Large",
"boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50,
"node_local_partition_size" : 0,
"ceph_partition_size" : 0
}
},
"worker-1" : {
"node_type" : "worker",
"size" : "Large",
"boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50,
"node_local_partition_size" : 0,
"ceph_partition_size" : 0
}
},
"worker-2" : {
"node_type" : "worker",
"size" : "Large",
"boot_disk" : {
"image_name" : "Linux Ubuntu 20.04 LTS 64-bit",
"root_partition_size" : 50,
"node_local_partition_size" : 0,
"ceph_partition_size" : 0
}
}
}
nodeport_whitelist = [
"0.0.0.0/0"
]
ssh_whitelist = [
"0.0.0.0/0"
]
api_server_whitelist = [
"0.0.0.0/0"
]

View File

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

View File

@@ -0,0 +1,19 @@
[all]
${connection_strings_master}
${connection_strings_worker}
[kube_control_plane]
${list_master}
[kube_control_plane:vars]
supplementary_addresses_in_ssl_keys = [ "${api_lb_ip_address}" ]
[etcd]
${list_master}
[kube_node]
${list_worker}
[k8s_cluster:children]
kube_control_plane
kube_node

View File

@@ -0,0 +1,46 @@
variable "zone" {
description = "The zone where to run the cluster"
}
variable "prefix" {
description = "Prefix for resource names"
default = "default"
}
variable "machines" {
description = "Cluster machines"
type = map(object({
node_type = string
size = string
boot_disk = object({
image_name = string
root_partition_size = number
ceph_partition_size = number
node_local_partition_size = number
})
}))
}
variable "ssh_public_keys" {
description = "List of public SSH keys which are injected into the VMs."
type = list(string)
}
variable "ssh_whitelist" {
description = "List of IP ranges (CIDR) to whitelist for ssh"
type = list(string)
}
variable "api_server_whitelist" {
description = "List of IP ranges (CIDR) to whitelist for kubernetes api server"
type = list(string)
}
variable "nodeport_whitelist" {
description = "List of IP ranges (CIDR) to whitelist for kubernetes nodeports"
type = list(string)
}
variable "inventory_file" {
description = "Where to store the generated inventory file"
}

View File

@@ -0,0 +1,15 @@
terraform {
required_providers {
exoscale = {
source = "exoscale/exoscale"
version = ">= 0.21"
}
null = {
source = "hashicorp/null"
}
template = {
source = "hashicorp/template"
}
}
required_version = ">= 0.13"
}

View File

@@ -50,13 +50,13 @@ for name in "${WORKER_NAMES[@]}"; do
done
echo ""
echo "[kube-master]"
echo "[kube_control_plane]"
for name in "${MASTER_NAMES[@]}"; do
echo "${name}"
done
echo ""
echo "[kube-master:vars]"
echo "[kube_control_plane:vars]"
echo "supplementary_addresses_in_ssl_keys = [ '${API_LB}' ]" # Add LB address to API server certificate
echo ""
echo "[etcd]"
@@ -65,12 +65,12 @@ for name in "${MASTER_NAMES[@]}"; do
done
echo ""
echo "[kube-node]"
echo "[kube_node]"
for name in "${WORKER_NAMES[@]}"; do
echo "${name}"
done
echo ""
echo "[k8s-cluster:children]"
echo "kube-master"
echo "kube-node"
echo "[k8s_cluster:children]"
echo "kube_control_plane"
echo "kube_node"

View File

@@ -263,12 +263,13 @@ For your cluster, edit `inventory/$CLUSTER/cluster.tfvars`.
|`number_of_bastions` | Number of bastion hosts to create. Scripts assume this is really just zero or one |
|`number_of_gfs_nodes_no_floating_ip` | Number of gluster servers to provision. |
| `gfs_volume_size_in_gb` | Size of the non-ephemeral volumes to be attached to store the GlusterFS bricks |
|`supplementary_master_groups` | To add ansible groups to the masters, such as `kube-node` for tainting them as nodes, empty by default. |
|`supplementary_node_groups` | To add ansible groups to the nodes, such as `kube-ingress` for running ingress controller pods, empty by default. |
|`supplementary_master_groups` | To add ansible groups to the masters, such as `kube_node` for tainting them as nodes, empty by default. |
|`supplementary_node_groups` | To add ansible groups to the nodes, such as `kube_ingress` for running ingress controller pods, empty by default. |
|`bastion_allowed_remote_ips` | List of CIDR allowed to initiate a SSH connection, `["0.0.0.0/0"]` by default |
|`master_allowed_remote_ips` | List of CIDR blocks allowed to initiate an API connection, `["0.0.0.0/0"]` by default |
|`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 |
|`master_allowed_ports` | List of ports to open on master nodes, expected format is `[{ "protocol" = "tcp", "port_range_min" = 443, "port_range_max" = 443, "remote_ip_prefix" = "0.0.0.0/0"}]`, empty by default |
|`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 |
@@ -281,7 +282,7 @@ For your cluster, edit `inventory/$CLUSTER/cluster.tfvars`.
##### k8s_nodes
Allows a custom defintion of worker nodes giving the operator full control over individual node flavor and
Allows a custom definition of worker nodes giving the operator full control over individual node flavor and
availability zone placement. To enable the use of this mode set the `number_of_k8s_nodes` and
`number_of_k8s_nodes_no_floating_ip` variables to 0. Then define your desired worker node configuration
using the `k8s_nodes` variable.
@@ -420,7 +421,7 @@ terraform apply -var-file=cluster.tfvars ../../contrib/terraform/openstack
```
if you chose to create a bastion host, this script will create
`contrib/terraform/openstack/k8s-cluster.yml` with an ssh command for Ansible to
`contrib/terraform/openstack/k8s_cluster.yml` with an ssh command for Ansible to
be able to access your machines tunneling through the bastion's IP address. If
you want to manually handle the ssh tunneling to these machines, please delete
or move that file. If you want to use this, just leave it there, as ansible will
@@ -545,7 +546,7 @@ bin_dir: /opt/bin
cloud_provider: openstack
```
Edit `inventory/$CLUSTER/group_vars/k8s-cluster/k8s-cluster.yml`:
Edit `inventory/$CLUSTER/group_vars/k8s_cluster/k8s_cluster.yml`:
- Set variable **kube_network_plugin** to your desired networking plugin.
- **flannel** works out-of-the-box

View File

@@ -52,7 +52,11 @@ module "compute" {
master_volume_type = var.master_volume_type
public_key_path = var.public_key_path
image = var.image
image_uuid = var.image_uuid
image_gfs = var.image_gfs
image_master = var.image_master
image_master_uuid = var.image_master_uuid
image_gfs_uuid = var.image_gfs_uuid
ssh_user = var.ssh_user
ssh_user_gfs = var.ssh_user_gfs
flavor_k8s_master = var.flavor_k8s_master

View File

@@ -1,11 +1,20 @@
data "openstack_images_image_v2" "vm_image" {
count = var.image_uuid == "" ? 1 : 0
most_recent = true
name = var.image
}
data "openstack_images_image_v2" "gfs_image" {
count = var.image_gfs_uuid == "" ? var.image_uuid == "" ? 1 : 0 : 0
most_recent = true
name = var.image_gfs == "" ? var.image : var.image_gfs
}
data "openstack_images_image_v2" "image_master" {
count = var.image_master_uuid == "" ? var.image_uuid == "" ? 1 : 0 : 0
name = var.image_master == "" ? var.image : var.image_master
}
resource "openstack_compute_keypair_v2" "k8s" {
name = "kubernetes-${var.cluster_name}"
public_key = chomp(file(var.public_key_path))
@@ -149,21 +158,28 @@ locals {
worker_sec_groups = compact([
openstack_networking_secgroup_v2.k8s.name,
openstack_networking_secgroup_v2.worker.name,
var.extra_sec_groups ? openstack_networking_secgroup_v2.k8s_master_extra[0].name : "",
var.extra_sec_groups ? openstack_networking_secgroup_v2.worker_extra[0].name : "",
])
# Image uuid
image_to_use_node = var.image_uuid != "" ? var.image_uuid : data.openstack_images_image_v2.vm_image[0].id
# Image_gfs uuid
image_to_use_gfs = var.image_gfs_uuid != "" ? var.image_gfs_uuid : var.image_uuid != "" ? var.image_uuid : data.openstack_images_image_v2.gfs_image[0].id
# image_master uuidimage_gfs_uuid
image_to_use_master = var.image_master_uuid != "" ? var.image_master_uuid : var.image_uuid != "" ? var.image_uuid : data.openstack_images_image_v2.image_master[0].id
}
resource "openstack_compute_instance_v2" "bastion" {
name = "${var.cluster_name}-bastion-${count.index + 1}"
count = var.number_of_bastions
image_name = var.image
image_id = var.bastion_root_volume_size_in_gb == 0 ? local.image_to_use_node : null
flavor_id = var.flavor_bastion
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.bastion_root_volume_size_in_gb > 0 ? [var.image] : []
for_each = var.bastion_root_volume_size_in_gb > 0 ? [local.image_to_use_node] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
uuid = local.image_to_use_node
source_type = "image"
volume_size = var.bastion_root_volume_size_in_gb
boot_index = 0
@@ -188,7 +204,7 @@ resource "openstack_compute_instance_v2" "bastion" {
}
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"
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"
}
}
@@ -196,15 +212,15 @@ resource "openstack_compute_instance_v2" "k8s_master" {
name = "${var.cluster_name}-k8s-master-${count.index + 1}"
count = var.number_of_k8s_masters
availability_zone = element(var.az_list, count.index)
image_name = var.image
image_id = var.master_root_volume_size_in_gb == 0 ? local.image_to_use_master : null
flavor_id = var.flavor_k8s_master
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.master_root_volume_size_in_gb > 0 ? [var.image] : []
for_each = var.master_root_volume_size_in_gb > 0 ? [local.image_to_use_master] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
uuid = local.image_to_use_master
source_type = "image"
volume_size = var.master_root_volume_size_in_gb
volume_type = var.master_volume_type
@@ -229,13 +245,13 @@ resource "openstack_compute_instance_v2" "k8s_master" {
metadata = {
ssh_user = var.ssh_user
kubespray_groups = "etcd,kube-master,${var.supplementary_master_groups},k8s-cluster,vault"
kubespray_groups = "etcd,kube_control_plane,${var.supplementary_master_groups},k8s_cluster"
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"
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"
}
}
@@ -243,15 +259,15 @@ 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
availability_zone = element(var.az_list, count.index)
image_name = var.image
image_id = var.master_root_volume_size_in_gb == 0 ? local.image_to_use_master : null
flavor_id = var.flavor_k8s_master
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.master_root_volume_size_in_gb > 0 ? [var.image] : []
for_each = var.master_root_volume_size_in_gb > 0 ? [local.image_to_use_master] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
uuid = local.image_to_use_master
source_type = "image"
volume_size = var.master_root_volume_size_in_gb
volume_type = var.master_volume_type
@@ -276,13 +292,13 @@ resource "openstack_compute_instance_v2" "k8s_master_no_etcd" {
metadata = {
ssh_user = var.ssh_user
kubespray_groups = "kube-master,${var.supplementary_master_groups},k8s-cluster,vault"
kubespray_groups = "kube_control_plane,${var.supplementary_master_groups},k8s_cluster"
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"
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"
}
}
@@ -290,14 +306,14 @@ resource "openstack_compute_instance_v2" "etcd" {
name = "${var.cluster_name}-etcd-${count.index + 1}"
count = var.number_of_etcd
availability_zone = element(var.az_list, count.index)
image_name = var.image
image_id = var.etcd_root_volume_size_in_gb == 0 ? local.image_to_use_master : null
flavor_id = var.flavor_etcd
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.etcd_root_volume_size_in_gb > 0 ? [var.image] : []
for_each = var.etcd_root_volume_size_in_gb > 0 ? [local.image_to_use_master] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
uuid = local.image_to_use_master
source_type = "image"
volume_size = var.etcd_root_volume_size_in_gb
boot_index = 0
@@ -321,7 +337,7 @@ resource "openstack_compute_instance_v2" "etcd" {
metadata = {
ssh_user = var.ssh_user
kubespray_groups = "etcd,vault,no-floating"
kubespray_groups = "etcd,no_floating"
depends_on = var.network_id
use_access_ip = var.use_access_ip
}
@@ -331,14 +347,14 @@ 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
availability_zone = element(var.az_list, count.index)
image_name = var.image
image_id = var.master_root_volume_size_in_gb == 0 ? local.image_to_use_master : null
flavor_id = var.flavor_k8s_master
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.master_root_volume_size_in_gb > 0 ? [var.image] : []
for_each = var.master_root_volume_size_in_gb > 0 ? [local.image_to_use_master] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
uuid = local.image_to_use_master
source_type = "image"
volume_size = var.master_root_volume_size_in_gb
volume_type = var.master_volume_type
@@ -363,7 +379,7 @@ resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip" {
metadata = {
ssh_user = var.ssh_user
kubespray_groups = "etcd,kube-master,${var.supplementary_master_groups},k8s-cluster,vault,no-floating"
kubespray_groups = "etcd,kube_control_plane,${var.supplementary_master_groups},k8s_cluster,no_floating"
depends_on = var.network_id
use_access_ip = var.use_access_ip
}
@@ -373,14 +389,14 @@ 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
availability_zone = element(var.az_list, count.index)
image_name = var.image
image_id = var.master_root_volume_size_in_gb == 0 ? local.image_to_use_master : null
flavor_id = var.flavor_k8s_master
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.master_root_volume_size_in_gb > 0 ? [var.image] : []
for_each = var.master_root_volume_size_in_gb > 0 ? [local.image_to_use_master] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
uuid = local.image_to_use_master
source_type = "image"
volume_size = var.master_root_volume_size_in_gb
volume_type = var.master_volume_type
@@ -405,7 +421,7 @@ resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip_no_etcd" {
metadata = {
ssh_user = var.ssh_user
kubespray_groups = "kube-master,${var.supplementary_master_groups},k8s-cluster,vault,no-floating"
kubespray_groups = "kube_control_plane,${var.supplementary_master_groups},k8s_cluster,no_floating"
depends_on = var.network_id
use_access_ip = var.use_access_ip
}
@@ -415,14 +431,14 @@ resource "openstack_compute_instance_v2" "k8s_node" {
name = "${var.cluster_name}-k8s-node-${count.index + 1}"
count = var.number_of_k8s_nodes
availability_zone = element(var.az_list_node, count.index)
image_name = var.image
image_id = var.node_root_volume_size_in_gb == 0 ? local.image_to_use_node : null
flavor_id = var.flavor_k8s_node
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.node_root_volume_size_in_gb > 0 ? [var.image] : []
for_each = var.node_root_volume_size_in_gb > 0 ? [local.image_to_use_node] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
uuid = local.image_to_use_node
source_type = "image"
volume_size = var.node_root_volume_size_in_gb
boot_index = 0
@@ -446,13 +462,13 @@ resource "openstack_compute_instance_v2" "k8s_node" {
metadata = {
ssh_user = var.ssh_user
kubespray_groups = "kube-node,k8s-cluster,${var.supplementary_node_groups}"
kubespray_groups = "kube_node,k8s_cluster,${var.supplementary_node_groups}"
depends_on = var.network_id
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"
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"
}
}
@@ -460,14 +476,14 @@ 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
availability_zone = element(var.az_list_node, count.index)
image_name = var.image
image_id = var.node_root_volume_size_in_gb == 0 ? local.image_to_use_node : null
flavor_id = var.flavor_k8s_node
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.node_root_volume_size_in_gb > 0 ? [var.image] : []
for_each = var.node_root_volume_size_in_gb > 0 ? [local.image_to_use_node] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
uuid = local.image_to_use_node
source_type = "image"
volume_size = var.node_root_volume_size_in_gb
boot_index = 0
@@ -491,7 +507,7 @@ resource "openstack_compute_instance_v2" "k8s_node_no_floating_ip" {
metadata = {
ssh_user = var.ssh_user
kubespray_groups = "kube-node,k8s-cluster,no-floating,${var.supplementary_node_groups}"
kubespray_groups = "kube_node,k8s_cluster,no_floating,${var.supplementary_node_groups}"
depends_on = var.network_id
use_access_ip = var.use_access_ip
}
@@ -501,14 +517,14 @@ resource "openstack_compute_instance_v2" "k8s_nodes" {
for_each = var.number_of_k8s_nodes == 0 && var.number_of_k8s_nodes_no_floating_ip == 0 ? var.k8s_nodes : {}
name = "${var.cluster_name}-k8s-node-${each.key}"
availability_zone = each.value.az
image_name = var.image
image_id = var.node_root_volume_size_in_gb == 0 ? local.image_to_use_node : null
flavor_id = each.value.flavor
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.node_root_volume_size_in_gb > 0 ? [var.image] : []
for_each = var.node_root_volume_size_in_gb > 0 ? [local.image_to_use_node] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
uuid = local.image_to_use_node
source_type = "image"
volume_size = var.node_root_volume_size_in_gb
boot_index = 0
@@ -532,13 +548,13 @@ resource "openstack_compute_instance_v2" "k8s_nodes" {
metadata = {
ssh_user = var.ssh_user
kubespray_groups = "kube-node,k8s-cluster,%{if each.value.floating_ip == false}no-floating,%{endif}${var.supplementary_node_groups}"
kubespray_groups = "kube_node,k8s_cluster,%{if each.value.floating_ip == false}no_floating,%{endif}${var.supplementary_node_groups}"
depends_on = var.network_id
use_access_ip = var.use_access_ip
}
provisioner "local-exec" {
command = "%{if each.value.floating_ip}sed s/USER/${var.ssh_user}/ ../../contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${element(concat(var.bastion_fips, [for key, value in var.k8s_nodes_fips : value.address]), 0)}/ > group_vars/no-floating.yml%{else}true%{endif}"
command = "%{if each.value.floating_ip}sed s/USER/${var.ssh_user}/ ../../contrib/terraform/openstack/ansible_bastion_template.txt | sed s/BASTION_ADDRESS/${element(concat(var.bastion_fips, [for key, value in var.k8s_nodes_fips : value.address]), 0)}/ > group_vars/no_floating.yml%{else}true%{endif}"
}
}
@@ -546,14 +562,14 @@ resource "openstack_compute_instance_v2" "glusterfs_node_no_floating_ip" {
name = "${var.cluster_name}-gfs-node-nf-${count.index + 1}"
count = var.number_of_gfs_nodes_no_floating_ip
availability_zone = element(var.az_list, count.index)
image_name = var.image_gfs
image_name = var.gfs_root_volume_size_in_gb == 0 ? local.image_to_use_gfs : null
flavor_id = var.flavor_gfs_node
key_pair = openstack_compute_keypair_v2.k8s.name
dynamic "block_device" {
for_each = var.gfs_root_volume_size_in_gb > 0 ? [var.image] : []
for_each = var.gfs_root_volume_size_in_gb > 0 ? [local.image_to_use_gfs] : []
content {
uuid = data.openstack_images_image_v2.vm_image.id
uuid = local.image_to_use_gfs
source_type = "image"
volume_size = var.gfs_root_volume_size_in_gb
boot_index = 0
@@ -577,7 +593,7 @@ resource "openstack_compute_instance_v2" "glusterfs_node_no_floating_ip" {
metadata = {
ssh_user = var.ssh_user_gfs
kubespray_groups = "gfs-cluster,network-storage,no-floating"
kubespray_groups = "gfs-cluster,network-storage,no_floating"
depends_on = var.network_id
use_access_ip = var.use_access_ip
}

View File

@@ -135,3 +135,19 @@ variable "extra_sec_groups" {
variable "extra_sec_groups_name" {
type = string
}
variable "image_uuid" {
type = string
}
variable "image_gfs_uuid" {
type = string
}
variable "image_master" {
type = string
}
variable "image_master_uuid" {
type = string
}

View File

@@ -177,12 +177,12 @@ variable "external_net" {
}
variable "supplementary_master_groups" {
description = "supplementary kubespray ansible groups for masters, such kube-node"
description = "supplementary kubespray ansible groups for masters, such kube_node"
default = ""
}
variable "supplementary_node_groups" {
description = "supplementary kubespray ansible groups for worker nodes, such as kube-ingress"
description = "supplementary kubespray ansible groups for worker nodes, such as kube_ingress"
default = ""
}
@@ -258,3 +258,23 @@ variable "extra_sec_groups" {
variable "extra_sec_groups_name" {
default = "custom"
}
variable "image_uuid" {
description = "uuid of image inside openstack to use"
default = ""
}
variable "image_gfs_uuid" {
description = "uuid of image to be used on gluster fs nodes. If empty defaults to image_uuid"
default = ""
}
variable "image_master" {
description = "uuid of image inside openstack to use"
default = ""
}
variable "image_master_uuid" {
description = "uuid of image to be used on master nodes. If empty defaults to image_uuid"
default = ""
}

View File

@@ -108,7 +108,7 @@ While the defaults in variables.tf will successfully deploy a cluster, it is rec
Kubespray will pull down a Kubernetes configuration file to access this cluster by enabling the
`kubeconfig_localhost: true` in the Kubespray configuration.
Edit `inventory/$CLUSTER/group_vars/k8s-cluster/k8s-cluster.yml` and comment back in the following line and change from `false` to `true`:
Edit `inventory/$CLUSTER/group_vars/k8s_cluster/k8s_cluster.yml` and comment back in the following line and change from `false` to `true`:
`\# kubeconfig_localhost: false`
becomes:
`kubeconfig_localhost: true`

View File

@@ -19,7 +19,7 @@ resource "packet_device" "k8s_master" {
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"]
tags = ["cluster-${var.cluster_name}", "k8s_cluster", "kube_control_plane", "etcd", "kube_node"]
}
resource "packet_device" "k8s_master_no_etcd" {
@@ -32,7 +32,7 @@ resource "packet_device" "k8s_master_no_etcd" {
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"]
tags = ["cluster-${var.cluster_name}", "k8s_cluster", "kube_control_plane"]
}
resource "packet_device" "k8s_etcd" {
@@ -58,6 +58,6 @@ resource "packet_device" "k8s_node" {
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"]
tags = ["cluster-${var.cluster_name}", "k8s_cluster", "kube_node"]
}

View File

@@ -323,7 +323,7 @@ def openstack_host(resource, module_name):
})
# add groups based on attrs
groups.append('os_image=' + attrs['image']['name'])
groups.append('os_image=' + attrs['image']['id'])
groups.append('os_flavor=' + attrs['flavor']['name'])
groups.extend('os_metadata_%s=%s' % item
for item in list(attrs['metadata'].items()))

View File

@@ -0,0 +1,106 @@
# Kubernetes on UpCloud with Terraform
Provision a Kubernetes cluster on [UpCloud](https://upcloud.com/) using Terraform and Kubespray
## Overview
The setup looks like following
```text
Kubernetes cluster
+-----------------------+
| +--------------+ |
| | +--------------+ |
| | | | |
| | | Master/etcd | |
| | | node(s) | |
| +-+ | |
| +--------------+ |
| ^ |
| | |
| v |
| +--------------+ |
| | +--------------+ |
| | | | |
| | | Worker | |
| | | node(s) | |
| +-+ | |
| +--------------+ |
+-----------------------+
```
## Requirements
* Terraform 0.13.0 or newer
## Quickstart
NOTE: Assumes you are at the root of the kubespray repo.
For authentication in your cluster you can use the environment variables.
```bash
export TF_VAR_UPCLOUD_USERNAME=username
export TF_VAR_UPCLOUD_PASSWORD=password
```
To allow API access to your UpCloud account, you need to allow API connections by visiting [Account-page](https://hub.upcloud.com/account) in your UpCloud Hub.
Copy the cluster configuration file.
```bash
CLUSTER=my-upcloud-cluster
cp -r inventory/sample inventory/$CLUSTER
cp contrib/terraform/upcloud/cluster-settings.tfvars inventory/$CLUSTER/
export ANSIBLE_CONFIG=ansible.cfg
cd inventory/$CLUSTER
```
Edit `cluster-settings.tfvars` to match your requirement.
Run Terraform to create the infrastructure.
```bash
terraform init ../../contrib/terraform/upcloud
terraform apply --var-file cluster-settings.tfvars \
-state=tfstate-$CLUSTER.tfstate \
../../contrib/terraform/upcloud/
```
You should now have a inventory file named `inventory.ini` that you can use with kubespray.
You can use the inventory file with kubespray to set up a cluster.
It is a good idea to check that you have basic SSH connectivity to the nodes. You can do that by:
```bash
ansible -i inventory.ini -m ping all
```
You can setup Kubernetes with kubespray using the generated inventory:
```bash
ansible-playbook -i inventory.ini ../../cluster.yml -b -v
```
## Teardown
You can teardown your infrastructure using the following Terraform command:
```bash
terraform destroy --var-file cluster-settings.tfvars \
-state=tfstate-$CLUSTER.tfstate \
../../contrib/terraform/upcloud/
```
## Variables
* `hostname`: A valid domain name, e.g. example.com. The maximum length is 128 characters.
* `template_name`: The name or UUID of a base image
* `username`: a user to access the nodes
* `ssh_public_keys`: List of public SSH keys to install on all machines
* `zone`: The zone where to run the cluster
* `machines`: Machines to provision. Key of this object will be used as the name of the machine
* `node_type`: The role of this node *(master|worker)*
* `cpu`: number of cpu cores
* `mem`: memory size in MB
* `disk_size`: The size of the storage in GB

View File

@@ -0,0 +1,58 @@
# See: https://developers.upcloud.com/1.3/5-zones/
zone = "fi-hel1"
username = "ubuntu"
inventory_file = "inventory.ini"
# A valid domain name, e.g. host.example.com. The maximum length is 128 characters.
hostname = "example.com"
# Set the operating system using UUID or exact name
template_name = "Ubuntu Server 20.04 LTS (Focal Fossa)"
ssh_public_keys = [
# Put your public SSH key here
"ssh-rsa public key 1",
"ssh-rsa public key 2",
]
#check list of available plan https://developers.upcloud.com/1.3/7-plans/
machines = {
"master-0" : {
"node_type" : "master",
#number of cpu cores
"cpu" : "2",
#memory size in MB
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
},
"worker-0" : {
"node_type" : "worker",
#number of cpu cores
"cpu" : "2",
#memory size in MB
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
},
"worker-1" : {
"node_type" : "worker",
#number of cpu cores
"cpu" : "2",
#memory size in MB
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
},
"worker-2" : {
"node_type" : "worker",
#number of cpu cores
"cpu" : "2",
#memory size in MB
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
}
}

View File

@@ -0,0 +1,55 @@
terraform {
required_version = ">= 0.13.0"
}
provider "upcloud" {
# Your UpCloud credentials are read from environment variables:
username = var.UPCLOUD_USERNAME
password = var.UPCLOUD_PASSWORD
}
module "kubernetes" {
source = "./modules/kubernetes-cluster"
zone = var.zone
hostname = var.hostname
template_name = var.template_name
username = var.username
machines = var.machines
ssh_public_keys = var.ssh_public_keys
}
#
# Generate ansible inventory
#
data "template_file" "inventory" {
template = file("${path.module}/templates/inventory.tpl")
vars = {
connection_strings_master = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s etcd_member_name=etcd%d",
keys(module.kubernetes.master_ip),
values(module.kubernetes.master_ip),
range(1, length(module.kubernetes.master_ip) + 1)))
connection_strings_worker = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s",
keys(module.kubernetes.worker_ip),
values(module.kubernetes.worker_ip)))
list_master = join("\n", formatlist("%s",
keys(module.kubernetes.master_ip)))
list_worker = join("\n", formatlist("%s",
keys(module.kubernetes.worker_ip)))
}
}
resource "null_resource" "inventories" {
provisioner "local-exec" {
command = "echo '${data.template_file.inventory.rendered}' > ${var.inventory_file}"
}
triggers = {
template = data.template_file.inventory.rendered
}
}

View File

@@ -0,0 +1,66 @@
resource "upcloud_server" "master" {
for_each = {
for name, machine in var.machines :
name => machine
if machine.node_type == "master"
}
hostname = "${each.key}.${var.hostname}"
cpu = each.value.cpu
mem = each.value.mem
zone = var.zone
template {
storage = var.template_name
size = each.value.disk_size
}
# Network interfaces
network_interface {
type = "public"
}
network_interface {
type = "utility"
}
# Include at least one public SSH key
login {
user = var.username
keys = var.ssh_public_keys
create_password = false
}
}
resource "upcloud_server" "worker" {
for_each = {
for name, machine in var.machines :
name => machine
if machine.node_type == "worker"
}
hostname = "${each.key}.${var.hostname}"
cpu = each.value.cpu
mem = each.value.mem
zone = var.zone
template {
storage = var.template_name
size = each.value.disk_size
}
# Network interfaces
network_interface {
type = "public"
}
# Include at least one public SSH key
login {
user = var.username
keys = var.ssh_public_keys
create_password = false
}
}

View File

@@ -0,0 +1,14 @@
output "master_ip" {
value = {
for instance in upcloud_server.master :
instance.hostname => instance.network_interface[0].ip_address
}
}
output "worker_ip" {
value = {
for instance in upcloud_server.worker :
instance.hostname => instance.network_interface[0].ip_address
}
}

View File

@@ -0,0 +1,25 @@
variable "zone" {
type = string
}
variable "hostname"{
default ="example.com"
}
variable "template_name"{}
variable "username"{}
variable "machines" {
description = "Cluster machines"
type = map(object({
node_type = string
cpu = string
mem = string
disk_size = number
}))
}
variable "ssh_public_keys" {
type = list(string)
}

View File

@@ -0,0 +1,10 @@
terraform {
required_providers {
upcloud = {
source = "UpCloudLtd/upcloud"
version = "~>2.0.0"
}
}
required_version = ">= 0.13"
}

View File

@@ -0,0 +1,8 @@
output "master_ip" {
value = module.kubernetes.master_ip
}
output "worker_ip" {
value = module.kubernetes.worker_ip
}

View File

@@ -0,0 +1,56 @@
# See: https://developers.upcloud.com/1.3/5-zones/
zone = "fi-hel1"
username = "ubuntu"
inventory_file = "inventory.ini"
# A valid domain name, e.g. host.example.com. The maximum length is 128 characters.
hostname = "example.com"
# Set the operating system using UUID or exact name
template_name = "Ubuntu Server 20.04 LTS (Focal Fossa)"
ssh_public_keys = [
# Put your public SSH key here
"ssh-rsa I-did-not-read-the-docs",
"ssh-rsa I-did-not-read-the-docs 2",
]
check list of available plan https://developers.upcloud.com/1.3/7-plans/
machines = {
"master-0" : {
"node_type" : "master",
#number of cpu cores
"cpu" : "2",
#memory size in MB
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
},
"worker-0" : {
"node_type" : "worker",
#number of cpu cores
"cpu" : "2",
#memory size in MB
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
},
"worker-1" : {
"node_type" : "worker",
#number of cpu cores
"cpu" : "2",
#memory size in MB
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
},
"worker-2" : {
"node_type" : "worker",
#number of cpu cores
"cpu" : "2",
#memory size in MB
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
}
}

View File

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

View File

@@ -0,0 +1,17 @@
[all]
${connection_strings_master}
${connection_strings_worker}
[kube_control_plane]
${list_master}
[etcd]
${list_master}
[kube_node]
${list_worker}
[k8s_cluster:children]
kube_control_plane
kube_node

View File

@@ -0,0 +1,35 @@
variable "zone" {
description = "The zone where to run the cluster"
}
variable "hostname" {
default = "example.com"
}
variable "template_name" {}
variable "username" {}
variable "machines" {
description = "Cluster machines"
type = map(object({
node_type = string
cpu = string
mem = string
disk_size = number
}))
}
variable "ssh_public_keys" {
description = "List of public SSH keys which are injected into the VMs."
type = list(string)
}
variable "inventory_file" {
description = "Where to store the generated inventory file"
}
variable "UPCLOUD_USERNAME" {}
variable "UPCLOUD_PASSWORD" {}

View File

@@ -0,0 +1,10 @@
terraform {
required_providers {
upcloud = {
source = "UpCloudLtd/upcloud"
version = "~>2.0.0"
}
}
required_version = ">= 0.13"
}

View File

@@ -0,0 +1,117 @@
# Kubernetes on Exoscale with Terraform
Provision a Kubernetes cluster on [vSphere](https://www.vmware.com/se/products/vsphere.html) using Terraform and Kubespray.
## Overview
The setup looks like following.
```text
Kubernetes cluster
+-----------------------+
| +--------------+ |
| | +--------------+ |
| | | | |
| | | Master/etcd | |
| | | node(s) | |
| +-+ | |
| +--------------+ |
| ^ |
| | |
| v |
| +--------------+ |
| | +--------------+ |
| | | | |
| | | Worker | |
| | | node(s) | |
| +-+ | |
| +--------------+ |
+-----------------------+
```
## Warning
This setup assumes that the DHCP is disabled in the vSphere cluster and IP addresses have to be provided in the configuration file.
## Requirements
* Terraform 0.13.0 or newer
*0.12 also works if you modify the provider block to include version and remove all `versions.tf` files*
## Quickstart
NOTE: *Assumes you are at the root of the kubespray repo*
Copy the sample inventory for your cluster and copy the default terraform variables.
```bash
CLUSTER=my-vsphere-cluster
cp -r inventory/sample inventory/$CLUSTER
cp contrib/terraform/vsphere/default.tfvars inventory/$CLUSTER/
cd inventory/$CLUSTER
```
Edit `default.tfvars` to match your setup. You MUST set values specific for you network and vSphere cluster.
```bash
# Ensure $EDITOR points to your favorite editor, e.g., vim, emacs, VS Code, etc.
$EDITOR default.tfvars
```
For authentication in your vSphere cluster you can use the environment variables.
```bash
export TF_VAR_vsphere_user=username
export TF_VAR_vsphere_password=password
```
Run Terraform to create the infrastructure.
```bash
terraform init ../../contrib/terraform/vsphere
terraform apply \
-var-file default.tfvars \
-state=tfstate-$CLUSTER.tfstate \
../../contrib/terraform/vsphere
```
You should now have a inventory file named `inventory.ini` that you can use with kubespray.
You can now copy your inventory file and use it with kubespray to set up a cluster.
You can type `terraform output` to find out the IP addresses of the nodes.
It is a good idea to check that you have basic SSH connectivity to the nodes. You can do that by:
```bash
ansible -i inventory.ini -m ping all
```
Example to use this with the default sample inventory:
```bash
ansible-playbook -i inventory.ini ../../cluster.yml -b -v
```
## Variables
### Required
* `machines`: Machines to provision. Key of this object will be used as the name of the machine
* `node_type`: The role of this node *(master|worker)*
* `ip`: The IP address with the netmask (CIDR notation)
* `gateway`: The IP address of the network gateway
* `ssh_public_keys`: List of public SSH keys to install on all machines
* `vsphere_datacenter`: The identifier of vSphere data center
* `vsphere_compute_cluster`: The identifier of vSphere compute cluster
* `vsphere_datastore`: The identifier of vSphere data store
* `vsphere_server`: The address of vSphere server
* `vsphere_hostname`: The IP address of vSphere hostname
* `template_name`: The name of a base image (the image has to be uploaded to vSphere beforehand)
### Optional
* `prefix`: Prefix to use for all resources, required to be unique for all clusters in the same project *(Defaults to `default`)*
* `dns_primary`: The IP address of primary DNS server *(Defaults to `8.8.4.4`)*
* `dns_secondary`:The IP address of secondary DNS server *(Defaults to `8.8.8.8`)*
An example variables file can be found `default.tfvars`

View File

@@ -0,0 +1,34 @@
prefix = "default"
inventory_file = "inventory.ini"
machines = {
"master-0" : {
"node_type" : "master",
"ip" : "i-did-not-read-the-docs" # e.g. 192.168.0.2/24
},
"worker-0" : {
"node_type" : "worker",
"ip" : "i-did-not-read-the-docs" # e.g. 192.168.0.2/24
},
"worker-1" : {
"node_type" : "worker",
"ip" : "i-did-not-read-the-docs" # e.g. 192.168.0.2/24
}
}
gateway = "i-did-not-read-the-docs" # e.g. 192.168.0.2
ssh_public_keys = [
# Put your public SSH key here
"ssh-rsa I-did-not-read-the-docs",
"ssh-rsa I-did-not-read-the-docs 2",
]
vsphere_datacenter = "i-did-not-read-the-docs"
vsphere_compute_cluster = "i-did-not-read-the-docs" # e.g. Cluster
vsphere_datastore = "i-did-not-read-the-docs" # e.g. ssd-000000
vsphere_server = "i-did-not-read-the-docs" # e.g. vsphere.server.com
vsphere_hostname = "i-did-not-read-the-docs" # e.g. 192.168.0.2
template_name = "i-did-not-read-the-docs" # e.g. ubuntu-bionic-18.04-cloudimg

View File

@@ -0,0 +1,116 @@
provider "vsphere" {
# Username and password set through env vars VSPHERE_USER and VSPHERE_PASSWORD
user = var.vsphere_user
password = var.vsphere_password
vsphere_server = var.vsphere_server
# If you have a self-signed cert
allow_unverified_ssl = true
}
data "vsphere_datacenter" "dc" {
name = var.vsphere_datacenter
}
data "vsphere_datastore" "datastore" {
name = var.vsphere_datastore
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_network" "network" {
name = "VM Network"
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_host" "host" {
name = var.vsphere_hostname
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_virtual_machine" "template" {
name = var.template_name
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_compute_cluster" "compute_cluster" {
name = var.vsphere_compute_cluster
datacenter_id = data.vsphere_datacenter.dc.id
}
resource "vsphere_resource_pool" "pool" {
name = "${var.prefix}-cluster-pool"
parent_resource_pool_id = data.vsphere_host.host.resource_pool_id
}
module "kubernetes" {
source = "./modules/kubernetes-cluster"
prefix = var.prefix
machines = var.machines
## Master ##
master_cores = var.master_cores
master_memory = var.master_memory
master_disk_size = var.master_disk_size
## Worker ##
worker_cores = var.worker_cores
worker_memory = var.worker_memory
worker_disk_size = var.worker_disk_size
## Global ##
gateway = var.gateway
dns_primary = var.dns_primary
dns_secondary = var.dns_secondary
pool_id = vsphere_resource_pool.pool.id
datastore_id = data.vsphere_datastore.datastore.id
folder = ""
guest_id = data.vsphere_virtual_machine.template.guest_id
scsi_type = data.vsphere_virtual_machine.template.scsi_type
network_id = data.vsphere_network.network.id
adapter_type = data.vsphere_virtual_machine.template.network_interface_types[0]
firmware = var.firmware
hardware_version = var.hardware_version
disk_thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
template_id = data.vsphere_virtual_machine.template.id
ssh_public_keys = var.ssh_public_keys
}
#
# Generate ansible inventory
#
data "template_file" "inventory" {
template = file("${path.module}/templates/inventory.tpl")
vars = {
connection_strings_master = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s etcd_member_name=etcd%d",
keys(module.kubernetes.master_ip),
values(module.kubernetes.master_ip),
range(1, length(module.kubernetes.master_ip) + 1)))
connection_strings_worker = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s",
keys(module.kubernetes.worker_ip),
values(module.kubernetes.worker_ip)))
list_master = join("\n", formatlist("%s",
keys(module.kubernetes.master_ip)))
list_worker = join("\n", formatlist("%s",
keys(module.kubernetes.worker_ip)))
}
}
resource "null_resource" "inventories" {
provisioner "local-exec" {
command = "echo '${data.template_file.inventory.rendered}' > ${var.inventory_file}"
}
triggers = {
template = data.template_file.inventory.rendered
}
}

View File

@@ -0,0 +1,109 @@
resource "vsphere_virtual_machine" "worker" {
for_each = {
for name, machine in var.machines :
name => machine
if machine.node_type == "worker"
}
name = each.key
resource_pool_id = var.pool_id
datastore_id = var.datastore_id
num_cpus = var.worker_cores
memory = var.worker_memory
memory_reservation = var.worker_memory
guest_id = var.guest_id
enable_disk_uuid = "true"
scsi_type = var.scsi_type
folder = var.folder
firmware = var.firmware
hardware_version = var.hardware_version
wait_for_guest_net_routable = false
network_interface {
network_id = var.network_id
adapter_type = var.adapter_type
}
disk {
label = "disk0"
size = var.worker_disk_size
thin_provisioned = var.disk_thin_provisioned
}
lifecycle {
ignore_changes = [disk]
}
clone {
template_uuid = var.template_id
}
cdrom {
client_device = true
}
vapp {
properties = {
"user-data" = base64encode(templatefile("${path.module}/templates/cloud-init.tmpl", { ip = each.value.ip,
gw = var.gateway,
dns = var.dns_primary,
ssh_public_keys = var.ssh_public_keys}))
}
}
}
resource "vsphere_virtual_machine" "master" {
for_each = {
for name, machine in var.machines :
name => machine
if machine.node_type == "master"
}
name = each.key
resource_pool_id = var.pool_id
datastore_id = var.datastore_id
num_cpus = var.master_cores
memory = var.master_memory
memory_reservation = var.master_memory
guest_id = var.guest_id
enable_disk_uuid = "true"
scsi_type = var.scsi_type
folder = var.folder
firmware = var.firmware
hardware_version = var.hardware_version
network_interface {
network_id = var.network_id
adapter_type = var.adapter_type
}
disk {
label = "disk0"
size = var.master_disk_size
thin_provisioned = var.disk_thin_provisioned
}
lifecycle {
ignore_changes = [disk]
}
clone {
template_uuid = var.template_id
}
cdrom {
client_device = true
}
vapp {
properties = {
"user-data" = base64encode(templatefile("${path.module}/templates/cloud-init.tmpl", { ip = each.value.ip,
gw = var.gateway,
dns = var.dns_primary,
ssh_public_keys = var.ssh_public_keys}))
}
}
}

View File

@@ -0,0 +1,13 @@
output "master_ip" {
value = {
for instance in vsphere_virtual_machine.master :
instance.name => instance.default_ip_address
}
}
output "worker_ip" {
value = {
for instance in vsphere_virtual_machine.worker :
instance.name => instance.default_ip_address
}
}

View File

@@ -0,0 +1,35 @@
#cloud-config
ssh_authorized_keys:
%{ for ssh_public_key in ssh_public_keys ~}
- ${ssh_public_key}
%{ endfor ~}
write_files:
- path: /etc/netplan/20-internal-network.yaml
content: |
network:
version: 2
ethernets:
"lo:0":
match:
name: lo
dhcp4: false
addresses:
- 172.17.0.100/32
- path: /etc/netplan/10-user-network.yaml
content: |
network:
version: 2
ethernets:
ens192:
dhcp4: false #true to use dhcp
addresses:
- ${ip}
gateway4: ${gw} # Set gw here
nameservers:
addresses:
- ${dns} # Set DNS ip address here
runcmd:
- netplan apply

View File

@@ -0,0 +1,38 @@
## Global ##
variable "prefix" {}
variable "machines" {
description = "Cluster machines"
type = map(object({
node_type = string
ip = string
}))
}
variable "gateway" {}
variable "dns_primary" {}
variable "dns_secondary" {}
variable "pool_id" {}
variable "datastore_id" {}
variable "guest_id" {}
variable "scsi_type" {}
variable "network_id" {}
variable "adapter_type" {}
variable "disk_thin_provisioned" {}
variable "template_id" {}
variable "firmware" {}
variable "folder" {}
variable "ssh_public_keys" {
type = list(string)
}
variable "hardware_version" {}
## Master ##
variable "master_cores" {}
variable "master_memory" {}
variable "master_disk_size" {}
## Worker ##
variable "worker_cores" {}
variable "worker_memory" {}
variable "worker_disk_size" {}

View File

@@ -0,0 +1,9 @@
terraform {
required_providers {
vsphere = {
source = "hashicorp/vsphere"
version = ">= 1.24.3"
}
}
required_version = ">= 0.13"
}

View File

@@ -0,0 +1,31 @@
output "master_ip_addresses" {
value = module.kubernetes.master_ip
}
output "worker_ip_addresses" {
value = module.kubernetes.worker_ip
}
output "vsphere_datacenter" {
value = var.vsphere_datacenter
}
output "vsphere_server" {
value = var.vsphere_server
}
output "vsphere_datastore" {
value = var.vsphere_datastore
}
output "vsphere_network" {
value = var.network
}
output "vsphere_folder" {
value = terraform.workspace
}
output "vsphere_pool" {
value = "${terraform.workspace}-cluster-pool"
}

View File

@@ -0,0 +1,34 @@
prefix = "default"
inventory_file = "inventory.ini"
machines = {
"master-0" : {
"node_type" : "master",
"ip" : "i-did-not-read-the-docs" # e.g. 192.168.0.2/24
},
"worker-0" : {
"node_type" : "worker",
"ip" : "i-did-not-read-the-docs" # e.g. 192.168.0.2/24
},
"worker-1" : {
"node_type" : "worker",
"ip" : "i-did-not-read-the-docs" # e.g. 192.168.0.2/24
}
}
gateway = "i-did-not-read-the-docs" # e.g. 192.168.0.2
ssh_public_keys = [
# Put your public SSH key here
"ssh-rsa I-did-not-read-the-docs",
"ssh-rsa I-did-not-read-the-docs 2",
]
vsphere_datacenter = "i-did-not-read-the-docs"
vsphere_compute_cluster = "i-did-not-read-the-docs" # e.g. Cluster
vsphere_datastore = "i-did-not-read-the-docs" # e.g. ssd-000000
vsphere_server = "i-did-not-read-the-docs" # e.g. vsphere.server.com
vsphere_hostname = "i-did-not-read-the-docs" # e.g. 192.168.0.2
template_name = "i-did-not-read-the-docs" # e.g. ubuntu-bionic-18.04-cloudimg

View File

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

View File

@@ -0,0 +1,17 @@
[all]
${connection_strings_master}
${connection_strings_worker}
[kube_control_plane]
${list_master}
[etcd]
${list_master}
[kube_node]
${list_worker}
[k8s_cluster:children]
kube_control_plane
kube_node

View File

@@ -0,0 +1,89 @@
## Global ##
variable "prefix" {
default = ""
}
variable "machines" {
description = "Cluster machines"
type = map(object({
node_type = string
ip = string
}))
}
variable "inventory_file" {
default = "inventory.ini"
}
variable "network" {
default = "VM Network"
}
variable "gateway" {}
variable "dns_primary" {
default = "8.8.4.4"
}
variable "dns_secondary" {
default = "8.8.8.8"
}
variable "vsphere_datacenter" {}
variable "vsphere_compute_cluster" {}
variable "vsphere_datastore" {}
variable "vsphere_user" {}
variable "vsphere_password" {}
variable "vsphere_server" {}
variable "vsphere_hostname" {}
variable "firmware" {
default = "bios"
}
variable "hardware_version" {
default = "15"
}
variable "template_name" {
default = "ubuntu-focal-20.04-cloudimg"
}
variable "ssh_public_keys" {
description = "List of public SSH keys which are injected into the VMs."
type = list(string)
}
## Master ##
variable "master_cores" {
default = 4
}
variable "master_memory" {
default = 4096
}
variable "master_disk_size" {
default = "20"
}
## Worker ##
variable "worker_cores" {
default = 16
}
variable "worker_memory" {
default = 8192
}
variable "worker_disk_size" {
default = "100"
}

View File

@@ -0,0 +1,15 @@
terraform {
required_providers {
vsphere = {
source = "hashicorp/vsphere"
version = ">= 1.24.3"
}
null = {
source = "hashicorp/null"
}
template = {
source = "hashicorp/template"
}
}
required_version = ">= 0.13"
}

View File

@@ -1,32 +0,0 @@
---
vault_deployment_type: docker
vault_binary_checksum: 3c4d70ba71619a43229e65c67830e30e050eab7a81ac6b28325ff707e5914188
vault_version: 0.10.1
vault_download_url: "https://releases.hashicorp.com/vault/{{ vault_version }}/vault_{{ vault_version }}_linux_{{ image_arch }}.zip"
vault_image_repo: "vault"
vault_image_tag: "{{ vault_version }}"
vault_downloads:
vault:
enabled: "{{ cert_management == 'vault' }}"
container: "{{ vault_deployment_type != 'host' }}"
file: "{{ vault_deployment_type == 'host' }}"
dest: "{{local_release_dir}}/vault/vault_{{ vault_version }}_linux_{{ image_arch }}.zip"
mode: "0755"
owner: "vault"
repo: "{{ vault_image_repo }}"
sha256: "{{ vault_binary_checksum if vault_deployment_type == 'host' else vault_digest_checksum|d(none) }}"
tag: "{{ vault_image_tag }}"
unarchive: true
url: "{{ vault_download_url }}"
version: "{{ vault_version }}"
groups:
- vault
# Vault data dirs.
vault_base_dir: /etc/vault
vault_cert_dir: "{{ vault_base_dir }}/ssl"
vault_config_dir: "{{ vault_base_dir }}/config"
vault_roles_dir: "{{ vault_base_dir }}/roles"
vault_secrets_dir: "{{ vault_base_dir }}/secrets"
kube_vault_mount_path: "/kube"
etcd_vault_mount_path: "/etcd"

View File

@@ -1 +0,0 @@
ansible-modules-hashivault>=3.9.4

View File

@@ -1,73 +0,0 @@
---
- include_tasks: sync_etcd_master_certs.yml
when: inventory_hostname in groups.etcd
tags:
- etcd-secrets
- include_tasks: sync_etcd_node_certs.yml
when: inventory_hostname in etcd_node_cert_hosts
tags:
- etcd-secrets
# Issue master certs to Etcd nodes
- include_tasks: ../../vault/tasks/shared/issue_cert.yml
vars:
issue_cert_common_name: "etcd:master:{{ item.rsplit('/', 1)[1].rsplit('.', 1)[0] }}"
issue_cert_alt_names: "{{ groups['etcd'] + ['localhost'] + (etcd_cert_alt_names)|default() }}"
issue_cert_copy_ca: "{{ item == etcd_master_certs_needed|first }}"
issue_cert_file_group: "{{ etcd_cert_group }}"
issue_cert_file_owner: kube
issue_cert_hosts: "{{ groups.etcd }}"
issue_cert_ip_sans: >-
[
{%- for host in groups.etcd -%}
"{{ hostvars[host]['ansible_default_ipv4']['address'] }}",
{%- if hostvars[host]['ip'] is defined -%}
"{{ hostvars[host]['ip'] }}",
{%- endif -%}
{%- endfor -%}
{%- for cert_alt_ip in etcd_cert_alt_ips -%}
"{{ cert_alt_ip }}",
{%- endfor -%}
"127.0.0.1","::1"
]
issue_cert_path: "{{ item }}"
issue_cert_role: etcd
issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
issue_cert_mount_path: "{{ etcd_vault_mount_path }}"
with_items: "{{ etcd_master_certs_needed|d([]) }}"
when: inventory_hostname in groups.etcd
notify: set etcd_secret_changed
# Issue node certs to everyone else
- include_tasks: ../../vault/tasks/shared/issue_cert.yml
vars:
issue_cert_common_name: "etcd:node:{{ item.rsplit('/', 1)[1].rsplit('.', 1)[0] }}"
issue_cert_alt_names: "{{ etcd_node_cert_hosts }}"
issue_cert_copy_ca: "{{ item == etcd_node_certs_needed|first }}"
issue_cert_file_group: "{{ etcd_cert_group }}"
issue_cert_file_owner: kube
issue_cert_hosts: "{{ etcd_node_cert_hosts }}"
issue_cert_ip_sans: >-
[
{%- for host in etcd_node_cert_hosts -%}
"{{ hostvars[host]['ansible_default_ipv4']['address'] }}",
{%- if hostvars[host]['ip'] is defined -%}
"{{ hostvars[host]['ip'] }}",
{%- endif -%}
{%- endfor -%}
"127.0.0.1","::1"
]
issue_cert_path: "{{ item }}"
issue_cert_role: etcd
issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
issue_cert_mount_path: "{{ etcd_vault_mount_path }}"
with_items: "{{ etcd_node_certs_needed|d([]) }}"
when: inventory_hostname in etcd_node_cert_hosts
notify: set etcd_secret_changed
- name: gen_certs_vault | ensure file permissions
shell: >-
find {{etcd_cert_dir }} -type d -exec chmod 0755 {} \; &&
find {{etcd_cert_dir }} -type f -exec chmod 0640 {} \;
changed_when: false

View File

@@ -1,39 +0,0 @@
---
- name: sync_etcd_master_certs | Create list of master certs needing creation
set_fact:
etcd_master_cert_list: >-
{{ etcd_master_cert_list|default([]) + [
"admin-" + inventory_hostname + ".pem",
"member-" + inventory_hostname + ".pem"
] }}
- include_tasks: ../../vault/tasks/shared/sync_file.yml
vars:
sync_file: "{{ item }}"
sync_file_dir: "{{ etcd_cert_dir }}"
sync_file_hosts: [ "{{ inventory_hostname }}" ]
sync_file_owner: kube
sync_file_group: root
sync_file_is_cert: true
with_items: "{{ etcd_master_cert_list|d([]) }}"
- name: sync_etcd_certs | Set facts for etcd sync_file results
set_fact:
etcd_master_certs_needed: "{{ etcd_master_certs_needed|default([]) + [item.path] }}"
with_items: "{{ sync_file_results|d([]) }}"
when: item.no_srcs|bool
- name: sync_etcd_certs | Unset sync_file_results after etcd certs sync
set_fact:
sync_file_results: []
- include_tasks: ../../vault/tasks/shared/sync_file.yml
vars:
sync_file: ca.pem
sync_file_dir: "{{ etcd_cert_dir }}"
sync_file_hosts: [ "{{ inventory_hostname }}" ]
- name: sync_etcd_certs | Unset sync_file_results after ca.pem sync
set_fact:
sync_file_results: []

View File

@@ -1,33 +0,0 @@
---
- name: sync_etcd_node_certs | Create list of node certs needing creation
set_fact:
etcd_node_cert_list: "{{ etcd_node_cert_list|default([]) + ['node-' + inventory_hostname + '.pem'] }}"
- include_tasks: ../../vault/tasks/shared/sync_file.yml
vars:
sync_file: "{{ item }}"
sync_file_dir: "{{ etcd_cert_dir }}"
sync_file_hosts: [ "{{ inventory_hostname }}" ]
sync_file_is_cert: true
with_items: "{{ etcd_node_cert_list|d([]) }}"
- name: sync_etcd_node_certs | Set facts for etcd sync_file results
set_fact:
etcd_node_certs_needed: "{{ etcd_node_certs_needed|default([]) + [item.path] }}"
with_items: "{{ sync_file_results|d([]) }}"
when: item.no_srcs|bool
- name: sync_etcd_node_certs | Unset sync_file_results after etcd node certs
set_fact:
sync_file_results: []
- include_tasks: ../../vault/tasks/shared/sync_file.yml
vars:
sync_file: ca.pem
sync_file_dir: "{{ etcd_cert_dir }}"
sync_file_hosts: "{{ groups['etcd'] }}"
- name: sync_etcd_node_certs | Unset sync_file_results after ca.pem
set_fact:
sync_file_results: []

View File

@@ -1,134 +0,0 @@
---
- import_tasks: sync_kube_master_certs.yml
when: inventory_hostname in groups['kube-master']
- import_tasks: sync_kube_node_certs.yml
when: inventory_hostname in groups['k8s-cluster']
# Issue admin certs to kube-master hosts
- include_tasks: ../../../vault/tasks/shared/issue_cert.yml
vars:
issue_cert_common_name: "admin"
issue_cert_copy_ca: "{{ item == kube_admin_certs_needed|first }}"
issue_cert_file_group: "{{ kube_cert_group }}"
issue_cert_file_owner: kube
issue_cert_hosts: "{{ groups['kube-master'] }}"
issue_cert_path: "{{ item }}"
issue_cert_role: kube-master
issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
issue_cert_mount_path: "{{ kube_vault_mount_path }}"
with_items: "{{ kube_admin_certs_needed|d([]) }}"
when: inventory_hostname in groups['kube-master']
- name: gen_certs_vault | Set fact about certificate alt names
set_fact:
kube_cert_alt_names: >-
{{
groups['kube-master'] +
['kubernetes.default.svc.'+cluster_name, 'kubernetes.default.svc', 'kubernetes.default', 'kubernetes'] +
['localhost']
}}
run_once: true
- name: gen_certs_vault | Add external load balancer domain name to certificate alt names
set_fact:
kube_cert_alt_names: "{{ kube_cert_alt_names + [apiserver_loadbalancer_domain_name] }}"
when: loadbalancer_apiserver is defined
run_once: true
# Issue master components certs to kube-master hosts
- include_tasks: ../../../vault/tasks/shared/issue_cert.yml
vars:
issue_cert_common_name: "kubernetes"
issue_cert_alt_names: "{{ kube_cert_alt_names }}"
issue_cert_file_group: "{{ kube_cert_group }}"
issue_cert_file_owner: kube
issue_cert_hosts: "{{ groups['kube-master'] }}"
issue_cert_run_once: true
issue_cert_ip_sans: >-
[
{%- for host in groups['kube-master'] -%}
"{{ hostvars[host]['ansible_default_ipv4']['address'] }}",
{%- if hostvars[host]['ip'] is defined -%}
"{{ hostvars[host]['ip'] }}",
{%- endif -%}
{%- endfor -%}
{%- if supplementary_addresses_in_ssl_keys is defined -%}
{%- for ip_item in supplementary_addresses_in_ssl_keys -%}
"{{ ip_item }}",
{%- endfor -%}
{%- endif -%}
"127.0.0.1","::1","{{ kube_apiserver_ip }}"
]
issue_cert_path: "{{ item }}"
issue_cert_role: kube-master
issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
issue_cert_mount_path: "{{ kube_vault_mount_path }}"
with_items: "{{ kube_master_components_certs_needed|d([]) }}"
when: inventory_hostname in groups['kube-master']
notify: set secret_changed
# Issue node certs to k8s-cluster nodes
- include_tasks: ../../../vault/tasks/shared/issue_cert.yml
vars:
# Need to strip out the 'node-' prefix from the cert name so it can be used
# with the node authorization plugin ( CN matches kubelet node name )
issue_cert_common_name: "system:node:{{ item.rsplit('/', 1)[1].rsplit('.', 1)[0] | regex_replace('^node-', '') }}"
issue_cert_copy_ca: "{{ item == kube_node_certs_needed|first }}"
issue_cert_file_group: "{{ kube_cert_group }}"
issue_cert_file_owner: kube
issue_cert_hosts: "{{ groups['k8s-cluster'] }}"
issue_cert_path: "{{ item }}"
issue_cert_role: kube-node
issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
issue_cert_mount_path: "{{ kube_vault_mount_path }}"
with_items: "{{ kube_node_certs_needed|d([]) }}"
when: inventory_hostname in groups['k8s-cluster']
# Issue proxy certs to k8s-cluster nodes
- include_tasks: ../../../vault/tasks/shared/issue_cert.yml
vars:
issue_cert_common_name: "system:kube-proxy"
issue_cert_copy_ca: "{{ item == kube_proxy_certs_needed|first }}"
issue_cert_file_group: "{{ kube_cert_group }}"
issue_cert_file_owner: kube
issue_cert_hosts: "{{ groups['k8s-cluster'] }}"
issue_cert_path: "{{ item }}"
issue_cert_role: kube-proxy
issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
issue_cert_mount_path: "{{ kube_vault_mount_path }}"
with_items: "{{ kube_proxy_certs_needed|d([]) }}"
when: inventory_hostname in groups['k8s-cluster']
# Issue front proxy cert to kube-master hosts
- include_tasks: ../../../vault/tasks/shared/issue_cert.yml
vars:
issue_cert_common_name: "front-proxy-client"
issue_cert_copy_ca: "{{ item == kube_front_proxy_clients_certs_needed|first }}"
issue_cert_ca_filename: front-proxy-ca.pem
issue_cert_alt_names: "{{ kube_cert_alt_names }}"
issue_cert_file_group: "{{ kube_cert_group }}"
issue_cert_file_owner: kube
issue_cert_hosts: "{{ groups['kube-master'] }}"
issue_cert_ip_sans: >-
[
{%- for host in groups['kube-master'] -%}
"{{ hostvars[host]['ansible_default_ipv4']['address'] }}",
{%- if hostvars[host]['ip'] is defined -%}
"{{ hostvars[host]['ip'] }}",
{%- endif -%}
{%- endfor -%}
{%- if supplementary_addresses_in_ssl_keys is defined -%}
{%- for ip_item in supplementary_addresses_in_ssl_keys -%}
"{{ ip_item }}",
{%- endfor -%}
{%- endif -%}
"127.0.0.1","::1","{{ kube_apiserver_ip }}"
]
issue_cert_path: "{{ item }}"
issue_cert_role: front-proxy-client
issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
issue_cert_mount_path: "{{ kube_vault_mount_path }}"
with_items: "{{ kube_front_proxy_clients_certs_needed|d([]) }}"
when: inventory_hostname in groups['kube-master']
notify: set secret_changed

View File

@@ -1,89 +0,0 @@
---
- name: sync_kube_master_certs | Create list of needed kube admin certs
set_fact:
kube_admin_cert_list: "{{ kube_admin_cert_list|d([]) + ['admin-' + inventory_hostname + '.pem'] }}"
- include_tasks: ../../../vault/tasks/shared/sync_file.yml
vars:
sync_file: "{{ item }}"
sync_file_dir: "{{ kube_cert_dir }}"
sync_file_group: "{{ kube_cert_group }}"
sync_file_hosts: [ "{{ inventory_hostname }}" ]
sync_file_is_cert: true
sync_file_owner: kube
with_items: "{{ kube_admin_cert_list|d([]) }}"
- name: sync_kube_master_certs | Set facts for kube admin sync_file results
set_fact:
kube_admin_certs_needed: "{{ kube_admin_certs_needed|default([]) + [item.path] }}"
with_items: "{{ sync_file_results|d([]) }}"
when: item.no_srcs|bool
- name: sync_kube_master_certs | Unset sync_file_results after kube admin certs
set_fact:
sync_file_results: []
- include_tasks: ../../../vault/tasks/shared/sync_file.yml
vars:
sync_file: "{{ item }}"
sync_file_dir: "{{ kube_cert_dir }}"
sync_file_group: "{{ kube_cert_group }}"
sync_file_hosts: "{{ groups['kube-master'] }}"
sync_file_is_cert: true
sync_file_owner: kube
with_items: ["apiserver.pem", "kube-scheduler.pem", "kube-controller-manager.pem", "service-account.pem"]
- name: sync_kube_master_certs | Set facts for kube master components sync_file results
set_fact:
kube_master_components_certs_needed: "{{ kube_master_components_certs_needed|d([]) + [item.path] }}"
with_items: "{{ sync_file_results|d([]) }}"
when: item.no_srcs|bool
- name: sync_kube_master_certs | Unset sync_file_results after kube master components cert
set_fact:
sync_file_results: []
- include_tasks: ../../../vault/tasks/shared/sync_file.yml
vars:
sync_file: front-proxy-ca.pem
sync_file_dir: "{{ kube_cert_dir }}"
sync_file_group: "{{ kube_cert_group }}"
sync_file_hosts: "{{ groups['kube-master'] }}"
sync_file_owner: kube
- name: sync_kube_master_certs | Unset sync_file_results after front-proxy-ca.pem
set_fact:
sync_file_results: []
- include_tasks: ../../../vault/tasks/shared/sync_file.yml
vars:
sync_file: "{{ item }}"
sync_file_dir: "{{ kube_cert_dir }}"
sync_file_group: "{{ kube_cert_group }}"
sync_file_hosts: "{{ groups['kube-master'] }}"
sync_file_is_cert: true
sync_file_owner: kube
with_items: ["front-proxy-client.pem"]
- name: sync_kube_master_certs | Set facts for front-proxy-client certs sync_file results
set_fact:
kube_front_proxy_clients_certs_needed: "{{ kube_front_proxy_clients_certs_needed|d([]) + [item.path] }}"
with_items: "{{ sync_file_results|d([]) }}"
when: item.no_srcs|bool
- name: sync_kube_master_certs | Unset sync_file_results after front-proxy-client sync
set_fact:
sync_file_results: []
- include_tasks: ../../../vault/tasks/shared/sync_file.yml
vars:
sync_file: ca.pem
sync_file_dir: "{{ kube_cert_dir }}"
sync_file_group: "{{ kube_cert_group }}"
sync_file_hosts: "{{ groups['kube-master'] }}"
sync_file_owner: kube
- name: sync_kube_master_certs | Unset sync_file_results after ca.pem
set_fact:
sync_file_results: []

View File

@@ -1,60 +0,0 @@
---
- name: sync_kube_node_certs | Create list of needed certs
set_fact:
kube_node_cert_list: "{{ kube_node_cert_list|default([]) + ['node-' + inventory_hostname + '.pem'] }}"
- include_tasks: ../../../vault/tasks/shared/sync_file.yml
vars:
sync_file: "{{ item }}"
sync_file_dir: "{{ kube_cert_dir }}"
sync_file_group: "{{ kube_cert_group }}"
sync_file_hosts: [ "{{ inventory_hostname }}" ]
sync_file_is_cert: true
sync_file_owner: kube
with_items: "{{ kube_node_cert_list|default([]) }}"
- name: sync_kube_node_certs | Set facts for kube-master sync_file results
set_fact:
kube_node_certs_needed: "{{ kube_node_certs_needed|default([]) + [item.path] }}"
with_items: "{{ sync_file_results|d([]) }}"
when: item.no_srcs|bool
- name: sync_kube_node_certs | Unset sync_file_results after kube node certs
set_fact:
sync_file_results: []
- include_tasks: ../../../vault/tasks/shared/sync_file.yml
vars:
sync_file: ca.pem
sync_file_dir: "{{ kube_cert_dir }}"
sync_file_group: "{{ kube_cert_group }}"
sync_file_hosts: "{{ groups['k8s-cluster'] }}"
sync_file_owner: kube
- name: sync_kube_node_certs | Unset sync_file_results after ca.pem
set_fact:
sync_file_results: []
- name: sync_kube_node_certs | Create list of needed kube-proxy certs
set_fact:
kube_proxy_cert_list: "{{ kube_proxy_cert_list|default([]) + ['kube-proxy-' + inventory_hostname + '.pem'] }}"
- include_tasks: ../../../vault/tasks/shared/sync_file.yml
vars:
sync_file: "{{ item }}"
sync_file_dir: "{{ kube_cert_dir }}"
sync_file_group: "{{ kube_cert_group }}"
sync_file_hosts: [ "{{ inventory_hostname }}" ]
sync_file_owner: kube
with_items: "{{ kube_proxy_cert_list|default([]) }}"
- name: sync_kube_node_certs | Set facts for kube-proxy sync_file results
set_fact:
kube_proxy_certs_needed: "{{ kube_proxy_certs_needed|default([]) + [item.path] }}"
with_items: "{{ sync_file_results|d([]) }}"
when: item.no_srcs|bool
- name: sync_kube_node_certs | Unset sync_file_results after kube proxy certs
set_fact:
sync_file_results: []

View File

@@ -1,200 +0,0 @@
---
vault_bootstrap: false
vault_deployment_type: docker
vault_adduser_vars:
comment: "Hashicorp Vault User"
createhome: no
name: vault
shell: /sbin/nologin
system: yes
# This variables redefined in kubespray-defaults for using shared tasks
# in etcd and kubernetes/secrets roles
vault_base_dir: /etc/vault
vault_cert_dir: "{{ vault_base_dir }}/ssl"
vault_config_dir: "{{ vault_base_dir }}/config"
vault_roles_dir: "{{ vault_base_dir }}/roles"
vault_secrets_dir: "{{ vault_base_dir }}/secrets"
vault_lib_dir: "/var/lib/vault"
vault_log_dir: "/var/log/vault"
vault_version: 0.10.1
vault_binary_checksum: 66f0f1b0b221d664dd5913f8697409d7401df4bb2a19c7277e8fbad152063fae
vault_download_url: "https://releases.hashicorp.com/vault/{{ vault_version }}/vault_{{ vault_version }}_linux_{{ image_arch }}.zip"
# hvac==0.7.0 is broken at the moment
hvac_version: 0.6.4
# Arch of Docker images and needed packages
image_arch: "{{host_architecture}}"
vault_download_vars:
container: "{{ vault_deployment_type != 'host' }}"
dest: "vault/vault_{{ vault_version }}_linux_{{ image_arch }}.zip"
enabled: true
mode: "0755"
owner: "vault"
repo: "{{ vault_image_repo }}"
sha256: "{{ vault_binary_checksum if vault_deployment_type == 'host' else vault_digest_checksum|d(none) }}"
source_url: "{{ vault_download_url }}"
tag: "{{ vault_image_tag }}"
unarchive: true
url: "{{ vault_download_url }}"
version: "{{ vault_version }}"
vault_container_name: kube-hashicorp-vault
vault_temp_container_name: vault-temp
vault_image_repo: "vault"
vault_image_tag: "{{ vault_version }}"
vault_bind_address: 0.0.0.0
vault_port: 8200
vault_etcd_url: "{{ etcd_access_addresses }}"
# By default lease
vault_default_lease_ttl: 70080h
vault_max_lease_ttl: 87600h
vault_temp_config:
backend:
file:
path: /vault/file
default_lease_ttl: "{{ vault_default_lease_ttl }}"
listener:
tcp:
address: "{{ vault_bind_address }}:{{ vault_port }}"
tls_disable: "true"
max_lease_ttl: "{{ vault_max_lease_ttl }}"
vault_config:
backend:
etcd:
address: "{{ vault_etcd_url }}"
ha_enabled: "true"
redirect_addr: "https://{{ inventory_hostname }}:{{ vault_port }}"
tls_ca_file: "{{ etcd_cert_dir }}/ca.pem"
tls_cert_file: "{{ etcd_cert_dir}}/node-{{ inventory_hostname }}.pem"
tls_key_file: "{{ etcd_cert_dir}}/node-{{ inventory_hostname }}-key.pem"
cluster_name: "kubernetes-vault"
default_lease_ttl: "{{ vault_default_lease_ttl }}"
max_lease_ttl: "{{ vault_max_lease_ttl }}"
ui: "true"
listener:
tcp:
address: "{{ vault_bind_address }}:{{ vault_port }}"
tls_cert_file: "{{ vault_cert_dir }}/api.pem"
tls_key_file: "{{ vault_cert_dir }}/api-key.pem"
vault_secret_shares: 1
vault_secret_threshold: 1
vault_successful_http_codes: ["200", "429", "500", "501", "503"]
vault_ca_options:
vault:
common_name: vault
format: pem
ttl: "{{ vault_max_lease_ttl }}"
exclude_cn_from_sans: true
alt_names: "vault.kube-system.svc.{{ dns_domain }},vault.kube-system.svc,vault.kube-system,vault"
etcd:
common_name: etcd
format: pem
ttl: "{{ vault_max_lease_ttl }}"
exclude_cn_from_sans: true
kube:
common_name: kube
format: pem
ttl: "{{ vault_max_lease_ttl }}"
exclude_cn_from_sans: true
vault_client_headers:
Accept: "application/json"
Content-Type: "application/json"
etcd_cert_dir: /etc/ssl/etcd/ssl
kube_cert_dir: /etc/kubernetes/ssl
vault_pki_mounts:
userpass:
name: userpass
default_lease_ttl: "{{ vault_default_lease_ttl }}"
max_lease_ttl: "{{ vault_max_lease_ttl }}"
description: "Userpass"
cert_dir: "{{ vault_cert_dir }}"
roles:
- name: userpass
group: userpass
password: "{{ lookup('password', credentials_dir + '/vault/userpass.creds length=15') }}"
policy_rules: default
role_options:
allow_any_name: true
vault:
name: vault
default_lease_ttl: "{{ vault_default_lease_ttl }}"
max_lease_ttl: "{{ vault_max_lease_ttl }}"
description: "Vault Root CA"
cert_dir: "{{ vault_cert_dir }}"
roles:
- name: vault
group: vault
password: "{{ lookup('password', credentials_dir + '/vault/vault.creds length=15') }}"
policy_rules: default
role_options:
allow_any_name: true
etcd:
name: etcd
default_lease_ttl: "{{ vault_default_lease_ttl }}"
max_lease_ttl: "{{ vault_max_lease_ttl }}"
description: "Etcd Root CA"
cert_dir: "{{ etcd_cert_dir }}"
roles:
- name: etcd
group: etcd
password: "{{ lookup('password', credentials_dir + '/vault/etcd.creds length=15') }}"
policy_rules: default
role_options:
allow_any_name: true
enforce_hostnames: false
organization: "kube:etcd"
kube:
name: kube
default_lease_ttl: "{{ vault_default_lease_ttl }}"
max_lease_ttl: "{{ vault_max_lease_ttl }}"
description: "Kubernetes Root CA"
cert_dir: "{{ kube_cert_dir }}"
roles:
- name: kube-master
group: kube-master
password: "{{ lookup('password', credentials_dir + '/vault/kube-master.creds length=15') }}"
policy_rules: default
role_options:
allow_any_name: true
enforce_hostnames: false
organization: "system:masters"
- name: front-proxy-client
group: kube-master
password: "{{ lookup('password', credentials_dir + '/vault/kube-proxy.creds length=15') }}"
policy_rules: default
role_options:
allow_any_name: true
enforce_hostnames: false
organization: "system:front-proxy-client"
- name: kube-node
group: k8s-cluster
password: "{{ lookup('password', credentials_dir + '/vault/kube-node.creds length=15') }}"
policy_rules: default
role_options:
allow_any_name: true
enforce_hostnames: false
organization: "system:nodes"
- name: kube-proxy
group: k8s-cluster
password: "{{ lookup('password', credentials_dir + '/vault/kube-proxy.creds length=15') }}"
policy_rules: default
role_options:
allow_any_name: true
enforce_hostnames: false
organization: "system:node-proxier"

View File

@@ -1,50 +0,0 @@
---
- name: restart vault
command: /bin/true
notify:
- restart vault service
- wait for vault up
- unseal vault
- name: wait for vault up
uri:
url: "{{ vault_leader_url | default('https://localhost:8200') }}/v1/sys/health"
headers: "{{ vault_client_headers }}"
status_code: "{{ vault_successful_http_codes | join(',') }}"
register: vault_health_check
until: vault_health_check is succeeded
retries: 10
delay: "{{ retry_stagger | random + 3 }}"
run_once: yes
notify: set facts about local Vault health
- name: wait for vault up nowait
uri:
url: "{{ vault_leader_url | default('https://localhost:8200') }}/v1/sys/health"
headers: "{{ vault_client_headers }}"
status_code: "{{ vault_successful_http_codes | join(',') }}"
register: vault_health_check
run_once: yes
failed_when: false
notify: set facts about local Vault health
- name: set facts about local Vault health
set_fact:
vault_is_running: "{{ vault_health_check.get('status', '-1') in vault_successful_http_codes }}"
vault_cluster_is_initialized: "{{ vault_health_check.get('json', {}).get('initialized', false) }}"
vault_is_sealed: "{{ vault_health_check.get('json', {}).get('sealed', true) }}"
- name: restart vault service
systemd:
daemon_reload: true
enabled: yes
name: vault
state: restarted
- name: unseal vault
hashivault_unseal:
url: "{{ vault_leader_url | default('https://localhost:8200') }}"
token: "{{ vault_root_token }}"
ca_cert: "{{ vault_cert_dir }}/ca.pem"
keys: "{{ item }}"
with_items: "{{ vault_unseal_keys|default([]) }}"

View File

@@ -1,4 +0,0 @@
---
dependencies:
- role: adduser
user: "{{ vault_adduser_vars }}"

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