feat(infra): forte-drop in-cluster postgres + nightly backup (prod) #17

Closed
jorgen.stensrud wants to merge 7 commits from feat/forte-drop-infra into main
9 changed files with 350 additions and 0 deletions
Showing only changes of commit 3ce93017f9 - Show all commits

View File

@@ -0,0 +1,40 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: forte-drop-minio
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "0"
labels:
app.kubernetes.io/name: forte-drop-minio
app.kubernetes.io/part-of: apps
app.kubernetes.io/managed-by: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
jorgen.stensrud marked this conversation as resolved Outdated

Using SSH Git URL may cause access issues in CI/CD pipelines; consider using HTTPS with token authentication.

    repoURL: https://git.forteapps.net/Forte/launchpad.git

#ai-review-inline

Using SSH Git URL may cause access issues in CI/CD pipelines; consider using HTTPS with token authentication. ```suggestion repoURL: https://git.forteapps.net/Forte/launchpad.git ``` #ai-review-inline
targetRevision: HEAD
jorgen.stensrud marked this conversation as resolved Outdated

Using HEAD as targetRevision can lead to unpredictable deployments; pin to a specific branch or tag.

    targetRevision: main

#ai-review-inline

Using HEAD as targetRevision can lead to unpredictable deployments; pin to a specific branch or tag. ```suggestion targetRevision: main ``` #ai-review-inline
path: infra/overlays/upc-dev/forte-drop-minio/resources
destination:
server: https://kubernetes.default.svc
namespace: forte-drop
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- Validate=true
- ServerSideApply=true
ignoreDifferences:
- group: apps
kind: StatefulSet
jsonPointers:
- /spec/volumeClaimTemplates

View File

@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- forte-drop-minio.yaml
jorgen.stensrud marked this conversation as resolved Outdated

The referenced resource file 'forte-drop-minio.yaml' should exist in the same directory for this Kustomization to work properly.

#ai-review-inline

The referenced resource file 'forte-drop-minio.yaml' should exist in the same directory for this Kustomization to work properly. #ai-review-inline

View File

@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
jorgen.stensrud marked this conversation as resolved Outdated

Remove the '# added' comment as it's not necessary for production code.

apiVersion: kustomize.config.k8s.io/v1beta1

#ai-review-inline

Remove the '# added' comment as it's not necessary for production code. ```suggestion apiVersion: kustomize.config.k8s.io/v1beta1 ``` #ai-review-inline
kind: Kustomization
jorgen.stensrud marked this conversation as resolved Outdated

Remove the '# added' comment as it's not necessary for production code.

kind: Kustomization

#ai-review-inline

Remove the '# added' comment as it's not necessary for production code. ```suggestion kind: Kustomization ``` #ai-review-inline
resources:
jorgen.stensrud marked this conversation as resolved Outdated

Remove the '# added' comment as it's not necessary for production code.

resources:

#ai-review-inline

Remove the '# added' comment as it's not necessary for production code. ```suggestion resources: ``` #ai-review-inline
- minio.yaml
jorgen.stensrud marked this conversation as resolved Outdated

Remove the '# added' comment as it's not necessary for production code.

- minio.yaml

#ai-review-inline

Remove the '# added' comment as it's not necessary for production code. ```suggestion - minio.yaml ``` #ai-review-inline
- forte-drop-minio-creds-sealed.yaml
jorgen.stensrud marked this conversation as resolved Outdated

Remove the '# added' comment as it's not necessary for production code.

- forte-drop-minio-creds-sealed.yaml

#ai-review-inline

Remove the '# added' comment as it's not necessary for production code. ```suggestion - forte-drop-minio-creds-sealed.yaml ``` #ai-review-inline

View File

@@ -0,0 +1,146 @@
apiVersion: v1
kind: Service
metadata:
name: forte-drop-minio
namespace: forte-drop
labels:
app.kubernetes.io/name: minio
app.kubernetes.io/instance: forte-drop
app.kubernetes.io/component: object-storage
spec:
type: ClusterIP
ports:
- name: http-api
port: 9000
targetPort: http-api
- name: http-console
port: 9001
targetPort: http-console
selector:
app.kubernetes.io/name: minio
app.kubernetes.io/instance: forte-drop
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: forte-drop-minio
namespace: forte-drop
labels:
app.kubernetes.io/name: minio
app.kubernetes.io/instance: forte-drop
app.kubernetes.io/component: object-storage
spec:
serviceName: forte-drop-minio
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: minio
app.kubernetes.io/instance: forte-drop
template:
metadata:
labels:
app.kubernetes.io/name: minio
app.kubernetes.io/instance: forte-drop
app.kubernetes.io/component: object-storage
spec:
containers:
- name: minio
image: quay.io/minio/minio:latest
jorgen.stensrud marked this conversation as resolved Outdated

