--- apiVersion: v1 kind: Namespace metadata: name: tandoor --- # kubectl -n tandoor create secret generic recipes --from-literal=postgresql-password=$(openssl rand -base64 33) --from-literal=postgresql-postgres-password=$(openssl rand -base64 33) --from-literal=secret-key=$(openssl rand -hex 32) #kind: Secret #apiVersion: v1 #metadata: # name: recipes # namespace: tandoor #type: Opaque #data: # postgresql-password: ... # postgresql-postgres-password: ... # secret-key: ... --- kind: ConfigMap apiVersion: v1 metadata: labels: app: recipes name: recipes-nginx-config namespace: tandoor data: nginx-config: |- events { worker_connections 1024; } http { include mime.types; server { listen 80; server_name _; client_max_body_size 16M; # serve static files location /static/ { alias /static/; } # serve media files location /media/ { alias /media/; } } } --- apiVersion: v1 kind: ServiceAccount metadata: name: recipes namespace: tandoor --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: recipes-media namespace: tandoor labels: app: recipes spec: accessModes: - ReadWriteMany resources: requests: storage: 100Gi storageClassName: rook-cephfs --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: recipes-static namespace: tandoor labels: app: recipes spec: accessModes: - ReadWriteMany resources: requests: storage: 100Gi storageClassName: rook-cephfs --- apiVersion: apps/v1 kind: StatefulSet metadata: labels: app: recipes tier: database name: recipes-postgresql namespace: tandoor spec: replicas: 1 selector: matchLabels: app: recipes serviceName: recipes-postgresql updateStrategy: type: RollingUpdate template: metadata: annotations: backup.velero.io/backup-volumes: data labels: app: recipes tier: database name: recipes-postgresql spec: containers: - name: recipes-db env: - name: BITNAMI_DEBUG value: "false" - name: POSTGRESQL_PORT_NUMBER value: "5432" - name: POSTGRESQL_VOLUME_DIR value: /bitnami/postgresql - name: PGDATA value: /bitnami/postgresql/data - name: POSTGRES_USER value: recipes - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: recipes key: postgresql-password - name: POSTGRESQL_POSTGRES_PASSWORD valueFrom: secretKeyRef: name: recipes key: postgresql-postgres-password - name: POSTGRES_DB value: recipes image: docker.io/bitnami/postgresql:15.5.0-debian-11-r17 imagePullPolicy: IfNotPresent livenessProbe: exec: command: - sh - -c - exec pg_isready -U "postgres" -d "wiki" -h 127.0.0.1 -p 5432 failureThreshold: 6 initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5 ports: - containerPort: 5432 name: postgresql protocol: TCP readinessProbe: exec: command: - sh - -c - -e - | pg_isready -U "postgres" -d "wiki" -h 127.0.0.1 -p 5432 [ -f /opt/bitnami/postgresql/tmp/.initialized ] failureThreshold: 6 initialDelaySeconds: 5 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5 resources: requests: cpu: 250m memory: 256Mi securityContext: runAsUser: 1001 terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /bitnami/postgresql name: data dnsPolicy: ClusterFirst initContainers: - command: - sh - -c - | mkdir -p /bitnami/postgresql/data chmod 700 /bitnami/postgresql/data find /bitnami/postgresql -mindepth 0 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | \ xargs chown -R 1001:1001 image: docker.io/bitnami/minideb:stretch imagePullPolicy: Always name: init-chmod-data resources: requests: cpu: 250m memory: 256Mi securityContext: runAsUser: 0 volumeMounts: - mountPath: /bitnami/postgresql name: data restartPolicy: Always securityContext: fsGroup: 1001 serviceAccount: recipes serviceAccountName: recipes terminationGracePeriodSeconds: 30 volumeClaimTemplates: - apiVersion: v1 kind: PersistentVolumeClaim metadata: name: data spec: accessModes: - ReadWriteOnce resources: requests: storage: 50Gi volumeMode: Filesystem storageClassName: rook-ssd-block --- apiVersion: v1 kind: Service metadata: labels: app: recipes tier: database name: recipes-postgresql namespace: tandoor spec: ports: - name: postgresql port: 5432 protocol: TCP targetPort: postgresql selector: app: recipes tier: database sessionAffinity: None type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: recipes namespace: tandoor labels: app: recipes environment: production tier: frontend spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: recipes environment: production template: metadata: annotations: backup.velero.io/backup-volumes: media,static labels: app: recipes tier: frontend environment: production spec: restartPolicy: Always serviceAccount: recipes serviceAccountName: recipes initContainers: - name: init-chmod-data env: - name: SECRET_KEY valueFrom: secretKeyRef: name: recipes key: secret-key - name: DB_ENGINE value: django.db.backends.postgresql - name: POSTGRES_HOST value: recipes-postgresql - name: POSTGRES_PORT value: "5432" - name: POSTGRES_USER value: postgres - name: POSTGRES_DB value: recipes - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: recipes key: postgresql-postgres-password image: vabene1111/recipes imagePullPolicy: Always resources: requests: cpu: 250m memory: 64Mi command: - sh - -c - | set -e source venv/bin/activate echo "Updating database" python manage.py migrate python manage.py collectstatic_js_reverse python manage.py collectstatic --noinput echo "Setting media file attributes" chown -R 65534:65534 /opt/recipes/mediafiles find /opt/recipes/mediafiles -type d | xargs -r chmod 755 find /opt/recipes/mediafiles -type f | xargs -r chmod 644 echo "Done" securityContext: runAsUser: 0 volumeMounts: - mountPath: /opt/recipes/mediafiles name: media # mount as subPath due to lost+found on ext4 pvc subPath: files - mountPath: /opt/recipes/staticfiles name: static # mount as subPath due to lost+found on ext4 pvc subPath: files containers: - name: recipes-nginx image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80 protocol: TCP name: http - containerPort: 8080 protocol: TCP name: gunicorn resources: requests: cpu: 250m memory: 64Mi volumeMounts: - mountPath: /media name: media # mount as subPath due to lost+found on ext4 pvc subPath: files - mountPath: /static name: static # mount as subPath due to lost+found on ext4 pvc subPath: files - name: nginx-config mountPath: /etc/nginx/nginx.conf subPath: nginx-config readOnly: true - name: recipes image: vabene1111/recipes imagePullPolicy: IfNotPresent command: - /opt/recipes/venv/bin/gunicorn - -b - :8080 - --access-logfile - "-" - --error-logfile - "-" - --log-level - INFO - recipes.wsgi livenessProbe: failureThreshold: 3 httpGet: path: / port: 8080 scheme: HTTP periodSeconds: 30 readinessProbe: httpGet: path: / port: 8080 scheme: HTTP periodSeconds: 30 resources: requests: cpu: 250m memory: 64Mi volumeMounts: - mountPath: /opt/recipes/mediafiles name: media # mount as subPath due to lost+found on ext4 pvc subPath: files - mountPath: /opt/recipes/staticfiles name: static # mount as subPath due to lost+found on ext4 pvc subPath: files env: - name: DEBUG value: "0" - name: ALLOWED_HOSTS value: '*' - name: SECRET_KEY valueFrom: secretKeyRef: name: recipes key: secret-key - name: GUNICORN_MEDIA value: "0" - name: DB_ENGINE value: django.db.backends.postgresql - name: POSTGRES_HOST value: recipes-postgresql - name: POSTGRES_PORT value: "5432" - name: POSTGRES_USER value: postgres - name: POSTGRES_DB value: recipes - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: recipes key: postgresql-postgres-password securityContext: runAsUser: 65534 volumes: - name: media persistentVolumeClaim: claimName: recipes-media - name: static persistentVolumeClaim: claimName: recipes-static - name: nginx-config configMap: name: recipes-nginx-config --- apiVersion: v1 kind: Service metadata: name: recipes namespace: tandoor labels: app: recipes tier: frontend spec: selector: app: recipes tier: frontend environment: production ports: - port: 80 targetPort: http name: http protocol: TCP - port: 8080 targetPort: gunicorn name: gunicorn protocol: TCP --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/tls-acme: "true" cert-manager.io/cluster-issuer: letsencrypt-prod name: recipes namespace: tandoor spec: ingressClassName: nginx rules: - host: recipes.tblflp.net http: paths: - backend: service: name: recipes port: number: 8080 path: / pathType: Prefix - backend: service: name: recipes port: number: 80 path: /media pathType: Prefix - backend: service: name: recipes port: number: 80 path: /static pathType: Prefix tls: - hosts: - recipes.tblflp.net secretName: recipes-local-tls