From 57a2968d7433fd71a7e4669de0487380e982083d Mon Sep 17 00:00:00 2001 From: tusuii Date: Tue, 10 Mar 2026 22:39:47 +0530 Subject: [PATCH] added k8s files and jenkinsfile --- Dockerfile | 2 +- Jenkinsfile | 130 +++++++++++++++ k8s/backend/00-namespace.yaml | 4 + k8s/backend/configmap.yaml | 25 +++ k8s/backend/deployment.yaml | 45 +++++ k8s/backend/ingress.yaml | 20 +++ k8s/backend/migration-job.yaml | 22 +++ k8s/backend/secret.yaml | 17 ++ k8s/backend/service.yaml | 13 ++ k8s/database/00-namespace.yaml | 4 + k8s/database/DATABASE-SETUP.md | 218 +++++++++++++++++++++++++ k8s/database/mongodb-pvc.yaml | 11 ++ k8s/database/mongodb-service.yaml | 13 ++ k8s/database/mongodb-statefulset.yaml | 45 +++++ k8s/database/nginx-tcp-configmap.yaml | 27 +++ k8s/database/postgres-pvc.yaml | 11 ++ k8s/database/postgres-secret.yaml | 11 ++ k8s/database/postgres-service.yaml | 13 ++ k8s/database/postgres-statefulset.yaml | 67 ++++++++ k8s/database/redis-pvc.yaml | 11 ++ k8s/database/redis-service.yaml | 12 ++ k8s/database/redis-statefulset.yaml | 47 ++++++ 22 files changed, 767 insertions(+), 1 deletion(-) create mode 100644 Jenkinsfile create mode 100644 k8s/backend/00-namespace.yaml create mode 100644 k8s/backend/configmap.yaml create mode 100644 k8s/backend/deployment.yaml create mode 100644 k8s/backend/ingress.yaml create mode 100644 k8s/backend/migration-job.yaml create mode 100644 k8s/backend/secret.yaml create mode 100644 k8s/backend/service.yaml create mode 100644 k8s/database/00-namespace.yaml create mode 100644 k8s/database/DATABASE-SETUP.md create mode 100644 k8s/database/mongodb-pvc.yaml create mode 100644 k8s/database/mongodb-service.yaml create mode 100644 k8s/database/mongodb-statefulset.yaml create mode 100644 k8s/database/nginx-tcp-configmap.yaml create mode 100644 k8s/database/postgres-pvc.yaml create mode 100644 k8s/database/postgres-secret.yaml create mode 100644 k8s/database/postgres-service.yaml create mode 100644 k8s/database/postgres-statefulset.yaml create mode 100644 k8s/database/redis-pvc.yaml create mode 100644 k8s/database/redis-service.yaml create mode 100644 k8s/database/redis-statefulset.yaml diff --git a/Dockerfile b/Dockerfile index 48c56c6..ccdee84 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20-bullseye-slim +FROM mirror.gcr.io/library/node:20-bullseye-slim WORKDIR /app diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..693278f --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,130 @@ +pipeline { + agent any + + parameters { + string( + name: 'NODE_IP', + defaultValue: '192.168.108.200', + description: 'On-premise Kubernetes node IP' + ) + } + + environment { + HARBOR = '192.168.108.200:80' + IMAGE = '192.168.108.200:80/vaishnavi-ecommerce/backend' + OLD_IMAGE = '192.168.49.2:30004/vaishnavi-ecommerce/backend:latest' + TAG = "${env.BUILD_NUMBER}" + NAMESPACE = 'ecommerce' + K8S_DIR = 'k8s/backend' + } + + stages { + stage('Build Image') { + steps { + sh "docker build -t ${IMAGE}:${TAG} -t ${IMAGE}:latest ." + } + } + + stage('Push to Harbor') { + steps { + withCredentials([usernamePassword( + credentialsId: 'harbor-credentials', + usernameVariable: 'HARBOR_USER', + passwordVariable: 'HARBOR_PASS' + )]) { + sh """ + echo "\$HARBOR_PASS" | docker login ${HARBOR} -u "\$HARBOR_USER" --password-stdin + docker push ${IMAGE}:${TAG} + docker push ${IMAGE}:latest + """ + } + } + } + + stage('Apply Namespace') { + steps { + withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) { + sh "kubectl apply -f ${K8S_DIR}/00-namespace.yaml" + } + } + } + + stage('Apply ConfigMap') { + steps { + withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) { + sh """ + sed "s/NODE_IP_PLACEHOLDER/${params.NODE_IP}/g" \ + ${K8S_DIR}/configmap.yaml | kubectl apply -f - + """ + } + } + } + + stage('Apply Secret') { + steps { + withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) { + sh "kubectl apply -f ${K8S_DIR}/secret.yaml" + } + } + } + + stage('Run Migration') { + steps { + withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) { + sh """ + kubectl delete job backend-migration -n ${NAMESPACE} --ignore-not-found=true + + sed "s|${OLD_IMAGE}|${IMAGE}:${TAG}|g" \ + ${K8S_DIR}/migration-job.yaml | kubectl apply -f - + + kubectl wait --for=condition=complete job/backend-migration \ + -n ${NAMESPACE} --timeout=120s + """ + } + } + } + + stage('Deploy Backend') { + steps { + withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) { + sh """ + sed "s|${OLD_IMAGE}|${IMAGE}:${TAG}|g" \ + ${K8S_DIR}/deployment.yaml | kubectl apply -f - + kubectl apply -f ${K8S_DIR}/service.yaml + kubectl apply -f ${K8S_DIR}/ingress.yaml + """ + } + } + } + + stage('Verify Rollout') { + steps { + withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) { + sh "kubectl rollout status deployment/backend -n ${NAMESPACE} --timeout=180s" + } + } + } + + stage('Smoke Test') { + steps { + sh "curl -f http://${params.NODE_IP}:30080/health" + } + } + } + + post { + always { + sh "docker rmi ${IMAGE}:${TAG} || true" + sh "docker rmi ${IMAGE}:latest || true" + } + success { + echo "Deploy successful. Backend accessible at http://${params.NODE_IP}:30080" + } + failure { + withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) { + sh "kubectl get pods -n ${NAMESPACE} || true" + sh "kubectl describe deployment/backend -n ${NAMESPACE} || true" + } + } + } +} diff --git a/k8s/backend/00-namespace.yaml b/k8s/backend/00-namespace.yaml new file mode 100644 index 0000000..1da536c --- /dev/null +++ b/k8s/backend/00-namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: ecommerce diff --git a/k8s/backend/configmap.yaml b/k8s/backend/configmap.yaml new file mode 100644 index 0000000..d2072a1 --- /dev/null +++ b/k8s/backend/configmap.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: backend-configmap + namespace: ecommerce +data: + NODE_ENV: "production" + PORT: "3000" + SEND_REAL_WHATSAPP: "false" + MONGODB_URI: "mongodb://mongodb.database.svc.cluster.local:27017/vaishnavi_products" + REDIS_URL: "redis://redis.database.svc.cluster.local:6379" + AWS_REGION: "us-east-1" + AWS_S3_BUCKET: "e-commerce" + AWS_ENDPOINT: "s3.sahasrarameta.tech" + AWS_PORT: "443" + AWS_SSL: "true" + JWT_EXPIRES_IN: "7d" + JWT_REFRESH_EXPIRES_IN: "30d" + FRONTEND_URL: "http://NODE_IP_PLACEHOLDER:30081" + CORS_ORIGIN: "http://NODE_IP_PLACEHOLDER:30081,http://NODE_IP_PLACEHOLDER:30082,https://vaishnavi-admin.myriadcara.in,https://vaishnavi-bakend.myriadcara.in,https://vaishnavi-test.myriadcara.in" + PAYTM_WEBSITE: "WEBSTAGING" + PAYTM_HOST: "securegw-stage.paytm.in" + PAYTM_CALLBACK_URL: "http://NODE_IP_PLACEHOLDER:30080/api/payments/paytm/callback" + WAPP_BASE_URL: "https://api.wappconnect.com" + WAPP_INSTANCE: "SSM" diff --git a/k8s/backend/deployment.yaml b/k8s/backend/deployment.yaml new file mode 100644 index 0000000..b81185b --- /dev/null +++ b/k8s/backend/deployment.yaml @@ -0,0 +1,45 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backend + namespace: ecommerce +spec: + replicas: 1 + selector: + matchLabels: + app: backend + template: + metadata: + labels: + app: backend + spec: + containers: + - name: backend + image: 192.168.49.2:30004/vaishnavi-ecommerce/backend:latest + imagePullPolicy: Always + ports: + - containerPort: 3000 + envFrom: + - configMapRef: + name: backend-configmap + - secretRef: + name: backend-secret + resources: + requests: + cpu: "250m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "512Mi" + livenessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 30 + periodSeconds: 15 + readinessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 10 + periodSeconds: 5 diff --git a/k8s/backend/ingress.yaml b/k8s/backend/ingress.yaml new file mode 100644 index 0000000..c56bfaf --- /dev/null +++ b/k8s/backend/ingress.yaml @@ -0,0 +1,20 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: backend-ingress + namespace: ecommerce + annotations: + nginx.ingress.kubernetes.io/proxy-body-size: "10m" +spec: + ingressClassName: nginx + rules: + - host: backend.local + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: backend + port: + number: 3000 diff --git a/k8s/backend/migration-job.yaml b/k8s/backend/migration-job.yaml new file mode 100644 index 0000000..5daed0f --- /dev/null +++ b/k8s/backend/migration-job.yaml @@ -0,0 +1,22 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: backend-migration + namespace: ecommerce +spec: + template: + spec: + containers: + - name: migration + image: 192.168.49.2:30004/vaishnavi-ecommerce/backend:latest + imagePullPolicy: Always + command: + - npx + - prisma + - db + - push + envFrom: + - secretRef: + name: backend-secret + restartPolicy: Never + backoffLimit: 3 diff --git a/k8s/backend/secret.yaml b/k8s/backend/secret.yaml new file mode 100644 index 0000000..d50ac8c --- /dev/null +++ b/k8s/backend/secret.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Secret +metadata: + name: backend-secret + namespace: ecommerce +type: Opaque +data: + DATABASE_URL: cG9zdGdyZXNxbDovL3ZhaXNobmF2aTphZG1pbkBwb3N0Z3Jlcy5kYXRhYmFzZS5zdmMuY2x1c3Rlci5sb2NhbDo1NDMyL3ZhaXNobmF2aV9kYj9zY2hlbWE9cHVibGlj + JWT_SECRET: eW91ci1zdXBlci1zZWNyZXQtand0LWtleS1jaGFuZ2UtdGhpcy1pbi1wcm9kdWN0aW9u + JWT_REFRESH_SECRET: eW91ci1yZWZyZXNoLXRva2VuLXNlY3JldA== + AWS_ACCESS_KEY_ID: dUE3V3ZUOWZoeWRjb3p5ejVhbG8= + AWS_SECRET_ACCESS_KEY: QXVzRXk2S0txYW5RUVUzWnczclhZQmFpUzVCTThhUG9BS2ZwY2JGcg== + EMAIL_USER: dmFpYmhhdi5zYWhhc3JhcmFAZ21haWwuY29t + EMAIL_PASS: cGV6amN4Zm5lZ2d1emt1aA== + PAYTM_MERCHANT_ID: eW91cl9tZXJjaGFudF9pZA== + PAYTM_MERCHANT_KEY: YWJjZDEyMzRhYmNkMTIzNA== + WAPP_TOKEN: Y2x6Z2t0emRiYXdzNW1nZHU3c3M1YTRyYQ== diff --git a/k8s/backend/service.yaml b/k8s/backend/service.yaml new file mode 100644 index 0000000..d98fae2 --- /dev/null +++ b/k8s/backend/service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: backend + namespace: ecommerce +spec: + type: NodePort + selector: + app: backend + ports: + - port: 3000 + targetPort: 3000 + nodePort: 30080 diff --git a/k8s/database/00-namespace.yaml b/k8s/database/00-namespace.yaml new file mode 100644 index 0000000..49f912e --- /dev/null +++ b/k8s/database/00-namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: database diff --git a/k8s/database/DATABASE-SETUP.md b/k8s/database/DATABASE-SETUP.md new file mode 100644 index 0000000..74fad9e --- /dev/null +++ b/k8s/database/DATABASE-SETUP.md @@ -0,0 +1,218 @@ +# Database Namespace — Setup & On-Premise Replication Guide + +Covers PostgreSQL 16 and MongoDB 7 deployed in the `database` Kubernetes namespace. +Verified working on: **minikube** (local dev). On-premise steps are in [Section 4](#4-on-premise-replication). + +--- + +## 1. What's Deployed + +| Resource | Namespace | Details | +|---|---|---| +| StatefulSet `postgres` | `database` | `postgres:16`, 1 replica, 5 Gi PVC | +| StatefulSet `mongodb` | `database` | `mongo:7`, 1 replica, 5 Gi PVC, no auth | +| Service `postgres` | `database` | ClusterIP, port 5432 | +| Service `mongodb` | `database` | ClusterIP, port 27017 | +| Secret `postgres-secret` | `database` | DB name, user, password, DATABASE_URL | +| PVC `postgres-pvc` | `database` | 5 Gi, ReadWriteOnce | +| PVC `mongodb-pvc` | `database` | 5 Gi, ReadWriteOnce | +| ConfigMap `tcp-services` | `ingress-nginx` | TCP passthrough for external PostgreSQL access | + +--- + +## 2. Connection Strings + +| Consumer | URL | +|---|---| +| Backend pod (in-cluster) | `postgresql://vaishnavi:admin@postgres.database.svc.cluster.local:5432/vaishnavi_db?schema=public` | +| Backend pod (in-cluster) | `mongodb://mongodb.database.svc.cluster.local:27017/vaishnavi_products` | +| External / pgAdmin (host) | `postgresql://vaishnavi:admin@postgres.local:5432/vaishnavi_db` | + +--- + +## 3. File Structure + +``` +k8s/database/ +├── 00-namespace.yaml # database namespace +├── postgres-secret.yaml # base64-encoded credentials + DATABASE_URL +├── postgres-pvc.yaml # 5 Gi PVC +├── postgres-statefulset.yaml # postgres:16 StatefulSet +├── postgres-service.yaml # ClusterIP :5432 +├── mongodb-pvc.yaml # 5 Gi PVC +├── mongodb-statefulset.yaml # mongo:7 StatefulSet, no auth +├── mongodb-service.yaml # ClusterIP :27017 +└── nginx-tcp-configmap.yaml # TCP passthrough for postgres.local:5432 +``` + +--- + +## 4. On-Premise Replication + +### 4.1 Prerequisites + +- Kubernetes cluster (kubeadm, k3s, RKE2, or similar) with at least 1 worker node +- `kubectl` configured with cluster-admin rights +- A StorageClass that supports `ReadWriteOnce` PVCs + Common options: + - `local-path` (Rancher Local Path Provisioner — simplest for single-node) + - `longhorn` (multi-node HA storage) + - NFS provisioner +- Ingress-NGINX controller deployed (`kubectl get pods -n ingress-nginx`) + +--- + +### 4.2 StorageClass: Install Local Path Provisioner (if needed) + +```bash +kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml + +# Set as default if no other default exists +kubectl patch storageclass local-path \ + -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' +``` + +--- + +### 4.3 Deploy the Databases + +```bash +cd vaishnavi-ecommerce-backend/k8s/database + +kubectl apply -f 00-namespace.yaml +kubectl apply -f postgres-secret.yaml +kubectl apply -f postgres-pvc.yaml +kubectl apply -f postgres-statefulset.yaml +kubectl apply -f postgres-service.yaml +kubectl apply -f mongodb-pvc.yaml +kubectl apply -f mongodb-statefulset.yaml +kubectl apply -f mongodb-service.yaml +``` + +Wait for both pods to reach `Running`: +```bash +kubectl get pods -n database -w +# Expected: +# mongodb-0 1/1 Running 0 +# postgres-0 1/1 Running 0 +``` + +--- + +### 4.4 External PostgreSQL Access via TCP Ingress (optional) + +This lets you connect to PostgreSQL from outside the cluster using `postgres.local:5432`. + +**Step 1 — Apply the TCP ConfigMap:** +```bash +kubectl apply -f nginx-tcp-configmap.yaml +``` + +**Step 2 — Expose port 5432 on the ingress-nginx Service:** +```bash +kubectl patch svc ingress-nginx-controller -n ingress-nginx \ + --type='json' \ + -p='[{"op":"add","path":"/spec/ports/-","value":{"name":"postgres","port":5432,"targetPort":5432,"protocol":"TCP"}}]' +``` + +**Step 3 — Add `--tcp-services-configmap` arg to the ingress-nginx Deployment:** +```bash +kubectl patch deployment ingress-nginx-controller -n ingress-nginx \ + --type='json' \ + -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--tcp-services-configmap=ingress-nginx/tcp-services"}]' +``` + +**Step 4 — Add to `/etc/hosts` on every machine that needs external access:** +``` + postgres.local +``` +Replace `` with the IP of any cluster node (or load balancer IP if using MetalLB). + +--- + +### 4.5 Credentials / Secret Values + +The secret values are baked into `postgres-secret.yaml`. To change them: + +```bash +# Generate new base64 values +echo -n "your_password" | base64 + +# Or use kubectl to create the secret directly (bypasses base64 manual encoding) +kubectl create secret generic postgres-secret \ + --namespace=database \ + --from-literal=POSTGRES_DB=vaishnavi_db \ + --from-literal=POSTGRES_USER=vaishnavi \ + --from-literal=POSTGRES_PASSWORD=admin \ + --from-literal=DATABASE_URL="postgresql://vaishnavi:admin@postgres.database.svc.cluster.local:5432/vaishnavi_db?schema=public" \ + --dry-run=client -o yaml > postgres-secret.yaml +``` + +--- + +### 4.6 Backend ConfigMap / Secret Reference + +The backend reads DATABASE_URL and MONGODB_URI from its own configmap/secret in the `ecommerce` namespace. Ensure these point to the `database` namespace services: + +```yaml +DATABASE_URL: postgresql://vaishnavi:admin@postgres.database.svc.cluster.local:5432/vaishnavi_db?schema=public +MONGODB_URI: mongodb://mongodb.database.svc.cluster.local:27017/vaishnavi_products +``` + +--- + +## 5. Verification + +```bash +# Both pods Running +kubectl get pods -n database + +# PVCs Bound +kubectl get pvc -n database + +# Services present +kubectl get svc -n database + +# PostgreSQL accepting connections +kubectl exec -n database postgres-0 -- pg_isready -U vaishnavi -d vaishnavi_db + +# PostgreSQL — list databases +kubectl exec -n database postgres-0 -- psql -U vaishnavi -d vaishnavi_db -c '\l' + +# MongoDB ping +kubectl exec -n database mongodb-0 -- mongosh --eval "db.adminCommand('ping')" --quiet + +# In-cluster connectivity test (PostgreSQL) +kubectl run psql-test --rm -it --image=postgres:16 --restart=Never -n database -- \ + psql postgresql://vaishnavi:admin@postgres.database.svc.cluster.local:5432/vaishnavi_db -c '\l' + +# In-cluster connectivity test (MongoDB) +kubectl run mongo-test --rm -it --image=mongo:7 --restart=Never -n database -- \ + mongosh mongodb://mongodb.database.svc.cluster.local:27017/vaishnavi_products --eval "db.stats()" + +# External PostgreSQL (after TCP ingress setup + /etc/hosts) +psql postgresql://vaishnavi:admin@postgres.local:5432/vaishnavi_db -c '\l' +``` + +--- + +## 6. Teardown + +```bash +# Remove databases (data is lost when PVCs are deleted) +kubectl delete namespace database + +# Remove TCP ingress config (if applied) +kubectl delete configmap tcp-services -n ingress-nginx +``` + +To preserve data before teardown, dump first: +```bash +# PostgreSQL dump +kubectl exec -n database postgres-0 -- \ + pg_dump -U vaishnavi vaishnavi_db > vaishnavi_db_backup.sql + +# MongoDB dump +kubectl exec -n database mongodb-0 -- \ + mongodump --db vaishnavi_products --archive > vaishnavi_products_backup.archive +``` diff --git a/k8s/database/mongodb-pvc.yaml b/k8s/database/mongodb-pvc.yaml new file mode 100644 index 0000000..afc0b63 --- /dev/null +++ b/k8s/database/mongodb-pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mongodb-pvc + namespace: database +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi diff --git a/k8s/database/mongodb-service.yaml b/k8s/database/mongodb-service.yaml new file mode 100644 index 0000000..98fb84d --- /dev/null +++ b/k8s/database/mongodb-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: mongodb + namespace: database +spec: + type: ClusterIP + selector: + app: mongodb + ports: + - name: mongodb + port: 27017 + targetPort: 27017 diff --git a/k8s/database/mongodb-statefulset.yaml b/k8s/database/mongodb-statefulset.yaml new file mode 100644 index 0000000..c090a00 --- /dev/null +++ b/k8s/database/mongodb-statefulset.yaml @@ -0,0 +1,45 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: mongodb + namespace: database +spec: + serviceName: mongodb + replicas: 1 + selector: + matchLabels: + app: mongodb + template: + metadata: + labels: + app: mongodb + spec: + containers: + - name: mongodb + image: mongo:7 + ports: + - containerPort: 27017 + volumeMounts: + - name: mongodb-data + mountPath: /data/db + livenessProbe: + exec: + command: + - mongosh + - --eval + - "db.adminCommand('ping')" + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 6 + readinessProbe: + exec: + command: + - mongosh + - --eval + - "db.adminCommand('ping')" + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: mongodb-data + persistentVolumeClaim: + claimName: mongodb-pvc diff --git a/k8s/database/nginx-tcp-configmap.yaml b/k8s/database/nginx-tcp-configmap.yaml new file mode 100644 index 0000000..9054c45 --- /dev/null +++ b/k8s/database/nginx-tcp-configmap.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: tcp-services + namespace: ingress-nginx +data: + "5432": "database/postgres:5432" + +# ─── Manual one-time steps after applying this ConfigMap ───────────────────── +# +# 1. Expose port 5432 on the ingress-nginx-controller Service: +# +# kubectl patch svc ingress-nginx-controller -n ingress-nginx \ +# --type='json' \ +# -p='[{"op":"add","path":"/spec/ports/-","value":{"name":"postgres","port":5432,"targetPort":5432,"protocol":"TCP"}}]' +# +# 2. Add --tcp-services-configmap arg to the ingress-nginx-controller Deployment: +# +# kubectl patch deployment ingress-nginx-controller -n ingress-nginx \ +# --type='json' \ +# -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--tcp-services-configmap=ingress-nginx/tcp-services"}]' +# +# 3. Add to /etc/hosts on your host machine: +# +# 192.168.49.2 postgres.local +# +# ───────────────────────────────────────────────────────────────────────────── diff --git a/k8s/database/postgres-pvc.yaml b/k8s/database/postgres-pvc.yaml new file mode 100644 index 0000000..82d862e --- /dev/null +++ b/k8s/database/postgres-pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: postgres-pvc + namespace: database +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi diff --git a/k8s/database/postgres-secret.yaml b/k8s/database/postgres-secret.yaml new file mode 100644 index 0000000..dedabc0 --- /dev/null +++ b/k8s/database/postgres-secret.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Secret +metadata: + name: postgres-secret + namespace: database +type: Opaque +data: + POSTGRES_DB: dmFpc2huYXZpX2Ri # vaishnavi_db + POSTGRES_USER: dmFpc2huYXZp # vaishnavi + POSTGRES_PASSWORD: YWRtaW4= # admin + DATABASE_URL: cG9zdGdyZXNxbDovL3ZhaXNobmF2aTphZG1pbkBwb3N0Z3Jlcy5kYXRhYmFzZS5zdmMuY2x1c3Rlci5sb2NhbDo1NDMyL3ZhaXNobmF2aV9kYj9zY2hlbWE9cHVibGlj diff --git a/k8s/database/postgres-service.yaml b/k8s/database/postgres-service.yaml new file mode 100644 index 0000000..33917b6 --- /dev/null +++ b/k8s/database/postgres-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: database +spec: + type: ClusterIP + selector: + app: postgres + ports: + - name: postgres + port: 5432 + targetPort: 5432 diff --git a/k8s/database/postgres-statefulset.yaml b/k8s/database/postgres-statefulset.yaml new file mode 100644 index 0000000..a858924 --- /dev/null +++ b/k8s/database/postgres-statefulset.yaml @@ -0,0 +1,67 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: postgres + namespace: database +spec: + serviceName: postgres + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:16 + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_DB + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-secret + key: POSTGRES_PASSWORD + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + livenessProbe: + exec: + command: + - pg_isready + - -U + - $(POSTGRES_USER) + - -d + - $(POSTGRES_DB) + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 6 + readinessProbe: + exec: + command: + - pg_isready + - -U + - $(POSTGRES_USER) + - -d + - $(POSTGRES_DB) + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: postgres-pvc diff --git a/k8s/database/redis-pvc.yaml b/k8s/database/redis-pvc.yaml new file mode 100644 index 0000000..961eccd --- /dev/null +++ b/k8s/database/redis-pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-pvc + namespace: database +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi diff --git a/k8s/database/redis-service.yaml b/k8s/database/redis-service.yaml new file mode 100644 index 0000000..204f2b1 --- /dev/null +++ b/k8s/database/redis-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis + namespace: database +spec: + type: ClusterIP + selector: + app: redis + ports: + - port: 6379 + targetPort: 6379 diff --git a/k8s/database/redis-statefulset.yaml b/k8s/database/redis-statefulset.yaml new file mode 100644 index 0000000..81201cf --- /dev/null +++ b/k8s/database/redis-statefulset.yaml @@ -0,0 +1,47 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis + namespace: database +spec: + serviceName: redis + replicas: 1 + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + spec: + containers: + - name: redis + image: redis:7-alpine + command: + - redis-server + - --appendonly + - "yes" + ports: + - containerPort: 6379 + volumeMounts: + - name: redis-data + mountPath: /data + livenessProbe: + exec: + command: + - redis-cli + - ping + initialDelaySeconds: 10 + periodSeconds: 10 + failureThreshold: 6 + readinessProbe: + exec: + command: + - redis-cli + - ping + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: redis-data + persistentVolumeClaim: + claimName: redis-pvc