KubeHarbor · Back to portfolio · Case study

helm: dev → prod

Unified diff of the committed renders. This is not a live cluster diff.

--- helm/dev.yaml
+++ helm/prod.yaml
@@ -3,7 +3,7 @@
 apiVersion: v1
 kind: Namespace
 metadata:
-  name: ledgerlite-dev
+  name: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -18,7 +18,7 @@
 kind: NetworkPolicy
 metadata:
   name: ledgerlite-default-deny
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -37,7 +37,7 @@
 kind: NetworkPolicy
 metadata:
   name: ledgerlite-allow-ingress-nginx
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -65,7 +65,7 @@
 kind: NetworkPolicy
 metadata:
   name: ledgerlite-allow-prometheus
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -93,7 +93,7 @@
 kind: NetworkPolicy
 metadata:
   name: ledgerlite-allow-dns
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -133,7 +133,7 @@
 kind: NetworkPolicy
 metadata:
   name: ledgerlite-allow-egress-postgres
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -151,59 +151,22 @@
         values:
           - api
           - migrate
-          - backup
   policyTypes:
     - Egress
   egress:
     - to:
-        - podSelector:
-            matchLabels:
-              app.kubernetes.io/name: ledgerlite
-              app.kubernetes.io/instance: ledgerlite
-              app.kubernetes.io/component: postgres
+        - ipBlock:
+            cidr: "10.8.0.0/16"
       ports:
         - port: 5432
           protocol: TCP
 ---
-# Source: ledgerlite/templates/networkpolicy.yaml
-apiVersion: networking.k8s.io/v1
-kind: NetworkPolicy
-metadata:
-  name: ledgerlite-allow-postgres-ingress
-  namespace: ledgerlite-dev
-  labels:
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/component: network
-    app.kubernetes.io/part-of: ledgerlite
-spec:
-  podSelector:
-    matchLabels:
-      app.kubernetes.io/name: ledgerlite
-      app.kubernetes.io/instance: ledgerlite
-      app.kubernetes.io/component: postgres
-  policyTypes:
-    - Ingress
-  ingress:
-    - from:
-        - podSelector:
-            matchExpressions:
-              - key: app.kubernetes.io/component
-                operator: In
-                values:
-                  - api
-                  - migrate
-                  - backup
-      ports:
-        - port: 5432
-          protocol: TCP
----
 # Source: ledgerlite/templates/resourcequota.yaml
 apiVersion: v1
 kind: ResourceQuota
 metadata:
   name: ledgerlite
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -211,20 +174,20 @@
     app.kubernetes.io/part-of: ledgerlite
 spec:
   hard:
-    pods: "20"
-    requests.cpu: "2"
-    requests.memory: "2Gi"
-    limits.cpu: "4"
-    limits.memory: "4Gi"
-    persistentvolumeclaims: "4"
-    requests.storage: "5Gi"
+    pods: "40"
+    requests.cpu: "8"
+    requests.memory: "8Gi"
+    limits.cpu: "16"
+    limits.memory: "16Gi"
+    persistentvolumeclaims: "0"
+    requests.storage: "0"
 ---
 # Source: ledgerlite/templates/limitrange.yaml
 apiVersion: v1
 kind: LimitRange
 metadata:
   name: ledgerlite
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -243,12 +206,32 @@
         cpu: "2"
         memory: "2Gi"
 ---
+# Source: ledgerlite/templates/pdb.yaml
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+  name: ledgerlite-api
+  namespace: ledgerlite-prod
+  labels:
+    app.kubernetes.io/name: ledgerlite
+    app.kubernetes.io/instance: ledgerlite
+    app.kubernetes.io/component: api
+    app.kubernetes.io/part-of: ledgerlite
+spec:
+  minAvailable: 2
+  unhealthyPodEvictionPolicy: AlwaysAllow
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: ledgerlite
+      app.kubernetes.io/instance: ledgerlite
+      app.kubernetes.io/component: api
+---
 # Source: ledgerlite/templates/serviceaccount.yaml
 apiVersion: v1
 kind: ServiceAccount
 metadata:
   name: ledgerlite
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -261,7 +244,7 @@
 kind: ConfigMap
 metadata:
   name: ledgerlite-api
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -270,57 +253,16 @@
 data:
   LOG_LEVEL: "info"
   PORT: "8000"
-  ENVIRONMENT: "dev"
+  ENVIRONMENT: "prod"
   METRICS_PATH: /metrics
   WEB_CONCURRENCY: "1"
