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.

231 lines
8.3 KiB

  1. # Kubernetes on Packet with Terraform
  2. Provision a Kubernetes cluster with [Terraform](https://www.terraform.io) on
  3. [Packet](https://www.packet.com).
  4. ## Status
  5. This will install a Kubernetes cluster on Packet bare metal. It should work in all locations and on most server types.
  6. ## Approach
  7. The terraform configuration inspects variables found in
  8. [variables.tf](variables.tf) to create resources in your Packet project.
  9. There is a [python script](../terraform.py) that reads the generated`.tfstate`
  10. file to generate a dynamic inventory that is consumed by [cluster.yml](../../..//cluster.yml)
  11. to actually install Kubernetes with Kubespray.
  12. ### Kubernetes Nodes
  13. You can create many different kubernetes topologies by setting the number of
  14. different classes of hosts.
  15. - Master nodes with etcd: `number_of_k8s_masters` variable
  16. - Master nodes without etcd: `number_of_k8s_masters_no_etcd` variable
  17. - Standalone etcd hosts: `number_of_etcd` variable
  18. - Kubernetes worker nodes: `number_of_k8s_nodes` variable
  19. Note that the Ansible script will report an invalid configuration if you wind up
  20. with an *even number* of etcd instances since that is not a valid configuration. This
  21. restriction includes standalone etcd nodes that are deployed in a cluster along with
  22. master nodes with etcd replicas. As an example, if you have three master nodes with
  23. etcd replicas and three standalone etcd nodes, the script will fail since there are
  24. now six total etcd replicas.
  25. ## Requirements
  26. - [Install Terraform](https://www.terraform.io/intro/getting-started/install.html)
  27. - Install dependencies: `sudo pip install -r requirements.txt`
  28. - Account with Packet Host
  29. - An SSH key pair
  30. ## SSH Key Setup
  31. An SSH keypair is required so Ansible can access the newly provisioned nodes (bare metal Packet hosts). By default, the public SSH key defined in cluster.tf will be installed in authorized_key on the newly provisioned nodes (~/.ssh/id_rsa.pub). Terraform will upload this public key and then it will be distributed out to all the nodes. If you have already set this public key in Packet (i.e. via the portal), then set the public keyfile name in cluster.tf to blank to prevent the duplicate key from being uploaded which will cause an error.
  32. If you don't already have a keypair generated (~/.ssh/id_rsa and ~/.ssh/id_rsa.pub), then a new keypair can be generated with the command:
  33. ```ShellSession
  34. ssh-keygen -f ~/.ssh/id_rsa
  35. ```
  36. ## Terraform
  37. Terraform will be used to provision all of the Packet resources with base software as appropriate.
  38. ### Configuration
  39. #### Inventory files
  40. Create an inventory directory for your cluster by copying the existing sample and linking the `hosts` script (used to build the inventory based on Terraform state):
  41. ```ShellSession
  42. $ cp -LRp contrib/terraform/packet/sample-inventory inventory/$CLUSTER
  43. $ cd inventory/$CLUSTER
  44. $ ln -s ../../contrib/terraform/packet/hosts
  45. ```
  46. This will be the base for subsequent Terraform commands.
  47. #### Packet API access
  48. Your Packet API key must be available in the `PACKET_AUTH_TOKEN` environment variable.
  49. This key is typically stored outside of the code repo since it is considered secret.
  50. If someone gets this key, they can startup/shutdown hosts in your project!
  51. For more information on how to generate an API key or find your project ID, please see:
  52. https://support.packet.com/kb/articles/api-integrations
  53. The Packet Project ID associated with the key will be set later in cluster.tf.
  54. For more information about the API, please see:
  55. https://www.packet.com/developers/api/
  56. Example:
  57. ```ShellSession
  58. $ export PACKET_AUTH_TOKEN="Example-API-Token"
  59. ```
  60. Note that to deploy several clusters within the same project you need to use [terraform workspace](https://www.terraform.io/docs/state/workspaces.html#using-workspaces).
  61. #### Cluster variables
  62. The construction of the cluster is driven by values found in
  63. [variables.tf](variables.tf).
  64. For your cluster, edit `inventory/$CLUSTER/cluster.tf`.
  65. The `cluster_name` is used to set a tag on each server deployed as part of this cluster.
  66. This helps when identifying which hosts are associated with each cluster.
  67. While the defaults in variables.tf will successfully deploy a cluster, it is recommended to set the following values:
  68. * cluster_name = the name of the inventory directory created above as $CLUSTER
  69. * packet_project_id = the Packet Project ID associated with the Packet API token above
  70. #### Enable localhost access
  71. Kubespray will pull down a Kubernetes configuration file to access this cluster by enabling the
  72. `kubeconfig_localhost: true` in the Kubespray configuration.
  73. Edit `inventory/$CLUSTER/group_vars/k8s-cluster/k8s-cluster.yml` and comment back in the following line and change from `false` to `true`:
  74. `\# kubeconfig_localhost: false`
  75. becomes:
  76. `kubeconfig_localhost: true`
  77. Once the Kubespray playbooks are run, a Kubernetes configuration file will be written to the local host at `inventory/$CLUSTER/artifacts/admin.conf`
  78. #### Terraform state files
  79. In the cluster's inventory folder, the following files might be created (either by Terraform
  80. or manually), to prevent you from pushing them accidentally they are in a
  81. `.gitignore` file in the `terraform/packet` directory :
  82. * `.terraform`
  83. * `.tfvars`
  84. * `.tfstate`
  85. * `.tfstate.backup`
  86. You can still add them manually if you want to.
  87. ### Initialization
  88. Before Terraform can operate on your cluster you need to install the required
  89. plugins. This is accomplished as follows:
  90. ```ShellSession
  91. $ cd inventory/$CLUSTER
  92. $ terraform init ../../contrib/terraform/packet
  93. ```
  94. This should finish fairly quickly telling you Terraform has successfully initialized and loaded necessary modules.
  95. ### Provisioning cluster
  96. You can apply the Terraform configuration to your cluster with the following command
  97. issued from your cluster's inventory directory (`inventory/$CLUSTER`):
  98. ```ShellSession
  99. $ terraform apply -var-file=cluster.tf ../../contrib/terraform/packet
  100. $ export ANSIBLE_HOST_KEY_CHECKING=False
  101. $ ansible-playbook -i hosts ../../cluster.yml
  102. ```
  103. ### Destroying cluster
  104. You can destroy your new cluster with the following command issued from the cluster's inventory directory:
  105. ```ShellSession
  106. $ terraform destroy -var-file=cluster.tf ../../contrib/terraform/packet
  107. ```
  108. If you've started the Ansible run, it may also be a good idea to do some manual cleanup:
  109. * remove SSH keys from the destroyed cluster from your `~/.ssh/known_hosts` file
  110. * clean up any temporary cache files: `rm /tmp/$CLUSTER-*`
  111. ### Debugging
  112. You can enable debugging output from Terraform by setting `TF_LOG` to `DEBUG` before running the Terraform command.
  113. ## Ansible
  114. ### Node access
  115. #### SSH
  116. Ensure your local ssh-agent is running and your ssh key has been added. This
  117. step is required by the terraform provisioner:
  118. ```
  119. $ eval $(ssh-agent -s)
  120. $ ssh-add ~/.ssh/id_rsa
  121. ```
  122. If you have deployed and destroyed a previous iteration of your cluster, you will need to clear out any stale keys from your SSH "known hosts" file ( `~/.ssh/known_hosts`).
  123. #### Test access
  124. Make sure you can connect to the hosts. Note that Container Linux by CoreOS will have a state `FAILED` due to Python not being present. This is okay, because Python will be installed during bootstrapping, so long as the hosts are not `UNREACHABLE`.
  125. ```
  126. $ ansible -i inventory/$CLUSTER/hosts -m ping all
  127. example-k8s_node-1 | SUCCESS => {
  128. "changed": false,
  129. "ping": "pong"
  130. }
  131. example-etcd-1 | SUCCESS => {
  132. "changed": false,
  133. "ping": "pong"
  134. }
  135. example-k8s-master-1 | SUCCESS => {
  136. "changed": false,
  137. "ping": "pong"
  138. }
  139. ```
  140. If it fails try to connect manually via SSH. It could be something as simple as a stale host key.
  141. ### Deploy Kubernetes
  142. ```
  143. $ ansible-playbook --become -i inventory/$CLUSTER/hosts cluster.yml
  144. ```
  145. This will take some time as there are many tasks to run.
  146. ## Kubernetes
  147. ### Set up kubectl
  148. * [Install kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) on the localhost.
  149. * Verify that Kubectl runs correctly
  150. ```
  151. kubectl version
  152. ```
  153. * Verify that the Kubernetes configuration file has been copied over
  154. ```
  155. cat inventory/alpha/$CLUSTER/admin.conf
  156. ```
  157. * Verify that all the nodes are running correctly.
  158. ```
  159. kubectl version
  160. kubectl --kubeconfig=inventory/$CLUSTER/artifacts/admin.conf get nodes
  161. ```
  162. ## What's next
  163. Try out your new Kubernetes cluster with the [Hello Kubernetes service](https://kubernetes.io/docs/tasks/access-application-cluster/service-access-application-cluster/).