[H1][PULUMI-K8S-GENERATOR]
Dictum: Infrastructure code follows deploy.ts canonical patterns.
Generate 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)
| Use this skill |
Use OTHER skill |
| Create/generate Pulumi K8s resources |
pulumi-k8s-validator: Validate existing code |
| Build ComponentResource compositions |
k8s-debug: Debug deployed resources |
| Define multi-resource stacks |
observability-stack: Observability infra |
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
- Invoke
pulumi-k8s-validator skill
- 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 pulumi-k8s-validator/references/common_issues.md |
| 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 |
1---2name: pulumi-k8s-generator3description: Generates production-ready Pulumi K8s TypeScript resources following deploy.ts patterns. Use when creating new Deployments, Services, Ingress, Gateway API, HPA, ConfigMaps, Secrets, PVCs, DaemonSets, NetworkPolicies, PDBs, ValidatingAdmissionPolicies, or ComponentResources in infrastructure code. NOT for validating existing Pulumi code (use pulumi-k8s-validator).4---5
6# [H1][PULUMI-K8S-GENERATOR]
7>**Dictum:** *Infrastructure code follows deploy.ts canonical patterns.*
8
9<br>
10
11Generate Pulumi K8s resources in TypeScript: `_CONFIG` + `_Ops` + dispatch table.
12
13**Provider:** current stable `@pulumi/kubernetes` (Server-Side Apply default) | **K8s:** 1.32-1.35 | **Canonical:** `infrastructure/src/deploy.ts` (207 LOC)
14
15| Use this skill | Use OTHER skill |
16| ------------------------------------ | ---------------------------------------------- |
17| Create/generate Pulumi K8s resources | `pulumi-k8s-validator`: Validate existing code |
18| Build ComponentResource compositions | `k8s-debug`: Debug deployed resources |
19| Define multi-resource stacks | `observability-stack`: Observability infra |
20
21**Tasks:**
221. Gather requirements (table below)
232. Lookup API docs via `context7-tools` for `@pulumi/kubernetes` target kind; fallback: WebSearch `"@pulumi/kubernetes" "<kind>" TypeScript API 2025`
243. Read `references/pulumi_k8s_patterns.md` -- naming, labels, security, mode dispatch
254. Read `references/resource_templates.md` -- templates, factories, ComponentResource, advanced patterns
265. Read `infrastructure/src/deploy.ts` -- canonical implementation
276. Generate resources per architecture and standards below
287. Invoke `pulumi-k8s-validator` skill
298. Deliver summary table with `pulumi preview` / `pulumi up` next steps
30
31---
32## [1][REQUIREMENTS]
33>**Dictum:** *Gather all inputs before generation.*
34
35<br>
36
37| Field | Required | Default | deploy.ts Reference |
38| ------------------ | -------- | ----------------------------------------------- | ------------------------------ |
39| Deployment mode | YES | -- | `_Ops.mode()` (line 64) |
40| Resource kind(s) | YES | -- | -- |
41| Container image | YES | -- | `input.api.image` (line 163) |
42| Port | YES | `4000` | `_CONFIG.ports.api` (line 22) |
43| Health paths | YES | `/api/health/liveness`, `/api/health/readiness` | `_CONFIG.k8s.probes` (line 19) |
44| CPU/memory | NO | `small` preset | `input.api.cpu` (line 168) |
45| HPA min/max/target | NO | env-driven | `input.hpa.*` (line 174) |
46| PVC size | NO | `10Gi` | `_k8sObserve` (line 120) |
47| Namespace | NO | `parametric` | `_CONFIG.k8s.namespace` |
48
49Mode: `cloud` (K8s+AWS) or `selfhosted` (Docker). Kind: Deployment, Service, Ingress, Gateway, HTTPRoute, GRPCRoute, HPA, ConfigMap, Secret, PVC, DaemonSet, NetworkPolicy, PDB, ValidatingAdmissionPolicy, ComponentResource.
50
51---
52## [2][ARCHITECTURE]
53>**Dictum:** *deploy.ts layers structure all generated code.*
54
55<br>
56
57| Layer | Purpose | Lines |
58| ------------- | ------------------------------------------------------------ | ------- |
59| `_CONFIG` | Immutable `as const` -- ports, labels, probes, images | 11-24 |
60| `_Ops` | Pure factories -- `meta()`, `k8sUrl()`, `secret()`, `fail()` | 28-119 |
61| `_k8sObserve` | Array-driven factory: PVC+ConfigMap+Deployment+Service | 120-126 |
62| `_DEPLOY` | Dispatch table `{ cloud, selfhosted } as const` | 130-195 |
63| `deploy` | Entry point: resolves mode, delegates to dispatch | 199-202 |
64
65**Guidance:**
66- `Mode dispatch` - Cloud uses ClusterIP + nginx ingress. Selfhosted uses `@pulumi/docker` exclusively.
67- `Output tracking` - Use `namespace.metadata.name` (Output) for implicit dependency ordering.
68- `Secrets` - `pulumi.secret()` wraps sensitive values; `pulumi.interpolate` for `Output<T>` strings.
69- `Factories` - Array-driven `_k8sObserve` pattern for repetitive resource groups.
70
71**Best-Practices:**
72- Resources require `requests` + `limits` (env-driven, deploy.ts:168). Guaranteed QoS when `limits == requests`.
73- All workloads require liveness + readiness + startup probes (deploy.ts:19).
74- New workloads require `_SECURITY` pod/container contexts (see resource_templates.md).
75- `terminationGracePeriodSeconds: 30` on all pod specs (deploy.ts:171).
76- `as const satisfies` for config objects; `pulumi.interpolate` only when mixing `Output<T>`.
77- PodDisruptionBudget required for `replicas >= 2`. NetworkPolicy required for production namespaces.
78- `topologySpreadConstraints` for zone distribution; pod anti-affinity for node distribution.
79
80---
81## [3][MODE_RULES]
82>**Dictum:** *Mode dispatch prevents cross-concern resource creation.*
83
84<br>
85
86| Concern | `cloud` (K8s + AWS) | `selfhosted` (Docker) |
87| ------- | ----------------------------------------- | ------------------------------------ |
88| Compute | Deployment + Service (ClusterIP) | `docker.Container` + Traefik labels |
89| Ingress | Ingress (nginx class) or Gateway API | Traefik reverse proxy |
90| Scaling | HPA (CPU + memory targets) | None |
91| Config | ConfigMap + Secret | `docker.Container.envs` |
92| Data | AWS RDS + ElastiCache + S3 | Docker containers (pg, redis, minio) |
93| TLS | Ingress TLS + ssl-redirect annotation | Let's Encrypt via Traefik |
94| Observe | DaemonSet (Alloy) + `_k8sObserve` factory | Docker containers with uploads |
95
96[CRITICAL] Cloud: ClusterIP + nginx ingress (NOT LoadBalancer + ALB). Selfhosted: `@pulumi/docker` only (NOT Kubernetes).
97
98---
99## [4][TROUBLESHOOTING]
100>**Dictum:** *Common failures have deterministic fixes.*
101
102<br>
103
104| Issue | Cause | Fix |
105| ---------------------------- | --------------------------------- | ------------------------------------------------------------- |
106| Type errors on k8s resources | API shape changed in provider | Verify against current stable API via context7 |
107| Preview fails on namespace | Namespace not yet created | Use `namespace.metadata.name` Output for implicit dep |
108| Cross-stack reference errors | Wrong format or different backend | Format: `<org>/<project>/<stack>`, same backend required |
109| Selfhosted creating k8s | Mode violation | Selfhosted uses `@pulumi/docker` only |
110| `already exists` in preview | Resource in cluster not in state | `pulumi import <type> <name> <id>` |
111| Replace instead of update | Immutable field changed | See `pulumi-k8s-validator/references/common_issues.md` |
112| Server-Side Apply conflicts | Field manager ownership conflict | `pulumi refresh` or set field manager explicitly |
113| Gateway API not found | CRDs not installed | Install gateway controller before Gateway/HTTPRoute/GRPCRoute |