@intentius/chant-lexicon-k8s 0.0.14 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/integrity.json +8 -4
- package/dist/manifest.json +1 -1
- package/dist/rules/latest-image-tag.ts +121 -0
- package/dist/rules/missing-resource-limits.ts +111 -0
- package/dist/rules/wk8204.ts +33 -1
- package/dist/rules/wk8304.ts +70 -0
- package/dist/rules/wk8305.ts +115 -0
- package/dist/rules/wk8306.ts +50 -0
- package/package.json +27 -24
- package/src/codegen/docs.ts +1 -1
- package/src/composites/adot-collector.ts +8 -2
- package/src/composites/agic-ingress.ts +148 -0
- package/src/composites/aks-external-dns-agent.ts +199 -0
- package/src/composites/alb-ingress.ts +2 -1
- package/src/composites/autoscaled-service.ts +25 -7
- package/src/composites/azure-disk-storage-class.ts +82 -0
- package/src/composites/azure-file-storage-class.ts +77 -0
- package/src/composites/azure-monitor-collector.ts +232 -0
- package/src/composites/batch-job.ts +36 -3
- package/src/composites/composites.test.ts +1060 -0
- package/src/composites/config-connector-context.ts +62 -0
- package/src/composites/configured-app.ts +6 -0
- package/src/composites/cron-workload.ts +6 -0
- package/src/composites/ebs-storage-class.ts +4 -4
- package/src/composites/external-dns-agent.ts +6 -0
- package/src/composites/filestore-storage-class.ts +79 -0
- package/src/composites/fluent-bit-agent.ts +5 -0
- package/src/composites/gce-ingress.ts +143 -0
- package/src/composites/gce-pd-storage-class.ts +85 -0
- package/src/composites/gke-external-dns-agent.ts +175 -0
- package/src/composites/gke-fluent-bit-agent.ts +219 -0
- package/src/composites/gke-gateway.ts +143 -0
- package/src/composites/gke-otel-collector.ts +229 -0
- package/src/composites/index.ts +31 -0
- package/src/composites/metrics-server.ts +1 -1
- package/src/composites/monitored-service.ts +6 -0
- package/src/composites/network-isolated-app.ts +6 -0
- package/src/composites/node-agent.ts +6 -0
- package/src/composites/security-context.ts +10 -0
- package/src/composites/sidecar-app.ts +6 -0
- package/src/composites/stateful-app.ts +4 -7
- package/src/composites/web-app.ts +4 -7
- package/src/composites/worker-pool.ts +4 -7
- package/src/composites/workload-identity-sa.ts +118 -0
- package/src/composites/workload-identity-service-account.ts +116 -0
- package/src/index.ts +20 -1
- package/src/lint/post-synth/post-synth.test.ts +362 -1
- package/src/lint/post-synth/wk8204.ts +33 -1
- package/src/lint/post-synth/wk8304.ts +70 -0
- package/src/lint/post-synth/wk8305.ts +115 -0
- package/src/lint/post-synth/wk8306.ts +50 -0
- package/src/lint/rules/latest-image-tag.ts +121 -0
- package/src/lint/rules/missing-resource-limits.ts +111 -0
- package/src/lint/rules/rules.test.ts +192 -0
- package/src/plugin.test.ts +2 -2
- package/src/plugin.ts +129 -209
- package/src/serializer.test.ts +120 -0
- package/src/serializer.ts +16 -4
- package/src/skills/chant-k8s-aks.md +146 -0
- package/src/skills/chant-k8s-gke.md +191 -0
- package/src/skills/kubernetes-patterns.md +183 -0
- package/src/skills/kubernetes-security.md +237 -0
- /package/{dist → src}/skills/chant-k8s-eks.md +0 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GkeFluentBitAgent composite — DaemonSet + RBAC + ConfigMap for Fluent Bit on GKE.
|
|
3
|
+
*
|
|
4
|
+
* @gke Like FluentBitAgent but targets Cloud Logging via the stackdriver
|
|
5
|
+
* output plugin and uses GKE Workload Identity instead of IRSA.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface GkeFluentBitAgentProps {
|
|
9
|
+
/** GKE cluster name — used as log stream prefix. */
|
|
10
|
+
clusterName: string;
|
|
11
|
+
/** GCP project ID. */
|
|
12
|
+
projectId: string;
|
|
13
|
+
/** GCP service account email for Workload Identity. */
|
|
14
|
+
gcpServiceAccountEmail?: string;
|
|
15
|
+
/** Agent name (default: "fluent-bit"). */
|
|
16
|
+
name?: string;
|
|
17
|
+
/** Fluent Bit image (default: "fluent/fluent-bit:latest"). */
|
|
18
|
+
image?: string;
|
|
19
|
+
/** Namespace (default: "gke-logging"). */
|
|
20
|
+
namespace?: string;
|
|
21
|
+
/** Additional labels. */
|
|
22
|
+
labels?: Record<string, string>;
|
|
23
|
+
/** CPU request (default: "50m"). */
|
|
24
|
+
cpuRequest?: string;
|
|
25
|
+
/** Memory request (default: "64Mi"). */
|
|
26
|
+
memoryRequest?: string;
|
|
27
|
+
/** CPU limit (default: "200m"). */
|
|
28
|
+
cpuLimit?: string;
|
|
29
|
+
/** Memory limit (default: "128Mi"). */
|
|
30
|
+
memoryLimit?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface GkeFluentBitAgentResult {
|
|
34
|
+
daemonSet: Record<string, unknown>;
|
|
35
|
+
serviceAccount: Record<string, unknown>;
|
|
36
|
+
clusterRole: Record<string, unknown>;
|
|
37
|
+
clusterRoleBinding: Record<string, unknown>;
|
|
38
|
+
configMap: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Create a GkeFluentBitAgent composite — returns prop objects for
|
|
43
|
+
* a DaemonSet, ServiceAccount, ClusterRole, ClusterRoleBinding, and ConfigMap.
|
|
44
|
+
*
|
|
45
|
+
* @gke
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* import { GkeFluentBitAgent } from "@intentius/chant-lexicon-k8s";
|
|
49
|
+
*
|
|
50
|
+
* const { daemonSet, serviceAccount, clusterRole, clusterRoleBinding, configMap } = GkeFluentBitAgent({
|
|
51
|
+
* clusterName: "my-cluster",
|
|
52
|
+
* projectId: "my-project",
|
|
53
|
+
* gcpServiceAccountEmail: "fluent-bit@my-project.iam.gserviceaccount.com",
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export function GkeFluentBitAgent(props: GkeFluentBitAgentProps): GkeFluentBitAgentResult {
|
|
58
|
+
const {
|
|
59
|
+
clusterName,
|
|
60
|
+
projectId,
|
|
61
|
+
gcpServiceAccountEmail,
|
|
62
|
+
name = "fluent-bit",
|
|
63
|
+
image = "fluent/fluent-bit:latest",
|
|
64
|
+
namespace = "gke-logging",
|
|
65
|
+
labels: extraLabels = {},
|
|
66
|
+
cpuRequest = "50m",
|
|
67
|
+
memoryRequest = "64Mi",
|
|
68
|
+
cpuLimit = "200m",
|
|
69
|
+
memoryLimit = "128Mi",
|
|
70
|
+
} = props;
|
|
71
|
+
|
|
72
|
+
const saName = `${name}-sa`;
|
|
73
|
+
const clusterRoleName = `${name}-role`;
|
|
74
|
+
const bindingName = `${name}-binding`;
|
|
75
|
+
const configMapName = `${name}-config`;
|
|
76
|
+
|
|
77
|
+
const commonLabels: Record<string, string> = {
|
|
78
|
+
"app.kubernetes.io/name": name,
|
|
79
|
+
"app.kubernetes.io/managed-by": "chant",
|
|
80
|
+
...extraLabels,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const fluentBitConfig = `[SERVICE]
|
|
84
|
+
Flush 5
|
|
85
|
+
Log_Level info
|
|
86
|
+
Daemon off
|
|
87
|
+
Parsers_File parsers.conf
|
|
88
|
+
|
|
89
|
+
[INPUT]
|
|
90
|
+
Name tail
|
|
91
|
+
Tag kube.*
|
|
92
|
+
Path /var/log/containers/*.log
|
|
93
|
+
Parser docker
|
|
94
|
+
DB /var/fluent-bit/state/flb_container.db
|
|
95
|
+
Mem_Buf_Limit 5MB
|
|
96
|
+
Skip_Long_Lines On
|
|
97
|
+
Refresh_Interval 10
|
|
98
|
+
|
|
99
|
+
[FILTER]
|
|
100
|
+
Name kubernetes
|
|
101
|
+
Match kube.*
|
|
102
|
+
Kube_URL https://kubernetes.default.svc:443
|
|
103
|
+
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
|
104
|
+
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
|
|
105
|
+
Merge_Log On
|
|
106
|
+
K8S-Logging.Parser On
|
|
107
|
+
K8S-Logging.Exclude Off
|
|
108
|
+
|
|
109
|
+
[OUTPUT]
|
|
110
|
+
Name stackdriver
|
|
111
|
+
Match *
|
|
112
|
+
google_service_credentials /var/run/secrets/kubernetes.io/serviceaccount/token
|
|
113
|
+
resource k8s_container
|
|
114
|
+
k8s_cluster_name ${clusterName}
|
|
115
|
+
k8s_cluster_location ${projectId}
|
|
116
|
+
`;
|
|
117
|
+
|
|
118
|
+
const container: Record<string, unknown> = {
|
|
119
|
+
name,
|
|
120
|
+
image,
|
|
121
|
+
resources: {
|
|
122
|
+
requests: { cpu: cpuRequest, memory: memoryRequest },
|
|
123
|
+
limits: { cpu: cpuLimit, memory: memoryLimit },
|
|
124
|
+
},
|
|
125
|
+
volumeMounts: [
|
|
126
|
+
{ name: "varlog", mountPath: "/var/log", readOnly: true },
|
|
127
|
+
{ name: "config", mountPath: `/etc/${name}`, readOnly: true },
|
|
128
|
+
{ name: "state", mountPath: "/var/fluent-bit/state" },
|
|
129
|
+
],
|
|
130
|
+
securityContext: {
|
|
131
|
+
runAsUser: 0,
|
|
132
|
+
readOnlyRootFilesystem: true,
|
|
133
|
+
allowPrivilegeEscalation: false,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const daemonSetProps: Record<string, unknown> = {
|
|
138
|
+
metadata: {
|
|
139
|
+
name,
|
|
140
|
+
namespace,
|
|
141
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "agent" },
|
|
142
|
+
},
|
|
143
|
+
spec: {
|
|
144
|
+
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
145
|
+
template: {
|
|
146
|
+
metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
|
|
147
|
+
spec: {
|
|
148
|
+
serviceAccountName: saName,
|
|
149
|
+
containers: [container],
|
|
150
|
+
volumes: [
|
|
151
|
+
{ name: "varlog", hostPath: { path: "/var/log" } },
|
|
152
|
+
{ name: "config", configMap: { name: configMapName } },
|
|
153
|
+
{ name: "state", hostPath: { path: `/var/fluent-bit/state/${name}` } },
|
|
154
|
+
],
|
|
155
|
+
tolerations: [{ operator: "Exists" }],
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const serviceAccountProps: Record<string, unknown> = {
|
|
162
|
+
metadata: {
|
|
163
|
+
name: saName,
|
|
164
|
+
namespace,
|
|
165
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "agent" },
|
|
166
|
+
...(gcpServiceAccountEmail
|
|
167
|
+
? { annotations: { "iam.gke.io/gcp-service-account": gcpServiceAccountEmail } }
|
|
168
|
+
: {}),
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const clusterRoleProps: Record<string, unknown> = {
|
|
173
|
+
metadata: {
|
|
174
|
+
name: clusterRoleName,
|
|
175
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
176
|
+
},
|
|
177
|
+
rules: [
|
|
178
|
+
{ apiGroups: [""], resources: ["namespaces", "pods"], verbs: ["get", "list", "watch"] },
|
|
179
|
+
],
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const clusterRoleBindingProps: Record<string, unknown> = {
|
|
183
|
+
metadata: {
|
|
184
|
+
name: bindingName,
|
|
185
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
186
|
+
},
|
|
187
|
+
roleRef: {
|
|
188
|
+
apiGroup: "rbac.authorization.k8s.io",
|
|
189
|
+
kind: "ClusterRole",
|
|
190
|
+
name: clusterRoleName,
|
|
191
|
+
},
|
|
192
|
+
subjects: [
|
|
193
|
+
{
|
|
194
|
+
kind: "ServiceAccount",
|
|
195
|
+
name: saName,
|
|
196
|
+
namespace,
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const configMapProps: Record<string, unknown> = {
|
|
202
|
+
metadata: {
|
|
203
|
+
name: configMapName,
|
|
204
|
+
namespace,
|
|
205
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "config" },
|
|
206
|
+
},
|
|
207
|
+
data: {
|
|
208
|
+
"fluent-bit.conf": fluentBitConfig,
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
daemonSet: daemonSetProps,
|
|
214
|
+
serviceAccount: serviceAccountProps,
|
|
215
|
+
clusterRole: clusterRoleProps,
|
|
216
|
+
clusterRoleBinding: clusterRoleBindingProps,
|
|
217
|
+
configMap: configMapProps,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GkeGateway composite — Gateway + HTTPRoute for GKE Gateway API.
|
|
3
|
+
*
|
|
4
|
+
* @gke Creates a Gateway with a GKE-specific `gatewayClassName` and
|
|
5
|
+
* HTTPRoute resources for traffic routing.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface GkeGatewayHost {
|
|
9
|
+
/** Hostname (e.g., "api.example.com"). */
|
|
10
|
+
hostname: string;
|
|
11
|
+
/** Path rules for this host. */
|
|
12
|
+
paths: Array<{
|
|
13
|
+
path: string;
|
|
14
|
+
serviceName: string;
|
|
15
|
+
servicePort: number;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface GkeGatewayProps {
|
|
20
|
+
/** Gateway name — used in metadata and labels. */
|
|
21
|
+
name: string;
|
|
22
|
+
/** GKE gateway class (default: "gke-l7-global-external-managed"). */
|
|
23
|
+
gatewayClassName?:
|
|
24
|
+
| "gke-l7-global-external-managed"
|
|
25
|
+
| "gke-l7-regional-external-managed"
|
|
26
|
+
| "gke-l7-rilb";
|
|
27
|
+
/** Host definitions with paths. */
|
|
28
|
+
hosts: GkeGatewayHost[];
|
|
29
|
+
/** Google-managed certificate name for TLS. */
|
|
30
|
+
certificateName?: string;
|
|
31
|
+
/** Additional labels to apply to all resources. */
|
|
32
|
+
labels?: Record<string, string>;
|
|
33
|
+
/** Namespace for all resources. */
|
|
34
|
+
namespace?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface GkeGatewayResult {
|
|
38
|
+
gateway: Record<string, unknown>;
|
|
39
|
+
httpRoute: Record<string, unknown>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create a GkeGateway composite — returns prop objects for
|
|
44
|
+
* a Gateway and HTTPRoute with GKE-specific gateway class.
|
|
45
|
+
*
|
|
46
|
+
* @gke
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* import { GkeGateway } from "@intentius/chant-lexicon-k8s";
|
|
50
|
+
*
|
|
51
|
+
* const { gateway, httpRoute } = GkeGateway({
|
|
52
|
+
* name: "api-gateway",
|
|
53
|
+
* hosts: [
|
|
54
|
+
* {
|
|
55
|
+
* hostname: "api.example.com",
|
|
56
|
+
* paths: [{ path: "/", serviceName: "api", servicePort: 80 }],
|
|
57
|
+
* },
|
|
58
|
+
* ],
|
|
59
|
+
* certificateName: "api-cert",
|
|
60
|
+
* });
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export function GkeGateway(props: GkeGatewayProps): GkeGatewayResult {
|
|
64
|
+
const {
|
|
65
|
+
name,
|
|
66
|
+
gatewayClassName = "gke-l7-global-external-managed",
|
|
67
|
+
hosts,
|
|
68
|
+
certificateName,
|
|
69
|
+
labels: extraLabels = {},
|
|
70
|
+
namespace,
|
|
71
|
+
} = props;
|
|
72
|
+
|
|
73
|
+
const routeName = `${name}-route`;
|
|
74
|
+
|
|
75
|
+
const commonLabels: Record<string, string> = {
|
|
76
|
+
"app.kubernetes.io/name": name,
|
|
77
|
+
"app.kubernetes.io/managed-by": "chant",
|
|
78
|
+
...extraLabels,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// Build Gateway listeners
|
|
82
|
+
const listeners: Array<Record<string, unknown>> = [];
|
|
83
|
+
|
|
84
|
+
if (certificateName) {
|
|
85
|
+
listeners.push({
|
|
86
|
+
name: "https",
|
|
87
|
+
protocol: "HTTPS",
|
|
88
|
+
port: 443,
|
|
89
|
+
tls: {
|
|
90
|
+
mode: "Terminate",
|
|
91
|
+
certificateRefs: [{ kind: "ManagedCertificate", name: certificateName }],
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
listeners.push({
|
|
96
|
+
name: "http",
|
|
97
|
+
protocol: "HTTP",
|
|
98
|
+
port: 80,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const gatewayProps: Record<string, unknown> = {
|
|
103
|
+
metadata: {
|
|
104
|
+
name,
|
|
105
|
+
...(namespace && { namespace }),
|
|
106
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "gateway" },
|
|
107
|
+
},
|
|
108
|
+
spec: {
|
|
109
|
+
gatewayClassName,
|
|
110
|
+
listeners,
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Build HTTPRoute rules
|
|
115
|
+
const hostnames = hosts.map((h) => h.hostname);
|
|
116
|
+
|
|
117
|
+
const rules = hosts.flatMap((host) =>
|
|
118
|
+
host.paths.map((p) => ({
|
|
119
|
+
matches: [{ path: { type: "PathPrefix", value: p.path } }],
|
|
120
|
+
backendRefs: [
|
|
121
|
+
{ name: p.serviceName, port: p.servicePort },
|
|
122
|
+
],
|
|
123
|
+
})),
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const httpRouteProps: Record<string, unknown> = {
|
|
127
|
+
metadata: {
|
|
128
|
+
name: routeName,
|
|
129
|
+
...(namespace && { namespace }),
|
|
130
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "route" },
|
|
131
|
+
},
|
|
132
|
+
spec: {
|
|
133
|
+
parentRefs: [{ name }],
|
|
134
|
+
hostnames,
|
|
135
|
+
rules,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
gateway: gatewayProps,
|
|
141
|
+
httpRoute: httpRouteProps,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
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
|
+
|
|
8
|
+
export interface GkeOtelCollectorProps {
|
|
9
|
+
/** GKE cluster name. */
|
|
10
|
+
clusterName: string;
|
|
11
|
+
/** GCP project ID. */
|
|
12
|
+
projectId: string;
|
|
13
|
+
/** GCP service account email for Workload Identity. */
|
|
14
|
+
gcpServiceAccountEmail?: string;
|
|
15
|
+
/** Agent name (default: "gke-otel-collector"). */
|
|
16
|
+
name?: string;
|
|
17
|
+
/** OTel Collector image (default: "otel/opentelemetry-collector-contrib:latest"). */
|
|
18
|
+
image?: string;
|
|
19
|
+
/** Namespace (default: "gke-monitoring"). */
|
|
20
|
+
namespace?: string;
|
|
21
|
+
/** Additional labels. */
|
|
22
|
+
labels?: Record<string, string>;
|
|
23
|
+
/** CPU request (default: "100m"). */
|
|
24
|
+
cpuRequest?: string;
|
|
25
|
+
/** Memory request (default: "256Mi"). */
|
|
26
|
+
memoryRequest?: string;
|
|
27
|
+
/** CPU limit (default: "500m"). */
|
|
28
|
+
cpuLimit?: string;
|
|
29
|
+
/** Memory limit (default: "512Mi"). */
|
|
30
|
+
memoryLimit?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface GkeOtelCollectorResult {
|
|
34
|
+
daemonSet: Record<string, unknown>;
|
|
35
|
+
serviceAccount: Record<string, unknown>;
|
|
36
|
+
clusterRole: Record<string, unknown>;
|
|
37
|
+
clusterRoleBinding: Record<string, unknown>;
|
|
38
|
+
configMap: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Create a GkeOtelCollector composite — returns prop objects for
|
|
43
|
+
* a DaemonSet, ServiceAccount, ClusterRole, ClusterRoleBinding, and ConfigMap.
|
|
44
|
+
*
|
|
45
|
+
* @gke
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* import { GkeOtelCollector } from "@intentius/chant-lexicon-k8s";
|
|
49
|
+
*
|
|
50
|
+
* const { daemonSet, serviceAccount, clusterRole, clusterRoleBinding, configMap } = GkeOtelCollector({
|
|
51
|
+
* clusterName: "my-cluster",
|
|
52
|
+
* projectId: "my-project",
|
|
53
|
+
* gcpServiceAccountEmail: "otel@my-project.iam.gserviceaccount.com",
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export function GkeOtelCollector(props: GkeOtelCollectorProps): GkeOtelCollectorResult {
|
|
58
|
+
const {
|
|
59
|
+
clusterName,
|
|
60
|
+
projectId,
|
|
61
|
+
gcpServiceAccountEmail,
|
|
62
|
+
name = "gke-otel-collector",
|
|
63
|
+
image = "otel/opentelemetry-collector-contrib:latest",
|
|
64
|
+
namespace = "gke-monitoring",
|
|
65
|
+
labels: extraLabels = {},
|
|
66
|
+
cpuRequest = "100m",
|
|
67
|
+
memoryRequest = "256Mi",
|
|
68
|
+
cpuLimit = "500m",
|
|
69
|
+
memoryLimit = "512Mi",
|
|
70
|
+
} = props;
|
|
71
|
+
|
|
72
|
+
const saName = `${name}-sa`;
|
|
73
|
+
const clusterRoleName = `${name}-role`;
|
|
74
|
+
const bindingName = `${name}-binding`;
|
|
75
|
+
const configMapName = `${name}-config`;
|
|
76
|
+
|
|
77
|
+
const commonLabels: Record<string, string> = {
|
|
78
|
+
"app.kubernetes.io/name": name,
|
|
79
|
+
"app.kubernetes.io/managed-by": "chant",
|
|
80
|
+
...extraLabels,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const otelConfig = `receivers:
|
|
84
|
+
otlp:
|
|
85
|
+
protocols:
|
|
86
|
+
grpc:
|
|
87
|
+
endpoint: 0.0.0.0:4317
|
|
88
|
+
http:
|
|
89
|
+
endpoint: 0.0.0.0:4318
|
|
90
|
+
|
|
91
|
+
processors:
|
|
92
|
+
batch:
|
|
93
|
+
timeout: 30s
|
|
94
|
+
send_batch_size: 8192
|
|
95
|
+
resourcedetection:
|
|
96
|
+
detectors: [gcp]
|
|
97
|
+
timeout: 10s
|
|
98
|
+
|
|
99
|
+
exporters:
|
|
100
|
+
googlecloud:
|
|
101
|
+
project: ${projectId}
|
|
102
|
+
metric:
|
|
103
|
+
prefix: custom.googleapis.com/${clusterName}
|
|
104
|
+
trace:
|
|
105
|
+
attribute_mappings:
|
|
106
|
+
- key: service.name
|
|
107
|
+
replacement: g.co/r/service/name
|
|
108
|
+
|
|
109
|
+
service:
|
|
110
|
+
pipelines:
|
|
111
|
+
metrics:
|
|
112
|
+
receivers: [otlp]
|
|
113
|
+
processors: [batch, resourcedetection]
|
|
114
|
+
exporters: [googlecloud]
|
|
115
|
+
traces:
|
|
116
|
+
receivers: [otlp]
|
|
117
|
+
processors: [batch, resourcedetection]
|
|
118
|
+
exporters: [googlecloud]
|
|
119
|
+
`;
|
|
120
|
+
|
|
121
|
+
const container: Record<string, unknown> = {
|
|
122
|
+
name,
|
|
123
|
+
image,
|
|
124
|
+
args: ["--config=/etc/otel/config.yaml"],
|
|
125
|
+
ports: [
|
|
126
|
+
{ containerPort: 4317, name: "otlp-grpc" },
|
|
127
|
+
{ containerPort: 4318, name: "otlp-http" },
|
|
128
|
+
],
|
|
129
|
+
resources: {
|
|
130
|
+
requests: { cpu: cpuRequest, memory: memoryRequest },
|
|
131
|
+
limits: { cpu: cpuLimit, memory: memoryLimit },
|
|
132
|
+
},
|
|
133
|
+
volumeMounts: [
|
|
134
|
+
{ name: "config", mountPath: "/etc/otel", readOnly: true },
|
|
135
|
+
],
|
|
136
|
+
securityContext: {
|
|
137
|
+
runAsNonRoot: true,
|
|
138
|
+
runAsUser: 10001,
|
|
139
|
+
readOnlyRootFilesystem: true,
|
|
140
|
+
allowPrivilegeEscalation: false,
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const daemonSetProps: Record<string, unknown> = {
|
|
145
|
+
metadata: {
|
|
146
|
+
name,
|
|
147
|
+
namespace,
|
|
148
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "agent" },
|
|
149
|
+
},
|
|
150
|
+
spec: {
|
|
151
|
+
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
152
|
+
template: {
|
|
153
|
+
metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
|
|
154
|
+
spec: {
|
|
155
|
+
serviceAccountName: saName,
|
|
156
|
+
containers: [container],
|
|
157
|
+
volumes: [
|
|
158
|
+
{ name: "config", configMap: { name: configMapName } },
|
|
159
|
+
],
|
|
160
|
+
tolerations: [{ operator: "Exists" }],
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const serviceAccountProps: Record<string, unknown> = {
|
|
167
|
+
metadata: {
|
|
168
|
+
name: saName,
|
|
169
|
+
namespace,
|
|
170
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "agent" },
|
|
171
|
+
...(gcpServiceAccountEmail
|
|
172
|
+
? { annotations: { "iam.gke.io/gcp-service-account": gcpServiceAccountEmail } }
|
|
173
|
+
: {}),
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const clusterRoleProps: Record<string, unknown> = {
|
|
178
|
+
metadata: {
|
|
179
|
+
name: clusterRoleName,
|
|
180
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
181
|
+
},
|
|
182
|
+
rules: [
|
|
183
|
+
{ apiGroups: [""], resources: ["pods", "nodes", "endpoints"], verbs: ["get", "list", "watch"] },
|
|
184
|
+
{ apiGroups: ["apps"], resources: ["replicasets"], verbs: ["get", "list", "watch"] },
|
|
185
|
+
{ apiGroups: ["batch"], resources: ["jobs"], verbs: ["get", "list", "watch"] },
|
|
186
|
+
{ apiGroups: [""], resources: ["nodes/proxy"], verbs: ["get"] },
|
|
187
|
+
{ apiGroups: [""], resources: ["nodes/stats", "configmaps", "events"], verbs: ["create", "get"] },
|
|
188
|
+
{ apiGroups: [""], resources: ["configmaps"], verbs: ["get", "update", "create"], resourceNames: ["otel-container-insight-clusterleader"] },
|
|
189
|
+
],
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const clusterRoleBindingProps: Record<string, unknown> = {
|
|
193
|
+
metadata: {
|
|
194
|
+
name: bindingName,
|
|
195
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
196
|
+
},
|
|
197
|
+
roleRef: {
|
|
198
|
+
apiGroup: "rbac.authorization.k8s.io",
|
|
199
|
+
kind: "ClusterRole",
|
|
200
|
+
name: clusterRoleName,
|
|
201
|
+
},
|
|
202
|
+
subjects: [
|
|
203
|
+
{
|
|
204
|
+
kind: "ServiceAccount",
|
|
205
|
+
name: saName,
|
|
206
|
+
namespace,
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const configMapProps: Record<string, unknown> = {
|
|
212
|
+
metadata: {
|
|
213
|
+
name: configMapName,
|
|
214
|
+
namespace,
|
|
215
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "config" },
|
|
216
|
+
},
|
|
217
|
+
data: {
|
|
218
|
+
"config.yaml": otelConfig,
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
daemonSet: daemonSetProps,
|
|
224
|
+
serviceAccount: serviceAccountProps,
|
|
225
|
+
clusterRole: clusterRoleProps,
|
|
226
|
+
clusterRoleBinding: clusterRoleBindingProps,
|
|
227
|
+
configMap: configMapProps,
|
|
228
|
+
};
|
|
229
|
+
}
|
package/src/composites/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export type { ContainerSecurityContext } from "./security-context";
|
|
1
2
|
export { WebApp } from "./web-app";
|
|
2
3
|
export type { WebAppProps, WebAppResult } from "./web-app";
|
|
3
4
|
export { StatefulApp } from "./stateful-app";
|
|
@@ -40,3 +41,33 @@ export { AdotCollector } from "./adot-collector";
|
|
|
40
41
|
export type { AdotCollectorProps, AdotCollectorResult } from "./adot-collector";
|
|
41
42
|
export { MetricsServer } from "./metrics-server";
|
|
42
43
|
export type { MetricsServerProps, MetricsServerResult } from "./metrics-server";
|
|
44
|
+
export { WorkloadIdentityServiceAccount } from "./workload-identity-service-account";
|
|
45
|
+
export type { WorkloadIdentityServiceAccountProps, WorkloadIdentityServiceAccountResult } from "./workload-identity-service-account";
|
|
46
|
+
export { GcePdStorageClass } from "./gce-pd-storage-class";
|
|
47
|
+
export type { GcePdStorageClassProps, GcePdStorageClassResult } from "./gce-pd-storage-class";
|
|
48
|
+
export { FilestoreStorageClass } from "./filestore-storage-class";
|
|
49
|
+
export type { FilestoreStorageClassProps, FilestoreStorageClassResult } from "./filestore-storage-class";
|
|
50
|
+
export { GkeGateway } from "./gke-gateway";
|
|
51
|
+
export type { GkeGatewayProps, GkeGatewayResult } from "./gke-gateway";
|
|
52
|
+
export { ConfigConnectorContext } from "./config-connector-context";
|
|
53
|
+
export type { ConfigConnectorContextProps, ConfigConnectorContextResult } from "./config-connector-context";
|
|
54
|
+
export { GceIngress } from "./gce-ingress";
|
|
55
|
+
export type { GceIngressProps, GceIngressResult } from "./gce-ingress";
|
|
56
|
+
export { AgicIngress } from "./agic-ingress";
|
|
57
|
+
export type { AgicIngressProps, AgicIngressResult } from "./agic-ingress";
|
|
58
|
+
export { AzureDiskStorageClass } from "./azure-disk-storage-class";
|
|
59
|
+
export type { AzureDiskStorageClassProps, AzureDiskStorageClassResult } from "./azure-disk-storage-class";
|
|
60
|
+
export { AzureFileStorageClass } from "./azure-file-storage-class";
|
|
61
|
+
export type { AzureFileStorageClassProps, AzureFileStorageClassResult } from "./azure-file-storage-class";
|
|
62
|
+
export { AzureMonitorCollector } from "./azure-monitor-collector";
|
|
63
|
+
export type { AzureMonitorCollectorProps, AzureMonitorCollectorResult } from "./azure-monitor-collector";
|
|
64
|
+
export { WorkloadIdentityServiceAccount as AksWorkloadIdentityServiceAccount } from "./workload-identity-sa";
|
|
65
|
+
export type { WorkloadIdentityServiceAccountProps as AksWorkloadIdentityServiceAccountProps, WorkloadIdentityServiceAccountResult as AksWorkloadIdentityServiceAccountResult } from "./workload-identity-sa";
|
|
66
|
+
export { GkeFluentBitAgent } from "./gke-fluent-bit-agent";
|
|
67
|
+
export type { GkeFluentBitAgentProps, GkeFluentBitAgentResult } from "./gke-fluent-bit-agent";
|
|
68
|
+
export { GkeOtelCollector } from "./gke-otel-collector";
|
|
69
|
+
export type { GkeOtelCollectorProps, GkeOtelCollectorResult } from "./gke-otel-collector";
|
|
70
|
+
export { GkeExternalDnsAgent } from "./gke-external-dns-agent";
|
|
71
|
+
export type { GkeExternalDnsAgentProps, GkeExternalDnsAgentResult } from "./gke-external-dns-agent";
|
|
72
|
+
export { AksExternalDnsAgent } from "./aks-external-dns-agent";
|
|
73
|
+
export type { AksExternalDnsAgentProps, AksExternalDnsAgentResult } from "./aks-external-dns-agent";
|
|
@@ -147,7 +147,7 @@ export function MetricsServer(props: MetricsServerProps): MetricsServerResult {
|
|
|
147
147
|
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
148
148
|
},
|
|
149
149
|
rules: [
|
|
150
|
-
{ apiGroups: [""], resources: ["pods", "nodes", "namespaces"], verbs: ["get", "list", "watch"] },
|
|
150
|
+
{ apiGroups: [""], resources: ["pods", "nodes", "namespaces", "configmaps"], verbs: ["get", "list", "watch"] },
|
|
151
151
|
{ apiGroups: [""], resources: ["nodes/metrics", "nodes/stats"], verbs: ["get"] },
|
|
152
152
|
],
|
|
153
153
|
};
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* as raw objects that can be serialized alongside native K8s resources.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import type { ContainerSecurityContext } from "./security-context";
|
|
10
|
+
|
|
9
11
|
export interface AlertRule {
|
|
10
12
|
/** Alert name. */
|
|
11
13
|
name: string;
|
|
@@ -50,6 +52,8 @@ export interface MonitoredServiceProps {
|
|
|
50
52
|
namespace?: string;
|
|
51
53
|
/** Environment variables for the container. */
|
|
52
54
|
env?: Array<{ name: string; value: string }>;
|
|
55
|
+
/** Container security context (supports PSS restricted fields). */
|
|
56
|
+
securityContext?: ContainerSecurityContext;
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
export interface MonitoredServiceResult {
|
|
@@ -95,6 +99,7 @@ export function MonitoredService(props: MonitoredServiceProps): MonitoredService
|
|
|
95
99
|
memoryRequest = "128Mi",
|
|
96
100
|
namespace,
|
|
97
101
|
env,
|
|
102
|
+
securityContext,
|
|
98
103
|
} = props;
|
|
99
104
|
|
|
100
105
|
const commonLabels: Record<string, string> = {
|
|
@@ -132,6 +137,7 @@ export function MonitoredService(props: MonitoredServiceProps): MonitoredService
|
|
|
132
137
|
requests: { cpu: cpuRequest, memory: memoryRequest },
|
|
133
138
|
},
|
|
134
139
|
...(env && { env }),
|
|
140
|
+
...(securityContext && { securityContext }),
|
|
135
141
|
},
|
|
136
142
|
],
|
|
137
143
|
},
|