KubeHarbor · Back to portfolio · Case study

kustomize: dev → prod

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

--- kustomize/dev.yaml
+++ kustomize/prod.yaml
@@ -9,7 +9,7 @@
     pod-security.kubernetes.io/audit: restricted
     pod-security.kubernetes.io/enforce: restricted
     pod-security.kubernetes.io/warn: restricted
-  name: ledgerlite-dev
+  name: ledgerlite-prod
 ---
 apiVersion: v1
 kind: ResourceQuota
@@ -20,16 +20,16 @@
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 spec:
   hard:
-    limits.cpu: "4"
-    limits.memory: 4Gi
-    persistentvolumeclaims: "4"
-    pods: "20"
-    requests.cpu: "2"
-    requests.memory: 2Gi
-    requests.storage: 5Gi
+    limits.cpu: "16"
+    limits.memory: 16Gi
+    persistentvolumeclaims: "0"
+    pods: "40"
+    requests.cpu: "8"
+    requests.memory: 8Gi
+    requests.storage: "0"
 ---
 apiVersion: v1
 automountServiceAccountToken: false
@@ -41,11 +41,11 @@
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 ---
 apiVersion: v1
 data:
-  ENVIRONMENT: dev
+  ENVIRONMENT: prod
   LOG_LEVEL: info
   METRICS_PATH: /metrics
   PORT: "8000"
@@ -58,7 +58,7 @@
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite-api
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 ---
 apiVersion: v1
 kind: Service
@@ -69,7 +69,7 @@
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite-api
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 spec:
   ports:
   - name: http
@@ -83,28 +83,6 @@
   type: ClusterIP
 ---
 apiVersion: v1
-kind: Service
-metadata:
-  labels:
-    app.kubernetes.io/component: postgres
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/part-of: ledgerlite
-  name: ledgerlite-postgres
-  namespace: ledgerlite-dev
-spec:
-  clusterIP: None
-  ports:
-  - name: postgres
-    port: 5432
-    protocol: TCP
-    targetPort: postgres
-  selector:
-    app.kubernetes.io/component: postgres
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/name: ledgerlite
----
-apiVersion: v1
 kind: LimitRange
 metadata:
   labels:
@@ -113,7 +91,7 @@
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 spec:
   limits:
   - default:
@@ -127,23 +105,6 @@
       memory: 2Gi
     type: Container
 ---
-apiVersion: v1
-kind: PersistentVolumeClaim
-metadata:
-  labels:
-    app.kubernetes.io/component: backup
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/part-of: ledgerlite
-  name: ledgerlite-postgres-backup
-  namespace: ledgerlite-dev
-spec:
-  accessModes:
-  - ReadWriteOnce
-  resources:
-    requests:
-      storage: 1Gi
----
 apiVersion: apps/v1
 kind: Deployment
 metadata:
@@ -153,9 +114,9 @@
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite-api
-  namespace: ledgerlite-dev
-spec:
-  replicas: 1
+  namespace: ledgerlite-prod
+spec:
+  replicas: 3
   selector:
     matchLabels:
       app.kubernetes.io/component: api
@@ -219,8 +180,8 @@
           valueFrom:
             secretKeyRef:
               key: DATABASE_URL
-              name: ledgerlite-dev-db
-        image: ghcr.io/OWNER/ledgerlite:0.1.0
+              name: ledgerlite-prod-db
+        image: ghcr.io/OWNER/ledgerlite@sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
         imagePullPolicy: Always
         livenessProbe:
           failureThreshold: 3
@@ -243,11 +204,11 @@
           timeoutSeconds: 2
         resources:
           limits:
+            cpu: "1"
+            memory: 512Mi
+          requests:
             cpu: 250m
             memory: 256Mi
-          requests:
-            cpu: 50m
-            memory: 64Mi
         securityContext:
           allowPrivilegeEscalation: false
           capabilities:
@@ -303,261 +264,68 @@
       - emptyDir: {}
         name: tmp
 ---
