more real world exampls; fix scanner when scanning empty character in lexer

This commit is contained in:
mhoffm
2021-06-21 19:40:27 +02:00
parent 3bc4153bc2
commit a7f23cc579
2020 changed files with 64141 additions and 10630 deletions

View File

@@ -0,0 +1,358 @@
terraform {
required_version = ">= 0.10.7"
}
provider "archive" {
version = "1.0.0"
}
provider "external" {
version = "1.0.0"
}
provider "ignition" {
version = "1.0.0"
}
provider "local" {
version = "1.0.0"
}
provider "null" {
version = "1.0.0"
}
provider "random" {
version = "1.0.0"
}
provider "template" {
version = "1.0.0"
}
provider "tls" {
version = "1.0.1"
}
variable "tectonic_config_version" {
description = <<EOF
(internal) This declares the version of the global configuration variables.
It has no impact on generated assets but declares the version contract of the configuration.
EOF
default = "1.0"
}
variable "tectonic_image_re" {
description = <<EOF
(internal) Regular expression used to extract repo and tag components
EOF
type = "string"
default = "/^([^/]+/[^/]+):(.*)$/"
}
variable "tectonic_container_images" {
description = "(internal) Container images to use"
type = "map"
default = {
addon_resizer = "gcr.io/google_containers/addon-resizer:2.1"
awscli = "quay.io/coreos/awscli:025a357f05242fdad6a81e8a6b520098aa65a600"
gcloudsdk = "google/cloud-sdk:178.0.0-alpine"
bootkube = "quay.io/coreos/bootkube:v0.10.0"
tnc_operator = "quay.io/coreos/tectonic-node-controller-operator-dev:c3cee2bc5673011e88ac7b0ab1659c2c7243a499"
etcd_cert_signer = "quay.io/coreos/kube-etcd-signer-server:678cc8e6841e2121ebfdb6e2db568fce290b67d6"
etcd = "quay.io/coreos/etcd:v3.2.14"
hyperkube = "openshift/origin-node:latest"
kube_core_renderer = "quay.io/coreos/kube-core-renderer-dev:c3cee2bc5673011e88ac7b0ab1659c2c7243a499"
kube_core_operator = "quay.io/coreos/kube-core-operator-dev:c3cee2bc5673011e88ac7b0ab1659c2c7243a499"
tectonic_channel_operator = "quay.io/coreos/tectonic-channel-operator-dev:c3cee2bc5673011e88ac7b0ab1659c2c7243a499"
kube_addon_operator = "quay.io/coreos/kube-addon-operator-dev:c3cee2bc5673011e88ac7b0ab1659c2c7243a499"
tectonic_alm_operator = "quay.io/coreos/tectonic-alm-operator:v0.3.1"
tectonic_ingress_controller_operator = "quay.io/coreos/tectonic-ingress-controller-operator-dev:c3cee2bc5673011e88ac7b0ab1659c2c7243a499"
tectonic_utility_operator = "quay.io/coreos/tectonic-utility-operator-dev:c3cee2bc5673011e88ac7b0ab1659c2c7243a499"
tectonic_network_operator = "quay.io/coreos/tectonic-network-operator-dev:c3cee2bc5673011e88ac7b0ab1659c2c7243a499"
}
}
variable "tectonic_container_base_images" {
description = "(internal) Base images of the components to use"
type = "map"
default = {
tectonic_monitoring_auth = "quay.io/coreos/tectonic-monitoring-auth"
config_reload = "quay.io/coreos/configmap-reload"
addon_resizer = "quay.io/coreos/addon-resizer"
kube_state_metrics = "quay.io/coreos/kube-state-metrics"
grafana = "quay.io/coreos/monitoring-grafana"
grafana_watcher = "quay.io/coreos/grafana-watcher"
prometheus_operator = "quay.io/coreos/prometheus-operator"
prometheus_config_reload = "quay.io/coreos/prometheus-config-reloader"
prometheus = "quay.io/prometheus/prometheus"
alertmanager = "quay.io/prometheus/alertmanager"
node_exporter = "quay.io/prometheus/node-exporter"
kube_rbac_proxy = "quay.io/coreos/kube-rbac-proxy"
}
}
variable "tectonic_versions" {
description = "(internal) Versions of the components to use"
type = "map"
default = {
tectonic = "1.8.4-tectonic.2"
alm = "0.4.0"
}
}
variable "tectonic_service_cidr" {
type = "string"
description = <<EOF
(optional) This declares the IP range to assign Kubernetes service cluster IPs in CIDR notation.
The maximum size of this IP range is /12
EOF
}
variable "tectonic_cluster_cidr" {
type = "string"
description = "(optional) This declares the IP range to assign Kubernetes pod IPs in CIDR notation."
}
variable "tectonic_master_count" {
type = "string"
default = "1"
description = <<EOF
The number of master nodes to be created.
This applies only to cloud platforms.
EOF
}
variable "tectonic_worker_count" {
type = "string"
default = "3"
description = <<EOF
The number of worker nodes to be created.
This applies only to cloud platforms.
EOF
}
variable "tectonic_etcd_count" {
type = "string"
default = "0"
description = <<EOF
The number of etcd nodes to be created.
If set to zero, the count of etcd nodes will be determined automatically.
EOF
}
variable "tectonic_base_domain" {
type = "string"
description = <<EOF
The base DNS domain of the cluster. It must NOT contain a trailing period. Some
DNS providers will automatically add this if necessary.
Example: `openshift.example.com`.
Note: This field MUST be set manually prior to creating the cluster.
This applies only to cloud platforms.
EOF
}
variable "tectonic_cluster_name" {
type = "string"
description = <<EOF
The name of the cluster.
If used in a cloud-environment, this will be prepended to `tectonic_base_domain` resulting in the URL to the Tectonic console.
Note: This field MUST be set manually prior to creating the cluster.
EOF
}
variable "tectonic_pull_secret_path" {
type = "string"
default = ""
description = <<EOF
The path the pull secret file in JSON format.
This is known to be a "Docker pull secret" as produced by the docker login [1] command.
A sample JSON content is shown in [2].
You can download the pull secret from your Account overview page at [3].
[1] https://docs.docker.com/engine/reference/commandline/login/
[2] https://coreos.com/os/docs/latest/registry-authentication.html#manual-registry-auth-setup
[3] https://account.coreos.com/overview
EOF
}
variable "tectonic_license_path" {
type = "string"
default = ""
description = <<EOF
The path to the tectonic licence file.
You can download the Tectonic license file from your Account overview page at [1].
[1] https://account.coreos.com/overview
EOF
}
variable "tectonic_container_linux_channel" {
type = "string"
description = <<EOF
The Container Linux update channel.
Examples: `stable`, `beta`, `alpha`
EOF
}
variable "tectonic_container_linux_version" {
type = "string"
description = <<EOF
The Container Linux version to use. Set to `latest` to select the latest available version for the selected update channel.
Examples: `latest`, `1465.6.0`
EOF
}
variable "tectonic_update_server" {
type = "string"
default = "https://tectonic.update.core-os.net"
description = "(internal) The URL of the Tectonic Omaha update server"
}
variable "tectonic_update_channel" {
type = "string"
default = "tectonic-1.9-production"
description = "(internal) The Tectonic Omaha update channel"
}
variable "tectonic_update_app_id" {
type = "string"
default = "6bc7b986-4654-4a0f-94b3-84ce6feb1db4"
description = "(internal) The Tectonic Omaha update App ID"
}
variable "tectonic_admin_email" {
type = "string"
description = <<EOF
(internal) The e-mail address used to:
1. login as the admin user to the Tectonic Console.
2. generate DNS zones for some providers.
Note: This field MUST be in all lower-case e-mail address format and set manually prior to creating the cluster.
EOF
}
variable "tectonic_admin_password" {
type = "string"
description = <<EOF
(internal) The admin user password to login to the Tectonic Console.
Note: This field MUST be set manually prior to creating the cluster. Backslashes and double quotes must
also be escaped.
EOF
}
variable "tectonic_ca_cert" {
type = "string"
default = ""
description = <<EOF
(optional) The content of the PEM-encoded CA certificate, used to generate all cluster certificates.
If left blank, a CA certificate will be automatically generated.
EOF
}
variable "tectonic_ca_key" {
type = "string"
default = ""
description = <<EOF
(optional) The content of the PEM-encoded CA key, used to generate Tectonic all cluster certificates.
This field is mandatory if `tectonic_ca_cert` is set.
EOF
}
variable "tectonic_ca_key_alg" {
type = "string"
default = "RSA"
description = <<EOF
(optional) The algorithm used to generate tectonic_ca_key.
The default value is currently recommended.
This field is mandatory if `tectonic_ca_cert` is set.
EOF
}
variable "tectonic_stats_url" {
type = "string"
default = "https://stats-collector.tectonic.com"
description = "(internal) The Tectonic statistics collection URL to which to report."
}
variable "tectonic_networking" {
description = <<EOF
(optional) Configures the network to be used in Tectonic. One of the following values can be used:
- "flannel": enables overlay networking only. This is implemented by flannel using VXLAN.
- "canal": enables overlay networking including network policy. Overlay is implemented by flannel using VXLAN. Network policy is implemented by Calico.
- "calico-ipip": [ALPHA] enables BGP based networking. Routing and network policy is implemented by Calico. Note this has been tested on bare metal installations only.
- "none": disables the installation of any Pod level networking layer provided by Tectonic. By setting this value, users are expected to deploy their own solution to enable network connectivity for Pods and Services.
EOF
}
variable "tectonic_kubelet_debug_config" {
type = "string"
default = ""
description = "(internal) debug flags for the kubelet (used in CI only)"
}
variable "tectonic_ignition_master" {
type = "string"
default = ""
description = <<EOF
(internal) Ignition config file path. This is automatically generated by the installer.
EOF
}
variable "tectonic_ignition_worker" {
type = "string"
default = ""
description = <<EOF
(internal) Ignition config file path. This is automatically generated by the installer.
EOF
}
variable "tectonic_platform" {
type = "string"
description = <<EOF
(internal) The internal Terraform platform type, e.g. aws or libvirt
EOF
}
// This variable is generated by tectonic internally. Do not modify
variable "tectonic_cluster_id" {
type = "string"
description = "(internal) The Tectonic cluster id."
}

View File

@@ -0,0 +1,610 @@
terraform {
required_version = ">= 0.10.7"
}
provider "archive" {
version = "1.0.0"
}
provider "external" {
version = "1.0.0"
}
provider "ignition" {
version = "1.0.0"
}
provider "local" {
version = "1.0.0"
}
provider "null" {
version = "1.0.0"
}
provider "random" {
version = "1.0.0"
}
provider "template" {
version = "1.0.0"
}
provider "tls" {
version = "1.0.1"
}
locals {
// The total amount of public CA certificates present in Tectonic.
// That is all custom CAs + kube CA + etcd CA + ingress CA
// This is a local constant, which needs to be dependency injected because TF cannot handle length() on computed values,
// see https://github.com/hashicorp/terraform/issues/10857#issuecomment-268289775.
tectonic_ca_count = "${length(var.tectonic_custom_ca_pem_list) + 3}"
tectonic_http_proxy_enabled = "${length(var.tectonic_http_proxy_address) > 0}"
}
variable "tectonic_config_version" {
description = <<EOF
(internal) This declares the version of the global configuration variables.
It has no impact on generated assets but declares the version contract of the configuration.
EOF
default = "1.0"
}
variable "tectonic_image_re" {
description = <<EOF
(internal) Regular expression used to extract repo and tag components
EOF
type = "string"
default = "/^([^/]+/[^/]+/[^/]+):(.*)$/"
}
variable "tectonic_container_images" {
description = "(internal) Container images to use"
type = "map"
default = {
addon_resizer = "gcr.io/google_containers/addon-resizer:2.1"
awscli = "quay.io/coreos/awscli:025a357f05242fdad6a81e8a6b520098aa65a600"
gcloudsdk = "google/cloud-sdk:178.0.0-alpine"
bootkube = "quay.io/coreos/bootkube:v0.8.1"
calico = "quay.io/calico/node:v2.6.1"
calico_cni = "quay.io/calico/cni:v1.11.0"
console = "quay.io/coreos/tectonic-console:v6.0.5"
error_server = "quay.io/coreos/tectonic-error-server:1.1"
etcd = "quay.io/coreos/etcd:v3.1.8"
etcd_operator = "quay.io/coreos/etcd-operator:v0.5.0"
flannel = "quay.io/coreos/flannel:v0.8.0-amd64"
flannel_cni = "quay.io/coreos/flannel-cni:v0.2.0"
heapster = "gcr.io/google_containers/heapster:v1.4.1"
hyperkube = "quay.io/coreos/hyperkube:v1.9.6_coreos.0"
identity = "quay.io/coreos/dex:v2.8.1"
ingress_controller = "quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.9.0-beta.17"
kenc = "quay.io/coreos/kenc:0.0.2"
kubedns = "gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.8"
kubednsmasq = "gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.8"
kubedns_sidecar = "gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.8"
kube_version = "quay.io/coreos/kube-version:0.1.0"
kube_version_operator = "quay.io/coreos/kube-version-operator:v1.9.6-kvo.4"
node_agent = "quay.io/coreos/node-agent:cd69b4a0f65b0d3a3b30edfce3bb184fd2a22c26"
pod_checkpointer = "quay.io/coreos/pod-checkpointer:e22cc0e3714378de92f45326474874eb602ca0ac"
stats_emitter = "quay.io/coreos/tectonic-stats:6e882361357fe4b773adbf279cddf48cb50164c1"
stats_extender = "quay.io/coreos/tectonic-stats-extender:487b3da4e175da96dabfb44fba65cdb8b823db2e"
tectonic_channel_operator = "quay.io/coreos/tectonic-channel-operator:0.6.4"
tectonic_etcd_operator = "quay.io/coreos/tectonic-etcd-operator:v0.0.2"
tectonic_prometheus_operator = "quay.io/coreos/tectonic-prometheus-operator:v1.9.5"
tectonic_cluo_operator = "quay.io/coreos/tectonic-cluo-operator:v0.3.2"
tectonic_torcx = "quay.io/coreos/tectonic-torcx:v0.2.0"
tectonic_alm_operator = "quay.io/coreos/tectonic-alm-operator:v0.4.0"
}
}
variable "tectonic_container_base_images" {
description = "(internal) Base images of the components to use"
type = "map"
default = {
tectonic_monitoring_auth = "quay.io/coreos/tectonic-monitoring-auth"
config_reload = "quay.io/coreos/configmap-reload"
addon_resizer = "quay.io/coreos/addon-resizer"
kube_state_metrics = "quay.io/coreos/kube-state-metrics"
grafana = "quay.io/coreos/monitoring-grafana"
grafana_watcher = "quay.io/coreos/grafana-watcher"
prometheus_operator = "quay.io/coreos/prometheus-operator"
prometheus_config_reload = "quay.io/coreos/prometheus-config-reloader"
prometheus = "quay.io/prometheus/prometheus"
alertmanager = "quay.io/prometheus/alertmanager"
node_exporter = "quay.io/prometheus/node-exporter"
kube_rbac_proxy = "quay.io/coreos/kube-rbac-proxy"
}
}
variable "tectonic_versions" {
description = "(internal) Versions of the components to use"
type = "map"
default = {
etcd = "3.1.8"
kubernetes = "1.9.6+tectonic.1"
monitoring = "1.9.5"
tectonic = "1.9.6-tectonic.1"
tectonic-etcd = "0.0.1"
cluo = "0.3.2"
alm = "0.4.0"
}
}
variable "tectonic_service_cidr" {
type = "string"
default = "10.3.0.0/16"
description = <<EOF
(optional) This declares the IP range to assign Kubernetes service cluster IPs in CIDR notation.
The maximum size of this IP range is /12
EOF
}
variable "tectonic_cluster_cidr" {
type = "string"
default = "10.2.0.0/16"
description = "(optional) This declares the IP range to assign Kubernetes pod IPs in CIDR notation."
}
variable "tectonic_master_count" {
type = "string"
default = "1"
description = <<EOF
The number of master nodes to be created.
This applies only to cloud platforms.
EOF
}
variable "tectonic_worker_count" {
type = "string"
default = "3"
description = <<EOF
The number of worker nodes to be created.
This applies only to cloud platforms.
EOF
}
variable "tectonic_etcd_count" {
type = "string"
default = "0"
description = <<EOF
The number of etcd nodes to be created.
If set to zero, the count of etcd nodes will be determined automatically.
Note: This is not supported on bare metal.
EOF
}
variable "tectonic_etcd_servers" {
description = <<EOF
(optional) List of external etcd v3 servers to connect with (hostnames/IPs only).
Needs to be set if using an external etcd cluster.
Note: If this variable is defined, the installer will not create self-signed certs.
To provide a CA certificate to trust the etcd servers, set "tectonic_etcd_ca_cert_path".
Example: `["etcd1", "etcd2", "etcd3"]`
EOF
type = "list"
default = []
}
variable "tectonic_etcd_tls_enabled" {
default = true
description = <<EOF
(optional) If set to `true`, all etcd endpoints will be configured to use the "https" scheme.
Note: If `tectonic_experimental` is set to `true` this variable has no effect, because the experimental self-hosted etcd always uses TLS.
EOF
}
variable "tectonic_etcd_ca_cert_path" {
type = "string"
default = "/dev/null"
description = <<EOF
(optional) The path of the file containing the CA certificate for TLS communication with etcd.
Note: This works only when used in conjunction with an external etcd cluster.
If set, the variable `tectonic_etcd_servers` must also be set.
EOF
}
variable "tectonic_etcd_client_cert_path" {
type = "string"
default = "/dev/null"
description = <<EOF
(optional) The path of the file containing the client certificate for TLS communication with etcd.
Note: This works only when used in conjunction with an external etcd cluster.
If set, the variables `tectonic_etcd_servers`, `tectonic_etcd_ca_cert_path`, and `tectonic_etcd_client_key_path` must also be set.
EOF
}
variable "tectonic_etcd_client_key_path" {
type = "string"
default = "/dev/null"
description = <<EOF
(optional) The path of the file containing the client key for TLS communication with etcd.
Note: This works only when used in conjunction with an external etcd cluster.
If set, the variables `tectonic_etcd_servers`, `tectonic_etcd_ca_cert_path`, and `tectonic_etcd_client_cert_path` must also be set.
EOF
}
variable "tectonic_base_domain" {
type = "string"
description = <<EOF
The base DNS domain of the cluster. It must NOT contain a trailing period. Some
DNS providers will automatically add this if necessary.
Example: `openstack.dev.coreos.systems`.
Note: This field MUST be set manually prior to creating the cluster.
This applies only to cloud platforms.
[Azure-specific NOTE]
To use Azure-provided DNS, `tectonic_base_domain` should be set to `""`
If using DNS records, ensure that `tectonic_base_domain` is set to a properly configured external DNS zone.
Instructions for configuring delegated domains for Azure DNS can be found here: https://docs.microsoft.com/en-us/azure/dns/dns-delegate-domain-azure-dns
EOF
}
variable "tectonic_cluster_name" {
type = "string"
description = <<EOF
The name of the cluster.
If used in a cloud-environment, this will be prepended to `tectonic_base_domain` resulting in the URL to the Tectonic console.
Note: This field MUST be set manually prior to creating the cluster.
Warning: Special characters in the name like '.' may cause errors on OpenStack platforms due to resource name constraints.
EOF
}
variable "tectonic_pull_secret_path" {
type = "string"
default = ""
description = <<EOF
The path the pull secret file in JSON format.
This is known to be a "Docker pull secret" as produced by the docker login [1] command.
A sample JSON content is shown in [2].
You can download the pull secret from your Account overview page at [3].
[1] https://docs.docker.com/engine/reference/commandline/login/
[2] https://coreos.com/os/docs/latest/registry-authentication.html#manual-registry-auth-setup
[3] https://account.coreos.com/overview
Note: This field MUST be set manually prior to creating the cluster unless `tectonic_vanilla_k8s` is set to `true`.
EOF
}
variable "tectonic_license_path" {
type = "string"
default = ""
description = <<EOF
The path to the tectonic licence file.
You can download the Tectonic license file from your Account overview page at [1].
[1] https://account.coreos.com/overview
Note: This field MUST be set manually prior to creating the cluster unless `tectonic_vanilla_k8s` is set to `true`.
EOF
}
variable "tectonic_container_linux_channel" {
type = "string"
default = "stable"
description = <<EOF
(optional) The Container Linux update channel.
Examples: `stable`, `beta`, `alpha`
EOF
}
variable "tectonic_container_linux_version" {
type = "string"
default = "latest"
description = <<EOF
The Container Linux version to use. Set to `latest` to select the latest available version for the selected update channel.
Examples: `latest`, `1465.6.0`
EOF
}
variable "tectonic_update_server" {
type = "string"
default = "https://tectonic.update.core-os.net"
description = "(internal) The URL of the Tectonic Omaha update server"
}
variable "tectonic_update_channel" {
type = "string"
default = "tectonic-1.8-production"
description = "(internal) The Tectonic Omaha update channel"
}
variable "tectonic_update_app_id" {
type = "string"
default = "6bc7b986-4654-4a0f-94b3-84ce6feb1db4"
description = "(internal) The Tectonic Omaha update App ID"
}
variable "tectonic_admin_email" {
type = "string"
description = <<EOF
(internal) The e-mail address used to:
1. login as the admin user to the Tectonic Console.
2. generate DNS zones for some providers.
Note: This field MUST be in all lower-case e-mail address format and set manually prior to creating the cluster.
EOF
}
variable "tectonic_admin_password" {
type = "string"
description = <<EOF
(internal) The admin user password to login to the Tectonic Console.
Note: This field MUST be set manually prior to creating the cluster. Backslashes and double quotes must
also be escaped.
EOF
}
variable "tectonic_ca_cert" {
type = "string"
default = ""
description = <<EOF
(optional) The content of the PEM-encoded CA certificate, used to generate Tectonic Console's server certificate.
If left blank, a CA certificate will be automatically generated.
EOF
}
variable "tectonic_ca_key" {
type = "string"
default = ""
description = <<EOF
(optional) The content of the PEM-encoded CA key, used to generate Tectonic Console's server certificate.
This field is mandatory if `tectonic_ca_cert` is set.
EOF
}
variable "tectonic_ca_key_alg" {
type = "string"
default = "RSA"
description = <<EOF
(optional) The algorithm used to generate tectonic_ca_key.
The default value is currently recommended.
This field is mandatory if `tectonic_ca_cert` is set.
EOF
}
variable "tectonic_tls_validity_period" {
type = "string"
default = "26280"
description = <<EOF
Validity period of the self-signed certificates (in hours).
Default is 3 years.
This setting is ignored if user provided certificates are used.
EOF
}
variable "tectonic_vanilla_k8s" {
default = false
description = <<EOF
If set to true, a vanilla Kubernetes cluster will be deployed, omitting any Tectonic assets.
EOF
}
variable "tectonic_stats_url" {
type = "string"
default = "https://stats-collector.tectonic.com"
description = "(internal) The Tectonic statistics collection URL to which to report."
}
variable "tectonic_ddns_server" {
type = "string"
default = ""
description = <<EOF
(optional) This only applies if you use the modules/dns/ddns module.
Specifies the RFC2136 Dynamic DNS server IP/host to register IP addresses to.
EOF
}
variable "tectonic_ddns_key_name" {
type = "string"
default = ""
description = <<EOF
(optional) This only applies if you use the modules/dns/ddns module.
Specifies the RFC2136 Dynamic DNS server key name.
EOF
}
variable "tectonic_ddns_key_algorithm" {
type = "string"
default = ""
description = <<EOF
(optional) This only applies if you use the modules/dns/ddns module.
Specifies the RFC2136 Dynamic DNS server key algorithm.
EOF
}
variable "tectonic_ddns_key_secret" {
type = "string"
default = ""
description = <<EOF
(optional) This only applies if you use the modules/dns/ddns module.
Specifies the RFC2136 Dynamic DNS server key secret.
EOF
}
variable "tectonic_networking" {
default = "flannel"
description = <<EOF
(optional) Configures the network to be used in Tectonic. One of the following values can be used:
- "flannel": enables overlay networking only. This is implemented by flannel using VXLAN.
- "canal": [ALPHA] enables overlay networking including network policy. Overlay is implemented by flannel using VXLAN. Network policy is implemented by Calico.
- "calico": [ALPHA] enables BGP based networking. Routing and network policy is implemented by Calico. Note this has been tested on baremetal installations only.
EOF
}
variable "tectonic_self_hosted_etcd" {
default = ""
description = <<EOF
(internal) [ALPHA] If set to one of the following values, self-hosted etcd is deployed:
- "enabled": Deploys a self-hosted etcd cluster.
- "pv_backup": Deploys a self-hosted etcd cluster including backups to Persistence Volumes.
`tectonic_etcd_backup_size` and `tectonic_etcd_backup_storage_class` must be configured when using this setting.
EOF
}
variable "tectonic_etcd_backup_size" {
type = "string"
description = "(optional) The size in MB of the PersistentVolume used for handling etcd backups."
default = "512"
}
variable "tectonic_etcd_backup_storage_class" {
type = "string"
default = ""
description = "(optional) The name of an existing Kubernetes StorageClass that will be used for handling etcd backups."
}
variable "tectonic_bootstrap_upgrade_cl" {
type = "string"
default = "true"
description = "(internal) Whether to trigger a ContainerLinux upgrade on node bootstrap."
}
variable "tectonic_kubelet_debug_config" {
type = "string"
default = ""
description = "(internal) debug flags for the kubelet (used in CI only)"
}
variable "tectonic_custom_ca_pem_list" {
type = "list"
default = []
description = <<EOF
(optional) A list of PEM encoded CA files that will be installed in /etc/ssl/certs on etcd, master, and worker nodes.
EOF
}
variable "tectonic_iscsi_enabled" {
type = "string"
default = "false"
description = "(optional) Start iscsid.service to enable iscsi volume attachment."
}
variable "tectonic_http_proxy_address" {
type = "string"
default = ""
description = <<EOF
(optional) HTTP proxy address.
Example: `http://myproxy.example.com`
EOF
}
variable "tectonic_https_proxy_address" {
type = "string"
default = ""
description = <<EOF
(optional) HTTPS proxy address.
Example: `http://myproxy.example.com`
EOF
}
variable "tectonic_no_proxy" {
type = "list"
default = []
description = <<EOF
(optional) List of local endpoints that will not use HTTP proxy.
Example: `["127.0.0.1","localhost",".example.com","10.3.0.1"]`
EOF
}
variable "tectonic_ntp_servers" {
type = "list"
default = []
description = <<EOF
(optional) If left blank, the default Container Linux NTP servers will be used.
A list of NTP servers to be used for time synchronization on the cluster nodes.
EOF
}
variable "tectonic_nfs_config_file" {
type = "string"
default = ""
description = <<EOF
(optional) the path to an NFS configuration file to be placed in /etc/conf.d/nfs
file on the CL nodes.
EOF
}
# Workaround for https://github.com/hashicorp/hil/issues/50
locals {
_tectonic_nfs_config_file = "${var.tectonic_nfs_config_file != "" ? var.tectonic_nfs_config_file : "/dev/null"}"
}
variable "tectonic_proxy_exclusive_units" {
default = false
description = <<EOF
(optional) When set to true, it restricts the application of proxy settings to processes started through systemd units.
Global proxy settings will not be affected in this case.
When set to false, the proxy settings will apply globally, including to all processes lauched by users.
EOF
}

