diff --git a/contrib/terraform/openstack/.gitignore b/contrib/terraform/openstack/.gitignore new file mode 100644 index 000000000..0e3980cbd --- /dev/null +++ b/contrib/terraform/openstack/.gitignore @@ -0,0 +1,4 @@ +.terraform +*.tfvars +*.tfstate +*.tfstate.backup diff --git a/contrib/terraform/openstack/README.md b/contrib/terraform/openstack/README.md index 032f2c93e..6ff0860ca 100644 --- a/contrib/terraform/openstack/README.md +++ b/contrib/terraform/openstack/README.md @@ -82,23 +82,102 @@ used to deploy and provision the software requirements. #### OpenStack -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: +No provider variables are hard coded inside `variables.tf` because Terraform +supports various authentication method for OpenStack, between identity v2 and +v3 API, `openrc` or `clouds.yaml`. + +These are examples and may vary depending on your OpenStack cloud provider, +for an exhaustive list on how to authenticate on OpenStack with Terraform +please read the [OpenStack provider documentation](https://www.terraform.io/docs/providers/openstack/). + +##### Recommended method : clouds.yaml + +Newer recommended authentication method is to use a `clouds.yaml` file that can be store in : + +* `Current Directory` +* `~/.config/openstack` +* `/etc/openstack` + +`clouds.yaml` : ``` -$ source ~/.stackrc +clouds: + mycloud: + auth: + auth_url: https://openstack:5000/v3 + username: "username" + project_name: "projectname" + project_id: projectid + user_domain_name: "Default" + password: "password" + region_name: "RegionOne" + interface: "public" + identity_api_version: 3 ``` -Ensure that you have your Openstack credentials loaded into Terraform -environment variables. Likely via a command similar to: +If you have multiple clouds defined in your `clouds.yaml` file you can choose +the one you want to use with the environment variable `OS_CLOUD` : ``` -$ echo Setting up Terraform creds && \ - export TF_VAR_username=${OS_USERNAME} && \ - export TF_VAR_password=${OS_PASSWORD} && \ - export TF_VAR_tenant=${OS_TENANT_NAME} && \ - export TF_VAR_auth_url=${OS_AUTH_URL} +export OS_CLOUD=mycloud +``` + +##### Deprecated method : openrc + +When using classic environment variables, Terraform uses default `OS_*` +environment variables : + +With identity v2 : + +``` +source openrc + +env | grep OS + +OS_AUTH_URL=https://openstack:5000/v2.0 +OS_PROJECT_ID=projectid +OS_PROJECT_NAME=projectname +OS_USERNAME=username +OS_PASSWORD=password +OS_REGION_NAME=RegionOne +OS_INTERFACE=public +OS_IDENTITY_API_VERSION=2 +``` + +With identity v3 : + +``` +source openrc + +env | grep OS + +OS_AUTH_URL=https://openstack:5000/v3 +OS_PROJECT_ID=projectid +OS_PROJECT_NAME=username +OS_PROJECT_DOMAIN_ID=default +OS_USERNAME=username +OS_PASSWORD=password +OS_REGION_NAME=RegionOne +OS_INTERFACE=public +OS_IDENTITY_API_VERSION=3 +OS_USER_DOMAIN_NAME=Default +``` + +Terraform does not support a mix of DomainName and DomainID, choose one or the +other : + +``` +* provider.openstack: You must provide exactly one of DomainID or DomainName to authenticate by Username +``` + +``` +unset OS_USER_DOMAIN_NAME +export OS_USER_DOMAIN_ID=default + +or + +unset OS_PROJECT_DOMAIN_ID +set OS_PROJECT_DOMAIN_NAME=Default ``` ### Terraform Variables @@ -114,7 +193,7 @@ ones: |---------|-------------| |`cluster_name` | All OpenStack resources will use the Terraform variable`cluster_name` (default`example`) in their name to make it easier to track. For example the first compute resource will be named`example-kubernetes-1`. | |`network_name` | The name to be given to the internal network that will be generated | -|`dns_nameservers`| An array of DNS name server names to be used by hosts in the internal subnet. | +|`dns_nameservers`| An array of DNS name server names to be used by hosts in the internal subnet. | |`floatingip_pool` | Name of the pool from which floating IPs will be allocated | |`external_net` | UUID of the external network that will be routed to | |`flavor_k8s_master`,`flavor_k8s_node`,`flavor_etcd`, `flavor_bastion`,`flavor_gfs_node` | Flavor depends on your openstack installation, you can get available flavor IDs through`nova flavor-list` | @@ -129,7 +208,21 @@ ones: |`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 | +### Terraform files + +In the root folder, the following files might be created (either by Terraform +or manually), to prevent you from pushing them accidentally they are in a +`.gitignore` file in the `terraform/openstack` directory : + +* `.terraform` +* `.tfvars` +* `.tfstate` +* `.tfstate.backup` + +You can still add them manually if you want to. + ## Initializing Terraform + Before Terraform can operate on your cluster you need to install required plugins. This is accomplished with the command @@ -163,6 +256,12 @@ $ terraform destroy -state=contrib/terraform/openstack/terraform.tfstate -var-fi You can enable debugging output from Terraform by setting `OS_DEBUG` to 1 and`TF_LOG` to`DEBUG` before runing the terraform command +## Terraform output + +Terraform can output useful values that need to be reused if you want to use Kubernetes OpenStack cloud provider with Neutron/Octavia LBaaS or Cinder persistent Volume provisioning: + + - `private_subnet_id`: the subnet where your instances are running, maps to `openstack_lbaas_subnet_id` + - `floating_network_id`: the network_id where the floating IP are provisioned, maps to `openstack_lbaas_floating_network_id` # Running the Ansible Script Ensure your local ssh-agent is running and your ssh key has been added. This diff --git a/contrib/terraform/openstack/kubespray.tf b/contrib/terraform/openstack/kubespray.tf index c09ad9527..e0dbfd02d 100644 --- a/contrib/terraform/openstack/kubespray.tf +++ b/contrib/terraform/openstack/kubespray.tf @@ -1,55 +1,77 @@ - module "network" { source = "modules/network" - external_net = "${var.external_net}" - network_name = "${var.network_name}" - cluster_name = "${var.cluster_name}" + external_net = "${var.external_net}" + network_name = "${var.network_name}" + cluster_name = "${var.cluster_name}" dns_nameservers = "${var.dns_nameservers}" } - module "ips" { source = "modules/ips" - number_of_k8s_masters = "${var.number_of_k8s_masters}" + number_of_k8s_masters = "${var.number_of_k8s_masters}" number_of_k8s_masters_no_etcd = "${var.number_of_k8s_masters_no_etcd}" - number_of_k8s_nodes = "${var.number_of_k8s_nodes}" - floatingip_pool = "${var.floatingip_pool}" - number_of_bastions = "${var.number_of_bastions}" - external_net = "${var.external_net}" - network_name = "${var.network_name}" - router_id = "${module.network.router_id}" + number_of_k8s_nodes = "${var.number_of_k8s_nodes}" + floatingip_pool = "${var.floatingip_pool}" + number_of_bastions = "${var.number_of_bastions}" + external_net = "${var.external_net}" + network_name = "${var.network_name}" + router_id = "${module.network.router_id}" } module "compute" { source = "modules/compute" - cluster_name = "${var.cluster_name}" - number_of_k8s_masters = "${var.number_of_k8s_masters}" - number_of_k8s_masters_no_etcd = "${var.number_of_k8s_masters_no_etcd}" - number_of_etcd = "${var.number_of_etcd}" - number_of_k8s_masters_no_floating_ip = "${var.number_of_k8s_masters_no_floating_ip}" + cluster_name = "${var.cluster_name}" + number_of_k8s_masters = "${var.number_of_k8s_masters}" + number_of_k8s_masters_no_etcd = "${var.number_of_k8s_masters_no_etcd}" + number_of_etcd = "${var.number_of_etcd}" + number_of_k8s_masters_no_floating_ip = "${var.number_of_k8s_masters_no_floating_ip}" number_of_k8s_masters_no_floating_ip_no_etcd = "${var.number_of_k8s_masters_no_floating_ip_no_etcd}" - number_of_k8s_nodes = "${var.number_of_k8s_nodes}" - number_of_bastions = "${var.number_of_bastions}" - number_of_k8s_nodes_no_floating_ip = "${var.number_of_k8s_nodes_no_floating_ip}" - number_of_gfs_nodes_no_floating_ip = "${var.number_of_gfs_nodes_no_floating_ip}" - gfs_volume_size_in_gb = "${var.gfs_volume_size_in_gb}" - public_key_path = "${var.public_key_path}" - image = "${var.image}" - image_gfs = "${var.image_gfs}" - ssh_user = "${var.ssh_user}" - ssh_user_gfs = "${var.ssh_user_gfs}" - flavor_k8s_master = "${var.flavor_k8s_master}" - flavor_k8s_node = "${var.flavor_k8s_node}" - flavor_etcd = "${var.flavor_etcd}" - flavor_gfs_node = "${var.flavor_gfs_node}" - network_name = "${var.network_name}" - flavor_bastion = "${var.flavor_bastion}" - k8s_master_fips = "${module.ips.k8s_master_fips}" - k8s_node_fips = "${module.ips.k8s_node_fips}" - bastion_fips = "${module.ips.bastion_fips}" + number_of_k8s_nodes = "${var.number_of_k8s_nodes}" + number_of_bastions = "${var.number_of_bastions}" + number_of_k8s_nodes_no_floating_ip = "${var.number_of_k8s_nodes_no_floating_ip}" + number_of_gfs_nodes_no_floating_ip = "${var.number_of_gfs_nodes_no_floating_ip}" + gfs_volume_size_in_gb = "${var.gfs_volume_size_in_gb}" + public_key_path = "${var.public_key_path}" + image = "${var.image}" + image_gfs = "${var.image_gfs}" + ssh_user = "${var.ssh_user}" + ssh_user_gfs = "${var.ssh_user_gfs}" + flavor_k8s_master = "${var.flavor_k8s_master}" + flavor_k8s_node = "${var.flavor_k8s_node}" + flavor_etcd = "${var.flavor_etcd}" + flavor_gfs_node = "${var.flavor_gfs_node}" + network_name = "${var.network_name}" + flavor_bastion = "${var.flavor_bastion}" + k8s_master_fips = "${module.ips.k8s_master_fips}" + k8s_node_fips = "${module.ips.k8s_node_fips}" + bastion_fips = "${module.ips.bastion_fips}" network_id = "${module.network.router_id}" } + +output "private_subnet_id" { + value = "${module.network.subnet_id}" +} + +output "floating_network_id" { + value = "${var.external_net}" +} + +output "router_id" { + value = "${module.network.router_id}" +} + +output "k8s_master_fips" { + value = "${module.ips.k8s_master_fips}" +} + +output "k8s_node_fips" { + value = "${module.ips.k8s_node_fips}" +} + +output "bastion_fips" { + value = "${module.ips.bastion_fips}" +} diff --git a/contrib/terraform/openstack/modules/compute/main.tf b/contrib/terraform/openstack/modules/compute/main.tf index 624c39f0d..e0a8eab4a 100644 --- a/contrib/terraform/openstack/modules/compute/main.tf +++ b/contrib/terraform/openstack/modules/compute/main.tf @@ -1,280 +1,306 @@ - - -variable user_data { - type = "string" - default = <