k8s: work with kubectl apply -f as well as -k

- The secrets template moves to k8s/secrets/, and the filled-in copy to
  k8s/secrets/secrets.yaml (gitignored). `kubectl apply -f k8s/` does
  not recurse, so neither the placeholder template nor the real secrets
  can be applied by accident.
- The server image digest is pinned in server.yaml instead of through
  kustomize's images override, which `-f` ignores (it would have pulled
  a nonexistent :latest).
- README and kustomization.yaml say to use `-k`: plain `-f` never
  creates the generated Grafana ConfigMaps.
- The IngressRoutes drop `tls: {}`, like the other routes on this
  Traefik: TLS is configured on the websecure entrypoint.

Manifests validated both ways (14 resources rendered with kustomize,
11 as plain files — the difference is the Grafana ConfigMaps).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
This commit is contained in:
2026-10-17 21:36:17 +02:00
co-authored by Claude Opus 5.5
parent 46dccee1de
commit 84fb3aac21
7 changed files with 26 additions and 24 deletions
+11 -8
View File
@@ -11,19 +11,19 @@ is applied automatically. Apply them yourself.
| `grafana.yaml` | Grafana 13.2.3 Deployment (1Gi PVC), Service; datasource and dashboards provisioned |
| `grafana/` | The provisioned InfluxDB datasource and the MG4 dashboards (Live, Consumption, Charging) |
| `ingress.yaml` | Traefik `IngressRoute`s for car.k8s.stinnesbeck.com and Grafana, TLS from Traefik's default certificate |
| `secrets.example.yaml` | **Template** for the Secrets; placeholders only, not in `kustomization.yaml` |
| `secrets.yaml` | Your filled-in copy — **gitignored**, never committed |
| `kustomization.yaml` | Everything except the Secrets; pins the server image, generates the Grafana ConfigMaps |
| `secrets/secrets.example.yaml` | **Template** for the Secrets; placeholders only, not in `kustomization.yaml` |
| `secrets/secrets.yaml` | Your filled-in copy — **gitignored**, never committed |
| `kustomization.yaml` | Everything except the Secrets; generates the Grafana ConfigMaps |
## Before the first apply
1. **Check `ingress.yaml`:** Grafana's host (placeholder `car-grafana.k8s.stinnesbeck.com`).
Both routes use the `traefik-internal` class, and both hosts must be
covered by Traefik's default certificate.
2. **Create the Secrets.** `cp k8s/secrets.example.yaml k8s/secrets.yaml` (gitignored), replace
2. **Create the Secrets.** `cp k8s/secrets/secrets.example.yaml k8s/secrets/secrets.yaml` (gitignored), replace
every `CHANGE-ME` there (`openssl rand -hex 32`): `influxdb-auth`, `mg4-server` (ingest token,
approval password for pairing, your ABRP API key and user token) and `grafana-admin`. Keep
`secrets.example.yaml` itself on placeholders only.
the template itself on placeholders only.
3. **Registry access.** The `mg4-server` package on git.stinnesbeck.com is public, so no pull
secret is needed. If you make it private, add an `imagePullSecrets` entry to `server.yaml`.
@@ -31,10 +31,13 @@ is applied automatically. Apply them yourself.
```sh
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/secrets.yaml
kubectl apply -f k8s/secrets/secrets.yaml
kubectl apply -k k8s/
```
Use **`-k`**, not `-f k8s/`: plain `-f` applies the files without kustomize, so the Grafana
ConfigMaps (datasource and dashboards) are never created and Grafana does not start.
## Notes
- InfluxDB's setup mode runs only on an empty volume. Changing `admin-token` in the Secret later
@@ -43,5 +46,5 @@ kubectl apply -k k8s/
for Grafana, read/write for the server) can replace it later.
- The dashboards are read-only in Grafana's UI. Change the JSON in `grafana/dashboards/`; the
ConfigMap name changes with its content, which rolls Grafana.
- The server image is pinned by digest in `kustomization.yaml`. To upgrade, push a new tag and
put its digest there (`skopeo inspect docker://git.stinnesbeck.com/nils/mg4-server:<tag>`).
- The server image is pinned by digest in `server.yaml`. To upgrade, push a new tag and put its
digest there (`skopeo inspect docker://git.stinnesbeck.com/nils/mg4-server:<tag>`).
+3 -4
View File
@@ -1,5 +1,6 @@
# Routes on the traefik-internal class, like the rest of *.k8s.stinnesbeck.com. TLS uses
# Traefik's default certificate, so there is no per-host Certificate here.
# Routes on the traefik-internal class, like the rest of *.k8s.stinnesbeck.com. No tls section
# and no per-host Certificate: TLS is configured on Traefik's websecure entrypoint, which serves
# the default certificate.
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
@@ -18,7 +19,6 @@ spec:
name: mg4-server
namespace: mg4
port: 80
tls: {}
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
@@ -39,4 +39,3 @@ spec:
name: grafana
namespace: mg4
port: 80
tls: {}
+2 -6
View File
@@ -1,5 +1,5 @@
# Render with `kustomize build k8s/` (or `kubectl kustomize k8s/`) and apply it yourself.
# The Secrets are not included: create them from secrets.example.yaml first.
# Apply with `kubectl apply -k k8s/` — not `-f k8s/`, which skips the Grafana ConfigMaps below.
# The Secrets are not included: create them from secrets/secrets.example.yaml first.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
@@ -8,10 +8,6 @@ resources:
- server.yaml
- grafana.yaml
- ingress.yaml
images:
- name: git.stinnesbeck.com/nils/mg4-server
# 2.1.0, pinned by digest so a re-pushed tag cannot change what runs.
digest: sha256:e5f6e2d2ef9dc2650055a0823a3f86d8903e46918a76e990540482edf819766d
generatorOptions:
labels:
app.kubernetes.io/part-of: mg4
+3 -2
View File
@@ -1,5 +1,6 @@
# TEMPLATE ONLY — not part of kustomization.yaml. Copy it to k8s/secrets.yaml (gitignored),
# fill in real values there, and apply that file yourself. Never put real values in here.
# TEMPLATE ONLY — not part of kustomization.yaml. Copy it to k8s/secrets/secrets.yaml
# (gitignored), fill in real values there, and apply that file yourself. Never put real values
# in here. This folder is outside `kubectl apply -f k8s/`, which does not recurse.
#
# openssl rand -hex 32 for every token and password below
apiVersion: v1
+2 -1
View File
@@ -29,7 +29,8 @@ spec:
type: RuntimeDefault
containers:
- name: server
image: git.stinnesbeck.com/nils/mg4-server:latest # pinned by kustomization.yaml
# 2.1.0, pinned by digest so a re-pushed tag cannot change what runs.
image: git.stinnesbeck.com/nils/mg4-server@sha256:e5f6e2d2ef9dc2650055a0823a3f86d8903e46918a76e990540482edf819766d
ports:
- name: http
containerPort: 8080