@mark1russell7/kind 0.4.0 → 0.5.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.
@@ -87,7 +87,7 @@ type Template = "T07" | "T15" | "T18";
87
87
  /**
88
88
  * A mesh flavor is the install of Istio 1.31.3 in the cluster:
89
89
  * - `sidecar`: the profile `minimal`, istiod only. The injector puts an Envoy sidecar in each pod of a labeled namespace.
90
- * - `ambient`: the profile `ambient`, with istio-cni and ztunnel. The lab does not install it yet.
90
+ * - `ambient`: the profile `ambient`, with istio-cni and ztunnel on each node. A labeled namespace is in the ambient mesh.
91
91
  */
92
92
  type MeshFlavor = "sidecar" | "ambient";
93
93
  /** A mesh mode is the data plane of the pods of a cell: an Envoy sidecar in each pod, or ztunnel on each node. */
@@ -877,4 +877,4 @@ declare const quantileOf: (sorted: readonly number[], p: number) => number;
877
877
  declare const medianInterval: (sorted: readonly number[]) => [number, number];
878
878
  //#endregion
879
879
  export { updatesOf as $, Replica as $t, TriggerV1 as A, transitionOf as At, RunCheck as B, showBand as Bt, KindCellResult as C, rulesOf as Ct, PredictionV1 as D, sliceEmptyOf as Dt, LoadSample as E, sliceDropOf as Et, KIND_NOISE as F, REDIS as Ft, judgeKind as G, KubeletProbe as Gt, checkRun as H, Declaration as Ht, KindDecision as I, SERVER as It, propagationOf as J, MeshMode as Jt, observationAfter as K, Mesh as Kt, KindVerdict as L, bandOf as Lt, upgrade as M, HEALTH_PORT as Mt, upgradeCell as N, LOG_LABEL as Nt, RunCheckV1 as O, slicesOf as Ot, Deleted as P, PORT as Pt, unitOf as Q, Reference as Qt, LAST_SLACK as R, seconds as Rt, KindCellRecordV1 as S, restartsAt as St, KindVerdictV1 as T, signalsOf as Tt, deletionsOf as U, KindCell as Ut, RunFacts as V, Band as Vt, factsOf as W, KindRun as Wt, referenceOf as X, Prediction as Xt, propagationSource as Y, PodSettings as Yt, reusesReset as Z, RedisDeclaration as Zt, ClusterManifest as _, nodeNames as _n, outcomesOf as _t, STAGES as a, Workload as an, Request as at, FORMAT_V1 as b, recordsOf as bt, readRecord as c, KindScenario as cn, backendsAt as ct, calibrationOf as d, NodeImage as dn, deletionOf as dt, ResetReuse as en, Endpoint as et, cellsTable as f, cidrOverlap as fn, dropOf as ft, BandV1 as g, kubeProxyPatch as gn, kernelCounts as gt, timeSpread as h, kindConfig as hn, intakeOf as ht, quantileOf as i, TriggerKind as in, RecordLine as it, judge as j, CLIENT as jt, RunFactsV1 as k, stoppingOf as kt, Judged as l, KubeProxyMode as ln, byClients as lt, predictionText as m, goDuration as mn, failuresOf as mt, medianInterval as n, Template as nn, PodLine as nt, kindCellRecordSchema as o, KUBE_PROXY_MODES as on, RulesLine as ot, medianText as p, cidrRange as pn, emptyOf as pt, observationEnd as q, MeshFlavor as qt, middle as r, Trigger as rn, PropagationSource as rt, kindCellRecordV1Schema as s, KindConfig as sn, SliceLine as st, RELATIVE as t, Stack as tn, Line as tt, TimeSpread as u, NODE_IMAGES as un, byNode as ut, EnvironmentManifest as v, scenario as vn, podsAt as vt, KindCellV1 as w, signalOf as wt, KindCellRecord as x, requestsOf as xt, FORMAT as y, scenarioProblems as yn, podsOf as yt, Propagated as z, secondsOf as zt };
