@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
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WK8602: `tail_sampling` on a multi-replica gateway that collectors reach
|
|
3
|
+
* without trace-aware load balancing
|
|
4
|
+
*
|
|
5
|
+
* Tail sampling needs every span of a trace in the same process. Behind a
|
|
6
|
+
* ClusterIP Service, connections are spread across the gateway replicas with
|
|
7
|
+
* no regard for trace ids, so the spans of one trace land on different
|
|
8
|
+
* replicas and each samples a fragment. The fix is a `loadbalancing`
|
|
9
|
+
* exporter in front, routing by `traceID` to the replicas themselves (the
|
|
10
|
+
* `k8s` resolver on any Service that selects them, or the `dns` resolver on
|
|
11
|
+
* a headless one). A single-replica gateway passes.
|
|
12
|
+
*
|
|
13
|
+
* The check fires on evidence, not on absence: another collector in the
|
|
14
|
+
* build whose traces pipeline exports to one of the gateway's Services
|
|
15
|
+
* through `otlp`/`otlphttp`, through a `loadbalancing` exporter routed by
|
|
16
|
+
* something other than `traceID`, or through the `dns` resolver on a
|
|
17
|
+
* ClusterIP Service (one virtual IP, so one backend per connection). When
|
|
18
|
+
* the senders live in another build root, or are applications talking to
|
|
19
|
+
* the gateway directly, it stays silent (chant #1939).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
23
|
+
import { docsToManifests } from "./k8s-helpers";
|
|
24
|
+
import {
|
|
25
|
+
collectorPlacements,
|
|
26
|
+
componentType,
|
|
27
|
+
describePlacement,
|
|
28
|
+
hostOfEndpoint,
|
|
29
|
+
pipelinesOf,
|
|
30
|
+
serviceOfHost,
|
|
31
|
+
servicesSelecting,
|
|
32
|
+
tracePipelineProcessors,
|
|
33
|
+
type CollectorPlacement,
|
|
34
|
+
} from "./otel-placement-helpers";
|
|
35
|
+
|
|
36
|
+
const TRACE_ID_KEYS = new Set([undefined, null, "", "traceID"]);
|
|
37
|
+
|
|
38
|
+
function record(v: unknown): Record<string, unknown> {
|
|
39
|
+
return typeof v === "object" && v !== null && !Array.isArray(v) ? (v as Record<string, unknown>) : {};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Why each traces exporter of `sender` that reaches `services` does so without trace-aware routing. */
|
|
43
|
+
function unroutedExporters(sender: CollectorPlacement, services: Map<string, boolean>): string[] {
|
|
44
|
+
const reasons: string[] = [];
|
|
45
|
+
const seen = new Set<string>();
|
|
46
|
+
for (const [, pipeline] of pipelinesOf(sender.config, "traces")) {
|
|
47
|
+
for (const id of pipeline.exporters) {
|
|
48
|
+
if (seen.has(id)) continue;
|
|
49
|
+
seen.add(id);
|
|
50
|
+
const type = componentType(id);
|
|
51
|
+
const cfg = record(sender.config.exporters?.[id]);
|
|
52
|
+
|
|
53
|
+
if (type === "loadbalancing") {
|
|
54
|
+
const resolver = record(cfg.resolver);
|
|
55
|
+
const k8sService = record(resolver.k8s).service;
|
|
56
|
+
const dnsHost = record(resolver.dns).hostname;
|
|
57
|
+
let target: string | undefined;
|
|
58
|
+
if (typeof k8sService === "string") {
|
|
59
|
+
const svc = serviceOfHost(k8sService, sender.namespace);
|
|
60
|
+
if (svc && services.has(svc)) target = svc;
|
|
61
|
+
} else if (typeof dnsHost === "string") {
|
|
62
|
+
const svc = serviceOfHost(dnsHost, sender.namespace);
|
|
63
|
+
if (svc && services.has(svc)) {
|
|
64
|
+
target = svc;
|
|
65
|
+
if (!services.get(svc)) {
|
|
66
|
+
reasons.push(`${id} resolves ClusterIP Service ${svc} through dns, which returns one virtual IP rather than the replicas`);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (target && !TRACE_ID_KEYS.has(cfg.routing_key as string | undefined)) {
|
|
72
|
+
reasons.push(`${id} routes by ${String(cfg.routing_key)}, not traceID`);
|
|
73
|
+
}
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (type === "otlp" || type === "otlphttp") {
|
|
78
|
+
for (const field of ["endpoint", "traces_endpoint"]) {
|
|
79
|
+
const host = hostOfEndpoint(cfg[field]);
|
|
80
|
+
const svc = host ? serviceOfHost(host, sender.namespace) : undefined;
|
|
81
|
+
if (svc && services.has(svc)) {
|
|
82
|
+
reasons.push(`${id} sends to Service ${svc} directly`);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return reasons;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const wk8602: PostSynthCheck = {
|
|
93
|
+
id: "WK8602",
|
|
94
|
+
description:
|
|
95
|
+
"OpenTelemetry Collector gateway runs tail_sampling on more than one replica, but collectors send it traces without a loadbalancing exporter routed by traceID. Sees one build root at a time (chant #1939).",
|
|
96
|
+
|
|
97
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
98
|
+
const manifests = docsToManifests(ctx);
|
|
99
|
+
const placements = collectorPlacements(manifests);
|
|
100
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
101
|
+
|
|
102
|
+
for (const gateway of placements) {
|
|
103
|
+
if (gateway.kind === "DaemonSet" || gateway.replicas === undefined || gateway.replicas <= 1) continue;
|
|
104
|
+
const tail = tracePipelineProcessors(gateway.config, "tail_sampling");
|
|
105
|
+
if (tail.length === 0) continue;
|
|
106
|
+
|
|
107
|
+
const services = new Map<string, boolean>();
|
|
108
|
+
for (const s of servicesSelecting(manifests, gateway.workload)) services.set(`${s.name}.${s.namespace}`, s.headless);
|
|
109
|
+
if (services.size === 0) continue;
|
|
110
|
+
|
|
111
|
+
const senders = new Set<string>();
|
|
112
|
+
for (const sender of placements) {
|
|
113
|
+
if (sender.workload === gateway.workload) continue;
|
|
114
|
+
const key = `${sender.kind}/${sender.namespace}/${sender.name}/${sender.configMap}/${sender.key}`;
|
|
115
|
+
if (senders.has(key)) continue;
|
|
116
|
+
senders.add(key);
|
|
117
|
+
const reasons = unroutedExporters(sender, services);
|
|
118
|
+
if (reasons.length === 0) continue;
|
|
119
|
+
diagnostics.push({
|
|
120
|
+
checkId: "WK8602",
|
|
121
|
+
severity: "warning",
|
|
122
|
+
message:
|
|
123
|
+
`${describePlacement(gateway)} runs ${tail.join(", ")} on up to ${gateway.replicas} replicas, and ${describePlacement(sender)} sends it traces without trace-aware routing: ${reasons.join("; ")}. ` +
|
|
124
|
+
`Spans of one trace land on different replicas and each samples a fragment. ` +
|
|
125
|
+
`Export traces through a loadbalancing exporter with routing_key traceID (gatewayExporter(gateway, { loadBalance: true })), or run one replica.`,
|
|
126
|
+
entity: gateway.name,
|
|
127
|
+
lexicon: "k8s",
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return diagnostics;
|
|
132
|
+
},
|
|
133
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WK8603: `k8s_cluster` receiver in a collector that runs more than one copy
|
|
3
|
+
* without a leader elector
|
|
4
|
+
*
|
|
5
|
+
* The `k8s_cluster` receiver reports cluster-level metrics and entity events
|
|
6
|
+
* (nodes, deployments, pods, resource quotas) by watching the API server.
|
|
7
|
+
* Every copy of the collector reports every object, so in a DaemonSet the
|
|
8
|
+
* cluster is reported once per node, and in a Deployment once per replica:
|
|
9
|
+
* duplicated series and N watches against the API server. Run it in a
|
|
10
|
+
* single-replica Deployment, or set the receiver's `k8s_leader_elector` to a
|
|
11
|
+
* `k8s_leader_elector` extension enabled in `service.extensions` (both ship in
|
|
12
|
+
* otelcol-contrib and otelcol-k8s at the pinned v0.130.0), so only the
|
|
13
|
+
* leader collects.
|
|
14
|
+
*
|
|
15
|
+
* One build root at a time (chant #1939).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
19
|
+
import { docsToManifests } from "./k8s-helpers";
|
|
20
|
+
import { allPipelines, collectorPlacements, componentType, describePlacement, type CollectorConfigShape } from "./otel-placement-helpers";
|
|
21
|
+
|
|
22
|
+
/** Why a `k8s_cluster` receiver is not behind a working leader elector, or undefined when it is. */
|
|
23
|
+
function missingLeader(config: CollectorConfigShape, id: string): string | undefined {
|
|
24
|
+
const cfg = config.receivers?.[id];
|
|
25
|
+
const ref = typeof cfg === "object" && cfg !== null ? (cfg as Record<string, unknown>).k8s_leader_elector : undefined;
|
|
26
|
+
if (typeof ref !== "string" || ref.length === 0) return `${id} has no k8s_leader_elector`;
|
|
27
|
+
if (componentType(ref) !== "k8s_leader_elector" || !(config.extensions && ref in config.extensions)) {
|
|
28
|
+
return `${id} names k8s_leader_elector "${ref}", which is not a declared k8s_leader_elector extension`;
|
|
29
|
+
}
|
|
30
|
+
const enabled = Array.isArray(config.service.extensions) && config.service.extensions.includes(ref);
|
|
31
|
+
if (!enabled) return `${id} names k8s_leader_elector "${ref}", which is not enabled in service.extensions`;
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const wk8603: PostSynthCheck = {
|
|
36
|
+
id: "WK8603",
|
|
37
|
+
description:
|
|
38
|
+
"OpenTelemetry Collector runs the k8s_cluster receiver in a DaemonSet or multi-replica workload without a k8s_leader_elector; every copy reports every cluster object. Sees one build root at a time (chant #1939).",
|
|
39
|
+
|
|
40
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
41
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
42
|
+
for (const p of collectorPlacements(docsToManifests(ctx))) {
|
|
43
|
+
const copies = p.kind === "DaemonSet" ? "every node" : p.replicas !== undefined && p.replicas > 1 ? `each of up to ${p.replicas} replicas` : undefined;
|
|
44
|
+
if (!copies) continue;
|
|
45
|
+
|
|
46
|
+
const used = new Set<string>();
|
|
47
|
+
for (const [, pipeline] of allPipelines(p.config)) {
|
|
48
|
+
for (const id of pipeline.receivers) if (componentType(id) === "k8s_cluster") used.add(id);
|
|
49
|
+
}
|
|
50
|
+
const reasons = [...used].map((id) => missingLeader(p.config, id)).filter((r): r is string => r !== undefined);
|
|
51
|
+
if (reasons.length === 0) continue;
|
|
52
|
+
|
|
53
|
+
diagnostics.push({
|
|
54
|
+
checkId: "WK8603",
|
|
55
|
+
severity: "warning",
|
|
56
|
+
message:
|
|
57
|
+
`${describePlacement(p)} runs the k8s_cluster receiver on ${copies} (ConfigMap ${p.configMap}, ${p.key}): ${reasons.join("; ")}. ` +
|
|
58
|
+
`Each copy reports every cluster object, duplicating series and API server watches. ` +
|
|
59
|
+
`Run it in a single-replica Deployment, or reference a k8s_leader_elector extension from the receiver and enable it in service.extensions.`,
|
|
60
|
+
entity: p.name,
|
|
61
|
+
lexicon: "k8s",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return diagnostics;
|
|
65
|
+
},
|
|
66
|
+
};
|
package/dist/serializer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAsC,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAsC,MAAM,6BAA6B,CAAC;AAiSlG;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,UAkO3B,CAAC"}
|
package/dist/skills/chant-k8s.md
CHANGED
|
@@ -171,6 +171,8 @@ Composites are higher-level functions that produce multiple coordinated K8s reso
|
|
|
171
171
|
| Multi-host TLS Ingress (cert-manager) | **SecureIngress** | Ingress + optional Certificate |
|
|
172
172
|
| HPA metrics provider | **MetricsServer** | Deployment + Service + RBAC + APIService |
|
|
173
173
|
| CockroachDB cluster | **CockroachDbCluster** | StatefulSet + Services + PVCs + RBAC + optional CertificateRequests |
|
|
174
|
+
| OpenTelemetry agent on every node | **OtelCollector** | DaemonSet + node-local Service + RBAC + ConfigMap |
|
|
175
|
+
| OpenTelemetry gateway tier | **OtelCollectorGateway** | Deployment + ClusterIP and headless Services + PDB + ConfigMap; point agents at it with `gatewayExporter(gateway, { loadBalance: true })` |
|
|
174
176
|
|
|
175
177
|
### Decision Tree — AWS (EKS) Composites
|
|
176
178
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-k8s",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.97.0",
|
|
4
4
|
"description": "Kubernetes lexicon for chant — declarative IaC in TypeScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -73,11 +73,12 @@
|
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"@intentius/chant-lexicon-otel": "*",
|
|
76
|
+
"@intentius/chant-lexicon-prometheus": "*",
|
|
76
77
|
"js-yaml": "^4.3.1",
|
|
77
78
|
"@types/js-yaml": "^4.0.9"
|
|
78
79
|
},
|
|
79
80
|
"optionalDependencies": {
|
|
80
|
-
"@intentius/chant-k8s-client": "^0.
|
|
81
|
+
"@intentius/chant-k8s-client": "^0.97.0"
|
|
81
82
|
},
|
|
82
83
|
"devDependencies": {
|
|
83
84
|
"@intentius/chant": "*",
|
|
@@ -85,7 +86,7 @@
|
|
|
85
86
|
},
|
|
86
87
|
"peerDependencies": {
|
|
87
88
|
"zod": "^4.3.6",
|
|
88
|
-
"@intentius/chant": "^0.
|
|
89
|
+
"@intentius/chant": "^0.97.0",
|
|
89
90
|
"typescript": "^5.9.3"
|
|
90
91
|
}
|
|
91
92
|
}
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`GkeOtelCollector output > with Workload Identity 1`] = `
|
|
4
|
+
"apiVersion: apps/v1
|
|
5
|
+
kind: DaemonSet
|
|
6
|
+
metadata:
|
|
7
|
+
name: gke-otel-collector
|
|
8
|
+
namespace: gke-monitoring
|
|
9
|
+
labels:
|
|
10
|
+
app.kubernetes.io/name: gke-otel-collector
|
|
11
|
+
app.kubernetes.io/managed-by: chant
|
|
12
|
+
app.kubernetes.io/component: agent
|
|
13
|
+
spec:
|
|
14
|
+
selector:
|
|
15
|
+
matchLabels:
|
|
16
|
+
app.kubernetes.io/name: gke-otel-collector
|
|
17
|
+
template:
|
|
18
|
+
metadata:
|
|
19
|
+
labels:
|
|
20
|
+
app.kubernetes.io/name: gke-otel-collector
|
|
21
|
+
spec:
|
|
22
|
+
serviceAccountName: gke-otel-collector-sa
|
|
23
|
+
containers:
|
|
24
|
+
- name: gke-otel-collector
|
|
25
|
+
image: otel/opentelemetry-collector-contrib:latest
|
|
26
|
+
args:
|
|
27
|
+
- --config=/etc/otel/config.yaml
|
|
28
|
+
ports:
|
|
29
|
+
- containerPort: 4317
|
|
30
|
+
name: otlp-grpc
|
|
31
|
+
- containerPort: 4318
|
|
32
|
+
name: otlp-http
|
|
33
|
+
resources:
|
|
34
|
+
requests:
|
|
35
|
+
cpu: '100m'
|
|
36
|
+
memory: '256Mi'
|
|
37
|
+
limits:
|
|
38
|
+
cpu: '500m'
|
|
39
|
+
memory: '512Mi'
|
|
40
|
+
volumeMounts:
|
|
41
|
+
- name: config
|
|
42
|
+
mountPath: /etc/otel
|
|
43
|
+
readOnly: true
|
|
44
|
+
securityContext:
|
|
45
|
+
runAsNonRoot: true
|
|
46
|
+
runAsUser: 10001
|
|
47
|
+
readOnlyRootFilesystem: true
|
|
48
|
+
allowPrivilegeEscalation: false
|
|
49
|
+
volumes:
|
|
50
|
+
- name: config
|
|
51
|
+
configMap:
|
|
52
|
+
name: gke-otel-collector-config
|
|
53
|
+
tolerations:
|
|
54
|
+
- operator: Exists
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
apiVersion: v1
|
|
58
|
+
kind: ServiceAccount
|
|
59
|
+
metadata:
|
|
60
|
+
name: gke-otel-collector-sa
|
|
61
|
+
namespace: gke-monitoring
|
|
62
|
+
labels:
|
|
63
|
+
app.kubernetes.io/name: gke-otel-collector
|
|
64
|
+
app.kubernetes.io/managed-by: chant
|
|
65
|
+
app.kubernetes.io/component: agent
|
|
66
|
+
annotations:
|
|
67
|
+
iam.gke.io/gcp-service-account: otel@test-project.iam.gserviceaccount.com
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
apiVersion: rbac.authorization.k8s.io/v1
|
|
71
|
+
kind: ClusterRole
|
|
72
|
+
metadata:
|
|
73
|
+
name: gke-otel-collector-role
|
|
74
|
+
labels:
|
|
75
|
+
app.kubernetes.io/name: gke-otel-collector
|
|
76
|
+
app.kubernetes.io/managed-by: chant
|
|
77
|
+
app.kubernetes.io/component: rbac
|
|
78
|
+
rules:
|
|
79
|
+
- apiGroups:
|
|
80
|
+
- ''
|
|
81
|
+
resources:
|
|
82
|
+
- pods
|
|
83
|
+
- nodes
|
|
84
|
+
- endpoints
|
|
85
|
+
verbs:
|
|
86
|
+
- get
|
|
87
|
+
- list
|
|
88
|
+
- watch
|
|
89
|
+
- apiGroups:
|
|
90
|
+
- apps
|
|
91
|
+
resources:
|
|
92
|
+
- replicasets
|
|
93
|
+
verbs:
|
|
94
|
+
- get
|
|
95
|
+
- list
|
|
96
|
+
- watch
|
|
97
|
+
- apiGroups:
|
|
98
|
+
- batch
|
|
99
|
+
resources:
|
|
100
|
+
- jobs
|
|
101
|
+
verbs:
|
|
102
|
+
- get
|
|
103
|
+
- list
|
|
104
|
+
- watch
|
|
105
|
+
- apiGroups:
|
|
106
|
+
- ''
|
|
107
|
+
resources:
|
|
108
|
+
- nodes/proxy
|
|
109
|
+
verbs:
|
|
110
|
+
- get
|
|
111
|
+
- apiGroups:
|
|
112
|
+
- ''
|
|
113
|
+
resources:
|
|
114
|
+
- nodes/stats
|
|
115
|
+
- configmaps
|
|
116
|
+
- events
|
|
117
|
+
verbs:
|
|
118
|
+
- create
|
|
119
|
+
- get
|
|
120
|
+
- apiGroups:
|
|
121
|
+
- ''
|
|
122
|
+
resources:
|
|
123
|
+
- configmaps
|
|
124
|
+
verbs:
|
|
125
|
+
- get
|
|
126
|
+
- update
|
|
127
|
+
- create
|
|
128
|
+
resourceNames:
|
|
129
|
+
- otel-container-insight-clusterleader
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
apiVersion: rbac.authorization.k8s.io/v1
|
|
133
|
+
kind: ClusterRoleBinding
|
|
134
|
+
metadata:
|
|
135
|
+
name: gke-otel-collector-binding
|
|
136
|
+
labels:
|
|
137
|
+
app.kubernetes.io/name: gke-otel-collector
|
|
138
|
+
app.kubernetes.io/managed-by: chant
|
|
139
|
+
app.kubernetes.io/component: rbac
|
|
140
|
+
roleRef:
|
|
141
|
+
apiGroup: rbac.authorization.k8s.io
|
|
142
|
+
kind: ClusterRole
|
|
143
|
+
name: gke-otel-collector-role
|
|
144
|
+
subjects:
|
|
145
|
+
- kind: ServiceAccount
|
|
146
|
+
name: gke-otel-collector-sa
|
|
147
|
+
namespace: gke-monitoring
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
apiVersion: v1
|
|
151
|
+
kind: ConfigMap
|
|
152
|
+
metadata:
|
|
153
|
+
name: gke-otel-collector-config
|
|
154
|
+
namespace: gke-monitoring
|
|
155
|
+
labels:
|
|
156
|
+
app.kubernetes.io/name: gke-otel-collector
|
|
157
|
+
app.kubernetes.io/managed-by: chant
|
|
158
|
+
app.kubernetes.io/component: config
|
|
159
|
+
data:
|
|
160
|
+
config.yaml: |
|
|
161
|
+
receivers:
|
|
162
|
+
otlp:
|
|
163
|
+
protocols:
|
|
164
|
+
grpc:
|
|
165
|
+
endpoint: 0.0.0.0:4317
|
|
166
|
+
http:
|
|
167
|
+
endpoint: 0.0.0.0:4318
|
|
168
|
+
|
|
169
|
+
processors:
|
|
170
|
+
batch:
|
|
171
|
+
timeout: 30s
|
|
172
|
+
send_batch_size: 8192
|
|
173
|
+
resourcedetection:
|
|
174
|
+
detectors: [gcp]
|
|
175
|
+
timeout: 10s
|
|
176
|
+
|
|
177
|
+
exporters:
|
|
178
|
+
googlecloud:
|
|
179
|
+
project: test-project
|
|
180
|
+
metric:
|
|
181
|
+
prefix: custom.googleapis.com/test-cluster
|
|
182
|
+
trace:
|
|
183
|
+
attribute_mappings:
|
|
184
|
+
- key: service.name
|
|
185
|
+
replacement: g.co/r/service/name
|
|
186
|
+
|
|
187
|
+
service:
|
|
188
|
+
pipelines:
|
|
189
|
+
metrics:
|
|
190
|
+
receivers: [otlp]
|
|
191
|
+
processors: [batch, resourcedetection]
|
|
192
|
+
exporters: [googlecloud]
|
|
193
|
+
traces:
|
|
194
|
+
receivers: [otlp]
|
|
195
|
+
processors: [batch, resourcedetection]
|
|
196
|
+
exporters: [googlecloud]
|
|
197
|
+
"
|
|
198
|
+
`;
|
|
199
|
+
|
|
200
|
+
exports[`GkeOtelCollector output > with every prop set 1`] = `
|
|
201
|
+
"apiVersion: apps/v1
|
|
202
|
+
kind: DaemonSet
|
|
203
|
+
metadata:
|
|
204
|
+
name: otel
|
|
205
|
+
namespace: telemetry
|
|
206
|
+
labels:
|
|
207
|
+
app.kubernetes.io/name: otel
|
|
208
|
+
app.kubernetes.io/managed-by: chant
|
|
209
|
+
team: obs
|
|
210
|
+
app.kubernetes.io/component: agent
|
|
211
|
+
spec:
|
|
212
|
+
selector:
|
|
213
|
+
matchLabels:
|
|
214
|
+
app.kubernetes.io/name: otel
|
|
215
|
+
template:
|
|
216
|
+
metadata:
|
|
217
|
+
labels:
|
|
218
|
+
app.kubernetes.io/name: otel
|
|
219
|
+
team: obs
|
|
220
|
+
spec:
|
|
221
|
+
serviceAccountName: otel-sa
|
|
222
|
+
containers:
|
|
223
|
+
- name: otel
|
|
224
|
+
image: otel/opentelemetry-collector-contrib:0.100.0
|
|
225
|
+
args:
|
|
226
|
+
- --config=/etc/otel/config.yaml
|
|
227
|
+
ports:
|
|
228
|
+
- containerPort: 4317
|
|
229
|
+
name: otlp-grpc
|
|
230
|
+
- containerPort: 4318
|
|
231
|
+
name: otlp-http
|
|
232
|
+
resources:
|
|
233
|
+
requests:
|
|
234
|
+
cpu: '50m'
|
|
235
|
+
memory: '128Mi'
|
|
236
|
+
limits:
|
|
237
|
+
cpu: '1'
|
|
238
|
+
memory: '1Gi'
|
|
239
|
+
volumeMounts:
|
|
240
|
+
- name: config
|
|
241
|
+
mountPath: /etc/otel
|
|
242
|
+
readOnly: true
|
|
243
|
+
securityContext:
|
|
244
|
+
runAsNonRoot: true
|
|
245
|
+
runAsUser: 10001
|
|
246
|
+
readOnlyRootFilesystem: true
|
|
247
|
+
allowPrivilegeEscalation: false
|
|
248
|
+
volumes:
|
|
249
|
+
- name: config
|
|
250
|
+
configMap:
|
|
251
|
+
name: otel-config
|
|
252
|
+
tolerations:
|
|
253
|
+
- operator: Exists
|
|
254
|
+
updateStrategy:
|
|
255
|
+
type: OnDelete
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
apiVersion: v1
|
|
259
|
+
kind: ServiceAccount
|
|
260
|
+
metadata:
|
|
261
|
+
name: otel-sa
|
|
262
|
+
namespace: telemetry
|
|
263
|
+
labels:
|
|
264
|
+
app.kubernetes.io/name: otel
|
|
265
|
+
app.kubernetes.io/managed-by: chant
|
|
266
|
+
team: obs
|
|
267
|
+
app.kubernetes.io/component: agent
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
apiVersion: rbac.authorization.k8s.io/v1
|
|
271
|
+
kind: ClusterRole
|
|
272
|
+
metadata:
|
|
273
|
+
name: otel-role
|
|
274
|
+
labels:
|
|
275
|
+
app.kubernetes.io/name: otel
|
|
276
|
+
app.kubernetes.io/managed-by: chant
|
|
277
|
+
team: obs
|
|
278
|
+
app.kubernetes.io/component: rbac
|
|
279
|
+
rules:
|
|
280
|
+
- apiGroups:
|
|
281
|
+
- ''
|
|
282
|
+
resources:
|
|
283
|
+
- pods
|
|
284
|
+
- nodes
|
|
285
|
+
- endpoints
|
|
286
|
+
verbs:
|
|
287
|
+
- get
|
|
288
|
+
- list
|
|
289
|
+
- watch
|
|
290
|
+
- apiGroups:
|
|
291
|
+
- apps
|
|
292
|
+
resources:
|
|
293
|
+
- replicasets
|
|
294
|
+
verbs:
|
|
295
|
+
- get
|
|
296
|
+
- list
|
|
297
|
+
- watch
|
|
298
|
+
- apiGroups:
|
|
299
|
+
- batch
|
|
300
|
+
resources:
|
|
301
|
+
- jobs
|
|
302
|
+
verbs:
|
|
303
|
+
- get
|
|
304
|
+
- list
|
|
305
|
+
- watch
|
|
306
|
+
- apiGroups:
|
|
307
|
+
- ''
|
|
308
|
+
resources:
|
|
309
|
+
- nodes/proxy
|
|
310
|
+
verbs:
|
|
311
|
+
- get
|
|
312
|
+
- apiGroups:
|
|
313
|
+
- ''
|
|
314
|
+
resources:
|
|
315
|
+
- nodes/stats
|
|
316
|
+
- configmaps
|
|
317
|
+
- events
|
|
318
|
+
verbs:
|
|
319
|
+
- create
|
|
320
|
+
- get
|
|
321
|
+
- apiGroups:
|
|
322
|
+
- ''
|
|
323
|
+
resources:
|
|
324
|
+
- configmaps
|
|
325
|
+
verbs:
|
|
326
|
+
- get
|
|
327
|
+
- update
|
|
328
|
+
- create
|
|
329
|
+
resourceNames:
|
|
330
|
+
- otel-container-insight-clusterleader
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
apiVersion: rbac.authorization.k8s.io/v1
|
|
334
|
+
kind: ClusterRoleBinding
|
|
335
|
+
metadata:
|
|
336
|
+
name: otel-binding
|
|
337
|
+
labels:
|
|
338
|
+
app.kubernetes.io/name: otel
|
|
339
|
+
app.kubernetes.io/managed-by: chant
|
|
340
|
+
team: obs
|
|
341
|
+
app.kubernetes.io/component: rbac
|
|
342
|
+
roleRef:
|
|
343
|
+
apiGroup: rbac.authorization.k8s.io
|
|
344
|
+
kind: ClusterRole
|
|
345
|
+
name: otel-role
|
|
346
|
+
subjects:
|
|
347
|
+
- kind: ServiceAccount
|
|
348
|
+
name: otel-sa
|
|
349
|
+
namespace: telemetry
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
apiVersion: v1
|
|
353
|
+
kind: ConfigMap
|
|
354
|
+
metadata:
|
|
355
|
+
name: otel-config
|
|
356
|
+
namespace: telemetry
|
|
357
|
+
labels:
|
|
358
|
+
app.kubernetes.io/name: otel
|
|
359
|
+
app.kubernetes.io/managed-by: chant
|
|
360
|
+
team: obs
|
|
361
|
+
app.kubernetes.io/component: config
|
|
362
|
+
data:
|
|
363
|
+
config.yaml: |
|
|
364
|
+
receivers:
|
|
365
|
+
otlp:
|
|
366
|
+
protocols:
|
|
367
|
+
grpc:
|
|
368
|
+
endpoint: 0.0.0.0:4317
|
|
369
|
+
http:
|
|
370
|
+
endpoint: 0.0.0.0:4318
|
|
371
|
+
|
|
372
|
+
processors:
|
|
373
|
+
batch:
|
|
374
|
+
timeout: 30s
|
|
375
|
+
send_batch_size: 8192
|
|
376
|
+
resourcedetection:
|
|
377
|
+
detectors: [gcp]
|
|
378
|
+
timeout: 10s
|
|
379
|
+
|
|
380
|
+
exporters:
|
|
381
|
+
googlecloud:
|
|
382
|
+
project: p-123456
|
|
383
|
+
metric:
|
|
384
|
+
prefix: custom.googleapis.com/c1
|
|
385
|
+
trace:
|
|
386
|
+
attribute_mappings:
|
|
387
|
+
- key: service.name
|
|
388
|
+
replacement: g.co/r/service/name
|
|
389
|
+
|
|
390
|
+
service:
|
|
391
|
+
pipelines:
|
|
392
|
+
metrics:
|
|
393
|
+
receivers: [otlp]
|
|
394
|
+
processors: [batch, resourcedetection]
|
|
395
|
+
exporters: [googlecloud]
|
|
396
|
+
traces:
|
|
397
|
+
receivers: [otlp]
|
|
398
|
+
processors: [batch, resourcedetection]
|
|
399
|
+
exporters: [googlecloud]
|
|
400
|
+
"
|
|
401
|
+
`;
|