----
-# Source: ledgerlite/templates/backup-pvc.yaml
-apiVersion: v1
-kind: PersistentVolumeClaim
-metadata:
-  name: ledgerlite-postgres-backup
-  namespace: ledgerlite-dev
-  labels:
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/component: backup
-    app.kubernetes.io/part-of: ledgerlite
-spec:
-  accessModes:
-    - ReadWriteOnce
-  resources:
-    requests:
-      storage: "1Gi"
----
-# Source: ledgerlite/templates/postgres-service.yaml
-apiVersion: v1
-kind: Service
-metadata:
-  name: ledgerlite-postgres
-  namespace: ledgerlite-dev
-  labels:
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/component: postgres
-    app.kubernetes.io/part-of: ledgerlite
-spec:
-  clusterIP: "None"
-  selector:
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/component: postgres
-  ports:
-    - name: postgres
-      port: 5432
-      targetPort: postgres
-      protocol: TCP
 ---
 # Source: ledgerlite/templates/service.yaml
 apiVersion: v1
 kind: Service
 metadata:
   name: ledgerlite-api
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -343,14 +285,14 @@
 kind: Deployment
 metadata:
   name: ledgerlite-api
-  namespace: ledgerlite-dev
-  labels:
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/component: api
-    app.kubernetes.io/part-of: ledgerlite
-spec:
-  replicas: 1
+  namespace: ledgerlite-prod
+  labels:
+    app.kubernetes.io/name: ledgerlite
+    app.kubernetes.io/instance: ledgerlite
+    app.kubernetes.io/component: api
+    app.kubernetes.io/part-of: ledgerlite
+spec:
+  replicas: 3
   selector:
     matchLabels:
       app.kubernetes.io/name: ledgerlite
@@ -369,7 +311,7 @@
         app.kubernetes.io/component: api
         app.kubernetes.io/part-of: ledgerlite
       annotations:
-        checksum/config: 49d3bb28c933f095da10530dd0f4b61a8e868359bb8fcd5d67a0d8a13af73a48
+        checksum/config: 45849d55e5897e96831f645cb4ef27df0becfbb31ff96fb8b975b12bc99494d1
     spec:
       serviceAccountName: ledgerlite
       automountServiceAccountToken: false
@@ -414,7 +356,7 @@
               app.kubernetes.io/component: api
       containers:
         - name: api
-          image: "ghcr.io/OWNER/ledgerlite:0.1.0"
+          image: "ghcr.io/OWNER/ledgerlite@sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
           imagePullPolicy: Always
           command: ["python", "-m", "app"]
           ports:
@@ -448,15 +390,15 @@
             - name: DATABASE_URL
               valueFrom:
                 secretKeyRef:
-                  name: ledgerlite-dev-db
+                  name: ledgerlite-prod-db
                   key: DATABASE_URL
           resources:
             requests:
-              cpu: "50m"
-              memory: "64Mi"
-            limits:
               cpu: "250m"
               memory: "256Mi"
+            limits:
+              cpu: "1"
+              memory: "512Mi"
           securityContext:
             allowPrivilegeEscalation: false
             privileged: false
@@ -497,279 +439,72 @@
         - name: tmp
           emptyDir: {}
 ---
