# terraform/aws/premium

Root Terraform module that provisions a TiDB Cloud **Premium** (`DEPLOY_TYPE_NEXTGEN`) seed cluster on AWS and bootstraps all required in-cluster services.

## What this module owns

- EKS cluster: `{env}-seed-{logical_region_name}` in the seed AWS account
- VPC with public/private subnets across the given availability zones (single NAT gateway)
- IAM IRSA roles for: load-balancer-controller, dataplane-manager, external-secrets-operator, cert-manager, cluster-autoscaler, vector-agent
- Metering S3 bucket and IAM roles (`metering-write-only` for dataplane accounts, `metering-read-write` for dataplane-manager)
- EKS-to-RDS security group ingress rule (port 3306)
- ArgoCD cluster registration and kubeconfig (written to `/tmp/{cluster-name}-kubeconfig`)
- All in-cluster services via Argo Workflows (`../../modules/app`): cert-manager, issuers, ESO, cluster-autoscaler, AWS LBC, kube-prometheus, victoria-metrics, Crossplane/upbound, Kong gateway CRDs + ingress controller, dataplane-manager, jumpserver, o11y-agent, o11y-agent-control-server, cluster-ng-service CRDs + server, config-center-regional, TiCDC service, gateway-api CRDs
- Route53 alias record: `{logical_region_name}.regional-api.{hosted_zone_name}` → Kong NLB
- Region registration in global registry as service plan `Premium`

## Required variables (no defaults)

| Variable | Example |
|---|---|
| `env` | `dev` |
| `aws_region` | `ap-south-1` |
| `logical_region_name` | `ap-south-1-ng` |
| `availability_zones` | `["aps1-az1", "aps1-az2", "aps1-az3"]` — AZ **IDs**, not names |
| `dataplane_accounts` | `["385595570414"]` — at least one required |

See [`test.tfvars`](test.tfvars) for a working dev example.

## State and account resolution

- **Backend**: S3 bucket `autonomous-deployment-terraform-state` (us-west-2), native S3 lock. State key must be supplied at `terraform init -backend-config=key=...`.
- **Two AWS provider aliases**:
  - _(default)_: profile `local.seed_account`, region `var.aws_region` — all target resources
  - `tf_state`: profile `default`, region `us-west-2` — reads state bucket

`local.seed_account` is resolved at plan time from S3 (`aws/account/seed/{env}.json`). The `default` AWS profile must be able to read the state bucket before `terraform plan`.

### Remote state sources (`main.tf`)

| Key | `local.*` derived |
|---|---|
| `aws/base/{env}.json` | `base_account`, `base_public_ips`, `pca_arn`, `billing_sqs_arn` |
| `aws/account/seed/{env}.json` | `seed_account`, `hosted_zone_name`, `hosted_zone_id` |
| `aws/clinic/{env}.json` (staging when env=dev) | `clinic_outputs.public_ips` |
| `aws/devops/{env}.json` (staging when env=dev) | `devops_outputs.public_ips`, `devops_server_role_arn` |
| `aws/o11y-global/prod.json` | `o11y_account` |
| `aws/region/{env}-{aws_region}.json` | RDS endpoint, password secret ARN, sg ID |

## Typical workflow

```sh
terraform init -backend-config="key=aws/premium/<env>/<logical_region_name>.json"
terraform plan -var-file=<vars>.tfvars
terraform apply -var-file=<vars>.tfvars
```

## Non-obvious constraints

- **`availability_zones` are AZ IDs** (e.g. `aps1-az1`), not AZ names. `eks.tf` maps them to names via `data.aws_availability_zones`.
- **Kubeconfig is ephemeral**: written to `/tmp/{cluster-name}-kubeconfig` during apply by the `kubeconfig` module. All Kubernetes/kubectl providers and `app` modules consume it from there.
- **`metering_read_write_role_arn` is pre-computed** as a local to avoid a circular dependency between `iam-dataplane-manager` (which grants `sts:AssumeRole` on it) and `aws_iam_role.metering_read_write` (whose trust policy references the dataplane-manager role ARN). Do not re-introduce this dependency.
- **Route53 destroy workaround**: `regional-api-dns.tf` sets the alias target to `"deleted"` when the Kong service hostname is unavailable, so `terraform destroy` can proceed without an empty alias target.
- **Two `time_sleep` resources** of 5 minutes each are in the apply chain: one after Kong gateway CRDs (before `kong-gateway`), one after the Route53 record (before `region_registration` and `dataplane-manager`). Total forced wait: 10 minutes during a full apply.
- **`jumpserver_role_name`** is `dbaas-prod-devops` for prod, `dbaas-dev` for all other envs.
- **Image registry** for all in-cluster services is `{seed_account}.dkr.ecr.us-west-2.amazonaws.com` — always us-west-2 regardless of deployment region.
- **EKS node port 8080 open** from control plane (for Kong webhook).
- **EKS `vpc-cni` addon** uses prefix delegation (`ENABLE_PREFIX_DELEGATION=true`) and is configured `before_compute`.

## Related Documentation

- [alicloud/premium AGENTS.md](../../alicloud/premium/AGENTS.md) — parallel module for Alibaba Cloud; useful for cross-cloud pattern reference
- [terraform/aws/region AGENTS.md](../region/AGENTS.md) — provisions the RDS cluster that this module reads state from
