# PlanPal Helm values. Mirrors planpalto-infrato/k8s + kustomization.yaml. # namespace empty -> defaults to the release name, so multiple installs # (helm install planpal-a / planpal-b) land in separate namespaces and don't # collide. Set it to pin a fixed namespace. namespace: "" createNamespace: true image: registry: 134604498185.dkr.ecr.ap-southeast-3.amazonaws.com backend: repository: fakhri-planpal-backend tag: latest frontend: repository: fakhri-planpal-frontend tag: latest # ECR frontend repo only publishes latest (1.1 was a minikube-local tag) pullPolicy: IfNotPresent serviceAccount: name: planpal-backend # Pod Identity -> role fakhri-app-planpal create: true # App workloads. backend+workers share the backend image and mount backend-env+aws-env. # frontend uses the frontend image and frontend-env. apps: backend: command: [planpal-server] image: backend envFrom: [backend-env, aws-env] ports: - { name: http, containerPort: 8088 } - { name: metrics, containerPort: 9090 } service: port: 8088 targetPort: 8088 probePath: /api/v1/health probePort: 8088 resources: requests: { cpu: 25m, memory: 64Mi } limits: { cpu: 250m, memory: 256Mi } hpa: { min: 2, max: 5, cpu: 50 } pdb: { maxUnavailable: 1 } frontend: command: [] image: frontend envFrom: [frontend-env] ports: - { name: http, containerPort: 3000 } service: port: 3000 targetPort: 3000 annotations: alb.ingress.kubernetes.io/healthcheck-path: "/" alb.ingress.kubernetes.io/success-codes: "200" probePath: / probePort: 3000 resources: requests: { cpu: 25m, memory: 96Mi } limits: { cpu: 300m, memory: 384Mi } hpa: { min: 2, max: 5, cpu: 50 } pdb: { maxUnavailable: 1 } # Workers declare no metrics port: the worker binaries don't serve /metrics # (only planpal-server does). Adding one just yields a DOWN scrape target. schedule-worker: command: [planpal-schedule-worker] image: backend envFrom: [backend-env, aws-env] ports: [] resources: requests: { cpu: 25m, memory: 64Mi } limits: { cpu: 200m, memory: 256Mi } hpa: { min: 1, max: 3, cpu: 60 } notification-worker: command: [planpal-notification-worker] image: backend envFrom: [backend-env, aws-env] ports: [] resources: requests: { cpu: 25m, memory: 64Mi } limits: { cpu: 200m, memory: 256Mi } hpa: { min: 1, max: 3, cpu: 60 } ai-worker: command: [planpal-ai-worker] image: backend envFrom: [backend-env, aws-env] ports: [] resources: requests: { cpu: 25m, memory: 64Mi } limits: { cpu: 200m, memory: 256Mi } hpa: { min: 1, max: 3, cpu: 60 } # Stateless in-cluster deps. redis: image: redis:7-alpine resources: requests: { cpu: 250m, memory: 256Mi } limits: { cpu: 500m, memory: 512Mi } nats: image: nats:2-alpine resources: requests: { cpu: 100m, memory: 128Mi } limits: { cpu: 200m, memory: 256Mi } # External Secrets Operator: pull each k8s Secret from AWS Secrets Manager. externalSecrets: enabled: true region: ap-southeast-3 # storeName empty -> "-aws-planpal". The ClusterSecretStore is # cluster-scoped, so it must be unique per release. storeName: "" refreshInterval: 1h # target k8s Secret name -> Secrets Manager key. Releases share these keys # (same DB/seed/config is fine). Point a release at other keys to isolate it. secrets: backend-env: planpal/backend-env aws-env: planpal/aws-env seed-env: planpal/seed-env frontend-env: planpal/frontend # Prometheus scraping + Grafana dashboard. Off by default; prod turns it on. # Needs kube-prometheus-stack on the cluster (ServiceMonitor CRD + Grafana sidecar). monitoring: enabled: false # ServiceMonitor is only discovered by Prometheus if it carries this label. # kube-prometheus-stack default release name is "monitoring". prometheusRelease: monitoring scrapeInterval: 30s # Admin seed one-shot Job. seedJob: enabled: true command: [seed_admin] envFrom: [backend-env, seed-env] # ALB ingress. host is the external DNS name; certArn is the ACM cert. ingress: enabled: true className: alb host: fakhri-k8.sandbox.devopsinstitute.id certArn: arn:aws:acm:ap-southeast-3:134604498185:certificate/c9fcfcb9-9d16-4dbb-989f-9f77f6496621 # groupName empty -> release name, so each install gets its own ALB. Set the # same value on two releases to make them share one ALB. groupName: "" healthcheckPath: /api/v1/health # externalDNS true adds the external-dns hostname annotation. The external-dns # controller then creates the Route53 record for host. Needs external-dns # installed and permitted on the target hosted zone. externalDNS: false