View File

@@ -0,0 +1,161 @@
provider "aws" {
region = "${var.vpc_aws_region}"
}
# Declare the data source
data "aws_availability_zones" "available" {}
resource "aws_vpc" "vpc" {
cidr_block = "${var.vpc_cidr}"
enable_dns_support = true
enable_dns_hostnames = true
tags {
Name = "${var.vpc_name}"
}
}
data "aws_ami" "coreos_ami" {
most_recent = true
filter {
name = "name"
values = ["CoreOS-stable-*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "owner-id"
values = ["190570271432"]
}
}
resource "aws_instance" "bastion" {
# 1st available AZ
availability_zone = "${data.aws_availability_zones.available.names[0]}"
ami = "${data.aws_ami.coreos_ami.image_id}"
instance_type = "${var.instance_type}"
subnet_id = "${aws_subnet.pub_subnet_generic.id}"
vpc_security_group_ids = ["${compact(concat(list(aws_security_group.powerdns.id), list(aws_security_group.vpn_sg.id)))}"]
source_dest_check = false
key_name = "${var.ssh_key}"
user_data = "${data.ignition_config.main.rendered}"
depends_on = ["aws_eip.ovpn_eip"]
tags {
Name = "${var.vpc_name}-server"
}
}
data "ignition_config" "main" {
files = ["${data.ignition_file.nginx_conf.id}"]
systemd = ["${compact(list(
data.ignition_systemd_unit.gateway_service.id,
data.ignition_systemd_unit.nginx_service.id,
data.ignition_systemd_unit.openvpn_service.id,
data.ignition_systemd_unit.powerdns_service.id,
data.ignition_systemd_unit.update-engine.id,
data.ignition_systemd_unit.locksmithd.id,
))}"]
}
data "ignition_systemd_unit" "update-engine" {
name = "update-engine.service"
mask = true
}
data "ignition_systemd_unit" "locksmithd" {
name = "locksmithd.service"
mask = true
}
# IGW
resource "aws_internet_gateway" "igw" {
vpc_id = "${aws_vpc.vpc.id}"
tags {
Name = "${var.vpc_name}-igw"
}
}
# General purpose public subnet. used for OVPN access and IGW/NAT attachment.
resource "aws_subnet" "pub_subnet_generic" {
vpc_id = "${aws_vpc.vpc.id}"
# 1st available AZ
availability_zone = "${data.aws_availability_zones.available.names[0]}"
cidr_block = "10.0.255.0/24"
map_public_ip_on_launch = true
tags {
Name = "${var.vpc_name}-vpn"
}
}
resource "aws_route_table_association" "pub_subnet_generic" {
subnet_id = "${aws_subnet.pub_subnet_generic.id}"
route_table_id = "${aws_route_table.pub_rt.id}"
}
# public subnet route table
resource "aws_route_table" "pub_rt" {
vpc_id = "${aws_vpc.vpc.id}"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.igw.id}"
}
tags {
Name = "${var.vpc_name}-public"
}
}
# private subnets
resource "aws_subnet" "priv_subnet" {
count = "${var.subnet_count}"
vpc_id = "${aws_vpc.vpc.id}"
availability_zone = "${element(data.aws_availability_zones.available.names, count.index)}"
cidr_block = "${cidrsubnet(var.vpc_cidr, 8, count.index + 100)}"
tags {
Name = "${var.vpc_name}-${count.index}"
}
}
resource "aws_route_table_association" "priv_subnet" {
count = "${var.subnet_count}"
subnet_id = "${aws_subnet.priv_subnet.*.id[count.index]}"
route_table_id = "${aws_route_table.priv_rt.id}"
}
# private subnet route table
resource "aws_route_table" "priv_rt" {
vpc_id = "${aws_vpc.vpc.id}"
propagating_vgws = ["${aws_vpn_gateway.vpg.id}"]
route {
cidr_block = "0.0.0.0/0"
instance_id = "${aws_instance.bastion.id}"
}
route {
cidr_block = "${var.local_network_cidr}"
gateway_id = "${aws_vpn_gateway.vpg.id}"
}
tags {
Name = "${var.vpc_name}-private"
}
}

View File

@@ -0,0 +1,74 @@
# Security Group
resource "aws_security_group" "powerdns" {
vpc_id = "${aws_vpc.vpc.id}"
}
resource "aws_security_group_rule" "powerdns_egress" {
type = "egress"
security_group_id = "${aws_security_group.powerdns.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "powerdns_ingress_ssh" {
type = "ingress"
security_group_id = "${aws_security_group.powerdns.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 22
to_port = 22
}
resource "aws_security_group_rule" "powerdns_ingress_http" {
type = "ingress"
security_group_id = "${aws_security_group.powerdns.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
}
resource "aws_security_group_rule" "powerdns_ingress_https" {
type = "ingress"
security_group_id = "${aws_security_group.powerdns.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
}
resource "aws_security_group_rule" "powerdns_ingress_api" {
type = "ingress"
security_group_id = "${aws_security_group.powerdns.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 8081
to_port = 8081
}
resource "aws_security_group_rule" "powerdns_ingress_dns" {
type = "ingress"
security_group_id = "${aws_security_group.powerdns.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 53
to_port = 53
}
resource "aws_security_group_rule" "powerdns_ingress_dns_udp" {
type = "ingress"
security_group_id = "${aws_security_group.powerdns.id}"
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 53
to_port = 53
}

View File

@@ -0,0 +1,76 @@
data "template_file" "gateway_service" {
template = "${file("${path.module}/resources/gateway.service")}"
vars {
private_cidr = "${cidrsubnet(var.vpc_cidr, 6, 25)}"
}
}
data "ignition_systemd_unit" "gateway_service" {
name = "gateway.service"
enabled = true
content = "${data.template_file.gateway_service.rendered}"
}
data "template_file" "nginx_service" {
template = "${file("${path.module}/resources/nginx.service")}"
vars {
username = "${var.nginx_username}"
password = "${var.nginx_password}"
nginx_image = "${var.container_images["nginx"]}"
}
}
data "ignition_systemd_unit" "nginx_service" {
name = "nginx.service"
enabled = true
content = "${data.template_file.nginx_service.rendered}"
}
data "template_file" "nginx_conf" {
template = "${file("${path.module}/resources/nginx.conf")}"
}
data "ignition_file" "nginx_conf" {
filesystem = "root"
path = "/home/core/nginx-config/default.conf"
mode = 0644
content {
content = "${data.template_file.nginx_conf.rendered}"
}
}
data "template_file" "openvpn_service" {
template = "${file("${path.module}/resources/openvpn.service")}"
vars {
ip = "${aws_eip.ovpn_eip.public_ip}"
openvpn_image = "${var.container_images["openvpn"]}"
}
}
data "ignition_systemd_unit" "openvpn_service" {
name = "openvpn.service"
enabled = true
content = "${data.template_file.openvpn_service.rendered}"
}
data "template_file" "powerdns_service" {
template = "${file("${path.module}/resources/powerdns.service")}"
vars {
dns_zone = "${var.base_domain}"
pdns_api_key = "${var.pdns_api_key}"
mysql_password = "${var.mysql_password}"
powerdns_image = "${var.container_images["powerdns"]}"
mysql_image = "${var.container_images["mysql"]}"
}
}
data "ignition_systemd_unit" "powerdns_service" {
name = "powerdns.service"
enabled = true
content = "${data.template_file.powerdns_service.rendered}"
}

View File

@@ -0,0 +1,95 @@
# placeholders for access_key / secret_key
# should be fed through env var or variable file
# https://www.terraform.io/docs/configuration/variables.html
variable "vpc_name" {
description = "The name of the VPC to identify created resources."
default = "bastion"
}
variable "instance_type" {
description = "The type of the ec2 machine."
default = "t2.micro"
}
variable "base_domain" {
default = "tectonic-ci.de"
description = "The base domain for this cluster's FQDN"
}
variable "vpc_aws_region" {
description = "The target AWS region for the cluster"
default = "us-gov-west-1"
}
variable "vpc_cidr" {
default = "10.0.0.0/16"
description = "The CIDR range used for your entire VPC"
}
variable "subnet_count" {
default = 4
description = "Number of private subnets to pre-create"
}
variable "local_network_cidr" {
default = "10.7.0.0/16"
description = "IP range in the network your laptop is on (dosn't actually matter unless your instances need to connect to the local network your laptop is on)"
}
variable "ssh_key" {
description = "Name of an SSH key located within the AWS region. Example: coreos-user."
default = ""
}
variable "nginx_username" {
description = "Used for retrieving the OpenVPN client config file."
}
variable "nginx_password" {
description = "Used for retrieving the OpenVPN client config file."
}
variable "mysql_password" {
description = "Used as PowerDNS backend."
}
variable "pdns_api_key" {
description = "Used by clients to communicate with the PowerDNS API."
}
variable "container_images" {
description = "Container images to use"
type = "map"
default = {
powerdns = "quay.io/coreos/pdns:20678f8bffc316579367d885ca4fcb229b1dbc1d"
mysql = "quay.io/coreos/mysql:5.7.21"
openvpn = "quay.io/coreos/openvpn:2.4"
nginx = "quay.io/coreos/nginx:1.13.7-alpine"
}
}
output "ovpn_url" {
value = "http://${aws_eip.ovpn_eip.public_ip}"
}
output "base_domain" {
value = "${var.base_domain}"
}
output "vpc_id" {
value = "${aws_vpc.vpc.id}"
}
output "vpc_dns_ip" {
value = "${aws_instance.bastion.private_ip}"
}
output "dns_api_url" {
value = "http://${aws_instance.bastion.private_ip}:8081"
}
output "subnets" {
value = "${aws_subnet.priv_subnet.*.id}"
}

View File

@@ -0,0 +1,108 @@
resource "aws_vpn_gateway" "vpg" {
vpc_id = "${aws_vpc.vpc.id}"
# 1st available AZ
availability_zone = "${data.aws_availability_zones.available.names[0]}"
tags {
Name = "${var.vpc_name}-vpg"
}
}
resource "aws_eip" "ovpn_eip" {
vpc = true
}
resource "aws_eip_association" "vpn_eip_assoc" {
instance_id = "${aws_instance.bastion.id}"
allocation_id = "${aws_eip.ovpn_eip.id}"
}
resource "aws_security_group" "vpn_sg" {
name = "ovpn-server-sg"
description = "Allow all inbound traffic"
vpc_id = "${aws_vpc.vpc.id}"
ingress {
from_port = 0
to_port = 65535
protocol = "tcp"
cidr_blocks = ["${cidrsubnet(var.vpc_cidr, 6, 25)}"]
}
ingress {
from_port = 943
to_port = 943
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 943
to_port = 943
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 1194
to_port = 1194
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
# all
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags {
Name = "${var.vpc_name}-ovpn-sg"
}
}
resource "aws_customer_gateway" "customer_gateway" {
bgp_asn = 65000
ip_address = "${aws_eip.ovpn_eip.public_ip}"
type = "ipsec.1"
tags {
Name = "${var.vpc_name}-customer-gateway"
}
}
resource "aws_vpn_connection" "main" {
vpn_gateway_id = "${aws_vpn_gateway.vpg.id}"
customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}"
type = "ipsec.1"
static_routes_only = true
tags {
Name = "${var.vpc_name}-vpn-conn"
}
}

View File

@@ -0,0 +1,118 @@
provider "aws" {
region = "${var.vpc_aws_region}"
}
# Declare the data source
data "aws_availability_zones" "available" {}
resource "aws_vpc" "vpc" {
cidr_block = "${var.vpc_cidr}"
enable_dns_support = true
enable_dns_hostnames = true
tags {
Name = "${var.vpc_name}"
}
}
# Private DNS zone
resource "aws_route53_zone" "priv_zone" {
name = "${var.base_domain}"
vpc_id = "${aws_vpc.vpc.id}"
comment = "Managed by Terraform"
tags {
Name = "${var.vpc_name}"
}
}
# IGW
resource "aws_internet_gateway" "igw" {
vpc_id = "${aws_vpc.vpc.id}"
tags {
Name = "${var.vpc_name}-igw"
}
}
# NAT Gateway
resource "aws_eip" "natgw" {
vpc = true
}
resource "aws_nat_gateway" "natgw" {
allocation_id = "${aws_eip.natgw.id}"
subnet_id = "${aws_subnet.pub_subnet_generic.id}"
depends_on = ["aws_internet_gateway.igw"]
}
# General purpose public subnet. used for OVPN access and IGW/NAT attachment.
resource "aws_subnet" "pub_subnet_generic" {
vpc_id = "${aws_vpc.vpc.id}"
# 1st available AZ
availability_zone = "${data.aws_availability_zones.available.names[0]}"
cidr_block = "10.0.255.0/24"
map_public_ip_on_launch = true
tags {
Name = "${var.vpc_name}-vpn"
}
}
resource "aws_route_table_association" "pub_subnet_generic" {
subnet_id = "${aws_subnet.pub_subnet_generic.id}"
route_table_id = "${aws_route_table.pub_rt.id}"
}
# public subnet route table
resource "aws_route_table" "pub_rt" {
vpc_id = "${aws_vpc.vpc.id}"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.igw.id}"
}
tags {
Name = "${var.vpc_name}-public"
}
}
# private subnets
resource "aws_subnet" "priv_subnet" {
count = "${var.subnet_count}"
vpc_id = "${aws_vpc.vpc.id}"
availability_zone = "${element(data.aws_availability_zones.available.names, count.index)}"
cidr_block = "${cidrsubnet(var.vpc_cidr, 8, count.index + 100)}"
tags {
Name = "${var.vpc_name}-${count.index}"
}
}
resource "aws_route_table_association" "priv_subnet" {
count = "${var.subnet_count}"
subnet_id = "${aws_subnet.priv_subnet.*.id[count.index]}"
route_table_id = "${aws_route_table.priv_rt.id}"
}
# private subnet route table
resource "aws_route_table" "priv_rt" {
vpc_id = "${aws_vpc.vpc.id}"
propagating_vgws = ["${aws_vpn_gateway.vpg.id}"]
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = "${aws_nat_gateway.natgw.id}"
}
route {
cidr_block = "${var.local_network_cidr}"
gateway_id = "${aws_vpn_gateway.vpg.id}"
}
tags {
Name = "${var.vpc_name}-private"
}
}

View File

@@ -0,0 +1,60 @@
# placeholders for access_key / secret_key
# should be fed through env var or variable file
# https://www.terraform.io/docs/configuration/variables.html
variable vpc_name {
description = "The name of the VPC to identify created resources."
}
variable base_domain {
default = "tectonic-ci.de"
description = "The base domain for this cluster's FQDN"
}
variable vpc_aws_region {
description = "The target AWS region for the cluster"
}
variable vpc_cidr {
default = "10.0.0.0/16"
description = "The CIDR range used for your entire VPC"
}
variable subnet_count {
default = 4
description = "Number of private subnets to pre-create"
}
variable local_network_cidr {
default = "10.7.0.0/16"
description = "IP range in the network your laptop is on (dosn't actually matter unless your instances need to connect to the local network your laptop is on)"
}
variable ovpn_password {
default = "PASSWORD"
description = "password to use when connecting"
}
output "ovpn_url" {
value = "https://${aws_eip.ovpn_eip.public_ip}:443"
}
output "base_domain" {
value = "${var.base_domain}"
}
output "private_zone_id" {
value = "${aws_route53_zone.priv_zone.id}"
}
output "vpc_id" {
value = "${aws_vpc.vpc.id}"
}
output "vpc_dns" {
value = "${cidrhost(var.vpc_cidr, 2)}"
}
output "subnets" {
value = "${aws_subnet.priv_subnet.*.id}"
}

View File