Using ':latest' tag is discouraged as it can lead to unpredictable deployments; pin to a specific version.

        image: quay.io/minio/minio:RELEASE.2024-03-15T01-07-19Z

#ai-review-inline

Using ':latest' tag is discouraged as it can lead to unpredictable deployments; pin to a specific version. ```suggestion image: quay.io/minio/minio:RELEASE.2024-03-15T01-07-19Z ``` #ai-review-inline
args:
- server
- /data
- --console-address
- :9001
ports:
- name: http-api
containerPort: 9000
- name: http-console
containerPort: 9001
env:
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
name: forte-drop-minio-creds
key: root-user
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: forte-drop-minio-creds
key: root-password
volumeMounts:
- name: data
mountPath: /data
livenessProbe:
httpGet:
path: /minio/health/live
port: http-api
initialDelaySeconds: 30
periodSeconds: 20
readinessProbe:
httpGet:
path: /minio/health/ready
port: http-api
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes:
- ReadWriteOnce
storageClassName: upcloud-block-storage-maxiops
resources:
requests:
storage: 20Gi
---
# Bootstrap job — creates the 'drops' bucket once MinIO is reachable.
# Idempotent: `mc mb --ignore-existing` skips if bucket already exists.
apiVersion: batch/v1
kind: Job
metadata:
name: forte-drop-minio-bootstrap
namespace: forte-drop
labels:
app.kubernetes.io/name: minio
app.kubernetes.io/instance: forte-drop
app.kubernetes.io/component: bootstrap
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
backoffLimit: 5
template:
spec:
restartPolicy: OnFailure
containers:
- name: mc
image: quay.io/minio/mc:latest
jorgen.stensrud marked this conversation as resolved Outdated

Using ':latest' tag is discouraged as it can lead to unpredictable deployments; pin to a specific version.

        image: quay.io/minio/mc:RELEASE.2024-03-15T01-07-19Z

#ai-review-inline

Using ':latest' tag is discouraged as it can lead to unpredictable deployments; pin to a specific version. ```suggestion image: quay.io/minio/mc:RELEASE.2024-03-15T01-07-19Z ``` #ai-review-inline
env:
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
name: forte-drop-minio-creds
key: root-user
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: forte-drop-minio-creds
key: root-password
command:
- sh
- -c
- |
set -e
jorgen.stensrud marked this conversation as resolved Outdated

Shell script should include 'set -uo pipefail' for better error handling and safer execution.

          set -euo pipefail

#ai-review-inline

Shell script should include 'set -uo pipefail' for better error handling and safer execution. ```suggestion set -euo pipefail ``` #ai-review-inline
until mc alias set local http://forte-drop-minio:9000 "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" 2>/dev/null; do
echo "waiting for minio..."
sleep 2
done
mc mb --ignore-existing local/drops
echo "bucket 'drops' ready"

View File

@@ -0,0 +1,45 @@
apiVersion: v1
kind: Namespace
metadata:
name: forte-drop
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: forte-drop-postgresql
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "0"
labels:
app.kubernetes.io/name: forte-drop-postgresql
app.kubernetes.io/part-of: apps
app.kubernetes.io/managed-by: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
jorgen.stensrud marked this conversation as resolved
Review

SSH Git URL exposes the internal Git server hostname and port which may be considered sensitive infrastructure information.

#ai-review-inline

SSH Git URL exposes the internal Git server hostname and port which may be considered sensitive infrastructure information. #ai-review-inline
targetRevision: HEAD
path: infra/overlays/upc-dev/forte-drop-postgresql/resources
destination:
server: https://kubernetes.default.svc
namespace: forte-drop
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- Validate=true
- ServerSideApply=true
ignoreDifferences:
- group: apps
kind: StatefulSet
jsonPointers:
- /spec/volumeClaimTemplates

View File

@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
jorgen.stensrud marked this conversation as resolved
Review

Missing namespace field in Kustomization which is required for proper resource scoping.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: upc-dev
resources:
- forte-drop-postgresql.yaml

#ai-review-inline

Missing namespace field in Kustomization which is required for proper resource scoping. ```suggestion apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: upc-dev resources: - forte-drop-postgresql.yaml ``` #ai-review-inline
kind: Kustomization
resources:
- forte-drop-postgresql.yaml

