-
Notifications
You must be signed in to change notification settings - Fork 21
/
index.ts
93 lines (80 loc) · 2.8 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
* Copyright 2024 Defense Unicorns
* SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Defense-Unicorns-Commercial
*/
import { Exec, KubeConfig } from "@kubernetes/client-node";
import { Capability, a } from "pepr";
import { Component, setupLogger } from "../logger";
// configure subproject logger
const log = setupLogger(Component.ISTIO);
export const istio = new Capability({
name: "istio",
description: "UDS Core Capability for Istio service mesh.",
});
const { When } = istio;
// Keep track of in-progress terminations
const inProgress = new Set<string>();
/**
* Watch Pods with the "batch.kubernetes.io/job-name" and "service.istio.io/canonical-name" labels
* to terminate the sidecar after the job completes successfully.
*/
When(a.Pod)
.IsCreatedOrUpdated()
.WithLabel("batch.kubernetes.io/job-name")
.WithLabel("service.istio.io/canonical-name")
.Watch(async pod => {
if (!pod.metadata?.name || !pod.metadata.namespace) {
log.error(pod, `Invalid Pod definition`);
return;
}
const { name, namespace } = pod.metadata;
const key = `${namespace}/${name}`;
// Ensure termination isn't already in progress
if (inProgress.has(key)) {
return;
}
// Only terminate if the pod is running
if (pod.status?.phase == "Running") {
// Check all container statuses
if (!pod.status.containerStatuses) {
log.error(pod, `Invalid container status in Pod`);
return;
}
const shouldTerminate = pod.status.containerStatuses
// Ignore the istio-proxy container
.filter(c => c.name != "istio-proxy")
// and if ALL are terminated AND restartPolicy is Never or is OnFailure with a 0 exit code then shouldTerminate is true
.every(
c =>
c.state?.terminated &&
(pod.spec?.restartPolicy == "Never" ||
(pod.spec?.restartPolicy == "OnFailure" && c.state.terminated.exitCode == 0)),
);
if (shouldTerminate) {
// Mark the pod as seen
inProgress.add(key);
log.info(`Attempting to terminate sidecar for ${key}`);
try {
const kc = new KubeConfig();
kc.loadFromDefault();
const exec = new Exec(kc);
await exec.exec(
namespace,
name,
"istio-proxy",
["pilot-agent", "request", "POST", "/quitquitquit"],
null, // Could capture exec stdout here
null, // Could capture exec stderr here
process.stdin,
true,
);
log.info(`Terminated sidecar for ${key}`);
} catch (err) {
log.error({ err }, `Failed to terminate the sidecar for ${key}`);
} finally {
// Remove the pod from the seen list
inProgress.delete(key);
}
}
}
});