shelly-manager will build+flash BLE proxies by spawning short-lived esphome Jobs (on the shelly-manager-iot macvlan → mDNS → OTA:3232) and streaming their logs. Give it a namespace-scoped identity to do so: - ServiceAccount shelly-manager + Role shelly-manager-firmware (jobs: create/get/list/watch/delete; pods: get/list/watch; pods/log: get) + RoleBinding. No cluster-wide, secret, or exec rights. - Wire serviceAccountName into the Deployment. - Sync esphome/shelly-ble-proxy.yaml logger to the lean level already OTA'd to the device (esp32_ble_client DEBUG, not VERBOSE) so the PVC stops filling; VERBOSE is now an on-demand diagnostic via the pipeline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
119 lines
5.0 KiB
YAML
119 lines
5.0 KiB
YAML
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: shelly-manager
|
|
namespace: home-assistant
|
|
labels:
|
|
app.kubernetes.io/name: shelly-manager
|
|
spec:
|
|
replicas: 1
|
|
strategy:
|
|
type: Recreate
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: shelly-manager
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: shelly-manager
|
|
annotations:
|
|
# Multus attaches `net1` on v30iot with a DHCP-leased address (see
|
|
# shelly-manager-network-attachment.yaml). The mDNS resolver
|
|
# inside the app needs L2 presence on the IoT VLAN to browse
|
|
# for `_shelly._tcp.local.` — multicast doesn't cross the L3
|
|
# boundary between the cluster pod CIDR and v30iot.
|
|
#
|
|
# But net1 must carry ONLY multicast, not the admin HTTP server.
|
|
# The app has no auth of its own; its ingress is gated by Authentik
|
|
# (shelly-manager-gate). That gate only guards the Traefik path —
|
|
# macvlan traffic bypasses Cilium policy entirely, so a `0.0.0.0`
|
|
# bind exposes the unauthenticated UI on :8080 directly to every
|
|
# device on the IoT VLAN (verified 2026-07-10: GET http://<net1
|
|
# ip>:8080/ from the VLAN returned 200 and the full UI). See the
|
|
# ASPNETCORE_URLS binding below, which pins Kestrel to the pod
|
|
# (eth0) address so :8080 is not reachable over net1. The mDNS
|
|
# resolver is a separate ZeroconfResolver socket set and is
|
|
# unaffected.
|
|
k8s.v1.cni.cncf.io/networks: shelly-manager-iot
|
|
spec:
|
|
# eth0 (Cilium-managed pod network) is still the primary — it
|
|
# carries the ingress, mosquitto LB return path, etc. The macvlan
|
|
# above is additive. No explicit edge exclusion is needed: the
|
|
# `workload-class=pinned:NoSchedule` taint on k8s-edge already
|
|
# keeps this pod off there (we never tolerate it), and the NAD's
|
|
# `master: eth2` lines up with v30iot on every k8s-{1,2,3} worker.
|
|
enableServiceLinks: false
|
|
# Grants shelly-manager the in-cluster identity used by the firmware
|
|
# pipeline to create esphome flash Jobs and stream their logs. RBAC is
|
|
# namespace-scoped to home-assistant (shelly-manager-firmware-rbac.yaml).
|
|
serviceAccountName: shelly-manager
|
|
securityContext:
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
containers:
|
|
- name: shelly-manager
|
|
image: gitea.renner.uno/k.renner/shelly-manager:build.1784021738 # {"$imagepolicy": "flux-system:shelly-manager"}
|
|
imagePullPolicy: IfNotPresent
|
|
ports:
|
|
- name: http
|
|
containerPort: 8080
|
|
env:
|
|
- name: TZ
|
|
value: Europe/Berlin
|
|
# Pin Kestrel to the pod's eth0 (cluster CIDR) address, not
|
|
# 0.0.0.0. The image's Dockerfile default is
|
|
# ASPNETCORE_URLS=http://0.0.0.0:8080, which also binds the
|
|
# macvlan net1 interface on the IoT VLAN — exposing the
|
|
# unauthenticated UI to that untrusted segment past the
|
|
# Authentik gate. POD_IP is the eth0 IPv4 (status.podIP); the
|
|
# Service, the Authentik outpost, and the kubelet httpGet
|
|
# probes all reach the app on that address. mDNS discovery is
|
|
# unaffected: ZeroconfResolver binds its own multicast sockets
|
|
# on net1 independently of Kestrel.
|
|
- name: POD_IP
|
|
valueFrom:
|
|
fieldRef:
|
|
fieldPath: status.podIP
|
|
- name: ASPNETCORE_URLS
|
|
value: "http://$(POD_IP):8080"
|
|
# BLE radios: ESP32 esphome bluetooth_proxy nodes (e.g. the M5 Atom
|
|
# Echo) are AUTO-DISCOVERED on the IoT VLAN via mDNS
|
|
# (_esphomelib._tcp) over the same net1 macvlan route as the Shellys —
|
|
# no static hostname/DNS (which the *.renner.uno wildcard would poison
|
|
# over IPv6). The shared fleet Noise key (= the dashboard's
|
|
# shelly_ble_proxy_api_key) lets shelly-manager complete the encrypted
|
|
# native-API handshake to each discovered proxy: DeviceInfo on
|
|
# /ble-radios today, the BLE scan/GATT provisioning path next.
|
|
- name: Ble__Discovery__Key
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: shelly-ble-proxy-key
|
|
key: api-key
|
|
volumeMounts:
|
|
- name: data
|
|
mountPath: /data
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /
|
|
port: http
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 30
|
|
timeoutSeconds: 5
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /
|
|
port: http
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
resources:
|
|
requests:
|
|
cpu: 50m
|
|
memory: 128Mi
|
|
limits:
|
|
memory: 512Mi
|
|
volumes:
|
|
- name: data
|
|
persistentVolumeClaim:
|
|
claimName: shelly-manager-data
|