880
- //# sourceMappingURL=judge-DMuI3aDn.d.ts.map
880
+ //# sourceMappingURL=judge-BS9pk96o.d.ts.map
package/build/judge.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { $ as updatesOf, $t as Replica, A as TriggerV1, At as transitionOf, B as RunCheck, Bt as showBand, C as KindCellResult, Ct as rulesOf, D as PredictionV1, Dt as sliceEmptyOf, E as LoadSample, Et as sliceDropOf, F as KIND_NOISE, Ft as REDIS, G as judgeKind, Gt as KubeletProbe, H as checkRun, Ht as Declaration, I as KindDecision, It as SERVER, J as propagationOf, Jt as MeshMode, K as observationAfter, Kt as Mesh, L as KindVerdict, Lt as bandOf, M as upgrade, Mt as HEALTH_PORT, N as upgradeCell, Nt as LOG_LABEL, O as RunCheckV1, Ot as slicesOf, P as Deleted, Pt as PORT, Q as unitOf, Qt as Reference, R as LAST_SLACK, Rt as seconds, S as KindCellRecordV1, St as restartsAt, T as KindVerdictV1, Tt as signalsOf, U as deletionsOf, Ut as KindCell, V as RunFacts, Vt as Band, W as factsOf, Wt as KindRun, X as referenceOf, Xt as Prediction, Y as propagationSource, Yt as PodSettings, Z as reusesReset, Zt as RedisDeclaration, _ as ClusterManifest, _t as outcomesOf, a as STAGES, an as Workload, at as Request, b as FORMAT_V1, bt as recordsOf, c as readRecord, ct as backendsAt, d as calibrationOf, dt as deletionOf, en as ResetReuse, et as Endpoint, f as cellsTable, ft as dropOf, g as BandV1, gt as kernelCounts, h as timeSpread, ht as intakeOf, i as quantileOf, in as TriggerKind, it as RecordLine, j as judge, jt as CLIENT, k as RunFactsV1, kt as stoppingOf, l as Judged, ln as KubeProxyMode, lt as byClients, m as predictionText, mt as failuresOf, n as medianInterval, nn as Template, nt as PodLine, o as kindCellRecordSchema, ot as RulesLine, p as medianText, pt as emptyOf, q as observationEnd, qt as MeshFlavor, r as middle, rn as Trigger, rt as PropagationSource, s as kindCellRecordV1Schema, st as SliceLine, t as RELATIVE, tn as Stack, tt as Line, u as TimeSpread, ut as byNode, v as EnvironmentManifest, vt as podsAt, w as KindCellV1, wt as signalOf, x as KindCellRecord, xt as requestsOf, y as FORMAT, yt as podsOf, z as Propagated, zt as secondsOf } from "./judge-DMuI3aDn.js";
1
+ import { $ as updatesOf, $t as Replica, A as TriggerV1, At as transitionOf, B as RunCheck, Bt as showBand, C as KindCellResult, Ct as rulesOf, D as PredictionV1, Dt as sliceEmptyOf, E as LoadSample, Et as sliceDropOf, F as KIND_NOISE, Ft as REDIS, G as judgeKind, Gt as KubeletProbe, H as checkRun, Ht as Declaration, I as KindDecision, It as SERVER, J as propagationOf, Jt as MeshMode, K as observationAfter, Kt as Mesh, L as KindVerdict, Lt as bandOf, M as upgrade, Mt as HEALTH_PORT, N as upgradeCell, Nt as LOG_LABEL, O as RunCheckV1, Ot as slicesOf, P as Deleted, Pt as PORT, Q as unitOf, Qt as Reference, R as LAST_SLACK, Rt as seconds, S as KindCellRecordV1, St as restartsAt, T as KindVerdictV1, Tt as signalsOf, U as deletionsOf, Ut as KindCell, V as RunFacts, Vt as Band, W as factsOf, Wt as KindRun, X as referenceOf, Xt as Prediction, Y as propagationSource, Yt as PodSettings, Z as reusesReset, Zt as RedisDeclaration, _ as ClusterManifest, _t as outcomesOf, a as STAGES, an as Workload, at as Request, b as FORMAT_V1, bt as recordsOf, c as readRecord, ct as backendsAt, d as calibrationOf, dt as deletionOf, en as ResetReuse, et as Endpoint, f as cellsTable, ft as dropOf, g as BandV1, gt as kernelCounts, h as timeSpread, ht as intakeOf, i as quantileOf, in as TriggerKind, it as RecordLine, j as judge, jt as CLIENT, k as RunFactsV1, kt as stoppingOf, l as Judged, ln as KubeProxyMode, lt as byClients, m as predictionText, mt as failuresOf, n as medianInterval, nn as Template, nt as PodLine, o as kindCellRecordSchema, ot as RulesLine, p as medianText, pt as emptyOf, q as observationEnd, qt as MeshFlavor, r as middle, rn as Trigger, rt as PropagationSource, s as kindCellRecordV1Schema, st as SliceLine, t as RELATIVE, tn as Stack, tt as Line, u as TimeSpread, ut as byNode, v as EnvironmentManifest, vt as podsAt, w as KindCellV1, wt as signalOf, x as KindCellRecord, xt as requestsOf, y as FORMAT, yt as podsOf, z as Propagated, zt as secondsOf } from "./judge-BS9pk96o.js";
2
2
  export { type Band, type BandV1, CLIENT, type ClusterManifest, type Declaration, type Deleted, Endpoint, type EnvironmentManifest, FORMAT, FORMAT_V1, HEALTH_PORT, type Judged, KIND_NOISE, type KindCell, type KindCellRecord, type KindCellRecordV1, type KindCellResult, type KindCellV1, type KindDecision, type KindRun, type KindVerdict, type KindVerdictV1, type KubeProxyMode, type KubeletProbe, LAST_SLACK, LOG_LABEL, Line, type LoadSample, type Mesh, type MeshFlavor, type MeshMode, PORT, PodLine, type PodSettings, type Prediction, type PredictionV1, type Propagated, PropagationSource, REDIS, RELATIVE, RecordLine, type RedisDeclaration, type Reference, type Replica, Request, type ResetReuse, RulesLine, type RunCheck, type RunCheckV1, type RunFacts, type RunFactsV1, SERVER, STAGES, SliceLine, type Stack, type Template, type TimeSpread, type Trigger, type TriggerKind, type TriggerV1, type Workload, backendsAt, bandOf, byClients, byNode, calibrationOf, cellsTable, checkRun, deletionOf, deletionsOf, dropOf, emptyOf, factsOf, failuresOf, intakeOf, judge, judgeKind, kernelCounts, kindCellRecordSchema, kindCellRecordV1Schema, medianInterval, medianText, middle, observationAfter, observationEnd, outcomesOf, podsAt, podsOf, predictionText, propagationOf, propagationSource, quantileOf, readRecord, recordsOf, referenceOf, requestsOf, restartsAt, reusesReset, rulesOf, seconds, secondsOf, showBand, signalOf, signalsOf, sliceDropOf, sliceEmptyOf, slicesOf, stoppingOf, timeSpread, transitionOf, unitOf, updatesOf, upgrade, upgradeCell };
