Skip to content

Commit d481ae8

Browse files
committed
docs(aws): add OpenSpec artifacts for EKS Auto Mode change
Persists the full spec-driven planning state in the repository: - proposal.md: motivation and capabilities - specs/: 4 capability specs (bootstrap, platform, deployment, testing) - design.md: 9 architectural decisions with rationale - tasks.md: 50+ implementation tasks in dependency order All 4/4 artifacts complete. Implementation blocked pending AWS account. Refs: #19
1 parent a16a68c commit d481ae8

9 files changed

Lines changed: 621 additions & 0 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-08-22
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
## Context
2+
3+
Ontoserver is a FHIR terminology server deployed via Helm charts in this repo. The existing `azure/` directory demonstrates infrastructure provisioning with Terraform targeting AKS. The `sparked-infrastructure` repo has an internal EKS deployment, but it's tightly coupled to CSIRO's account and not suitable for external customers.
4+
5+
EKS Auto Mode (GA since Dec 2024) shifts compute, storage, networking, and load balancing management to AWS. EKS Capabilities (ACK, KRO, Argo CD — all fully managed, running in EKS not on worker nodes) provide a Kubernetes-native GitOps platform without self-installed controllers.
6+
7+
The target audience is external Ontoserver customers who want to deploy on AWS with minimal Kubernetes expertise.
8+
9+
## Goals / Non-Goals
10+
11+
**Goals:**
12+
- Self-contained `aws/` directory usable by external customers with no dependency on internal repos
13+
- Minimal Terraform bootstrap (only chicken-and-egg resources)
14+
- All application-layer AWS resources managed declaratively from within the cluster (ACK + KRO)
15+
- GitOps via Argo CD (EKS Capability) — single source of truth in Git
16+
- Clean teardown: delete KRO instance → cascading cleanup of all AWS resources; `terraform destroy` → removes cluster and networking
17+
- 5-layer tagging for cost tracking and cleanup auditability
18+
- Both read-write and read-only Ontoserver patterns
19+
- Integration test validating end-to-end functionality including FHIR operations
20+
- Documentation suitable for customers unfamiliar with EKS
21+
22+
**Non-Goals:**
23+
- Multi-account or multi-cluster fleet management
24+
- Production high-availability (multi-region, RDS Multi-AZ) — document as upgrade path only
25+
- Custom node management — rely entirely on Auto Mode defaults
26+
- Helm chart modifications — use existing `charts/ontoserver` as-is with values overrides
27+
- CI/CD pipeline for the customer's application code (only infrastructure delivery)
28+
29+
## Decisions
30+
31+
### D1: EKS Auto Mode over standard EKS with Karpenter
32+
33+
**Choice:** EKS Auto Mode
34+
**Rationale:** The target audience wants minimal ops. Auto Mode manages node lifecycle, AMI patching, scaling, EBS CSI, ALB controller, and VPC CNI with zero configuration. The sparked-infrastructure pattern (standard EKS + Karpenter + managed node groups + multiple addons) requires significantly more expertise.
35+
**Alternative considered:** Standard EKS with EKS Blueprints addons — rejected due to operational complexity for external customers.
36+
37+
### D2: EKS Capabilities (managed ACK/KRO/Argo CD) over self-installed controllers
38+
39+
**Choice:** EKS Capabilities
40+
**Rationale:** All three run in EKS (not on worker nodes), are fully managed by AWS (patching, scaling, availability), and require only an API call to enable. No Helm chart installation, no IRSA setup for controllers, no version pinning of controller images.
41+
**Alternative considered:** Self-installed ACK via Helm + Flux — rejected because it defeats the "leave switches on Auto" principle and adds maintenance burden.
42+
43+
### D3: Argo CD (EKS Capability) for GitOps over Flux
44+
45+
**Choice:** Argo CD as EKS Capability
46+
**Rationale:** Managed by AWS (zero maintenance), integrates with AWS Identity Center for auth, provides a hosted UI, and is designed to work with ACK + KRO. One Git repo is the source of truth. External customers get observability into sync state via the Argo UI without installing anything.
47+
**Alternative considered:** Flux + CodeCommit — lighter weight but requires self-installation, and CodeCommit is deprecated for new customers.
48+
49+
### D4: Single top-level KRO instance per environment
50+
51+
**Choice:** One `OntoserverPlatform` ResourceGraphDefinition composing all AWS resources, instantiated once per environment.
52+
**Rationale:** Maps to the Azure "Resource Group" mental model — delete the instance, everything goes away. Simplifies the customer's mental model: one YAML file = one environment. Sub-compositions (RDS, CDN, etc.) are internal implementation details within the RGD.
53+
**Alternative considered:** Separate KRO instances per concern (DB, CDN, networking) — more flexible but harder to reason about for cleanup. Documented as an alternative for advanced users.
54+
55+
### D5: ACK CloudFront controller despite Preview status
56+
57+
**Choice:** Use the Preview ACK cloudfront-controller
58+
**Rationale:** Maintains the K8s-native philosophy. CloudFront is optional (`cdn.enabled = false` by default). The Preview risk is acceptable for a CDN layer that can be replaced without data loss. Document the risk clearly.
59+
**Alternative considered:** Terraform for CloudFront — breaks the single-plane-of-glass model. Could be added as a fallback if ACK proves unstable.
60+
61+
### D6: ALB with ACM for TLS over cert-manager
62+
63+
**Choice:** ALB terminates TLS using ACM certificate ARN annotations
64+
**Rationale:** Simplest path on AWS. Auto Mode's built-in ALB controller handles provisioning. ACM certificates are free, auto-renewing, and don't require in-cluster certificate management. The existing chart README explicitly notes cert-manager is incompatible with ALB ingress class.
65+
**Alternative considered:** cert-manager + Envoy Gateway — powerful but adds components the customer must maintain.
66+
67+
### D7: EKS Pod Identity over IRSA
68+
69+
**Choice:** EKS Pod Identity
70+
**Rationale:** Newer, simpler mechanism. No OIDC provider setup required. Works with EKS Auto Mode natively. The bootstrap Terraform only needs to create Pod Identity associations (IAM role + service account binding) rather than OIDC configuration.
71+
**Alternative considered:** IRSA — proven but requires OIDC provider and more complex IAM trust policies.
72+
73+
### D8: 5-layer tagging architecture
74+
75+
**Choice:** Implement all 5 layers with `enable_auto_mode_custom_tags = true`
76+
**Rationale:** Without this, EC2 instances, EBS volumes, ALBs, and ENIs created by Auto Mode controllers are untagged. The IAM permission grant is a single flag on the EKS module. Customer can audit/delete by tag.
77+
**Risk:** Layer 3 (NodeClass) requires a custom NodeClass — the managed `default` NodeClass cannot be patched (EKS silently reverts changes). We create a dedicated named NodeClass + NodePool.
78+
79+
### D9: Terraform for bootstrap only, not application resources
80+
81+
**Choice:** Terraform scope limited to: S3 state bucket, VPC, EKS cluster, IAM roles, EKS Capability enablement.
82+
**Rationale:** Once the cluster exists with capabilities enabled, everything else is managed from within K8s via ACK/KRO/Argo CD. This gives a clean separation: `terraform destroy` removes infrastructure, `kubectl delete` removes application resources. Matches the customer mental model of "provision then configure."
83+
84+
## Risks / Trade-offs
85+
86+
**[KRO API stability]** → KRO is `v1alpha1`. ResourceGraphDefinition schema may change. Mitigation: pin KRO capability version; document that updates may require manifest changes. Since it's a managed capability, AWS handles the upgrade path.
87+
88+
**[ACK CloudFront Preview]** → Controller may have bugs or missing features. Mitigation: CDN is optional, off by default. Document the risk. Fall back to Varnish in-cluster caching (ontoserver-extras chart) if CloudFront proves problematic.
89+
90+
**[Cascading delete risk]** → Deleting the KRO instance deletes the RDS database. Mitigation: ACK supports `deletionPolicy: retain` on the DBInstance CR. Document this clearly. For production, recommend setting retain and taking a final snapshot.
91+
92+
**[EKS Auto Mode NodeClass restriction]** → Cannot patch the `default` NodeClass for tagging. Mitigation: Create a separate custom NodeClass. Workloads using the default NodePool will have untagged instances — acceptable for system pods, not for Ontoserver. Route Ontoserver to the custom NodePool via nodeSelector.
93+
94+
**[ACM certificate manual step]** → ACM certificates require DNS or email validation, which cannot be fully automated without existing Route 53 control. Mitigation: Document as a prerequisite. If Route 53 hosted zone exists, ACK can automate validation via DNS records.
95+
96+
**[EKS Capabilities pricing]** → Each capability incurs hourly charges. Mitigation: Document the cost. For dev/test, capabilities can be disabled when not in use. Provide cost estimate in README.
97+
98+
## Migration Plan
99+
100+
This is a net-new deployment (no migration from existing systems). Deployment order:
101+
102+
1. **Bootstrap** (Terraform): state bucket → VPC → EKS Auto Mode → IAM → enable capabilities
103+
2. **Platform** (Argo CD syncs KRO definitions): ResourceGraphDefinitions applied → then instance created → ACK provisions RDS, ECR, etc.
104+
3. **Deployment** (Argo CD syncs Ontoserver): Helm release installed with EKS values → pods scheduled → ALB provisioned → DNS record created
105+
106+
Teardown order (reverse):
107+
1. Delete Ontoserver Argo CD Application (pods removed, ALB deleted)
108+
2. Delete KRO instance (ACK deletes RDS, ECR, CloudFront, WAF, Route 53)
109+
3. `terraform destroy` (EKS cluster, VPC, IAM removed)
110+
111+
## Open Questions
112+
113+
1. **ACK capability service scope**: Can a single ACK capability manage all required services (RDS, ECR, CloudFront, WAFv2, Route 53), or does each service need a separate capability enablement? Need to verify during implementation.
114+
2. **Argo CD initial bootstrap**: How does the first Argo CD Application get applied if Argo CD manages everything? Likely needs a one-time `kubectl apply` of the root Application (app-of-apps pattern), after which Argo CD self-manages. Document this step.
115+
3. **EBS volume lifecycle with Auto Mode**: If a node is replaced (21-day max lifetime), does the PVC volume reattach to the new node cleanly? Expected yes (standard K8s PVC behavior), but validate in testing.
116+
4. **KRO + ACK tag propagation**: Can KRO pass tag values from the instance spec down to ACK resource specs automatically, or must each ACK resource in the RGD explicitly list tags? Likely explicit — validate.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
## Why
2+
3+
Ontoserver customers on AWS have no self-contained deployment recipe. The existing `azure/` directory provides a complete Terraform-based AKS deployment, but there is no AWS equivalent. Customers must reverse-engineer patterns from `sparked-infrastructure` (an internal repo) or piece together the Helm chart examples manually. A turnkey `aws/` directory — using EKS Auto Mode and the managed EKS Capabilities (ACK, KRO, Argo CD) — gives customers a Kubernetes-native, low-maintenance path to running Ontoserver on AWS with minimal infrastructure expertise.
4+
5+
## What Changes
6+
7+
- Add `aws/` directory with a complete, self-contained AWS deployment for Ontoserver
8+
- Minimal Terraform bootstrap: VPC + EKS Auto Mode cluster + IAM for EKS Capabilities
9+
- EKS Capabilities (ACK, KRO, Argo CD) enabled as managed features — no self-installed controllers
10+
- KRO ResourceGraphDefinitions composing: RDS PostgreSQL, ECR pull-through cache, CloudFront CDN, WAF, Route 53 DNS
11+
- One top-level KRO instance per environment for cascading resource cleanup
12+
- 5-layer tagging strategy for all resources (Terraform, cluster, NodeClass, StorageClass, IngressClassParams)
13+
- ALB ingress with ACM TLS termination (Auto Mode built-in LB controller)
14+
- Argo CD (EKS Capability) for GitOps deployment of platform resources and Ontoserver Helm release
15+
- EBS gp3 persistence for Lucene indexes via Auto Mode's built-in EBS CSI
16+
- External Secrets Operator with ClusterSecretStore → AWS Secrets Manager
17+
- EKS Pod Identity for workload IAM
18+
- Container Insights + CloudWatch Logs (Auto Mode defaults)
19+
- Both read-write and read-only Ontoserver deployment patterns documented as KRO instances
20+
- README with architecture diagram and step-by-step instructions
21+
- Integration test: deploy, validate FHIR endpoint, upload CodeSystem, query, teardown
22+
23+
## Capabilities
24+
25+
### New Capabilities
26+
27+
- `aws-bootstrap`: Terraform module creating VPC, EKS Auto Mode cluster, IAM roles, and enabling EKS Capabilities (ACK, KRO, Argo CD). Supports new or existing VPC. Implements 5-layer tagging.
28+
- `aws-platform`: KRO ResourceGraphDefinitions composing ACK resources (RDS, ECR, CloudFront, WAF, Route 53) into a single per-environment instance. Includes StorageClass, IngressClassParams, and External Secrets configuration.
29+
- `aws-deployment`: Argo CD Application definitions deploying the ontoserver Helm chart with EKS-specific values (ALB ingress, ACM TLS, EBS persistence, Pod Identity, RDS connection). Covers read-write and scaled read-only patterns.
30+
- `aws-testing`: Integration test suite — deploy to live AWS account, validate FHIR endpoints with TLS, upload/query a CodeSystem, verify tagging, clean teardown.
31+
32+
### Modified Capabilities
33+
34+
(none — no existing specs)
35+
36+
## Impact
37+
38+
- New `aws/` directory tree (bootstrap/, platform/, deployment/, docs/)
39+
- No changes to existing charts, azure/, docker/, or examples/ directories
40+
- CI may gain an optional integration-test workflow gated on AWS credentials
41+
- README.md top-level table gains an `aws/` row
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
## ADDED Requirements
2+
3+
### Requirement: VPC creation
4+
The bootstrap SHALL create a new VPC with public and private subnets across 3 Availability Zones in the configured region, with NAT Gateway for private subnet egress. The bootstrap SHALL accept an optional existing VPC ID to skip VPC creation.
5+
6+
#### Scenario: New VPC created by default
7+
- **WHEN** the user runs `terraform apply` without providing an existing VPC ID
8+
- **THEN** a new VPC is created with public subnets, private subnets, an Internet Gateway, and a NAT Gateway across 3 AZs
9+
10+
#### Scenario: Existing VPC provided
11+
- **WHEN** the user provides a `vpc_id` variable
12+
- **THEN** no new VPC is created and the EKS cluster uses the provided VPC's subnets
13+
14+
### Requirement: EKS Auto Mode cluster
15+
The bootstrap SHALL create an EKS cluster with Auto Mode enabled, pinned to a specific Kubernetes version, with a public API server endpoint.
16+
17+
#### Scenario: Cluster creation with Auto Mode
18+
- **WHEN** `terraform apply` completes successfully
19+
- **THEN** an EKS cluster exists with `computeConfig.enabled = true`, `storageConfig.enabled = true`, `kubernetesNetworkConfig` set to Auto Mode defaults, and the specified Kubernetes version
20+
21+
#### Scenario: Kubernetes version pinning
22+
- **WHEN** the user sets `kubernetes_version = "1.32"`
23+
- **THEN** the EKS cluster control plane runs Kubernetes 1.32 and Auto Mode nodes use the corresponding AMI
24+
25+
### Requirement: EKS Capabilities enablement
26+
The bootstrap SHALL enable all three EKS Capabilities (ACK, KRO, Argo CD) on the cluster with appropriate IAM roles.
27+
28+
#### Scenario: ACK capability created
29+
- **WHEN** the cluster is provisioned
30+
- **THEN** an ACK capability is active with IAM permissions for RDS, ECR, CloudFront, WAFv2, and Route 53
31+
32+
#### Scenario: KRO capability created
33+
- **WHEN** the cluster is provisioned
34+
- **THEN** a KRO capability is active and can reconcile ResourceGraphDefinition custom resources
35+
36+
#### Scenario: Argo CD capability created
37+
- **WHEN** the cluster is provisioned
38+
- **THEN** an Argo CD capability is active with a reachable Argo CD UI endpoint
39+
40+
### Requirement: IAM for EKS Capabilities
41+
The bootstrap SHALL create IAM roles for each EKS Capability with least-privilege policies scoped to the services they manage.
42+
43+
#### Scenario: ACK capability role permissions
44+
- **WHEN** ACK attempts to create an RDS instance, ECR repository, CloudFront distribution, WAF WebACL, or Route 53 record
45+
- **THEN** the operation succeeds because the capability role has the necessary permissions
46+
47+
#### Scenario: Custom tag permissions
48+
- **WHEN** Auto Mode controllers (Karpenter, EBS CSI, ALB controller) create resources with custom tag keys (Project, Environment, ManagedBy)
49+
- **THEN** the operations succeed because `enable_auto_mode_custom_tags = true` adds the necessary IAM policy
50+
51+
### Requirement: 5-layer tagging (bootstrap layers)
52+
The bootstrap SHALL implement layers 1 and 2 of the 5-layer tagging pattern: Terraform `default_tags` on all TF-created resources, and `cluster_tags` on the EKS primary security group.
53+
54+
#### Scenario: Terraform-created resources tagged
55+
- **WHEN** any resource is created by Terraform (VPC, subnets, NAT, EKS cluster, IAM roles)
56+
- **THEN** the resource carries tags: `Project`, `Environment`, `ManagedBy=terraform`
57+
58+
#### Scenario: EKS primary security group tagged
59+
- **WHEN** the EKS cluster is created
60+
- **THEN** the EKS-managed primary security group carries the same tag set via `cluster_tags`
61+
62+
### Requirement: Terraform state backend
63+
The bootstrap SHALL use an S3 backend with DynamoDB locking for Terraform state. A helper script SHALL create the state bucket if it does not exist.
64+
65+
#### Scenario: State bucket creation
66+
- **WHEN** the user runs the bootstrap setup script for the first time
67+
- **THEN** an S3 bucket with versioning, encryption, and a DynamoDB lock table are created
68+
69+
#### Scenario: State locking
70+
- **WHEN** two concurrent `terraform apply` runs target the same state
71+
- **THEN** one is blocked by the DynamoDB lock until the other completes
72+
73+
### Requirement: Configurable variables
74+
The bootstrap SHALL expose variables for: region, environment name, Kubernetes version, VPC CIDR, existing VPC ID (optional), and tag values.
75+
76+
#### Scenario: Minimal configuration
77+
- **WHEN** the user provides only `environment = "dev"` and `region = "ap-southeast-2"`
78+
- **THEN** all other variables use sensible defaults and the deployment succeeds

0 commit comments

Comments
 (0)