-apiVersion: apps/v1
-kind: StatefulSet
-metadata:
-  labels:
-    app.kubernetes.io/component: postgres
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/part-of: ledgerlite
-  name: ledgerlite-postgres
-  namespace: ledgerlite-dev
-spec:
-  replicas: 1
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+  labels:
+    app.kubernetes.io/component: api
+    app.kubernetes.io/instance: ledgerlite
+    app.kubernetes.io/name: ledgerlite
+    app.kubernetes.io/part-of: ledgerlite
+  name: ledgerlite-api
+  namespace: ledgerlite-prod
+spec:
+  minAvailable: 2
   selector:
     matchLabels:
-      app.kubernetes.io/component: postgres
+      app.kubernetes.io/component: api
       app.kubernetes.io/instance: ledgerlite
       app.kubernetes.io/name: ledgerlite
-  serviceName: ledgerlite-postgres
-  template:
-    metadata:
-      labels:
-        app.kubernetes.io/component: postgres
-        app.kubernetes.io/instance: ledgerlite
-        app.kubernetes.io/name: ledgerlite
-        app.kubernetes.io/part-of: ledgerlite
-    spec:
-      automountServiceAccountToken: false
-      containers:
-      - env:
-        - name: PGDATA
-          value: /var/lib/postgresql/data/pgdata
-        - name: POSTGRES_USER
-          valueFrom:
-            secretKeyRef:
-              key: POSTGRES_USER
-              name: ledgerlite-dev-db
-        - name: POSTGRES_PASSWORD
-          valueFrom:
-            secretKeyRef:
-              key: POSTGRES_PASSWORD
-              name: ledgerlite-dev-db
-        - name: POSTGRES_DB
-          valueFrom:
-            secretKeyRef:
-              key: POSTGRES_DB
-              name: ledgerlite-dev-db
-        image: postgres:16-alpine
-        imagePullPolicy: Always
-        livenessProbe:
-          failureThreshold: 3
-          periodSeconds: 10
-          tcpSocket:
-            port: postgres
-          timeoutSeconds: 2
-        name: postgres
-        ports:
-        - containerPort: 5432
-          name: postgres
-          protocol: TCP
-        readinessProbe:
-          failureThreshold: 3
-          periodSeconds: 10
-          tcpSocket:
-            port: postgres
-          timeoutSeconds: 2
-        resources:
-          limits:
-            cpu: 250m
-            memory: 256Mi
-          requests:
-            cpu: 50m
-            memory: 64Mi
-        securityContext:
-          allowPrivilegeEscalation: false
-          capabilities:
-            drop:
-            - ALL
-          privileged: false
-          readOnlyRootFilesystem: true
-          runAsGroup: 70
-          runAsNonRoot: true
-          runAsUser: 70
-          seccompProfile:
-            type: RuntimeDefault
-        startupProbe:
-          failureThreshold: 30
-          periodSeconds: 5
-          tcpSocket:
-            port: postgres
-          timeoutSeconds: 2
-        volumeMounts:
-        - mountPath: /var/lib/postgresql/data
-          name: data
-        - mountPath: /var/run/postgresql
-          name: run
-        - mountPath: /tmp
-          name: tmp
-      enableServiceLinks: false
-      hostIPC: false
-      hostNetwork: false
-      hostPID: false
-      securityContext:
-        fsGroup: 70
-        runAsGroup: 70
-        runAsNonRoot: true
-        runAsUser: 70
-        seccompProfile:
-          type: RuntimeDefault
-      serviceAccountName: ledgerlite
-      volumes:
-      - emptyDir: {}
-        name: run
-      - emptyDir: {}
-        name: tmp
-  volumeClaimTemplates:
-  - metadata:
-      labels:
-        app.kubernetes.io/component: postgres
-        app.kubernetes.io/instance: ledgerlite
-        app.kubernetes.io/name: ledgerlite
-        app.kubernetes.io/part-of: ledgerlite
-      name: data
-    spec:
-      accessModes:
-      - ReadWriteOnce
-      resources:
-        requests:
-          storage: 1Gi
----
-apiVersion: batch/v1
-kind: CronJob
-metadata:
-  labels:
-    app.kubernetes.io/component: backup
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/part-of: ledgerlite
-  name: ledgerlite-postgres-backup
-  namespace: ledgerlite-dev
-spec:
-  concurrencyPolicy: Forbid
-  failedJobsHistoryLimit: 1
-  jobTemplate:
-    spec:
-      template:
-        metadata:
-          labels:
-            app.kubernetes.io/component: backup
-            app.kubernetes.io/instance: ledgerlite
-            app.kubernetes.io/name: ledgerlite
-            app.kubernetes.io/part-of: ledgerlite
-        spec:
-          automountServiceAccountToken: false
-          containers:
-          - 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:
-                  key: POSTGRES_USER
-                  name: ledgerlite-dev-db
-            - name: PGPASSWORD
-              valueFrom:
-                secretKeyRef:
-                  key: POSTGRES_PASSWORD
-                  name: ledgerlite-dev-db
-            - name: PGDATABASE
-              valueFrom:
-                secretKeyRef:
-                  key: POSTGRES_DB
-                  name: ledgerlite-dev-db
-            image: postgres:16-alpine
-            imagePullPolicy: Always
-            livenessProbe:
-              exec:
-                command:
-                - pg_dump
-                - --version
-              failureThreshold: 3
-              periodSeconds: 20
-              timeoutSeconds: 5
-            name: backup
-            readinessProbe:
-              exec:
-                command:
-                - pg_dump
-                - --version
-              failureThreshold: 3
-              periodSeconds: 10
-              timeoutSeconds: 5
-            resources:
-              limits:
-                cpu: 250m
-                memory: 256Mi
-              requests:
-                cpu: 50m
-                memory: 64Mi
-            securityContext:
-              allowPrivilegeEscalation: false
-              capabilities:
-                drop:
-                - ALL
-              privileged: false
-              readOnlyRootFilesystem: true
-              runAsGroup: 70
-              runAsNonRoot: true
-              runAsUser: 70
-              seccompProfile:
-                type: RuntimeDefault
-            startupProbe:
-              exec:
-                command:
-                - pg_dump
-                - --version
-              failureThreshold: 12
-              periodSeconds: 5
-              timeoutSeconds: 5
-            volumeMounts:
-            - mountPath: /backup
-              name: backup
-            - mountPath: /tmp
-              name: tmp
-          enableServiceLinks: false
-          hostIPC: false
-          hostNetwork: false
-          hostPID: false
-          restartPolicy: Never
-          securityContext:
-            fsGroup: 70
-            runAsGroup: 70
-            runAsNonRoot: true
-            runAsUser: 70
-            seccompProfile:
-              type: RuntimeDefault
-          serviceAccountName: ledgerlite
-          volumes:
-          - name: backup
-            persistentVolumeClaim:
-              claimName: ledgerlite-postgres-backup
-          - emptyDir: {}
-            name: tmp
-  schedule: 0 3 * * *
-  successfulJobsHistoryLimit: 1
+  unhealthyPodEvictionPolicy: AlwaysAllow
+---
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+  labels:
+    app.kubernetes.io/component: api
+    app.kubernetes.io/instance: ledgerlite
+    app.kubernetes.io/name: ledgerlite
+    app.kubernetes.io/part-of: ledgerlite
+  name: ledgerlite-api
+  namespace: ledgerlite-prod
+spec:
+  behavior:
+    scaleDown:
+      policies:
+      - periodSeconds: 60
+        type: Percent
+        value: 50
+      stabilizationWindowSeconds: 300
+    scaleUp:
+      policies:
+      - periodSeconds: 60
+        type: Percent
+        value: 100
+      stabilizationWindowSeconds: 60
+  maxReplicas: 10
+  metrics:
+  - resource:
+      name: cpu
+      target:
+        averageUtilization: 70
+        type: Utilization
+    type: Resource
+  - resource:
+      name: memory
+      target:
+        averageUtilization: 70
+        type: Utilization
+    type: Resource
+  minReplicas: 3
+  scaleTargetRef:
+    apiVersion: apps/v1
+    kind: Deployment
+    name: ledgerlite-api
 ---
 apiVersion: batch/v1
 kind: Job
