@intentius/chant-lexicon-k8s 0.124.31 → 0.124.33
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/actions/apps.js +18 -0
- package/dist/actions/batch.js +6 -0
- package/dist/actions/core.js +48 -0
- package/dist/actions/index.js +13 -0
- package/dist/actions/networking.js +11 -0
- package/dist/actions/rbac.js +8 -0
- package/dist/api/classify.js +123 -0
- package/dist/api/connect.js +62 -0
- package/dist/api/fake-cluster.js +175 -0
- package/dist/api/operation-surface.d.ts.map +1 -1
- package/dist/api/operation-surface.js +109 -0
- package/dist/api/owner-chain.js +100 -0
- package/dist/api/sweep-types.js +35 -0
- package/dist/behaviour-kinds.js +82 -0
- package/dist/codegen/docs-cli.js +2 -0
- package/dist/codegen/docs.js +146 -0
- package/dist/codegen/generate-cli.js +30 -0
- package/dist/codegen/generate-lexicon.js +74 -0
- package/dist/codegen/generate-list-map-keys.js +88 -0
- package/dist/codegen/generate-operations.js +53 -0
- package/dist/codegen/generate-typescript.js +124 -0
- package/dist/codegen/generate.js +173 -0
- package/dist/codegen/naming.js +174 -0
- package/dist/codegen/package.js +36 -0
- package/dist/codegen/patches.js +88 -0
- package/dist/codegen/typecheck.js +4 -0
- package/dist/codegen/versions.js +41 -0
- package/dist/components/argo-app.js +51 -0
- package/dist/components/builders.js +22 -0
- package/dist/components/capability-plugin.js +31 -0
- package/dist/components/flux-reconcile.js +61 -0
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +18 -0
- package/dist/components/kubectl-apply.d.ts +83 -1
- package/dist/components/kubectl-apply.d.ts.map +1 -1
- package/dist/components/kubectl-apply.js +274 -0
- package/dist/components/kustomize-apply.js +25 -0
- package/dist/composites/adot-collector.js +184 -0
- package/dist/composites/agic-ingress.js +85 -0
- package/dist/composites/aks-external-dns-agent.js +146 -0
- package/dist/composites/alb-ingress.js +86 -0
- package/dist/composites/argo-app.js +199 -0
- package/dist/composites/autoscaled-service.js +174 -0
- package/dist/composites/azure-disk-storage-class.js +47 -0
- package/dist/composites/azure-file-storage-class.js +48 -0
- package/dist/composites/azure-monitor-collector.js +176 -0
- package/dist/composites/batch-job.js +139 -0
- package/dist/composites/catalog.js +4110 -0
- package/dist/composites/cockroachdb-cluster.js +371 -0
- package/dist/composites/cockroachdb-region-stack.js +369 -0
- package/dist/composites/config-connector-context.js +40 -0
- package/dist/composites/configured-app.js +135 -0
- package/dist/composites/cron-schedule.js +38 -0
- package/dist/composites/cron-workload.js +109 -0
- package/dist/composites/ebs-storage-class.js +54 -0
- package/dist/composites/efs-storage-class.js +46 -0
- package/dist/composites/external-dns-agent.js +122 -0
- package/dist/composites/filestore-storage-class.js +49 -0
- package/dist/composites/fluent-bit-agent.js +157 -0
- package/dist/composites/flux-app.js +156 -0
- package/dist/composites/gce-ingress.js +83 -0
- package/dist/composites/gce-pd-storage-class.js +49 -0
- package/dist/composites/gke-external-dns-agent.js +129 -0
- package/dist/composites/gke-fluent-bit-agent.js +165 -0
- package/dist/composites/gke-gateway.js +91 -0
- package/dist/composites/gke-otel-collector.js +94 -0
- package/dist/composites/index.js +51 -0
- package/dist/composites/inference-service.js +76 -0
- package/dist/composites/irsa-service-account.js +77 -0
- package/dist/composites/member-defaults.js +14 -0
- package/dist/composites/metrics-server.js +181 -0
- package/dist/composites/model.js +92 -0
- package/dist/composites/monitored-service.js +152 -0
- package/dist/composites/namespace-env.js +114 -0
- package/dist/composites/network-isolated-app.js +124 -0
- package/dist/composites/node-agent.js +149 -0
- package/dist/composites/operator-stack.js +268 -0
- package/dist/composites/otel-collector-agent.js +142 -0
- package/dist/composites/otel-collector-gateway.js +216 -0
- package/dist/composites/otel-collector-node.js +176 -0
- package/dist/composites/otel-collector-rbac.js +115 -0
- package/dist/composites/otel-collector-shape.js +128 -0
- package/dist/composites/otel-collector.js +115 -0
- package/dist/composites/otel-operator-collector.js +123 -0
- package/dist/composites/ray-cluster.js +378 -0
- package/dist/composites/ray-job.js +136 -0
- package/dist/composites/ray-service.js +178 -0
- package/dist/composites/secure-ingress.js +100 -0
- package/dist/composites/security-context.js +1 -0
- package/dist/composites/sidecar-app.js +105 -0
- package/dist/composites/stateful-app.js +111 -0
- package/dist/composites/vllm-serving-runtime.js +114 -0
- package/dist/composites/web-app.js +157 -0
- package/dist/composites/worker-pool.js +167 -0
- package/dist/composites/workload-identity-sa.js +81 -0
- package/dist/composites/workload-identity-service-account.js +77 -0
- package/dist/config-schema.js +72 -0
- package/dist/config.js +59 -0
- package/dist/coverage.js +27 -0
- package/dist/crd/crd-sources.js +615 -0
- package/dist/crd/loader.js +181 -0
- package/dist/crd/oci-chart.js +144 -0
- package/dist/crd/parser.js +382 -0
- package/dist/crd/project-codegen.js +273 -0
- package/dist/crd/types.js +7 -0
- package/dist/deep-observe-hooks.js +306 -0
- package/dist/deep-observe.js +234 -0
- package/dist/default-labels.js +87 -0
- package/dist/describe-resources.js +699 -0
- package/dist/describe-stack-status.js +99 -0
- package/dist/detect.js +11 -0
- package/dist/effect-receipt-row.js +205 -0
- package/dist/export-resources.js +39 -0
- package/dist/generated/index.js +1092 -0
- package/dist/generated/runtime.js +4 -0
- package/dist/group-namespace.js +96 -0
- package/dist/import/embedded.js +197 -0
- package/dist/import/generator.js +288 -0
- package/dist/import/live-export.js +85 -0
- package/dist/import/parser.js +204 -0
- package/dist/import/testdata/embedded/fixtures.js +60 -0
- package/dist/include/entity.js +78 -0
- package/dist/include/resolve.js +170 -0
- package/dist/index.js +59 -0
- package/dist/integrity.json +3 -3
- package/dist/kube/apply.js +90 -0
- package/dist/kube/connect.js +46 -0
- package/dist/kube/delete.js +138 -0
- package/dist/kube/describe.js +169 -0
- package/dist/kube/events.js +132 -0
- package/dist/kube/flags.js +91 -0
- package/dist/kube/get.js +159 -0
- package/dist/kube/group.js +123 -0
- package/dist/kube/logs.js +82 -0
- package/dist/kube/project.js +94 -0
- package/dist/kube/render.js +227 -0
- package/dist/kube/source.js +122 -0
- package/dist/kube/target.js +63 -0
- package/dist/kube/testing.js +28 -0
- package/dist/kube/top.js +99 -0
- package/dist/kube/verdict.js +72 -0
- package/dist/kube/wait.js +129 -0
- package/dist/kustomize/render.js +73 -0
- package/dist/kustomize/rendered-entity.js +67 -0
- package/dist/kustomize/root.js +68 -0
- package/dist/lint/audit-catalog.js +61 -0
- package/dist/lint/audit-lineage.js +118 -0
- package/dist/lint/post-synth/argo-helpers.js +36 -0
- package/dist/lint/post-synth/argo002.js +31 -0
- package/dist/lint/post-synth/argo003.js +53 -0
- package/dist/lint/post-synth/argo005.js +54 -0
- package/dist/lint/post-synth/crd-schema-helpers.d.ts.map +1 -1
- package/dist/lint/post-synth/crd-schema-helpers.js +214 -0
- package/dist/lint/post-synth/flux002.js +56 -0
- package/dist/lint/post-synth/flux003.js +50 -0
- package/dist/lint/post-synth/index.js +104 -0
- package/dist/lint/post-synth/k8s-helpers.js +186 -0
- package/dist/lint/post-synth/monitoring-selection-helpers.js +163 -0
- package/dist/lint/post-synth/otel-placement-helpers.js +293 -0
- package/dist/lint/post-synth/sops-helpers.js +43 -0
- package/dist/lint/post-synth/wk8005.js +44 -0
- package/dist/lint/post-synth/wk8006.js +56 -0
- package/dist/lint/post-synth/wk8041.js +60 -0
- package/dist/lint/post-synth/wk8042.js +36 -0
- package/dist/lint/post-synth/wk8101.js +52 -0
- package/dist/lint/post-synth/wk8102.js +30 -0
- package/dist/lint/post-synth/wk8103.js +33 -0
- package/dist/lint/post-synth/wk8104.js +58 -0
- package/dist/lint/post-synth/wk8105.js +33 -0
- package/dist/lint/post-synth/wk8201.js +44 -0
- package/dist/lint/post-synth/wk8202.js +34 -0
- package/dist/lint/post-synth/wk8203.js +34 -0
- package/dist/lint/post-synth/wk8204.js +71 -0
- package/dist/lint/post-synth/wk8205.js +38 -0
- package/dist/lint/post-synth/wk8207.js +33 -0
- package/dist/lint/post-synth/wk8208.js +33 -0
- package/dist/lint/post-synth/wk8209.js +33 -0
- package/dist/lint/post-synth/wk8301.js +49 -0
- package/dist/lint/post-synth/wk8302.js +34 -0
- package/dist/lint/post-synth/wk8303.js +68 -0
- package/dist/lint/post-synth/wk8304.js +58 -0
- package/dist/lint/post-synth/wk8305.js +96 -0
- package/dist/lint/post-synth/wk8306.js +38 -0
- package/dist/lint/post-synth/wk8401.js +86 -0
- package/dist/lint/post-synth/wk8402.js +31 -0
- package/dist/lint/post-synth/wk8403.js +49 -0
- package/dist/lint/post-synth/wk8404.js +36 -0
- package/dist/lint/post-synth/wk8405.js +65 -0
- package/dist/lint/post-synth/wk8406.js +50 -0
- package/dist/lint/post-synth/wk8407.js +58 -0
- package/dist/lint/post-synth/wk8501.js +36 -0
- package/dist/lint/post-synth/wk8502.js +35 -0
- package/dist/lint/post-synth/wk8503.js +164 -0
- package/dist/lint/post-synth/wk8504.js +20 -0
- package/dist/lint/post-synth/wk8505.js +31 -0
- package/dist/lint/post-synth/wk8601.js +40 -0
- package/dist/lint/post-synth/wk8602.js +120 -0
- package/dist/lint/post-synth/wk8603.js +63 -0
- package/dist/lint/post-synth/wk8604.js +31 -0
- package/dist/lint/post-synth/wk8605.js +124 -0
- package/dist/lint/post-synth/wk8606.js +22 -0
- package/dist/lint/post-synth/wk8701.js +31 -0
- package/dist/lint/post-synth/wk8702.js +37 -0
- package/dist/lint/post-synth/wk8703.js +31 -0
- package/dist/lint/post-synth/wk8704.js +135 -0
- package/dist/lint/post-synth/wk8705.js +38 -0
- package/dist/lint/rules/argo-appset-single-project.js +56 -0
- package/dist/lint/rules/argo-ast.js +94 -0
- package/dist/lint/rules/argo-automated-prune.js +59 -0
- package/dist/lint/rules/flux-source-ref-pin.js +44 -0
- package/dist/lint/rules/hardcoded-namespace.js +57 -0
- package/dist/lint/rules/latest-image-tag.js +103 -0
- package/dist/lint/rules/missing-resource-limits.js +85 -0
- package/dist/lsp/completions.d.ts.map +1 -1
- package/dist/lsp/completions.js +18 -0
- package/dist/lsp/hover.d.ts.map +1 -1
- package/dist/lsp/hover.js +57 -0
- package/dist/manifest-entity.js +71 -0
- package/dist/manifest.json +1 -1
- package/dist/micro-time.js +49 -0
- package/dist/op/activities/apply-diff.d.ts +31 -0
- package/dist/op/activities/apply-diff.d.ts.map +1 -0
- package/dist/op/activities/apply-diff.js +79 -0
- package/dist/op/activities/argo.js +98 -0
- package/dist/op/activities/ensure-secret.js +38 -0
- package/dist/op/activities/index.js +51 -0
- package/dist/op/activities/kubectl.d.ts +64 -0
- package/dist/op/activities/kubectl.d.ts.map +1 -1
- package/dist/op/activities/kubectl.js +517 -0
- package/dist/op/activities/wait-for-ready.js +229 -0
- package/dist/op/builders.js +68 -0
- package/dist/package-cli.js +21 -0
- package/dist/patch/json-patch.js +187 -0
- package/dist/patch/rendered-patch.js +94 -0
- package/dist/plugin.js +741 -0
- package/dist/project-kinds.js +56 -0
- package/dist/receipt-store.js +216 -0
- package/dist/rules/crd-schema-helpers.ts +2 -1
- package/dist/secret-labels.js +33 -0
- package/dist/secret-store.js +116 -0
- package/dist/serializer.d.ts.map +1 -1
- package/dist/serializer.js +578 -0
- package/dist/sops/encrypted-secret-file.js +194 -0
- package/dist/sops/entity.js +32 -0
- package/dist/spec/fetch.js +58 -0
- package/dist/spec/parse.js +622 -0
- package/dist/subscribe-changes.js +168 -0
- package/dist/teardown.js +197 -0
- package/dist/telemetry-release.js +86 -0
- package/dist/validate-cli.js +17 -0
- package/dist/validate.js +47 -0
- package/dist/variables.js +34 -0
- package/dist/whoami.js +109 -0
- package/package.json +12 -12
- package/src/api/operation-surface.ts +2 -1
- package/src/codegen/package.ts +2 -2
- package/src/components/index.ts +3 -0
- package/src/components/kubectl-apply-plan.k3d.e2e.test.ts +127 -0
- package/src/components/kubectl-apply.test.ts +262 -0
- package/src/components/kubectl-apply.ts +341 -12
- package/src/deep-observe-hooks.ts +2 -2
- package/src/import/roundtrip-build.test.ts +46 -0
- package/src/lint/post-synth/crd-schema-helpers.ts +2 -1
- package/src/lsp/completions.ts +2 -1
- package/src/lsp/hover.ts +2 -1
- package/src/op/activities/apply-diff.ts +87 -0
- package/src/op/activities/kubectl-plan.test.ts +224 -0
- package/src/op/activities/kubectl.ts +204 -16
- package/src/serializer.ts +2 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GkeOtelCollector composite — DaemonSet + RBAC + ConfigMap for OpenTelemetry on GKE.
|
|
3
|
+
*
|
|
4
|
+
* @gke Like AdotCollector but targets Cloud Trace + Cloud Monitoring via the
|
|
5
|
+
* googlecloud exporter and uses GKE Workload Identity instead of IRSA.
|
|
6
|
+
*
|
|
7
|
+
* The collector config is typed through the otel lexicon
|
|
8
|
+
* (`@intentius/chant-lexicon-otel`) and rendered with its `collectorYaml`, so
|
|
9
|
+
* it is checked the way any declared collector config is.
|
|
10
|
+
*/
|
|
11
|
+
import { Composite } from "@intentius/chant";
|
|
12
|
+
import { OtlpReceiver, BatchProcessor, ResourceDetectionProcessor, GoogleCloudExporter, Pipeline, buildCollectorConfig, collectorYaml, } from "@intentius/chant-lexicon-otel";
|
|
13
|
+
import { collectorAgentResources } from "./otel-collector-agent.js";
|
|
14
|
+
import { agentClusterRules } from "./otel-collector-rbac.js";
|
|
15
|
+
import { collectorNodeAccess } from "./otel-collector-node.js";
|
|
16
|
+
/**
|
|
17
|
+
* Create a GkeOtelCollector composite — returns prop objects for
|
|
18
|
+
* a DaemonSet, ServiceAccount, ClusterRole, ClusterRoleBinding, and ConfigMap.
|
|
19
|
+
*
|
|
20
|
+
* @gke
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { GkeOtelCollector } from "@intentius/chant-lexicon-k8s";
|
|
24
|
+
*
|
|
25
|
+
* const { daemonSet, serviceAccount, clusterRole, clusterRoleBinding, configMap } = GkeOtelCollector({
|
|
26
|
+
* clusterName: "my-cluster",
|
|
27
|
+
* projectId: "my-project",
|
|
28
|
+
* gcpServiceAccountEmail: "otel@my-project.iam.gserviceaccount.com",
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export const GkeOtelCollector = Composite((props) => {
|
|
33
|
+
const { clusterName, projectId, gcpServiceAccountEmail, name = "gke-otel-collector", image = "otel/opentelemetry-collector-contrib:latest", namespace = "gke-monitoring", labels: extraLabels = {}, cpuRequest = "100m", memoryRequest = "256Mi", cpuLimit = "500m", memoryLimit = "512Mi", defaults: defs, } = props;
|
|
34
|
+
const commonLabels = {
|
|
35
|
+
"app.kubernetes.io/name": name,
|
|
36
|
+
"app.kubernetes.io/managed-by": "chant",
|
|
37
|
+
...extraLabels,
|
|
38
|
+
};
|
|
39
|
+
// The collector config, declared through the otel lexicon and rendered to
|
|
40
|
+
// the same YAML the ConfigMap has always carried (#2559).
|
|
41
|
+
const otlp = new OtlpReceiver({
|
|
42
|
+
protocols: {
|
|
43
|
+
grpc: { endpoint: "0.0.0.0:4317" },
|
|
44
|
+
http: { endpoint: "0.0.0.0:4318" },
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
const batch = new BatchProcessor({ timeout: "30s", send_batch_size: 8192 });
|
|
48
|
+
const resourceDetection = new ResourceDetectionProcessor({ detectors: ["gcp"], timeout: "10s" });
|
|
49
|
+
const googleCloud = new GoogleCloudExporter({
|
|
50
|
+
project: projectId,
|
|
51
|
+
metric: { prefix: `custom.googleapis.com/${clusterName}` },
|
|
52
|
+
trace: {
|
|
53
|
+
attribute_mappings: [{ key: "service.name", replacement: "g.co/r/service/name" }],
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
const entities = [
|
|
57
|
+
otlp,
|
|
58
|
+
batch,
|
|
59
|
+
resourceDetection,
|
|
60
|
+
googleCloud,
|
|
61
|
+
new Pipeline({ signal: "metrics", receivers: [otlp], processors: [batch, resourceDetection], exporters: [googleCloud] }),
|
|
62
|
+
new Pipeline({ signal: "traces", receivers: [otlp], processors: [batch, resourceDetection], exporters: [googleCloud] }),
|
|
63
|
+
];
|
|
64
|
+
const otelConfig = collectorYaml(entities);
|
|
65
|
+
const built = buildCollectorConfig(entities).config;
|
|
66
|
+
// The DaemonSet, RBAC and ConfigMap are the ones OtelCollector builds too.
|
|
67
|
+
return collectorAgentResources({
|
|
68
|
+
name,
|
|
69
|
+
namespace,
|
|
70
|
+
image,
|
|
71
|
+
commonLabels,
|
|
72
|
+
extraLabels,
|
|
73
|
+
configYaml: otelConfig,
|
|
74
|
+
configDir: "/etc/otel",
|
|
75
|
+
// The ClusterRole OtelCollector shares: k8sattributes' rules, and none
|
|
76
|
+
// for receivers, since the config's only receiver is otlp (#2923).
|
|
77
|
+
clusterRules: agentClusterRules(built),
|
|
78
|
+
// Derived like OtelCollector's (#3103). The config reads nothing from the
|
|
79
|
+
// node, so this adds no variable or mount and the output is unchanged.
|
|
80
|
+
nodeAccess: collectorNodeAccess(built, "/etc/otel"),
|
|
81
|
+
ports: [
|
|
82
|
+
{ containerPort: 4317, name: "otlp-grpc" },
|
|
83
|
+
{ containerPort: 4318, name: "otlp-http" },
|
|
84
|
+
],
|
|
85
|
+
cpuRequest,
|
|
86
|
+
memoryRequest,
|
|
87
|
+
cpuLimit,
|
|
88
|
+
memoryLimit,
|
|
89
|
+
...(gcpServiceAccountEmail
|
|
90
|
+
? { serviceAccountAnnotations: { "iam.gke.io/gcp-service-account": gcpServiceAccountEmail } }
|
|
91
|
+
: {}),
|
|
92
|
+
defaults: defs,
|
|
93
|
+
});
|
|
94
|
+
}, "GkeOtelCollector");
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export { WebApp } from "./web-app.js";
|
|
2
|
+
export { StatefulApp } from "./stateful-app.js";
|
|
3
|
+
export { CronWorkload } from "./cron-workload.js";
|
|
4
|
+
export { AutoscaledService } from "./autoscaled-service.js";
|
|
5
|
+
export { WorkerPool } from "./worker-pool.js";
|
|
6
|
+
export { NamespaceEnv } from "./namespace-env.js";
|
|
7
|
+
export { NodeAgent } from "./node-agent.js";
|
|
8
|
+
export { BatchJob } from "./batch-job.js";
|
|
9
|
+
export { SecureIngress } from "./secure-ingress.js";
|
|
10
|
+
export { ConfiguredApp } from "./configured-app.js";
|
|
11
|
+
export { SidecarApp } from "./sidecar-app.js";
|
|
12
|
+
export { MonitoredService } from "./monitored-service.js";
|
|
13
|
+
export { NetworkIsolatedApp } from "./network-isolated-app.js";
|
|
14
|
+
export { IrsaServiceAccount } from "./irsa-service-account.js";
|
|
15
|
+
export { AlbIngress } from "./alb-ingress.js";
|
|
16
|
+
export { EbsStorageClass } from "./ebs-storage-class.js";
|
|
17
|
+
export { EfsStorageClass } from "./efs-storage-class.js";
|
|
18
|
+
export { FluentBitAgent } from "./fluent-bit-agent.js";
|
|
19
|
+
export { ExternalDnsAgent } from "./external-dns-agent.js";
|
|
20
|
+
export { AdotCollector } from "./adot-collector.js";
|
|
21
|
+
export { MetricsServer } from "./metrics-server.js";
|
|
22
|
+
export { WorkloadIdentityServiceAccount } from "./workload-identity-service-account.js";
|
|
23
|
+
export { GcePdStorageClass } from "./gce-pd-storage-class.js";
|
|
24
|
+
export { FilestoreStorageClass } from "./filestore-storage-class.js";
|
|
25
|
+
export { GkeGateway } from "./gke-gateway.js";
|
|
26
|
+
export { ConfigConnectorContext } from "./config-connector-context.js";
|
|
27
|
+
export { GceIngress } from "./gce-ingress.js";
|
|
28
|
+
export { AgicIngress } from "./agic-ingress.js";
|
|
29
|
+
export { AzureDiskStorageClass } from "./azure-disk-storage-class.js";
|
|
30
|
+
export { AzureFileStorageClass } from "./azure-file-storage-class.js";
|
|
31
|
+
export { AzureMonitorCollector } from "./azure-monitor-collector.js";
|
|
32
|
+
export { WorkloadIdentityServiceAccount as AksWorkloadIdentityServiceAccount } from "./workload-identity-sa.js";
|
|
33
|
+
export { GkeFluentBitAgent } from "./gke-fluent-bit-agent.js";
|
|
34
|
+
export { OtelCollector } from "./otel-collector.js";
|
|
35
|
+
export { OtelOperatorCollector } from "./otel-operator-collector.js";
|
|
36
|
+
export { OtelCollectorGateway, gatewayExporter } from "./otel-collector-gateway.js";
|
|
37
|
+
export { OTEL_COLLECTOR_ANNOTATIONS } from "./otel-collector-shape.js";
|
|
38
|
+
export { GkeOtelCollector } from "./gke-otel-collector.js";
|
|
39
|
+
export { GkeExternalDnsAgent } from "./gke-external-dns-agent.js";
|
|
40
|
+
export { AksExternalDnsAgent } from "./aks-external-dns-agent.js";
|
|
41
|
+
export { CockroachDbCluster } from "./cockroachdb-cluster.js";
|
|
42
|
+
export { CockroachDbRegionStack } from "./cockroachdb-region-stack.js";
|
|
43
|
+
export { RayCluster } from "./ray-cluster.js";
|
|
44
|
+
export { RayJob } from "./ray-job.js";
|
|
45
|
+
export { RayService } from "./ray-service.js";
|
|
46
|
+
export { InferenceService } from "./inference-service.js";
|
|
47
|
+
export { ArgoAppFor, ArgoAppSetForRegions, registerArgoCluster } from "./argo-app.js";
|
|
48
|
+
export { FluxGitSource, FluxAppFor } from "./flux-app.js";
|
|
49
|
+
export { VllmServingRuntime } from "./vllm-serving-runtime.js";
|
|
50
|
+
export { Model, resolveModelStorageUri } from "./model.js";
|
|
51
|
+
export { OperatorStack, deriveHostVerbClass, DEFAULT_RESOURCE_RULES } from "./operator-stack.js";
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InferenceService composite — KServe `InferenceService` (v1beta1).
|
|
3
|
+
*
|
|
4
|
+
* Spec-true to KServe: the predictor references a `ServingRuntime` by name
|
|
5
|
+
* (the plug seam KServe itself defines — see #984's VllmServingRuntime) and
|
|
6
|
+
* a model `storageUri`, plus the real `ComponentExtensionSpec` autoscaling
|
|
7
|
+
* knobs (`minReplicas`/`maxReplicas`/`scaleTarget`/`scaleMetric`) and
|
|
8
|
+
* `canaryTrafficPercent`. No chant-flavored runtime abstraction is invented;
|
|
9
|
+
* `runtime` is just the `ServingRuntime`/`ClusterServingRuntime` name string
|
|
10
|
+
* KServe's own webhook resolves against `supportedModelFormats`.
|
|
11
|
+
*
|
|
12
|
+
* Coupling note (#984/#986 land in parallel in this same lexicon): this
|
|
13
|
+
* composite does not import either sibling. `runtime` is a plain name
|
|
14
|
+
* string (whatever `VllmServingRuntime` from #984 names its `ServingRuntime`
|
|
15
|
+
* object). `model` accepts either a raw `storageUri` string or a
|
|
16
|
+
* `{ storageUri }`-shaped object — the resolved-value shape `Model` from
|
|
17
|
+
* #986 is expected to return — matched structurally, not by import.
|
|
18
|
+
*/
|
|
19
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
20
|
+
import { InferenceService as InferenceServiceResource } from "../generated/index.js";
|
|
21
|
+
function resolveStorageUri(model) {
|
|
22
|
+
return typeof model === "string" ? model : model.storageUri;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create an InferenceService composite — a KServe `InferenceService`
|
|
26
|
+
* predictor referencing a `ServingRuntime` and a model `storageUri`, with
|
|
27
|
+
* autoscaling bounds and an optional canary traffic split.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* import { InferenceService } from "@intentius/chant-lexicon-k8s";
|
|
32
|
+
*
|
|
33
|
+
* const svc = InferenceService({
|
|
34
|
+
* name: "llama-3-8b",
|
|
35
|
+
* namespace: "serving",
|
|
36
|
+
* model: "gs://my-models/llama-3-8b/v1",
|
|
37
|
+
* runtime: "vllm-runtime",
|
|
38
|
+
* modelFormat: "vLLM",
|
|
39
|
+
* minReplicas: 1,
|
|
40
|
+
* maxReplicas: 4,
|
|
41
|
+
* scaleTarget: 8,
|
|
42
|
+
* scaleMetric: "concurrency",
|
|
43
|
+
* canaryTrafficPercent: 10,
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export const InferenceService = Composite((props) => {
|
|
48
|
+
const { name, namespace, model, runtime, modelFormat, minReplicas, maxReplicas, scaleTarget, scaleMetric, canaryTrafficPercent, labels: extraLabels = {}, defaults: defs, } = props;
|
|
49
|
+
const commonLabels = {
|
|
50
|
+
"app.kubernetes.io/name": name,
|
|
51
|
+
"app.kubernetes.io/managed-by": "chant",
|
|
52
|
+
"app.kubernetes.io/component": "inference-service",
|
|
53
|
+
...extraLabels,
|
|
54
|
+
};
|
|
55
|
+
const predictor = {
|
|
56
|
+
model: {
|
|
57
|
+
runtime,
|
|
58
|
+
storageUri: resolveStorageUri(model),
|
|
59
|
+
...(modelFormat !== undefined && { modelFormat: { name: modelFormat } }),
|
|
60
|
+
},
|
|
61
|
+
...(minReplicas !== undefined && { minReplicas }),
|
|
62
|
+
...(maxReplicas !== undefined && { maxReplicas }),
|
|
63
|
+
...(scaleTarget !== undefined && { scaleTarget }),
|
|
64
|
+
...(scaleMetric !== undefined && { scaleMetric }),
|
|
65
|
+
...(canaryTrafficPercent !== undefined && { canaryTrafficPercent }),
|
|
66
|
+
};
|
|
67
|
+
const inferenceService = new InferenceServiceResource(mergeDefaults({
|
|
68
|
+
metadata: {
|
|
69
|
+
name,
|
|
70
|
+
namespace,
|
|
71
|
+
labels: commonLabels,
|
|
72
|
+
},
|
|
73
|
+
spec: { predictor },
|
|
74
|
+
}, defs?.inferenceService));
|
|
75
|
+
return { inferenceService };
|
|
76
|
+
}, "InferenceService");
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IrsaServiceAccount composite — ServiceAccount + IAM annotation + optional RBAC.
|
|
3
|
+
*
|
|
4
|
+
* @eks Creates a ServiceAccount with the `eks.amazonaws.com/role-arn`
|
|
5
|
+
* annotation for IAM Roles for Service Accounts (IRSA).
|
|
6
|
+
*/
|
|
7
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
8
|
+
import { ServiceAccount, Role, RoleBinding } from "../generated/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* Create an IrsaServiceAccount composite — returns prop objects for
|
|
11
|
+
* a ServiceAccount with IRSA annotation, and optional Role + RoleBinding.
|
|
12
|
+
*
|
|
13
|
+
* @eks
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
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
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export const IrsaServiceAccount = Composite((props) => {
|
|
28
|
+
const { name, iamRoleArn, rbacRules, labels: extraLabels = {}, namespace, defaults: defs, } = props;
|
|
29
|
+
const roleName = `${name}-role`;
|
|
30
|
+
const bindingName = `${name}-binding`;
|
|
31
|
+
const commonLabels = {
|
|
32
|
+
"app.kubernetes.io/name": name,
|
|
33
|
+
"app.kubernetes.io/managed-by": "chant",
|
|
34
|
+
...extraLabels,
|
|
35
|
+
};
|
|
36
|
+
const serviceAccount = new ServiceAccount(mergeDefaults({
|
|
37
|
+
metadata: {
|
|
38
|
+
name,
|
|
39
|
+
...(namespace && { namespace }),
|
|
40
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "service-account" },
|
|
41
|
+
annotations: {
|
|
42
|
+
"eks.amazonaws.com/role-arn": iamRoleArn,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}, defs?.serviceAccount));
|
|
46
|
+
const result = { serviceAccount };
|
|
47
|
+
if (rbacRules && rbacRules.length > 0) {
|
|
48
|
+
result.role = new Role(mergeDefaults({
|
|
49
|
+
metadata: {
|
|
50
|
+
name: roleName,
|
|
51
|
+
...(namespace && { namespace }),
|
|
52
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
53
|
+
},
|
|
54
|
+
rules: rbacRules,
|
|
55
|
+
}, defs?.role));
|
|
56
|
+
result.roleBinding = new RoleBinding(mergeDefaults({
|
|
57
|
+
metadata: {
|
|
58
|
+
name: bindingName,
|
|
59
|
+
...(namespace && { namespace }),
|
|
60
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
61
|
+
},
|
|
62
|
+
roleRef: {
|
|
63
|
+
apiGroup: "rbac.authorization.k8s.io",
|
|
64
|
+
kind: "Role",
|
|
65
|
+
name: roleName,
|
|
66
|
+
},
|
|
67
|
+
subjects: [
|
|
68
|
+
{
|
|
69
|
+
kind: "ServiceAccount",
|
|
70
|
+
name,
|
|
71
|
+
...(namespace && { namespace }),
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
}, defs?.roleBinding));
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}, "IrsaServiceAccount");
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the per-member `defaults` option on composites.
|
|
3
|
+
*
|
|
4
|
+
* Each member's override is checked against the constructor props of the
|
|
5
|
+
* generated class that builds it. The override is merged into the composite's
|
|
6
|
+
* own props by mergeDefaults, so objects are partial at every depth; arrays
|
|
7
|
+
* are appended, so their elements stay complete.
|
|
8
|
+
*
|
|
9
|
+
* The props come from the generated declaration file. `../generated` itself
|
|
10
|
+
* resolves to the runtime index.ts, whose classes take `Record<string, unknown>`.
|
|
11
|
+
* The lexicon build copies that declaration file next to the emitted types so
|
|
12
|
+
* the reference resolves for consumers too.
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetricsServer composite — Deployment + Service + ServiceAccount + RBAC + APIService.
|
|
3
|
+
*
|
|
4
|
+
* Deploys metrics-server for HPA pod CPU/memory metrics. metrics-server is not an
|
|
5
|
+
* EKS managed addon — it needs K8s workloads. Uses in-cluster RBAC only (no IRSA).
|
|
6
|
+
*/
|
|
7
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
8
|
+
import { Deployment, Service, ServiceAccount, ClusterRole, ClusterRoleBinding, APIService } from "../generated/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* Create a MetricsServer composite — returns prop objects for a Deployment,
|
|
11
|
+
* Service, ServiceAccount, ClusterRoles, ClusterRoleBindings, and APIService.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { MetricsServer } from "@intentius/chant-lexicon-k8s";
|
|
16
|
+
*
|
|
17
|
+
* const ms = MetricsServer({});
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const MetricsServer = Composite((props) => {
|
|
21
|
+
const { name = "metrics-server", image = "registry.k8s.io/metrics-server/metrics-server:v0.7.2", replicas = 1, namespace = "kube-system", labels: extraLabels = {}, defaults: defs, } = props;
|
|
22
|
+
const saName = `${name}-sa`;
|
|
23
|
+
const commonLabels = {
|
|
24
|
+
"app.kubernetes.io/name": name,
|
|
25
|
+
"app.kubernetes.io/managed-by": "chant",
|
|
26
|
+
...extraLabels,
|
|
27
|
+
};
|
|
28
|
+
const deployment = new Deployment(mergeDefaults({
|
|
29
|
+
metadata: {
|
|
30
|
+
name,
|
|
31
|
+
namespace,
|
|
32
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "metrics" },
|
|
33
|
+
},
|
|
34
|
+
spec: {
|
|
35
|
+
replicas,
|
|
36
|
+
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
37
|
+
template: {
|
|
38
|
+
metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
|
|
39
|
+
spec: {
|
|
40
|
+
serviceAccountName: saName,
|
|
41
|
+
containers: [
|
|
42
|
+
{
|
|
43
|
+
name,
|
|
44
|
+
image,
|
|
45
|
+
args: [
|
|
46
|
+
"--cert-dir=/tmp",
|
|
47
|
+
"--secure-port=10250",
|
|
48
|
+
"--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname",
|
|
49
|
+
"--kubelet-use-node-status-port",
|
|
50
|
+
"--metric-resolution=15s",
|
|
51
|
+
],
|
|
52
|
+
ports: [{ containerPort: 10250, name: "https", protocol: "TCP" }],
|
|
53
|
+
resources: {
|
|
54
|
+
requests: { cpu: "100m", memory: "200Mi" },
|
|
55
|
+
limits: { cpu: "100m", memory: "200Mi" },
|
|
56
|
+
},
|
|
57
|
+
livenessProbe: {
|
|
58
|
+
httpGet: { path: "/livez", port: 10250, scheme: "HTTPS" },
|
|
59
|
+
initialDelaySeconds: 0,
|
|
60
|
+
periodSeconds: 10,
|
|
61
|
+
failureThreshold: 3,
|
|
62
|
+
},
|
|
63
|
+
readinessProbe: {
|
|
64
|
+
httpGet: { path: "/readyz", port: 10250, scheme: "HTTPS" },
|
|
65
|
+
initialDelaySeconds: 20,
|
|
66
|
+
periodSeconds: 10,
|
|
67
|
+
failureThreshold: 3,
|
|
68
|
+
},
|
|
69
|
+
securityContext: {
|
|
70
|
+
runAsNonRoot: true,
|
|
71
|
+
readOnlyRootFilesystem: true,
|
|
72
|
+
allowPrivilegeEscalation: false,
|
|
73
|
+
},
|
|
74
|
+
volumeMounts: [{ name: "tmp-dir", mountPath: "/tmp" }],
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
volumes: [{ name: "tmp-dir", emptyDir: {} }],
|
|
78
|
+
priorityClassName: "system-cluster-critical",
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
}, defs?.deployment));
|
|
83
|
+
const service = new Service(mergeDefaults({
|
|
84
|
+
metadata: {
|
|
85
|
+
name,
|
|
86
|
+
namespace,
|
|
87
|
+
labels: {
|
|
88
|
+
...commonLabels,
|
|
89
|
+
"app.kubernetes.io/component": "metrics",
|
|
90
|
+
"kubernetes.io/cluster-service": "true",
|
|
91
|
+
"kubernetes.io/name": "Metrics-server",
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
spec: {
|
|
95
|
+
selector: { "app.kubernetes.io/name": name },
|
|
96
|
+
ports: [{ port: 443, targetPort: 10250, protocol: "TCP", name: "https" }],
|
|
97
|
+
},
|
|
98
|
+
}, defs?.service));
|
|
99
|
+
const serviceAccount = new ServiceAccount(mergeDefaults({
|
|
100
|
+
metadata: {
|
|
101
|
+
name: saName,
|
|
102
|
+
namespace,
|
|
103
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "metrics" },
|
|
104
|
+
},
|
|
105
|
+
}, defs?.serviceAccount));
|
|
106
|
+
const clusterRole = new ClusterRole(mergeDefaults({
|
|
107
|
+
metadata: {
|
|
108
|
+
name: `system:${name}`,
|
|
109
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
110
|
+
},
|
|
111
|
+
rules: [
|
|
112
|
+
{ apiGroups: [""], resources: ["pods", "nodes", "namespaces", "configmaps"], verbs: ["get", "list", "watch"] },
|
|
113
|
+
{ apiGroups: [""], resources: ["nodes/metrics", "nodes/stats"], verbs: ["get"] },
|
|
114
|
+
],
|
|
115
|
+
}, defs?.clusterRole));
|
|
116
|
+
const clusterRoleBinding = new ClusterRoleBinding(mergeDefaults({
|
|
117
|
+
metadata: {
|
|
118
|
+
name: `system:${name}`,
|
|
119
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
120
|
+
},
|
|
121
|
+
roleRef: {
|
|
122
|
+
apiGroup: "rbac.authorization.k8s.io",
|
|
123
|
+
kind: "ClusterRole",
|
|
124
|
+
name: `system:${name}`,
|
|
125
|
+
},
|
|
126
|
+
subjects: [{ kind: "ServiceAccount", name: saName, namespace }],
|
|
127
|
+
}, defs?.clusterRoleBinding));
|
|
128
|
+
const aggregatedClusterRole = new ClusterRole(mergeDefaults({
|
|
129
|
+
metadata: {
|
|
130
|
+
name: `system:${name}-aggregated-reader`,
|
|
131
|
+
labels: {
|
|
132
|
+
...commonLabels,
|
|
133
|
+
"app.kubernetes.io/component": "rbac",
|
|
134
|
+
"rbac.authorization.k8s.io/aggregate-to-admin": "true",
|
|
135
|
+
"rbac.authorization.k8s.io/aggregate-to-edit": "true",
|
|
136
|
+
"rbac.authorization.k8s.io/aggregate-to-view": "true",
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
rules: [
|
|
140
|
+
{ apiGroups: ["metrics.k8s.io"], resources: ["pods", "nodes"], verbs: ["get", "list", "watch"] },
|
|
141
|
+
],
|
|
142
|
+
}, defs?.aggregatedClusterRole));
|
|
143
|
+
const authDelegatorBinding = new ClusterRoleBinding(mergeDefaults({
|
|
144
|
+
metadata: {
|
|
145
|
+
name: `${name}:system:auth-delegator`,
|
|
146
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
147
|
+
},
|
|
148
|
+
roleRef: {
|
|
149
|
+
apiGroup: "rbac.authorization.k8s.io",
|
|
150
|
+
kind: "ClusterRole",
|
|
151
|
+
name: "system:auth-delegator",
|
|
152
|
+
},
|
|
153
|
+
subjects: [{ kind: "ServiceAccount", name: saName, namespace }],
|
|
154
|
+
}, defs?.authDelegatorBinding));
|
|
155
|
+
const apiService = new APIService(mergeDefaults({
|
|
156
|
+
apiVersion: "apiregistration.k8s.io/v1",
|
|
157
|
+
kind: "APIService",
|
|
158
|
+
metadata: {
|
|
159
|
+
name: "v1beta1.metrics.k8s.io",
|
|
160
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "metrics" },
|
|
161
|
+
},
|
|
162
|
+
spec: {
|
|
163
|
+
service: { name, namespace },
|
|
164
|
+
group: "metrics.k8s.io",
|
|
165
|
+
version: "v1beta1",
|
|
166
|
+
insecureSkipTLSVerify: true,
|
|
167
|
+
groupPriorityMinimum: 100,
|
|
168
|
+
versionPriority: 100,
|
|
169
|
+
},
|
|
170
|
+
}, defs?.apiService));
|
|
171
|
+
return {
|
|
172
|
+
deployment,
|
|
173
|
+
service,
|
|
174
|
+
serviceAccount,
|
|
175
|
+
clusterRole,
|
|
176
|
+
clusterRoleBinding,
|
|
177
|
+
aggregatedClusterRole,
|
|
178
|
+
authDelegatorBinding,
|
|
179
|
+
apiService,
|
|
180
|
+
};
|
|
181
|
+
}, "MetricsServer");
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model composite — resolves a model artifact reference to a KServe
|
|
3
|
+
* `storageUri` (+ optional warm-cache PVC), keyed by `(id, version)`.
|
|
4
|
+
*
|
|
5
|
+
* This is the FSx-warm-cache equivalent from the Netflix serving yardstick
|
|
6
|
+
* (see epic #982): a small, spec-true resolver that InferenceService (#985)
|
|
7
|
+
* consumes for its predictor's model reference. It does not itself emit an
|
|
8
|
+
* InferenceService or ServingRuntime — those are #984/#985's job.
|
|
9
|
+
*
|
|
10
|
+
* `version` is required so every resolved `storageUri` is pinned: the
|
|
11
|
+
* version is always appended as the trailing path segment, whether the
|
|
12
|
+
* default `id`-derived path is used or `uri` overrides it. This keeps the
|
|
13
|
+
* output stable for the unpinned-model lint rule (#988).
|
|
14
|
+
*
|
|
15
|
+
* `Model` itself is a plain resolver — a resolved value object, per the
|
|
16
|
+
* composite conventions — rather than a `Composite`, because its primary
|
|
17
|
+
* output (`storageUri`) is a string, not a Declarable; a `Composite`
|
|
18
|
+
* factory's members must all be Declarables. The optional cache PVC is
|
|
19
|
+
* built through an internal `Composite` so it gets the same bookkeeping
|
|
20
|
+
* (provenance, defaults-merging) as every other emitted resource.
|
|
21
|
+
*/
|
|
22
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
23
|
+
import { PersistentVolumeClaim } from "../generated/index.js";
|
|
24
|
+
const STORAGE_SCHEME = {
|
|
25
|
+
hf: "hf",
|
|
26
|
+
gcs: "gs",
|
|
27
|
+
s3: "s3",
|
|
28
|
+
pvc: "pvc",
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Resolve a model artifact's `{ id, version, source, uri }` to a pinned
|
|
32
|
+
* KServe `storageUri` string.
|
|
33
|
+
*/
|
|
34
|
+
export function resolveModelStorageUri(props) {
|
|
35
|
+
const { id, version, source, uri } = props;
|
|
36
|
+
const scheme = STORAGE_SCHEME[source];
|
|
37
|
+
const path = uri ?? id;
|
|
38
|
+
return `${scheme}://${path}/${version}`;
|
|
39
|
+
}
|
|
40
|
+
const ModelCachePvc = Composite((props) => {
|
|
41
|
+
const { id, version, storageClass, size, defaults } = props;
|
|
42
|
+
const pvc = new PersistentVolumeClaim(mergeDefaults({
|
|
43
|
+
metadata: {
|
|
44
|
+
name: `${id}-${version}`,
|
|
45
|
+
labels: {
|
|
46
|
+
"app.kubernetes.io/name": id,
|
|
47
|
+
"app.kubernetes.io/managed-by": "chant",
|
|
48
|
+
"app.kubernetes.io/component": "model-cache",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
spec: {
|
|
52
|
+
accessModes: ["ReadWriteMany"],
|
|
53
|
+
storageClassName: storageClass,
|
|
54
|
+
resources: { requests: { storage: size } },
|
|
55
|
+
},
|
|
56
|
+
}, defaults));
|
|
57
|
+
return { pvc };
|
|
58
|
+
}, "ModelCachePvc");
|
|
59
|
+
/**
|
|
60
|
+
* Resolve a model artifact `{ id, version, source, uri, cache }` to a pinned
|
|
61
|
+
* `storageUri`, with an optional warm-cache PVC.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* import { Model } from "@intentius/chant-lexicon-k8s";
|
|
66
|
+
*
|
|
67
|
+
* const { storageUri, cache } = Model({
|
|
68
|
+
* id: "llama-3-8b-instruct",
|
|
69
|
+
* version: "2024-07-01",
|
|
70
|
+
* source: "gcs",
|
|
71
|
+
* uri: "my-models-bucket/llama-3-8b-instruct",
|
|
72
|
+
* cache: { storageClass: "premium-rwo", size: "200Gi" },
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export function Model(props) {
|
|
77
|
+
const { id, version, cache, defaults } = props;
|
|
78
|
+
const storageUri = resolveModelStorageUri(props);
|
|
79
|
+
const cachePvc = cache
|
|
80
|
+
? ModelCachePvc({
|
|
81
|
+
id,
|
|
82
|
+
version,
|
|
83
|
+
storageClass: cache.storageClass,
|
|
84
|
+
size: cache.size,
|
|
85
|
+
defaults: defaults?.cachePvc,
|
|
86
|
+
}).pvc
|
|
87
|
+
: undefined;
|
|
88
|
+
return {
|
|
89
|
+
storageUri,
|
|
90
|
+
...(cachePvc && { cache: cachePvc }),
|
|
91
|
+
};
|
|
92
|
+
}
|