Skip to content

Commit a4345ae

Browse files
committed
Infrastructure: CI ownership, dependabot, k8s manifests
- .github/CODEOWNERS, dependabot.yml, pull_request_template.md. - k8s/: pilot-website (deployment, service, ingress, alerts, blackbox, dashboard, probes), pilot-install-canary, pilot-probe, pilot- exporter, pilot-release, gcp-vms bootstraps.
1 parent 2474f49 commit a4345ae

37 files changed

Lines changed: 4677 additions & 0 deletions

.github/CODEOWNERS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Every PR requires review from a maintainer.
2+
# See GOVERNANCE.md for the maintainer list.
3+
4+
* @TeoSlayer @Alexgodoroja

.github/dependabot.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: gomod
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
open-pull-requests-limit: 5
8+
labels:
9+
- dependencies
10+
- go
11+
12+
- package-ecosystem: npm
13+
directory: /web
14+
schedule:
15+
interval: weekly
16+
open-pull-requests-limit: 5
17+
labels:
18+
- dependencies
19+
- web
20+
21+
- package-ecosystem: npm
22+
directory: /sdk/node
23+
schedule:
24+
interval: weekly
25+
open-pull-requests-limit: 5
26+
labels:
27+
- dependencies
28+
- sdk
29+
30+
- package-ecosystem: github-actions
31+
directory: /
32+
schedule:
33+
interval: weekly
34+
open-pull-requests-limit: 5
35+
labels:
36+
- dependencies
37+
- ci

.github/pull_request_template.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Pull Request
2+
3+
## Summary
4+
5+
<!-- One or two sentences describing the change and why. -->
6+
7+
## Changes
8+
9+
<!-- Bullet list of the concrete changes in this PR. -->
10+
11+
-
12+
13+
## Test Plan
14+
15+
- [ ] `go build ./cmd/...` succeeds
16+
- [ ] `go vet ./...` clean
17+
- [ ] Relevant tests pass (`go test -parallel 4 ./tests/ ./pkg/beacon/`)
18+
- [ ] Pre-commit hooks pass (`pre-commit run --all-files`)
19+
20+
## Checklist
21+
22+
- [ ] New code includes the SPDX license header
23+
- [ ] No secrets or credentials committed
24+
- [ ] `go.mod` / `go.sum` changes are intentional
25+
- [ ] Documentation updated if behavior changed
26+
- [ ] Linked issue or context: <!-- #issue-number -->

