Skip to content

Commit 7fe0eea

Browse files
ELaresELaresclaude
authored
feat: console packaging: image + Helm/k8s/compose + deploy-lint CI (#363) (#489)
* feat: console packaging: image + Helm/k8s/compose artifacts + deploy-lint CI (#363) Ships the reference PACKAGING for the stateless console, and the CI gate that validates it (no docker/helm/kubectl was available locally, so the lint job is the validation oracle -- the same CI-as-oracle pattern as the redis differential test). - Dockerfile.console: the SAME static-musl, distroless/nonroot recipe as the cache Dockerfile, staging `ironcache-console` (no data VOLUME; sets IRONCACHE_CONSOLE_HTTP_ADDR=0.0.0.0:9180 so a kubelet/LB probe can reach the otherwise-loopback listener; CMD ["run"]). - Helm: an OPTIONAL stateless console (console.enabled, default off) rendering a Deployment + Service + (2+ replicas) PodDisruptionBudget, with a `console:` values block and console.* label/selector helpers (component=console, so the Deployment selector never collides with the StatefulSet's). Chart 0.1.0 -> 0.2.0. - deploy/k8s/ironcache-console.yaml: the same as raw manifests (Secret + Deployment + Service + PDB). - deploy/compose/docker-compose.console.yml + config/console-nginx.conf: two stateless replicas behind an nginx LB, as an overlay onto a cache compose file. - .github/workflows/deploy-lint.yml: a NEW gate that runs on any PR touching deploy/** or a Dockerfile -- `helm lint` + `kubeconform` on the rendered chart (defaults AND console.enabled=true), `kubeconform` on the raw manifests, `hadolint` on both Dockerfiles, and `docker compose config` on the compose files. It also guards the EXISTING server manifests from drift. All console manifests are stateless (no PVC/identity/headless service), match the server's securityContext/anti-affinity/probe conventions, and wire the console's real interface (port 9180; /livez + /readyz; IRONCACHE_CONSOLE_SEEDS / _PROMETHEUS_URL / _NODE_USER / _NODE_PASSWORD_FILE / _READ_TOKEN). DEPLOY.md documents deploying the console in each form. NOTE: the release.yml/image.yml entry that actually BUILDS + publishes the console image is tag-triggered (not PR-CI-validatable), so it is a deliberate follow-up. 🤖 Generated with Claude Code Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: ELares <zeke@butlr.io> * ci: pass a placeholder cluster secret to the compose lint step (#363) `docker compose config` fails on docker-compose.cluster.yml because its ${IRONCACHE_CLUSTER_SECRET:?} is a fail-fast required var; deploy-lint checks file STRUCTURE not real secrets, so set a placeholder in the step env. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: ELares <zeke@butlr.io> * fix: give the console a distinct app name to end the cache selector collision (#363) Two independent adversarial reviews found the same real defect: the cache-side Service / PDB / ServiceMonitor / StatefulSet selectors are `{name, instance}` only, and the console pods carried `{name, instance, ..., component=console}` -- a SUPERSET -- so the cache selectors ALSO matched the console pods. Worst case: the cache PDB (which selects pods with no port filter) formed a cross-controller disruption budget spanning the StatefulSet AND the console Deployment, which can corrupt eviction accounting and block a cache node drain; the cache Services were saved only incidentally by a named-port mismatch. (Both reviews also confirmed the opposite, more-worrying axis is fine: the console does ZERO runtime filesystem writes -- the only fs writes are in #[cfg(test)] -- so readOnlyRootFilesystem:true with no writable volume is correct and needs no emptyDir /tmp.) Fix: the console now uses a DISTINCT `app.kubernetes.io/name` (`<name>-console`) instead of the cache's `<name>`, so its labels are no longer a superset of the cache selector and the cache selectors cannot match console pods -- in EVERY direction (PDB, Services, ServiceMonitor, StatefulSet). This is done entirely on the console side, so it does NOT change (and break) the cache's immutable StatefulSet selector, keeping `helm upgrade` from 0.1.0 clean. Applied in both the Helm console helpers and the raw ironcache-console.yaml. Also hardened deploy-lint: the helm-template job now asserts that `console.enabled=true` actually RENDERS the console resources (kubeconform is happy with zero objects, so a future broken `console.enabled` gate would otherwise pass green). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: ELares <zeke@butlr.io> --------- Signed-off-by: ELares <zeke@butlr.io> Co-authored-by: ELares <zeke@butlr.io> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 720a468 commit 7fe0eea

13 files changed

Lines changed: 798 additions & 7 deletions

File tree

.github/workflows/deploy-lint.yml

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# SPDX-License-Identifier: MIT OR Apache-2.0
2+
#
3+
# Deploy-artifact lint gate (#363). The repo ships production deployment artifacts
4+
# (the Helm chart, the raw k8s manifests, the docker-compose files, the two
5+
# Dockerfiles) that no other workflow validates: image.yml only runs on `v*` tags,
6+
# and rust.yml lints Rust, not YAML. This gate lints them on every PR that TOUCHES
7+
# them (the `paths:` filter), so a malformed chart / manifest / Dockerfile is caught
8+
# before it ships rather than when an operator first applies it.
9+
#
10+
# It renders the chart (default AND with the console enabled) and validates the
11+
# output against the Kubernetes schemas, validates the raw manifests the same way,
12+
# and hadolints both Dockerfiles. Third-party actions are tag-pinned to match the
13+
# CI-workflow convention (rust.yml / docs.yml use `@v4`-style tags; the release/
14+
# image workflows use SHA pins).
15+
name: deploy-lint
16+
17+
on:
18+
push:
19+
branches: [main]
20+
pull_request:
21+
paths:
22+
- "deploy/**"
23+
- "Dockerfile"
24+
- "Dockerfile.console"
25+
- ".github/workflows/deploy-lint.yml"
26+
27+
permissions:
28+
contents: read
29+
30+
env:
31+
# Validate against a recent stable Kubernetes API surface.
32+
KUBE_VERSION: "1.30.0"
33+
KUBECONFORM_VERSION: "0.6.7"
34+
HELM_VERSION: "v3.15.4"
35+
36+
jobs:
37+
helm:
38+
name: helm lint + kubeconform (rendered chart)
39+
runs-on: ubuntu-latest
40+
timeout-minutes: 10
41+
steps:
42+
- uses: actions/checkout@v4
43+
- uses: azure/setup-helm@v4
44+
with:
45+
version: ${{ env.HELM_VERSION }}
46+
- name: helm lint (defaults + console enabled)
47+
run: |
48+
set -euo pipefail
49+
helm lint deploy/helm/ironcache
50+
helm lint deploy/helm/ironcache \
51+
--set console.enabled=true --set console.replicas=2
52+
- name: Install kubeconform
53+
run: |
54+
set -euo pipefail
55+
curl -fsSL \
56+
"https://github.com/yannh/kubeconform/releases/download/v${KUBECONFORM_VERSION}/kubeconform-linux-amd64.tar.gz" \
57+
| tar -xz kubeconform
58+
sudo install -m 0755 kubeconform /usr/local/bin/kubeconform
59+
kubeconform -v
60+
- name: helm template | kubeconform (both value sets)
61+
run: |
62+
set -euo pipefail
63+
# -ignore-missing-schemas skips CRDs (ServiceMonitor) that have no core
64+
# schema; -strict rejects unknown fields in the core resources.
65+
for extra in "" "--set console.enabled=true --set console.replicas=2"; do
66+
echo "::group::helm template ${extra:-(defaults)}"
67+
rendered="$(helm template ic deploy/helm/ironcache $extra)"
68+
printf '%s\n' "$rendered" \
69+
| kubeconform -strict -summary -verbose \
70+
-ignore-missing-schemas \
71+
-kubernetes-version "${KUBE_VERSION}"
72+
if [ -n "$extra" ]; then
73+
# Guard against a broken `console.enabled` gate silently rendering
74+
# nothing (kubeconform is happy with zero console objects, so assert
75+
# the console Deployment/Service actually appeared).
76+
printf '%s\n' "$rendered" | grep -q "ic-ironcache-console" \
77+
|| { echo "ERROR: console.enabled=true rendered no console resources"; exit 1; }
78+
fi
79+
echo "::endgroup::"
80+
done
81+
82+
k8s:
83+
name: kubeconform (raw manifests)
84+
runs-on: ubuntu-latest
85+
timeout-minutes: 10
86+
steps:
87+
- uses: actions/checkout@v4
88+
- name: Install kubeconform
89+
run: |
90+
set -euo pipefail
91+
curl -fsSL \
92+
"https://github.com/yannh/kubeconform/releases/download/v${KUBECONFORM_VERSION}/kubeconform-linux-amd64.tar.gz" \
93+
| tar -xz kubeconform
94+
sudo install -m 0755 kubeconform /usr/local/bin/kubeconform
95+
- name: kubeconform deploy/k8s
96+
run: |
97+
set -euo pipefail
98+
kubeconform -strict -summary -verbose \
99+
-ignore-missing-schemas \
100+
-kubernetes-version "${KUBE_VERSION}" \
101+
deploy/k8s/*.yaml
102+
103+
docker:
104+
name: hadolint (Dockerfiles)
105+
runs-on: ubuntu-latest
106+
timeout-minutes: 10
107+
steps:
108+
- uses: actions/checkout@v4
109+
- name: hadolint Dockerfile
110+
uses: hadolint/hadolint-action@v3.1.0
111+
with:
112+
dockerfile: Dockerfile
113+
- name: hadolint Dockerfile.console
114+
uses: hadolint/hadolint-action@v3.1.0
115+
with:
116+
dockerfile: Dockerfile.console
117+
118+
compose:
119+
name: docker compose config (validate)
120+
runs-on: ubuntu-latest
121+
timeout-minutes: 10
122+
steps:
123+
- uses: actions/checkout@v4
124+
- name: Validate every compose file parses + resolves
125+
env:
126+
# The cluster compose uses a fail-fast required var (${IRONCACHE_CLUSTER_SECRET:?});
127+
# deploy-lint only checks the file STRUCTURE, not real secrets, so a
128+
# placeholder lets `config` interpolate. Add more here if a compose file
129+
# introduces another required var.
130+
IRONCACHE_CLUSTER_SECRET: deploy-lint-placeholder
131+
run: |
132+
set -euo pipefail
133+
for f in deploy/compose/docker-compose*.yml; do
134+
echo "::group::docker compose -f $f config"
135+
# `config` fully parses + interpolates + schema-checks the file; -q
136+
# suppresses the rendered output, leaving only errors.
137+
docker compose -f "$f" config -q
138+
echo "::endgroup::"
139+
done

CHANGELOG.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,16 @@ release.
169169
a different `/api/timeseries` window (the fix is a shared `prometheus_url`); the console is otherwise
170170
already stateless (header-token auth, independently-polled topology, per-replica `/livez` + `/readyz`
171171
probes) and safe to run as N replicas behind an LB. DEPLOY.md documents the stateless-behind-a-load-
172-
balancer HA topology. The reference container image + Helm/k8s manifests are tracked follow-up
173-
packaging work under #363.
172+
balancer HA topology.
173+
- Console packaging (issue #363): a container image (`Dockerfile.console`, the same static-musl,
174+
distroless/nonroot recipe as the cache image) plus reference deployment artifacts for the stateless
175+
console: an optional Helm Deployment + Service + PDB (`console.enabled=true`), a raw
176+
`deploy/k8s/ironcache-console.yaml`, and a `deploy/compose/docker-compose.console.yml` overlay (two
177+
replicas behind an nginx LB). A new `deploy-lint` CI workflow validates all of it on every PR that
178+
touches it (`helm lint` + `kubeconform` on the rendered chart and raw manifests, `hadolint` on both
179+
Dockerfiles, `docker compose config` on the compose files), so the manifests cannot silently rot.
180+
DEPLOY.md documents deploying the console in each form. (The tag-triggered release/image-publish
181+
entry that BUILDS the console image is a tracked follow-up.)
174182
- Reference least-privilege console aclfile (issue #367): `deploy/aclfile.console.example` ships two
175183
scoped IronCache ACL users the console authenticates as when it dials nodes: `console_monitor`
176184
(read-only, exactly the poll loop's PING/INFO/CLIENT LIST, no key access, no mutation) and

DEPLOY.md

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,20 @@
33

44
This guide covers the production deployment artifacts that ship in this repo:
55

6-
- A multi-stage, non-root container image (`Dockerfile`), published to GHCR by
6+
- Two multi-stage, non-root container images (`Dockerfile` for the cache,
7+
`Dockerfile.console` for the console), published to GHCR by
78
`.github/workflows/image.yml`.
8-
- `deploy/compose/` -- single-node and 3-node Raft cluster docker-compose files.
9-
- `deploy/helm/ironcache/` -- a Helm chart deploying a StatefulSet.
10-
- `deploy/k8s/` -- the same StatefulSet as raw, Helm-free YAML.
9+
- `deploy/compose/` -- single-node and 3-node Raft cluster docker-compose files,
10+
plus `docker-compose.console.yml` (two stateless console replicas behind an LB).
11+
- `deploy/helm/ironcache/` -- a Helm chart deploying the cache StatefulSet and an
12+
optional stateless console Deployment (`console.enabled=true`).
13+
- `deploy/k8s/` -- the same StatefulSet as raw, Helm-free YAML, plus
14+
`ironcache-console.yaml` (the console Deployment + Service).
15+
16+
The deploy artifacts are lint-gated on every PR that touches them
17+
(`.github/workflows/deploy-lint.yml`: `helm lint` + `kubeconform` on the rendered
18+
chart and the raw manifests, `hadolint` on both Dockerfiles, `docker compose
19+
config` on the compose files).
1120

1221
It maps every knob to the REAL config key, explains the ports, and is honest
1322
about what was validated offline versus what needs a live cluster to confirm.
@@ -204,6 +213,28 @@ kubectl create namespace ironcache
204213
kubectl -n ironcache apply -f deploy/k8s/ironcache.yaml
205214
```
206215

216+
### The console (optional, stateless)
217+
218+
The monitoring/management console (epic #352) is a SEPARATE, stateless workload,
219+
off by default. It is a Deployment of N identical replicas behind a Service (no
220+
PVC, no per-pod identity), so it scales horizontally and any replica serves any
221+
request; see "Console HA" under section 7 for the statelessness details.
222+
223+
- **Helm:** enable it in the same release with `--set console.enabled=true`
224+
(tune `console.replicas`, `console.seeds`, `console.prometheusUrl`, and the
225+
`console.nodePasswordSecret` / `console.tokensSecret` references). It renders a
226+
Deployment + Service + (at 2+ replicas) a PodDisruptionBudget.
227+
- **Raw manifests:** `kubectl -n ironcache apply -f deploy/k8s/ironcache-console.yaml`
228+
(edit the Secret placeholders + the seeds/Prometheus env first).
229+
- **docker-compose:** overlay `docker-compose.console.yml` (two replicas + an nginx
230+
LB) onto a cache compose file.
231+
232+
In every form: point the console at the cache client Service/nodes
233+
(`IRONCACHE_CONSOLE_SEEDS`), a SHARED Prometheus for consistent history
234+
(`IRONCACHE_CONSOLE_PROMETHEUS_URL`), and the least-privilege node user
235+
(`console_monitor`, section 6); set a read token so the privileged API is not open;
236+
and keep the console Service behind a VPN-locked LB (#369).
237+
207238
---
208239

209240
## 6. Enabling auth and TLS

Dockerfile.console

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# SPDX-License-Identifier: MIT OR Apache-2.0
2+
#
3+
# Production container image for the IronCache CONSOLE (epic #352, issue #363).
4+
#
5+
# The console is a SEPARATE, STATELESS monitoring/management server from the
6+
# `ironcache` data-plane binary; it discovers a deployment, aggregates a
7+
# cluster-wide view, and serves a dashboard + `/api/*`, staying OUT of the client
8+
# data path. This image mirrors the server image (Dockerfile): it STAGES the SAME
9+
# fully-static musl `ironcache-console` binary the release pipeline builds (the
10+
# `*-unknown-linux-musl` targets, `crt-static`, no libc dependency) onto a minimal,
11+
# nonroot, distroless runtime. There is no Rust toolchain in either stage, so the
12+
# final image is tiny and cannot drift from the released, attested artifact. The
13+
# dashboard assets (HTML/CSS/JS/fonts) are compiled INTO the binary (include_str!/
14+
# include_bytes!), so nothing else needs staging. Unlike the server image there is
15+
# NO data VOLUME (the console holds no durable state).
16+
#
17+
# Local / manual multi-arch build (after the release tarballs are unpacked under
18+
# dist/, see .github/workflows/image.yml for the exact layout):
19+
# docker buildx build --platform linux/amd64,linux/arm64 \
20+
# -f Dockerfile.console -t ghcr.io/elares/ironcache-console:dev --load .
21+
#
22+
# Port:
23+
# 9180 the single HTTP listener: /livez + /readyz + /metrics + the UI + /api/*
24+
# (IRONCACHE_CONSOLE_HTTP_ADDR). It defaults to loopback, so this image
25+
# sets it to 0.0.0.0:9180 below or a kubelet/LB probe could not reach it.
26+
27+
# --- stage: take the prebuilt static musl binary for the target arch ----------
28+
# `alpine` is a throwaway staging filesystem to chmod the binary; it never reaches
29+
# the final image. TARGETARCH (amd64 | arm64) is set by buildx, so one Dockerfile
30+
# serves both arches.
31+
FROM alpine:3 AS stage
32+
ARG TARGETARCH
33+
WORKDIR /stage
34+
# dist/amd64/ironcache-console and dist/arm64/ironcache-console are the fully-static
35+
# musl binaries unpacked from the release tarballs by the image-publish CI.
36+
COPY dist/${TARGETARCH}/ironcache-console /stage/ironcache-console
37+
RUN chmod 0755 /stage/ironcache-console
38+
39+
# --- final: distroless static, nonroot, least-privilege -----------------------
40+
# gcr.io/distroless/static:nonroot ships CA certs + a nonroot user (uid/gid 65532)
41+
# and NOTHING else (no shell, no package manager, no libc): the minimal, secure
42+
# runtime for a static binary.
43+
FROM gcr.io/distroless/static:nonroot
44+
45+
# OCI image metadata. The version label is overwritten at build time by the CI
46+
# `--label org.opencontainers.image.version=<tag>`.
47+
LABEL org.opencontainers.image.title="ironcache-console"
48+
LABEL org.opencontainers.image.description="The IronCache monitoring + management console (stateless)."
49+
LABEL org.opencontainers.image.source="https://github.com/ELares/IronCache"
50+
LABEL org.opencontainers.image.licenses="MIT OR Apache-2.0"
51+
52+
COPY --from=stage /stage/ironcache-console /usr/local/bin/ironcache-console
53+
54+
# Run as the distroless nonroot user (uid 65532), never root. The console needs no
55+
# writable filesystem (stateless), so it pairs with readOnlyRootFilesystem: true.
56+
USER 65532:65532
57+
58+
# Document the single HTTP port (EXPOSE is metadata only; it does not publish).
59+
EXPOSE 9180
60+
61+
# Bind all interfaces so a kubelet probe / load balancer can reach the listener
62+
# (the binary defaults to loopback 127.0.0.1:9180, which is unreachable in a
63+
# container). Mirrors how the server image sets IRONCACHE_DATA_DIR. Override any
64+
# other knob via IRONCACHE_CONSOLE_* env vars or a mounted TOML.
65+
ENV IRONCACHE_CONSOLE_HTTP_ADDR=0.0.0.0:9180
66+
67+
ENTRYPOINT ["/usr/local/bin/ironcache-console"]
68+
CMD ["run"]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# SPDX-License-Identifier: MIT OR Apache-2.0
2+
#
3+
# nginx reverse proxy / load balancer in front of the two stateless IronCache
4+
# console replicas (deploy/compose/docker-compose.console.yml, issue #363). Any
5+
# request may go to either replica (the console is stateless), and nginx marks a
6+
# replica down + retries the other on a connection error, so a dead replica is
7+
# transparently routed around. This is the HTTP health surface for the compose
8+
# topology (the distroless console image has no curl for a container healthcheck).
9+
10+
upstream ironcache_console {
11+
server console-1:9180 max_fails=3 fail_timeout=10s;
12+
server console-2:9180 max_fails=3 fail_timeout=10s;
13+
}
14+
15+
server {
16+
listen 9180;
17+
18+
location / {
19+
proxy_pass http://ironcache_console;
20+
proxy_set_header Host $host;
21+
proxy_set_header X-Real-IP $remote_addr;
22+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
23+
proxy_set_header X-Forwarded-Proto $scheme;
24+
# Retry the other replica on a connection-level failure (a dead pod), so a
25+
# single replica loss is invisible to the client.
26+
proxy_next_upstream error timeout http_502 http_503 http_504;
27+
proxy_connect_timeout 2s;
28+
}
29+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# SPDX-License-Identifier: MIT OR Apache-2.0
2+
#
3+
# The IronCache CONSOLE as TWO stateless replicas behind an nginx load balancer
4+
# (epic #352, issue #363). This is an OVERLAY: run it alongside a cache (the
5+
# single-node docker-compose.yml or the 3-node docker-compose.cluster.yml), e.g.
6+
#
7+
# docker compose \
8+
# -f docker-compose.cluster.yml \
9+
# -f docker-compose.console.yml up -d
10+
# curl localhost:9180/readyz # served by whichever replica the LB picks
11+
#
12+
# The two replicas are IDENTICAL and stateless (Bearer-header auth, per-replica
13+
# derived topology, per-replica readiness), so the LB can route any request to
14+
# either and transparently drop a dead one. History is kept consistent by pointing
15+
# every replica at ONE shared Prometheus (IRONCACHE_CONSOLE_PROMETHEUS_URL); leave
16+
# it unset only for a single replica. Set IRONCACHE_CONSOLE_SEEDS to the cache
17+
# node(s) and IRONCACHE_CONSOLE_READ_TOKEN to gate the privileged API.
18+
#
19+
# Note: the console image is distroless (no shell/curl), so there is no per-container
20+
# HTTP healthcheck; the nginx LB is the HTTP health surface (it proxies /readyz).
21+
22+
name: ironcache-console
23+
24+
# The common console replica config (both replicas are identical).
25+
x-console: &console
26+
image: ghcr.io/elares/ironcache-console:latest
27+
command: [run]
28+
environment:
29+
IRONCACHE_CONSOLE_HTTP_ADDR: 0.0.0.0:9180
30+
# Point at the cache node(s). Defaults to the single-node compose service name.
31+
IRONCACHE_CONSOLE_SEEDS: ${IRONCACHE_CONSOLE_SEEDS:-ironcache:6379}
32+
# A SHARED Prometheus keeps history consistent across the two replicas.
33+
IRONCACHE_CONSOLE_PROMETHEUS_URL: ${IRONCACHE_CONSOLE_PROMETHEUS_URL:-}
34+
# Dial nodes as the least-privilege user (deploy/aclfile.console.example).
35+
IRONCACHE_CONSOLE_NODE_USER: ${IRONCACHE_CONSOLE_NODE_USER:-console_monitor}
36+
IRONCACHE_CONSOLE_NODE_PASSWORD_FILE: ${IRONCACHE_CONSOLE_NODE_PASSWORD_FILE:-}
37+
# Set a read token so the privileged API is not open behind the LB.
38+
IRONCACHE_CONSOLE_READ_TOKEN: ${IRONCACHE_CONSOLE_READ_TOKEN:-}
39+
restart: unless-stopped
40+
41+
services:
42+
console-1:
43+
<<: *console
44+
console-2:
45+
<<: *console
46+
console-lb:
47+
image: nginx:1.27-alpine
48+
ports:
49+
- "9180:9180"
50+
volumes:
51+
- ./config/console-nginx.conf:/etc/nginx/conf.d/default.conf:ro
52+
depends_on:
53+
- console-1
54+
- console-2
55+
restart: unless-stopped

deploy/helm/ironcache/Chart.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ description: >-
88
preserves Raft quorum.
99
type: application
1010
# The chart version. Bump on chart changes (independent of the app version).
11-
version: 0.1.0
11+
# 0.2.0: adds the optional stateless console Deployment (console.enabled, #363).
12+
version: 0.2.0
1213
# The default IronCache image tag this chart targets. Override via
1314
# image.tag in values.yaml. Quoted so a calendar version is not parsed as a float.
1415
appVersion: "latest"

0 commit comments

Comments
 (0)