@intentius/chant-lexicon-k8s 0.0.13 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/integrity.json +17 -15
- package/dist/manifest.json +1 -1
- package/dist/skills/chant-k8s-eks.md +156 -0
- package/dist/skills/chant-k8s-patterns.md +245 -0
- package/dist/skills/chant-k8s.md +36 -227
- package/package.json +2 -2
- package/src/codegen/docs.ts +4 -4
- package/src/composites/adot-collector.ts +239 -0
- package/src/composites/alb-ingress.ts +151 -0
- package/src/composites/autoscaled-service.ts +33 -0
- package/src/composites/batch-job.ts +188 -0
- package/src/composites/composites.test.ts +883 -0
- package/src/composites/configured-app.ts +218 -0
- package/src/composites/ebs-storage-class.ts +96 -0
- package/src/composites/efs-storage-class.ts +77 -0
- package/src/composites/external-dns-agent.ts +168 -0
- package/src/composites/fluent-bit-agent.ts +215 -0
- package/src/composites/index.ts +28 -0
- package/src/composites/irsa-service-account.ts +114 -0
- package/src/composites/metrics-server.ts +224 -0
- package/src/composites/monitored-service.ts +215 -0
- package/src/composites/network-isolated-app.ts +196 -0
- package/src/composites/secure-ingress.ts +149 -0
- package/src/composites/sidecar-app.ts +201 -0
- package/src/composites/stateful-app.ts +70 -15
- package/src/composites/web-app.ts +107 -35
- package/src/composites/worker-pool.ts +41 -4
- package/src/index.ts +19 -2
- package/src/plugin.ts +552 -241
package/dist/integrity.json
CHANGED
|
@@ -1,32 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "xxhash64",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "59b066d7c2f8d709",
|
|
5
5
|
"meta.json": "1ce194f36f9b5f90",
|
|
6
6
|
"types/index.d.ts": "beec4cc869064186",
|
|
7
7
|
"rules/hardcoded-namespace.ts": "54b216c71018e101",
|
|
8
|
-
"rules/wk8006.ts": "6e04f754f79f076e",
|
|
9
8
|
"rules/wk8201.ts": "4dbbd20e21b5fa04",
|
|
10
|
-
"rules/
|
|
11
|
-
"rules/k8s-helpers.ts": "53a6d3bfbedb2852",
|
|
9
|
+
"rules/wk8204.ts": "31c3f8eac8455795",
|
|
12
10
|
"rules/wk8301.ts": "283265ab0c5b8511",
|
|
13
|
-
"rules/
|
|
11
|
+
"rules/wk8102.ts": "78d4aac387107b56",
|
|
14
12
|
"rules/wk8101.ts": "f8ffcf6e5c89076b",
|
|
15
13
|
"rules/wk8302.ts": "a80d1eab37c0dbe4",
|
|
14
|
+
"rules/wk8005.ts": "a9a1b93b80f3aa51",
|
|
15
|
+
"rules/wk8209.ts": "820df53f304e0a59",
|
|
16
16
|
"rules/wk8203.ts": "f5bf17539c0428c5",
|
|
17
|
-
"rules/wk8042.ts": "6064c84481ae8551",
|
|
18
|
-
"rules/wk8202.ts": "6bd950ae2128256c",
|
|
19
|
-
"rules/wk8207.ts": "6f2bc621d530afa2",
|
|
20
17
|
"rules/wk8104.ts": "94bd75c16b8d50b7",
|
|
18
|
+
"rules/wk8303.ts": "c545464e2af8fbb9",
|
|
19
|
+
"rules/wk8103.ts": "e5d6a506d966e312",
|
|
21
20
|
"rules/wk8205.ts": "d000527c6371a05",
|
|
21
|
+
"rules/wk8042.ts": "6064c84481ae8551",
|
|
22
|
+
"rules/wk8006.ts": "6e04f754f79f076e",
|
|
22
23
|
"rules/wk8041.ts": "4df512c93caaef50",
|
|
23
|
-
"rules/
|
|
24
|
-
"rules/wk8005.ts": "a9a1b93b80f3aa51",
|
|
25
|
-
"rules/wk8303.ts": "c545464e2af8fbb9",
|
|
26
|
-
"rules/wk8204.ts": "31c3f8eac8455795",
|
|
24
|
+
"rules/wk8202.ts": "6bd950ae2128256c",
|
|
27
25
|
"rules/wk8208.ts": "1133f9e53c174ae9",
|
|
28
|
-
"rules/
|
|
29
|
-
"
|
|
26
|
+
"rules/wk8105.ts": "8dbcfe399f23656a",
|
|
27
|
+
"rules/k8s-helpers.ts": "53a6d3bfbedb2852",
|
|
28
|
+
"rules/wk8207.ts": "6f2bc621d530afa2",
|
|
29
|
+
"skills/chant-k8s.md": "c7db82c3ba37c78",
|
|
30
|
+
"skills/chant-k8s-eks.md": "f79f31f058c7f2ed",
|
|
31
|
+
"skills/chant-k8s-patterns.md": "c5151ed799145c4b"
|
|
30
32
|
},
|
|
31
|
-
"composite": "
|
|
33
|
+
"composite": "586aea18d5400dd8"
|
|
32
34
|
}
|
package/dist/manifest.json
CHANGED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
skill: chant-k8s-eks
|
|
3
|
+
description: EKS-specific Kubernetes patterns and composites
|
|
4
|
+
user-invocable: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# EKS Kubernetes Patterns
|
|
8
|
+
|
|
9
|
+
## EKS Composites Overview
|
|
10
|
+
|
|
11
|
+
These composites produce K8s YAML with EKS-specific annotations and configurations.
|
|
12
|
+
|
|
13
|
+
### IrsaServiceAccount — ServiceAccount with IAM Role annotation
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { IrsaServiceAccount } from "@intentius/chant-lexicon-k8s";
|
|
17
|
+
|
|
18
|
+
const { serviceAccount, role, roleBinding } = IrsaServiceAccount({
|
|
19
|
+
name: "app-sa",
|
|
20
|
+
iamRoleArn: "arn:aws:iam::123456789012:role/my-app-role",
|
|
21
|
+
rbacRules: [
|
|
22
|
+
{ apiGroups: [""], resources: ["secrets"], verbs: ["get"] },
|
|
23
|
+
],
|
|
24
|
+
namespace: "prod",
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### AlbIngress — Ingress with AWS ALB Controller annotations
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { AlbIngress } from "@intentius/chant-lexicon-k8s";
|
|
32
|
+
|
|
33
|
+
const { ingress } = AlbIngress({
|
|
34
|
+
name: "api-ingress",
|
|
35
|
+
hosts: [
|
|
36
|
+
{
|
|
37
|
+
hostname: "api.example.com",
|
|
38
|
+
paths: [{ path: "/", serviceName: "api", servicePort: 80 }],
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
scheme: "internet-facing",
|
|
42
|
+
certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/abc-123",
|
|
43
|
+
groupName: "shared-alb",
|
|
44
|
+
healthCheckPath: "/healthz",
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Features:
|
|
49
|
+
- Auto-sets `alb.ingress.kubernetes.io/*` annotations
|
|
50
|
+
- SSL redirect enabled by default when `certificateArn` set
|
|
51
|
+
- `groupName` for shared ALB across multiple Ingresses
|
|
52
|
+
- `wafAclArn` for WAFv2 integration
|
|
53
|
+
|
|
54
|
+
### EbsStorageClass — StorageClass for EBS CSI
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { EbsStorageClass } from "@intentius/chant-lexicon-k8s";
|
|
58
|
+
|
|
59
|
+
const { storageClass } = EbsStorageClass({
|
|
60
|
+
name: "gp3-encrypted",
|
|
61
|
+
type: "gp3",
|
|
62
|
+
encrypted: true,
|
|
63
|
+
iops: "3000",
|
|
64
|
+
throughput: "125",
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### EfsStorageClass — StorageClass for EFS CSI (ReadWriteMany)
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { EfsStorageClass } from "@intentius/chant-lexicon-k8s";
|
|
72
|
+
|
|
73
|
+
const { storageClass } = EfsStorageClass({
|
|
74
|
+
name: "efs-shared",
|
|
75
|
+
fileSystemId: "fs-12345678",
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Use EFS when you need ReadWriteMany (shared across pods/nodes). Use EBS for ReadWriteOnce (single pod).
|
|
80
|
+
|
|
81
|
+
### FluentBitAgent — DaemonSet for CloudWatch logging
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { FluentBitAgent } from "@intentius/chant-lexicon-k8s";
|
|
85
|
+
|
|
86
|
+
const result = FluentBitAgent({
|
|
87
|
+
logGroup: "/aws/eks/my-cluster/containers",
|
|
88
|
+
region: "us-east-1",
|
|
89
|
+
clusterName: "my-cluster",
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### ExternalDnsAgent — ExternalDNS for Route53
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { ExternalDnsAgent } from "@intentius/chant-lexicon-k8s";
|
|
97
|
+
|
|
98
|
+
const result = ExternalDnsAgent({
|
|
99
|
+
iamRoleArn: "arn:aws:iam::123456789012:role/external-dns-role",
|
|
100
|
+
domainFilters: ["example.com"],
|
|
101
|
+
txtOwnerId: "my-cluster",
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### AdotCollector — ADOT for CloudWatch/X-Ray
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { AdotCollector } from "@intentius/chant-lexicon-k8s";
|
|
109
|
+
|
|
110
|
+
const result = AdotCollector({
|
|
111
|
+
region: "us-east-1",
|
|
112
|
+
clusterName: "my-cluster",
|
|
113
|
+
exporters: ["cloudwatch", "xray"],
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Pod Identity vs IRSA
|
|
118
|
+
|
|
119
|
+
| Feature | IRSA | Pod Identity |
|
|
120
|
+
|---------|------|-------------|
|
|
121
|
+
| K8s annotation needed | Yes (`eks.amazonaws.com/role-arn`) | No |
|
|
122
|
+
| Composite available | **IrsaServiceAccount** | None needed |
|
|
123
|
+
| Setup | OIDC provider + IAM role trust policy | EKS Pod Identity Agent add-on + association |
|
|
124
|
+
| When to use | Existing clusters, broad compatibility | New clusters (EKS 1.28+), simpler management |
|
|
125
|
+
|
|
126
|
+
For Pod Identity, no K8s-side composite is needed — configure the association via AWS API/CloudFormation and use a plain ServiceAccount.
|
|
127
|
+
|
|
128
|
+
## Karpenter
|
|
129
|
+
|
|
130
|
+
Karpenter replaces Cluster Autoscaler for node provisioning. Karpenter NodePool and EC2NodeClass are simple CRDs — use CRD import rather than composites:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Import Karpenter CRDs into your chant project
|
|
134
|
+
chant import --url https://raw.githubusercontent.com/aws/karpenter/main/pkg/apis/crds/karpenter.sh_nodepools.yaml
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Fargate Considerations
|
|
138
|
+
|
|
139
|
+
When running on EKS Fargate:
|
|
140
|
+
- **No DaemonSets** — FluentBitAgent and AdotCollector cannot run on Fargate nodes
|
|
141
|
+
- **No hostPath volumes** — use EFS for shared storage
|
|
142
|
+
- **No privileged containers** — security context restrictions apply
|
|
143
|
+
- For Fargate logging, use the built-in Fluent Bit log router (Fargate logging configuration)
|
|
144
|
+
|
|
145
|
+
## EKS Add-ons
|
|
146
|
+
|
|
147
|
+
Common add-ons managed via AWS (not K8s manifests):
|
|
148
|
+
- **vpc-cni** — Amazon VPC CNI plugin
|
|
149
|
+
- **coredns** — Cluster DNS
|
|
150
|
+
- **kube-proxy** — Network proxy
|
|
151
|
+
- **aws-ebs-csi-driver** — EBS CSI driver (required for EbsStorageClass)
|
|
152
|
+
- **aws-efs-csi-driver** — EFS CSI driver (required for EfsStorageClass)
|
|
153
|
+
- **adot** — AWS Distro for OpenTelemetry (alternative to AdotCollector composite)
|
|
154
|
+
- **aws-guardduty-agent** — Runtime threat detection
|
|
155
|
+
|
|
156
|
+
Configure add-ons via the AWS lexicon (`@intentius/chant-lexicon-aws`) CloudFormation resources.
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
---
|
|
2
|
+
skill: chant-k8s-patterns
|
|
3
|
+
description: Advanced Kubernetes deployment patterns and composites
|
|
4
|
+
user-invocable: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Advanced Kubernetes Patterns
|
|
8
|
+
|
|
9
|
+
## Sidecar Patterns
|
|
10
|
+
|
|
11
|
+
### SidecarApp — multi-container Deployment
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { SidecarApp } from "@intentius/chant-lexicon-k8s";
|
|
15
|
+
|
|
16
|
+
// Envoy sidecar proxy
|
|
17
|
+
const { deployment, service } = SidecarApp({
|
|
18
|
+
name: "api",
|
|
19
|
+
image: "api:1.0",
|
|
20
|
+
port: 8080,
|
|
21
|
+
sidecars: [
|
|
22
|
+
{
|
|
23
|
+
name: "envoy",
|
|
24
|
+
image: "envoyproxy/envoy:v1.28",
|
|
25
|
+
ports: [{ containerPort: 9901, name: "admin" }],
|
|
26
|
+
resources: { requests: { cpu: "100m", memory: "128Mi" }, limits: { cpu: "200m", memory: "256Mi" } },
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
initContainers: [
|
|
30
|
+
{ name: "migrate", image: "api:1.0", command: ["python", "manage.py", "migrate"] },
|
|
31
|
+
],
|
|
32
|
+
sharedVolumes: [{ name: "tmp", emptyDir: {} }],
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Common sidecar use cases:
|
|
37
|
+
- **Envoy proxy** — service mesh, mTLS, traffic management
|
|
38
|
+
- **Log forwarder** — Fluent Bit sidecar for app-specific log routing
|
|
39
|
+
- **Auth proxy** — OAuth2 Proxy for authentication
|
|
40
|
+
- **Config watcher** — reload config on ConfigMap changes
|
|
41
|
+
|
|
42
|
+
## Config and Secret Mounting
|
|
43
|
+
|
|
44
|
+
### ConfiguredApp — automatic volume wiring
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { ConfiguredApp } from "@intentius/chant-lexicon-k8s";
|
|
48
|
+
|
|
49
|
+
const { deployment, service, configMap } = ConfiguredApp({
|
|
50
|
+
name: "api",
|
|
51
|
+
image: "api:1.0",
|
|
52
|
+
port: 8080,
|
|
53
|
+
// Mount ConfigMap as volume
|
|
54
|
+
configData: { "app.conf": "key=value\nother=setting" },
|
|
55
|
+
configMountPath: "/etc/api",
|
|
56
|
+
// Mount existing Secret as volume
|
|
57
|
+
secretName: "api-creds",
|
|
58
|
+
secretMountPath: "/secrets",
|
|
59
|
+
// Inject as environment variables
|
|
60
|
+
envFrom: { secretRef: "api-env-secret", configMapRef: "api-env-config" },
|
|
61
|
+
// Run migrations before the app starts
|
|
62
|
+
initContainers: [
|
|
63
|
+
{ name: "migrate", image: "api:1.0", command: ["./migrate.sh"] },
|
|
64
|
+
],
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Volume patterns
|
|
69
|
+
|
|
70
|
+
| Pattern | Use Case | ConfiguredApp Props |
|
|
71
|
+
|---------|----------|---------------------|
|
|
72
|
+
| ConfigMap as file | Config files, templates | `configData` + `configMountPath` |
|
|
73
|
+
| Secret as file | TLS certs, credentials | `secretName` + `secretMountPath` |
|
|
74
|
+
| ConfigMap as env | Simple key-value config | `envFrom.configMapRef` |
|
|
75
|
+
| Secret as env | Database URLs, API keys | `envFrom.secretRef` |
|
|
76
|
+
|
|
77
|
+
## TLS / cert-manager
|
|
78
|
+
|
|
79
|
+
### SecureIngress — multi-host TLS with cert-manager
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { SecureIngress } from "@intentius/chant-lexicon-k8s";
|
|
83
|
+
|
|
84
|
+
const { ingress, certificate } = SecureIngress({
|
|
85
|
+
name: "app-ingress",
|
|
86
|
+
hosts: [
|
|
87
|
+
{
|
|
88
|
+
hostname: "api.example.com",
|
|
89
|
+
paths: [
|
|
90
|
+
{ path: "/v1", serviceName: "api-v1", servicePort: 80 },
|
|
91
|
+
{ path: "/v2", serviceName: "api-v2", servicePort: 80 },
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
hostname: "admin.example.com",
|
|
96
|
+
paths: [{ path: "/", serviceName: "admin", servicePort: 80 }],
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
clusterIssuer: "letsencrypt-prod",
|
|
100
|
+
ingressClassName: "nginx",
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Features:
|
|
105
|
+
- Multiple hosts and paths per Ingress
|
|
106
|
+
- Automatic cert-manager Certificate when `clusterIssuer` set
|
|
107
|
+
- TLS secret auto-provisioned by cert-manager
|
|
108
|
+
|
|
109
|
+
### cert-manager setup (prerequisite)
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Install cert-manager
|
|
113
|
+
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
|
|
114
|
+
|
|
115
|
+
# Create ClusterIssuer for Let's Encrypt
|
|
116
|
+
kubectl apply -f - <<EOF
|
|
117
|
+
apiVersion: cert-manager.io/v1
|
|
118
|
+
kind: ClusterIssuer
|
|
119
|
+
metadata:
|
|
120
|
+
name: letsencrypt-prod
|
|
121
|
+
spec:
|
|
122
|
+
acme:
|
|
123
|
+
server: https://acme-v02.api.letsencrypt.org/directory
|
|
124
|
+
email: admin@example.com
|
|
125
|
+
privateKeySecretRef:
|
|
126
|
+
name: letsencrypt-prod-key
|
|
127
|
+
solvers:
|
|
128
|
+
- http01:
|
|
129
|
+
ingress:
|
|
130
|
+
class: nginx
|
|
131
|
+
EOF
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Observability
|
|
135
|
+
|
|
136
|
+
### MonitoredService — Prometheus monitoring
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { MonitoredService } from "@intentius/chant-lexicon-k8s";
|
|
140
|
+
|
|
141
|
+
const { deployment, service, serviceMonitor, prometheusRule } = MonitoredService({
|
|
142
|
+
name: "api",
|
|
143
|
+
image: "api:1.0",
|
|
144
|
+
port: 8080,
|
|
145
|
+
metricsPort: 9090,
|
|
146
|
+
metricsPath: "/metrics",
|
|
147
|
+
scrapeInterval: "15s",
|
|
148
|
+
alertRules: [
|
|
149
|
+
{
|
|
150
|
+
name: "HighErrorRate",
|
|
151
|
+
expr: 'rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05',
|
|
152
|
+
for: "5m",
|
|
153
|
+
severity: "critical",
|
|
154
|
+
annotations: { summary: "High error rate on {{ $labels.instance }}" },
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "HighLatency",
|
|
158
|
+
expr: 'histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 1',
|
|
159
|
+
for: "10m",
|
|
160
|
+
severity: "warning",
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Prerequisites
|
|
167
|
+
|
|
168
|
+
- Prometheus Operator installed (for ServiceMonitor/PrometheusRule CRDs)
|
|
169
|
+
- Prometheus configured to discover ServiceMonitors
|
|
170
|
+
|
|
171
|
+
## Network Isolation
|
|
172
|
+
|
|
173
|
+
### NetworkIsolatedApp — per-app firewall rules
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
import { NetworkIsolatedApp } from "@intentius/chant-lexicon-k8s";
|
|
177
|
+
|
|
178
|
+
const { deployment, service, networkPolicy } = NetworkIsolatedApp({
|
|
179
|
+
name: "api",
|
|
180
|
+
image: "api:1.0",
|
|
181
|
+
port: 8080,
|
|
182
|
+
allowIngressFrom: [
|
|
183
|
+
{ podSelector: { "app.kubernetes.io/name": "frontend" } },
|
|
184
|
+
{ namespaceSelector: { "kubernetes.io/metadata.name": "monitoring" } },
|
|
185
|
+
],
|
|
186
|
+
allowEgressTo: [
|
|
187
|
+
{ podSelector: { "app.kubernetes.io/name": "postgres" }, ports: [{ port: 5432 }] },
|
|
188
|
+
{ podSelector: { "app.kubernetes.io/name": "redis" }, ports: [{ port: 6379 }] },
|
|
189
|
+
],
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Combining with NamespaceEnv
|
|
194
|
+
|
|
195
|
+
Use NamespaceEnv for namespace-level default-deny, then NetworkIsolatedApp for per-app allow rules:
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// Namespace: deny all by default
|
|
199
|
+
const ns = NamespaceEnv({ name: "prod", defaultDenyIngress: true, defaultDenyEgress: true });
|
|
200
|
+
|
|
201
|
+
// App: allow specific traffic
|
|
202
|
+
const app = NetworkIsolatedApp({
|
|
203
|
+
name: "api",
|
|
204
|
+
image: "api:1.0",
|
|
205
|
+
namespace: "prod",
|
|
206
|
+
allowIngressFrom: [{ podSelector: { "app.kubernetes.io/name": "gateway" } }],
|
|
207
|
+
allowEgressTo: [{ podSelector: { "app.kubernetes.io/name": "db" }, ports: [{ port: 5432 }] }],
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Blue/Green and Canary
|
|
212
|
+
|
|
213
|
+
These patterns use standard K8s resources — no special composite needed.
|
|
214
|
+
|
|
215
|
+
### Blue/Green
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
// Two Deployments with different versions
|
|
219
|
+
const blue = WebApp({ name: "app-blue", image: "app:1.0", labels: { version: "blue" } });
|
|
220
|
+
const green = WebApp({ name: "app-green", image: "app:2.0", labels: { version: "green" } });
|
|
221
|
+
|
|
222
|
+
// Service points to active version — switch by changing selector
|
|
223
|
+
// Active: blue → green (update the Service selector)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Canary
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
// Main deployment (90% traffic)
|
|
230
|
+
const main = AutoscaledService({ name: "app", image: "app:1.0", minReplicas: 9, maxReplicas: 20, ... });
|
|
231
|
+
|
|
232
|
+
// Canary deployment (10% traffic) — same app label, fewer replicas
|
|
233
|
+
const canary = WebApp({ name: "app-canary", image: "app:2.0", replicas: 1, labels: { track: "canary" } });
|
|
234
|
+
// Both share the same Service selector ("app.kubernetes.io/name": "app") for traffic splitting
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Gateway API (future direction)
|
|
238
|
+
|
|
239
|
+
Gateway API is the successor to Ingress. Key differences:
|
|
240
|
+
- **HTTPRoute** replaces Ingress rules
|
|
241
|
+
- **Gateway** replaces IngressClass
|
|
242
|
+
- Built-in traffic splitting, header matching, URL rewriting
|
|
243
|
+
- Currently in beta — use Ingress/SecureIngress/AlbIngress for production today
|
|
244
|
+
|
|
245
|
+
When Gateway API reaches GA, new composites will be added. For now, use CRD import if you need Gateway API resources.
|