blumeops/argocd/manifests/grafana/deployment.yaml
Erich Blume d05d2fbaff
All checks were successful
Build Container (Nix) / detect (push) Successful in 2s
Build Container / detect (push) Successful in 1s
Build Container (Nix) / build (grafana) (push) Successful in 2s
Build Container / build (grafana) (push) Successful in 7s
C2: Upgrade Grafana to 12.x with Nix container and Kustomize (#260)
## Summary

Mikado chain to upgrade Grafana from 11.4.0 (Helm chart) to 12.x with:
- Home-built Nix container image (`forge.ops.eblu.me/eblume/grafana`)
- Kustomize manifests replacing the Helm chart
- Single-source ArgoCD app

## Chain

Goal: `upgrade-grafana`
Leaves: `build-grafana-container`, `kustomize-grafana-deployment`

Track with: `mise run docs-mikado upgrade-grafana`

## Test plan
- [ ] Container builds successfully via Nix
- [ ] Container pushed to registry
- [ ] Kustomize manifests produce equivalent resources to current Helm
- [ ] Pod runs, UI loads, OIDC works, datasources healthy
- [ ] `mise run services-check` passes

Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/260
2026-02-23 18:07:18 -08:00

176 lines
5.4 KiB
YAML

apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
namespace: monitoring
labels:
app.kubernetes.io/name: grafana
app.kubernetes.io/instance: grafana
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/name: grafana
app.kubernetes.io/instance: grafana
strategy:
type: RollingUpdate
template:
metadata:
labels:
app.kubernetes.io/name: grafana
app.kubernetes.io/instance: grafana
annotations:
kubectl.kubernetes.io/default-container: grafana
spec:
automountServiceAccountToken: true
serviceAccountName: grafana
securityContext:
fsGroup: 472
runAsGroup: 472
runAsNonRoot: true
runAsUser: 472
initContainers:
- name: init-chown-data
image: docker.io/library/busybox:1.31.1
imagePullPolicy: IfNotPresent
command: ["chown", "-R", "472:472", "/var/lib/grafana"]
securityContext:
runAsNonRoot: false
runAsUser: 0
capabilities:
add: ["CHOWN"]
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: storage
mountPath: /var/lib/grafana
containers:
# Dashboard sidecar - watches ConfigMaps with grafana_dashboard=1
- name: grafana-sc-dashboard
image: quay.io/kiwigrid/k8s-sidecar:1.28.0
imagePullPolicy: IfNotPresent
env:
- name: METHOD
value: WATCH
- name: LABEL
value: grafana_dashboard
- name: LABEL_VALUE
value: "1"
- name: FOLDER
value: /tmp/dashboards
- name: RESOURCE
value: both
- name: FOLDER_ANNOTATION
value: grafana_folder
- name: REQ_USERNAME
valueFrom:
secretKeyRef:
name: grafana-admin
key: admin-user
- name: REQ_PASSWORD
valueFrom:
secretKeyRef:
name: grafana-admin
key: admin-password
- name: REQ_URL
value: http://localhost:3000/api/admin/provisioning/dashboards/reload
- name: REQ_METHOD
value: POST
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: sc-dashboard-volume
mountPath: /tmp/dashboards
# Grafana
- name: grafana
image: registry.ops.eblu.me/blumeops/grafana:v12.3.3-09ac36b
imagePullPolicy: IfNotPresent
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: GF_SECURITY_ADMIN_USER
valueFrom:
secretKeyRef:
name: grafana-admin
key: admin-user
- name: GF_SECURITY_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: grafana-admin
key: admin-password
- name: GF_PATHS_DATA
value: /var/lib/grafana/
- name: GF_PATHS_LOGS
value: /var/log/grafana
- name: GF_PATHS_PLUGINS
value: /var/lib/grafana/plugins
- name: GF_PATHS_PROVISIONING
value: /etc/grafana/provisioning
envFrom:
- secretRef:
name: grafana-teslamate-datasource
optional: true
- secretRef:
name: grafana-authentik-oauth
optional: true
ports:
- name: http
containerPort: 3000
protocol: TCP
livenessProbe:
httpGet:
path: /api/health
port: 3000
initialDelaySeconds: 60
timeoutSeconds: 30
failureThreshold: 10
readinessProbe:
httpGet:
path: /api/health
port: 3000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: config
mountPath: /etc/grafana/grafana.ini
subPath: grafana.ini
- name: config
mountPath: /etc/grafana/provisioning/datasources/datasources.yaml
subPath: datasources.yaml
- name: storage
mountPath: /var/lib/grafana
- name: sc-dashboard-volume
mountPath: /tmp/dashboards
- name: sc-dashboard-provider
mountPath: /etc/grafana/provisioning/dashboards/sc-dashboardproviders.yaml
subPath: provider.yaml
volumes:
- name: config
configMap:
name: grafana
- name: storage
persistentVolumeClaim:
claimName: grafana
- name: sc-dashboard-volume
emptyDir: {}
- name: sc-dashboard-provider
configMap:
name: grafana-config-dashboards