Skip to content

Commit aa63387

Browse files
feat: remove all kubectl port-forward; NodePort + SSH tunnels everywhere
The NodePort + SSH tunnel conversion had only ever covered the 5 persistent browser UIs. Apicurio was missed, and every demo plus the walkthrough still shelled out to kubectl port-forward — which is why the walkthrough's trace act failed (it port-forwarded a KEDA-scaled-to-zero gateway that KEDA reverts). - Route all host access through stable SSH tunnels via one allocation map (demos/lib/tunnels.sh: ensure_tunnel / wait_http / wake_gateway); zero executable kubectl port-forward remain - NodePort the app charts (order 30080, notification 30083, review 30086, inventory 30087) + Apicurio (30084); pin KEDA interceptor (30081), istio-ingress (30088), Tempo OTLP (30418) - Walkthrough Act 1 (trace) now wakes graphql-gateway the real way — through the KEDA HTTP interceptor (Host: graphql-gateway.capstone) — via demo-trace-flow.sh - Add Kafka UI (kafbat) as data-mesh infrastructure on tunnel :8089 so Kafka topics/messages/schemas are browsable - Harden bootstrap for a stop/start restart: wait for the CNPG webhook before applying the Postgres CR; idempotently re-pin interceptor/ingress NodePorts that the skipped Istio/KEDA tiers would otherwise miss - publish-discovery-contracts.sh sends the Host header so the SDL fetch routes through the interceptor - Delete superseded scripts/port-forward-ui.sh; update README, setup.html, docs
1 parent 301fd65 commit aa63387

48 files changed

Lines changed: 677 additions & 704 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎_docs/06-progressive-delivery-mtls.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ A couple of honest simplifications worth naming. v1 and v2 here run the *same im
3737
with an environment toggle and a different `version` label, rather than two images from
3838
two commits — that keeps the demo focused on the traffic-management mechanism rather
3939
than an image pipeline, and the Istio mechanics are identical either way. And traffic
40-
enters through the ingress gateway (port-forwarded, under the rootless-podman setup
41-
from §11) rather than from a meshed client, so no client needs to join the mesh for the
42-
canary to work.
40+
enters through the ingress gateway (reached over an SSH tunnel to its NodePort, under
41+
the rootless-podman setup from §11) rather than from a meshed client, so no client needs
42+
to join the mesh for the canary to work.
4343

4444
This was verified end to end: with the split set to 90/10, a run of 100 requests landed
4545
95 on v1 and 5 on v2; shifted to 50/50, it landed 46 on v1 and 54 on v2 — both within

‎examples/lgtm-datamesh/README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ load or idle timeouts.
215215
| Tempo | `http://localhost:3200` | Trace query API; also accessible via Grafana Explore |
216216
| Kiali | `http://localhost:20001/kiali` | |
217217
| OpenMetadata | `http://localhost:8585` | |
218+
| Apicurio | `http://localhost:8084` | Schema registry UI + API (`/apis/registry/v3`) |
219+
| Kafka UI | `http://localhost:8089` | Browse Kafka topics, messages, consumer groups, schemas |
218220

219221
```bash
220222
./scripts/tunnel-services.sh --status # check which tunnels are alive

‎examples/lgtm-datamesh/charts/capstone/charts/apicurio/templates/service.yaml‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ metadata:
77
app.kubernetes.io/name: apicurio
88
app.kubernetes.io/part-of: capstone
99
spec:
10-
type: ClusterIP
10+
type: {{ .Values.service.type | default "ClusterIP" }}
1111
selector:
1212
app.kubernetes.io/name: apicurio
1313
ports:
1414
- name: http
1515
port: {{ .Values.service.port }}
1616
targetPort: {{ .Values.service.targetPort }}
17+
{{- if and (eq (.Values.service.type | default "ClusterIP") "NodePort") .Values.service.nodePort }}
18+
nodePort: {{ .Values.service.nodePort }}
19+
{{- end }}

‎examples/lgtm-datamesh/charts/capstone/charts/apicurio/values.yaml‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@ image:
1111
tag: "3.2.4"
1212
pullPolicy: IfNotPresent
1313

14+
# Exposed as NodePort so it can be reached over the stable SSH tunnel
15+
# (scripts/tunnel-services.sh), same as the other persistent UIs — not a
16+
# kubectl port-forward, which drops when the system quiesces. nodePort 30084 /
17+
# local 8084 is the canonical Apicurio allocation from the lgtm-minikube-stack
18+
# skill (local 8084 avoids the ephemeral demo forwards that transiently use 8080).
1419
service:
20+
type: NodePort
1521
port: 8080
1622
targetPort: 8080
23+
nodePort: 30084
1724

1825
resources:
1926
requests:

‎examples/lgtm-datamesh/charts/capstone/charts/inventory-service/templates/service.yaml‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ metadata:
77
app.kubernetes.io/name: inventory-service
88
app.kubernetes.io/part-of: capstone
99
spec:
10-
type: ClusterIP
10+
type: {{ .Values.service.type | default "ClusterIP" }}
1111
selector:
1212
app.kubernetes.io/name: inventory-service
1313
ports:
1414
- name: http
1515
port: {{ .Values.service.port }}
1616
targetPort: {{ .Values.service.targetPort }}
17+
{{- if and (eq (.Values.service.type | default "ClusterIP") "NodePort") .Values.service.nodePort }}
18+
nodePort: {{ .Values.service.nodePort }}
19+
{{- end }}
1720
- name: grpc
1821
port: {{ .Values.service.grpcPort }}
1922
targetPort: {{ .Values.service.grpcPort }}

‎examples/lgtm-datamesh/charts/capstone/charts/inventory-service/values.yaml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,14 @@ image:
99
tag: v1
1010
pullPolicy: Always
1111

12+
# http exposed as NodePort so demos reach it over the stable SSH tunnel
13+
# (local 8087) instead of kubectl port-forward; gRPC stays in-cluster only.
14+
# See demos/lib/tunnels.sh for the allocation map.
1215
service:
16+
type: NodePort
1317
port: 80
1418
targetPort: 8080
19+
nodePort: 30087
1520
# gRPC (r23): InventoryService.CheckStock
1621
grpcPort: 50051
1722

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
apiVersion: v2
2+
name: kafka-ui
3+
description: Kafka UI (kafbat) for the §17 capstone — a data-mesh infrastructure console to browse Kafka topics, messages, consumer groups, and (via Apicurio ccompat) schemas.
4+
type: application
5+
version: 0.1.0
6+
appVersion: "latest"
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: kafka-ui
5+
namespace: {{ .Release.Namespace }}
6+
labels:
7+
app.kubernetes.io/name: kafka-ui
8+
app.kubernetes.io/part-of: capstone
9+
app.kubernetes.io/component: kafka-console
10+
spec:
11+
replicas: {{ .Values.replicas }}
12+
selector:
13+
matchLabels:
14+
app.kubernetes.io/name: kafka-ui
15+
template:
16+
metadata:
17+
labels:
18+
app.kubernetes.io/name: kafka-ui
19+
app.kubernetes.io/part-of: capstone
20+
annotations:
21+
# Opt out of the mesh: kafka-ui talks to the (non-meshed) Kafka bootstrap
22+
# and Apicurio; a sidecar would only complicate that. Matches the other
23+
# operator-managed infra (CAP-024 scope note in setup-istio.sh).
24+
sidecar.istio.io/inject: "false"
25+
spec:
26+
containers:
27+
- name: kafka-ui
28+
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
29+
imagePullPolicy: {{ .Values.image.pullPolicy }}
30+
ports:
31+
- name: http
32+
containerPort: {{ .Values.service.targetPort }}
33+
env:
34+
- name: KAFKA_CLUSTERS_0_NAME
35+
value: {{ .Values.kafka.clusterName | quote }}
36+
- name: KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS
37+
value: {{ .Values.kafka.bootstrapServers | quote }}
38+
- name: KAFKA_CLUSTERS_0_SCHEMAREGISTRY
39+
value: {{ .Values.kafka.schemaRegistry | quote }}
40+
- name: DYNAMIC_CONFIG_ENABLED
41+
value: "true"
42+
- name: SERVER_PORT
43+
value: {{ .Values.service.targetPort | quote }}
44+
resources:
45+
requests:
46+
cpu: {{ .Values.resources.requests.cpu }}
47+
memory: {{ .Values.resources.requests.memory }}
48+
limits:
49+
memory: {{ .Values.resources.limits.memory }}
50+
# TCP probes avoid guessing the actuator health path across kafka-ui
51+
# versions; startup budget is generous for the Spring Boot cold start.
52+
startupProbe:
53+
tcpSocket:
54+
port: http
55+
periodSeconds: 5
56+
failureThreshold: 40
57+
livenessProbe:
58+
tcpSocket:
59+
port: http
60+
periodSeconds: 10
61+
readinessProbe:
62+
tcpSocket:
63+
port: http
64+
periodSeconds: 5
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: kafka-ui
5+
namespace: {{ .Release.Namespace }}
6+
labels:
7+
app.kubernetes.io/name: kafka-ui
8+
app.kubernetes.io/part-of: capstone
9+
spec:
10+
type: {{ .Values.service.type | default "ClusterIP" }}
11+
selector:
12+
app.kubernetes.io/name: kafka-ui
13+
ports:
14+
- name: http
15+
port: {{ .Values.service.port }}
16+
targetPort: {{ .Values.service.targetPort }}
17+
{{- if and (eq (.Values.service.type | default "ClusterIP") "NodePort") .Values.service.nodePort }}
18+
nodePort: {{ .Values.service.nodePort }}
19+
{{- end }}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Kafka UI (kafbat) — a data-mesh infrastructure console for browsing Kafka
2+
# topics, messages, consumer groups, and schemas. Exposed as NodePort so it is
3+
# reached over the stable SSH tunnel (local 8089) instead of kubectl port-forward.
4+
# See demos/lib/tunnels.sh for the allocation map (nodePort 30084 apicurio,
5+
# 30089 kafka-ui, …).
6+
replicas: 1
7+
8+
image:
9+
repository: ghcr.io/kafbat/kafka-ui
10+
tag: "latest" # pin to a released tag (e.g. v1.x) for reproducible builds
11+
pullPolicy: IfNotPresent
12+
13+
kafka:
14+
clusterName: capstone-kafka
15+
bootstrapServers: capstone-kafka-kafka-bootstrap:9092
16+
# Apicurio's Confluent-compatible endpoint, so the UI renders Avro schemas too.
17+
schemaRegistry: http://apicurio:8080/apis/ccompat/v7
18+
19+
service:
20+
type: NodePort
21+
port: 8080
22+
targetPort: 8080
23+
nodePort: 30089
24+
25+
resources:
26+
requests:
27+
cpu: 100m
28+
memory: 512Mi
29+
limits:
30+
memory: 1Gi

0 commit comments

Comments
 (0)