@@ -0,0 +1,142 @@
# For details see https://docs.openvpn.net/how-to-tutorialsguides/virtual-platforms/amazon-ec2-appliance-ami-quick-start-guide
data "aws_ami" "openvpn_ami" {
most_recent = true
filter {
name = "name"
values = ["OpenVPN Access Server*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "owner-id"
values = ["679593333241"]
}
}
resource "aws_vpn_gateway" "vpg" {
vpc_id = "${aws_vpc.vpc.id}"
# 1st available AZ
availability_zone = "${data.aws_availability_zones.available.names[0]}"
tags {
Name = "${var.vpc_name}-vpg"
}
}
resource "aws_instance" "ovpn" {
# 1st available AZ
availability_zone = "${data.aws_availability_zones.available.names[0]}"
ami = "${data.aws_ami.openvpn_ami.image_id}"
instance_type = "t2.micro"
subnet_id = "${aws_subnet.pub_subnet_generic.id}"
vpc_security_group_ids = ["${aws_security_group.vpn_sg.id}"]
user_data = <<EOF
public_hostname=${aws_eip.ovpn_eip.public_ip}
admin_user=openvpn
admin_pw=${var.ovpn_password}
reroute_gw=1
reroute_dns=1
EOF
depends_on = ["aws_eip.ovpn_eip"]
tags {
Name = "${var.vpc_name}-ovpn-server"
}
}
resource "aws_eip" "ovpn_eip" {
vpc = true
}
resource "aws_eip_association" "vpn_eip_assoc" {
instance_id = "${aws_instance.ovpn.id}"
allocation_id = "${aws_eip.ovpn_eip.id}"
}
resource "aws_security_group" "vpn_sg" {
name = "ovpn-server-sg"
description = "Allow all inbound traffic"
vpc_id = "${aws_vpc.vpc.id}"
ingress {
from_port = 943
to_port = 943
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 943
to_port = 943
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 1194
to_port = 1194
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
# all
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags {
Name = "${var.vpc_name}-ovpn-sg"
}
}
resource "aws_customer_gateway" "customer_gateway" {
bgp_asn = 65000
ip_address = "${aws_eip.ovpn_eip.public_ip}"
type = "ipsec.1"
tags {
Name = "${var.vpc_name}-customer-gateway"
}
}
resource "aws_vpn_connection" "main" {
vpn_gateway_id = "${aws_vpn_gateway.vpg.id}"
customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}"
type = "ipsec.1"
static_routes_only = true
tags {
Name = "${var.vpc_name}-vpn-conn"
}
}

View File

@@ -0,0 +1,41 @@
{
"tectonic_admin_email": "admin@example.com",
"tectonic_admin_password": "password",
"tectonic_aws_etcd_ec2_type": "t2.medium",
"tectonic_aws_etcd_root_volume_size": 30,
"tectonic_aws_etcd_root_volume_type": "gp2",
"tectonic_aws_extra_tags": {
"test_tag": "testing"
},
"tectonic_aws_master_custom_subnets": {
"us-west-1a": "10.0.0.0/19",
"us-west-1c": "10.0.32.0/19"
},
"tectonic_aws_master_ec2_type": "t2.medium",
"tectonic_aws_master_root_volume_size": 30,
"tectonic_aws_master_root_volume_type": "gp2",
"tectonic_aws_private_endpoints": false,
"tectonic_aws_region": "us-west-1",
"tectonic_aws_ssh_key": "tectonic-jenkins",
"tectonic_aws_vpc_cidr_block": "10.0.0.0/16",
"tectonic_aws_worker_custom_subnets": {
"us-west-1a": "10.0.64.0/19",
"us-west-1c": "10.0.96.0/19"
},
"tectonic_aws_worker_ec2_type": "t2.medium",
"tectonic_aws_worker_root_volume_size": 30,
"tectonic_aws_worker_root_volume_type": "gp2",
"tectonic_base_domain": "tectonic.dev.coreos.systems",
"tectonic_cluster_cidr": "10.2.0.0/16",
"tectonic_cluster_name": "test",
"tectonic_dns_name": "test",
"tectonic_etcd_count": 3,
"tectonic_kube_apiserver_service_ip": "10.3.0.1",
"tectonic_kube_dns_service_ip": "10.3.0.10",
"tectonic_kube_etcd_service_ip": "10.3.0.15",
"tectonic_license_path": "./license.txt",
"tectonic_master_count": 3,
"tectonic_pull_secret_path": "./pull_secret.json",
"tectonic_service_cidr": "10.3.0.0/16",
"tectonic_worker_count": 3
}

View File

@@ -0,0 +1,44 @@
{
"tectonic_admin_email": "admin@example.com",
"tectonic_admin_password": "password",
"tectonic_base_domain": "unused",
"tectonic_cluster_cidr": "10.2.0.0/16",
"tectonic_cluster_name": "my-cluster",
"tectonic_container_linux_version": "1353.8.0",
"tectonic_dns_name": "",
"tectonic_kube_apiserver_service_ip": "10.3.0.1",
"tectonic_kube_dns_service_ip": "10.3.0.10",
"tectonic_kube_etcd_service_ip": "10.3.0.15",
"tectonic_license_path": "./license.txt",
"tectonic_metal_controller_domain": "cluster.example.com",
"tectonic_metal_controller_domains": [
"node1.example.com"
],
"tectonic_metal_controller_macs": [
"52:54:00:a1:9c:ae"
],
"tectonic_metal_controller_names": [
"node1"
],
"tectonic_metal_ingress_domain": "tectonic.example.com",
"tectonic_metal_matchbox_ca": "-----BEGIN CERTIFICATE-----\nMIIFDTCCAvWgAwIBAgIJAIuXq10k2OFlMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV\nBAMMB2Zha2UtY2EwHhcNMTcwMjAxMjIxMzI0WhcNMjcwMTMwMjIxMzI0WjASMRAw\nDgYDVQQDDAdmYWtlLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\nzzHsB56F6oZjsVBKzfpicsG+mVHQ/QzA4jqRCbQ8Zr12NtUZKnPUVwDoFf4WTfmy\nZ0u8Uv+6/B/8un3LGsIaJEugPfRboc2oZKJcqfMJSFfLb/wkmT0D/1HJR60ml/M5\nwpHeh4vQ7BhktNsK90EjdlLvr1GDfevXArnye5ksEInOSX9nXVsGPrm0AGSffhmY\nuUAjY8f9IspJa1j4vL6NI89GWO4jqME+SUnuI4SYIkuQJoSElofAIX2b5Tk3dFya\nVKmAq2L89teCMYsciPbFa/Z2HvDNZ7pC17Ow7zr1f+V5BU18h3cLk610YNPcEBw0\nf94+mePsmMSMjUM0f+NMFyDERF+pys60/3qqVWrJe/FkJM6NDCyWXXXAfTxIwLq0\nCVrlWALdTc+RMAPI2sxAdUp4BqAuek4SjIg3FuoJrBs3EAUPfybclJ7g3HJwyXM2\n3WIe10BnSk+rGzd4KMVbYw5/nM8Nc/Y20R2an/vVZn6xTxs9o6hhEHF7d5iws6Bi\n7/jv+jdZhLG8b3sG6Tj7a7YdvKWqH/mSPFlc/sevYOjR7NKYRMwGnl0d9qf+Xe5V\nxyH1llIXPs6+y1B4tRyL/tulyeVqi25+I4QVAYypxWU8CPyw7tsSdOsSTbeGTmXj\nehelY/BCjAqAcexL7oRV7dy7VZ1Ezg6zQRwMt0Tar90CAwEAAaNmMGQwHQYDVR0O\nBBYEFNGPoXTjJnHjG2zMpjSg/9vNO/trMB8GA1UdIwQYMBaAFNGPoXTjJnHjG2zM\npjSg/9vNO/trMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0G\nCSqGSIb3DQEBCwUAA4ICAQC9V/0iiEZYHz7xbezHpeGHwmecH5oylEvAeCcN10gx\nHFvUN+XMyBaPqN7iRtx/rSqyp2iN2AK1Cdn1viOSRc09lwPiuj9V4diSDyPwJWxd\n60gqd5E9F9gQXlenWoIdm7kW8Lo8HLfx8ItYKGpE51JUctTmGY5WURRmBlVKr1LA\nhbVsAWBaGQfPyW1CrFcxxc5mCABxWOxjRjLw8A8c5IXD0Q5C5pRd0BckBHKTdl40\nowm893oPEQcu/1C432T4vIddVh1Ktq1pd7O/9BPYOaPryzf7076xSwZ0bSuBUGRq\nVd3STfu5QRqpMv4dIrhqRofmIUzjOHLRX8Lx2pzgYcMgMQ8O+jM+ETrYD6rsDoLQ\nuiVSWZK0YFndKzNTA04u57arRumWKqqfS0kkDFayumyv6KaDS6YZdsqSRmaiLAOG\nF6jchpUtkDhDY0v/Y7jESUneT0hRnqNMPAKJMNhE4hS+1qkcP/ikQQgZl/OWma1z\nHUyBGT4OGP2T3JIfq12Z4vC5FGVD4aD/frTvPMlifV3i8lKlYZs271JPXUo6ASIA\nZSBpV5QilOlE25Q5Lcw0yWmN4KwxqBL9bJ5W9D1I0qhWxaMF78m+8vLIFv+dAylE\nOd27a+1We/P5ey7WRlwCfuEcFV7nYS/qMykYdQ9fxHSPgTPlrGrSwKstaaIIqOkE\nkA==\n-----END CERTIFICATE-----\n",
"tectonic_metal_matchbox_client_cert": "-----BEGIN CERTIFICATE-----\nMIIEYDCCAkigAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHZmFr\nZS1jYTAeFw0xNzAyMDEyMjEzMjVaFw0xODAyMDEyMjEzMjVaMBYxFDASBgNVBAMM\nC2Zha2UtY2xpZW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr8S7\nx/tAS6W+aRW3X833OvNfxXjUJAiRkUV85Raln7tqVcTG/9iyRhWgNpUn/WU1/3qV\nobto4ZCURIwoQh0kWk8io1lafZJ+S6Znm3+0TKo7u6QMavolJyetsOQkT/bIoZ73\n09fhk4Vu9GILjtZtxV7GDb4WqR9R7z77nYTdHMio/BQVk+Xg6rkOsMRyoR+B9JHG\nn9mvXLZSi8Q+3ABtsN6flPt7mTkhFFFvTgWxtzgVbeORT/uFxIV/IMjtGseUIzvF\nGUQP6KCyCJb3Kp4rxSxIbi35mFqEWXjB7BVT/0pjx1mc5tSvGuFl7G4N/MmGe3Zq\nZCF4FalpiPGAInKrWQIDAQABo4G7MIG4MAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEB\nBAQDAgeAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBDbGllbnQg\nQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNZOj+0OOvhOFEtGGriZrPVCSzc3MB8GA1Ud\nIwQYMBaAFNGPoXTjJnHjG2zMpjSg/9vNO/trMA4GA1UdDwEB/wQEAwIF4DATBgNV\nHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAgEAiiGHlmPI6RlJQq7/\nz/1i0vFArDbnc2mwBf3pqrDPyqx1EBx7V3Tsm38TNMZyHaz0IyPUDvRPn10UYXui\n2ZGseauwU/PmvFNofxVbG0Dc55lOoxl31520K0h9cWxVHcYzUxPndQ1pltYkXiMm\n/596LHkJ+unMJszDVhAIOmc0PgECtGH1VG6EoTTFlMu7VJekKInkYNow4Q6cAVcr\n11F4meOs0DMZgzfeUjSnsKG7KsLHfr5bLw6FEEzobgtI2sXVMOJi+ypd3zTY+ACq\noRt6wkRFCUoEgap7SG6B2TwHPGe15VIFZJtcnOZqHdrnfJLVROPnA4dYhJVJj1v1\n9JFH/T6EIi6nIqnrlX+10zaatpzq2+AFX8LiWpr7C7S99LgH3cnFdssfmlqoG82t\n3BshYpDrIw1f72zy8+RCkK52OdjNpDoVwubwz6i8jldzoENqmsioyetyaVfe9GGH\nUdEPrUZ4BHLeGPjHclOPVEhjVBZuofQ/GgM2gmCUdn5tcVLjnIeLAv/sQXwkMxIe\n4m9QcPrxVAKOlDr9LhB0mVPr2kfc4yI/wYWEe+CniwcuvxJiOmjsyrENxfaFY30r\nQspTSDVt8hVfVISzpuEchtLVjuRO/ESpmeOF1rRTc1qL/CjetmidkedDm64EZjyK\njyXQv9IZPMTwOndF6AVLH7l1F0E=\n-----END CERTIFICATE-----\n",
"tectonic_metal_matchbox_client_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAr8S7x/tAS6W+aRW3X833OvNfxXjUJAiRkUV85Raln7tqVcTG\n/9iyRhWgNpUn/WU1/3qVobto4ZCURIwoQh0kWk8io1lafZJ+S6Znm3+0TKo7u6QM\navolJyetsOQkT/bIoZ7309fhk4Vu9GILjtZtxV7GDb4WqR9R7z77nYTdHMio/BQV\nk+Xg6rkOsMRyoR+B9JHGn9mvXLZSi8Q+3ABtsN6flPt7mTkhFFFvTgWxtzgVbeOR\nT/uFxIV/IMjtGseUIzvFGUQP6KCyCJb3Kp4rxSxIbi35mFqEWXjB7BVT/0pjx1mc\n5tSvGuFl7G4N/MmGe3ZqZCF4FalpiPGAInKrWQIDAQABAoIBAQCR/OQ+0JdxfWNu\nYqQhBbA/nV7BZH9GwnstXrrCiBHeXsqOHFdwruo7PcEJNM+3LnYwEP/xCfityOjt\nGkBh0VSdUbciV5fKTn9pk/ff9qypNIdSbYoG3Gc5Y0JndsYWSJIRczjCEj+AyMYE\nYt7Yr48S7ImxZl3p8GKcRQK1rWH9geg4cyCPisbaDSfjJbYh5yLk/2wsxGBRM3gg\nCyJEbkJ/v107a1iThTGBgEgnFPP+FqZ2jlnfhBPVzuYggYyiMJuNtgDl7Vi7NLBe\n2ueqq1UAT9LCpZNLJ8eYiDuyNHZtA7a2r3O/jTR4cvQy1xEjD3h4Es7olkAf/Lzu\n6wuggbllAoGBANcqZyJtVxkGwHV9CWTWniTT7BNQ2ehYErkNKggMXl2AzOqEKzqn\nIDRoBhiJKeAphdw/ccvqUEm9bUJD2QLpTJuMmUBkOwqMhATBXFrFCBX4PzGHYnC8\n6hEXjoUE6XhKdJEOgXTqrt31HDgj13GwAp/2DnsscFkC9co5+IW68sUjAoGBANEg\nQvZYdI4Me6JxLXotyirpo57xjocvlo+uffws/YwBH8nK/op6am69zzMMOgUYA5Li\n00WzfEXoyO+BdcbH28xYdBZT0CTkGlPM8IHuH+d/AwnEurxUElWZRRXSz6g17siM\nKjBodqI8h+jQiQJuJ/zBJbOm3bUbpIt1Z+ROjstTAoGAWdAdVMWHQa8Lzv7uWOUt\nBfpf5IAvNUjuJ8hS7yEakrUc1BdvZAA29Skmwj8e967dbV4eRhv8f4tOfAaOIyT3\nEUbTAYnVC0Y0JTgBMPJluaXx2t7EPILewVuv5d5zBf8uQQ5pA0Ci1YtmyBhN6eqq\nbdLroIagLseJiWxBTLEIfTkCgYEAjikXPC2fdhzoQuIbHy5Xe1p+PwNId3+TIzNk\nM3RGG9F70YqsBGj5RzTC0JnkKyhK7aRCKOS9eyymw6HG9Y1RTpVmvPLW0O07NHJh\noIHGsHD4GMDijDm+iO/7Nb2sKlYXb79Qwr2Qv/LUFSEFsmA90KVgQsMRfhc/gQob\nyOjaSz8CgYEAwr3aYp1CkKBXeUTNioLbyymhA4RqGPH/69F1NQ7froLXb152SzOV\njWcrt4ogRacgHb8thuTedrjUiJJLoWhQ3KqzSA2pI3tTLIxrJePiMMpt1Xb2z9l6\nPikk0rvNVB/vrPeVjAdGY9TJC/vpz3om92DRDmUifu8rCFxIHE0GrQ0=\n-----END RSA PRIVATE KEY-----\n",
"tectonic_metal_matchbox_http_url": "http://matchbox.example.com:8080",
"tectonic_metal_matchbox_rpc_endpoint": "matchbox.example.com:8081",
"tectonic_metal_worker_domains": [
"node2.example.com",
"node3.example.com"
],
"tectonic_metal_worker_macs": [
"52:54:00:b2:2f:86",
"52:54:00:c3:61:77"
],
"tectonic_metal_worker_names": [
"node2",
"node3"
],
"tectonic_pull_secret_path": "./pull_secret.json",
"tectonic_service_cidr": "10.3.0.0/16",
"tectonic_ssh_authorized_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCt3BebCHqnSsgpLjo4kVvyfY/z2BS8t27r/7du+O2pb4xYkr7n+KFpbOz523vMTpQ+o1jY4u4TgexglyT9nqasWgLOvo1qjD1agHme8LlTPQSk07rXqOB85Uq5p7ig2zoOejF6qXhcc3n1c7+HkxHrgpBENjLVHOBpzPBIAHkAGaZcl07OCqbsG5yxqEmSGiAlh/IiUVOZgdDMaGjCRFy0wk0mQaGD66DmnFc1H5CzcPjsxr0qO65e7lTGsE930KkO1Vc+RHCVwvhdXs+c2NhJ2/3740Kpes9n1/YullaWZUzlCPDXtRuy6JRbFbvy39JUgHWGWzB3d+3f8oJ/N4qZ cardno:000603633110"
}

View File

@@ -0,0 +1,20 @@
locals {
ignition_etcd_keys = ["ignition_etcd_0.json", "ignition_etcd_1.json", "ignition_etcd_2.json"]
}
data "ignition_config" "tnc" {
count = "${var.instance_count}"
append {
source = "${format("http://${var.cluster_name}-tnc.${var.base_domain}/config/etcd?etcd_index=%d", count.index)}"
# TODO: add verification
}
# Used for loading certificates
append {
source = "${format("s3://%s/%s", var.s3_bucket, local.ignition_etcd_keys[count.index])}"
# TODO: add verification
}
}

View File

@@ -0,0 +1,38 @@
data "ignition_config" "etcd" {
count = "${length(var.external_endpoints) == 0 ? var.instance_count : 0}"
systemd = [
"${data.ignition_systemd_unit.locksmithd.*.id[count.index]}",
"${var.ign_etcd_dropin_id_list[count.index]}",
]
files = ["${compact(list(
var.ign_profile_env_id,
var.ign_systemd_default_env_id,
))}",
"${var.ign_etcd_crt_id_list}",
"${var.ign_ntp_dropin_id}",
]
}
data "ignition_systemd_unit" "locksmithd" {
count = "${length(var.external_endpoints) == 0 ? var.instance_count : 0}"
name = "locksmithd.service"
enabled = true
dropin = [
{
name = "40-etcd-lock.conf"
content = <<EOF
[Service]
Environment=REBOOT_STRATEGY=etcd-lock
${var.tls_enabled ? "Environment=\"LOCKSMITHD_ETCD_CAFILE=/etc/ssl/etcd/ca.crt\"" : ""}
${var.tls_enabled ? "Environment=\"LOCKSMITHD_ETCD_KEYFILE=/etc/ssl/etcd/client.key\"" : ""}
${var.tls_enabled ? "Environment=\"LOCKSMITHD_ETCD_CERTFILE=/etc/ssl/etcd/client.crt\"" : ""}
Environment="LOCKSMITHD_ENDPOINT=${var.tls_enabled ? "https" : "http"}://${var.cluster_name}-etcd-${count.index}.${var.base_domain}:2379"
EOF
},
]
}

View File

@@ -0,0 +1,25 @@
resource "aws_s3_bucket_object" "ignition_etcd" {
count = "${length(var.external_endpoints) == 0 ? var.instance_count : 0}"
bucket = "${var.s3_bucket}"
key = "ignition_etcd_${count.index}.json"
content = "${data.ignition_config.etcd.*.rendered[count.index]}"
acl = "private"
server_side_encryption = "AES256"
tags = "${merge(map(
"Name", "${var.cluster_name}-ignition-etcd-${count.index}",
"KubernetesCluster", "${var.cluster_name}",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
data "ignition_config" "s3" {
count = "${length(var.external_endpoints) == 0 ? var.instance_count : 0}"
replace {
source = "${format("s3://%s/%s", var.s3_bucket, aws_s3_bucket_object.ignition_etcd.*.key[count.index])}"
verification = "sha512-${sha512(data.ignition_config.etcd.*.rendered[count.index])}"
}
}

View File

@@ -0,0 +1,135 @@
locals {
ami_owner = "595879546273"
arn = "aws"
}
data "aws_ami" "coreos_ami" {
filter {
name = "name"
values = ["CoreOS-${var.container_linux_channel}-${var.container_linux_version}-*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "owner-id"
values = ["${local.ami_owner}"]
}
}
resource "aws_iam_instance_profile" "etcd" {
name = "${var.cluster_name}-etcd-profile"
role = "${var.etcd_iam_role == "" ?
join("|", aws_iam_role.etcd_role.*.name) :
join("|", data.aws_iam_role.etcd_role.*.name)
}"
}
data "aws_iam_role" "etcd_role" {
count = "${var.etcd_iam_role == "" ? 0 : 1}"
name = "${var.etcd_iam_role}"
}
resource "aws_iam_role" "etcd_role" {
count = "${var.etcd_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}-etcd-role"
path = "/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "etcd" {
count = "${var.etcd_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}_etcd_policy"
role = "${aws_iam_role.etcd_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:Describe*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:AttachVolume",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:DetachVolume",
"Resource": "*"
},
{
"Action" : [
"s3:GetObject"
],
"Resource": "arn:${local.arn}:s3:::*",
"Effect": "Allow"
}
]
}
EOF
}
resource "aws_instance" "etcd_node" {
count = "${var.instance_count}"
ami = "${coalesce(var.ec2_ami, data.aws_ami.coreos_ami.image_id)}"
iam_instance_profile = "${aws_iam_instance_profile.etcd.name}"
instance_type = "${var.ec2_type}"
key_name = "${var.ssh_key}"
subnet_id = "${element(var.subnets, count.index)}"
user_data = "${data.ignition_config.tnc.*.rendered[count.index]}"
vpc_security_group_ids = ["${var.sg_ids}"]
lifecycle {
# Ignore changes in the AMI which force recreation of the resource. This
# avoids accidental deletion of nodes whenever a new CoreOS Release comes
# out.
ignore_changes = ["ami"]
}
tags = "${merge(map(
"Name", "${var.cluster_name}-etcd-${count.index}",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
root_block_device {
volume_type = "${var.root_volume_type}"
volume_size = "${var.root_volume_size}"
iops = "${var.root_volume_type == "io1" ? var.root_volume_iops : var.root_volume_type == "gp2" ? min(10000, max(100, 3 * var.root_volume_size)) : 0}"
}
volume_tags = "${merge(map(
"Name", "${var.cluster_name}-etcd-${count.index}-vol",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}

View File

@@ -0,0 +1,145 @@
locals {
ami_owner = "595879546273"
arn = "aws"
}
data "aws_ami" "coreos_ami" {
filter {
name = "name"
values = ["CoreOS-${var.container_linux_channel}-${var.container_linux_version}-*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "owner-id"
values = ["${local.ami_owner}"]
}
}
resource "aws_iam_instance_profile" "etcd" {
count = "${length(var.external_endpoints) == 0 ? 1 : 0}"
name = "${var.cluster_name}-etcd-profile"
role = "${var.etcd_iam_role == "" ?
join("|", aws_iam_role.etcd_role.*.name) :
join("|", data.aws_iam_role.etcd_role.*.name)
}"
}
data "aws_iam_role" "etcd_role" {
count = "${var.etcd_iam_role == "" ? 0 : 1}"
name = "${var.etcd_iam_role}"
}
resource "aws_iam_role" "etcd_role" {
count = "${length(var.external_endpoints) == 0 && var.etcd_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}-etcd-role"
path = "/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "etcd" {
count = "${var.etcd_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}_etcd_policy"
role = "${aws_iam_role.etcd_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:Describe*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:AttachVolume",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:DetachVolume",
"Resource": "*"
},
{
"Action": [
"ecr:DescribeRepositories",
"ecr:ListImages",
"ecr:BatchGetImage"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action" : [
"s3:GetObject"
],
"Resource": "arn:${local.arn}:s3:::*",
"Effect": "Allow"
}
]
}
EOF
}
resource "aws_instance" "etcd_node" {
count = "${length(var.external_endpoints) == 0 ? var.instance_count : 0}"
ami = "${coalesce(var.ec2_ami, data.aws_ami.coreos_ami.image_id)}"
iam_instance_profile = "${aws_iam_instance_profile.etcd.name}"
instance_type = "${var.ec2_type}"
key_name = "${var.ssh_key}"
subnet_id = "${element(var.subnets, count.index)}"
user_data = "${data.ignition_config.s3.*.rendered[count.index]}"
vpc_security_group_ids = ["${var.sg_ids}"]
lifecycle {
# Ignore changes in the AMI which force recreation of the resource. This
# avoids accidental deletion of nodes whenever a new CoreOS Release comes
# out.
ignore_changes = ["ami"]
}
tags = "${merge(map(
"Name", "${var.cluster_name}-etcd-${count.index}",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
root_block_device {
volume_type = "${var.root_volume_type}"
volume_size = "${var.root_volume_size}"
iops = "${var.root_volume_type == "io1" ? var.root_volume_iops : var.root_volume_type == "gp2" ? min(10000, max(100, 3 * var.root_volume_size)) : 0}"
}
volume_tags = "${merge(map(
"Name", "${var.cluster_name}-etcd-${count.index}-vol",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}

View File

@@ -0,0 +1,3 @@
output "ip_addresses" {
value = "${aws_instance.etcd_node.*.private_ip}"
}

View File

@@ -0,0 +1,3 @@
output "ip_addresses" {
value = "${aws_instance.etcd_node.*.private_ip}"
}

View File

@@ -0,0 +1,86 @@
variable "base_domain" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
variable "cluster_name" {
type = "string"
}
variable "container_linux_channel" {
type = "string"
}
variable "container_linux_version" {
type = "string"
}
variable "instance_count" {
default = "3"
}
variable "ssh_key" {
type = "string"
}
variable "subnets" {
type = "list"
}
variable "container_image" {
type = "string"
}
variable "ec2_type" {
type = "string"
}
variable "ec2_ami" {
type = "string"
default = ""
}
variable "extra_tags" {
description = "Extra AWS tags to be applied to created resources."
type = "map"
default = {}
}
variable "root_volume_type" {
type = "string"
description = "The type of volume for the root block device."
}
variable "root_volume_size" {
type = "string"
description = "The size of the volume in gigabytes for the root block device."
}
variable "root_volume_iops" {
type = "string"
default = "100"
description = "The amount of provisioned IOPS for the root block device."
}
variable "sg_ids" {
type = "list"
description = "The security group IDs to be applied."
}
variable "s3_bucket" {
type = "string"
}
variable "etcd_iam_role" {
type = "string"
default = ""
description = "IAM role to use for the instance profiles of etcd nodes."
}
variable "dns_server_ip" {
type = "string"
default = ""
}

View File

@@ -0,0 +1,111 @@
variable "base_domain" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
variable "cluster_name" {
type = "string"
}
variable "container_linux_channel" {
type = "string"
}
variable "container_linux_version" {
type = "string"
}
variable "instance_count" {
default = "3"
}
variable "ssh_key" {
type = "string"
}
variable "subnets" {
type = "list"
}
variable "external_endpoints" {
type = "list"
}
variable "container_image" {
type = "string"
}
variable "ec2_type" {
type = "string"
}
variable "ec2_ami" {
type = "string"
default = ""
}
variable "extra_tags" {
description = "Extra AWS tags to be applied to created resources."
type = "map"
default = {}
}
variable "root_volume_type" {
type = "string"
description = "The type of volume for the root block device."
}
variable "root_volume_size" {
type = "string"
description = "The size of the volume in gigabytes for the root block device."
}
variable "root_volume_iops" {
type = "string"
default = "100"
description = "The amount of provisioned IOPS for the root block device."
}
variable "sg_ids" {
type = "list"
description = "The security group IDs to be applied."
}
variable "tls_enabled" {
default = false
}
variable "ign_etcd_dropin_id_list" {
type = "list"
}
variable "s3_bucket" {
type = "string"
}
variable "ign_etcd_crt_id_list" {
type = "list"
}
variable "etcd_iam_role" {
type = "string"
default = ""
description = "IAM role to use for the instance profiles of etcd nodes."
}
variable "ign_profile_env_id" {
type = "string"
default = ""
}
variable "ign_systemd_default_env_id" {
type = "string"
default = ""
}
variable "ign_ntp_dropin_id" {
type = "string"
}

View File

@@ -0,0 +1,91 @@
data "ignition_config" "main" {
files = ["${compact(list(
data.ignition_file.detect_master.id,
data.ignition_file.init_assets.id,
data.ignition_file.rm_assets.id,
var.ign_installer_kubelet_env_id,
var.ign_installer_runtime_mappings_id,
var.ign_max_user_watches_id,
var.ign_nfs_config_id,
var.ign_ntp_dropin_id,
var.ign_profile_env_id,
var.ign_s3_puller_id,
var.ign_systemd_default_env_id,
))}",
"${var.ign_ca_cert_id_list}",
]
systemd = ["${compact(list(
var.ign_bootkube_path_unit_id,
var.ign_bootkube_service_id,
var.ign_docker_dropin_id,
var.ign_init_assets_service_id,
var.ign_iscsi_service_id,
var.ign_k8s_node_bootstrap_service_id,
var.ign_kubelet_service_id,
var.ign_locksmithd_service_id,
var.ign_rm_assets_path_unit_id,
var.ign_rm_assets_service_id,
var.ign_tectonic_path_unit_id,
var.ign_tectonic_service_id,
var.ign_update_ca_certificates_dropin_id,
))}"]
}
data "template_file" "detect_master" {
template = "${file("${path.module}/resources/detect-master.sh")}"
vars {
load_balancer_name = "${format("%s-%s", var.cluster_name, var.private_endpoints ? "int" : "ext")}"
}
}
data "ignition_file" "detect_master" {
filesystem = "root"
path = "/opt/detect-master.sh"
mode = 0755
content {
content = "${data.template_file.detect_master.rendered}"
}
}
data "template_file" "init_assets" {
template = "${file("${path.module}/resources/init-assets.sh")}"
vars {
assets_s3_location = "${var.assets_s3_location}"
awscli_image = "${var.container_images["awscli"]}"
cluster_name = "${var.cluster_name}"
}
}
data "ignition_file" "init_assets" {
filesystem = "root"
path = "/opt/init-assets.sh"
mode = 0755
content {
content = "${data.template_file.init_assets.rendered}"
}
}
data "template_file" "rm_assets" {
template = "${file("${path.module}/resources/rm-assets.sh")}"
vars {
assets_s3_location = "${var.assets_s3_location}"
awscli_image = "${var.container_images["awscli"]}"
cluster_name = "${var.cluster_name}"
}
}
data "ignition_file" "rm_assets" {
filesystem = "root"
path = "/opt/rm-assets.sh"
mode = 0755
content {
content = "${data.template_file.rm_assets.rendered}"
}
}

View File