-# Source: ledgerlite/templates/postgres-statefulset.yaml
-apiVersion: apps/v1
-kind: StatefulSet
-metadata:
-  name: ledgerlite-postgres
-  namespace: ledgerlite-dev
-  labels:
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/component: postgres
-    app.kubernetes.io/part-of: ledgerlite
-spec:
-  serviceName: ledgerlite-postgres
-  replicas: 1
-  selector:
-    matchLabels:
-      app.kubernetes.io/name: ledgerlite
-      app.kubernetes.io/instance: ledgerlite
-      app.kubernetes.io/component: postgres
-  template:
-    metadata:
-      labels:
-        app.kubernetes.io/name: ledgerlite
-        app.kubernetes.io/instance: ledgerlite
-        app.kubernetes.io/component: postgres
-        app.kubernetes.io/part-of: ledgerlite
-    spec:
-      serviceAccountName: ledgerlite
-      automountServiceAccountToken: false
-      enableServiceLinks: false
-      hostNetwork: false
-      hostPID: false
-      hostIPC: false
-      securityContext:
-        runAsNonRoot: true
-        runAsUser: 70
-        runAsGroup: 70
-        fsGroup: 70
-        seccompProfile:
-          type: RuntimeDefault
-      containers:
-        - name: postgres
-          image: "postgres:16-alpine"
-          imagePullPolicy: Always
-          ports:
-            - name: postgres
-              containerPort: 5432
-              protocol: TCP
-          env:
-            - name: PGDATA
-              value: /var/lib/postgresql/data/pgdata
-            - name: POSTGRES_USER
-              valueFrom:
-                secretKeyRef:
-                  name: ledgerlite-dev-db
-                  key: POSTGRES_USER
-            - name: POSTGRES_PASSWORD
-              valueFrom:
-                secretKeyRef:
-                  name: ledgerlite-dev-db
-                  key: POSTGRES_PASSWORD
-            - name: POSTGRES_DB
-              valueFrom:
-                secretKeyRef:
-                  name: ledgerlite-dev-db
-                  key: POSTGRES_DB
-          resources:
-            requests:
-              cpu: "50m"
-              memory: "64Mi"
-            limits:
-              cpu: "250m"
-              memory: "256Mi"
-          securityContext:
-            allowPrivilegeEscalation: false
-            privileged: false
-            readOnlyRootFilesystem: true
-            runAsNonRoot: true
-            runAsUser: 70
-            runAsGroup: 70
-            capabilities:
-              drop:
-                - ALL
-            seccompProfile:
-              type: RuntimeDefault
-          startupProbe:
-            tcpSocket:
-              port: postgres
-            periodSeconds: 5
-            timeoutSeconds: 2
-            failureThreshold: 30
-          livenessProbe:
-            tcpSocket:
-              port: postgres
-            periodSeconds: 10
-            timeoutSeconds: 2
-            failureThreshold: 3
-          readinessProbe:
-            tcpSocket:
-              port: postgres
-            periodSeconds: 10
-            timeoutSeconds: 2
-            failureThreshold: 3
-          volumeMounts:
-            - name: data
-              mountPath: /var/lib/postgresql/data
-            - name: run
-              mountPath: /var/run/postgresql
-            - name: tmp
-              mountPath: /tmp
-      volumes:
-        - name: run
-          emptyDir: {}
-        - name: tmp
-          emptyDir: {}
-  volumeClaimTemplates:
-    - metadata:
-        name: data
-        labels:
-          app.kubernetes.io/name: ledgerlite
-          app.kubernetes.io/instance: ledgerlite
-          app.kubernetes.io/component: postgres
-          app.kubernetes.io/part-of: ledgerlite
-      spec:
-        accessModes:
-          - ReadWriteOnce
-        resources:
-          requests:
-            storage: "1Gi"
----
-# Source: ledgerlite/templates/backup-cronjob.yaml
-apiVersion: batch/v1
-kind: CronJob
-metadata:
-  name: ledgerlite-postgres-backup
-  namespace: ledgerlite-dev
-  labels:
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/component: backup
-    app.kubernetes.io/part-of: ledgerlite
-spec:
-  schedule: "0 3 * * *"
-  concurrencyPolicy: Forbid
-  successfulJobsHistoryLimit: 1
-  failedJobsHistoryLimit: 1
-  jobTemplate:
-    spec:
-      template:
-        metadata:
-          labels:
-            app.kubernetes.io/name: ledgerlite
-            app.kubernetes.io/instance: ledgerlite
-            app.kubernetes.io/component: backup
-            app.kubernetes.io/part-of: ledgerlite
-        spec:
-          restartPolicy: Never
-          serviceAccountName: ledgerlite
-          automountServiceAccountToken: false
-          enableServiceLinks: false
-          hostNetwork: false
-          hostPID: false
-          hostIPC: false
-          securityContext:
-            runAsNonRoot: true
-            runAsUser: 70
-            runAsGroup: 70
-            fsGroup: 70
-            seccompProfile:
-              type: RuntimeDefault
-          containers:
-            - name: backup
-              image: "postgres:16-alpine"
-              imagePullPolicy: Always
-              command:
-                - /bin/sh
-                - -c
-                - |
-                  set -eu
-                  ts=$(date -u +%Y%m%dT%H%M%SZ)
-                  mkdir -p /backup
-                  pg_dump --file="/backup/ledgerlite-${ts}.sql"
-                  ls -1t /backup/ledgerlite-*.sql | awk 'NR>7' | while IFS= read -r old; do
-                    rm -f "$old"
-                  done
-              env:
-                - name: PGHOST
-                  value: ledgerlite-postgres
-                - name: PGUSER
-                  valueFrom:
-                    secretKeyRef:
-                      name: ledgerlite-dev-db
-                      key: POSTGRES_USER
-                - name: PGPASSWORD
-                  valueFrom:
-                    secretKeyRef:
-                      name: ledgerlite-dev-db
-                      key: POSTGRES_PASSWORD
-                - name: PGDATABASE
-                  valueFrom:
-                    secretKeyRef:
-                      name: ledgerlite-dev-db
-                      key: POSTGRES_DB
-              resources:
-                requests:
-                  cpu: "50m"
-                  memory: "64Mi"
-                limits:
-                  cpu: "250m"
-                  memory: "256Mi"
-              securityContext:
-                allowPrivilegeEscalation: false
-                privileged: false
-                readOnlyRootFilesystem: true
-                runAsNonRoot: true
-                runAsUser: 70
-                runAsGroup: 70
-                capabilities:
-                  drop:
-                    - ALL
-                seccompProfile:
-                  type: RuntimeDefault
-              startupProbe:
-                exec:
-                  command: ["pg_dump", "--version"]
-                periodSeconds: 5
-                timeoutSeconds: 5
-                failureThreshold: 12
-              livenessProbe:
-                exec:
-                  command: ["pg_dump", "--version"]
-                periodSeconds: 20
-                timeoutSeconds: 5
-                failureThreshold: 3
-              readinessProbe:
-                exec:
-                  command: ["pg_dump", "--version"]
-                periodSeconds: 10
-                timeoutSeconds: 5
-                failureThreshold: 3
-              volumeMounts:
-                - name: backup
-                  mountPath: /backup
-                - name: tmp
-                  mountPath: /tmp
-          volumes:
-            - name: backup
-              persistentVolumeClaim:
-                claimName: ledgerlite-postgres-backup
-            - name: tmp
-              emptyDir: {}
+# Source: ledgerlite/templates/hpa.yaml
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+  name: ledgerlite-api
+  namespace: ledgerlite-prod
+  labels:
+    app.kubernetes.io/name: ledgerlite
+    app.kubernetes.io/instance: ledgerlite
+    app.kubernetes.io/component: api
+    app.kubernetes.io/part-of: ledgerlite
+spec:
+  scaleTargetRef:
+    apiVersion: apps/v1
+    kind: Deployment
+    name: ledgerlite-api
+  minReplicas: 3
+  maxReplicas: 10
+  metrics:
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 70
+    - type: Resource
+      resource:
+        name: memory
+        target:
+          type: Utilization
+          averageUtilization: 70
+  behavior:
+    scaleUp:
+      stabilizationWindowSeconds: 60
+      policies:
+        - type: Percent
+          value: 100
+          periodSeconds: 60
+    scaleDown:
+      stabilizationWindowSeconds: 300
+      policies:
+        - type: Percent
+          value: 50
+          periodSeconds: 60
 ---
 # Source: ledgerlite/templates/ingress.yaml
 apiVersion: networking.k8s.io/v1
 kind: Ingress
 metadata:
   name: ledgerlite-api
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
     app.kubernetes.io/component: api
     app.kubernetes.io/part-of: ledgerlite
   annotations:
