You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
11 KiB

  1. # Kubernetes on Openstack with Terraform
  2. Provision a Kubernetes cluster with [Terraform](https://www.terraform.io) on
  3. Openstack.
  4. ## Status
  5. This will install a Kubernetes cluster on an Openstack Cloud. It has been tested on a
  6. OpenStack Cloud provided by [BlueBox](https://www.blueboxcloud.com/) and on OpenStack at [EMBL-EBI's](http://www.ebi.ac.uk/) [EMBASSY Cloud](http://www.embassycloud.org/). This should work on most modern installs of OpenStack that support the basic
  7. services.
  8. There are some assumptions made to try and ensure it will work on your openstack cluster.
  9. * floating-ips are used for access, but you can have masters and nodes that don't use floating-ips if needed. You need currently at least 1 floating ip, which needs to be used on a master. If using more than one, at least one should be on a master for bastions to work fine.
  10. * you already have a suitable OS image in glance
  11. * you already have both an internal network and a floating-ip pool created
  12. * you have security-groups enabled
  13. ## Requirements
  14. - [Install Terraform](https://www.terraform.io/intro/getting-started/install.html)
  15. ## Terraform
  16. Terraform will be used to provision all of the OpenStack resources. It is also used to deploy and provision the software
  17. requirements.
  18. ### Prep
  19. #### OpenStack
  20. Ensure your OpenStack **Identity v2** credentials are loaded in environment variables. This can be done by downloading a credentials .rc file from your OpenStack dashboard and sourcing it:
  21. ```
  22. $ source ~/.stackrc
  23. ```
  24. > You must set **OS_REGION_NAME** and **OS_TENANT_ID** environment variables not required by openstack CLI
  25. You will need two networks before installing, an internal network and
  26. an external (floating IP Pool) network. The internet network can be shared as
  27. we use security groups to provide network segregation. Due to the many
  28. differences between OpenStack installs the Terraform does not attempt to create
  29. these for you.
  30. By default Terraform will expect that your networks are called `internal` and
  31. `external`. You can change this by altering the Terraform variables `network_name` and `floatingip_pool`. This can be done on a new variables file or through environment variables.
  32. A full list of variables you can change can be found at [variables.tf](variables.tf).
  33. All OpenStack resources will use the Terraform variable `cluster_name` (
  34. default `example`) in their name to make it easier to track. For example the
  35. first compute resource will be named `example-kubernetes-1`.
  36. #### Terraform
  37. Ensure your local ssh-agent is running and your ssh key has been added. This
  38. step is required by the terraform provisioner:
  39. ```
  40. $ eval $(ssh-agent -s)
  41. $ ssh-add ~/.ssh/id_rsa
  42. ```
  43. Ensure that you have your Openstack credentials loaded into Terraform
  44. environment variables. Likely via a command similar to:
  45. ```
  46. $ echo Setting up Terraform creds && \
  47. export TF_VAR_username=${OS_USERNAME} && \
  48. export TF_VAR_password=${OS_PASSWORD} && \
  49. export TF_VAR_tenant=${OS_TENANT_NAME} && \
  50. export TF_VAR_auth_url=${OS_AUTH_URL}
  51. ```
  52. ##### Alternative: etcd inside masters
  53. If you want to provision master or node VMs that don't use floating ips and where etcd is inside masters, write on a `my-terraform-vars.tfvars` file, for example:
  54. ```
  55. number_of_k8s_masters = "1"
  56. number_of_k8s_masters_no_floating_ip = "2"
  57. number_of_k8s_nodes_no_floating_ip = "1"
  58. number_of_k8s_nodes = "0"
  59. ```
  60. This will provision one VM as master using a floating ip, two additional masters using no floating ips (these will only have private ips inside your tenancy) and one VM as node, again without a floating ip.
  61. ##### Alternative: etcd on separate machines
  62. If you want to provision master or node VMs that don't use floating ips and where **etcd is on separate nodes from Kubernetes masters**, write on a `my-terraform-vars.tfvars` file, for example:
  63. ```
  64. number_of_etcd = "3"
  65. number_of_k8s_masters = "0"
  66. number_of_k8s_masters_no_etcd = "1"
  67. number_of_k8s_masters_no_floating_ip = "0"
  68. number_of_k8s_masters_no_floating_ip_no_etcd = "2"
  69. number_of_k8s_nodes_no_floating_ip = "1"
  70. number_of_k8s_nodes = "2"
  71. flavor_k8s_node = "desired-flavor-id"
  72. flavor_k8s_master = "desired-flavor-id"
  73. flavor_etcd = "desired-flavor-id"
  74. ```
  75. This will provision one VM as master using a floating ip, two additional masters using no floating ips (these will only have private ips inside your tenancy), two VMs as nodes with floating ips, one VM as node without floating ip and three VMs for etcd.
  76. ##### Alternative: add GlusterFS
  77. Additionally, now the terraform based installation supports provisioning of a GlusterFS shared file system based on a separate set of VMs, running either a Debian or RedHat based set of VMs. To enable this, you need to add to your `my-terraform-vars.tfvars` the following variables:
  78. ```
  79. # Flavour depends on your openstack installation, you can get available flavours through `nova flavor-list`
  80. flavor_gfs_node = "af659280-5b8a-42b5-8865-a703775911da"
  81. # This is the name of an image already available in your openstack installation.
  82. image_gfs = "Ubuntu 15.10"
  83. number_of_gfs_nodes_no_floating_ip = "3"
  84. # This is the size of the non-ephemeral volumes to be attached to store the GlusterFS bricks.
  85. gfs_volume_size_in_gb = "50"
  86. # The user needed for the image choosen for GlusterFS.
  87. ssh_user_gfs = "ubuntu"
  88. ```
  89. If these variables are provided, this will give rise to a new ansible group called `gfs-cluster`, for which we have added ansible roles to execute in the ansible provisioning step. If you are using Container Linux by CoreOS, these GlusterFS VM necessarily need to be either Debian or RedHat based VMs, Container Linux by CoreOS cannot serve GlusterFS, but can connect to it through binaries available on hyperkube v1.4.3_coreos.0 or higher.
  90. GlusterFS is not deployed by the standard `cluster.yml` playbook, see the [glusterfs playbook documentation](../../network-storage/glusterfs/README.md) for instructions.
  91. # Configure Cluster variables
  92. Edit `inventory/group_vars/all.yml`:
  93. - Set variable **bootstrap_os** according selected image
  94. ```
  95. # Valid bootstrap options (required): ubuntu, coreos, centos, none
  96. bootstrap_os: coreos
  97. ```
  98. - **bin_dir**
  99. ```
  100. # Directory where the binaries will be installed
  101. # Default:
  102. # bin_dir: /usr/local/bin
  103. # For Container Linux by CoreOS:
  104. bin_dir: /opt/bin
  105. ```
  106. - and **cloud_provider**
  107. ```
  108. cloud_provider: openstack
  109. ```
  110. Edit `inventory/group_vars/k8s-cluster.yml`:
  111. - Set variable **kube_network_plugin** according selected networking
  112. ```
  113. # Choose network plugin (calico, weave or flannel)
  114. # Can also be set to 'cloud', which lets the cloud provider setup appropriate routing
  115. kube_network_plugin: flannel
  116. ```
  117. > flannel works out-of-the-box
  118. > calico requires allowing service's and pod's subnets on according OpenStack Neutron ports
  119. - Set variable **resolvconf_mode**
  120. ```
  121. # Can be docker_dns, host_resolvconf or none
  122. # Default:
  123. # resolvconf_mode: docker_dns
  124. # For Container Linux by CoreOS:
  125. resolvconf_mode: host_resolvconf
  126. ```
  127. For calico configure OpenStack Neutron ports: [OpenStack](/docs/openstack.md)
  128. # Provision a Kubernetes Cluster on OpenStack
  129. If not using a tfvars file for your setup, then execute:
  130. ```
  131. terraform apply -state=contrib/terraform/openstack/terraform.tfstate contrib/terraform/openstack
  132. openstack_compute_secgroup_v2.k8s_master: Creating...
  133. description: "" => "example - Kubernetes Master"
  134. name: "" => "example-k8s-master"
  135. rule.#: "" => "<computed>"
  136. ...
  137. ...
  138. Apply complete! Resources: 9 added, 0 changed, 0 destroyed.
  139. The state of your infrastructure has been saved to the path
  140. below. This state is required to modify and destroy your
  141. infrastructure, so keep it safe. To inspect the complete state
  142. use the `terraform show` command.
  143. State path: contrib/terraform/openstack/terraform.tfstate
  144. ```
  145. Alternatively, if you wrote your terraform variables on a file `my-terraform-vars.tfvars`, your command would look like:
  146. ```
  147. terraform apply -state=contrib/terraform/openstack/terraform.tfstate -var-file=my-terraform-vars.tfvars contrib/terraform/openstack
  148. ```
  149. if you choose to add masters or nodes without floating ips (only internal ips on your OpenStack tenancy), this script will create as well a file `contrib/terraform/openstack/k8s-cluster.yml` with an ssh command for ansible to be able to access your machines tunneling through the first floating ip used. If you want to manually handling 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 pick it up automatically.
  150. Make sure you can connect to the hosts:
  151. ```
  152. $ ansible -i contrib/terraform/openstack/hosts -m ping all
  153. example-k8s_node-1 | SUCCESS => {
  154. "changed": false,
  155. "ping": "pong"
  156. }
  157. example-etcd-1 | SUCCESS => {
  158. "changed": false,
  159. "ping": "pong"
  160. }
  161. example-k8s-master-1 | SUCCESS => {
  162. "changed": false,
  163. "ping": "pong"
  164. }
  165. ```
  166. if you are deploying a system that needs bootstrapping, like Container Linux by CoreOS, these might have a state `FAILED` due to Container Linux by CoreOS not having python. As long as the state is not `UNREACHABLE`, this is fine.
  167. if it fails try to connect manually via SSH ... it could be somthing as simple as a stale host key.
  168. Deploy kubernetes:
  169. ```
  170. $ ansible-playbook --become -i contrib/terraform/openstack/hosts cluster.yml
  171. ```
  172. # Set up local kubectl
  173. 1. Install kubectl on your workstation:
  174. [Install and Set Up kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
  175. 2. Add route to internal IP of master node (if needed):
  176. ```
  177. sudo route add [master-internal-ip] gw [router-ip]
  178. ```
  179. or
  180. ```
  181. sudo route add -net [internal-subnet]/24 gw [router-ip]
  182. ```
  183. 3. List Kubernetes certs&keys:
  184. ```
  185. ssh [os-user]@[master-ip] sudo ls /etc/kubernetes/ssl/
  186. ```
  187. 4. Get admin's certs&key:
  188. ```
  189. ssh [os-user]@[master-ip] sudo cat /etc/kubernetes/ssl/admin-[cluster_name]-k8s-master-1-key.pem > admin-key.pem
  190. ssh [os-user]@[master-ip] sudo cat /etc/kubernetes/ssl/admin-[cluster_name]-k8s-master-1.pem > admin.pem
  191. ssh [os-user]@[master-ip] sudo cat /etc/kubernetes/ssl/ca.pem > ca.pem
  192. ```
  193. 5. Edit OpenStack Neutron master's Security Group to allow TCP connections to port 6443
  194. 6. Configure kubectl:
  195. ```
  196. kubectl config set-cluster default-cluster --server=https://[master-internal-ip]:6443 \
  197. --certificate-authority=ca.pem
  198. kubectl config set-credentials default-admin \
  199. --certificate-authority=ca.pem \
  200. --client-key=admin-key.pem \
  201. --client-certificate=admin.pem
  202. kubectl config set-context default-system --cluster=default-cluster --user=default-admin
  203. kubectl config use-context default-system
  204. ```
  205. 7. Check it:
  206. ```
  207. kubectl version
  208. ```
  209. # What's next
  210. [Start Hello Kubernetes Service](https://kubernetes.io/docs/tasks/access-application-cluster/service-access-application-cluster/)
  211. # clean up:
  212. ```
  213. $ terraform destroy
  214. Do you really want to destroy?
  215. Terraform will delete all your managed infrastructure.
  216. There is no undo. Only 'yes' will be accepted to confirm.
  217. Enter a value: yes
  218. ...
  219. ...
  220. Apply complete! Resources: 0 added, 0 changed, 12 destroyed.
  221. ```