@@ -571,7 +339,7 @@
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite-migrate
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 spec:
   backoffLimit: 2
   template:
@@ -597,8 +365,8 @@
           valueFrom:
             secretKeyRef:
               key: DATABASE_URL
-              name: ledgerlite-dev-db
-        image: ghcr.io/OWNER/ledgerlite:0.1.0
+              name: ledgerlite-prod-db
+        image: ghcr.io/OWNER/ledgerlite@sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
         imagePullPolicy: Always
         livenessProbe:
           exec:
@@ -665,22 +433,44 @@
         name: tmp
   ttlSecondsAfterFinished: 600
 ---
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  labels:
+    app.kubernetes.io/component: api
+    app.kubernetes.io/instance: ledgerlite
+    app.kubernetes.io/name: ledgerlite
+    app.kubernetes.io/part-of: ledgerlite
+  name: ledgerlite-api
+  namespace: ledgerlite-prod
+spec:
+  endpoints:
+  - interval: 30s
+    path: /metrics
+    port: http
+    scheme: http
+  selector:
+    matchLabels:
+      app.kubernetes.io/component: api
+      app.kubernetes.io/instance: ledgerlite
+      app.kubernetes.io/name: ledgerlite
+---
 apiVersion: networking.k8s.io/v1
 kind: Ingress
 metadata:
   annotations:
