# Kubernetes Deployment Example for CMS API ## 🔐 ایجاد Secrets ### برای Staging: ```bash kubectl create secret generic cms-secrets \ --from-literal=db-connection="Data Source=STAGING_SERVER;Initial Catalog=Foursat_Staging;User ID=sa;Password=STAGING_PASSWORD;MultipleActiveResultSets=True;Encrypt=False" \ --from-literal=jwt-key="YOUR_STAGING_JWT_KEY" \ --from-literal=kavenegar-key="YOUR_STAGING_KAVENEGAR_KEY" \ --from-literal=daya-key="YOUR_STAGING_DAYA_KEY" \ --from-literal=chatika-key="YOUR_STAGING_CHATIKA_KEY" \ --from-literal=sentry-dsn="YOUR_STAGING_SENTRY_DSN" \ --from-literal=slack-webhook="YOUR_STAGING_SLACK_WEBHOOK" \ --from-literal=seq-key="YOUR_STAGING_SEQ_KEY" \ --namespace=staging ``` ### برای Production: ```bash kubectl create secret generic cms-secrets \ --from-literal=db-connection="Data Source=PRODUCTION_SERVER;Initial Catalog=Foursat;User ID=sa;Password=PRODUCTION_PASSWORD;MultipleActiveResultSets=True;Encrypt=True" \ --from-literal=jwt-key="YOUR_PRODUCTION_JWT_KEY" \ --from-literal=kavenegar-key="YOUR_PRODUCTION_KAVENEGAR_KEY" \ --from-literal=daya-key="YOUR_PRODUCTION_DAYA_KEY" \ --from-literal=chatika-key="YOUR_PRODUCTION_CHATIKA_KEY" \ --from-literal=sentry-dsn="YOUR_PRODUCTION_SENTRY_DSN" \ --from-literal=slack-webhook="YOUR_PRODUCTION_SLACK_WEBHOOK" \ --from-literal=seq-key="YOUR_PRODUCTION_SEQ_KEY" \ --from-literal=smtp-username="production@domain.com" \ --from-literal=smtp-password="YOUR_SMTP_PASSWORD" \ --namespace=production ``` --- ## 📄 Deployment Manifest ### cms-deployment-staging.yaml ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: cms-api namespace: staging labels: app: cms-api environment: staging spec: replicas: 2 selector: matchLabels: app: cms-api template: metadata: labels: app: cms-api environment: staging spec: containers: - name: cms image: your-registry/cms-api:staging-latest ports: - containerPort: 5000 name: grpc protocol: TCP - containerPort: 8080 name: http protocol: TCP env: # Environment - name: ASPNETCORE_ENVIRONMENT value: "Staging" # Database - name: ConnectionStrings__DefaultConnection valueFrom: secretKeyRef: name: cms-secrets key: db-connection # JWT - name: JwtSecurityKey valueFrom: secretKeyRef: name: cms-secrets key: jwt-key # SMS - name: Sms__KavenegarApiKey valueFrom: secretKeyRef: name: cms-secrets key: kavenegar-key # Daya API - name: DayaApi__MerchantPermissionKey valueFrom: secretKeyRef: name: cms-secrets key: daya-key # Chatika - name: Chatika__ApiKey valueFrom: secretKeyRef: name: cms-secrets key: chatika-key # Monitoring - name: Monitoring__SentryDsn valueFrom: secretKeyRef: name: cms-secrets key: sentry-dsn - name: Monitoring__SlackWebhookUrl valueFrom: secretKeyRef: name: cms-secrets key: slack-webhook # Seq - name: Seq__ApiKey valueFrom: secretKeyRef: name: cms-secrets key: seq-key resources: requests: memory: "512Mi" cpu: "250m" limits: memory: "1Gi" cpu: "500m" 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 --- apiVersion: v1 kind: Service metadata: name: cms-api-service namespace: staging spec: selector: app: cms-api ports: - name: grpc port: 5000 targetPort: 5000 protocol: TCP - name: http port: 8080 targetPort: 8080 protocol: TCP type: ClusterIP --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: cms-api-ingress namespace: staging annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - cms-staging.domain.com secretName: cms-staging-tls rules: - host: cms-staging.domain.com http: paths: - path: / pathType: Prefix backend: service: name: cms-api-service port: number: 8080 ``` ### cms-deployment-production.yaml ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: cms-api namespace: production labels: app: cms-api environment: production spec: replicas: 3 # بیشتر برای production selector: matchLabels: app: cms-api template: metadata: labels: app: cms-api environment: production spec: containers: - name: cms image: your-registry/cms-api:production-latest ports: - containerPort: 5000 name: grpc - containerPort: 8080 name: http env: - name: ASPNETCORE_ENVIRONMENT value: "Production" # همان تنظیمات secrets مثل staging - name: ConnectionStrings__DefaultConnection valueFrom: secretKeyRef: name: cms-secrets key: db-connection - name: JwtSecurityKey valueFrom: secretKeyRef: name: cms-secrets key: jwt-key - name: Sms__KavenegarApiKey valueFrom: secretKeyRef: name: cms-secrets key: kavenegar-key - name: DayaApi__MerchantPermissionKey valueFrom: secretKeyRef: name: cms-secrets key: daya-key - name: Chatika__ApiKey valueFrom: secretKeyRef: name: cms-secrets key: chatika-key - name: Monitoring__SentryDsn valueFrom: secretKeyRef: name: cms-secrets key: sentry-dsn - name: Monitoring__SlackWebhookUrl valueFrom: secretKeyRef: name: cms-secrets key: slack-webhook - name: Seq__ApiKey valueFrom: secretKeyRef: name: cms-secrets key: seq-key # Email credentials for production - name: Email__SmtpUsername valueFrom: secretKeyRef: name: cms-secrets key: smtp-username - name: Email__SmtpPassword valueFrom: secretKeyRef: name: cms-secrets key: smtp-password resources: requests: memory: "1Gi" cpu: "500m" limits: memory: "2Gi" cpu: "1000m" livenessProbe: httpGet: path: /health/live port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /health/ready port: 8080 initialDelaySeconds: 10 periodSeconds: 5 --- apiVersion: v1 kind: Service metadata: name: cms-api-service namespace: production spec: selector: app: cms-api ports: - name: grpc port: 5000 targetPort: 5000 - name: http port: 8080 targetPort: 8080 type: ClusterIP --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: cms-api-ingress namespace: production annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - cms.domain.com secretName: cms-production-tls rules: - host: cms.domain.com http: paths: - path: / pathType: Prefix backend: service: name: cms-api-service port: number: 8080 ``` --- ## 🚀 Deploy Commands ### Staging: ```bash kubectl apply -f cms-deployment-staging.yaml kubectl get pods -n staging kubectl logs -f deployment/cms-api -n staging ``` ### Production: ```bash kubectl apply -f cms-deployment-production.yaml kubectl get pods -n production kubectl logs -f deployment/cms-api -n production ``` --- ## 🔄 CI/CD Integration ### GitLab CI Example: ```yaml stages: - build - deploy-staging - deploy-production variables: DOCKER_REGISTRY: your-registry.azurecr.io IMAGE_NAME: cms-api build: stage: build script: - docker build -t $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA . - docker push $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA deploy-staging: stage: deploy-staging only: - kub-stage script: - kubectl set image deployment/cms-api cms=$DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA -n staging - kubectl rollout status deployment/cms-api -n staging deploy-production: stage: deploy-production only: - production when: manual # نیاز به تأیید دستی script: - kubectl set image deployment/cms-api cms=$DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA -n production - kubectl rollout status deployment/cms-api -n production ``` --- ## 📋 Monitoring ### Check deployment status: ```bash kubectl get deployments -n staging kubectl get pods -n staging -l app=cms-api kubectl describe pod -n staging ``` ### View logs: ```bash kubectl logs -f deployment/cms-api -n staging kubectl logs --tail=100 deployment/cms-api -n production ``` ### Check configuration: ```bash kubectl exec -it -n staging -- env | grep ASPNETCORE ```