Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion .github/workflows/deploy-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ jobs:
# alerts file) plus the ServiceMonitor scrape knobs. -ignore-missing-schemas skips the
# CRDs themselves, so the guards below assert the CONTENT actually rendered.
mon_set="--set metrics.prometheusRule.enabled=true --set metrics.serviceMonitor.enabled=true --set metrics.serviceMonitor.sampleLimit=50000"
for extra in "" "--set console.enabled=true --set console.replicas=2" "$cluster_tls_set" "--set topologySpread.enabled=true" "$np_set" "$k3s_set" "$gd_set" "$mon_set"; do
# The console-UI Ingress needs BOTH console.enabled and console.ingress.enabled.
ing_set="--set console.enabled=true --set console.ingress.enabled=true --set console.ingress.className=traefik"
for extra in "" "--set console.enabled=true --set console.replicas=2" "$cluster_tls_set" "--set topologySpread.enabled=true" "$np_set" "$k3s_set" "$gd_set" "$mon_set" "$ing_set"; do
echo "::group::helm template ${extra:-(defaults)}"
# $extra must WORD-SPLIT into multiple `--set` flags, so it is
# intentionally unquoted (SC2086 does not apply here).
Expand All @@ -96,6 +98,14 @@ jobs:
# propagates -- turning a SUCCESSFUL match into a false failure. A here-string
# has no upstream writer to break.
case "$extra" in
*console.ingress.enabled=true*)
# Assert the Ingress rendered AND targets the CONSOLE Service (never the cache --
# RESP is L4 and an HTTP Ingress cannot front it).
grep -q "kind: Ingress" <<< "$rendered" \
|| { echo "ERROR: console.ingress.enabled rendered no Ingress"; exit 1; }
grep -q "name: ic-ironcache-console" <<< "$rendered" \
|| { echo "ERROR: console Ingress does not target the console Service"; exit 1; }
;;
*console.enabled=true*)
# Guard against a broken `console.enabled` gate silently rendering
# nothing (kubeconform is happy with zero console objects, so assert
Expand Down
11 changes: 4 additions & 7 deletions deploy/K8S_READINESS_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,8 @@ not stale text). The chart is production-safe for **fixed-size** clusters.
beta/default-on only from **1.30**, not 1.29), but `ct` and an **upgrade**-path test are still
missing. The chart is now 0.3.0.
- **Genuinely remaining** (each also flagged in the Section 2 table):
1. **P2-3 finish** -- the upgrade-path e2e (install -> `helm upgrade` -> re-test), the case that
catches charts which lint clean but fail to *upgrade*. In flight (#763).
2. **P2-7** a console-UI Ingress template, and **P2-8** the doc-only clarifications (incl.
pinning the busybox init image by digest).
3. **The day-2 scaling Operator** (Section 5) -- a deliberate non-goal for now; the chart + the
1. **P2-8** the doc-only clarifications (incl. pinning the busybox init image by digest).
2. **The day-2 scaling Operator** (Section 5) -- a deliberate non-goal for now; the chart + the
#392 upgrade driver cover fixed-size clusters.

---
Expand Down Expand Up @@ -113,10 +110,10 @@ not stale text). The chart is production-safe for **fixed-size** clusters.
| Prometheus alerts + Grafana dashboard | **DONE** | Dashboard auto-provisioned as a sidecar-discoverable ConfigMap (#758); alert rules shipped as a `PrometheusRule` from the same in-chart file a plain Prometheus can load (`metrics.prometheusRule.enabled`). |
| Cache-pods NetworkPolicy | **DONE** | Opt-in policy locking cluster-bus/repl to peers; client + metrics ports stay open by design (the metrics port serves the kubelet probes) (#748). Inert on flannel/k3s-default. |
| `values.schema.json` | **DONE** | draft-07: types, enums, port bounds, conditional-requires, and top-level `additionalProperties:false`; doc-only for the non-encodable rules. Negative tests in CI (#756). |
| `helm test` + `ct` (kind/k3d install) | **PARTIAL** | `helm test` PING hook + a kind **install** e2e (#759) -- which caught a real shipped preStop bug on its first run. Still missing: `ct` and, more importantly, an **upgrade** path test (the plan's P2-3 asks for install AND upgrade). |
| `helm test` + `ct` (kind/k3d install) | **DONE (via kind; `ct` not used)** | `helm test` PING hook + a kind e2e covering INSTALL and UPGRADE (#759, #763): install -> `helm test` -> `helm upgrade` (rolls the pod) -> `helm test` again, plus a live cluster-secret-preservation gate for #747 (the `lookup` branch deploy-lint can never reach). `ct` itself is not used -- the kind job covers what P2-3 asked for. #759's first run caught a real shipped preStop bug. |
| OCI chart publish + signing | **DONE** | Packaged + pushed to `ghcr.io/<owner>/charts` and keyless cosign-signed by digest on a release tag, with a clobber guard (#760). |
| `appVersion` / default `image.tag` pinned | **DONE** | `appVersion: 0.1.0` drives the tag (`image.tag | default .Chart.AppVersion`); raw manifests pinned too (#755). |
| Ingress template (console UI) | **MISSING** | Still no Ingress template (plan P2-7). RESP is L4 so the TCP path is documented in `deploy/K3S.md`, but the console UI has no templated Ingress. |
| Ingress template (console UI) | **DONE** | `console.ingress.*` renders an Ingress for the console UI only (requires `console.enabled`). RESP is L4, so the cache's TCP path stays documented in `deploy/K3S.md`. |
| k3s guidance (local-path/Traefik/servicelb/air-gap) | **DONE** | `deploy/K3S.md` + the `values-k3s.yaml` single-node overlay (#757). |

---
Expand Down
52 changes: 52 additions & 0 deletions deploy/helm/ironcache/templates/console-ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{{- /* SPDX-License-Identifier: MIT OR Apache-2.0 */ -}}
{{- if and .Values.console.enabled .Values.console.ingress.enabled }}
{{- $httpPort := int .Values.console.httpPort -}}
{{- $svc := include "ironcache.console.fullname" . -}}
# Ingress for the CONSOLE UI ONLY (plain HTTP). Requires console.enabled.
#
# It deliberately does NOT front the cache: RESP is an L4/TCP protocol, so an HTTP Ingress
# cannot proxy it. Expose the cache with the client Service (ClusterIP for in-cluster clients),
# a NodePort/LoadBalancer, or a Traefik `IngressRouteTCP` -- see deploy/K3S.md. And note a
# single L7/L4 endpoint in front of a raft cluster is NOT cluster-aware (nodes answer MOVED for
# slots they do not own), so prefer cluster-aware clients on the headless per-pod DNS.
#
# The console serves the operator UI + API: put real authentication in front of it (an
# ingress-level authn middleware and/or console.tokensSecret), and prefer TLS.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "ironcache.console.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "ironcache.console.labels" . | nindent 4 }}
{{- with .Values.console.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.console.ingress.className }}
# e.g. "traefik" on stock k3s, "nginx" elsewhere. Empty = the cluster's default IngressClass.
ingressClassName: {{ . | quote }}
{{- end }}
{{- with .Values.console.ingress.tls }}
tls:
{{- toYaml . | nindent 4 }}
{{- end }}
rules:
{{- range .Values.console.ingress.hosts }}
- {{- with .host }}
host: {{ . | quote }}
{{- end }}
http:
paths:
{{- range .paths }}
- path: {{ .path | default "/" | quote }}
pathType: {{ .pathType | default "Prefix" }}
backend:
service:
name: {{ $svc }}
port:
number: {{ $httpPort }}
{{- end }}
{{- end }}
{{- end }}
28 changes: 28 additions & 0 deletions deploy/helm/ironcache/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,34 @@
"items": {}
}
}
},
"ingress": {
"type": "object",
"description": "Optional Ingress for the console UI (plain HTTP). Cannot front the cache: RESP is L4.",
"properties": {
"enabled": {
"type": "boolean",
"description": "Render the console Ingress (requires console.enabled)."
},
"className": {
"type": "string",
"description": "IngressClass name, e.g. traefik on k3s. Empty = the cluster default."
},
"annotations": {
"type": "object",
"description": "Controller-specific annotations, passed through verbatim."
},
"hosts": {
"type": "array",
"description": "Rules: [{host, paths:[{path,pathType}]}]. host optional (catch-all).",
"items": {}
},
"tls": {
"type": "array",
"description": "Ingress TLS blocks, passed through verbatim.",
"items": {}
}
}
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions deploy/helm/ironcache/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,25 @@ console:
pullPolicy: IfNotPresent
# The single HTTP port serving /livez + /readyz + /metrics + the UI + /api/*.
httpPort: 9180
# Optional Ingress for the CONSOLE UI (plain HTTP). It does NOT and cannot front the cache:
# RESP is L4/TCP, so use the client Service / NodePort / LoadBalancer / a Traefik
# IngressRouteTCP for that (see deploy/K3S.md). Put real authn in front of this -- the console
# exposes an operator UI + API.
ingress:
enabled: false
# e.g. "traefik" on stock k3s, "nginx" elsewhere. Empty = the cluster's default IngressClass.
className: ""
# Controller-specific annotations (auth middleware, cert-manager issuer, ...).
annotations: {}
# Each entry: {host: <fqdn>, paths: [{path: /, pathType: Prefix}]}. `host` may be omitted
# for a catch-all rule; path defaults to "/" and pathType to "Prefix".
hosts:
- host: ironcache-console.local
paths:
- path: /
pathType: Prefix
# Verbatim Ingress TLS blocks, e.g. [{secretName: console-tls, hosts: [ironcache-console.local]}].
tls: []
service:
type: ClusterIP
# Seed nodes the console polls. Point at the cache client Service DNS, e.g.
Expand Down
Loading