| name | k8s |
| description | Generates and validates production-ready Pulumi K8s TypeScript resources following deploy.ts patterns, and diagnoses runtime cluster issues. Use when creating Deployments, Services, Ingress, Gateway API, HPA, ConfigMaps, Secrets, PVCs, DaemonSets, NetworkPolicies, PDBs, ValidatingAdmissionPolicies, ComponentResources, validating existing infra code, or debugging deployed K8s/EKS workloads. |
[H1][K8S]
Dictum: Infrastructure code follows deploy.ts canonical patterns; validation and debugging are integral.
Generate, validate, and debug Pulumi K8s resources in TypeScript: _CONFIG + _Ops + dispatch table.
Provider: current stable @pulumi/kubernetes (Server-Side Apply default) | K8s: 1.32-1.35 | Canonical: infrastructure/src/deploy.ts (207 LOC)
Tasks:
- Gather requirements (table below)
- Lookup API docs via
context7-tools for @pulumi/kubernetes target kind; fallback: WebSearch "@pulumi/kubernetes" "<kind>" TypeScript API 2025
- Read
references/pulumi_k8s_patterns.md -- naming, labels, security, mode dispatch
- Read
references/resource_templates.md -- templates, factories, ComponentResource, advanced patterns
- Read
infrastructure/src/deploy.ts -- canonical implementation
- Generate resources per architecture and standards below
- Validate against
references/validation.md -- security, reliability, cross-resource checks
- For runtime issues, read
references/debug.md -- decision tree, kubectl workflows, EKS diagnostics
- Deliver summary table with
pulumi preview / pulumi up next steps
[1][REQUIREMENTS]
Dictum: Gather all inputs before generation.
| Field | Required | Default | deploy.ts Reference |
|---|
| Deployment mode | YES | -- | _Ops.mode() (line 64) |
| Resource kind(s) | YES | -- | -- |
| Container image | YES | -- | input.api.image (line 163) |
| Port | YES | 4000 | _CONFIG.ports.api (line 22) |
| Health paths | YES | /api/health/liveness, /api/health/readiness | _CONFIG.k8s.probes (line 19) |
| CPU/memory | NO | small preset | input.api.cpu (line 168) |
| HPA min/max/target | NO | env-driven | input.hpa.* (line 174) |
| PVC size | NO | 10Gi | _k8sObserve (line 120) |
| Namespace | NO | parametric | _CONFIG.k8s.namespace |
Mode: cloud (K8s+AWS) or selfhosted (Docker). Kind: Deployment, Service, Ingress, Gateway, HTTPRoute, GRPCRoute, HPA, ConfigMap, Secret, PVC, DaemonSet, NetworkPolicy, PDB, ValidatingAdmissionPolicy, ComponentResource.
[2][ARCHITECTURE]
Dictum: deploy.ts layers structure all generated code.
| Layer | Purpose | Lines |
|---|
_CONFIG | Immutable as const -- ports, labels, probes, images | 11-24 |
_Ops | Pure factories -- meta(), k8sUrl(), secret(), fail() | 28-119 |
_k8sObserve | Array-driven factory: PVC+ConfigMap+Deployment+Service | 120-126 |
_DEPLOY | Dispatch table { cloud, selfhosted } as const | 130-195 |
deploy | Entry point: resolves mode, delegates to dispatch | 199-202 |
Guidance:
Mode dispatch - Cloud uses ClusterIP + nginx ingress. Selfhosted uses @pulumi/docker exclusively.
Output tracking - Use namespace.metadata.name (Output) for implicit dependency ordering.
Secrets - pulumi.secret() wraps sensitive values; pulumi.interpolate for Output<T> strings.
Factories - Array-driven _k8sObserve pattern for repetitive resource groups.
Best-Practices:
- Resources require
requests + limits (env-driven, deploy.ts:168). Guaranteed QoS when limits == requests.
- All workloads require liveness + readiness + startup probes (deploy.ts:19).
- New workloads require
_SECURITY pod/container contexts (see resource_templates.md).
terminationGracePeriodSeconds: 30 on all pod specs (deploy.ts:171).
as const satisfies for config objects; pulumi.interpolate only when mixing Output<T>.
- PodDisruptionBudget required for
replicas >= 2. NetworkPolicy required for production namespaces.
topologySpreadConstraints for zone distribution; pod anti-affinity for node distribution.
[3][MODE_RULES]
Dictum: Mode dispatch prevents cross-concern resource creation.
| Concern | cloud (K8s + AWS) | selfhosted (Docker) |
|---|
| Compute | Deployment + Service (ClusterIP) | docker.Container + Traefik labels |
| Ingress | Ingress (nginx class) or Gateway API | Traefik reverse proxy |
| Scaling | HPA (CPU + memory targets) | None |
| Config | ConfigMap + Secret | docker.Container.envs |
| Data | AWS RDS + ElastiCache + S3 | Docker containers (pg, redis, minio) |
| TLS | Ingress TLS + ssl-redirect annotation | Let's Encrypt via Traefik |
| Observe | DaemonSet (Alloy) + _k8sObserve factory | Docker containers with uploads |
[CRITICAL] Cloud: ClusterIP + nginx ingress (NOT LoadBalancer + ALB). Selfhosted: @pulumi/docker only (NOT Kubernetes).
[4][TROUBLESHOOTING]
Dictum: Common failures have deterministic fixes.
| Issue | Cause | Fix |
|---|
| Type errors on k8s resources | API shape changed in provider | Verify against current stable API via context7 |
| Preview fails on namespace | Namespace not yet created | Use namespace.metadata.name Output for implicit dep |
| Cross-stack reference errors | Wrong format or different backend | Format: <org>/<project>/<stack>, same backend required |
| Selfhosted creating k8s | Mode violation | Selfhosted uses @pulumi/docker only |
already exists in preview | Resource in cluster not in state | pulumi import <type> <name> <id> |
| Replace instead of update | Immutable field changed | See references/validation.md immutable fields table |
| Server-Side Apply conflicts | Field manager ownership conflict | pulumi refresh or set field manager explicitly |
| Gateway API not found | CRDs not installed | Install gateway controller before Gateway/HTTPRoute/GRPCRoute |
| Sidecar not recognized | K8s <1.33 or feature gate off | Verify cluster 1.33+; check SidecarContainers gate |
| In-place resize rejected | K8s <1.35 or feature gate off | Verify cluster 1.35+; check InPlacePodVerticalScaling gate |
| DRA ResourceClaim not bound | DRA driver not installed | Verify ResourceClass and device plugin running |
| Topology routing not working | Missing annotation | Add service.kubernetes.io/topology-mode: auto |