feat: add PersistentVolume for CMS uploads + apply manifests in CI/CD
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 12m12s

- Add k8s/staging/ and k8s/production/ deployment manifests
- PVC 20Gi for /app/Uploads (file uploads persist across pod restarts)
- FileStorage__UploadPath env var set to /app/Uploads
- Replicas reduced to 1 (ReadWriteOnce PVC)
- Pipelines now: create namespace → apply manifests → restart/update
This commit is contained in:
masoodafar-web
2026-02-23 20:11:56 +03:30
parent 8cdb197ee7
commit 3153fd8a74
4 changed files with 330 additions and 4 deletions
+10 -2
View File
@@ -86,8 +86,16 @@ jobs:
- name: Deploy to Kubernetes - name: Deploy to Kubernetes
run: | run: |
export SSHPASS="${{ secrets.SERVER_PASSWORD }}" export SSHPASS="${{ secrets.SERVER_PASSWORD }}"
# Copy K8s manifests to server
sshpass -e scp -o StrictHostKeyChecking=no k8s/staging/cms-deployment.yaml root@${{ env.K8S_SERVER }}:/tmp/cms-deployment.yaml
# Apply manifests and restart
sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} " sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} "
kubectl rollout restart deployment/cms kubectl create namespace foursat --dry-run=client -o yaml | kubectl apply -f - &&
kubectl rollout status deployment/cms --timeout=180s kubectl apply -f /tmp/cms-deployment.yaml &&
kubectl rollout restart deployment/cms -n foursat &&
kubectl rollout status deployment/cms -n foursat --timeout=180s &&
rm -f /tmp/cms-deployment.yaml
" "
echo "✅ Deployed!" echo "✅ Deployed!"
+10 -2
View File
@@ -86,8 +86,16 @@ jobs:
- name: Deploy to Production - name: Deploy to Production
run: | run: |
export SSHPASS="${{ secrets.SERVER_PASSWORD }}" export SSHPASS="${{ secrets.SERVER_PASSWORD }}"
# Copy K8s manifests to server
sshpass -e scp -o StrictHostKeyChecking=no k8s/production/cms-deployment.yaml root@${{ env.K8S_SERVER }}:/tmp/cms-deployment.yaml
# Apply manifests and update image
sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} " sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} "
kubectl set image deployment/cms cms=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} kubectl create namespace foursat --dry-run=client -o yaml | kubectl apply -f - &&
kubectl rollout status deployment/cms --timeout=300s kubectl apply -f /tmp/cms-deployment.yaml &&
kubectl set image deployment/cms cms=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} -n foursat &&
kubectl rollout status deployment/cms -n foursat --timeout=300s &&
rm -f /tmp/cms-deployment.yaml
" "
echo "✅ Deployed to Production!" echo "✅ Deployed to Production!"
+155
View File
@@ -0,0 +1,155 @@
---
# CMS Uploads PersistentVolumeClaim (Production)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cms-uploads-pvc
namespace: foursat
labels:
app: cms
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
# CMS Microservice Deployment (Production)
apiVersion: apps/v1
kind: Deployment
metadata:
name: cms
namespace: foursat
labels:
app: cms
spec:
replicas: 1
selector:
matchLabels:
app: cms
template:
metadata:
labels:
app: cms
spec:
containers:
- name: cms
image: git.se.kbs1.ir/admin/cms:prod
imagePullPolicy: Always
ports:
- containerPort: 8080
name: http
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
- name: ASPNETCORE_URLS
value: "http://+:8080"
- name: Kestrel__EndpointDefaults__Protocols
value: "Http1AndHttp2"
- name: FileStorage__UploadPath
value: "/app/Uploads"
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: postgres-secret
key: connection-string
- name: Email__Host
valueFrom:
secretKeyRef:
name: email-secret
key: smtp-host
- name: Email__Port
valueFrom:
secretKeyRef:
name: email-secret
key: smtp-port
- name: Email__Username
valueFrom:
secretKeyRef:
name: email-secret
key: smtp-username
- name: Email__Password
valueFrom:
secretKeyRef:
name: email-secret
key: smtp-password
- name: Kavenegar__ApiKey
valueFrom:
secretKeyRef:
name: sms-secret
key: api-key
volumeMounts:
- name: cms-uploads
mountPath: /app/Uploads
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumes:
- name: cms-uploads
persistentVolumeClaim:
claimName: cms-uploads-pvc
---
# CMS Service (Production)
apiVersion: v1
kind: Service
metadata:
name: cms-svc
namespace: foursat
spec:
selector:
app: cms
ports:
- name: http
port: 8080
targetPort: 8080
type: ClusterIP
---
# CMS Ingress (Production)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cms-ingress
namespace: foursat
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- cms.kbs1.ir
secretName: cms-tls
rules:
- host: cms.kbs1.ir
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: cms-svc
port:
number: 8080
+155
View File
@@ -0,0 +1,155 @@
---
# CMS Uploads PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cms-uploads-pvc
namespace: foursat
labels:
app: cms
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
# CMS Microservice Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: cms
namespace: foursat
labels:
app: cms
spec:
replicas: 1
selector:
matchLabels:
app: cms
template:
metadata:
labels:
app: cms
spec:
containers:
- name: cms
image: git.se.kbs1.ir/admin/cms:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
name: http
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
- name: ASPNETCORE_URLS
value: "http://+:8080"
- name: Kestrel__EndpointDefaults__Protocols
value: "Http1AndHttp2"
- name: FileStorage__UploadPath
value: "/app/Uploads"
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: postgres-secret
key: connection-string
- name: Email__Host
valueFrom:
secretKeyRef:
name: email-secret
key: smtp-host
- name: Email__Port
valueFrom:
secretKeyRef:
name: email-secret
key: smtp-port
- name: Email__Username
valueFrom:
secretKeyRef:
name: email-secret
key: smtp-username
- name: Email__Password
valueFrom:
secretKeyRef:
name: email-secret
key: smtp-password
- name: Kavenegar__ApiKey
valueFrom:
secretKeyRef:
name: sms-secret
key: api-key
volumeMounts:
- name: cms-uploads
mountPath: /app/Uploads
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumes:
- name: cms-uploads
persistentVolumeClaim:
claimName: cms-uploads-pvc
---
# CMS Service
apiVersion: v1
kind: Service
metadata:
name: cms-svc
namespace: foursat
spec:
selector:
app: cms
ports:
- name: http
port: 8080
targetPort: 8080
type: ClusterIP
---
# CMS Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cms-ingress
namespace: foursat
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- cms.se.kbs1.ir
secretName: cms-tls
rules:
- host: cms.se.kbs1.ir
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: cms-svc
port:
number: 8080