Hello,
I have a Terraform deployment that deploys a Kubernetes cluster and then later configures ingress. The basic order of events is this -
- Create VPC, EKS cluster and node group. Also deploy the nginx-ingress-controller helm chart to the Kubernetes cluster, which will create the
nginx
namespace on the Kubernetes cluster and provision a classic load balancer in AWS. - Import the
nginx
namespace into the Terraform state. This is required for two reasons -- Most importantly, when
terrafrom destory
is run thenginx
namespace is destroyed, ensuring that the classic load balancer that was provisioned in AWS is removed and thus allowing the VPC to be deleted. Without importing thenginx
namespace, automated destruction of the cluster is impossible. - So that
kubernetes_service
data source can be included , which in turn allows anaws_elb
data source to be included, which is then used to retrieve the hostname of the classic load balancer.
- Most importantly, when
- Create a Route53 hosted zone and add an A record for each of the ingresses that will be required.
So because I have to use terraform import
there is absolutely no way for me to run terraform apply
just once. Instead, I have to run it for step 1 and step 3 above, using the -target
option (which I know isn’t recommended).
While that’s not ideal, I could cope with it. However I’m running in to an issue with the import
command where I see Error: Unauthorized
.
Acquiring state lock. This may take a few moments...
module.ingress.kubernetes_namespace.nginx: Importing from ID "nginx"...
module.ingress.kubernetes_namespace.nginx: Import prepared!
Prepared kubernetes_namespace for import
module.ingress.kubernetes_namespace.nginx: Refreshing state... [id=nginx]
Error: Unauthorized
Releasing state lock. This may take a few moments...
I’ve looked in to the issue and it seems that there are severe limitations with the import
command that mean it doesn’t work properly where there are provider configurations that depend on a data source.
The only limitation Terraform has when reading the configuration files is that the import provider configurations must not depend on non-variable inputs. For example, a provider configuration cannot depend on a data source.
This seems to be my issue, as can be seen from my provider configuration.
terraform {
required_version = "1.0.6"
...
}
...
module "kubernetes-cluster" {
source = "../../modules/kubernetes-cluster"
cluster_name = var.cluster.name
cluster_region = var.cluster.region
subnet_ids = [
module.vpc.private_subnet_1_id,
module.vpc.private_subnet_2_id,
module.vpc.public_subnet_1_id
]
kubernetes_version = var.cluster.k8s_version
}
data "aws_eks_cluster" "cluster" {
name = module.kubernetes-cluster.id
}
data "aws_eks_cluster_auth" "cluster" {
name = module.kubernetes-cluster.id
}
provider "kubernetes" {
host = data.aws_eks_cluster.cluster.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
token = data.aws_eks_cluster_auth.cluster.token
}
...
So my question is this… How can I possibly use Terraform when I need to import a resource into my Kubernetes cluster?
- It is not possible to implicitly import a resource through
terraform apply
, meaning that I have to split my deployment into two pieces. - It is not possible to import a resource to a provider that is not statically configured. But as I’m creating the Kubernetes cluster within the template it’s not possible to know those values.
In an ideal world this would work with just one run of terraform apply
, but I don’t think that’s possible. Any tips and (hopefully!) solutions welcome.
Thanks,
David