@intentius/chant-lexicon-k8s 0.0.12 → 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/README.md +24 -0
- 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/src/plugin.ts
CHANGED
|
@@ -513,20 +513,6 @@ kubectl port-forward pod/<pod-name> 8080:8080
|
|
|
513
513
|
| CreateContainerError | Container config issue | \`kubectl describe pod\` → Events | Check volume mounts, configmap/secret refs, security context |
|
|
514
514
|
| Init:CrashLoopBackOff | Init container failing | \`kubectl logs -c <init-container>\` | Fix init container command, check dependencies |
|
|
515
515
|
|
|
516
|
-
### Resource inspection
|
|
517
|
-
|
|
518
|
-
\`\`\`bash
|
|
519
|
-
# Get all resources in namespace
|
|
520
|
-
kubectl get all -n <namespace>
|
|
521
|
-
|
|
522
|
-
# YAML output for debugging
|
|
523
|
-
kubectl get deployment/my-app -o yaml
|
|
524
|
-
|
|
525
|
-
# Check resource usage
|
|
526
|
-
kubectl top pods -l app.kubernetes.io/name=my-app
|
|
527
|
-
kubectl top nodes
|
|
528
|
-
\`\`\`
|
|
529
|
-
|
|
530
516
|
## Production safety
|
|
531
517
|
|
|
532
518
|
### Pre-apply validation
|
|
@@ -542,22 +528,6 @@ kubectl apply -f manifests.yaml --dry-run=server
|
|
|
542
528
|
kubectl apply -f manifests.yaml --dry-run=client
|
|
543
529
|
\`\`\`
|
|
544
530
|
|
|
545
|
-
### Rollback
|
|
546
|
-
|
|
547
|
-
\`\`\`bash
|
|
548
|
-
# Check rollout history
|
|
549
|
-
kubectl rollout history deployment/my-app
|
|
550
|
-
|
|
551
|
-
# Undo last rollout
|
|
552
|
-
kubectl rollout undo deployment/my-app
|
|
553
|
-
|
|
554
|
-
# Roll back to a specific revision
|
|
555
|
-
kubectl rollout undo deployment/my-app --to-revision=2
|
|
556
|
-
|
|
557
|
-
# Watch rollout progress
|
|
558
|
-
kubectl rollout status deployment/my-app --timeout=300s
|
|
559
|
-
\`\`\`
|
|
560
|
-
|
|
561
531
|
### Deployment strategies
|
|
562
532
|
|
|
563
533
|
- **RollingUpdate** (default): Gradually replaces pods. Set \`maxSurge\` and \`maxUnavailable\`.
|
|
@@ -565,157 +535,42 @@ kubectl rollout status deployment/my-app --timeout=300s
|
|
|
565
535
|
- **Canary**: Deploy a second Deployment with 1 replica + same selector labels. Route percentage via Ingress annotations or service mesh.
|
|
566
536
|
- **Blue/Green**: Two full Deployments (blue/green), switch Service selector between them.
|
|
567
537
|
|
|
568
|
-
##
|
|
569
|
-
|
|
570
|
-
Composites are higher-level functions that produce multiple coordinated K8s resources from a single call. They return plain prop objects — not class instances
|
|
571
|
-
|
|
572
|
-
###
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
const { cronJob, serviceAccount, role, roleBinding } = CronWorkload({
|
|
606
|
-
name: "db-backup",
|
|
607
|
-
image: "postgres:16",
|
|
608
|
-
schedule: "0 2 * * *",
|
|
609
|
-
command: ["pg_dump", "-h", "postgres", "mydb"],
|
|
610
|
-
rbacRules: [{ apiGroups: [""], resources: ["secrets"], verbs: ["get"] }],
|
|
611
|
-
});
|
|
612
|
-
\`\`\`
|
|
613
|
-
|
|
614
|
-
### AutoscaledService — Deployment + Service + HPA + PDB
|
|
615
|
-
|
|
616
|
-
Production HTTP service with autoscaling, health probes, and optional topology spreading.
|
|
617
|
-
|
|
618
|
-
\`\`\`typescript
|
|
619
|
-
import { AutoscaledService } from "@intentius/chant-lexicon-k8s";
|
|
620
|
-
|
|
621
|
-
const { deployment, service, hpa, pdb } = AutoscaledService({
|
|
622
|
-
name: "api",
|
|
623
|
-
image: "api:2.0",
|
|
624
|
-
port: 8080,
|
|
625
|
-
maxReplicas: 10,
|
|
626
|
-
minReplicas: 3,
|
|
627
|
-
cpuRequest: "200m",
|
|
628
|
-
memoryRequest: "256Mi",
|
|
629
|
-
cpuLimit: "1",
|
|
630
|
-
memoryLimit: "1Gi",
|
|
631
|
-
// Probe paths — defaults: /healthz and /readyz
|
|
632
|
-
livenessPath: "/healthz",
|
|
633
|
-
readinessPath: "/readyz",
|
|
634
|
-
// Zone-aware topology spreading (default: false)
|
|
635
|
-
topologySpread: true,
|
|
636
|
-
// Custom: topologySpread: { maxSkew: 2, topologyKey: "kubernetes.io/hostname" }
|
|
637
|
-
});
|
|
638
|
-
\`\`\`
|
|
639
|
-
|
|
640
|
-
Key features:
|
|
641
|
-
- **Probe paths**: \`livenessPath\` (default \`/healthz\`) and \`readinessPath\` (default \`/readyz\`) — override for apps that don't serve those routes
|
|
642
|
-
- **Topology spread**: \`topologySpread: true\` adds zone-aware spreading (maxSkew=1, DoNotSchedule); pass an object for custom key/skew
|
|
643
|
-
- **PDB minAvailable**: accepts number or string percentage (e.g., \`"50%"\`)
|
|
644
|
-
|
|
645
|
-
### WorkerPool — Deployment + RBAC + optional ConfigMap + optional HPA
|
|
646
|
-
|
|
647
|
-
Background queue workers with optional RBAC and autoscaling.
|
|
648
|
-
|
|
649
|
-
\`\`\`typescript
|
|
650
|
-
import { WorkerPool } from "@intentius/chant-lexicon-k8s";
|
|
651
|
-
|
|
652
|
-
const { deployment, serviceAccount, role, roleBinding, configMap, hpa } = WorkerPool({
|
|
653
|
-
name: "email-worker",
|
|
654
|
-
image: "worker:1.0",
|
|
655
|
-
command: ["bundle", "exec", "sidekiq"],
|
|
656
|
-
config: { REDIS_URL: "redis://redis:6379", QUEUE: "emails" },
|
|
657
|
-
autoscaling: { minReplicas: 2, maxReplicas: 20, targetCPUPercent: 60 },
|
|
658
|
-
});
|
|
659
|
-
\`\`\`
|
|
660
|
-
|
|
661
|
-
Key features:
|
|
662
|
-
- **RBAC opt-out**: Pass \`rbacRules: []\` to skip ServiceAccount/Role/RoleBinding creation entirely. Omitting \`rbacRules\` (undefined) creates default rules for secrets/configmaps.
|
|
663
|
-
- \`serviceAccount\`, \`role\`, \`roleBinding\` are optional in the result — check before use
|
|
664
|
-
|
|
665
|
-
### NamespaceEnv — Namespace + ResourceQuota + LimitRange + NetworkPolicy
|
|
666
|
-
|
|
667
|
-
Multi-tenant namespace provisioning with resource guardrails and network isolation.
|
|
668
|
-
|
|
669
|
-
\`\`\`typescript
|
|
670
|
-
import { NamespaceEnv } from "@intentius/chant-lexicon-k8s";
|
|
671
|
-
|
|
672
|
-
const { namespace, resourceQuota, limitRange, networkPolicy } = NamespaceEnv({
|
|
673
|
-
name: "team-alpha",
|
|
674
|
-
cpuQuota: "8",
|
|
675
|
-
memoryQuota: "16Gi",
|
|
676
|
-
maxPods: 50,
|
|
677
|
-
defaultCpuRequest: "100m",
|
|
678
|
-
defaultMemoryRequest: "128Mi",
|
|
679
|
-
defaultCpuLimit: "500m",
|
|
680
|
-
defaultMemoryLimit: "512Mi",
|
|
681
|
-
defaultDenyIngress: true,
|
|
682
|
-
defaultDenyEgress: true,
|
|
683
|
-
});
|
|
684
|
-
\`\`\`
|
|
685
|
-
|
|
686
|
-
Key features:
|
|
687
|
-
- **Quota-without-limits warning**: Setting ResourceQuota without LimitRange defaults emits a warning — pods without explicit resource requests will fail to schedule
|
|
688
|
-
- **Network policies**: \`defaultDenyIngress\` (default true), \`defaultDenyEgress\` (default false) — can be combined or used individually
|
|
689
|
-
|
|
690
|
-
### NodeAgent — DaemonSet + ServiceAccount + ClusterRole + ClusterRoleBinding + optional ConfigMap
|
|
691
|
-
|
|
692
|
-
Per-node agents (log collectors, security scanners, monitoring exporters).
|
|
693
|
-
|
|
694
|
-
\`\`\`typescript
|
|
695
|
-
import { NodeAgent } from "@intentius/chant-lexicon-k8s";
|
|
696
|
-
|
|
697
|
-
const { daemonSet, serviceAccount, clusterRole, clusterRoleBinding, configMap } = NodeAgent({
|
|
698
|
-
name: "log-collector",
|
|
699
|
-
image: "fluentd:v1.16",
|
|
700
|
-
port: 24224,
|
|
701
|
-
hostPaths: [
|
|
702
|
-
{ name: "varlog", hostPath: "/var/log", mountPath: "/var/log" },
|
|
703
|
-
],
|
|
704
|
-
config: { "fluent.conf": "..." },
|
|
705
|
-
rbacRules: [{ apiGroups: [""], resources: ["pods", "namespaces"], verbs: ["get", "list", "watch"] }],
|
|
706
|
-
cpuRequest: "50m", // default: 50m
|
|
707
|
-
memoryRequest: "64Mi", // default: 64Mi
|
|
708
|
-
cpuLimit: "200m", // default: 200m
|
|
709
|
-
memoryLimit: "128Mi", // default: 128Mi
|
|
710
|
-
namespace: "monitoring",
|
|
711
|
-
});
|
|
712
|
-
\`\`\`
|
|
713
|
-
|
|
714
|
-
Key features:
|
|
715
|
-
- **Container resources**: Always set with sensible defaults (50m/64Mi requests, 200m/128Mi limits) — override per-agent
|
|
716
|
-
- **Host paths**: Mounted read-only by default; set \`readOnly: false\` to enable writes
|
|
717
|
-
- **Tolerations**: \`tolerateAllTaints: true\` (default) ensures agent runs on every node
|
|
718
|
-
- Uses **ClusterRole/ClusterRoleBinding** (cluster-scoped) for node-level access
|
|
538
|
+
## Choosing the Right Composite
|
|
539
|
+
|
|
540
|
+
Composites are higher-level functions that produce multiple coordinated K8s resources from a single call. They return plain prop objects — not class instances.
|
|
541
|
+
|
|
542
|
+
### Decision Tree
|
|
543
|
+
|
|
544
|
+
| Need | Composite | Resources |
|
|
545
|
+
|------|-----------|-----------|
|
|
546
|
+
| Stateless web app | **WebApp** | Deployment + Service + optional Ingress + optional PDB |
|
|
547
|
+
| Stateful database/cache | **StatefulApp** | StatefulSet + headless Service + PVC + optional PDB |
|
|
548
|
+
| Production HTTP service with autoscaling | **AutoscaledService** | Deployment + Service + HPA + PDB |
|
|
549
|
+
| Background queue workers | **WorkerPool** | Deployment + RBAC + optional ConfigMap + optional HPA + optional PDB |
|
|
550
|
+
| Scheduled jobs | **CronWorkload** | CronJob + RBAC |
|
|
551
|
+
| One-shot batch jobs | **BatchJob** | Job + optional RBAC |
|
|
552
|
+
| App with ConfigMap/Secret mounts | **ConfiguredApp** | Deployment + Service + optional ConfigMap |
|
|
553
|
+
| Multi-container sidecar patterns | **SidecarApp** | Deployment + Service |
|
|
554
|
+
| App with Prometheus monitoring | **MonitoredService** | Deployment + Service + ServiceMonitor + optional PrometheusRule |
|
|
555
|
+
| App with fine-grained network policies | **NetworkIsolatedApp** | Deployment + Service + NetworkPolicy |
|
|
556
|
+
| Namespace with quotas and isolation | **NamespaceEnv** | Namespace + ResourceQuota + LimitRange + NetworkPolicy |
|
|
557
|
+
| Per-node agent (custom) | **NodeAgent** | DaemonSet + RBAC + optional ConfigMap |
|
|
558
|
+
| Multi-host TLS Ingress (cert-manager) | **SecureIngress** | Ingress + optional Certificate |
|
|
559
|
+
| EKS IRSA ServiceAccount | **IrsaServiceAccount** | ServiceAccount + optional RBAC |
|
|
560
|
+
| AWS ALB Ingress | **AlbIngress** | Ingress with ALB annotations |
|
|
561
|
+
| EBS StorageClass | **EbsStorageClass** | StorageClass (ebs.csi.aws.com) |
|
|
562
|
+
| EFS StorageClass | **EfsStorageClass** | StorageClass (efs.csi.aws.com) |
|
|
563
|
+
| Fluent Bit for CloudWatch | **FluentBitAgent** | DaemonSet + RBAC + ConfigMap |
|
|
564
|
+
| ExternalDNS for Route53 | **ExternalDnsAgent** | Deployment + IRSA SA + ClusterRole |
|
|
565
|
+
| ADOT for CloudWatch/X-Ray | **AdotCollector** | DaemonSet + RBAC + ConfigMap |
|
|
566
|
+
|
|
567
|
+
### Hardening options (available on Deployment-based composites)
|
|
568
|
+
|
|
569
|
+
- \`minAvailable\` — creates a PodDisruptionBudget (WebApp, StatefulApp, WorkerPool; AutoscaledService always has one)
|
|
570
|
+
- \`initContainers\` — run before main containers (WebApp, StatefulApp, AutoscaledService, ConfiguredApp, SidecarApp)
|
|
571
|
+
- \`securityContext\` — container security settings (WebApp, StatefulApp, AutoscaledService, WorkerPool)
|
|
572
|
+
- \`terminationGracePeriodSeconds\` — graceful shutdown (WebApp, StatefulApp, AutoscaledService, WorkerPool)
|
|
573
|
+
- \`priorityClassName\` — pod scheduling priority (WebApp, StatefulApp, AutoscaledService, WorkerPool)
|
|
719
574
|
|
|
720
575
|
### Common patterns across all composites
|
|
721
576
|
|
|
@@ -724,49 +579,6 @@ Key features:
|
|
|
724
579
|
- Pass \`namespace: "prod"\` to set namespace on all namespaced resources
|
|
725
580
|
- Pass \`env: [{ name: "KEY", value: "val" }]\` for container environment variables
|
|
726
581
|
|
|
727
|
-
## Namespace management
|
|
728
|
-
|
|
729
|
-
Use the **NamespaceEnv** composite (above) to manage namespaces declaratively. For manual kubectl management:
|
|
730
|
-
|
|
731
|
-
\`\`\`bash
|
|
732
|
-
# Create namespace
|
|
733
|
-
kubectl create namespace my-project
|
|
734
|
-
|
|
735
|
-
# Set default resource quotas
|
|
736
|
-
kubectl apply -f - <<EOF
|
|
737
|
-
apiVersion: v1
|
|
738
|
-
kind: ResourceQuota
|
|
739
|
-
metadata:
|
|
740
|
-
name: default-quota
|
|
741
|
-
namespace: my-project
|
|
742
|
-
spec:
|
|
743
|
-
hard:
|
|
744
|
-
requests.cpu: "4"
|
|
745
|
-
requests.memory: 8Gi
|
|
746
|
-
limits.cpu: "8"
|
|
747
|
-
limits.memory: 16Gi
|
|
748
|
-
pods: "20"
|
|
749
|
-
EOF
|
|
750
|
-
|
|
751
|
-
# Set default container limits via LimitRange
|
|
752
|
-
kubectl apply -f - <<EOF
|
|
753
|
-
apiVersion: v1
|
|
754
|
-
kind: LimitRange
|
|
755
|
-
metadata:
|
|
756
|
-
name: default-limits
|
|
757
|
-
namespace: my-project
|
|
758
|
-
spec:
|
|
759
|
-
limits:
|
|
760
|
-
- default:
|
|
761
|
-
cpu: 500m
|
|
762
|
-
memory: 256Mi
|
|
763
|
-
defaultRequest:
|
|
764
|
-
cpu: 100m
|
|
765
|
-
memory: 128Mi
|
|
766
|
-
type: Container
|
|
767
|
-
EOF
|
|
768
|
-
\`\`\`
|
|
769
|
-
|
|
770
582
|
## Troubleshooting reference table
|
|
771
583
|
|
|
772
584
|
| Symptom | Likely cause | Resolution |
|
|
@@ -775,11 +587,8 @@ EOF
|
|
|
775
587
|
| Pod stuck in Pending | PVC not bound | Check StorageClass exists, PV available |
|
|
776
588
|
| Pod stuck in Pending | Node selector/affinity mismatch | Verify node labels match selectors |
|
|
777
589
|
| Pod stuck in ContainerCreating | ConfigMap/Secret not found | Ensure referenced ConfigMaps/Secrets exist |
|
|
778
|
-
| Pod stuck in ContainerCreating | Volume mount failure | Check PVC status, CSI driver health |
|
|
779
590
|
| Service returns 503 | No ready endpoints | Check pod readiness probes, selector match |
|
|
780
|
-
| Service returns 503 | Wrong port configuration | Verify targetPort matches containerPort |
|
|
781
591
|
| Ingress returns 404 | Backend service not found | Check Ingress rules, service name/port |
|
|
782
|
-
| Ingress returns 404 | Wrong path matching | Check pathType (Prefix vs Exact) |
|
|
783
592
|
| HPA not scaling | Metrics server not installed | Install metrics-server |
|
|
784
593
|
| HPA not scaling | Resource requests not set | Add CPU/memory requests to containers |
|
|
785
594
|
| CronJob not running | Invalid cron expression | Validate cron syntax (5-field format) |
|
|
@@ -892,20 +701,522 @@ const { deployment, service, hpa, pdb } = AutoscaledService({
|
|
|
892
701
|
});`,
|
|
893
702
|
},
|
|
894
703
|
{
|
|
895
|
-
title: "
|
|
896
|
-
description: "
|
|
897
|
-
input: "
|
|
898
|
-
output: `import {
|
|
899
|
-
|
|
900
|
-
const {
|
|
901
|
-
name: "
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
704
|
+
title: "BatchJob composite",
|
|
705
|
+
description: "One-shot batch job with RBAC",
|
|
706
|
+
input: "Run a database migration job",
|
|
707
|
+
output: `import { BatchJob } from "@intentius/chant-lexicon-k8s";
|
|
708
|
+
|
|
709
|
+
const { job, serviceAccount, role, roleBinding } = BatchJob({
|
|
710
|
+
name: "db-migrate",
|
|
711
|
+
image: "api:1.0",
|
|
712
|
+
command: ["python", "manage.py", "migrate"],
|
|
713
|
+
backoffLimit: 3,
|
|
714
|
+
ttlSecondsAfterFinished: 3600,
|
|
715
|
+
});`,
|
|
716
|
+
},
|
|
717
|
+
],
|
|
718
|
+
},
|
|
719
|
+
{
|
|
720
|
+
name: "chant-k8s-eks",
|
|
721
|
+
description: "EKS-specific Kubernetes composites — IRSA, ALB, EBS/EFS, Fluent Bit, ExternalDNS, ADOT",
|
|
722
|
+
content: `---
|
|
723
|
+
skill: chant-k8s-eks
|
|
724
|
+
description: EKS-specific Kubernetes patterns and composites
|
|
725
|
+
user-invocable: true
|
|
726
|
+
---
|
|
727
|
+
|
|
728
|
+
# EKS Kubernetes Patterns
|
|
729
|
+
|
|
730
|
+
## EKS Composites Overview
|
|
731
|
+
|
|
732
|
+
These composites produce K8s YAML with EKS-specific annotations and configurations.
|
|
733
|
+
|
|
734
|
+
### IrsaServiceAccount — ServiceAccount with IAM Role annotation
|
|
735
|
+
|
|
736
|
+
\`\`\`typescript
|
|
737
|
+
import { IrsaServiceAccount } from "@intentius/chant-lexicon-k8s";
|
|
738
|
+
|
|
739
|
+
const { serviceAccount, role, roleBinding } = IrsaServiceAccount({
|
|
740
|
+
name: "app-sa",
|
|
741
|
+
iamRoleArn: "arn:aws:iam::123456789012:role/my-app-role",
|
|
742
|
+
rbacRules: [
|
|
743
|
+
{ apiGroups: [""], resources: ["secrets"], verbs: ["get"] },
|
|
744
|
+
],
|
|
745
|
+
namespace: "prod",
|
|
746
|
+
});
|
|
747
|
+
\`\`\`
|
|
748
|
+
|
|
749
|
+
### AlbIngress — Ingress with AWS ALB Controller annotations
|
|
750
|
+
|
|
751
|
+
\`\`\`typescript
|
|
752
|
+
import { AlbIngress } from "@intentius/chant-lexicon-k8s";
|
|
753
|
+
|
|
754
|
+
const { ingress } = AlbIngress({
|
|
755
|
+
name: "api-ingress",
|
|
756
|
+
hosts: [
|
|
757
|
+
{
|
|
758
|
+
hostname: "api.example.com",
|
|
759
|
+
paths: [{ path: "/", serviceName: "api", servicePort: 80 }],
|
|
760
|
+
},
|
|
761
|
+
],
|
|
762
|
+
scheme: "internet-facing",
|
|
763
|
+
certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/abc-123",
|
|
764
|
+
groupName: "shared-alb",
|
|
765
|
+
healthCheckPath: "/healthz",
|
|
766
|
+
});
|
|
767
|
+
\`\`\`
|
|
768
|
+
|
|
769
|
+
Features:
|
|
770
|
+
- Auto-sets \`alb.ingress.kubernetes.io/*\` annotations
|
|
771
|
+
- SSL redirect enabled by default when \`certificateArn\` set
|
|
772
|
+
- \`groupName\` for shared ALB across multiple Ingresses
|
|
773
|
+
- \`wafAclArn\` for WAFv2 integration
|
|
774
|
+
|
|
775
|
+
### EbsStorageClass — StorageClass for EBS CSI
|
|
776
|
+
|
|
777
|
+
\`\`\`typescript
|
|
778
|
+
import { EbsStorageClass } from "@intentius/chant-lexicon-k8s";
|
|
779
|
+
|
|
780
|
+
const { storageClass } = EbsStorageClass({
|
|
781
|
+
name: "gp3-encrypted",
|
|
782
|
+
type: "gp3",
|
|
783
|
+
encrypted: true,
|
|
784
|
+
iops: "3000",
|
|
785
|
+
throughput: "125",
|
|
786
|
+
});
|
|
787
|
+
\`\`\`
|
|
788
|
+
|
|
789
|
+
### EfsStorageClass — StorageClass for EFS CSI (ReadWriteMany)
|
|
790
|
+
|
|
791
|
+
\`\`\`typescript
|
|
792
|
+
import { EfsStorageClass } from "@intentius/chant-lexicon-k8s";
|
|
793
|
+
|
|
794
|
+
const { storageClass } = EfsStorageClass({
|
|
795
|
+
name: "efs-shared",
|
|
796
|
+
fileSystemId: "fs-12345678",
|
|
797
|
+
});
|
|
798
|
+
\`\`\`
|
|
799
|
+
|
|
800
|
+
Use EFS when you need ReadWriteMany (shared across pods/nodes). Use EBS for ReadWriteOnce (single pod).
|
|
801
|
+
|
|
802
|
+
### FluentBitAgent — DaemonSet for CloudWatch logging
|
|
803
|
+
|
|
804
|
+
\`\`\`typescript
|
|
805
|
+
import { FluentBitAgent } from "@intentius/chant-lexicon-k8s";
|
|
806
|
+
|
|
807
|
+
const result = FluentBitAgent({
|
|
808
|
+
logGroup: "/aws/eks/my-cluster/containers",
|
|
809
|
+
region: "us-east-1",
|
|
810
|
+
clusterName: "my-cluster",
|
|
811
|
+
});
|
|
812
|
+
\`\`\`
|
|
813
|
+
|
|
814
|
+
### ExternalDnsAgent — ExternalDNS for Route53
|
|
815
|
+
|
|
816
|
+
\`\`\`typescript
|
|
817
|
+
import { ExternalDnsAgent } from "@intentius/chant-lexicon-k8s";
|
|
818
|
+
|
|
819
|
+
const result = ExternalDnsAgent({
|
|
820
|
+
iamRoleArn: "arn:aws:iam::123456789012:role/external-dns-role",
|
|
821
|
+
domainFilters: ["example.com"],
|
|
822
|
+
txtOwnerId: "my-cluster",
|
|
823
|
+
});
|
|
824
|
+
\`\`\`
|
|
825
|
+
|
|
826
|
+
### AdotCollector — ADOT for CloudWatch/X-Ray
|
|
827
|
+
|
|
828
|
+
\`\`\`typescript
|
|
829
|
+
import { AdotCollector } from "@intentius/chant-lexicon-k8s";
|
|
830
|
+
|
|
831
|
+
const result = AdotCollector({
|
|
832
|
+
region: "us-east-1",
|
|
833
|
+
clusterName: "my-cluster",
|
|
834
|
+
exporters: ["cloudwatch", "xray"],
|
|
835
|
+
});
|
|
836
|
+
\`\`\`
|
|
837
|
+
|
|
838
|
+
## Pod Identity vs IRSA
|
|
839
|
+
|
|
840
|
+
| Feature | IRSA | Pod Identity |
|
|
841
|
+
|---------|------|-------------|
|
|
842
|
+
| K8s annotation needed | Yes (\`eks.amazonaws.com/role-arn\`) | No |
|
|
843
|
+
| Composite available | **IrsaServiceAccount** | None needed |
|
|
844
|
+
| Setup | OIDC provider + IAM role trust policy | EKS Pod Identity Agent add-on + association |
|
|
845
|
+
| When to use | Existing clusters, broad compatibility | New clusters (EKS 1.28+), simpler management |
|
|
846
|
+
|
|
847
|
+
For Pod Identity, no K8s-side composite is needed — configure the association via AWS API/CloudFormation and use a plain ServiceAccount.
|
|
848
|
+
|
|
849
|
+
## Karpenter
|
|
850
|
+
|
|
851
|
+
Karpenter replaces Cluster Autoscaler for node provisioning. Karpenter NodePool and EC2NodeClass are simple CRDs — use CRD import rather than composites:
|
|
852
|
+
|
|
853
|
+
\`\`\`bash
|
|
854
|
+
# Import Karpenter CRDs into your chant project
|
|
855
|
+
chant import --url https://raw.githubusercontent.com/aws/karpenter/main/pkg/apis/crds/karpenter.sh_nodepools.yaml
|
|
856
|
+
\`\`\`
|
|
857
|
+
|
|
858
|
+
## Fargate Considerations
|
|
859
|
+
|
|
860
|
+
When running on EKS Fargate:
|
|
861
|
+
- **No DaemonSets** — FluentBitAgent and AdotCollector cannot run on Fargate nodes
|
|
862
|
+
- **No hostPath volumes** — use EFS for shared storage
|
|
863
|
+
- **No privileged containers** — security context restrictions apply
|
|
864
|
+
- For Fargate logging, use the built-in Fluent Bit log router (Fargate logging configuration)
|
|
865
|
+
|
|
866
|
+
## EKS Add-ons
|
|
867
|
+
|
|
868
|
+
Common add-ons managed via AWS (not K8s manifests):
|
|
869
|
+
- **vpc-cni** — Amazon VPC CNI plugin
|
|
870
|
+
- **coredns** — Cluster DNS
|
|
871
|
+
- **kube-proxy** — Network proxy
|
|
872
|
+
- **aws-ebs-csi-driver** — EBS CSI driver (required for EbsStorageClass)
|
|
873
|
+
- **aws-efs-csi-driver** — EFS CSI driver (required for EfsStorageClass)
|
|
874
|
+
- **adot** — AWS Distro for OpenTelemetry (alternative to AdotCollector composite)
|
|
875
|
+
- **aws-guardduty-agent** — Runtime threat detection
|
|
876
|
+
|
|
877
|
+
Configure add-ons via the AWS lexicon (\`@intentius/chant-lexicon-aws\`) CloudFormation resources.
|
|
878
|
+
`,
|
|
879
|
+
triggers: [
|
|
880
|
+
{ type: "context", value: "eks" },
|
|
881
|
+
{ type: "context", value: "irsa" },
|
|
882
|
+
{ type: "context", value: "alb" },
|
|
883
|
+
{ type: "context", value: "ebs" },
|
|
884
|
+
{ type: "context", value: "efs" },
|
|
885
|
+
{ type: "context", value: "fluent-bit" },
|
|
886
|
+
{ type: "context", value: "cloudwatch" },
|
|
887
|
+
{ type: "context", value: "karpenter" },
|
|
888
|
+
{ type: "context", value: "fargate" },
|
|
889
|
+
],
|
|
890
|
+
preConditions: [
|
|
891
|
+
"chant CLI is installed (chant --version succeeds)",
|
|
892
|
+
"EKS cluster is provisioned",
|
|
893
|
+
"kubectl is configured for the EKS cluster",
|
|
894
|
+
],
|
|
895
|
+
postConditions: [
|
|
896
|
+
"EKS-specific resources are deployed and functional",
|
|
897
|
+
],
|
|
898
|
+
parameters: [],
|
|
899
|
+
examples: [
|
|
900
|
+
{
|
|
901
|
+
title: "IRSA ServiceAccount",
|
|
902
|
+
description: "Create a ServiceAccount with IAM role for S3 access",
|
|
903
|
+
input: "Create an IRSA ServiceAccount for my app that needs S3 access",
|
|
904
|
+
output: `import { IrsaServiceAccount } from "@intentius/chant-lexicon-k8s";
|
|
905
|
+
|
|
906
|
+
const { serviceAccount } = IrsaServiceAccount({
|
|
907
|
+
name: "app-sa",
|
|
908
|
+
iamRoleArn: "arn:aws:iam::123456789012:role/app-s3-role",
|
|
909
|
+
namespace: "prod",
|
|
910
|
+
});`,
|
|
911
|
+
},
|
|
912
|
+
{
|
|
913
|
+
title: "ALB Ingress with TLS",
|
|
914
|
+
description: "Create an ALB Ingress with ACM certificate",
|
|
915
|
+
input: "Set up an internet-facing ALB with TLS for my API",
|
|
916
|
+
output: `import { AlbIngress } from "@intentius/chant-lexicon-k8s";
|
|
917
|
+
|
|
918
|
+
const { ingress } = AlbIngress({
|
|
919
|
+
name: "api-ingress",
|
|
920
|
+
hosts: [{ hostname: "api.example.com", paths: [{ path: "/", serviceName: "api", servicePort: 80 }] }],
|
|
921
|
+
certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/abc-123",
|
|
922
|
+
});`,
|
|
923
|
+
},
|
|
924
|
+
],
|
|
925
|
+
},
|
|
926
|
+
{
|
|
927
|
+
name: "chant-k8s-patterns",
|
|
928
|
+
description: "Advanced K8s patterns — sidecars, observability, TLS, network isolation, config/secret mounting",
|
|
929
|
+
content: `---
|
|
930
|
+
skill: chant-k8s-patterns
|
|
931
|
+
description: Advanced Kubernetes deployment patterns and composites
|
|
932
|
+
user-invocable: true
|
|
933
|
+
---
|
|
934
|
+
|
|
935
|
+
# Advanced Kubernetes Patterns
|
|
936
|
+
|
|
937
|
+
## Sidecar Patterns
|
|
938
|
+
|
|
939
|
+
### SidecarApp — multi-container Deployment
|
|
940
|
+
|
|
941
|
+
\`\`\`typescript
|
|
942
|
+
import { SidecarApp } from "@intentius/chant-lexicon-k8s";
|
|
943
|
+
|
|
944
|
+
// Envoy sidecar proxy
|
|
945
|
+
const { deployment, service } = SidecarApp({
|
|
946
|
+
name: "api",
|
|
947
|
+
image: "api:1.0",
|
|
948
|
+
port: 8080,
|
|
949
|
+
sidecars: [
|
|
950
|
+
{
|
|
951
|
+
name: "envoy",
|
|
952
|
+
image: "envoyproxy/envoy:v1.28",
|
|
953
|
+
ports: [{ containerPort: 9901, name: "admin" }],
|
|
954
|
+
resources: { requests: { cpu: "100m", memory: "128Mi" }, limits: { cpu: "200m", memory: "256Mi" } },
|
|
955
|
+
},
|
|
956
|
+
],
|
|
957
|
+
initContainers: [
|
|
958
|
+
{ name: "migrate", image: "api:1.0", command: ["python", "manage.py", "migrate"] },
|
|
959
|
+
],
|
|
960
|
+
sharedVolumes: [{ name: "tmp", emptyDir: {} }],
|
|
961
|
+
});
|
|
962
|
+
\`\`\`
|
|
963
|
+
|
|
964
|
+
Common sidecar use cases:
|
|
965
|
+
- **Envoy proxy** — service mesh, mTLS, traffic management
|
|
966
|
+
- **Log forwarder** — Fluent Bit sidecar for app-specific log routing
|
|
967
|
+
- **Auth proxy** — OAuth2 Proxy for authentication
|
|
968
|
+
- **Config watcher** — reload config on ConfigMap changes
|
|
969
|
+
|
|
970
|
+
## Config and Secret Mounting
|
|
971
|
+
|
|
972
|
+
### ConfiguredApp — automatic volume wiring
|
|
973
|
+
|
|
974
|
+
\`\`\`typescript
|
|
975
|
+
import { ConfiguredApp } from "@intentius/chant-lexicon-k8s";
|
|
976
|
+
|
|
977
|
+
const { deployment, service, configMap } = ConfiguredApp({
|
|
978
|
+
name: "api",
|
|
979
|
+
image: "api:1.0",
|
|
980
|
+
port: 8080,
|
|
981
|
+
// Mount ConfigMap as volume
|
|
982
|
+
configData: { "app.conf": "key=value\\nother=setting" },
|
|
983
|
+
configMountPath: "/etc/api",
|
|
984
|
+
// Mount existing Secret as volume
|
|
985
|
+
secretName: "api-creds",
|
|
986
|
+
secretMountPath: "/secrets",
|
|
987
|
+
// Inject as environment variables
|
|
988
|
+
envFrom: { secretRef: "api-env-secret", configMapRef: "api-env-config" },
|
|
989
|
+
// Run migrations before the app starts
|
|
990
|
+
initContainers: [
|
|
991
|
+
{ name: "migrate", image: "api:1.0", command: ["./migrate.sh"] },
|
|
992
|
+
],
|
|
993
|
+
});
|
|
994
|
+
\`\`\`
|
|
995
|
+
|
|
996
|
+
### Volume patterns
|
|
997
|
+
|
|
998
|
+
| Pattern | Use Case | ConfiguredApp Props |
|
|
999
|
+
|---------|----------|---------------------|
|
|
1000
|
+
| ConfigMap as file | Config files, templates | \`configData\` + \`configMountPath\` |
|
|
1001
|
+
| Secret as file | TLS certs, credentials | \`secretName\` + \`secretMountPath\` |
|
|
1002
|
+
| ConfigMap as env | Simple key-value config | \`envFrom.configMapRef\` |
|
|
1003
|
+
| Secret as env | Database URLs, API keys | \`envFrom.secretRef\` |
|
|
1004
|
+
|
|
1005
|
+
## TLS / cert-manager
|
|
1006
|
+
|
|
1007
|
+
### SecureIngress — multi-host TLS with cert-manager
|
|
1008
|
+
|
|
1009
|
+
\`\`\`typescript
|
|
1010
|
+
import { SecureIngress } from "@intentius/chant-lexicon-k8s";
|
|
1011
|
+
|
|
1012
|
+
const { ingress, certificate } = SecureIngress({
|
|
1013
|
+
name: "app-ingress",
|
|
1014
|
+
hosts: [
|
|
1015
|
+
{
|
|
1016
|
+
hostname: "api.example.com",
|
|
1017
|
+
paths: [
|
|
1018
|
+
{ path: "/v1", serviceName: "api-v1", servicePort: 80 },
|
|
1019
|
+
{ path: "/v2", serviceName: "api-v2", servicePort: 80 },
|
|
1020
|
+
],
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
hostname: "admin.example.com",
|
|
1024
|
+
paths: [{ path: "/", serviceName: "admin", servicePort: 80 }],
|
|
1025
|
+
},
|
|
1026
|
+
],
|
|
1027
|
+
clusterIssuer: "letsencrypt-prod",
|
|
1028
|
+
ingressClassName: "nginx",
|
|
1029
|
+
});
|
|
1030
|
+
\`\`\`
|
|
1031
|
+
|
|
1032
|
+
Features:
|
|
1033
|
+
- Multiple hosts and paths per Ingress
|
|
1034
|
+
- Automatic cert-manager Certificate when \`clusterIssuer\` set
|
|
1035
|
+
- TLS secret auto-provisioned by cert-manager
|
|
1036
|
+
|
|
1037
|
+
### cert-manager setup (prerequisite)
|
|
1038
|
+
|
|
1039
|
+
\`\`\`bash
|
|
1040
|
+
# Install cert-manager
|
|
1041
|
+
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
|
|
1042
|
+
|
|
1043
|
+
# Create ClusterIssuer for Let's Encrypt
|
|
1044
|
+
kubectl apply -f - <<EOF
|
|
1045
|
+
apiVersion: cert-manager.io/v1
|
|
1046
|
+
kind: ClusterIssuer
|
|
1047
|
+
metadata:
|
|
1048
|
+
name: letsencrypt-prod
|
|
1049
|
+
spec:
|
|
1050
|
+
acme:
|
|
1051
|
+
server: https://acme-v02.api.letsencrypt.org/directory
|
|
1052
|
+
email: admin@example.com
|
|
1053
|
+
privateKeySecretRef:
|
|
1054
|
+
name: letsencrypt-prod-key
|
|
1055
|
+
solvers:
|
|
1056
|
+
- http01:
|
|
1057
|
+
ingress:
|
|
1058
|
+
class: nginx
|
|
1059
|
+
EOF
|
|
1060
|
+
\`\`\`
|
|
1061
|
+
|
|
1062
|
+
## Observability
|
|
1063
|
+
|
|
1064
|
+
### MonitoredService — Prometheus monitoring
|
|
1065
|
+
|
|
1066
|
+
\`\`\`typescript
|
|
1067
|
+
import { MonitoredService } from "@intentius/chant-lexicon-k8s";
|
|
1068
|
+
|
|
1069
|
+
const { deployment, service, serviceMonitor, prometheusRule } = MonitoredService({
|
|
1070
|
+
name: "api",
|
|
1071
|
+
image: "api:1.0",
|
|
1072
|
+
port: 8080,
|
|
1073
|
+
metricsPort: 9090,
|
|
1074
|
+
metricsPath: "/metrics",
|
|
1075
|
+
scrapeInterval: "15s",
|
|
1076
|
+
alertRules: [
|
|
1077
|
+
{
|
|
1078
|
+
name: "HighErrorRate",
|
|
1079
|
+
expr: 'rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05',
|
|
1080
|
+
for: "5m",
|
|
1081
|
+
severity: "critical",
|
|
1082
|
+
annotations: { summary: "High error rate on {{ $labels.instance }}" },
|
|
1083
|
+
},
|
|
1084
|
+
{
|
|
1085
|
+
name: "HighLatency",
|
|
1086
|
+
expr: 'histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 1',
|
|
1087
|
+
for: "10m",
|
|
1088
|
+
severity: "warning",
|
|
1089
|
+
},
|
|
1090
|
+
],
|
|
1091
|
+
});
|
|
1092
|
+
\`\`\`
|
|
1093
|
+
|
|
1094
|
+
### Prerequisites
|
|
1095
|
+
|
|
1096
|
+
- Prometheus Operator installed (for ServiceMonitor/PrometheusRule CRDs)
|
|
1097
|
+
- Prometheus configured to discover ServiceMonitors
|
|
1098
|
+
|
|
1099
|
+
## Network Isolation
|
|
1100
|
+
|
|
1101
|
+
### NetworkIsolatedApp — per-app firewall rules
|
|
1102
|
+
|
|
1103
|
+
\`\`\`typescript
|
|
1104
|
+
import { NetworkIsolatedApp } from "@intentius/chant-lexicon-k8s";
|
|
1105
|
+
|
|
1106
|
+
const { deployment, service, networkPolicy } = NetworkIsolatedApp({
|
|
1107
|
+
name: "api",
|
|
1108
|
+
image: "api:1.0",
|
|
1109
|
+
port: 8080,
|
|
1110
|
+
allowIngressFrom: [
|
|
1111
|
+
{ podSelector: { "app.kubernetes.io/name": "frontend" } },
|
|
1112
|
+
{ namespaceSelector: { "kubernetes.io/metadata.name": "monitoring" } },
|
|
1113
|
+
],
|
|
1114
|
+
allowEgressTo: [
|
|
1115
|
+
{ podSelector: { "app.kubernetes.io/name": "postgres" }, ports: [{ port: 5432 }] },
|
|
1116
|
+
{ podSelector: { "app.kubernetes.io/name": "redis" }, ports: [{ port: 6379 }] },
|
|
1117
|
+
],
|
|
1118
|
+
});
|
|
1119
|
+
\`\`\`
|
|
1120
|
+
|
|
1121
|
+
### Combining with NamespaceEnv
|
|
1122
|
+
|
|
1123
|
+
Use NamespaceEnv for namespace-level default-deny, then NetworkIsolatedApp for per-app allow rules:
|
|
1124
|
+
|
|
1125
|
+
\`\`\`typescript
|
|
1126
|
+
// Namespace: deny all by default
|
|
1127
|
+
const ns = NamespaceEnv({ name: "prod", defaultDenyIngress: true, defaultDenyEgress: true });
|
|
1128
|
+
|
|
1129
|
+
// App: allow specific traffic
|
|
1130
|
+
const app = NetworkIsolatedApp({
|
|
1131
|
+
name: "api",
|
|
1132
|
+
image: "api:1.0",
|
|
1133
|
+
namespace: "prod",
|
|
1134
|
+
allowIngressFrom: [{ podSelector: { "app.kubernetes.io/name": "gateway" } }],
|
|
1135
|
+
allowEgressTo: [{ podSelector: { "app.kubernetes.io/name": "db" }, ports: [{ port: 5432 }] }],
|
|
1136
|
+
});
|
|
1137
|
+
\`\`\`
|
|
1138
|
+
|
|
1139
|
+
## Blue/Green and Canary
|
|
1140
|
+
|
|
1141
|
+
These patterns use standard K8s resources — no special composite needed.
|
|
1142
|
+
|
|
1143
|
+
### Blue/Green
|
|
1144
|
+
|
|
1145
|
+
\`\`\`typescript
|
|
1146
|
+
// Two Deployments with different versions
|
|
1147
|
+
const blue = WebApp({ name: "app-blue", image: "app:1.0", labels: { version: "blue" } });
|
|
1148
|
+
const green = WebApp({ name: "app-green", image: "app:2.0", labels: { version: "green" } });
|
|
1149
|
+
|
|
1150
|
+
// Service points to active version — switch by changing selector
|
|
1151
|
+
// Active: blue → green (update the Service selector)
|
|
1152
|
+
\`\`\`
|
|
1153
|
+
|
|
1154
|
+
### Canary
|
|
1155
|
+
|
|
1156
|
+
\`\`\`typescript
|
|
1157
|
+
// Main deployment (90% traffic)
|
|
1158
|
+
const main = AutoscaledService({ name: "app", image: "app:1.0", minReplicas: 9, maxReplicas: 20, ... });
|
|
1159
|
+
|
|
1160
|
+
// Canary deployment (10% traffic) — same app label, fewer replicas
|
|
1161
|
+
const canary = WebApp({ name: "app-canary", image: "app:2.0", replicas: 1, labels: { track: "canary" } });
|
|
1162
|
+
// Both share the same Service selector ("app.kubernetes.io/name": "app") for traffic splitting
|
|
1163
|
+
\`\`\`
|
|
1164
|
+
|
|
1165
|
+
## Gateway API (future direction)
|
|
1166
|
+
|
|
1167
|
+
Gateway API is the successor to Ingress. Key differences:
|
|
1168
|
+
- **HTTPRoute** replaces Ingress rules
|
|
1169
|
+
- **Gateway** replaces IngressClass
|
|
1170
|
+
- Built-in traffic splitting, header matching, URL rewriting
|
|
1171
|
+
- Currently in beta — use Ingress/SecureIngress/AlbIngress for production today
|
|
1172
|
+
|
|
1173
|
+
When Gateway API reaches GA, new composites will be added. For now, use CRD import if you need Gateway API resources.
|
|
1174
|
+
`,
|
|
1175
|
+
triggers: [
|
|
1176
|
+
{ type: "context", value: "sidecar" },
|
|
1177
|
+
{ type: "context", value: "init-container" },
|
|
1178
|
+
{ type: "context", value: "prometheus" },
|
|
1179
|
+
{ type: "context", value: "cert-manager" },
|
|
1180
|
+
{ type: "context", value: "tls" },
|
|
1181
|
+
{ type: "context", value: "network-policy" },
|
|
1182
|
+
{ type: "context", value: "canary" },
|
|
1183
|
+
{ type: "context", value: "blue-green" },
|
|
1184
|
+
{ type: "context", value: "configmap-mount" },
|
|
1185
|
+
{ type: "context", value: "secret-mount" },
|
|
1186
|
+
],
|
|
1187
|
+
preConditions: [
|
|
1188
|
+
"chant CLI is installed (chant --version succeeds)",
|
|
1189
|
+
"kubectl is configured and can access the cluster",
|
|
1190
|
+
],
|
|
1191
|
+
postConditions: [
|
|
1192
|
+
"Pattern resources are deployed and functional",
|
|
1193
|
+
],
|
|
1194
|
+
parameters: [],
|
|
1195
|
+
examples: [
|
|
1196
|
+
{
|
|
1197
|
+
title: "Sidecar with envoy proxy",
|
|
1198
|
+
description: "Deploy an app with an Envoy sidecar",
|
|
1199
|
+
input: "Add an envoy sidecar proxy to my API",
|
|
1200
|
+
output: `import { SidecarApp } from "@intentius/chant-lexicon-k8s";
|
|
1201
|
+
|
|
1202
|
+
const { deployment, service } = SidecarApp({
|
|
1203
|
+
name: "api",
|
|
1204
|
+
image: "api:1.0",
|
|
1205
|
+
port: 8080,
|
|
1206
|
+
sidecars: [{ name: "envoy", image: "envoyproxy/envoy:v1.28", ports: [{ containerPort: 9901 }] }],
|
|
1207
|
+
});`,
|
|
1208
|
+
},
|
|
1209
|
+
{
|
|
1210
|
+
title: "Monitored service with alerts",
|
|
1211
|
+
description: "Deploy a service with Prometheus monitoring and alerting",
|
|
1212
|
+
input: "Set up monitoring for my API with error rate alerts",
|
|
1213
|
+
output: `import { MonitoredService } from "@intentius/chant-lexicon-k8s";
|
|
1214
|
+
|
|
1215
|
+
const { deployment, service, serviceMonitor, prometheusRule } = MonitoredService({
|
|
1216
|
+
name: "api",
|
|
1217
|
+
image: "api:1.0",
|
|
1218
|
+
metricsPort: 9090,
|
|
1219
|
+
alertRules: [{ name: "HighErrorRate", expr: 'rate(http_errors[5m]) > 0.1', severity: "critical" }],
|
|
909
1220
|
});`,
|
|
910
1221
|
},
|
|
911
1222
|
],
|