k8s/gcp-vms/Dockerfile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
FROM debian:12-slim
2+
3+
ARG GCLOUD_VERSION=508.0.0
4+
5+
RUN apt-get update && \
6+
apt-get install -y --no-install-recommends \
7+
ca-certificates curl bash python3 && \
8+
rm -rf /var/lib/apt/lists/*
9+
10+
RUN curl -fsSL "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-${GCLOUD_VERSION}-linux-arm.tar.gz" \
11+
-o /tmp/gcloud.tgz && \
12+
tar -xzf /tmp/gcloud.tgz -C /opt && \
13+
rm /tmp/gcloud.tgz && \
14+
/opt/google-cloud-sdk/install.sh --quiet --usage-reporting=false --path-update=false
15+
16+
ENV PATH=/opt/google-cloud-sdk/bin:$PATH

k8s/gcp-vms/build-and-load.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
# Build pilot-iap-scraper (arm64) with bundled gcloud CLI and import to every Jetson node.
3+
set -euo pipefail
4+
5+
IMAGE="${IMAGE:-pilot-iap-scraper:latest}"
6+
BASTION="${BASTION:-jetson@worker-node-2}"
7+
BASTION_PASS="${BASTION_PASS:-jetson}"
8+
AGENT_IPS=(192.168.5.65 192.168.5.61 192.168.5.66)
9+
10+
cd "$(dirname "$0")"
11+
12+
echo "==> building $IMAGE (arm64)"
13+
docker buildx build --platform linux/arm64 --load -t "$IMAGE" .
14+
15+
TAR="/tmp/${IMAGE//[:\/]/_}.tar"
16+
echo "==> saving to $TAR"
17+
docker save "$IMAGE" -o "$TAR"
18+
19+
echo "==> uploading to ${BASTION}"
20+
scp -q "$TAR" "${BASTION}:$TAR"
21+
22+
echo "==> importing on bastion"
23+
ssh "${BASTION}" "echo ${BASTION_PASS} | sudo -S k3s ctr images import $TAR"
24+
25+
for ip in "${AGENT_IPS[@]}"; do
26+
echo "==> distributing to $ip"
27+
ssh "${BASTION}" "sshpass -p ${BASTION_PASS} scp -o StrictHostKeyChecking=accept-new $TAR jetson@$ip:$TAR && \
28+
sshpass -p ${BASTION_PASS} ssh -o StrictHostKeyChecking=accept-new jetson@$ip 'echo ${BASTION_PASS} | sudo -S k3s ctr images import $TAR && rm -f $TAR'"
29+
done
30+
31+
ssh "${BASTION}" "rm -f $TAR"
32+
rm -f "$TAR"
33+
echo "done."
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
---
2+
# Cross-stack correlation dashboard. Each row puts two related signals on the same
3+
# time axis so you can eyeball causation: restart-vs-nodes, softirq-vs-retrans, etc.
4+
apiVersion: v1
5+
kind: ConfigMap
6+
metadata:
7+
name: pilot-gcp-correlation-dashboard
8+
namespace: monitoring
9+
labels: {grafana_dashboard: "1"}
10+
annotations: {grafana_folder: "Pilot GCP"}
11+
data:
12+
pilot-gcp-correlation.json: |
13+
{
14+
"title": "Pilot GCP — Correlation (how things tie together)",
15+
"uid": "pilot-gcp-correlation",
16+
"schemaVersion": 38,
17+
"timezone": "",
18+
"refresh": "30s",
19+
"time": {"from": "now-6h", "to": "now"},
20+
"tags": ["pilot", "gcp", "correlation"],
21+
"links": [
22+
{"title": "Fleet", "url": "/d/pilot-gcp-fleet", "type": "link"},
23+
{"title": "Diagnostics", "url": "/d/pilot-gcp-diagnostics", "type": "link"},
24+
{"title": "VM Explorer", "url": "/d/pilot-gcp-vm-explorer", "type": "link"}
25+
],
26+
"panels": [
27+
{"id": 1, "type": "row", "title": "Rendezvous — control-plane cascade", "collapsed": false,
28+
"gridPos": {"x": 0, "y": 0, "w": 24, "h": 1}},
29+
30+
{"id": 10, "type": "timeseries", "title": "Online nodes + restart events",
31+
"description": "Drops in online_nodes that align with restart_events = the restart caused the drop.",
32+
"gridPos": {"x": 0, "y": 1, "w": 12, "h": 8},
33+
"targets": [
34+
{"expr": "pilot_online_nodes", "refId": "A", "legendFormat": "online"},
35+
{"expr": "pilot_total_nodes", "refId": "B", "legendFormat": "total"},
36+
{"expr": "pilot_rendezvous_restart_events", "refId": "C", "legendFormat": "restart count (cumul)"}
37+
]},
38+
39+
{"id": 11, "type": "timeseries", "title": "Rendezvous CPU softirq vs request rate",
40+
"description": "Softirq time tracks packet processing. If softirq saturates but requests don't rise, we're bottlenecked on kernel networking.",
41+
"gridPos": {"x": 12, "y": 1, "w": 12, "h": 8},
42+
"targets": [
43+
{"expr": "sum(rate(node_cpu_seconds_total{vm=\"pilot-rendezvous\",mode=\"softirq\"}[5m]))", "refId": "A", "legendFormat": "softirq cores"},
44+
{"expr": "rate(pilot_total_requests[5m])", "refId": "B", "legendFormat": "req/s"}
45+
]},
46+
47+
{"id": 12, "type": "timeseries", "title": "TCP ESTABLISHED vs conntrack entries (rendezvous)",
48+
"description": "Rendezvous carries ~20k TCP. If conntrack climbs past connections, NAT/firewall churn is at play.",
49+
"gridPos": {"x": 0, "y": 9, "w": 12, "h": 8},
50+
"targets": [
51+
{"expr": "node_netstat_Tcp_CurrEstab{vm=\"pilot-rendezvous\"}", "refId": "A", "legendFormat": "TCP established"},
52+
{"expr": "node_nf_conntrack_entries{vm=\"pilot-rendezvous\"}", "refId": "B", "legendFormat": "conntrack entries"},
53+
{"expr": "node_filefd_allocated{vm=\"pilot-rendezvous\"}", "refId": "C", "legendFormat": "file descriptors"}
54+
]},
55+
56+
{"id": 13, "type": "timeseries", "title": "Rendezvous retrans + probe staleness",
57+
"description": "If retrans climbs and probe_staleness climbs together = network to rendezvous is degrading.",
58+
"gridPos": {"x": 12, "y": 9, "w": 12, "h": 8},
59+
"targets": [
60+
{"expr": "rate(node_netstat_Tcp_RetransSegs{vm=\"pilot-rendezvous\"}[5m])", "refId": "A", "legendFormat": "rendezvous retrans /s"},
61+
{"expr": "max by (probe) (pilot_probe_staleness_seconds)", "refId": "B", "legendFormat": "probe {{probe}} staleness"}
62+
]},
63+
64+
{"id": 20, "type": "row", "title": "Beacons — load-balancer symmetry", "collapsed": false,
65+
"gridPos": {"x": 0, "y": 17, "w": 24, "h": 1}},
66+
67+
{"id": 21, "type": "timeseries", "title": "UDP pps per beacon (should overlap)",
68+
"description": "Ideal: all 6 lines track together. Divergence = LB bias.",
69+
"gridPos": {"x": 0, "y": 18, "w": 12, "h": 8},
70+
"targets": [{"expr": "rate(node_netstat_Udp_InDatagrams{role=\"beacon\"}[5m])", "refId": "A", "legendFormat": "{{vm}}"}],
71+
"fieldConfig": {"defaults": {"unit": "pps"}}},
72+
73+
{"id": 22, "type": "timeseries", "title": "Network TX per beacon",
74+
"gridPos": {"x": 12, "y": 18, "w": 12, "h": 8},
75+
"targets": [{"expr": "rate(node_network_transmit_bytes_total{role=\"beacon\",device=\"ens4\"}[5m])", "refId": "A", "legendFormat": "{{vm}}"}],
76+
"fieldConfig": {"defaults": {"unit": "Bps"}}},
77+
78+
{"id": 23, "type": "bargauge", "title": "Beacon TX share now (even = 16.7%)",
79+
"description": "Normalized share of total beacon TX. Uniform bars = symmetric LB.",
80+
"gridPos": {"x": 0, "y": 26, "w": 12, "h": 6},
81+
"targets": [{"expr": "sum by (vm) (rate(node_network_transmit_bytes_total{role=\"beacon\",device=\"ens4\"}[5m])) / scalar(sum(rate(node_network_transmit_bytes_total{role=\"beacon\",device=\"ens4\"}[5m])))", "refId": "A", "legendFormat": "{{vm}}"}],
82+
"fieldConfig": {"defaults": {"unit": "percentunit", "min": 0, "max": 0.5, "thresholds": {"mode": "absolute", "steps": [{"color": "green", "value": null}, {"color": "orange", "value": 0.3}, {"color": "red", "value": 0.4}]}}},
83+
"options": {"displayMode": "basic", "orientation": "horizontal"}},
84+
85+
{"id": 24, "type": "stat", "title": "Beacon LB imbalance ratio (max/avg)",
86+
"description": "1.0 = perfect balance. >2 = one beacon taking 2x its share.",
87+
"gridPos": {"x": 12, "y": 26, "w": 6, "h": 6},
88+
"targets": [{"expr": "max(rate(node_network_transmit_bytes_total{role=\"beacon\",device=\"ens4\"}[5m])) / avg(rate(node_network_transmit_bytes_total{role=\"beacon\",device=\"ens4\"}[5m]))", "refId": "A"}],
89+
"options": {"reduceOptions": {"calcs": ["lastNotNull"]}, "colorMode": "background"},
90+
"fieldConfig": {"defaults": {"unit": "short", "decimals": 2, "thresholds": {"mode": "absolute", "steps": [{"color": "green", "value": null}, {"color": "orange", "value": 1.5}, {"color": "red", "value": 3}]}}}},
91+
92+
{"id": 25, "type": "stat", "title": "Beacon pps stddev",
93+
"description": "σ across beacons. Low = balanced.",
94+
"gridPos": {"x": 18, "y": 26, "w": 6, "h": 6},
95+
"targets": [{"expr": "stddev(rate(node_netstat_Udp_InDatagrams{role=\"beacon\"}[5m]))", "refId": "A"}],
96+
"options": {"reduceOptions": {"calcs": ["lastNotNull"]}},
97+
"fieldConfig": {"defaults": {"unit": "short", "decimals": 0}}},
98+
99+
{"id": 30, "type": "row", "title": "Agents — RTT vs reachability vs CPU", "collapsed": false,
100+
"gridPos": {"x": 0, "y": 32, "w": 24, "h": 1}},
101+
102+
{"id": 31, "type": "timeseries", "title": "Probe RTT vs agent CPU",
103+
"description": "If RTT climbs when probe's agent CPU saturates, agent is the bottleneck, not the network.",
104+
"gridPos": {"x": 0, "y": 33, "w": 12, "h": 8},
105+
"targets": [
106+
{"expr": "pilot_probe_rtt_ms", "refId": "A", "legendFormat": "RTT {{agent}} ms"},
107+
{"expr": "100 - avg by (vm) (rate(node_cpu_seconds_total{vm=~\".*agent.*\",mode=\"idle\"}[5m])) * 100", "refId": "B", "legendFormat": "{{vm}} cpu%"}
108+
]},
109+
110+
{"id": 32, "type": "timeseries", "title": "Probe reachability by cmd",
111+
"description": "Per-command reachability to the probe's agent. Drops = specific cmd broken.",
112+
"gridPos": {"x": 12, "y": 33, "w": 12, "h": 8},
113+
"targets": [{"expr": "pilot_probe_reachable", "refId": "A", "legendFormat": "{{agent}} / {{cmd}}"}],
114+
"fieldConfig": {"defaults": {"unit": "short", "min": 0, "max": 1}}},
115+
116+
{"id": 33, "type": "timeseries", "title": "NAT agents — TCP retrans (path health signal)",
117+
"description": "All 3 NAT agents have high baseline retrans (~800/s). Spikes above baseline = path degradation to peers.",
118+
"gridPos": {"x": 0, "y": 41, "w": 12, "h": 7},
119+
"targets": [{"expr": "rate(node_netstat_Tcp_RetransSegs{role=\"nat-agent\"}[5m])", "refId": "A", "legendFormat": "{{vm}}"}]},
120+
121+
{"id": 34, "type": "timeseries", "title": "NAT agents — TIME_WAIT (conn churn)",
122+
"description": "NAT agents churn ~2500 TW each. Climbing unbounded = outbound connections not closing cleanly.",
123+
"gridPos": {"x": 12, "y": 41, "w": 12, "h": 7},
124+
"targets": [{"expr": "node_sockstat_TCP_tw{role=\"nat-agent\"}", "refId": "A", "legendFormat": "{{vm}}"}]},
125+
126+
{"id": 40, "type": "row", "title": "Swarm — identity spoof footprint", "collapsed": false,
127+
"gridPos": {"x": 0, "y": 48, "w": 24, "h": 1}},
128+
129+
{"id": 41, "type": "timeseries", "title": "UDP sockets + file descriptors (swarm-1)",
130+
"description": "Each spoofed identity opens a UDP socket + file descriptors. Fleet size proxy.",
131+
"gridPos": {"x": 0, "y": 49, "w": 12, "h": 7},
132+
"targets": [
133+
{"expr": "node_sockstat_UDP_inuse{vm=~\"pilot-swarm-.*\"}", "refId": "A", "legendFormat": "{{vm}} UDP sockets"},
134+
{"expr": "node_filefd_allocated{vm=~\"pilot-swarm-.*\"}", "refId": "B", "legendFormat": "{{vm}} fds"}
135+
]},
136+
137+
{"id": 42, "type": "timeseries", "title": "Context switches + TCP established (swarm)",
138+
"description": "High context switches = traffic-generating goroutines active. TCP establish = connections they have open.",
139+
"gridPos": {"x": 12, "y": 49, "w": 12, "h": 7},
140+
"targets": [
141+
{"expr": "rate(node_context_switches_total{vm=~\"pilot-swarm-.*\"}[5m])", "refId": "A", "legendFormat": "{{vm}} ctxsw /s"},
142+
{"expr": "node_netstat_Tcp_CurrEstab{vm=~\"pilot-swarm-.*\"}", "refId": "B", "legendFormat": "{{vm}} TCP est"}
143+
]},
144+
145+
{"id": 50, "type": "row", "title": "Probe — agent path health over time", "collapsed": false,
146+
"gridPos": {"x": 0, "y": 56, "w": 24, "h": 1}},
147+
148+
{"id": 51, "type": "timeseries", "title": "Bench throughput vs RTT",
149+
"description": "Throughput should scale inversely with RTT (BDP). If both bad = congested link; just RTT bad = queue delay.",
150+
"gridPos": {"x": 0, "y": 57, "w": 12, "h": 7},
151+
"targets": [
152+
{"expr": "pilot_probe_bench_mbps * 100", "refId": "A", "legendFormat": "{{agent}} mbps×100"},
153+
{"expr": "pilot_probe_rtt_ms", "refId": "B", "legendFormat": "{{agent}} RTT ms"}
154+
]},
155+
156+
{"id": 52, "type": "timeseries", "title": "Probe iteration + error rate",
157+
"description": "Iterations /s = probe cadence. Errors /s = cmd failures. Ratio = error %.",
158+
"gridPos": {"x": 12, "y": 57, "w": 12, "h": 7},
159+
"targets": [
160+
{"expr": "rate(pilot_probe_iterations_total[5m])", "refId": "A", "legendFormat": "iterations /s"},
161+
{"expr": "rate(pilot_probe_errors_total[5m])", "refId": "B", "legendFormat": "errors /s"}
162+
]},
163+
164+
{"id": 53, "type": "timeseries", "title": "Ping loss ratio + cmd duration",
165+
"description": "Packet loss with normal duration = lossy wifi. Loss with long duration = stalling.",
166+
"gridPos": {"x": 0, "y": 64, "w": 12, "h": 7},
167+
"targets": [
168+
{"expr": "pilot_probe_ping_loss_ratio", "refId": "A", "legendFormat": "{{agent}} loss"},
169+
{"expr": "pilot_probe_cmd_duration_seconds", "refId": "B", "legendFormat": "{{agent}}/{{cmd}} dur"}
170+
]},
171+
172+
{"id": 54, "type": "timeseries", "title": "Daemon version age (auto-updater health)",
173+
"description": "Age since probe daemon was built. Climbing without resets = auto-updater not updating.",
174+
"gridPos": {"x": 12, "y": 64, "w": 12, "h": 7},
175+
"targets": [
176+
{"expr": "pilot_probe_version_age_seconds", "refId": "A", "legendFormat": "age (s)"},
177+
{"expr": "pilot_probe_version_matches_github", "refId": "B", "legendFormat": "matches github"}
178+
]},
179+
180+
{"id": 60, "type": "row", "title": "Scriptorium — disk/inode vs activity", "collapsed": false,
181+
"gridPos": {"x": 0, "y": 71, "w": 24, "h": 1}},
182+
183+
{"id": 61, "type": "timeseries", "title": "Inodes free + disk write rate (scriptorium)",
184+
"description": "Dropping inodes with sustained write rate = inbox accumulation. Cron at 00:00 should recover.",
185+
"gridPos": {"x": 0, "y": 72, "w": 12, "h": 7},
186+
"targets": [
187+
{"expr": "node_filesystem_files_free{vm=\"scriptorium-server\",mountpoint=\"/\"}", "refId": "A", "legendFormat": "inodes free"},
188+
{"expr": "sum(rate(node_disk_written_bytes_total{vm=\"scriptorium-server\"}[5m]))", "refId": "B", "legendFormat": "write B/s"}
189+
]},
190+
191+
{"id": 62, "type": "timeseries", "title": "Scriptorium TCP + UDP traffic",
192+
"description": "Correlate traffic spikes with inbox growth.",
193+
"gridPos": {"x": 12, "y": 72, "w": 12, "h": 7},
194+
"targets": [
195+
{"expr": "node_netstat_Tcp_CurrEstab{vm=\"scriptorium-server\"}", "refId": "A", "legendFormat": "TCP est"},
196+
{"expr": "rate(node_netstat_Udp_InDatagrams{vm=\"scriptorium-server\"}[5m])", "refId": "B", "legendFormat": "UDP in /s"}
197+
]}
198+
]
199+
}

0 commit comments

Comments
 (0)