@@ -0,0 +1,21 @@
resource "aws_s3_bucket_object" "ignition_master" {
bucket = "${var.s3_bucket}"
key = "ignition_master.json"
content = "${data.ignition_config.main.rendered}"
acl = "private"
server_side_encryption = "AES256"
tags = "${merge(map(
"Name", "${var.cluster_name}-ignition-master",
"KubernetesCluster", "${var.cluster_name}",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
data "ignition_config" "s3" {
replace {
source = "${format("s3://%s/%s", var.s3_bucket, aws_s3_bucket_object.ignition_master.key)}"
verification = "sha512-${sha512(data.ignition_config.main.rendered)}"
}
}

View File

@@ -0,0 +1,164 @@
locals {
ami_owner = "595879546273"
arn = "aws"
}
data "aws_ami" "coreos_ami" {
filter {
name = "name"
values = ["CoreOS-${var.container_linux_channel}-${var.container_linux_version}-*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "owner-id"
values = ["${local.ami_owner}"]
}
}
resource "aws_autoscaling_group" "masters" {
name = "${var.cluster_name}-masters"
desired_capacity = "${var.instance_count}"
max_size = "${var.instance_count * 3}"
min_size = "${var.instance_count}"
launch_configuration = "${aws_launch_configuration.master_conf.id}"
vpc_zone_identifier = ["${var.subnet_ids}"]
load_balancers = ["${var.aws_lbs}"]
tags = [
{
key = "Name"
value = "${var.cluster_name}-master"
propagate_at_launch = true
},
{
key = "kubernetes.io/cluster/${var.cluster_name}"
value = "owned"
propagate_at_launch = true
},
{
key = "tectonicClusterID"
value = "${var.cluster_id}"
propagate_at_launch = true
},
"${var.autoscaling_group_extra_tags}",
]
lifecycle {
create_before_destroy = true
}
}
resource "aws_launch_configuration" "master_conf" {
instance_type = "${var.ec2_type}"
image_id = "${coalesce(var.ec2_ami, data.aws_ami.coreos_ami.image_id)}"
name_prefix = "${var.cluster_name}-master-"
key_name = "${var.ssh_key}"
security_groups = ["${var.master_sg_ids}"]
iam_instance_profile = "${aws_iam_instance_profile.master_profile.arn}"
associate_public_ip_address = "${var.public_endpoints}"
user_data = "${var.user_data_ign}"
lifecycle {
create_before_destroy = true
# Ignore changes in the AMI which force recreation of the resource. This
# avoids accidental deletion of nodes whenever a new CoreOS Release comes
# out.
ignore_changes = ["image_id"]
}
root_block_device {
volume_type = "${var.root_volume_type}"
volume_size = "${var.root_volume_size}"
iops = "${var.root_volume_type == "io1" ? var.root_volume_iops : 0}"
}
}
resource "aws_iam_instance_profile" "master_profile" {
name = "${var.cluster_name}-master-profile"
role = "${var.master_iam_role == "" ?
join("|", aws_iam_role.master_role.*.name) :
join("|", data.aws_iam_role.master_role.*.name)
}"
}
data "aws_iam_role" "master_role" {
count = "${var.master_iam_role == "" ? 0 : 1}"
name = "${var.master_iam_role}"
}
resource "aws_iam_role" "master_role" {
count = "${var.master_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}-master-role"
path = "/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "master_policy" {
count = "${var.master_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}_master_policy"
role = "${aws_iam_role.master_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "ec2:*",
"Resource": "*",
"Effect": "Allow"
},
{
"Action": "elasticloadbalancing:*",
"Resource": "*",
"Effect": "Allow"
},
{
"Action" : [
"s3:GetObject",
"s3:HeadObject",
"s3:ListBucket",
"s3:PutObject"
],
"Resource": "arn:${local.arn}:s3:::*",
"Effect": "Allow"
},
{
"Action" : [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
EOF
}

View File

@@ -0,0 +1,164 @@
locals {
ami_owner = "595879546273"
arn = "aws"
}
data "aws_ami" "coreos_ami" {
filter {
name = "name"
values = ["CoreOS-${var.container_linux_channel}-${var.container_linux_version}-*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "owner-id"
values = ["${local.ami_owner}"]
}
}
resource "aws_autoscaling_group" "masters" {
name = "${var.cluster_name}-masters"
desired_capacity = "${var.instance_count}"
max_size = "${var.instance_count * 3}"
min_size = "${var.instance_count}"
launch_configuration = "${aws_launch_configuration.master_conf.id}"
vpc_zone_identifier = ["${var.subnet_ids}"]
load_balancers = ["${var.aws_lbs}"]
tags = [
{
key = "Name"
value = "${var.cluster_name}-master"
propagate_at_launch = true
},
{
key = "kubernetes.io/cluster/${var.cluster_name}"
value = "owned"
propagate_at_launch = true
},
{
key = "tectonicClusterID"
value = "${var.cluster_id}"
propagate_at_launch = true
},
"${var.autoscaling_group_extra_tags}",
]
lifecycle {
create_before_destroy = true
}
}
resource "aws_launch_configuration" "master_conf" {
instance_type = "${var.ec2_type}"
image_id = "${coalesce(var.ec2_ami, data.aws_ami.coreos_ami.image_id)}"
name_prefix = "${var.cluster_name}-master-"
key_name = "${var.ssh_key}"
security_groups = ["${var.master_sg_ids}"]
iam_instance_profile = "${aws_iam_instance_profile.master_profile.arn}"
associate_public_ip_address = "${var.public_endpoints}"
user_data = "${data.ignition_config.s3.rendered}"
lifecycle {
create_before_destroy = true
# Ignore changes in the AMI which force recreation of the resource. This
# avoids accidental deletion of nodes whenever a new CoreOS Release comes
# out.
ignore_changes = ["image_id"]
}
root_block_device {
volume_type = "${var.root_volume_type}"
volume_size = "${var.root_volume_size}"
iops = "${var.root_volume_type == "io1" ? var.root_volume_iops : 0}"
}
}
resource "aws_iam_instance_profile" "master_profile" {
name = "${var.cluster_name}-master-profile"
role = "${var.master_iam_role == "" ?
join("|", aws_iam_role.master_role.*.name) :
join("|", data.aws_iam_role.master_role.*.name)
}"
}
data "aws_iam_role" "master_role" {
count = "${var.master_iam_role == "" ? 0 : 1}"
name = "${var.master_iam_role}"
}
resource "aws_iam_role" "master_role" {
count = "${var.master_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}-master-role"
path = "/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "master_policy" {
count = "${var.master_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}_master_policy"
role = "${aws_iam_role.master_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "ec2:*",
"Resource": "*",
"Effect": "Allow"
},
{
"Action": "elasticloadbalancing:*",
"Resource": "*",
"Effect": "Allow"
},
{
"Action" : [
"s3:GetObject",
"s3:HeadObject",
"s3:ListBucket",
"s3:PutObject"
],
"Resource": "arn:${local.arn}:s3:::*",
"Effect": "Allow"
},
{
"Action" : [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
EOF
}

View File

@@ -0,0 +1,115 @@
variable "autoscaling_group_extra_tags" {
description = "Extra AWS tags to be applied to created autoscaling group resources."
type = "list"
default = []
}
variable "base_domain" {
type = "string"
description = "Domain on which the ELB records will be created"
}
variable "container_linux_channel" {
type = "string"
}
variable "container_linux_version" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
variable "cluster_name" {
type = "string"
}
variable "container_images" {
description = "Container images to use"
type = "map"
}
variable "ec2_type" {
type = "string"
}
variable "extra_tags" {
description = "Extra AWS tags to be applied to created resources."
type = "map"
default = {}
}
variable "ec2_ami" {
type = "string"
default = ""
}
variable "instance_count" {
type = "string"
}
variable "master_iam_role" {
type = "string"
default = ""
description = "IAM role to use for the instance profiles of master nodes."
}
variable "master_sg_ids" {
type = "list"
description = "The security group IDs to be applied to the master nodes."
}
variable "private_endpoints" {
description = "If set to true, private-facing ingress resources are created."
default = true
}
variable "public_endpoints" {
description = "If set to true, public-facing ingress resources are created."
default = true
}
variable "aws_lbs" {
description = "List of aws_lb IDs for the Console & APIs"
type = "list"
default = []
}
variable "root_volume_iops" {
type = "string"
default = "100"
description = "The amount of provisioned IOPS for the root block device."
}
variable "root_volume_size" {
type = "string"
description = "The size of the volume in gigabytes for the root block device."
}
variable "root_volume_type" {
type = "string"
description = "The type of volume for the root block device."
}
variable "ssh_key" {
type = "string"
}
variable "subnet_ids" {
type = "list"
}
variable "dns_server_ip" {
type = "string"
default = ""
}
variable "kubeconfig_content" {
type = "string"
default = ""
}
variable "user_data_ign" {
type = "string"
}

View File

@@ -0,0 +1,144 @@
variable "assets_s3_location" {
type = "string"
description = "Location on S3 of the Bootkube/Tectonic assets to use (bucket/key)"
}
variable "autoscaling_group_extra_tags" {
description = "Extra AWS tags to be applied to created autoscaling group resources."
type = "list"
default = []
}
variable "base_domain" {
type = "string"
description = "Domain on which the ELB records will be created"
}
variable "container_linux_channel" {
type = "string"
}
variable "container_linux_version" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
variable "cluster_name" {
type = "string"
}
variable "container_images" {
description = "Container images to use"
type = "map"
}
variable "ec2_type" {
type = "string"
}
variable "extra_tags" {
description = "Extra AWS tags to be applied to created resources."
type = "map"
default = {}
}
variable "ign_s3_puller_id" {
type = "string"
}
variable "ec2_ami" {
type = "string"
default = ""
}
variable "instance_count" {
type = "string"
}
variable "master_iam_role" {
type = "string"
default = ""
description = "IAM role to use for the instance profiles of master nodes."
}
variable "master_sg_ids" {
type = "list"
description = "The security group IDs to be applied to the master nodes."
}
variable "private_endpoints" {
description = "If set to true, private-facing ingress resources are created."
default = true
}
variable "public_endpoints" {
description = "If set to true, public-facing ingress resources are created."
default = true
}
variable "aws_lbs" {
description = "List of aws_lb IDs for the Console & APIs"
type = "list"
default = []
}
variable "root_volume_iops" {
type = "string"
default = "100"
description = "The amount of provisioned IOPS for the root block device."
}
variable "root_volume_size" {
type = "string"
description = "The size of the volume in gigabytes for the root block device."
}
variable "root_volume_type" {
type = "string"
description = "The type of volume for the root block device."
}
variable "ssh_key" {
type = "string"
}
variable "subnet_ids" {
type = "list"
}
variable "ign_bootkube_service_id" {
type = "string"
description = "The ID of the bootkube systemd service unit"
}
variable "ign_bootkube_path_unit_id" {
type = "string"
}
variable "ign_tectonic_service_id" {
type = "string"
description = "The ID of the tectonic installer systemd service unit"
}
variable "ign_tectonic_path_unit_id" {
type = "string"
}
variable "ign_init_assets_service_id" {
type = "string"
}
variable "ign_rm_assets_service_id" {
type = "string"
}
variable "ign_rm_assets_path_unit_id" {
type = "string"
}
variable "s3_bucket" {
type = "string"
}

View File

@@ -0,0 +1,12 @@
# These subnet data-sources import external subnets from their user-supplied subnet IDs
# whenever an external VPC is specified
#
data "aws_subnet" "external_worker" {
count = "${var.external_vpc_id == "" ? 0 : length(var.external_worker_subnets)}"
id = "${var.external_worker_subnets[count.index]}"
}
data "aws_subnet" "external_master" {
count = "${var.external_vpc_id == "" ? 0 : length(var.external_master_subnets)}"
id = "${var.external_master_subnets[count.index]}"
}

View File

@@ -0,0 +1,135 @@
resource "aws_elb" "tnc" {
count = "${var.private_master_endpoints ? 1 : 0}"
name = "${var.cluster_name}-tnc"
subnets = ["${local.master_subnet_ids}"]
internal = true
security_groups = ["${aws_security_group.tnc.id}"]
idle_timeout = 3600
connection_draining = true
connection_draining_timeout = 300
listener {
instance_port = 49500
instance_protocol = "tcp"
lb_port = 80
lb_protocol = "tcp"
}
health_check {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
target = "TCP:49500"
interval = 5
}
tags = "${merge(map(
"Name", "${var.cluster_name}-int",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_elb" "api_internal" {
count = "${var.private_master_endpoints ? 1 : 0}"
name = "${var.cluster_name}-int"
subnets = ["${local.master_subnet_ids}"]
internal = true
security_groups = ["${aws_security_group.api.id}"]
idle_timeout = 3600
connection_draining = true
connection_draining_timeout = 300
listener {
instance_port = 6443
instance_protocol = "tcp"
lb_port = 6443
lb_protocol = "tcp"
}
health_check {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
target = "SSL:6443"
interval = 5
}
tags = "${merge(map(
"Name", "${var.cluster_name}-int",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_elb" "api_external" {
count = "${var.public_master_endpoints ? 1 : 0}"
name = "${var.cluster_name}-ext"
subnets = ["${local.master_subnet_ids}"]
internal = false
security_groups = ["${aws_security_group.api.id}"]
idle_timeout = 3600
connection_draining = true
connection_draining_timeout = 300
listener {
instance_port = 6443
instance_protocol = "tcp"
lb_port = 6443
lb_protocol = "tcp"
}
health_check {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
target = "SSL:6443"
interval = 5
}
tags = "${merge(map(
"Name", "${var.cluster_name}-api-external",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_elb" "console" {
name = "${var.cluster_name}-con"
subnets = ["${local.master_subnet_ids}"]
internal = "${var.public_master_endpoints ? false : true}"
security_groups = ["${aws_security_group.console.id}"]
idle_timeout = 3600
listener {
instance_port = 32001
instance_protocol = "tcp"
lb_port = 80
lb_protocol = "tcp"
}
listener {
instance_port = 32000
instance_protocol = "tcp"
lb_port = 443
lb_protocol = "tcp"
}
health_check {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
target = "HTTP:32002/healthz"
interval = 5
}
tags = "${merge(map(
"Name", "${var.cluster_name}-console",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}

View File

@@ -0,0 +1,102 @@
resource "aws_elb" "api_internal" {
count = "${var.private_master_endpoints}"
name = "${var.cluster_name}-int"
subnets = ["${local.master_subnet_ids}"]
internal = true
security_groups = ["${aws_security_group.api.id}"]
idle_timeout = 3600
connection_draining = true
connection_draining_timeout = 300
listener {
instance_port = 443
instance_protocol = "tcp"
lb_port = 443
lb_protocol = "tcp"
}
health_check {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
target = "SSL:443"
interval = 5
}
tags = "${merge(map(
"Name", "${var.cluster_name}-int",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_elb" "api_external" {
count = "${var.public_master_endpoints}"
name = "${var.custom_dns_name == "" ? var.cluster_name : var.custom_dns_name}-ext"
subnets = ["${local.master_subnet_ids}"]
internal = false
security_groups = ["${aws_security_group.api.id}"]
idle_timeout = 3600
connection_draining = true
connection_draining_timeout = 300
listener {
instance_port = 443
instance_protocol = "tcp"
lb_port = 443
lb_protocol = "tcp"
}
health_check {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
target = "SSL:443"
interval = 5
}
tags = "${merge(map(
"Name", "${var.cluster_name}-api-external",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_elb" "console" {
name = "${var.custom_dns_name == "" ? var.cluster_name : var.custom_dns_name}-con"
subnets = ["${local.master_subnet_ids}"]
internal = "${var.public_master_endpoints ? false : true}"
security_groups = ["${aws_security_group.console.id}"]
idle_timeout = 3600
listener {
instance_port = 32001
instance_protocol = "tcp"
lb_port = 80
lb_protocol = "tcp"
}
listener {
instance_port = 32000
instance_protocol = "tcp"
lb_port = 443
lb_protocol = "tcp"
}
health_check {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
target = "HTTP:32002/healthz"
interval = 5
}
tags = "${merge(map(
"Name", "${var.cluster_name}-console",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}

View File

@@ -0,0 +1,81 @@
output "vpc_id" {
value = "${data.aws_vpc.cluster_vpc.id}"
}
# We have to do this join() & split() 'trick' because null_data_source and
# the ternary operator can't output lists or maps
output "master_subnet_ids" {
value = "${local.master_subnet_ids}"
}
output "worker_subnet_ids" {
value = "${local.worker_subnet_ids}"
}
output "etcd_sg_id" {
value = "${element(concat(aws_security_group.etcd.*.id, list("")), 0)}"
}
output "master_sg_id" {
value = "${aws_security_group.master.id}"
}
output "worker_sg_id" {
value = "${aws_security_group.worker.id}"
}
output "api_sg_id" {
value = "${aws_security_group.api.id}"
}
output "console_sg_id" {
value = "${aws_security_group.console.id}"
}
output "aws_elb_api_external_id" {
value = "${aws_elb.api_external.*.id}"
}
output "aws_elb_internal_id" {
value = "${aws_elb.api_internal.*.id}"
}
output "aws_elb_console_id" {
value = "${aws_elb.console.id}"
}
output "aws_lbs" {
value = ["${compact(concat(aws_elb.api_internal.*.id, list(aws_elb.console.id), aws_elb.api_external.*.id, aws_elb.tnc.*.id))}"]
}
output "aws_api_external_dns_name" {
value = "${element(concat(aws_elb.api_external.*.dns_name, list("")), 0)}"
}
output "aws_elb_api_external_zone_id" {
value = "${element(concat(aws_elb.api_external.*.zone_id, list("")), 0)}"
}
output "aws_api_internal_dns_name" {
value = "${element(concat(aws_elb.api_internal.*.dns_name, list("")), 0)}"
}
output "aws_elb_api_internal_zone_id" {
value = "${element(concat(aws_elb.api_internal.*.zone_id, list("")), 0)}"
}
output "aws_console_dns_name" {
value = "${aws_elb.console.dns_name}"
}
output "aws_elb_console_zone_id" {
value = "${aws_elb.console.zone_id}"
}
output "aws_elb_tnc_dns_name" {
value = "${element(concat(aws_elb.tnc.*.dns_name, list("")), 0)}"
}
output "aws_elb_tnc_zone_id" {
value = "${element(concat(aws_elb.tnc.*.zone_id, list("")), 0)}"
}

View File

@@ -0,0 +1,73 @@
output "vpc_id" {
value = "${data.aws_vpc.cluster_vpc.id}"
}
# We have to do this join() & split() 'trick' because null_data_source and
# the ternary operator can't output lists or maps
output "master_subnet_ids" {
value = "${local.master_subnet_ids}"
}
output "worker_subnet_ids" {
value = "${local.worker_subnet_ids}"
}
output "etcd_sg_id" {
value = "${element(concat(aws_security_group.etcd.*.id, list("")), 0)}"
}
output "master_sg_id" {
value = "${aws_security_group.master.id}"
}
output "worker_sg_id" {
value = "${aws_security_group.worker.id}"
}
output "api_sg_id" {
value = "${aws_security_group.api.id}"
}
output "console_sg_id" {
value = "${aws_security_group.console.id}"
}
output "aws_elb_api_external_id" {
value = "${aws_elb.api_external.*.id}"
}
output "aws_elb_internal_id" {
value = "${aws_elb.api_internal.*.id}"
}
output "aws_elb_console_id" {
value = "${aws_elb.console.id}"
}
output "aws_lbs" {
value = ["${compact(concat(aws_elb.api_internal.*.id, list(aws_elb.console.id), aws_elb.api_external.*.id))}"]
}
output "aws_api_external_dns_name" {
value = "${element(concat(aws_elb.api_external.*.dns_name, list("")), 0)}"
}
output "aws_elb_api_external_zone_id" {
value = "${element(concat(aws_elb.api_external.*.zone_id, list("")), 0)}"
}
output "aws_api_internal_dns_name" {
value = "${element(concat(aws_elb.api_internal.*.dns_name, list("")), 0)}"
}
output "aws_elb_api_internal_zone_id" {
value = "${element(concat(aws_elb.api_internal.*.zone_id, list("")), 0)}"
}
output "aws_console_dns_name" {
value = "${aws_elb.console.dns_name}"
}
output "aws_elb_console_zone_id" {
value = "${aws_elb.console.zone_id}"
}

View File

@@ -0,0 +1,88 @@
resource "aws_security_group" "tnc" {
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}_console_sg",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
egress {
from_port = 0
to_port = 0
protocol = "-1"
self = true
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
}
ingress {
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
}
}
resource "aws_security_group" "api" {
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}_api_sg",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
egress {
from_port = 0
to_port = 0
protocol = "-1"
self = true
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 6443
to_port = 6443
}
}
resource "aws_security_group" "console" {
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}_console_sg",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
egress {
from_port = 0
to_port = 0
protocol = "-1"
self = true
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
}
ingress {
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
}
}

View File

@@ -0,0 +1,56 @@
resource "aws_security_group" "api" {
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}_api_sg",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
egress {
from_port = 0
to_port = 0
protocol = "-1"
self = true
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
}
}
resource "aws_security_group" "console" {
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}_console_sg",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
egress {
from_port = 0
to_port = 0
protocol = "-1"
self = true
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
}
ingress {
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
}
}

View File

@@ -0,0 +1,49 @@
resource "aws_security_group" "etcd" {
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}_etcd_sg",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
egress {
from_port = 0
to_port = 0
protocol = "-1"
self = true
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 0
}
ingress {
protocol = "tcp"
from_port = 22
to_port = 22
self = true
security_groups = ["${aws_security_group.master.id}"]
}
ingress {
protocol = "tcp"
from_port = 2379
to_port = 2379
self = true
security_groups = ["${aws_security_group.master.id}"]
}
ingress {
protocol = "tcp"
from_port = 2380
to_port = 2380
self = true
}
}

View File

@@ -0,0 +1,50 @@
resource "aws_security_group" "etcd" {
count = "${var.enable_etcd_sg}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}_etcd_sg",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
egress {
from_port = 0
to_port = 0
protocol = "-1"
self = true
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 0
}
ingress {
protocol = "tcp"
from_port = 22
to_port = 22
self = true
security_groups = ["${aws_security_group.master.id}"]
}
ingress {
protocol = "tcp"
from_port = 2379
to_port = 2379
self = true
security_groups = ["${aws_security_group.master.id}"]
}
ingress {
protocol = "tcp"
from_port = 2380
to_port = 2380
self = true
}
}

View File

@@ -0,0 +1,209 @@
resource "aws_security_group" "master" {
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}_master_sg",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_security_group_rule" "master_tnc" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 49500
to_port = 49500
}
resource "aws_security_group_rule" "master_egress" {
type = "egress"
security_group_id = "${aws_security_group.master.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "master_ingress_icmp" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "icmp"
cidr_blocks = ["${data.aws_vpc.cluster_vpc.cidr_block}"]
from_port = 0
to_port = 0
}
resource "aws_security_group_rule" "master_ingress_ssh" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 22
to_port = 22
}
resource "aws_security_group_rule" "master_ingress_http" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
cidr_blocks = ["${data.aws_vpc.cluster_vpc.cidr_block}"]
from_port = 80
to_port = 80
}
resource "aws_security_group_rule" "master_ingress_https" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
cidr_blocks = ["${data.aws_vpc.cluster_vpc.cidr_block}"]
from_port = 6443
to_port = 6445
}
resource "aws_security_group_rule" "master_ingress_heapster" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 4194
to_port = 4194
self = true
}
resource "aws_security_group_rule" "master_ingress_heapster_from_worker" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 4194
to_port = 4194
}
resource "aws_security_group_rule" "master_ingress_flannel" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "udp"
from_port = 4789
to_port = 4789
self = true
}
resource "aws_security_group_rule" "master_ingress_flannel_from_worker" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.worker.id}"
protocol = "udp"
from_port = 4789
to_port = 4789
}
resource "aws_security_group_rule" "master_ingress_node_exporter" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 9100
to_port = 9100
self = true
}
resource "aws_security_group_rule" "master_ingress_node_exporter_from_worker" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 9100
to_port = 9100
}
resource "aws_security_group_rule" "master_ingress_kubelet_insecure" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 10250
to_port = 10250
self = true
}
resource "aws_security_group_rule" "master_ingress_kubelet_insecure_from_worker" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 10250
to_port = 10250
}
resource "aws_security_group_rule" "master_ingress_kubelet_secure" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 10255
to_port = 10255
self = true
}
resource "aws_security_group_rule" "master_ingress_kubelet_secure_from_worker" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 10255
to_port = 10255
}
resource "aws_security_group_rule" "master_ingress_etcd" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 2379
to_port = 2380
self = true
}
resource "aws_security_group_rule" "master_ingress_bootstrap_etcd" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 12379
to_port = 12380
self = true
}
resource "aws_security_group_rule" "master_ingress_services" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 30000
to_port = 32767
self = true
}
resource "aws_security_group_rule" "master_ingress_services_from_console" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.console.id}"
protocol = "tcp"
from_port = 30000
to_port = 32767
}

View File

@@ -0,0 +1,199 @@
resource "aws_security_group" "master" {
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}_master_sg",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_security_group_rule" "master_egress" {
type = "egress"
security_group_id = "${aws_security_group.master.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "master_ingress_icmp" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 0
}
resource "aws_security_group_rule" "master_ingress_ssh" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 22
to_port = 22
}
resource "aws_security_group_rule" "master_ingress_http" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
}
resource "aws_security_group_rule" "master_ingress_https" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
}
resource "aws_security_group_rule" "master_ingress_heapster" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 4194
to_port = 4194
self = true
}
resource "aws_security_group_rule" "master_ingress_heapster_from_worker" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 4194
to_port = 4194
}
resource "aws_security_group_rule" "master_ingress_flannel" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "udp"
from_port = 4789
to_port = 4789
self = true
}
resource "aws_security_group_rule" "master_ingress_flannel_from_worker" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.worker.id}"
protocol = "udp"
from_port = 4789
to_port = 4789
}
resource "aws_security_group_rule" "master_ingress_node_exporter" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 9100
to_port = 9100
self = true
}
resource "aws_security_group_rule" "master_ingress_node_exporter_from_worker" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 9100
to_port = 9100
}
resource "aws_security_group_rule" "master_ingress_kubelet_insecure" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 10250
to_port = 10250
self = true
}
resource "aws_security_group_rule" "master_ingress_kubelet_insecure_from_worker" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 10250
to_port = 10250
}
resource "aws_security_group_rule" "master_ingress_kubelet_secure" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 10255
to_port = 10255
self = true
}
resource "aws_security_group_rule" "master_ingress_kubelet_secure_from_worker" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 10255
to_port = 10255
}
resource "aws_security_group_rule" "master_ingress_etcd" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 2379
to_port = 2380
self = true
}
resource "aws_security_group_rule" "master_ingress_bootstrap_etcd" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 12379
to_port = 12380
self = true
}
resource "aws_security_group_rule" "master_ingress_services" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 30000
to_port = 32767
self = true
}
resource "aws_security_group_rule" "master_ingress_services_from_console" {
type = "ingress"
security_group_id = "${aws_security_group.master.id}"
source_security_group_id = "${aws_security_group.console.id}"
protocol = "tcp"
from_port = 30000
to_port = 32767
}

View File

@@ -0,0 +1,179 @@
resource "aws_security_group" "worker" {
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}_worker_sg",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_security_group_rule" "worker_egress" {
type = "egress"
security_group_id = "${aws_security_group.worker.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "worker_ingress_icmp" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 0
}
resource "aws_security_group_rule" "worker_ingress_ssh" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 22
to_port = 22
}
resource "aws_security_group_rule" "worker_ingress_http" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
}
resource "aws_security_group_rule" "worker_ingress_https" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
}
resource "aws_security_group_rule" "worker_ingress_heapster" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 4194
to_port = 4194
self = true
}
resource "aws_security_group_rule" "worker_ingress_heapster_from_master" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 4194
to_port = 4194
}
resource "aws_security_group_rule" "worker_ingress_flannel" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "udp"
from_port = 4789
to_port = 4789
self = true
}
resource "aws_security_group_rule" "worker_ingress_flannel_from_master" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.master.id}"
protocol = "udp"
from_port = 4789
to_port = 4789
}
resource "aws_security_group_rule" "worker_ingress_node_exporter" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 9100
to_port = 9100
self = true
}
resource "aws_security_group_rule" "worker_ingress_node_exporter_from_master" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 9100
to_port = 9100
}
resource "aws_security_group_rule" "worker_ingress_kubelet_insecure" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 10250
to_port = 10250
self = true
}
resource "aws_security_group_rule" "worker_ingress_kubelet_insecure_from_master" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 10250
to_port = 10250
}
resource "aws_security_group_rule" "worker_ingress_kubelet_secure" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 10255
to_port = 10255
self = true
}
resource "aws_security_group_rule" "worker_ingress_kubelet_secure_from_master" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 10255
to_port = 10255
}
resource "aws_security_group_rule" "worker_ingress_services" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 30000
to_port = 32767
self = true
}
resource "aws_security_group_rule" "worker_ingress_services_from_console" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.console.id}"
protocol = "tcp"
from_port = 30000
to_port = 32767
}

View File

@@ -0,0 +1,179 @@
resource "aws_security_group" "worker" {
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}_worker_sg",
"kubernetes.io/cluster/${var.cluster_name}", "owned",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_security_group_rule" "worker_egress" {
type = "egress"
security_group_id = "${aws_security_group.worker.id}"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "worker_ingress_icmp" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 0
}
resource "aws_security_group_rule" "worker_ingress_ssh" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 22
to_port = 22
}
resource "aws_security_group_rule" "worker_ingress_http" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
}
resource "aws_security_group_rule" "worker_ingress_https" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
}
resource "aws_security_group_rule" "worker_ingress_heapster" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 4194
to_port = 4194
self = true
}
resource "aws_security_group_rule" "worker_ingress_heapster_from_master" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 4194
to_port = 4194
}
resource "aws_security_group_rule" "worker_ingress_flannel" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "udp"
from_port = 4789
to_port = 4789
self = true
}
resource "aws_security_group_rule" "worker_ingress_flannel_from_master" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.master.id}"
protocol = "udp"
from_port = 4789
to_port = 4789
}
resource "aws_security_group_rule" "worker_ingress_node_exporter" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 9100
to_port = 9100
self = true
}
resource "aws_security_group_rule" "worker_ingress_node_exporter_from_master" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 9100
to_port = 9100
}
resource "aws_security_group_rule" "worker_ingress_kubelet_insecure" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 10250
to_port = 10250
self = true
}
resource "aws_security_group_rule" "worker_ingress_kubelet_insecure_from_master" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 10250
to_port = 10250
}
resource "aws_security_group_rule" "worker_ingress_kubelet_secure" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 10255
to_port = 10255
self = true
}
resource "aws_security_group_rule" "worker_ingress_kubelet_secure_from_master" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.master.id}"
protocol = "tcp"
from_port = 10255
to_port = 10255
}
resource "aws_security_group_rule" "worker_ingress_services" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
protocol = "tcp"
from_port = 30000
to_port = 32767
self = true
}
resource "aws_security_group_rule" "worker_ingress_services_from_console" {
type = "ingress"
security_group_id = "${aws_security_group.worker.id}"
source_security_group_id = "${aws_security_group.console.id}"
protocol = "tcp"
from_port = 30000
to_port = 32767
}

View File

@@ -0,0 +1,58 @@
variable "cidr_block" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
variable "base_domain" {
type = "string"
}
variable "cluster_name" {
type = "string"
}
variable "external_vpc_id" {
type = "string"
}
variable "external_master_subnet_ids" {
type = "list"
}
variable "external_worker_subnet_ids" {
type = "list"
}
variable "extra_tags" {
description = "Extra AWS tags to be applied to created resources."
type = "map"
default = {}
}
variable "new_master_subnet_configs" {
description = "{az_name = new_subnet_cidr}: Empty map means create new subnets in all availability zones in region with generated cidrs"
type = "map"
}
variable "new_worker_subnet_configs" {
description = "{az_name = new_subnet_cidr}: Empty map means create new subnets in all availability zones in region with generated cidrs"
type = "map"
}
variable "private_master_endpoints" {
description = "If set to true, private-facing ingress resources are created."
default = true
}
variable "public_master_endpoints" {
description = "If set to true, public-facing ingress resources are created."
default = true
}
variable "depends_on" {
default = []
type = "list"
}

View File

@@ -0,0 +1,78 @@
variable "master_az_count" {
type = "string"
}
variable "worker_az_count" {
type = "string"
}
variable "cidr_block" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
variable "base_domain" {
type = "string"
}
variable "cluster_name" {
type = "string"
}
variable "external_vpc_id" {
type = "string"
}
variable "external_master_subnets" {
type = "list"
}
variable "external_worker_subnets" {
type = "list"
}
variable "extra_tags" {
description = "Extra AWS tags to be applied to created resources."
type = "map"
default = {}
}
variable "enable_etcd_sg" {
description = "If set to true, security groups for etcd nodes are being created"
default = true
}
variable "master_subnets" {
type = "list"
}
variable "worker_subnets" {
type = "list"
}
variable "master_azs" {
type = "list"
}
variable "worker_azs" {
type = "list"
}
variable "private_master_endpoints" {
description = "If set to true, private-facing ingress resources are created."
default = true
}
variable "public_master_endpoints" {
description = "If set to true, public-facing ingress resources are created."
default = true
}
variable "custom_dns_name" {
type = "string"
default = ""
description = "DNS prefix used to construct the console and API server endpoints."
}

View File

@@ -0,0 +1,43 @@
resource "aws_route_table" "private_routes" {
count = "${local.new_worker_az_count}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name","${var.cluster_name}-private-${local.new_worker_subnet_azs[count.index]}",
"kubernetes.io/cluster/${var.cluster_name}", "shared",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_route" "to_nat_gw" {
count = "${local.new_worker_az_count}"
route_table_id = "${aws_route_table.private_routes.*.id[count.index]}"
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = "${element(aws_nat_gateway.nat_gw.*.id, count.index)}"
depends_on = ["aws_route_table.private_routes"]
}
resource "aws_subnet" "worker_subnet" {
count = "${local.new_worker_az_count}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
cidr_block = "${lookup(var.new_worker_subnet_configs,
local.new_worker_subnet_azs[count.index],
cidrsubnet(local.new_worker_cidr_range, 3, count.index),
)}"
tags = "${merge(map(
"Name", "${var.cluster_name}-worker-${local.new_worker_subnet_azs[count.index]}",
"kubernetes.io/cluster/${var.cluster_name}","shared",
"kubernetes.io/role/internal-elb", "",
"tectonicClusterID", "${var.cluster_id}",
),
var.extra_tags)}"
}
resource "aws_route_table_association" "worker_routing" {
count = "${local.new_worker_az_count}"
route_table_id = "${aws_route_table.private_routes.*.id[count.index]}"
subnet_id = "${aws_subnet.worker_subnet.*.id[count.index]}"
}

View File

@@ -0,0 +1,46 @@
resource "aws_route_table" "private_routes" {
count = "${var.external_vpc_id == "" ? var.worker_az_count : 0}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}-private-${data.aws_availability_zones.azs.names[count.index]}",
"kubernetes.io/cluster/${var.cluster_name}", "shared",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_route" "to_nat_gw" {
count = "${var.external_vpc_id == "" ? var.worker_az_count : 0}"
route_table_id = "${aws_route_table.private_routes.*.id[count.index]}"
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = "${element(aws_nat_gateway.nat_gw.*.id, count.index)}"
depends_on = ["aws_route_table.private_routes"]
}
resource "aws_subnet" "worker_subnet" {
count = "${var.external_vpc_id == "" ? var.worker_az_count : 0}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
cidr_block = "${length(var.worker_subnets) > 1 ?
"${element(var.worker_subnets, count.index)}" :
"${cidrsubnet(data.aws_vpc.cluster_vpc.cidr_block, 4, count.index + var.worker_az_count)}"
}"
availability_zone = "${var.worker_azs[count.index]}"
tags = "${merge(map(
"Name", "${var.cluster_name}-worker-${ "${length(var.worker_azs)}" > 0 ?
"${var.worker_azs[count.index]}" :
"${data.aws_availability_zones.azs.names[count.index]}" }",
"kubernetes.io/cluster/${var.cluster_name}", "shared",
"kubernetes.io/role/internal-elb", "",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_route_table_association" "worker_routing" {
count = "${var.external_vpc_id == "" ? var.worker_az_count : 0}"
route_table_id = "${aws_route_table.private_routes.*.id[count.index]}"
subnet_id = "${aws_subnet.worker_subnet.*.id[count.index]}"
}

View File

@@ -0,0 +1,74 @@
resource "aws_internet_gateway" "igw" {
count = "${local.external_vpc_mode ? 0 : 1}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}-igw",
"kubernetes.io/cluster/${var.cluster_name}", "shared",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_route_table" "default" {
count = "${var.external_vpc_id == "" ? 1 : 0}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}-public",
"kubernetes.io/cluster/${var.cluster_name}", "shared",
"tectonicClusterID", "${var.cluster_id}",
), var.extra_tags)}"
}
resource "aws_main_route_table_association" "main_vpc_routes" {
count = "${local.external_vpc_mode ? 0 : 1}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
route_table_id = "${aws_route_table.default.id}"
}
resource "aws_route" "igw_route" {
count = "${local.external_vpc_mode ? 0 : 1}"
destination_cidr_block = "0.0.0.0/0"
route_table_id = "${aws_route_table.default.id}"
gateway_id = "${aws_internet_gateway.igw.id}"
}
resource "aws_subnet" "master_subnet" {
count = "${local.new_master_az_count}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
cidr_block = "${lookup(var.new_master_subnet_configs,
local.new_master_subnet_azs[count.index],
cidrsubnet(local.new_master_cidr_range, 3, count.index),
)}"
availability_zone = "${local.new_master_subnet_azs[count.index]}"
tags = "${merge(map(
"Name", "${var.cluster_name}-master-${local.new_master_subnet_azs[count.index]}",
"kubernetes.io/cluster/${var.cluster_name}", "shared",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_route_table_association" "route_net" {
count = "${local.new_master_az_count}"
route_table_id = "${aws_route_table.default.id}"
subnet_id = "${aws_subnet.master_subnet.*.id[count.index]}"
}
resource "aws_eip" "nat_eip" {
count = "${min(local.new_master_az_count,local.new_worker_az_count)}"
vpc = true
# Terraform does not declare an explicit dependency towards the internet gateway.
# this can cause the internet gateway to be deleted/detached before the EIPs.
# https://github.com/coreos/tectonic-installer/issues/1017#issuecomment-307780549
depends_on = ["aws_internet_gateway.igw"]
}
resource "aws_nat_gateway" "nat_gw" {
count = "${min(local.new_master_az_count,local.new_worker_az_count)}"
allocation_id = "${aws_eip.nat_eip.*.id[count.index]}"
subnet_id = "${aws_subnet.master_subnet.*.id[count.index]}"
}

View File

@@ -0,0 +1,77 @@
resource "aws_internet_gateway" "igw" {
count = "${var.external_vpc_id == "" ? 1 : 0}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}-igw",
"kubernetes.io/cluster/${var.cluster_name}", "shared",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_route_table" "default" {
count = "${var.external_vpc_id == "" ? 1 : 0}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
tags = "${merge(map(
"Name", "${var.cluster_name}-public",
"kubernetes.io/cluster/${var.cluster_name}", "shared",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_main_route_table_association" "main_vpc_routes" {
count = "${var.external_vpc_id == "" ? 1 : 0}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
route_table_id = "${aws_route_table.default.id}"
}
resource "aws_route" "igw_route" {
count = "${var.external_vpc_id == "" ? 1 : 0}"
destination_cidr_block = "0.0.0.0/0"
route_table_id = "${aws_route_table.default.id}"
gateway_id = "${aws_internet_gateway.igw.id}"
}
resource "aws_subnet" "master_subnet" {
count = "${var.external_vpc_id == "" ? var.master_az_count : 0}"
vpc_id = "${data.aws_vpc.cluster_vpc.id}"
cidr_block = "${length(var.master_subnets) > 1 ?
"${element(var.master_subnets, count.index)}" :
"${cidrsubnet(data.aws_vpc.cluster_vpc.cidr_block, 4, count.index)}"
}"
availability_zone = "${var.master_azs[count.index]}"
tags = "${merge(map(
"Name", "${var.cluster_name}-master-${ "${length(var.master_azs)}" > 0 ?
"${var.master_azs[count.index]}" :
"${data.aws_availability_zones.azs.names[count.index]}" }",
"kubernetes.io/cluster/${var.cluster_name}", "shared",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
resource "aws_route_table_association" "route_net" {
count = "${var.external_vpc_id == "" ? var.master_az_count : 0}"
route_table_id = "${aws_route_table.default.id}"
subnet_id = "${aws_subnet.master_subnet.*.id[count.index]}"
}
resource "aws_eip" "nat_eip" {
count = "${var.external_vpc_id == "" ? min(var.master_az_count, var.worker_az_count) : 0}"
vpc = true
# Terraform does not declare an explicit dependency towards the internet gateway.
# this can cause the internet gateway to be deleted/detached before the EIPs.
# https://github.com/coreos/tectonic-installer/issues/1017#issuecomment-307780549
depends_on = ["aws_internet_gateway.igw"]
}
resource "aws_nat_gateway" "nat_gw" {
count = "${var.external_vpc_id == "" ? min(var.master_az_count, var.worker_az_count) : 0}"
allocation_id = "${aws_eip.nat_eip.*.id[count.index]}"
subnet_id = "${aws_subnet.master_subnet.*.id[count.index]}"
}

View File

@@ -0,0 +1,17 @@
locals {
new_worker_cidr_range = "${cidrsubnet(data.aws_vpc.cluster_vpc.cidr_block,1,1)}"
new_master_cidr_range = "${cidrsubnet(data.aws_vpc.cluster_vpc.cidr_block,1,0)}"
}
resource "aws_vpc" "new_vpc" {
count = "${var.external_vpc_id == "" ? 1 : 0}"
cidr_block = "${var.cidr_block}"
enable_dns_hostnames = true
enable_dns_support = true
tags = "${merge(map(
"Name", "${var.cluster_name}.${var.base_domain}",
"kubernetes.io/cluster/${var.cluster_name}", "shared",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}

View File

@@ -0,0 +1,30 @@
data "aws_availability_zones" "azs" {}
resource "aws_vpc" "new_vpc" {
count = "${var.external_vpc_id == "" ? 1 : 0}"
cidr_block = "${var.cidr_block}"
enable_dns_hostnames = true
enable_dns_support = true
tags = "${merge(map(
"Name", "${var.cluster_name}.${var.base_domain}",
"kubernetes.io/cluster/${var.cluster_name}", "shared",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
data "aws_vpc" "cluster_vpc" {
# The join() hack is required because currently the ternary operator
# evaluates the expressions on both branches of the condition before
# returning a value. When providing and external VPC, the template VPC
# resource gets a count of zero which triggers an evaluation error.
#
# This is tracked upstream: https://github.com/hashicorp/hil/issues/50
#
id = "${var.external_vpc_id == "" ? join(" ", aws_vpc.new_vpc.*.id) : var.external_vpc_id }"
}
locals {
master_subnet_ids = ["${split(",", var.external_vpc_id == "" ? join(",", aws_subnet.master_subnet.*.id) : join(",", data.aws_subnet.external_master.*.id))}"]
worker_subnet_ids = ["${split(",", var.external_vpc_id == "" ? join(",", aws_subnet.worker_subnet.*.id) : join(",", data.aws_subnet.external_worker.*.id))}"]
}

View File

@@ -0,0 +1,23 @@
data "ignition_config" "main" {
files = ["${compact(list(
var.ign_installer_kubelet_env_id,
var.ign_installer_runtime_mappings_id,
var.ign_max_user_watches_id,
var.ign_nfs_config_id,
var.ign_ntp_dropin_id,
var.ign_profile_env_id,
var.ign_s3_puller_id,
var.ign_systemd_default_env_id,
))}",
"${var.ign_ca_cert_id_list}",
]
systemd = [
"${var.ign_docker_dropin_id}",
"${var.ign_iscsi_service_id}",
"${var.ign_k8s_node_bootstrap_service_id}",
"${var.ign_kubelet_service_id}",
"${var.ign_locksmithd_service_id}",
"${var.ign_update_ca_certificates_dropin_id}",
]
}

View File

@@ -0,0 +1,21 @@
resource "aws_s3_bucket_object" "ignition_worker" {
bucket = "${var.s3_bucket}"
key = "ignition_worker.json"
content = "${data.ignition_config.main.rendered}"
acl = "private"
server_side_encryption = "AES256"
tags = "${merge(map(
"Name", "${var.cluster_name}-ignition-worker",
"KubernetesCluster", "${var.cluster_name}",
"tectonicClusterID", "${var.cluster_id}"
), var.extra_tags)}"
}
data "ignition_config" "s3" {
replace {
source = "${format("s3://%s/%s", var.s3_bucket, aws_s3_bucket_object.ignition_worker.key)}"
verification = "sha512-${sha512(data.ignition_config.main.rendered)}"
}
}

View File

@@ -0,0 +1,95 @@
variable "ssh_key" {
type = "string"
}
variable "container_linux_channel" {
type = "string"
}
variable "container_linux_version" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
variable "cluster_name" {
type = "string"
}
variable "ec2_type" {
type = "string"
}
variable "ec2_ami" {
type = "string"
default = ""
}
variable "instance_count" {
type = "string"
}
variable "subnet_ids" {
type = "list"
}
variable "sg_ids" {
type = "list"
description = "The security group IDs to be applied."
}
variable "load_balancers" {
description = "List of ELBs to attach all worker instances to."
type = "list"
default = []
}
variable "extra_tags" {
description = "Extra AWS tags to be applied to created resources."
type = "map"
default = {}
}
variable "autoscaling_group_extra_tags" {
description = "Extra AWS tags to be applied to created autoscaling group resources."
type = "list"
default = []
}
variable "root_volume_type" {
type = "string"
description = "The type of volume for the root block device."
}
variable "root_volume_size" {
type = "string"
description = "The size of the volume in gigabytes for the root block device."
}
variable "root_volume_iops" {
type = "string"
default = "100"
description = "The amount of provisioned IOPS for the root block device."
}
variable "worker_iam_role" {
type = "string"
default = ""
description = "IAM role to use for the instance profiles of worker nodes."
}
variable "base_domain" {
type = "string"
description = "Domain on which the ELB records will be created"
}
variable "kubeconfig_content" {
type = "string"
default = ""
}
variable "user_data_ign" {
type = "string"
}

View File

@@ -0,0 +1,93 @@
variable "ssh_key" {
type = "string"
}
variable "vpc_id" {
type = "string"
}
variable "container_linux_channel" {
type = "string"
}
variable "container_linux_version" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
variable "cluster_name" {
type = "string"
}
variable "ec2_type" {
type = "string"
}
variable "ec2_ami" {
type = "string"
default = ""
}
variable "instance_count" {
type = "string"
}
variable "subnet_ids" {
type = "list"
}
variable "sg_ids" {
type = "list"
description = "The security group IDs to be applied."
}
variable "load_balancers" {
description = "List of ELBs to attach all worker instances to."
type = "list"
default = []
}
variable "extra_tags" {
description = "Extra AWS tags to be applied to created resources."
type = "map"
default = {}
}
variable "autoscaling_group_extra_tags" {
description = "Extra AWS tags to be applied to created autoscaling group resources."
type = "list"
default = []
}
variable "root_volume_type" {
type = "string"
description = "The type of volume for the root block device."
}
variable "root_volume_size" {
type = "string"
description = "The size of the volume in gigabytes for the root block device."
}
variable "root_volume_iops" {
type = "string"
default = "100"
description = "The amount of provisioned IOPS for the root block device."
}
variable "worker_iam_role" {
type = "string"
default = ""
description = "IAM role to use for the instance profiles of worker nodes."
}
variable "ign_s3_puller_id" {
type = "string"
}
variable "s3_bucket" {
type = "string"
}

View File

@@ -0,0 +1,175 @@
locals {
ami_owner = "595879546273"
arn = "aws"
}
data "aws_ami" "coreos_ami" {
filter {
name = "name"
values = ["CoreOS-${var.container_linux_channel}-${var.container_linux_version}-*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "owner-id"
values = ["${local.ami_owner}"]
}
}
resource "aws_launch_configuration" "worker_conf" {
instance_type = "${var.ec2_type}"
image_id = "${coalesce(var.ec2_ami, data.aws_ami.coreos_ami.image_id)}"
name_prefix = "${var.cluster_name}-worker-"
key_name = "${var.ssh_key}"
security_groups = ["${var.sg_ids}"]
iam_instance_profile = "${aws_iam_instance_profile.worker_profile.arn}"
user_data = "${var.user_data_ign}"
lifecycle {
create_before_destroy = true
# Ignore changes in the AMI which force recreation of the resource. This
# avoids accidental deletion of nodes whenever a new CoreOS Release comes
# out.
ignore_changes = ["image_id"]
}
root_block_device {
volume_type = "${var.root_volume_type}"
volume_size = "${var.root_volume_size}"
iops = "${var.root_volume_type == "io1" ? var.root_volume_iops : 0}"
}
}
resource "aws_autoscaling_group" "workers" {
name = "${var.cluster_name}-workers"
desired_capacity = "${var.instance_count}"
max_size = "${var.instance_count * 3}"
min_size = "${var.instance_count}"
launch_configuration = "${aws_launch_configuration.worker_conf.id}"
vpc_zone_identifier = ["${var.subnet_ids}"]
tags = [
{
key = "Name"
value = "${var.cluster_name}-worker"
propagate_at_launch = true
},
{
key = "kubernetes.io/cluster/${var.cluster_name}"
value = "owned"
propagate_at_launch = true
},
{
key = "tectonicClusterID"
value = "${var.cluster_id}"
propagate_at_launch = true
},
"${var.autoscaling_group_extra_tags}",
]
lifecycle {
create_before_destroy = true
}
}
resource "aws_autoscaling_attachment" "workers" {
count = "${length(var.load_balancers)}"
autoscaling_group_name = "${aws_autoscaling_group.workers.name}"
elb = "${var.load_balancers[count.index]}"
}
resource "aws_iam_instance_profile" "worker_profile" {
name = "${var.cluster_name}-worker-profile"
role = "${var.worker_iam_role == "" ?
join("|", aws_iam_role.worker_role.*.name) :
join("|", data.aws_iam_role.worker_role.*.name)
}"
}
data "aws_iam_role" "worker_role" {
count = "${var.worker_iam_role == "" ? 0 : 1}"
name = "${var.worker_iam_role}"
}
resource "aws_iam_role" "worker_role" {
count = "${var.worker_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}-worker-role"
path = "/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "worker_policy" {
count = "${var.worker_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}_worker_policy"
role = "${aws_iam_role.worker_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:Describe*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:AttachVolume",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:DetachVolume",
"Resource": "*"
},
{
"Action": "elasticloadbalancing:*",
"Resource": "*",
"Effect": "Allow"
},
{
"Action" : [
"s3:GetObject"
],
"Resource": "arn:${local.arn}:s3:::*",
"Effect": "Allow"
},
{
"Action" : [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
EOF
}

View File

@@ -0,0 +1,175 @@
locals {
ami_owner = "595879546273"
arn = "aws"
}
data "aws_ami" "coreos_ami" {
filter {
name = "name"
values = ["CoreOS-${var.container_linux_channel}-${var.container_linux_version}-*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "owner-id"
values = ["${local.ami_owner}"]
}
}
resource "aws_launch_configuration" "worker_conf" {
instance_type = "${var.ec2_type}"
image_id = "${coalesce(var.ec2_ami, data.aws_ami.coreos_ami.image_id)}"
name_prefix = "${var.cluster_name}-worker-"
key_name = "${var.ssh_key}"
security_groups = ["${var.sg_ids}"]
iam_instance_profile = "${aws_iam_instance_profile.worker_profile.arn}"
user_data = "${data.ignition_config.s3.rendered}"
lifecycle {
create_before_destroy = true
# Ignore changes in the AMI which force recreation of the resource. This
# avoids accidental deletion of nodes whenever a new CoreOS Release comes
# out.
ignore_changes = ["image_id"]
}
root_block_device {
volume_type = "${var.root_volume_type}"
volume_size = "${var.root_volume_size}"
iops = "${var.root_volume_type == "io1" ? var.root_volume_iops : 0}"
}
}
resource "aws_autoscaling_group" "workers" {
name = "${var.cluster_name}-workers"
desired_capacity = "${var.instance_count}"
max_size = "${var.instance_count * 3}"
min_size = "${var.instance_count}"
launch_configuration = "${aws_launch_configuration.worker_conf.id}"
vpc_zone_identifier = ["${var.subnet_ids}"]
tags = [
{
key = "Name"
value = "${var.cluster_name}-worker"
propagate_at_launch = true
},
{
key = "kubernetes.io/cluster/${var.cluster_name}"
value = "owned"
propagate_at_launch = true
},
{
key = "tectonicClusterID"
value = "${var.cluster_id}"
propagate_at_launch = true
},
"${var.autoscaling_group_extra_tags}",
]
lifecycle {
create_before_destroy = true
}
}
resource "aws_autoscaling_attachment" "workers" {
count = "${length(var.load_balancers)}"
autoscaling_group_name = "${aws_autoscaling_group.workers.name}"
elb = "${var.load_balancers[count.index]}"
}
resource "aws_iam_instance_profile" "worker_profile" {
name = "${var.cluster_name}-worker-profile"
role = "${var.worker_iam_role == "" ?
join("|", aws_iam_role.worker_role.*.name) :
join("|", data.aws_iam_role.worker_role.*.name)
}"
}
data "aws_iam_role" "worker_role" {
count = "${var.worker_iam_role == "" ? 0 : 1}"
name = "${var.worker_iam_role}"
}
resource "aws_iam_role" "worker_role" {
count = "${var.worker_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}-worker-role"
path = "/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "worker_policy" {
count = "${var.worker_iam_role == "" ? 1 : 0}"
name = "${var.cluster_name}_worker_policy"
role = "${aws_iam_role.worker_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:Describe*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:AttachVolume",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:DetachVolume",
"Resource": "*"
},
{
"Action": "elasticloadbalancing:*",
"Resource": "*",
"Effect": "Allow"
},
{
"Action" : [
"s3:GetObject"
],
"Resource": "arn:${local.arn}:s3:::*",
"Effect": "Allow"
},
{
"Action" : [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
EOF
}

View File

@@ -0,0 +1,69 @@
resource "azurerm_availability_set" "etcd" {
count = "${var.etcd_count > 0 ? 1 : 0}"
name = "${var.cluster_name}-etcd"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
managed = true
platform_fault_domain_count = "${var.fault_domains}"
tags = "${merge(map(
"Name", "${var.cluster_name}-etcd",
"tectonicClusterID", "${var.cluster_id}"),
var.extra_tags)}"
}
resource "azurerm_virtual_machine" "etcd_node" {
count = "${var.etcd_count}"
name = "${var.cluster_name}-etcd-${count.index}"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
network_interface_ids = ["${var.network_interface_ids[count.index]}"]
vm_size = "${var.vm_size}"
availability_set_id = "${azurerm_availability_set.etcd.id}"
delete_os_disk_on_termination = true
storage_image_reference {
publisher = "CoreOS"
offer = "CoreOS"
sku = "${var.container_linux_channel}"
version = "${var.container_linux_version}"
}
storage_os_disk {
name = "etcd-${count.index}-os-${var.storage_id}"
managed_disk_type = "${var.storage_type}"
create_option = "FromImage"
caching = "ReadWrite"
os_type = "linux"
disk_size_gb = "${var.root_volume_size}"
}
os_profile {
computer_name = "${var.cluster_name}-etcd-${count.index}"
admin_username = "core"
admin_password = ""
custom_data = "${base64encode("${data.ignition_config.etcd.*.rendered[count.index]}")}"
}
os_profile_linux_config {
disable_password_authentication = true
ssh_keys {
path = "/home/core/.ssh/authorized_keys"
key_data = "${file(var.public_ssh_key)}"
}
}
tags = "${merge(map(
"Name", "${var.cluster_name}-etcd-${count.index}",
"tectonicClusterID", "${var.cluster_id}"),
var.extra_tags)}"
lifecycle {
ignore_changes = [
"storage_os_disk",
"storage_data_disk",
]
}
}

View File

@@ -0,0 +1,52 @@
data "ignition_config" "etcd" {
count = "${var.etcd_count}"
systemd = [
"${data.ignition_systemd_unit.locksmithd.*.id[count.index]}",
"${var.ign_etcd_dropin_id_list[count.index]}",
]
users = [
"${data.ignition_user.core.id}",
]
files = ["${compact(list(
var.ign_profile_env_id,
var.ign_systemd_default_env_id,
))}",
"${var.ign_etcd_crt_id_list}",
"${var.ign_ntp_dropin_id}",
]
}
data "ignition_user" "core" {
count = "${var.etcd_count > 0 ? 1 : 0}"
name = "core"
ssh_authorized_keys = [
"${file(var.public_ssh_key)}",
]
}
data "ignition_systemd_unit" "locksmithd" {
count = "${var.etcd_count}"
name = "locksmithd.service"
enabled = true
dropin = [
{
name = "40-etcd-lock.conf"
content = <<EOF
[Service]
Environment=REBOOT_STRATEGY=etcd-lock
${var.tls_enabled ? "Environment=\"LOCKSMITHD_ETCD_CAFILE=/etc/ssl/etcd/ca.crt\"" : ""}
${var.tls_enabled ? "Environment=\"LOCKSMITHD_ETCD_KEYFILE=/etc/ssl/etcd/client.key\"" : ""}
${var.tls_enabled ? "Environment=\"LOCKSMITHD_ETCD_CERTFILE=/etc/ssl/etcd/client.crt\"" : ""}
Environment="LOCKSMITHD_ENDPOINT=${var.tls_enabled ? "https" : "http"}://etcd-${count.index}:2379"
EOF
},
]
}

View File

@@ -0,0 +1,3 @@
output "etcd_vm_ids" {
value = ["${azurerm_virtual_machine.etcd_node.*.id}"]
}

View File

@@ -0,0 +1,109 @@
// Location is the Azure Location (East US, West US, etc)
variable "location" {
type = "string"
}
variable "resource_group_name" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
// VM Size name
variable "vm_size" {
type = "string"
}
// Storage account type
variable "storage_type" {
type = "string"
}
variable "storage_id" {
type = "string"
}
variable "root_volume_size" {
type = "string"
}
// Count of etcd nodes to be created.
variable "etcd_count" {
type = "string"
}
// The base DNS domain of the cluster.
// Example: `azure.dev.coreos.systems`
variable "base_domain" {
type = "string"
}
// The name of the cluster.
variable "cluster_name" {
type = "string"
}
variable "public_ssh_key" {
type = "string"
}
variable "network_interface_ids" {
type = "list"
}
variable "versions" {
description = "(internal) Versions of the components to use"
type = "map"
}
variable "container_linux_channel" {
type = "string"
}
variable "container_linux_version" {
type = "string"
}
variable "const_internal_node_names" {
type = "list"
default = ["etcd-0", "etcd-1", "etcd-2", "etcd-3", "etcd-4"]
description = "(internal) The list of hostnames assigned to etcd member nodes."
}
variable "tls_enabled" {
default = false
}
variable "container_image" {
type = "string"
}
variable "extra_tags" {
type = "map"
}
variable "ign_etcd_dropin_id_list" {
type = "list"
}
variable "fault_domains" {
type = "string"
}
variable "ign_etcd_crt_id_list" {
type = "list"
}
variable "ign_profile_env_id" {
type = "string"
}
variable "ign_systemd_default_env_id" {
type = "string"
}
variable "ign_ntp_dropin_id" {
type = "string"
}

View File

@@ -0,0 +1,62 @@
data "ignition_config" "master" {
files = ["${compact(list(
data.ignition_file.cloud_provider_config.id,
data.ignition_file.kubeconfig.id,
var.ign_azure_udev_rules_id,
var.ign_installer_kubelet_env_id,
var.ign_installer_runtime_mappings_id,
var.ign_max_user_watches_id,
var.ign_nfs_config_id,
var.ign_ntp_dropin_id,
var.ign_profile_env_id,
var.ign_systemd_default_env_id,
))}",
"${var.ign_ca_cert_id_list}",
]
systemd = ["${compact(list(
var.ign_docker_dropin_id,
var.ign_locksmithd_service_id,
var.ign_k8s_node_bootstrap_service_id,
var.ign_kubelet_service_id,
var.ign_tx_off_service_id,
var.ign_bootkube_service_id,
var.ign_tectonic_service_id,
var.ign_bootkube_path_unit_id,
var.ign_tectonic_path_unit_id,
var.ign_update_ca_certificates_dropin_id,
var.ign_iscsi_service_id,
))}"]
users = [
"${data.ignition_user.core.id}",
]
}
data "ignition_user" "core" {
name = "core"
ssh_authorized_keys = [
"${file(var.public_ssh_key)}",
]
}
data "ignition_file" "kubeconfig" {
filesystem = "root"
path = "/etc/kubernetes/kubeconfig"
mode = 0644
content {
content = "${var.kubeconfig_content}"
}
}
data "ignition_file" "cloud_provider_config" {
filesystem = "root"
path = "/etc/kubernetes/cloud/config"
mode = 0600
content {
content = "${var.cloud_provider_config}"
}
}

View File

@@ -0,0 +1,68 @@
resource "azurerm_availability_set" "tectonic_masters" {
name = "${var.cluster_name}-masters"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
managed = true
platform_fault_domain_count = "${var.fault_domains}"
tags = "${merge(map(
"Name", "${var.cluster_name}-masters",
"tectonicClusterID", "${var.cluster_id}"),
var.extra_tags)}"
}
resource "azurerm_virtual_machine" "tectonic_master" {
count = "${var.master_count}"
name = "${var.cluster_name}-master-${count.index}"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
network_interface_ids = ["${var.network_interface_ids[count.index]}"]
vm_size = "${var.vm_size}"
availability_set_id = "${azurerm_availability_set.tectonic_masters.id}"
delete_os_disk_on_termination = true
storage_image_reference {
publisher = "CoreOS"
offer = "CoreOS"
sku = "${var.container_linux_channel}"
version = "${var.container_linux_version}"
}
storage_os_disk {
name = "master-${count.index}-os-${var.storage_id}"
managed_disk_type = "${var.storage_type}"
create_option = "FromImage"
caching = "ReadWrite"
os_type = "linux"
disk_size_gb = "${var.root_volume_size}"
}
os_profile {
computer_name = "${var.cluster_name}-master-${count.index}"
admin_username = "core"
admin_password = ""
custom_data = "${base64encode("${data.ignition_config.master.rendered}")}"
}
os_profile_linux_config {
disable_password_authentication = true
ssh_keys {
path = "/home/core/.ssh/authorized_keys"
key_data = "${file(var.public_ssh_key)}"
}
}
tags = "${merge(map(
"Name", "${var.cluster_name}-master-${count.index}",
"tectonicClusterID", "${var.cluster_id}"),
var.extra_tags)}"
lifecycle {
ignore_changes = [
"storage_os_disk",
"storage_data_disk",
]
}
}

View File

@@ -0,0 +1,3 @@
output "master_vm_ids" {
value = ["${azurerm_virtual_machine.tectonic_master.*.id}"]
}

View File

@@ -0,0 +1,99 @@
variable "container_linux_channel" {
type = "string"
}
variable "container_linux_version" {
type = "string"
}
variable "cloud_provider_config" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
variable "cluster_name" {
type = "string"
description = "The name of the cluster."
}
variable "extra_tags" {
type = "map"
}
variable "ign_azure_udev_rules_id" {
type = "string"
}
variable "ign_tx_off_service_id" {
type = "string"
}
variable "kubeconfig_content" {
type = "string"
}
variable "location" {
type = "string"
description = "Location is the Azure Location (East US, West US, etc)"
}
variable "master_count" {
type = "string"
description = "Count of master nodes to be created."
}
variable "network_interface_ids" {
type = "list"
description = "List of NICs to use for master VMs"
}
variable "public_ssh_key" {
type = "string"
}
variable "resource_group_name" {
type = "string"
}
variable "storage_id" {
type = "string"
}
variable "storage_type" {
type = "string"
description = "Storage account type"
}
variable "root_volume_size" {
type = "string"
}
variable "vm_size" {
type = "string"
description = "VM Size name"
}
variable "ign_bootkube_service_id" {
type = "string"
description = "The ID of the bootkube systemd service unit"
}
variable "ign_bootkube_path_unit_id" {
type = "string"
}
variable "ign_tectonic_service_id" {
type = "string"
description = "The ID of the tectonic installer systemd service unit"
}
variable "ign_tectonic_path_unit_id" {
type = "string"
}
variable "fault_domains" {
type = "string"
}

View File

@@ -0,0 +1,44 @@
variable "external_rsg_id" {
default = ""
type = "string"
}
variable "azure_location" {
type = "string"
}
variable "cluster_name" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
# Storage ID
resource "random_id" "storage_id" {
byte_length = 2
}
variable "extra_tags" {
type = "map"
}
resource "azurerm_resource_group" "tectonic_cluster" {
count = "${var.external_rsg_id == "" ? 1 : 0}"
location = "${var.azure_location}"
name = "tectonic-cluster-${var.cluster_name}"
tags = "${merge(map(
"Name", "tectonic-cluster-${var.cluster_name}",
"tectonicClusterID", "${var.cluster_id}"),
var.extra_tags)}"
}
output "name" {
value = "${var.external_rsg_id == "" ? element(concat(azurerm_resource_group.tectonic_cluster.*.name, list("")), 0) : element(split("/", var.external_rsg_id), 4)}"
}
output "storage_id" {
value = "${random_id.storage_id.hex}"
}

View File

@@ -0,0 +1,3 @@
output "udev-rules_id" {
value = "${data.ignition_file.azure_udev_rules.id}"
}

View File

@@ -0,0 +1,9 @@
data "ignition_file" "azure_udev_rules" {
filesystem = "root"
path = "/etc/udev/rules.d/66-azure-storage.rules"
mode = 0644
content {
content = "${file("${path.module}/resources/66-azure-storage.rules")}"
}
}

View File

@@ -0,0 +1,73 @@
resource "azurerm_public_ip" "api_ip" {
count = "${var.private_cluster ? 0 : 1}"
name = "${var.cluster_name}_api_ip"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
public_ip_address_allocation = "static"
domain_name_label = "${var.cluster_name}-api"
tags = "${merge(map(
"Name", "${var.cluster_name}-api",
"tectonicClusterID", "${var.cluster_id}"),
var.extra_tags)}"
}
resource "azurerm_lb_rule" "api_lb" {
count = "${var.private_cluster ? 0 : 1}"
name = "api-lb-rule-443-443"
resource_group_name = "${var.resource_group_name}"
loadbalancer_id = "${join("", azurerm_lb.tectonic_lb.*.id)}"
backend_address_pool_id = "${join("", azurerm_lb_backend_address_pool.api-lb.*.id)}"
probe_id = "${azurerm_lb_probe.api_lb.id}"
protocol = "tcp"
frontend_port = 443
backend_port = 443
frontend_ip_configuration_name = "api"
}
resource "azurerm_lb_probe" "api_lb" {
count = "${var.private_cluster ? 0 : 1}"
name = "api-lb-probe-443-up"
loadbalancer_id = "${azurerm_lb.tectonic_lb.id}"
resource_group_name = "${var.resource_group_name}"
protocol = "tcp"
port = 443
}
resource "azurerm_lb_backend_address_pool" "api-lb" {
count = "${var.private_cluster ? 0 : 1}"
name = "api-lb-pool"
resource_group_name = "${var.resource_group_name}"
loadbalancer_id = "${azurerm_lb.tectonic_lb.id}"
}
resource "azurerm_lb_rule" "ssh_lb" {
count = "${var.private_cluster ? 0 : 1}"
name = "ssh-lb"
resource_group_name = "${var.resource_group_name}"
loadbalancer_id = "${join("", azurerm_lb.tectonic_lb.*.id)}"
backend_address_pool_id = "${join("", azurerm_lb_backend_address_pool.api-lb.*.id)}"
probe_id = "${azurerm_lb_probe.ssh_lb.id}"
load_distribution = "SourceIP"
protocol = "tcp"
frontend_port = 22
backend_port = 22
frontend_ip_configuration_name = "api"
}
resource "azurerm_lb_probe" "ssh_lb" {
count = "${var.private_cluster ? 0 : 1}"
name = "ssh-lb-22-up"
loadbalancer_id = "${azurerm_lb.tectonic_lb.id}"
resource_group_name = "${var.resource_group_name}"
protocol = "tcp"
port = 22
}

View File

@@ -0,0 +1,54 @@
resource "azurerm_public_ip" "console_ip" {
count = "${var.private_cluster ? 0 : 1}"
name = "${var.cluster_name}_console_ip"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
public_ip_address_allocation = "static"
domain_name_label = "${var.cluster_name}"
tags = "${merge(map(
"Name", "${var.cluster_name}",
"tectonicClusterID", "${var.cluster_id}"),
var.extra_tags)}"
}
resource "azurerm_lb_rule" "console_lb_https" {
count = "${var.private_cluster ? 0 : 1}"
name = "${var.cluster_name}-console-lb-rule-443-32000"
resource_group_name = "${var.resource_group_name}"
loadbalancer_id = "${azurerm_lb.tectonic_lb.id}"
backend_address_pool_id = "${join("", azurerm_lb_backend_address_pool.api-lb.*.id)}"
probe_id = "${azurerm_lb_probe.console_lb.id}"
protocol = "tcp"
frontend_port = 443
backend_port = 32000
frontend_ip_configuration_name = "console"
}
resource "azurerm_lb_rule" "console_lb_identity" {
count = "${var.private_cluster ? 0 : 1}"
name = "${var.cluster_name}-console-lb-rule-80-32001"
resource_group_name = "${var.resource_group_name}"
loadbalancer_id = "${azurerm_lb.tectonic_lb.id}"
backend_address_pool_id = "${join("", azurerm_lb_backend_address_pool.api-lb.*.id)}"
probe_id = "${azurerm_lb_probe.console_lb.id}"
protocol = "tcp"
frontend_port = 80
backend_port = 32001
frontend_ip_configuration_name = "console"
}
resource "azurerm_lb_probe" "console_lb" {
count = "${var.private_cluster ? 0 : 1}"
name = "${var.cluster_name}-console-lb-probe-443-up"
loadbalancer_id = "${azurerm_lb.tectonic_lb.id}"
resource_group_name = "${var.resource_group_name}"
protocol = "tcp"
port = 32000
}

View File

@@ -0,0 +1,24 @@
resource "azurerm_lb" "tectonic_lb" {
count = "${var.private_cluster ? 0 : 1}"
name = "${var.cluster_name}-api-lb"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
frontend_ip_configuration {
name = "api"
public_ip_address_id = "${join("", azurerm_public_ip.api_ip.*.id)}"
private_ip_address_allocation = "dynamic"
}
frontend_ip_configuration {
name = "console"
public_ip_address_id = "${join("" , azurerm_public_ip.console_ip.*.id)}"
private_ip_address_allocation = "dynamic"
}
tags = "${merge(map(
"Name", "${var.cluster_name}-api-lb",
"tectonicClusterID", "${var.cluster_id}"),
var.extra_tags)}"
}

View File

@@ -0,0 +1,12 @@
resource "azurerm_network_interface" "etcd_nic" {
count = "${var.etcd_count}"
name = "${var.cluster_name}-etcd-nic-${count.index}"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
ip_configuration {
name = "tectonic_etcd_configuration"
subnet_id = "${var.external_master_subnet_id == "" ? join(" ", azurerm_subnet.master_subnet.*.id) : var.external_master_subnet_id }"
private_ip_address_allocation = "dynamic"
}
}

View File

@@ -0,0 +1,14 @@
resource "azurerm_network_interface" "tectonic_master" {
count = "${var.master_count}"
name = "${var.cluster_name}-master-${count.index}"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
enable_ip_forwarding = true
ip_configuration {
private_ip_address_allocation = "dynamic"
name = "${var.cluster_name}-MasterIPConfiguration"
subnet_id = "${var.external_master_subnet_id == "" ? join("",azurerm_subnet.master_subnet.*.id) : var.external_master_subnet_id}"
load_balancer_backend_address_pools_ids = ["${compact(azurerm_lb_backend_address_pool.api-lb.*.id)}"]
}
}

View File

@@ -0,0 +1,13 @@
resource "azurerm_network_interface" "tectonic_worker" {
count = "${var.worker_count}"
name = "${var.cluster_name}-worker-${count.index}"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
enable_ip_forwarding = true
ip_configuration {
private_ip_address_allocation = "dynamic"
name = "${var.cluster_name}-WorkerIPConfiguration"
subnet_id = "${var.external_worker_subnet_id == "" ? join("", azurerm_subnet.worker_subnet.*.id) : var.external_worker_subnet_id}"
}
}

View File

@@ -0,0 +1,125 @@
resource "azurerm_network_security_rule" "etcd_egress" {
count = "${var.external_nsg_master_id == "" && var.etcd_count > 0 ? 1 : 0}"
name = "${var.cluster_name}-etcd-out"
description = "${var.cluster_name} etcd - Outbound"
priority = 2000
direction = "Outbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "*"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "etcd_ingress_ssh" {
count = "${var.external_nsg_master_id == "" && var.etcd_count > 0 ? 1 : 0}"
name = "${var.cluster_name}-etcd-in-ssh"
description = "${var.cluster_name} etcd - SSH"
priority = 400
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "22"
# TODO: Reference subnet
source_address_prefix = "${var.ssh_network_internal}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "etcd_ingress_ssh_admin" {
count = "${var.external_nsg_master_id == "" && var.etcd_count > 0 ? 1 : 0}"
name = "${var.cluster_name}-etcd-in-ssh-external"
description = "${var.cluster_name} etcd - SSH external"
priority = 405
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "22"
# TODO: Reference subnet
source_address_prefix = "${var.ssh_network_external}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "etcd_ingress_ssh_from_master" {
count = "${var.external_nsg_master_id == "" && var.etcd_count > 0 ? 1 : 0}"
name = "${var.cluster_name}-etcd-in-ssh-master"
description = "${var.cluster_name} etcd - SSH from master"
priority = 410
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "22"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "etcd_ingress_client_self" {
count = "${var.external_nsg_master_id == "" && var.etcd_count > 0 ? 1 : 0}"
name = "${var.cluster_name}-etcd-in-client-self"
description = "${var.cluster_name} etcd - etcd client"
priority = 415
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "2379"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "etcd_ingress_client_master" {
count = "${var.external_nsg_master_id == "" && var.etcd_count > 0 ? 1 : 0}"
name = "${var.cluster_name}-etcd-in-client-master"
description = "${var.cluster_name} etcd - etcd client from master"
priority = 420
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "2379"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "etcd_ingress_peer" {
count = "${var.external_nsg_master_id == "" && var.etcd_count > 0 ? 1 : 0}"
name = "${var.cluster_name}-etcd-in-peer"
description = "${var.cluster_name} etcd - etcd peer"
priority = 425
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "2380"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}

View File

@@ -0,0 +1,242 @@
resource "azurerm_network_security_group" "master" {
count = "${var.external_nsg_master_id == "" ? 1 : 0}"
name = "${var.cluster_name}-master"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
}
### LB rules
resource "azurerm_network_security_rule" "alb_probe" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-alb-probe"
description = "${var.cluster_name} master - Azure Load Balancer probe"
priority = 295
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "AzureLoadBalancer"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
# TODO: Fix NSG name and source
resource "azurerm_network_security_rule" "api_ingress_https" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-api-in-https"
description = "${var.cluster_name} Kubernetes API"
priority = 300
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "443"
# TODO: Ternary on private implementation
source_address_prefix = "*"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "console_ingress_https" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-console-in-https"
description = "${var.cluster_name} Azure Load Balancer - Tectonic Console"
priority = 305
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "443"
# TODO: Ternary on private implementation
source_address_prefix = "*"
destination_address_prefix = "AzureLoadBalancer"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "console_ingress_http" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-console-in-http"
description = "${var.cluster_name} Azure Load Balancer - Tectonic Identity"
priority = 310
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "80"
# TODO: Ternary on private implementation
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "AzureLoadBalancer"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
### Master node rules
resource "azurerm_network_security_rule" "master_egress" {
count = "${var.external_nsg_master_id == "" ? 1 : 0}"
name = "${var.cluster_name}-master-out"
description = "${var.cluster_name} master - Outbound"
priority = 2005
direction = "Outbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "*"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "master_ingress_ssh" {
count = "${var.external_nsg_master_id == "" ? 1 : 0}"
name = "${var.cluster_name}-master-in-ssh"
description = "${var.cluster_name} master - SSH"
priority = 500
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "22"
# TODO: Reference subnet
source_address_prefix = "${var.ssh_network_internal}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "master_ingress_ssh_admin" {
count = "${var.external_nsg_master_id == "" ? 1 : 0}"
name = "${var.cluster_name}-master-in-ssh-external"
description = "${var.cluster_name} master - SSH external"
priority = 505
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "22"
# TODO: Reference subnet
source_address_prefix = "${var.ssh_network_external}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "master_ingress_flannel" {
count = "${var.external_nsg_master_id == "" ? 1 : 0}"
name = "${var.cluster_name}-master-in-udp-4789"
description = "${var.cluster_name} master - flannel"
priority = 510
direction = "Inbound"
access = "Allow"
protocol = "UDP"
source_port_range = "*"
destination_port_range = "4789"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "master_ingress_node_exporter_from_master" {
count = "${var.external_nsg_master_id == "" ? 1 : 0}"
name = "${var.cluster_name}-master-in-tcp-9100-master"
description = "${var.cluster_name} master - Prometheus node exporter from master"
priority = 515
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "9100"
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "master_ingress_node_exporter_from_worker" {
count = "${var.external_nsg_master_id == "" ? 1 : 0}"
name = "${var.cluster_name}-master-in-tcp-9100-worker"
description = "${var.cluster_name} master - Prometheus node exporter from worker"
priority = 520
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "9100"
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
# TODO: Review NSG
resource "azurerm_network_security_rule" "master_ingress_k8s_nodeport_from_alb" {
count = "${var.external_nsg_master_id == "" ? 1 : 0}"
name = "${var.cluster_name}-master-in-any-30000-32767-alb"
description = "${var.cluster_name} master - Kubernetes NodePort range from Azure Load Balancer"
priority = 525
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "30000-32767"
# TODO: Reference subnet
source_address_prefix = "AzureLoadBalancer"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
# TODO: Review NSG
resource "azurerm_network_security_rule" "master_ingress_k8s_nodeport" {
count = "${var.external_nsg_master_id == "" ? 1 : 0}"
name = "${var.cluster_name}-master-in-any-30000-32767"
description = "${var.cluster_name} master - Kubernetes NodePort range"
priority = 530
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "30000-32767"
# TODO: Reference subnet
source_address_prefix = "*"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}
resource "azurerm_network_security_rule" "master_ingress_kubelet_secure" {
count = "${var.external_nsg_master_id == "" ? 1 : 0}"
name = "${var.cluster_name}-master-in-tcp-10255-vnet"
description = "${var.cluster_name} master - kubelet"
priority = 535
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "10255"
# TODO: CR on how open this should be
# TODO: Reference subnet
source_address_prefix = "VirtualNetwork"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.master.name}"
}

View File

@@ -0,0 +1,169 @@
resource "azurerm_network_security_group" "worker" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-worker"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
}
resource "azurerm_network_security_rule" "worker_egress" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-worker-out"
description = "${var.cluster_name} worker - Outbound"
priority = 2010
direction = "Outbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "*"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.worker.name}"
}
resource "azurerm_network_security_rule" "worker_ingress_ssh" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-worker-in-ssh"
description = "${var.cluster_name} worker - SSH"
priority = 600
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "22"
# TODO: Reference subnet
source_address_prefix = "${var.ssh_network_internal}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.worker.name}"
}
resource "azurerm_network_security_rule" "worker_ingress_ssh_admin" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-worker-in-ssh-external"
description = "${var.cluster_name} worker - SSH external"
priority = 605
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "22"
# TODO: Reference subnet
source_address_prefix = "${var.ssh_network_external}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.worker.name}"
}
# TODO: Determine if we need two rules for this
resource "azurerm_network_security_rule" "worker_ingress_k8s_nodeport" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-worker-in-any-30000-32767"
description = "${var.cluster_name} worker - Kubernetes NodePort range"
priority = 610
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "30000-32767"
source_address_prefix = "VirtualNetwork"
destination_address_prefix = "*"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.worker.name}"
}
resource "azurerm_network_security_rule" "worker_ingress_flannel" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-worker-in-udp-4789"
description = "${var.cluster_name} worker - flannel"
priority = 615
direction = "Inbound"
access = "Allow"
protocol = "UDP"
source_port_range = "*"
destination_port_range = "4789"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.worker.name}"
}
resource "azurerm_network_security_rule" "worker_ingress_kubelet_secure" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-worker-in-tcp-10255-vnet"
description = "${var.cluster_name} worker - kubelet"
priority = 620
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "10255"
# TODO: CR on how open this should be
# TODO: Reference subnet
source_address_prefix = "VirtualNetwork"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.worker.name}"
}
resource "azurerm_network_security_rule" "worker_ingress_node_exporter_from_worker" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-worker-in-tcp-9100-vnet"
description = "${var.cluster_name} worker - Prometheus node exporter from worker"
priority = 625
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "9100"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.worker.name}"
}
resource "azurerm_network_security_rule" "worker_ingress_node_exporter_from_master" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-worker-in-tcp-9100-master"
description = "${var.cluster_name} worker - Prometheus node exporter from master"
priority = 630
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "9100"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.worker.name}"
}
resource "azurerm_network_security_rule" "worker_ingress_heapster_from_master" {
count = "${var.external_nsg_worker_id == "" ? 1 : 0}"
name = "${var.cluster_name}-worker-in-tcp-4194-master"
description = "${var.cluster_name} worker - Heapster from master"
priority = 635
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "4194"
# TODO: Reference subnet
source_address_prefix = "${var.vnet_cidr_block}"
destination_address_prefix = "${var.vnet_cidr_block}"
resource_group_name = "${var.resource_group_name}"
network_security_group_name = "${azurerm_network_security_group.worker.name}"
}

View File

@@ -0,0 +1,84 @@
locals {
# A regular expression that parses a Azure subnet id to extract subnet name.
const_id_to_subnet_name_regex = "/^/subscriptions/[-\\w]+/resourceGroups/[-\\w]+/providers/Microsoft.Network/virtualNetworks/[.\\w]+/subnets/([.\\w-]+)$/"
# A regular expression that parses Azure resource IDs into component identifiers
const_id_to_group_name_regex = "/^/subscriptions/[-\\w]+/resourceGroups/([\\w()-\\.]+)/providers/[.\\w]+/[.\\w]+/([.\\w-]+)$/"
}
output "vnet_id" {
value = "${var.external_vnet_id == "" ? element(concat(azurerm_virtual_network.tectonic_vnet.*.name, list("")), 0) : replace(var.external_vnet_id, local.const_id_to_group_name_regex, "$2")}"
}
output "master_subnet" {
value = "${var.external_master_subnet_id == "" ? element(concat(azurerm_subnet.master_subnet.*.id, list("")), 0) : var.external_master_subnet_id}"
}
output "worker_subnet" {
value = "${var.external_worker_subnet_id == "" ? element(concat(azurerm_subnet.worker_subnet.*.id, list("")), 0) : var.external_worker_subnet_id}"
}
output "worker_subnet_name" {
value = "${var.external_worker_subnet_id == "" ? element(concat(azurerm_subnet.worker_subnet.*.name, list("")), 0) : replace(var.external_worker_subnet_id, local.const_id_to_subnet_name_regex, "$1")}"
}
output "vnet_resource_group" {
value = "${var.external_vnet_id == "" ? "" : replace(var.external_vnet_id, local.const_id_to_group_name_regex, "$1")}"
}
# TODO: Allow user to provide their own network
output "etcd_cidr" {
value = "${element(concat(azurerm_subnet.master_subnet.*.address_prefix, list("")), 0)}"
}
output "master_cidr" {
value = "${element(concat(azurerm_subnet.master_subnet.*.address_prefix, list("")), 0)}"
}
output "worker_cidr" {
value = "${element(concat(azurerm_subnet.worker_subnet.*.address_prefix, list("")), 0)}"
}
output "worker_nsg_name" {
value = "${var.external_nsg_worker_id == "" ? element(concat(azurerm_network_security_group.worker.*.name, list("")), 0) : var.external_nsg_worker_id}"
}
output "etcd_network_interface_ids" {
value = ["${azurerm_network_interface.etcd_nic.*.id}"]
}
output "etcd_endpoints" {
value = "${azurerm_network_interface.etcd_nic.*.private_ip_address}"
}
output "master_network_interface_ids" {
value = ["${azurerm_network_interface.tectonic_master.*.id}"]
}
output "worker_network_interface_ids" {
value = ["${azurerm_network_interface.tectonic_worker.*.id}"]
}
output "master_private_ip_addresses" {
value = ["${azurerm_network_interface.tectonic_master.*.private_ip_address}"]
}
output "worker_private_ip_addresses" {
value = ["${azurerm_network_interface.tectonic_worker.*.private_ip_address}"]
}
output "api_ip_addresses" {
value = ["${split("|", var.private_cluster ? join("|", azurerm_network_interface.tectonic_master.*.private_ip_address) : join("|", azurerm_public_ip.api_ip.*.ip_address))}"]
}
output "console_ip_addresses" {
value = ["${split("|", var.private_cluster ? join("|", azurerm_network_interface.tectonic_worker.*.private_ip_address) : join("|", azurerm_public_ip.console_ip.*.ip_address))}"]
}
output "ingress_fqdn" {
value = "${var.base_domain == "" ? element(concat(azurerm_public_ip.console_ip.*.fqdn, list("")), 0) : "${var.cluster_name}.${var.base_domain}${var.private_cluster ? ":32000" : ""}"}"
}
output "api_fqdn" {
value = "${var.base_domain == "" ? element(concat(azurerm_public_ip.api_ip.*.fqdn, list("")), 0) : "${var.cluster_name}-api.${var.base_domain}"}"
}

View File

@@ -0,0 +1,96 @@
variable "cluster_name" {
type = "string"
}
variable "cluster_id" {
type = "string"
}
// The base DNS domain of the cluster.
// Example: `azure.dev.coreos.systems`
variable "base_domain" {
type = "string"
}
variable "resource_group_name" {
type = "string"
}
variable "vnet_cidr_block" {
type = "string"
}
variable "location" {
type = "string"
}
variable "external_vnet_id" {
type = "string"
default = ""
}
variable "external_master_subnet_id" {
type = "string"
default = ""
}
variable "external_worker_subnet_id" {
type = "string"
default = ""
}
variable "external_nsg_master_id" {
type = "string"
default = ""
}
variable "external_nsg_worker_id" {
type = "string"
default = ""
}
variable "etcd_cidr" {
type = "string"
default = ""
}
variable "etcd_count" {
type = "string"
default = ""
}
variable "master_cidr" {
type = "string"
default = ""
}
variable "worker_cidr" {
type = "string"
default = ""
}
variable "ssh_network_internal" {
type = "string"
default = ""
}
variable "ssh_network_external" {
type = "string"
default = ""
}
variable "master_count" {
type = "string"
}
variable "worker_count" {
type = "string"
}
variable "extra_tags" {
type = "map"
}
variable "private_cluster" {
default = false
}

View File

@@ -0,0 +1,30 @@
resource "azurerm_virtual_network" "tectonic_vnet" {
count = "${var.external_vnet_id == "" ? 1 : 0 }"
name = "${var.cluster_name}"
resource_group_name = "${var.resource_group_name}"
address_space = ["${var.vnet_cidr_block}"]
location = "${var.location}"
tags = "${merge(map(
"Name", "${var.cluster_name}_vnet",
"tectonicClusterID", "${var.cluster_id}"),
var.extra_tags)}"
}
resource "azurerm_subnet" "master_subnet" {
count = "${var.external_master_subnet_id == "" ? 1 : 0}"
name = "${var.cluster_name}_master_subnet"
resource_group_name = "${var.external_vnet_id == "" ? var.resource_group_name : replace(var.external_vnet_id, "${var.const_id_to_group_name_regex}", "$1")}"
virtual_network_name = "${var.external_vnet_id == "" ? join("",azurerm_virtual_network.tectonic_vnet.*.name) : replace(var.external_vnet_id, "${var.const_id_to_group_name_regex}", "$2")}"
address_prefix = "${cidrsubnet(var.vnet_cidr_block, 4, 0)}"
network_security_group_id = "${var.external_nsg_master_id == "" ? azurerm_network_security_group.master.id : var.external_nsg_master_id}"
}
resource "azurerm_subnet" "worker_subnet" {
count = "${var.external_worker_subnet_id == "" ? 1 : 0}"
name = "${var.cluster_name}_worker_subnet"
resource_group_name = "${var.external_vnet_id == "" ? var.resource_group_name : replace(var.external_vnet_id, "${var.const_id_to_group_name_regex}", "$1")}"
virtual_network_name = "${var.external_vnet_id == "" ? join("",azurerm_virtual_network.tectonic_vnet.*.name) : replace(var.external_vnet_id, "${var.const_id_to_group_name_regex}", "$2") }"
address_prefix = "${cidrsubnet(var.vnet_cidr_block, 4, 1)}"
network_security_group_id = "${var.external_nsg_worker_id == "" ? azurerm_network_security_group.worker.id : var.external_nsg_worker_id}"
}

View File

@@ -0,0 +1,58 @@
data "ignition_config" "worker" {
files = ["${compact(list(
data.ignition_file.cloud-provider-config.id,
data.ignition_file.kubeconfig.id,
var.ign_azure_udev_rules_id,
var.ign_installer_kubelet_env_id,
var.ign_installer_runtime_mappings_id,
var.ign_max_user_watches_id,
var.ign_nfs_config_id,
var.ign_ntp_dropin_id,
var.ign_profile_env_id,
var.ign_systemd_default_env_id,
))}",
"${var.ign_ca_cert_id_list}",
]
systemd = [
"${var.ign_docker_dropin_id}",
"${var.ign_iscsi_service_id}",
"${var.ign_k8s_node_bootstrap_service_id}",
"${var.ign_kubelet_service_id}",
"${var.ign_locksmithd_service_id}",
"${var.ign_tx_off_service_id}",
"${var.ign_update_ca_certificates_dropin_id}",
]
users = [
"${data.ignition_user.core.id}",
]
}
data "ignition_file" "kubeconfig" {
filesystem = "root"
path = "/etc/kubernetes/kubeconfig"
mode = 0644
content {
content = "${var.kubeconfig_content}"
}
}
data "ignition_file" "cloud-provider-config" {
filesystem = "root"
path = "/etc/kubernetes/cloud/config"
mode = 0600
content {
content = "${var.cloud_provider_config}"
}
}
data "ignition_user" "core" {
name = "core"
ssh_authorized_keys = [
"${file(var.public_ssh_key)}",
]
}

View File

@@ -0,0 +1,3 @@
output "availability_set_name" {
value = "${azurerm_availability_set.tectonic_workers.name}"
}

View File

@@ -0,0 +1,92 @@
variable "container_linux_channel" {
type = "string"
}
variable "container_linux_version" {
type = "string"
}
variable "cloud_provider" {
type = "string"
default = "azure"
}
variable "cloud_provider_config" {
description = "Content of cloud provider config"
type = "string"
}
variable "cluster_id" {
type = "string"
}
variable "cluster_name" {
type = "string"
description = "The name of the cluster."
}
variable "extra_tags" {
type = "map"
}
variable "ign_azure_udev_rules_id" {
type = "string"
}
variable "ign_tx_off_service_id" {
type = "string"
}
variable "kubeconfig_content" {
type = "string"
default = ""
}
variable "location" {
type = "string"
description = "Location is the Azure Location (East US, West US, etc)"
}
variable "network_interface_ids" {
type = "list"
description = "List of NICs to use for master VMs"
}
variable "public_ssh_key" {
type = "string"
}
variable "resource_group_name" {
type = "string"
}
variable "storage_id" {
type = "string"
}
variable "storage_type" {
type = "string"
description = "Storage account type"
}
variable "root_volume_size" {
type = "string"
}
variable "tectonic_kube_dns_service_ip" {
type = "string"
}
variable "vm_size" {
type = "string"
description = "VM Size name"
}
variable "worker_count" {
type = "string"
description = "Count of worker nodes to be created."
}
variable "fault_domains" {
type = "string"
}

View File

@@ -0,0 +1,68 @@
resource "azurerm_availability_set" "tectonic_workers" {
name = "${var.cluster_name}-workers"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
managed = true
platform_fault_domain_count = "${var.fault_domains}"
tags = "${merge(map(
"Name", "${var.cluster_name}-workers",
"tectonicClusterID", "${var.cluster_id}"),
var.extra_tags)}"
}
resource "azurerm_virtual_machine" "tectonic_worker" {
count = "${var.worker_count}"
name = "${var.cluster_name}-worker-${count.index}"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
network_interface_ids = ["${var.network_interface_ids[count.index]}"]
vm_size = "${var.vm_size}"
availability_set_id = "${azurerm_availability_set.tectonic_workers.id}"
delete_os_disk_on_termination = true
storage_image_reference {
publisher = "CoreOS"
offer = "CoreOS"
sku = "${var.container_linux_channel}"
version = "${var.container_linux_version}"
}
storage_os_disk {
name = "worker-${count.index}-os-${var.storage_id}"
managed_disk_type = "${var.storage_type}"
create_option = "FromImage"
caching = "ReadWrite"
os_type = "linux"
disk_size_gb = "${var.root_volume_size}"
}
os_profile {
computer_name = "${var.cluster_name}-worker-${count.index}"
admin_username = "core"
admin_password = ""
custom_data = "${base64encode("${data.ignition_config.worker.rendered}")}"
}
os_profile_linux_config {
disable_password_authentication = true
ssh_keys {
path = "/home/core/.ssh/authorized_keys"
key_data = "${file(var.public_ssh_key)}"
}
}
tags = "${merge(map(
"Name", "${var.cluster_name}-worker-${count.index}",
"tectonicClusterID", "${var.cluster_id}"),
var.extra_tags)}"
lifecycle {
ignore_changes = [
"storage_os_disk",
"storage_data_disk",
]
}
}

View File

@@ -0,0 +1,85 @@
# kubeconfig (/auth/kubeconfig)
data "template_file" "kubeconfig" {
template = "${file("${path.module}/resources/kubeconfig")}"
vars {
root_ca_cert = "${base64encode(var.root_ca_cert_pem)}"
admin_cert = "${base64encode(var.admin_cert_pem)}"
admin_key = "${base64encode(var.admin_key_pem)}"
server = "${var.kube_apiserver_url}"
cluster_name = "${var.cluster_name}"
}
}
data "ignition_file" "kubeconfig" {
filesystem = "root"
path = "/opt/tectonic/auth/kubeconfig"
mode = "0600"
content {
content = "${data.template_file.kubeconfig.rendered}"
}
}
# kubeconfig-kubelet
data "template_file" "kubeconfig-kubelet" {
template = "${file("${path.module}/resources/kubeconfig-kubelet")}"
vars {
root_ca_cert = "${base64encode(var.root_ca_cert_pem)}"
client_cert = "${base64encode(var.kubelet_cert_pem)}"
client_key = "${base64encode(var.kubelet_key_pem)}"
server = "${var.kube_apiserver_url}"
cluster_name = "${var.cluster_name}"
}
}
data "ignition_file" "kubeconfig-kubelet" {
filesystem = "root"
path = "/opt/tectonic/auth/kubeconfig-kubelet"
mode = "0600"
content {
content = "${data.template_file.kubeconfig-kubelet.rendered}"
}
}
# bootkube.sh
data "template_file" "bootkube_sh" {
template = "${file("${path.module}/resources/bootkube.sh")}"
vars {
bootkube_image = "${var.container_images["bootkube"]}"
kube_core_renderer_image = "${var.container_images["kube_core_renderer"]}"
tnc_operator_image = "${var.container_images["tnc_operator"]}"
etcd_cert_signer_image = "${var.container_images["etcd_cert_signer"]}"
etcdctl_image = "${var.container_images["etcd"]}"
etcd_cluster = "${join(",", data.template_file.initial_cluster.*.rendered)}"
}
}
data "ignition_file" "bootkube_sh" {
filesystem = "root"
path = "/opt/tectonic/bootkube.sh"
mode = "0755"
content {
content = "${data.template_file.bootkube_sh.rendered}"
}
}
# bootkube.service (available as output variable)
data "template_file" "bootkube_service" {
template = "${file("${path.module}/resources/bootkube.service")}"
}
data "ignition_systemd_unit" "bootkube_service" {
name = "bootkube.service"
enabled = false
content = "${data.template_file.bootkube_service.rendered}"
}
data "template_file" "initial_cluster" {
count = "${length(var.etcd_endpoints)}"
template = "https://${var.etcd_endpoints[count.index]}:2379"
}

View File

