Ansible playbook bootstrapping secure highly available kubernetes. Script is generally based on https://github.com/kelseyhightower/kubernetes-the-hard-way, but adopted for bare-metal installation. After successfull run you get:
- highly available standalone etcd cluster
- highly available k8s control-plane cluster
- tls-security of all communications (peer etcd, kube-apiserver to etcd)
- flannel networking
- coredns
- ingress (kubernetes nginx)
- kubernetes-dashboard
Bootstrap kubernetes
cd k8s-install
ansible-playbook --become run-role.yml -e role_name=k8s -e host_pattern=k8s-1,k8s-2,k8s-3
. target/admin-activate.sh
kubectl get svc
# go to https://$ANY_NODE_IP_OR_HOST/kubernetes-dashboard/ to access kubernetes-dashboard
-
Configure your inventory.
Ensure file
~/.ansible.cfghas content like the following.[defaults] inventory = /home/user/.ansible-hosts.iniCreate file
~/.ansible-hosts.iniwith content like the following.[k8s] k8s-1 internal_ip_address=192.168.56.101 k8s-2 internal_ip_address=192.168.56.102 k8s-3 internal_ip_address=192.168.56.103If any host have multiple ip addresses (due to multiple network adapters), use
internal_ip_addressvariable to specify which one is for communication between hosts inside cluster. -
Install etcd
ansible-playbook --become run-role.yml -e role_name=etcd -e host_pattern=k8s-1,k8s-2,k8s-3Check etcd works
ssh user@one-of-etcd-nodes sudo etcdctlwrap member list -
Install kubernetes controllers, given etcd and workers hosts are known
ansible-playbook --become run-role.yml -e role_name=k8s-controllers -e host_pattern=k8s-1,k8s-2,k8s-3 -e etcd_hosts=k8s-1,k8s-2,k8s-3 -e k8s_worker_hosts=k8s-1,k8s-2,k8s-3 -
Install kubernetes workers, given controller hosts are known
ansible-playbook --become run-role.yml -e role_name=k8s-workers -e host_pattern=k8s-1,k8s-2,k8s-3 -e k8s_controller_hosts=k8s-1,k8s-2,k8s-3 -
Configure cluster
ansible-playbook run-role.yml -e role_name=k8s-configure -e host_pattern=k8s-1,k8s-2,k8s-3
-
Configure etcd cluster hosts in
~/.ansible-hosts.ini.[test_etcd_v1] k8s-1 internal_ip_address=192.168.56.101 etcd_node_name=etcd-a k8s-2 internal_ip_address=192.168.56.102 etcd_node_name=etcd-b k8s-3 internal_ip_address=192.168.56.103 etcd_node_name=etcd-c -
Install etcd on initial cluster.
ansible-playbook --become run-role.yml -e role_name=etcd -e host_pattern=test_etcd_v1 -
Put key to etcd cluster.
$ ssh user@192.168.56.102 $ sudo etcdctlwrap put test-key 'test value, hello from k8s-2'Check value is replicated among other hosts.
$ ssh user@192.168.56.101 $ sudo etcdctlwrap get test-key test-key test value, hello from k8s-2 -
Suppose, node
etcd-bhas failed. Shut down host192.168.56.102. -
Check value is survived, since replicated among two other nodes.
$ ssh user@192.168.56.101 $ sudo etcdctlwrap get test-key test-key test value, hello from k8s-2 -
Configure new set of hosts. Let failed second host be replaced with new one.
[test_etcd_v2] k8s-1 internal_ip_address=192.168.56.101 etcd_node_name=etcd-a k8s-4 internal_ip_address=192.168.56.104 etcd_node_name=etcd-b k8s-3 internal_ip_address=192.168.56.103 etcd_node_name=etcd-c -
Reinstall new version of cluster with
initial_cluster_state=existingoptionansible-playbook --become run-role.yml -e role_name=etcd -e host_pattern=test_etcd_v2 -e initial_cluster_state=existing -
Manually replace failed node in cluster with new one.
$ ssh user@192.168.56.101 $ sudo etcdctlwrap member list 5b464a2f75a38e65, started, etcd-c, https://k8s-3:2380, https://k8s-3:2379, false 69e952a5a6a6e798, started, etcd-a, https://k8s-1:2380, https://k8s-1:2379, false aee4be324f12ea53, started, etcd-b, https://k8s-2:2380, https://k8s-2:2379, false $ sudo etcdctlwrap member remove aee4be324f12ea53 $ sudo etcdctlwrap member add etcd-b --peer-urls=https://k8s-4:2380 $ sudo etcdctlwrap member list 14967b194abf439, started, etcd-b, https://k8s-4:2380, https://k8s-4:2379, false 5b464a2f75a38e65, started, etcd-c, https://k8s-3:2380, https://k8s-3:2379, false 69e952a5a6a6e798, started, etcd-a, https://k8s-1:2380, https://k8s-1:2379, false -
Check value is survived after all that.
$ ssh user@192.168.56.104 $ sudo etcdctlwrap get test-key test-key test value, hello from k8s-2
Ansible 2.5.1 not supported by this playbook. There is a bug which prevents priviledge escalation when using include_role. Also argv parameter not supported by command module. Ansible 2.7 and higher seems to work. On ubuntu upgrade ansible with the following commands
sudo apt update
sudo apt install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install ansible