-    cert-manager.io/cluster-issuer: letsencrypt-staging
+    cert-manager.io/cluster-issuer: letsencrypt-prod
   labels:
     app.kubernetes.io/component: api
     app.kubernetes.io/instance: ledgerlite
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite-api
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 spec:
   ingressClassName: nginx
   rules:
-  - host: ledgerlite.dev.example.com
+  - host: ledgerlite.prod.example.com
     http:
       paths:
       - backend:
@@ -692,8 +482,8 @@
         pathType: Prefix
   tls:
   - hosts:
-    - ledgerlite.dev.example.com
-    secretName: ledgerlite-dev-tls
+    - ledgerlite.prod.example.com
+    secretName: ledgerlite-prod-tls
 ---
 apiVersion: networking.k8s.io/v1
 kind: NetworkPolicy
@@ -704,7 +494,7 @@
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite-allow-dns
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 spec:
   egress:
   - ports:
@@ -743,18 +533,15 @@
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite-allow-egress-postgres
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 spec:
   egress:
   - ports:
     - port: 5432
       protocol: TCP
     to:
-    - podSelector:
-        matchLabels:
-          app.kubernetes.io/component: postgres
-          app.kubernetes.io/instance: ledgerlite
-          app.kubernetes.io/name: ledgerlite
+    - ipBlock:
+        cidr: 10.8.0.0/16
   podSelector:
     matchExpressions:
     - key: app.kubernetes.io/name
@@ -766,7 +553,6 @@
       values:
       - api
       - migrate
-      - backup
   policyTypes:
   - Egress
 ---
@@ -779,7 +565,7 @@
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite-allow-ingress-nginx
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 spec:
   ingress:
   - from:
@@ -805,40 +591,8 @@
     app.kubernetes.io/instance: ledgerlite
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
-  name: ledgerlite-allow-postgres-ingress
-  namespace: ledgerlite-dev
-spec:
-  ingress:
-  - from:
-    - podSelector:
-        matchExpressions:
-        - key: app.kubernetes.io/component
-          operator: In
-          values:
-          - api
-          - migrate
-          - backup
-    ports:
-    - port: 5432
-      protocol: TCP
-  podSelector:
-    matchLabels:
-      app.kubernetes.io/component: postgres
-      app.kubernetes.io/instance: ledgerlite
-      app.kubernetes.io/name: ledgerlite
-  policyTypes:
-  - Ingress
----
-apiVersion: networking.k8s.io/v1
-kind: NetworkPolicy
-metadata:
-  labels:
-    app.kubernetes.io/component: network
-    app.kubernetes.io/instance: ledgerlite
-    app.kubernetes.io/name: ledgerlite
-    app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite-allow-prometheus
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 spec:
   ingress:
   - from:
@@ -865,7 +619,7 @@
     app.kubernetes.io/name: ledgerlite
     app.kubernetes.io/part-of: ledgerlite
   name: ledgerlite-default-deny
-  namespace: ledgerlite-dev
+  namespace: ledgerlite-prod
 spec:
   egress: []
   ingress: []