@@ -0,0 +1,162 @@
# Self-hosted manifests (resources/generated/manifests/)
resource "template_dir" "bootkube" {
source_dir = "${path.module}/resources/manifests"
destination_dir = "./generated/manifests"
vars {
hyperkube_image = "${var.container_images["hyperkube"]}"
pod_checkpointer_image = "${var.container_images["pod_checkpointer"]}"
kubedns_image = "${var.container_images["kubedns"]}"
kubednsmasq_image = "${var.container_images["kubednsmasq"]}"
kubedns_sidecar_image = "${var.container_images["kubedns_sidecar"]}"
# Choose the etcd endpoints to use.
# 1. If self-hosted etcd is enabled, then use
# var.etcd_service_ip.
# 2. Else if no etcd TLS certificates are provided, i.e. we bootstrap etcd
# nodes ourselves (using http), then use insecure http var.etcd_endpoints.
# 3. Else (if etcd TLS certific are provided), then use the secure https
# var.etcd_endpoints.
etcd_servers = "${
var.self_hosted_etcd != ""
? format("https://%s:2379", cidrhost(var.service_cidr, 15))
: var.etcd_tls_enabled
? join(",", formatlist("https://%s:2379", var.etcd_endpoints))
: join(",", formatlist("http://%s:2379", var.etcd_endpoints))
}"
etcd_service_ip = "${cidrhost(var.service_cidr, 15)}"
bootstrap_etcd_service_ip = "${cidrhost(var.service_cidr, 20)}"
cloud_provider = "${var.cloud_provider}"
cloud_provider_config = "${var.cloud_provider_config}"
cloud_provider_config_flag = "${var.cloud_provider_config != "" ? "- --cloud-config=/etc/kubernetes/cloud/config" : "# no cloud provider config given"}"
cluster_cidr = "${var.cluster_cidr}"
service_cidr = "${var.service_cidr}"
kube_dns_service_ip = "${cidrhost(var.service_cidr, 10)}"
advertise_address = "${var.advertise_address}"
anonymous_auth = "${var.anonymous_auth}"
oidc_issuer_url = "${var.oidc_issuer_url}"
oidc_client_id = "${var.oidc_client_id}"
oidc_username_claim = "${var.oidc_username_claim}"
oidc_groups_claim = "${var.oidc_groups_claim}"
oidc_ca_cert = "${base64encode(var.oidc_ca_cert)}"
kube_ca_cert = "${base64encode(var.kube_ca_cert_pem)}"
apiserver_key = "${base64encode(var.apiserver_key_pem)}"
apiserver_cert = "${base64encode(var.apiserver_cert_pem)}"
serviceaccount_pub = "${base64encode(tls_private_key.service_account.public_key_pem)}"
serviceaccount_key = "${base64encode(tls_private_key.service_account.private_key_pem)}"
etcd_ca_flag = "${var.etcd_ca_cert_pem != "" ? "- --etcd-cafile=/etc/kubernetes/secrets/etcd-client-ca.crt" : "# no etcd-client-ca.crt given" }"
etcd_cert_flag = "${var.etcd_client_cert_pem != "" ? "- --etcd-certfile=/etc/kubernetes/secrets/etcd-client.crt" : "# no etcd-client.crt given" }"
etcd_key_flag = "${var.etcd_client_key_pem != "" ? "- --etcd-keyfile=/etc/kubernetes/secrets/etcd-client.key" : "# no etcd-client.key given" }"
etcd_ca_cert = "${base64encode(var.etcd_ca_cert_pem)}"
etcd_client_cert = "${base64encode(var.etcd_client_cert_pem)}"
etcd_client_key = "${base64encode(var.etcd_client_key_pem)}"
kubernetes_version = "${replace(var.versions["kubernetes"], "+", "-")}"
master_count = "${var.master_count}"
node_monitor_grace_period = "${var.node_monitor_grace_period}"
pod_eviction_timeout = "${var.pod_eviction_timeout}"
cloud_provider_profile = "${var.cloud_provider != "" ? "${var.cloud_provider}" : "metal"}"
cloud_config_path = "${var.cloud_config_path}"
}
}
# Self-hosted bootstrapping manifests (resources/generated/manifests-bootstrap/)
resource "template_dir" "bootkube_bootstrap" {
source_dir = "${path.module}/resources/bootstrap-manifests"
destination_dir = "./generated/bootstrap-manifests"
vars {
hyperkube_image = "${var.container_images["hyperkube"]}"
etcd_image = "${var.container_images["etcd"]}"
# Choose the etcd endpoints to use.
# 1. If self-hosted etcd mode is enabled, then use
# var.etcd_service_ip.
# 2. Else if no etcd TLS certificates are provided, i.e. we bootstrap etcd
# nodes ourselves (using http), then use insecure http var.etcd_endpoints.
# 3. Else (if etcd TLS certific are provided), then use the secure https
# var.etcd_endpoints.
etcd_servers = "${
var.self_hosted_etcd != ""
? format("https://%s:2379,https://127.0.0.1:12379", cidrhost(var.service_cidr, 15))
: var.etcd_tls_enabled
? join(",", formatlist("https://%s:2379", var.etcd_endpoints))
: join(",", formatlist("http://%s:2379", var.etcd_endpoints))
}"
etcd_ca_flag = "${var.etcd_ca_cert_pem != "" ? "- --etcd-cafile=/etc/kubernetes/secrets/etcd-client-ca.crt" : "# no etcd-client-ca.crt given" }"
etcd_cert_flag = "${var.etcd_client_cert_pem != "" ? "- --etcd-certfile=/etc/kubernetes/secrets/etcd-client.crt" : "# no etcd-client.crt given" }"
etcd_key_flag = "${var.etcd_client_key_pem != "" ? "- --etcd-keyfile=/etc/kubernetes/secrets/etcd-client.key" : "# no etcd-client.key given" }"
cloud_provider = "${var.cloud_provider}"
cloud_provider_config = "${var.cloud_provider_config}"
cloud_provider_config_flag = "${var.cloud_provider_config != "" ? "- --cloud-config=/etc/kubernetes/cloud/config" : "# no cloud provider config given"}"
advertise_address = "${var.advertise_address}"
cluster_cidr = "${var.cluster_cidr}"
service_cidr = "${var.service_cidr}"
}
}
# kubeconfig (resources/generated/auth/kubeconfig)
data "template_file" "kubeconfig" {
template = "${file("${path.module}/resources/kubeconfig")}"
vars {
kube_ca_cert = "${base64encode(var.kube_ca_cert_pem)}"
kubelet_cert = "${base64encode(var.kubelet_cert_pem)}"
kubelet_key = "${base64encode(var.kubelet_key_pem)}"
server = "${var.kube_apiserver_url}"
cluster_name = "${var.cluster_name}"
}
}
resource "local_file" "kubeconfig" {
content = "${data.template_file.kubeconfig.rendered}"
filename = "./generated/auth/kubeconfig"
}
# bootkube.sh (resources/generated/bootkube.sh)
data "template_file" "bootkube_sh" {
template = "${file("${path.module}/resources/bootkube.sh")}"
vars {
bootkube_image = "${var.container_images["bootkube"]}"
}
}
resource "local_file" "bootkube_sh" {
content = "${data.template_file.bootkube_sh.rendered}"
filename = "./generated/bootkube.sh"
}
# bootkube.service (available as output variable)
data "template_file" "bootkube_service" {
template = "${file("${path.module}/resources/bootkube.service")}"
}
data "ignition_systemd_unit" "bootkube_service" {
name = "bootkube.service"
enabled = false
content = "${data.template_file.bootkube_service.rendered}"
}
# bootkube.path (available as output variable)
data "template_file" "bootkube_path_unit" {
template = "${file("${path.module}/resources/bootkube.path")}"
}
data "ignition_systemd_unit" "bootkube_path_unit" {
name = "bootkube.path"
enabled = true
content = "${data.template_file.bootkube_path_unit.rendered}"
}

View File

@@ -0,0 +1,32 @@
output "kubeconfig-kubelet" {
value = "${data.template_file.kubeconfig-kubelet.rendered}"
}
output "systemd_service_id" {
value = "${data.ignition_systemd_unit.bootkube_service.id}"
}
output "kube_dns_service_ip" {
value = "${cidrhost(var.service_cidr, 10)}"
}
output "kubeconfig_rendered" {
value = "${data.template_file.kubeconfig.rendered}"
}
output "kubeconfig-kubelet_rendered" {
value = "${data.template_file.kubeconfig-kubelet.rendered}"
}
output "ignition_file_id_list" {
value = ["${flatten(list(
list(
data.ignition_file.bootkube_sh.id,
data.ignition_file.kubeconfig.id,
data.ignition_file.kubeconfig-kubelet.id,
data.ignition_file.service_account_key.id,
data.ignition_file.service_account_crt.id,
),
data.ignition_file.manifest_file_list.*.id,
))}"]
}

View File

@@ -0,0 +1,55 @@
# This output is meant to be used to inject a dependency on the generated
# assets. As of Terraform v0.9, it is difficult to make a module depend on
# another module (no depends_on, no triggers), or to make a data source
# depend on a module (no depends_on, no triggers, generally no dummy variable).
#
# For instance, using the 'archive_file' data source against the generated
# assets, which is a common use-case, is tricky. There is no mechanism for
# defining explicit dependencies and the only available variables are for the
# source, destination and archive type, leaving little opportunities for us to
# inject a dependency. Thanks to the property described below, this output can
# be used as part of the output filename, in order to enforce the creation of
# the archive after the assets have been properly generated.
#
# Both localfile and template_dir providers compute their IDs by hashing
# the content of the resources on disk. Because this output is computed from the
# combination of all the resources' IDs, it can't be guessed and can only be
# interpolated once the assets have all been created.
output "id" {
value = "${sha1("
${local_file.kubeconfig.id}
${local_file.bootkube_sh.id}
${template_dir.bootkube.id} ${template_dir.bootkube_bootstrap.id}
${join(" ",
template_dir.etcd_manifests.*.id,
template_dir.etcd_bootstrap_manifests.*.id,
local_file.etcd_bootstrap_service.*.id,
local_file.migrate_etcd_cluster.*.id,
local_file.migrate_etcd_cluster_pv_backup.*.id,
)}
")}"
}
output "kubeconfig" {
value = "${data.template_file.kubeconfig.rendered}"
}
output "systemd_service_rendered" {
value = "${data.template_file.bootkube_service.rendered}"
}
output "systemd_service_id" {
value = "${data.ignition_systemd_unit.bootkube_service.id}"
}
output "systemd_path_unit_rendered" {
value = "${data.template_file.bootkube_path_unit.rendered}"
}
output "systemd_path_unit_id" {
value = "${data.ignition_systemd_unit.bootkube_path_unit.id}"
}
output "kube_dns_service_ip" {
value = "${cidrhost(var.service_cidr, 10)}"
}

View File

@@ -0,0 +1,80 @@
resource "template_dir" "etcd_manifests" {
count = "${var.self_hosted_etcd != "" ? 1 : 0}"
source_dir = "${path.module}/resources/self-hosted-etcd/manifests"
destination_dir = "./generated/etcd/manifests"
vars {
etcd_operator_image = "${var.container_images["etcd_operator"]}"
etcd_service_ip = "${cidrhost(var.service_cidr, 15)}"
kenc_image = "${var.container_images["kenc"]}"
etcd_ca_cert = "${base64encode(var.etcd_ca_cert_pem)}"
etcd_server_cert = "${base64encode(var.etcd_server_cert_pem)}"
etcd_server_key = "${base64encode(var.etcd_server_key_pem)}"
etcd_client_cert = "${base64encode(var.etcd_client_cert_pem)}"
etcd_client_key = "${base64encode(var.etcd_client_key_pem)}"
etcd_peer_cert = "${base64encode(var.etcd_peer_cert_pem)}"
etcd_peer_key = "${base64encode(var.etcd_peer_key_pem)}"
}
}
resource "template_dir" "etcd_bootstrap_manifests" {
count = "${var.self_hosted_etcd != "" ? 1 : 0}"
source_dir = "${path.module}/resources/self-hosted-etcd/bootstrap-manifests"
destination_dir = "./generated/etcd/bootstrap-manifests"
vars {
etcd_image = "${var.container_images["etcd"]}"
etcd_version = "${var.versions["etcd"]}"
bootstrap_etcd_service_ip = "${cidrhost(var.service_cidr, 20)}"
}
}
data "template_file" "etcd_bootstrap_service" {
template = "${file("${path.module}/resources/self-hosted-etcd/bootstrap-etcd-service.json")}"
vars {
bootstrap_etcd_service_ip = "${cidrhost(var.service_cidr, 20)}"
}
}
resource "local_file" "etcd_bootstrap_service" {
count = "${var.self_hosted_etcd != "" ? 1 : 0}"
content = "${data.template_file.etcd_bootstrap_service.rendered}"
filename = "./generated/etcd/bootstrap-etcd-service.json"
}
data "template_file" "migrate_etcd_cluster" {
template = "${file("${path.module}/resources/self-hosted-etcd/migrate-etcd-cluster.json")}"
vars {
etcd_version = "${var.versions["etcd"]}"
bootstrap_etcd_service_ip = "${cidrhost(var.service_cidr, 20)}"
}
}
resource "local_file" "migrate_etcd_cluster" {
count = "${var.self_hosted_etcd == "enabled" ? 1 : 0}"
content = "${data.template_file.migrate_etcd_cluster.rendered}"
filename = "./generated/etcd/migrate-etcd-cluster.json"
}
data "template_file" "migrate_etcd_cluster_pv_backup" {
template = "${file("${path.module}/resources/self-hosted-etcd/migrate-etcd-cluster-pv-backup.json")}"
vars {
etcd_version = "${var.versions["etcd"]}"
bootstrap_etcd_service_ip = "${cidrhost(var.service_cidr, 20)}"
etcd_backup_size = "${var.etcd_backup_size}"
etcd_backup_storage_class = "${var.etcd_backup_storage_class}"
}
}
resource "local_file" "migrate_etcd_cluster_pv_backup" {
count = "${var.self_hosted_etcd == "pv_backup" ? 1 : 0}"
content = "${data.template_file.migrate_etcd_cluster_pv_backup.rendered}"
filename = "./generated/etcd/migrate-etcd-cluster.json"
}

View File

@@ -0,0 +1,35 @@
# Kubernete's Service Account (resources/generated/tls/{service-account.key,service-account.pub})
resource "tls_private_key" "service_account" {
algorithm = "RSA"
rsa_bits = "2048"
}
resource "local_file" "service_account_key" {
content = "${tls_private_key.service_account.private_key_pem}"
filename = "./generated/tls/service-account.key"
}
data "ignition_file" "service_account_key" {
filesystem = "root"
path = "/opt/tectonic/tls/service-account.key"
mode = "0644"
content {
content = "${tls_private_key.service_account.private_key_pem}"
}
}
resource "local_file" "service_account_crt" {
content = "${tls_private_key.service_account.public_key_pem}"
filename = "./generated/tls/service-account.pub"
}
data "ignition_file" "service_account_crt" {
filesystem = "root"
path = "/opt/tectonic/tls/service-account.pub"
mode = "0644"
content {
content = "${tls_private_key.service_account.public_key_pem}"
}
}

View File

@@ -0,0 +1,15 @@
# Kubernete's Service Account (resources/generated/tls/{service-account.key,service-account.pub})
resource "tls_private_key" "service_account" {
algorithm = "RSA"
rsa_bits = "2048"
}
resource "local_file" "service_account_key" {
content = "${tls_private_key.service_account.private_key_pem}"
filename = "./generated/tls/service-account.key"
}
resource "local_file" "service_account_crt" {
content = "${tls_private_key.service_account.public_key_pem}"
filename = "./generated/tls/service-account.pub"
}

View File

@@ -0,0 +1,147 @@
variable "apiserver_cert_pem" {
type = "string"
description = "The API server certificate in PEM format."
}
variable "apiserver_key_pem" {
type = "string"
description = "The API server key in PEM format."
}
variable "openshift_apiserver_cert_pem" {
type = "string"
description = "The Openshift API server certificate in PEM format."
}
variable "openshift_apiserver_key_pem" {
type = "string"
description = "The Openshift API server key in PEM format."
}
variable "apiserver_proxy_cert_pem" {
type = "string"
description = "The API server proxy certificate in PEM format."
}
variable "apiserver_proxy_key_pem" {
type = "string"
description = "The API server proxy key in PEM format."
}
variable "cloud_provider_config" {
description = "Content of cloud provider config"
type = "string"
default = ""
}
variable "cluster_name" {
type = "string"
}
variable "container_images" {
description = "Container images to use"
type = "map"
}
variable "etcd_ca_cert_pem" {
type = "string"
description = "The etcd CA certificate in PEM format."
}
variable "etcd_client_cert_pem" {
type = "string"
description = "The etcd client certificate in PEM format."
}
variable "etcd_client_key_pem" {
type = "string"
description = "The etcd client key in PEM format."
}
variable "etcd_endpoints" {
description = "List of etcd endpoints to connect with (hostnames/IPs only)"
type = "list"
}
variable "kube_apiserver_url" {
description = "URL used to reach kube-apiserver"
type = "string"
}
variable "root_ca_cert_pem" {
type = "string"
description = "The Root CA in PEM format."
}
variable "aggregator_ca_cert_pem" {
type = "string"
description = "The Aggregated API Server CA in PEM format."
}
variable "aggregator_ca_key_pem" {
type = "string"
description = "The Aggregated API Server CA key in PEM format."
}
variable "kube_ca_cert_pem" {
type = "string"
description = "The Kubernetes CA in PEM format."
}
variable "kube_ca_key_pem" {
type = "string"
description = "The Kubernetes CA key in PEM format."
}
variable "service_serving_ca_cert_pem" {
type = "string"
description = "The Service Serving CA in PEM format."
}
variable "service_serving_ca_key_pem" {
type = "string"
description = "The Service Serving CA key in PEM format."
}
variable "admin_cert_pem" {
type = "string"
description = "The admin certificate in PEM format."
}
variable "admin_key_pem" {
type = "string"
description = "The admin key in PEM format."
}
variable "kubelet_cert_pem" {
type = "string"
description = "The kubelet certificate in PEM format."
}
variable "kubelet_key_pem" {
type = "string"
description = "The kubelet key in PEM format."
}
variable "tnc_cert_pem" {
type = "string"
}
variable "tnc_key_pem" {
type = "string"
}
variable "oidc_ca_cert" {
type = "string"
}
variable "service_cidr" {
description = "A CIDR notation IP range from which to assign service cluster IPs"
type = "string"
}
variable "pull_secret_path" {
type = "string"
description = "Path on disk to your Tectonic pull secret. Obtain this from your Tectonic Account: https://account.coreos.com."
default = "/Users/coreos/Desktop/config.json"
}

View File

@@ -0,0 +1,179 @@
variable "advertise_address" {
description = "The IP address on which to advertise the apiserver to members of the cluster"
type = "string"
}
variable "anonymous_auth" {
description = "Enables anonymous requests to the secure port of the API server"
type = "string"
}
variable "apiserver_cert_pem" {
type = "string"
description = "The API server certificate in PEM format."
}
variable "apiserver_key_pem" {
type = "string"
description = "The API server key in PEM format."
}
variable "cloud_provider" {
description = "The provider for cloud services (empty string for no provider)"
type = "string"
}
variable "cloud_provider_config" {
description = "Content of cloud provider config"
type = "string"
default = ""
}
variable "cluster_cidr" {
description = "A CIDR notation IP range from which to assign pod IPs"
type = "string"
}
variable "cluster_name" {
type = "string"
}
variable "container_images" {
description = "Container images to use"
type = "map"
}
variable "etcd_tls_enabled" {
default = true
}
variable "etcd_ca_cert_pem" {
type = "string"
description = "The etcd CA certificate in PEM format."
}
variable "etcd_client_cert_pem" {
type = "string"
description = "The etcd client certificate in PEM format."
}
variable "etcd_client_key_pem" {
type = "string"
description = "The etcd client key in PEM format."
}
variable "etcd_endpoints" {
description = "List of etcd endpoints to connect with (hostnames/IPs only)"
type = "list"
}
variable "etcd_peer_cert_pem" {
type = "string"
description = "The etcd peer certificate in PEM format."
}
variable "etcd_peer_key_pem" {
type = "string"
description = "The etcd peer key in PEM format."
}
variable "etcd_server_cert_pem" {
type = "string"
description = "The etcd server certificate in PEM format."
}
variable "etcd_server_key_pem" {
type = "string"
description = "The etcd server key in PEM format."
}
variable "self_hosted_etcd" {
type = "string"
description = "See tectonic_self_hosted_etcd in config.tf"
}
variable "kube_apiserver_url" {
description = "URL used to reach kube-apiserver"
type = "string"
}
variable "kube_ca_cert_pem" {
type = "string"
description = "The Kubernetes CA in PEM format."
}
variable "kubelet_cert_pem" {
type = "string"
description = "The kubelet certificate in PEM format."
}
variable "kubelet_key_pem" {
type = "string"
description = "The kubelet key in PEM format."
}
variable "master_count" {
description = "The number of the master nodes"
type = "string"
}
variable "node_monitor_grace_period" {
description = "Amount of time which we allow running Node to be unresponsive before marking it unhealthy. Must be N times more than kubelet's nodeStatusUpdateFrequency, where N means number of retries allowed for kubelet to post node status. N must be stricly > 1."
type = "string"
default = "40s"
}
variable "oidc_ca_cert" {
type = "string"
}
variable "oidc_client_id" {
description = "The client ID for the OpenID Connect client"
type = "string"
}
variable "oidc_groups_claim" {
description = "The OpenID claim to use for specifying user groups (string or array of strings)"
type = "string"
}
variable "oidc_issuer_url" {
description = "The URL of the OpenID issuer, only HTTPS scheme will be accepted"
type = "string"
}
variable "oidc_username_claim" {
description = "The OpenID claim to use as the user name"
type = "string"
}
variable "pod_eviction_timeout" {
description = "The grace period for deleting pods on failed nodes. The eviction process will start after node_monitor_grace_period + pod_eviction_timeout."
type = "string"
default = "5m"
}
variable "cloud_config_path" {
description = "The path to the secret file that contains the cloud config contents. Either be empty ('') or ('/etc/kubernetes/cloud/config')."
type = "string"
}
variable "etcd_backup_size" {
type = "string"
description = "The size of the PersistentVolume used to handle etcd backups"
}
variable "etcd_backup_storage_class" {
type = "string"
description = "The name of the Kubernetes StorageClass that will be used to handle etcd backups"
}
variable "service_cidr" {
description = "A CIDR notation IP range from which to assign service cluster IPs"
type = "string"
}
variable "versions" {
description = "Container versions to use"
type = "map"
}

View File

@@ -0,0 +1,28 @@
resource "null_resource" "bootstrapper" {
triggers {
endpoint = "${var.bootstrapping_host}"
dependencies = "${join("", concat(flatten(var._dependencies)))}"
}
connection {
host = "${var.bootstrapping_host}"
user = "core"
agent = true
}
provisioner "file" {
when = "create"
source = "./generated"
destination = "$HOME/tectonic"
}
provisioner "remote-exec" {
when = "create"
inline = [
"sudo mkdir -p /opt",
"sudo rm -rf /opt/tectonic",
"sudo mv /home/core/tectonic /opt/",
]
}
}

View File

@@ -0,0 +1,7 @@
variable "bootstrapping_host" {
type = "string"
}
variable "_dependencies" {
type = "list"
}

View File

@@ -0,0 +1,4 @@
data "external" "version" {
count = "${var.release_version == "latest" ? 1 : 0}"
program = ["sh", "-c", "curl https://${var.release_channel}.release.core-os.net/amd64-usr/current/version.txt | sed -n 's/COREOS_VERSION=\\(.*\\)$/{\"version\": \"\\1\"}/p'"]
}

View File

@@ -0,0 +1,3 @@
data "external" "version" {
program = ["sh", "-c", "curl https://${var.release_channel}.release.core-os.net/amd64-usr/current/version.txt | sed -n 's/COREOS_VERSION=\\(.*\\)$/{\"version\": \"\\1\"}/p'"]
}

View File

@@ -0,0 +1,13 @@
locals {
// Create a map that matches the structure of the output of the external data source
// so we can avoid running the shell script and still parse the output consistently.
// Here, we jsonencode because ternaries can only operate on flat data types and
// Terraform `merge` and `element` do not play nicely with maps.
json = "${var.release_version == "latest" ? jsonencode(data.external.version.*.result) : jsonencode(map("version", var.release_version))}"
}
output "version" {
// Parse out the version from the well-known JSON of format:
// {"version":"<version>"}
value = "${replace(local.json, "/.*\"version\":\"(.*)\".*/", "$1")}"
}

View File

@@ -0,0 +1,3 @@
output "version" {
value = "${var.release_version == "latest" ? data.external.version.result["version"] : var.release_version}"
}

View File

@@ -0,0 +1,19 @@
variable "release_channel" {
type = "string"
description = <<EOF
The Container Linux update channel.
Examples: `stable`, `beta`, `alpha`
EOF
}
variable "release_version" {
type = "string"
description = <<EOF
The Container Linux version to use. Set to `latest` to select the latest available version for the selected update channel.
Examples: `latest`, `1465.6.0`
EOF
}

View File

@@ -0,0 +1,19 @@
variable "release_channel" {
type = "string"
description = <<EOF
The Container Linux update channel.
Examples: `stable`, `beta`, `alpha`
EOF
}
variable "release_version" {
type = "string"
description = <<EOF
The Container Linux version to use. Set to `latest` to select the latest available version for the selected update channel.
Examples: `latest`, `1465.6.0`
EOF
}

View File

@@ -0,0 +1,7 @@
resource "digitalocean_record" "etcd_nodes" {
count = "${var.droplet_count}"
type = "A"
domain = "${var.base_domain}"
name = "${var.cluster_name}-etcd-${count.index}"
value = "${digitalocean_droplet.etcd_node.*.ipv4_address[count.index]}"
}

View File

@@ -0,0 +1,49 @@
data "ignition_config" "etcd" {
count = "${length(var.external_endpoints) == 0 ? var.droplet_count : 0}"
systemd = [
"${data.ignition_systemd_unit.locksmithd.*.id[count.index]}",
"${var.ign_etcd_dropin_id_list[count.index]}",
]
files = [
"${compact(list(var.ign_profile_env_id, var.ign_systemd_default_env_id,))}",
"${var.ign_etcd_crt_id_list}",
"${data.ignition_file.node_hostname.*.id[count.index]}",
"${var.ign_ntp_dropin_id}",
]
}
data "ignition_systemd_unit" "locksmithd" {
count = "${length(var.external_endpoints) == 0 ? var.droplet_count : 0}"
name = "locksmithd.service"
enabled = true
dropin = [
{
name = "40-etcd-lock.conf"
content = <<EOF
[Service]
Environment=REBOOT_STRATEGY=etcd-lock
${var.tls_enabled ? "Environment=\"LOCKSMITHD_ETCD_CAFILE=/etc/ssl/etcd/ca.crt\"" : ""}
${var.tls_enabled ? "Environment=\"LOCKSMITHD_ETCD_KEYFILE=/etc/ssl/etcd/client.key\"" : ""}
${var.tls_enabled ? "Environment=\"LOCKSMITHD_ETCD_CERTFILE=/etc/ssl/etcd/client.crt\"" : ""}
Environment="LOCKSMITHD_ENDPOINT=${var.tls_enabled ? "https" : "http"}://${var.cluster_name}-etcd-${count.index}.${var.base_domain}:2379"
EOF
},
]
}
data "ignition_file" "node_hostname" {
count = "${length(var.external_endpoints) == 0 ? var.droplet_count : 0}"
path = "/etc/hostname"
mode = 0644
filesystem = "root"
content {
content = "${var.cluster_name}-etcd-${count.index}.${var.base_domain}"
}
}

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