View File

@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
jorgen.stensrud marked this conversation as resolved
Review

Remove inline comment '# added' as it appears to be temporary diff annotation.

apiVersion: kustomize.config.k8s.io/v1beta1

#ai-review-inline

Remove inline comment '# added' as it appears to be temporary diff annotation. ```suggestion apiVersion: kustomize.config.k8s.io/v1beta1 ``` #ai-review-inline
kind: Kustomization
jorgen.stensrud marked this conversation as resolved
Review

Remove inline comment '# added' as it appears to be temporary diff annotation.

kind: Kustomization

#ai-review-inline

Remove inline comment '# added' as it appears to be temporary diff annotation. ```suggestion kind: Kustomization ``` #ai-review-inline
resources:
jorgen.stensrud marked this conversation as resolved
Review

Remove inline comment '# added' as it appears to be temporary diff annotation.

resources:

#ai-review-inline

Remove inline comment '# added' as it appears to be temporary diff annotation. ```suggestion resources: ``` #ai-review-inline
- postgresql.yaml
jorgen.stensrud marked this conversation as resolved
Review

Remove inline comment '# added' as it appears to be temporary diff annotation.

- postgresql.yaml

#ai-review-inline

Remove inline comment '# added' as it appears to be temporary diff annotation. ```suggestion - postgresql.yaml ``` #ai-review-inline
- forte-drop-pg-creds-sealed.yaml
jorgen.stensrud marked this conversation as resolved
Review

Remove inline comment '# added' as it appears to be temporary diff annotation.

- forte-drop-pg-creds-sealed.yaml

#ai-review-inline

Remove inline comment '# added' as it appears to be temporary diff annotation. ```suggestion - forte-drop-pg-creds-sealed.yaml ``` #ai-review-inline

View File

@@ -0,0 +1,99 @@
apiVersion: v1
kind: Service
metadata:
name: forte-drop-postgresql
namespace: forte-drop
labels:
app.kubernetes.io/name: postgresql
app.kubernetes.io/instance: forte-drop
app.kubernetes.io/component: database
spec:
type: ClusterIP
ports:
- name: tcp-postgresql
port: 5432
targetPort: tcp-postgresql
selector:
app.kubernetes.io/name: postgresql
app.kubernetes.io/instance: forte-drop
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: forte-drop-postgresql
namespace: forte-drop
labels:
app.kubernetes.io/name: postgresql
app.kubernetes.io/instance: forte-drop
app.kubernetes.io/component: database
spec:
serviceName: forte-drop-postgresql
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: postgresql
app.kubernetes.io/instance: forte-drop
template:
metadata:
labels:
app.kubernetes.io/name: postgresql
app.kubernetes.io/instance: forte-drop
app.kubernetes.io/component: database
spec:
containers:
jorgen.stensrud marked this conversation as resolved
Review

Container is missing securityContext which should be set for security best practices.

      containers:
      - name: postgresql
        securityContext:
          runAsNonRoot: true
          runAsUser: 999
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: false

#ai-review-inline

Container is missing securityContext which should be set for security best practices. ```suggestion containers: - name: postgresql securityContext: runAsNonRoot: true runAsUser: 999 allowPrivilegeEscalation: false readOnlyRootFilesystem: false ``` #ai-review-inline
- name: postgresql
image: postgres:16-alpine
jorgen.stensrud marked this conversation as resolved
Review

Container image should use a pinned digest or exact tag instead of 'postgres:16-alpine' for better security and reproducibility.

        image: postgres:16.1-alpine

#ai-review-inline

Container image should use a pinned digest or exact tag instead of 'postgres:16-alpine' for better security and reproducibility. ```suggestion image: postgres:16.1-alpine ``` #ai-review-inline
ports:
- name: tcp-postgresql
containerPort: 5432
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: forte-drop-pg-creds
key: pgusername
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: forte-drop-pg-creds
key: pgpassword
- name: POSTGRES_DB
value: drops
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
livenessProbe:
exec:
command:
- sh
- -c
- pg_isready -U "$POSTGRES_USER" -d drops
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- sh
- -c
- pg_isready -U "$POSTGRES_USER" -d drops
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes:
- ReadWriteOnce
storageClassName: upcloud-block-storage-maxiops
resources:
requests:
storage: 5Gi

View File

@@ -4,6 +4,8 @@ resources:
- ../../base
- vaultwarden-postgresql
- vaultwarden
- forte-drop-postgresql
- forte-drop-minio
# No patches needed — base already has "upc-dev" paths
# upc-dev is the default/base cluster