@intentius/chant-lexicon-k8s 0.95.1 → 0.97.0
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/composites/catalog.d.ts.map +1 -1
- package/dist/composites/index.d.ts +4 -0
- package/dist/composites/index.d.ts.map +1 -1
- package/dist/composites/monitored-service.d.ts +19 -0
- package/dist/composites/monitored-service.d.ts.map +1 -1
- package/dist/composites/otel-collector-agent.d.ts +22 -0
- package/dist/composites/otel-collector-agent.d.ts.map +1 -1
- package/dist/composites/otel-collector-gateway.d.ts +173 -0
- package/dist/composites/otel-collector-gateway.d.ts.map +1 -0
- package/dist/composites/otel-collector-shape.d.ts +73 -0
- package/dist/composites/otel-collector-shape.d.ts.map +1 -0
- package/dist/composites/otel-collector.d.ts +19 -1
- package/dist/composites/otel-collector.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +7 -3
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/otel-placement-helpers.d.ts +103 -0
- package/dist/lint/post-synth/otel-placement-helpers.d.ts.map +1 -0
- package/dist/lint/post-synth/wk8601.d.ts +17 -0
- package/dist/lint/post-synth/wk8601.d.ts.map +1 -0
- package/dist/lint/post-synth/wk8602.d.ts +23 -0
- package/dist/lint/post-synth/wk8602.d.ts.map +1 -0
- package/dist/lint/post-synth/wk8603.d.ts +19 -0
- package/dist/lint/post-synth/wk8603.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/okf/index.md +3 -0
- package/dist/okf/rules/WK8601.md +15 -0
- package/dist/okf/rules/WK8602.md +16 -0
- package/dist/okf/rules/WK8603.md +15 -0
- package/dist/okf/types/DaemonSet.md +3 -0
- package/dist/okf/types/Service.md +1 -0
- package/dist/rules/otel-placement-helpers.ts +277 -0
- package/dist/rules/wk8601.ts +44 -0
- package/dist/rules/wk8602.ts +133 -0
- package/dist/rules/wk8603.ts +66 -0
- package/dist/serializer.d.ts.map +1 -1
- package/dist/skills/chant-k8s.md +2 -0
- package/package.json +4 -3
- package/src/composites/__snapshots__/gke-otel-collector.snapshot.test.ts.snap +401 -0
- package/src/composites/catalog.ts +109 -0
- package/src/composites/gke-otel-collector.snapshot.test.ts +51 -0
- package/src/composites/index.ts +9 -0
- package/src/composites/monitored-service.ts +40 -16
- package/src/composites/otel-collector-agent.ts +62 -26
- package/src/composites/otel-collector-gateway.test.ts +260 -0
- package/src/composites/otel-collector-gateway.ts +325 -0
- package/src/composites/otel-collector-shape.ts +141 -0
- package/src/composites/otel-collector.ts +74 -31
- package/src/index.ts +3 -0
- package/src/lint/audit-catalog.ts +3 -0
- package/src/lint/post-synth/index.ts +6 -0
- package/src/lint/post-synth/otel-placement-helpers.ts +277 -0
- package/src/lint/post-synth/otel-placement.test.ts +401 -0
- package/src/lint/post-synth/wk8601.ts +44 -0
- package/src/lint/post-synth/wk8602.ts +133 -0
- package/src/lint/post-synth/wk8603.ts +66 -0
- package/src/prometheus-rule-groups.test.ts +135 -0
- package/src/serializer.ts +9 -1
- package/src/skills/chant-k8s.md +2 -0
|
@@ -2153,6 +2153,7 @@ export const compositeCatalog: CompositeEntry[] = [
|
|
|
2153
2153
|
"ClusterRoleBinding",
|
|
2154
2154
|
"ConfigMap",
|
|
2155
2155
|
"DaemonSet",
|
|
2156
|
+
"Pipeline",
|
|
2156
2157
|
"ServiceAccount"
|
|
2157
2158
|
],
|
|
2158
2159
|
"params": [
|
|
@@ -2460,6 +2461,12 @@ export const compositeCatalog: CompositeEntry[] = [
|
|
|
2460
2461
|
"required": false,
|
|
2461
2462
|
"description": "Alert rules — if provided, creates a PrometheusRule."
|
|
2462
2463
|
},
|
|
2464
|
+
{
|
|
2465
|
+
"name": "ruleGroups",
|
|
2466
|
+
"type": "Array<RuleGroupEntity | RuleGroupProps>",
|
|
2467
|
+
"required": false,
|
|
2468
|
+
"description": "Rule groups from the prometheus lexicon — if provided, creates a PrometheusRule holding them, after the `alertRules` group when both are set."
|
|
2469
|
+
},
|
|
2463
2470
|
{
|
|
2464
2471
|
"name": "replicas",
|
|
2465
2472
|
"type": "number",
|
|
@@ -2894,6 +2901,8 @@ export const compositeCatalog: CompositeEntry[] = [
|
|
|
2894
2901
|
"ClusterRoleBinding",
|
|
2895
2902
|
"ConfigMap",
|
|
2896
2903
|
"DaemonSet",
|
|
2904
|
+
"Role",
|
|
2905
|
+
"RoleBinding",
|
|
2897
2906
|
"Service",
|
|
2898
2907
|
"ServiceAccount"
|
|
2899
2908
|
],
|
|
@@ -2972,6 +2981,106 @@ export const compositeCatalog: CompositeEntry[] = [
|
|
|
2972
2981
|
}
|
|
2973
2982
|
]
|
|
2974
2983
|
},
|
|
2984
|
+
{
|
|
2985
|
+
"name": "OtelCollectorGateway",
|
|
2986
|
+
"lexicon": "k8s",
|
|
2987
|
+
"description": "Create an OtelCollectorGateway composite.",
|
|
2988
|
+
"bundles": [
|
|
2989
|
+
"ClusterRole",
|
|
2990
|
+
"ClusterRoleBinding",
|
|
2991
|
+
"ConfigMap",
|
|
2992
|
+
"Deployment",
|
|
2993
|
+
"PodDisruptionBudget",
|
|
2994
|
+
"Service",
|
|
2995
|
+
"ServiceAccount"
|
|
2996
|
+
],
|
|
2997
|
+
"params": [
|
|
2998
|
+
{
|
|
2999
|
+
"name": "name",
|
|
3000
|
+
"type": "string",
|
|
3001
|
+
"required": false,
|
|
3002
|
+
"description": "Gateway name (default: \"otel-gateway\")."
|
|
3003
|
+
},
|
|
3004
|
+
{
|
|
3005
|
+
"name": "namespace",
|
|
3006
|
+
"type": "string",
|
|
3007
|
+
"required": false,
|
|
3008
|
+
"description": "Namespace (default: \"observability\")."
|
|
3009
|
+
},
|
|
3010
|
+
{
|
|
3011
|
+
"name": "replicas",
|
|
3012
|
+
"type": "number",
|
|
3013
|
+
"required": false,
|
|
3014
|
+
"description": "Number of collector pods (default: 2)."
|
|
3015
|
+
},
|
|
3016
|
+
{
|
|
3017
|
+
"name": "image",
|
|
3018
|
+
"type": "string",
|
|
3019
|
+
"required": false,
|
|
3020
|
+
"description": "Collector image (default: the contrib image at the otel lexicon's pinned collector version)."
|
|
3021
|
+
},
|
|
3022
|
+
{
|
|
3023
|
+
"name": "config",
|
|
3024
|
+
"type": "Iterable<Declarable>",
|
|
3025
|
+
"required": false,
|
|
3026
|
+
"description": "The collector config, as otel lexicon entities (components and pipelines)."
|
|
3027
|
+
},
|
|
3028
|
+
{
|
|
3029
|
+
"name": "exporters",
|
|
3030
|
+
"type": "OTelComponent<\"exporter\", string, any>[]",
|
|
3031
|
+
"required": false,
|
|
3032
|
+
"description": "Exporters for the default config (default: one `debug` exporter)."
|
|
3033
|
+
},
|
|
3034
|
+
{
|
|
3035
|
+
"name": "signals",
|
|
3036
|
+
"type": "Signal[]",
|
|
3037
|
+
"required": false,
|
|
3038
|
+
"description": "Signals the default config has pipelines for (default: traces, metrics and logs)."
|
|
3039
|
+
},
|
|
3040
|
+
{
|
|
3041
|
+
"name": "clusterRules",
|
|
3042
|
+
"type": "CollectorPolicyRule[]",
|
|
3043
|
+
"required": false,
|
|
3044
|
+
"description": "Cluster-wide read access the config needs, e.g. for a `k8s_cluster` receiver or a `k8sattributes` processor."
|
|
3045
|
+
},
|
|
3046
|
+
{
|
|
3047
|
+
"name": "labels",
|
|
3048
|
+
"type": "Record<string, string>",
|
|
3049
|
+
"required": false,
|
|
3050
|
+
"description": "Additional labels."
|
|
3051
|
+
},
|
|
3052
|
+
{
|
|
3053
|
+
"name": "cpuRequest",
|
|
3054
|
+
"type": "string",
|
|
3055
|
+
"required": false,
|
|
3056
|
+
"description": "CPU request (default: \"200m\")."
|
|
3057
|
+
},
|
|
3058
|
+
{
|
|
3059
|
+
"name": "memoryRequest",
|
|
3060
|
+
"type": "string",
|
|
3061
|
+
"required": false,
|
|
3062
|
+
"description": "Memory request (default: \"512Mi\")."
|
|
3063
|
+
},
|
|
3064
|
+
{
|
|
3065
|
+
"name": "cpuLimit",
|
|
3066
|
+
"type": "string",
|
|
3067
|
+
"required": false,
|
|
3068
|
+
"description": "CPU limit (default: \"1\")."
|
|
3069
|
+
},
|
|
3070
|
+
{
|
|
3071
|
+
"name": "memoryLimit",
|
|
3072
|
+
"type": "string",
|
|
3073
|
+
"required": false,
|
|
3074
|
+
"description": "Memory limit (default: \"1Gi\")."
|
|
3075
|
+
},
|
|
3076
|
+
{
|
|
3077
|
+
"name": "defaults",
|
|
3078
|
+
"type": "{ deployment?: Partial<Record<string, unknown>>; service?: Partial<Record<string, unknown>>; headlessService?: Partia...",
|
|
3079
|
+
"required": false,
|
|
3080
|
+
"description": "Per-member defaults for fine-grained overrides."
|
|
3081
|
+
}
|
|
3082
|
+
]
|
|
3083
|
+
},
|
|
2975
3084
|
{
|
|
2976
3085
|
"name": "RayCluster",
|
|
2977
3086
|
"lexicon": "k8s",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GkeOtelCollector's rendered manifests, held to a snapshot (#2898).
|
|
3
|
+
*
|
|
4
|
+
* `OtelCollector`, `OtelCollectorGateway` and `GkeOtelCollector` share the
|
|
5
|
+
* collector resources in `otel-collector-agent.ts`. The snapshot was recorded
|
|
6
|
+
* before the gateway work touched that file, so any change to the GKE output
|
|
7
|
+
* made through the shared code fails here.
|
|
8
|
+
*/
|
|
9
|
+
import { describe, expect, test } from "vitest";
|
|
10
|
+
import { expandComposite } from "@intentius/chant";
|
|
11
|
+
import { k8sSerializer } from "../serializer";
|
|
12
|
+
import { GkeOtelCollector } from "./gke-otel-collector";
|
|
13
|
+
|
|
14
|
+
function manifests(instance: ReturnType<typeof GkeOtelCollector>): string {
|
|
15
|
+
const out = k8sSerializer.serialize(expandComposite("collector", instance));
|
|
16
|
+
return typeof out === "string" ? out : out.primary;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe("GkeOtelCollector output", () => {
|
|
20
|
+
test("with Workload Identity", () => {
|
|
21
|
+
expect(
|
|
22
|
+
manifests(
|
|
23
|
+
GkeOtelCollector({
|
|
24
|
+
clusterName: "test-cluster",
|
|
25
|
+
projectId: "test-project",
|
|
26
|
+
gcpServiceAccountEmail: "otel@test-project.iam.gserviceaccount.com",
|
|
27
|
+
}),
|
|
28
|
+
),
|
|
29
|
+
).toMatchSnapshot();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("with every prop set", () => {
|
|
33
|
+
expect(
|
|
34
|
+
manifests(
|
|
35
|
+
GkeOtelCollector({
|
|
36
|
+
clusterName: "c1",
|
|
37
|
+
projectId: "p-123456",
|
|
38
|
+
name: "otel",
|
|
39
|
+
namespace: "telemetry",
|
|
40
|
+
image: "otel/opentelemetry-collector-contrib:0.100.0",
|
|
41
|
+
labels: { team: "obs" },
|
|
42
|
+
cpuRequest: "50m",
|
|
43
|
+
memoryRequest: "128Mi",
|
|
44
|
+
cpuLimit: "1",
|
|
45
|
+
memoryLimit: "1Gi",
|
|
46
|
+
defaults: { daemonSet: { spec: { updateStrategy: { type: "OnDelete" } } } },
|
|
47
|
+
}),
|
|
48
|
+
),
|
|
49
|
+
).toMatchSnapshot();
|
|
50
|
+
});
|
|
51
|
+
});
|
package/src/composites/index.ts
CHANGED
|
@@ -67,6 +67,15 @@ export { GkeFluentBitAgent } from "./gke-fluent-bit-agent";
|
|
|
67
67
|
export type { GkeFluentBitAgentProps, GkeFluentBitAgentResult } from "./gke-fluent-bit-agent";
|
|
68
68
|
export { OtelCollector } from "./otel-collector";
|
|
69
69
|
export type { OtelCollectorProps, OtelCollectorResult } from "./otel-collector";
|
|
70
|
+
export { OtelCollectorGateway, gatewayExporter } from "./otel-collector-gateway";
|
|
71
|
+
export type {
|
|
72
|
+
OtelCollectorGatewayProps,
|
|
73
|
+
OtelCollectorGatewayResult,
|
|
74
|
+
GatewayExporterOptions,
|
|
75
|
+
CollectorPolicyRule,
|
|
76
|
+
} from "./otel-collector-gateway";
|
|
77
|
+
export { OTEL_COLLECTOR_ANNOTATIONS } from "./otel-collector-shape";
|
|
78
|
+
export type { CollectorRole, GatewayRouting } from "./otel-collector-shape";
|
|
70
79
|
export { GkeOtelCollector } from "./gke-otel-collector";
|
|
71
80
|
export type { GkeOtelCollectorProps, GkeOtelCollectorResult } from "./gke-otel-collector";
|
|
72
81
|
export { GkeExternalDnsAgent } from "./gke-external-dns-agent";
|
|
@@ -4,9 +4,15 @@
|
|
|
4
4
|
* Observability pattern. ServiceMonitor and PrometheusRule are CRDs
|
|
5
5
|
* from the Prometheus Operator (monitoring.coreos.com/v1), returned
|
|
6
6
|
* as raw objects that can be serialized alongside native K8s resources.
|
|
7
|
+
*
|
|
8
|
+
* Rules come in two forms. `ruleGroups` takes `RuleGroup`s from the
|
|
9
|
+
* prometheus lexicon (`@intentius/chant-lexicon-prometheus`), typed and
|
|
10
|
+
* checked there, and rendered here exactly as they would be in a rule file.
|
|
11
|
+
* `alertRules` is the older shorthand for one group of alerts and still works.
|
|
7
12
|
*/
|
|
8
13
|
|
|
9
14
|
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
15
|
+
import { ruleGroupConfig, type RuleGroupEntity, type RuleGroupProps } from "@intentius/chant-lexicon-prometheus";
|
|
10
16
|
import { Deployment, Service, ServiceMonitor, PrometheusRule } from "../generated";
|
|
11
17
|
import type { ContainerSecurityContext } from "./security-context";
|
|
12
18
|
|
|
@@ -38,6 +44,11 @@ export interface MonitoredServiceProps {
|
|
|
38
44
|
scrapeInterval?: string;
|
|
39
45
|
/** Alert rules — if provided, creates a PrometheusRule. */
|
|
40
46
|
alertRules?: AlertRule[];
|
|
47
|
+
/**
|
|
48
|
+
* Rule groups from the prometheus lexicon — if provided, creates a
|
|
49
|
+
* PrometheusRule holding them, after the `alertRules` group when both are set.
|
|
50
|
+
*/
|
|
51
|
+
ruleGroups?: Array<RuleGroupEntity | RuleGroupProps>;
|
|
41
52
|
/** Number of replicas (default: 2). */
|
|
42
53
|
replicas?: number;
|
|
43
54
|
/** Additional labels to apply to all resources. */
|
|
@@ -89,6 +100,14 @@ export interface MonitoredServiceResult {
|
|
|
89
100
|
* { name: "HighErrorRate", expr: 'rate(http_errors_total[5m]) > 0.1', for: "5m", severity: "critical" },
|
|
90
101
|
* ],
|
|
91
102
|
* });
|
|
103
|
+
*
|
|
104
|
+
* // Or with typed rule groups from the prometheus lexicon:
|
|
105
|
+
* import { RuleGroup } from "@intentius/chant-lexicon-prometheus";
|
|
106
|
+
* const apiRules = new RuleGroup({
|
|
107
|
+
* name: "api",
|
|
108
|
+
* rules: [{ alert: "ApiDown", expr: 'up{job="api"} == 0', for: "5m", labels: { severity: "page" } }],
|
|
109
|
+
* });
|
|
110
|
+
* MonitoredService({ name: "api", image: "api:1.0", ruleGroups: [apiRules] });
|
|
92
111
|
* ```
|
|
93
112
|
*/
|
|
94
113
|
export const MonitoredService = Composite((props: MonitoredServiceProps) => {
|
|
@@ -100,6 +119,7 @@ export const MonitoredService = Composite((props: MonitoredServiceProps) => {
|
|
|
100
119
|
metricsPath = "/metrics",
|
|
101
120
|
scrapeInterval = "30s",
|
|
102
121
|
alertRules,
|
|
122
|
+
ruleGroups,
|
|
103
123
|
replicas = 2,
|
|
104
124
|
labels: extraLabels = {},
|
|
105
125
|
cpuLimit = "500m",
|
|
@@ -197,29 +217,33 @@ export const MonitoredService = Composite((props: MonitoredServiceProps) => {
|
|
|
197
217
|
|
|
198
218
|
const result: Record<string, any> = { deployment, service, serviceMonitor };
|
|
199
219
|
|
|
220
|
+
const groups: Array<Record<string, unknown>> = [];
|
|
200
221
|
if (alertRules && alertRules.length > 0) {
|
|
222
|
+
groups.push({
|
|
223
|
+
name: `${name}.rules`,
|
|
224
|
+
rules: alertRules.map((rule) => ({
|
|
225
|
+
alert: rule.name,
|
|
226
|
+
expr: rule.expr,
|
|
227
|
+
...(rule.for && { for: rule.for }),
|
|
228
|
+
labels: {
|
|
229
|
+
...(rule.severity && { severity: rule.severity }),
|
|
230
|
+
},
|
|
231
|
+
...(rule.annotations && { annotations: rule.annotations }),
|
|
232
|
+
})),
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
for (const group of ruleGroups ?? []) {
|
|
236
|
+
groups.push(ruleGroupConfig(group) as unknown as Record<string, unknown>);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (groups.length > 0) {
|
|
201
240
|
result.prometheusRule = new PrometheusRule(mergeDefaults({
|
|
202
241
|
metadata: {
|
|
203
242
|
name: `${name}-alerts`,
|
|
204
243
|
...(namespace && { namespace }),
|
|
205
244
|
labels: { ...commonLabels, "app.kubernetes.io/component": "monitoring" },
|
|
206
245
|
},
|
|
207
|
-
spec: {
|
|
208
|
-
groups: [
|
|
209
|
-
{
|
|
210
|
-
name: `${name}.rules`,
|
|
211
|
-
rules: alertRules.map((rule) => ({
|
|
212
|
-
alert: rule.name,
|
|
213
|
-
expr: rule.expr,
|
|
214
|
-
...(rule.for && { for: rule.for }),
|
|
215
|
-
labels: {
|
|
216
|
-
...(rule.severity && { severity: rule.severity }),
|
|
217
|
-
},
|
|
218
|
-
...(rule.annotations && { annotations: rule.annotations }),
|
|
219
|
-
})),
|
|
220
|
-
},
|
|
221
|
-
],
|
|
222
|
-
},
|
|
246
|
+
spec: { groups },
|
|
223
247
|
}, defs?.prometheusRule));
|
|
224
248
|
}
|
|
225
249
|
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
* `collectorYaml`) and says which ports the container exposes. Everything
|
|
9
9
|
* platform-specific, such as a Workload Identity annotation or probes, comes
|
|
10
10
|
* in as an option, so each composite keeps its own output.
|
|
11
|
+
*
|
|
12
|
+
* `OtelCollectorGateway` runs the same container and ConfigMap
|
|
13
|
+
* (`collectorContainer`, `collectorConfigMap`) in a Deployment.
|
|
11
14
|
*/
|
|
12
15
|
|
|
13
16
|
import { mergeDefaults } from "@intentius/chant";
|
|
@@ -34,6 +37,10 @@ export interface CollectorAgentOptions {
|
|
|
34
37
|
containerExtra?: Record<string, unknown>;
|
|
35
38
|
/** Annotations on the ServiceAccount, such as a cloud identity binding. */
|
|
36
39
|
serviceAccountAnnotations?: Record<string, string>;
|
|
40
|
+
/** Annotations on the DaemonSet, such as the deployment-shape markers in `otel-collector-shape.ts`. */
|
|
41
|
+
workloadAnnotations?: Record<string, string>;
|
|
42
|
+
/** Annotations on the ConfigMap. */
|
|
43
|
+
configMapAnnotations?: Record<string, string>;
|
|
37
44
|
defaults?: {
|
|
38
45
|
daemonSet?: Partial<Record<string, unknown>>;
|
|
39
46
|
serviceAccount?: Partial<Record<string, unknown>>;
|
|
@@ -58,32 +65,14 @@ export function collectorAgentResources(opts: CollectorAgentOptions): CollectorA
|
|
|
58
65
|
const bindingName = `${name}-binding`;
|
|
59
66
|
const configMapName = `${name}-config`;
|
|
60
67
|
|
|
61
|
-
const container
|
|
62
|
-
name,
|
|
63
|
-
image: opts.image,
|
|
64
|
-
args: [`--config=${opts.configDir}/config.yaml`],
|
|
65
|
-
ports: opts.ports,
|
|
66
|
-
resources: {
|
|
67
|
-
requests: { cpu: opts.cpuRequest, memory: opts.memoryRequest },
|
|
68
|
-
limits: { cpu: opts.cpuLimit, memory: opts.memoryLimit },
|
|
69
|
-
},
|
|
70
|
-
volumeMounts: [
|
|
71
|
-
{ name: "config", mountPath: opts.configDir, readOnly: true },
|
|
72
|
-
],
|
|
73
|
-
securityContext: {
|
|
74
|
-
runAsNonRoot: true,
|
|
75
|
-
runAsUser: 10001,
|
|
76
|
-
readOnlyRootFilesystem: true,
|
|
77
|
-
allowPrivilegeEscalation: false,
|
|
78
|
-
},
|
|
79
|
-
...opts.containerExtra,
|
|
80
|
-
};
|
|
68
|
+
const container = collectorContainer(opts);
|
|
81
69
|
|
|
82
70
|
const daemonSet = new DaemonSet(mergeDefaults({
|
|
83
71
|
metadata: {
|
|
84
72
|
name,
|
|
85
73
|
namespace,
|
|
86
74
|
labels: { ...commonLabels, "app.kubernetes.io/component": "agent" },
|
|
75
|
+
...(opts.workloadAnnotations ? { annotations: opts.workloadAnnotations } : {}),
|
|
87
76
|
},
|
|
88
77
|
spec: {
|
|
89
78
|
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
@@ -144,16 +133,63 @@ export function collectorAgentResources(opts: CollectorAgentOptions): CollectorA
|
|
|
144
133
|
],
|
|
145
134
|
}, defs?.clusterRoleBinding));
|
|
146
135
|
|
|
147
|
-
const configMap =
|
|
136
|
+
const configMap = collectorConfigMap(opts, configMapName, opts.configMapAnnotations);
|
|
137
|
+
|
|
138
|
+
return { daemonSet, serviceAccount, clusterRole, clusterRoleBinding, configMap };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** The fields the collector container and its ConfigMap are built from. */
|
|
142
|
+
export type CollectorContainerOptions = Pick<
|
|
143
|
+
CollectorAgentOptions,
|
|
144
|
+
"name" | "image" | "configDir" | "ports" | "cpuRequest" | "memoryRequest" | "cpuLimit" | "memoryLimit" | "containerExtra"
|
|
145
|
+
>;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The collector container: the image, the config file argument, the ports,
|
|
149
|
+
* requests and limits, the config volume mount and a non-root security
|
|
150
|
+
* context, with `containerExtra` laid over the top. The agent DaemonSet and
|
|
151
|
+
* the gateway Deployment run the same container.
|
|
152
|
+
*/
|
|
153
|
+
export function collectorContainer(opts: CollectorContainerOptions): Record<string, unknown> {
|
|
154
|
+
return {
|
|
155
|
+
name: opts.name,
|
|
156
|
+
image: opts.image,
|
|
157
|
+
args: [`--config=${opts.configDir}/config.yaml`],
|
|
158
|
+
ports: opts.ports,
|
|
159
|
+
resources: {
|
|
160
|
+
requests: { cpu: opts.cpuRequest, memory: opts.memoryRequest },
|
|
161
|
+
limits: { cpu: opts.cpuLimit, memory: opts.memoryLimit },
|
|
162
|
+
},
|
|
163
|
+
volumeMounts: [
|
|
164
|
+
{ name: "config", mountPath: opts.configDir, readOnly: true },
|
|
165
|
+
],
|
|
166
|
+
securityContext: {
|
|
167
|
+
runAsNonRoot: true,
|
|
168
|
+
runAsUser: 10001,
|
|
169
|
+
readOnlyRootFilesystem: true,
|
|
170
|
+
allowPrivilegeEscalation: false,
|
|
171
|
+
},
|
|
172
|
+
...opts.containerExtra,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** The ConfigMap holding the rendered collector config under `config.yaml`. */
|
|
177
|
+
export function collectorConfigMap(
|
|
178
|
+
opts: Pick<CollectorAgentOptions, "namespace" | "commonLabels" | "configYaml"> & {
|
|
179
|
+
defaults?: { configMap?: Partial<Record<string, unknown>> };
|
|
180
|
+
},
|
|
181
|
+
configMapName: string,
|
|
182
|
+
annotations?: Record<string, string>,
|
|
183
|
+
): InstanceType<typeof ConfigMap> {
|
|
184
|
+
return new ConfigMap(mergeDefaults({
|
|
148
185
|
metadata: {
|
|
149
186
|
name: configMapName,
|
|
150
|
-
namespace,
|
|
151
|
-
labels: { ...commonLabels, "app.kubernetes.io/component": "config" },
|
|
187
|
+
namespace: opts.namespace,
|
|
188
|
+
labels: { ...opts.commonLabels, "app.kubernetes.io/component": "config" },
|
|
189
|
+
...(annotations ? { annotations } : {}),
|
|
152
190
|
},
|
|
153
191
|
data: {
|
|
154
192
|
"config.yaml": opts.configYaml,
|
|
155
193
|
},
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
return { daemonSet, serviceAccount, clusterRole, clusterRoleBinding, configMap };
|
|
194
|
+
}, opts.defaults?.configMap));
|
|
159
195
|
}
|