diff --git a/README.md b/README.md index e05d8f56..87b7ab08 100644 --- a/README.md +++ b/README.md @@ -25,11 +25,7 @@ You also need to ensure your applications and add ons are updated, or workloads An example of harming update was the removal of several commonly used, but deprecated APIs, in Kubernetes 1.16. More information on the API removals, see the [Kubernetes blog post](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/). -By default, this module manages the `aws-auth` configmap for you (`manage_aws_auth=true`). To avoid the following [issue](https://github.com/aws/containers-roadmap/issues/654) where the EKS creation is `ACTIVE` but not ready, we implemented a retry logic with an `local-exec` provisioner and `wget` (by default) with failover to `curl`. - -**If you want to manage your `aws-auth` configmap, ensure you have `wget` (or `curl`) and `/bin/sh` installed where you're running Terraform or set `wait_for_cluster_cmd` and `wait_for_cluster_interpreter` to match your needs.** - -For windows users, please read the following [doc](https://github.com/terraform-aws-modules/terraform-aws-eks/blob/master/docs/faq.md#deploying-from-windows-binsh-file-does-not-exist). +By default, this module manages the `aws-auth` configmap for you (`manage_aws_auth=true`). To avoid the following [issue](https://github.com/aws/containers-roadmap/issues/654) where the EKS creation is `ACTIVE` but not ready. We implemented a "retry" logic with a fork of the http provider https://github.com/terraform-aws-modules/terraform-provider-http. This fork adds the support of a self-signed CA certificate. The original PR can be found at https://github.com/hashicorp/terraform-provider-http/pull/29. ## Usage example @@ -145,10 +141,10 @@ MIT Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-a | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 0.13.1 | -| [aws](#requirement\_aws) | >= 3.35.0 | +| [aws](#requirement\_aws) | >= 3.37.0 | +| [http](#requirement\_http) | >= 2.2.0 | | [kubernetes](#requirement\_kubernetes) | >= 1.11.1 | | [local](#requirement\_local) | >= 1.4 | -| [null](#requirement\_null) | >= 2.1 | | [random](#requirement\_random) | >= 2.1 | | [template](#requirement\_template) | >= 2.1 | @@ -156,10 +152,10 @@ MIT Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-a | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.35.0 | +| [aws](#provider\_aws) | >= 3.37.0 | +| [http](#provider\_http) | >= 2.2.0 | | [kubernetes](#provider\_kubernetes) | >= 1.11.1 | | [local](#provider\_local) | >= 1.4 | -| [null](#provider\_null) | >= 2.1 | | [random](#provider\_random) | >= 2.1 | | [template](#provider\_template) | >= 2.1 | @@ -208,7 +204,6 @@ MIT Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-a | [aws_security_group_rule.workers_ingress_self](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | | [kubernetes_config_map.aws_auth](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/config_map) | resource | | [local_file.kubeconfig](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | -| [null_resource.wait_for_cluster](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [random_pet.workers](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | | [random_pet.workers_launch_template](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | | [aws_ami.eks_worker](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | @@ -221,6 +216,7 @@ MIT Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-a | [aws_iam_policy_document.workers_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_role.custom_cluster_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_role) | data source | | [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | +| [http_http.wait_for_cluster](https://registry.terraform.io/providers/terraform-aws-modules/http/latest/docs/data-sources/http) | data source | | [template_file.launch_template_userdata](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) | data source | | [template_file.userdata](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) | data source | @@ -273,8 +269,6 @@ MIT Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-a | [subnets](#input\_subnets) | A list of subnets to place the EKS cluster and workers within. | `list(string)` | n/a | yes | | [tags](#input\_tags) | A map of tags to add to all resources. Tags added to launch configuration or templates override these values for ASG Tags only. | `map(string)` | `{}` | no | | [vpc\_id](#input\_vpc\_id) | VPC where the cluster and workers will be deployed. | `string` | n/a | yes | -| [wait\_for\_cluster\_cmd](#input\_wait\_for\_cluster\_cmd) | Custom local-exec command to execute for determining if the eks cluster is healthy. Cluster endpoint will be available as an environment variable called ENDPOINT | `string` | `"for i in `seq 1 60`; do if `command -v wget > /dev/null`; then wget --no-check-certificate -O - -q $ENDPOINT/healthz >/dev/null && exit 0 || true; else curl -k -s $ENDPOINT/healthz >/dev/null && exit 0 || true;fi; sleep 5; done; echo TIMEOUT && exit 1"` | no | -| [wait\_for\_cluster\_interpreter](#input\_wait\_for\_cluster\_interpreter) | Custom local-exec command line interpreter for the command to determining if the eks cluster is healthy. | `list(string)` |
[
"/bin/sh",
"-c"
]
| no | | [worker\_additional\_security\_group\_ids](#input\_worker\_additional\_security\_group\_ids) | A list of additional security group ids to attach to worker instances | `list(string)` | `[]` | no | | [worker\_ami\_name\_filter](#input\_worker\_ami\_name\_filter) | Name filter for AWS EKS worker AMI. If not provided, the latest official AMI for the specified 'cluster\_version' is used. | `string` | `""` | no | | [worker\_ami\_name\_filter\_windows](#input\_worker\_ami\_name\_filter\_windows) | Name filter for AWS EKS Windows worker AMI. If not provided, the latest official AMI for the specified 'cluster\_version' is used. | `string` | `""` | no | @@ -304,7 +298,7 @@ MIT Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-a | [cluster\_endpoint](#output\_cluster\_endpoint) | The endpoint for your EKS Kubernetes API. | | [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | IAM role ARN of the EKS cluster. | | [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | IAM role name of the EKS cluster. | -| [cluster\_id](#output\_cluster\_id) | The name/id of the EKS cluster. Will block on cluster creation until the cluster is really ready | +| [cluster\_id](#output\_cluster\_id) | The name/id of the EKS cluster. Will block on cluster creation until the cluster is really ready. | | [cluster\_oidc\_issuer\_url](#output\_cluster\_oidc\_issuer\_url) | The URL on the EKS cluster OIDC Issuer | | [cluster\_primary\_security\_group\_id](#output\_cluster\_primary\_security\_group\_id) | The cluster primary security group ID created by the EKS cluster on 1.14 or later. Referred to as 'Cluster security group' in the EKS console. | | [cluster\_security\_group\_id](#output\_cluster\_security\_group\_id) | Security group ID attached to the EKS cluster. On 1.14 or later, this is the 'Additional security groups' in the EKS console. | @@ -314,8 +308,8 @@ MIT Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-a | [fargate\_iam\_role\_name](#output\_fargate\_iam\_role\_name) | IAM role name for EKS Fargate pods | | [fargate\_profile\_arns](#output\_fargate\_profile\_arns) | Amazon Resource Name (ARN) of the EKS Fargate Profiles. | | [fargate\_profile\_ids](#output\_fargate\_profile\_ids) | EKS Cluster name and EKS Fargate Profile names separated by a colon (:). | -| [kubeconfig](#output\_kubeconfig) | kubectl config file contents for this EKS cluster. | -| [kubeconfig\_filename](#output\_kubeconfig\_filename) | The filename of the generated kubectl config. | +| [kubeconfig](#output\_kubeconfig) | kubectl config file contents for this EKS cluster. Will block on cluster creation until the cluster is really ready. | +| [kubeconfig\_filename](#output\_kubeconfig\_filename) | The filename of the generated kubectl config. Will block on cluster creation until the cluster is really ready. | | [node\_groups](#output\_node\_groups) | Outputs from EKS node groups. Map of maps, keyed by var.node\_groups keys | | [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | The ARN of the OIDC Provider if `enable_irsa = true`. | | [security\_group\_rule\_cluster\_https\_worker\_ingress](#output\_security\_group\_rule\_cluster\_https\_worker\_ingress) | Security group rule responsible for allowing pods to communicate with the EKS cluster API. | diff --git a/aws_auth.tf b/aws_auth.tf index 91b0a23a..f549dcce 100644 --- a/aws_auth.tf +++ b/aws_auth.tf @@ -64,7 +64,7 @@ locals { resource "kubernetes_config_map" "aws_auth" { count = var.create_eks && var.manage_aws_auth ? 1 : 0 - depends_on = [null_resource.wait_for_cluster[0]] + depends_on = [data.http.wait_for_cluster[0]] metadata { name = "aws-auth" @@ -72,7 +72,7 @@ resource "kubernetes_config_map" "aws_auth" { labels = merge( { "app.kubernetes.io/managed-by" = "Terraform" - # / are replaced by . because label validator fails in this lib + # / are replaced by . because label validator fails in this lib # https://github.com/kubernetes/apimachinery/blob/1bdd76d09076d4dc0362456e59c8f551f5f24a72/pkg/util/validation/validation.go#L166 "terraform.io/module" = "terraform-aws-modules.eks.aws" }, diff --git a/cluster.tf b/cluster.tf index 4306db30..3034d950 100644 --- a/cluster.tf +++ b/cluster.tf @@ -64,21 +64,10 @@ resource "aws_security_group_rule" "cluster_private_access" { } -resource "null_resource" "wait_for_cluster" { - count = var.create_eks && var.manage_aws_auth ? 1 : 0 - - depends_on = [ - aws_eks_cluster.this, - aws_security_group_rule.cluster_private_access, - ] - - provisioner "local-exec" { - command = var.wait_for_cluster_cmd - interpreter = var.wait_for_cluster_interpreter - environment = { - ENDPOINT = aws_eks_cluster.this[0].endpoint - } - } +data "http" "wait_for_cluster" { + count = var.create_eks && var.manage_aws_auth ? 1 : 0 + url = format("%s/healthz", aws_eks_cluster.this[0].endpoint) + ca_certificate = base64decode(coalescelist(aws_eks_cluster.this[*].certificate_authority[0].data, [""])[0]) } resource "aws_security_group" "cluster" { diff --git a/docs/faq.md b/docs/faq.md index 9fba65b7..3b9e118f 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -107,7 +107,7 @@ You do not need to do anything extra since v12.1.0 of the module as long as the - `manage_aws_auth = true` on the module (default) - the kubernetes provider is correctly configured like in the [Usage Example](https://github.com/terraform-aws-modules/terraform-aws-eks/blob/master/README.md#usage-example). Primarily the module's `cluster_id` output is used as input to the `aws_eks_cluster*` data sources. -The `cluster_id` depends on a `null_resource` that polls the EKS cluster's endpoint until it is alive. This blocks initialisation of the kubernetes provider. +The `cluster_id` depends on a `data.http.wait_for_cluster` that polls the EKS cluster's endpoint until it is alive. This blocks initialisation of the kubernetes provider. ## `aws_auth.tf: At 2:14: Unknown token: 2:14 IDENT` @@ -170,18 +170,6 @@ worker_groups = [ 4. With `kubectl get nodes` you can see cluster with mixed (Linux/Windows) nodes support. -## Deploying from Windows: `/bin/sh` file does not exist - -The module is almost pure Terraform apart from the `wait_for_cluster` `null_resource` that runs a local provisioner. The module has a default configuration for Unix-like systems. In order to run the provisioner on Windows systems you must set the interpreter to a valid value. [PR #795 (comment)](https://github.com/terraform-aws-modules/terraform-aws-eks/pull/795#issuecomment-599191029) suggests the following value: -```hcl -module "eks" { - # ... - wait_for_cluster_interpreter = ["c:/git/bin/sh.exe", "-c"] -} -``` - -Alternatively, you can disable the `null_resource` by disabling creation of the `aws-auth` ConfigMap via setting `manage_aws_auth = false` on the module. The ConfigMap will then need creating via a different method. - ## Worker nodes with labels do not join a 1.16+ cluster Kubelet restricts the allowed list of labels in the `kubernetes.io` namespace that can be applied to nodes starting in 1.16. diff --git a/outputs.tf b/outputs.tf index 62d75aaf..147f0360 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,9 +1,10 @@ output "cluster_id" { - description = "The name/id of the EKS cluster. Will block on cluster creation until the cluster is really ready" + description = "The name/id of the EKS cluster. Will block on cluster creation until the cluster is really ready." value = element(concat(aws_eks_cluster.this.*.id, [""]), 0) - # So that calling plans wait for the cluster to be available before attempting - # to use it. They will not need to duplicate this null_resource - depends_on = [null_resource.wait_for_cluster] + + # So that calling plans wait for the cluster to be available before attempting to use it. + # There is no need to duplicate this datasource + depends_on = [data.http.wait_for_cluster] } output "cluster_arn" { @@ -67,13 +68,21 @@ output "cloudwatch_log_group_arn" { } output "kubeconfig" { - description = "kubectl config file contents for this EKS cluster." + description = "kubectl config file contents for this EKS cluster. Will block on cluster creation until the cluster is really ready." value = local.kubeconfig + + # So that calling plans wait for the cluster to be available before attempting to use it. + # There is no need to duplicate this datasource + depends_on = [data.http.wait_for_cluster] } output "kubeconfig_filename" { - description = "The filename of the generated kubectl config." + description = "The filename of the generated kubectl config. Will block on cluster creation until the cluster is really ready." value = concat(local_file.kubeconfig.*.filename, [""])[0] + + # So that calling plans wait for the cluster to be available before attempting to use it. + # There is no need to duplicate this datasource + depends_on = [data.http.wait_for_cluster] } output "oidc_provider_arn" { diff --git a/variables.tf b/variables.tf index 6f904b63..a48093d5 100644 --- a/variables.tf +++ b/variables.tf @@ -205,18 +205,6 @@ variable "cluster_delete_timeout" { default = "15m" } -variable "wait_for_cluster_cmd" { - description = "Custom local-exec command to execute for determining if the eks cluster is healthy. Cluster endpoint will be available as an environment variable called ENDPOINT" - type = string - default = "for i in `seq 1 60`; do if `command -v wget > /dev/null`; then wget --no-check-certificate -O - -q $ENDPOINT/healthz >/dev/null && exit 0 || true; else curl -k -s $ENDPOINT/healthz >/dev/null && exit 0 || true;fi; sleep 5; done; echo TIMEOUT && exit 1" -} - -variable "wait_for_cluster_interpreter" { - description = "Custom local-exec command line interpreter for the command to determining if the eks cluster is healthy." - type = list(string) - default = ["/bin/sh", "-c"] -} - variable "cluster_create_security_group" { description = "Whether to create a security group for the cluster or attach the cluster to `cluster_security_group_id`." type = bool diff --git a/versions.tf b/versions.tf index 6d70b063..d6801b04 100644 --- a/versions.tf +++ b/versions.tf @@ -4,9 +4,12 @@ terraform { required_providers { aws = ">= 3.37.0" local = ">= 1.4" - null = ">= 2.1" template = ">= 2.1" random = ">= 2.1" kubernetes = ">= 1.11.1" + http = { + source = "terraform-aws-modules/http" + version = ">= 2.2.0" + } } }