package/image/watch.mjs CHANGED
@@ -10,10 +10,16 @@
10
10
  // stamp of its arrival: evidence, not a time that a band reads. An access line of a call that
11
11
  // succeeded at its first attempt is only counted (`proxy-ok`, each second), thus the record keeps
12
12
  // the failures, the retries and the local replies.
13
+ //
14
+ // With ZTUNNEL=1, for a cell in the ambient mesh, the watcher also follows each ztunnel pod in
15
+ // istio-system. Each such pod is a line `ztunnel-pod`, not `pod`: the tracker of the cell counts only
16
+ // the pods of the cell. Each line of the log of ztunnel becomes a line `ztunnel` with the stamp of
17
+ // its arrival. Its own stamp is of the wall clock, thus it is evidence, not a time that a band reads.
13
18
  import https from "node:https";
14
19
 
15
20
  const kube = JSON.parse(process.env.KUBE ?? "{}");
16
21
  const namespaces = (process.env.NAMESPACES ?? "default").split(",");
22
+ const ztunnel = process.env.ZTUNNEL === "1";
17
23
  const now = () => Number(process.hrtime.bigint()) / 1e6;
18
24
  const server = new URL(kube.server);
19
25
  const agent = new https.Agent({
@@ -114,6 +120,9 @@ const proxyLine = (pod, text) => {
114
120
  say({ ev: "proxy", t: now(), p: pod, text: text.slice(0, 500) });
115
121
  };
116
122
 
123
+ /** the namespace of the mesh, with the ztunnel pods */
124
+ const MESH_NS = "istio-system";
125
+
117
126
  const following = new Set();
118
127
  const follow = (ns, pod, container, id) => {
119
128
  const key = `${ns}/${pod}/${container}/${id}`;
@@ -121,9 +130,11 @@ const follow = (ns, pod, container, id) => {
121
130
  following.add(key);
122
131
  stream(
123
132
  `/api/v1/namespaces/${ns}/pods/${pod}/log`,
124
- { container, follow: "true" },
133
+ // a ztunnel ran before the cell: only its lines from the start of the watcher
134
+ ns === MESH_NS ? { container, follow: "true", sinceSeconds: "5" } : { container, follow: "true" },
125
135
  (text) => {
126
- if (container === PROXY) proxyLine(pod, text);
136
+ if (ns === MESH_NS) say({ ev: "ztunnel", t: now(), p: pod, text: text.slice(0, 500) });
137
+ else if (container === PROXY) proxyLine(pod, text);
127
138
  else if (text.startsWith("{")) pending.push(`${text}\n`);
128
139
  else say({ ev: "text", t: now(), p: pod, text: text.slice(0, 500) });
129
140
  },
@@ -218,4 +229,20 @@ for (const ns of namespaces) {
218
229
  return object.metadata.resourceVersion;
219
230
  });
220
231
  }
221
- say({ ev: "watcher", what: "start", t: now(), namespaces });
232
+ if (ztunnel) {
233
+ stream(`/api/v1/namespaces/${MESH_NS}/pods`, { watch: "1", allowWatchBookmarks: "true", labelSelector: "app=ztunnel" }, (text, t) => {
234
+ const event = JSON.parse(text);
235
+ const pod = event.object;
236
+ if (event.type === "BOOKMARK") return pod?.metadata?.resourceVersion;
237
+ if (event.type === "ERROR") {
238
+ say({ ev: "watch-fail", t, path: "ztunnel pods", status: pod?.code });
239
+ return null;
240
+ }
241
+ const containers = (pod.status?.containerStatuses ?? []).map((status) => ({ n: status.name, r: status.ready, rc: status.restartCount, st: stateOf(status.state), id: status.containerID ?? null }));
242
+ say({ ev: "ztunnel-pod", t, type: event.type, name: pod.metadata.name, node: pod.spec?.nodeName ?? null, ip: pod.status?.podIP ?? null, del: pod.metadata.deletionTimestamp !== undefined, cs: containers });
243
+ if (event.type !== "DELETED")
244
+ for (const status of pod.status?.containerStatuses ?? []) if (status.state?.running && status.containerID) follow(MESH_NS, pod.metadata.name, status.name, status.containerID);
245
+ return pod.metadata.resourceVersion;
246
+ });
247
+ }
248
+ say({ ev: "watcher", what: "start", t: now(), namespaces, ztunnel });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "@mark1russell7/kind",
4
- "version": "0.4.0",
4
+ "version": "0.5.0",
5
5
  "description": "Kubernetes in Docker as a lab for connection timers: a kind cluster from a scenario, faults in the namespaces of its pods, observations on the one monotonic clock of the VM, and predictions from the ordering law. Its judge entry reads and judges a raw record without Docker.",
6
6
  "keywords": [
7
7
  "kubernetes",
@@ -64,9 +64,9 @@
64
64
  "node": ">=22.19"
65
65
  },
66
66
  "dependencies": {
67
- "@mark1russell7/harness": "^0.12.2",
67
+ "@mark1russell7/harness": "^0.12.3",
68
68
  "@mark1russell7/quantity": "^0.2.0",
69
- "@mark1russell7/service": "^0.5.8",
69
+ "@mark1russell7/service": "^0.5.9",
70
70
  "testcontainers": "12.2.0"
71
71
  },
72
72
  "peerDependencies": {