-    cert-manager.io/cluster-issuer: "letsencrypt-staging"
+    cert-manager.io/cluster-issuer: "letsencrypt-prod"
 spec:
   ingressClassName: nginx
   tls:
     - hosts:
-        - "ledgerlite.dev.example.com"
-      secretName: ledgerlite-dev-tls
+        - "ledgerlite.prod.example.com"
+      secretName: ledgerlite-prod-tls
   rules:
-    - host: "ledgerlite.dev.example.com"
+    - host: "ledgerlite.prod.example.com"
       http:
         paths:
           - path: /
@@ -780,12 +515,35 @@
                 port:
                   number: 8000
 ---
+# Source: ledgerlite/templates/servicemonitor.yaml
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  name: ledgerlite-api
+  namespace: ledgerlite-prod
+  labels:
+    app.kubernetes.io/name: ledgerlite
+    app.kubernetes.io/instance: ledgerlite
+    app.kubernetes.io/component: api
+    app.kubernetes.io/part-of: ledgerlite
+spec:
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: ledgerlite
+      app.kubernetes.io/instance: ledgerlite
+      app.kubernetes.io/component: api
+  endpoints:
+    - port: http
+      path: /metrics
+      interval: 30s
+      scheme: http
+---
 # Source: ledgerlite/templates/migrate-job.yaml
 apiVersion: batch/v1
 kind: Job
 metadata:
   name: ledgerlite-migrate
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
   labels:
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/instance: ledgerlite
@@ -822,7 +580,7 @@
           type: RuntimeDefault
       containers:
         - name: migrate
-          image: "ghcr.io/OWNER/ledgerlite:0.1.0"
+          image: "ghcr.io/OWNER/ledgerlite@sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
           imagePullPolicy: Always
           command: ["alembic", "upgrade", "head"]
           env:
@@ -833,7 +591,7 @@
             - name: DATABASE_URL
               valueFrom:
                 secretKeyRef:
-                  name: ledgerlite-dev-db
+                  name: ledgerlite-prod-db
                   key: DATABASE_URL
           resources:
             requests: