diff --git a/technical/TECH-03-DEPLOYMENT-INFRA.md b/technical/TECH-03-DEPLOYMENT-INFRA.md index dd896d7..a0f3d90 100644 --- a/technical/TECH-03-DEPLOYMENT-INFRA.md +++ b/technical/TECH-03-DEPLOYMENT-INFRA.md @@ -1,7 +1,7 @@ # 🚀 استقرار، CI/CD و زیرساخت > **منابع ادغام‌شده:** `CICD-PIPELINE-GUIDE.md`, `DEPLOYMENT-README.md`, `INFRASTRUCTURE-GUIDE.md`, `INGRESS-NGINX-WARNING.md`, `OFFLINE-DEPLOYMENT-GUIDE.md`, `SERVER-MIRRORS-CONFIG.md` -> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: مرج پروداکشن + تنظیمات محیطی) +> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: PersistentVolume برای آپلود فایل + اصلاح namespace + حذف secretRef) --- @@ -77,31 +77,94 @@ ENTRYPOINT ["dotnet", "CMSMicroservice.dll"] ### ۳.۱ Manifests ساختار +مانیفست‌های K8s **داخل ریپوی CMS** نگهداری می‌شن و توسط CI/CD اعمال می‌شن: + ``` -deployment/k8s-manifests/ -├── cms-deployment.yaml -├── cms-service.yaml -├── backoffice-deployment.yaml -├── backoffice-service.yaml -├── frontoffice-deployment.yaml -├── frontoffice-service.yaml -├── db-statefulset.yaml -├── db-service.yaml -├── ingress.yaml -├── configmap.yaml -└── secrets.yaml +CMS/ + k8s/ + staging/ + cms-deployment.yaml ← PVC + Deployment + Service + Ingress + production/ + cms-deployment.yaml ← PVC + Deployment + Service + Ingress ``` -### ۳.۲ مثال Deployment +> ⚠️ **هر دو محیط از namespace `default` استفاده می‌کنن.** + +### ۳.۲ PersistentVolume برای آپلود فایل + +فایل‌های آپلود‌شده (عکس محصولات، بلاگ، آواتار و ...) در `/app/Uploads` ذخیره می‌شن. +برای جلوگیری از حذف فایل‌ها با ریستارت Pod، یک **PersistentVolumeClaim** مونت شده: + +```yaml +# PVC — 20Gi ذخیره‌سازی دائمی +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: cms-uploads-pvc + namespace: default +spec: + accessModes: [ReadWriteOnce] + resources: + requests: + storage: 20Gi +``` + +```yaml +# Volume Mount در Deployment +volumeMounts: +- name: cms-uploads + mountPath: /app/Uploads +volumes: +- name: cms-uploads + persistentVolumeClaim: + claimName: cms-uploads-pvc +``` + +| تنظیم | مقدار | +|--------|-------| +| **PVC Name** | `cms-uploads-pvc` | +| **Mount Path** | `/app/Uploads` | +| **Access Mode** | `ReadWriteOnce` | +| **حجم** | `20Gi` | +| **StorageClass** | `local-path` (K3s default) | +| **Replicas** | `1` (محدودیت RWO) | + +> 💡 **نکته مهم:** چون `ReadWriteOnce` هست، فقط **1 replica** می‌تونه بنویسه. برای 2+ replica نیاز به NFS/CephFS با `ReadWriteMany` هست. + +### ۳.۳ تنظیمات محیطی (Environment Variables) + +تنظیمات حساس (ConnectionString, Email, SMS, ZarinPal) **داخل `appsettings.{Environment}.json`** در ایمیج Docker قرار دارن. +**هیچ K8s Secret استفاده نمی‌شه** — .NET خودش فایل config مربوط به environment رو می‌خونه. + +| محیط | `ASPNETCORE_ENVIRONMENT` | فایل Config | +|------|---------------------------|-------------| +| **Staging** | `Staging` | `appsettings.Staging.json` | +| **Production** | `Production` | `appsettings.Production.json` | + +env var‌های K8s manifest: + +```yaml +env: +- name: ASPNETCORE_ENVIRONMENT + value: "Staging" # یا "Production" +- name: ASPNETCORE_URLS + value: "http://+:8080" +- name: Kestrel__EndpointDefaults__Protocols + value: "Http1AndHttp2" +- name: FileStorage__UploadPath + value: "/app/Uploads" +``` + +### ۳.۴ مثال Deployment (واقعی) ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: cms - namespace: foursat + namespace: default spec: - replicas: 2 + replicas: 1 selector: matchLabels: app: cms @@ -109,104 +172,109 @@ spec: spec: containers: - name: cms - image: foursat/cms:latest + image: 194.5.195.53:30080/admin/cms:latest + imagePullPolicy: Always ports: - - containerPort: 5001 + - containerPort: 8080 + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Staging" + - name: FileStorage__UploadPath + value: "/app/Uploads" + volumeMounts: + - name: cms-uploads + mountPath: /app/Uploads resources: - requests: - memory: "256Mi" - cpu: "250m" - limits: - memory: "512Mi" - cpu: "500m" - livenessProbe: - grpc: - port: 5001 - initialDelaySeconds: 15 - readinessProbe: - grpc: - port: 5001 + requests: { memory: "512Mi", cpu: "500m" } + limits: { memory: "1Gi", cpu: "1000m" } + volumes: + - name: cms-uploads + persistentVolumeClaim: + claimName: cms-uploads-pvc ``` -### ۳.۳ Ingress +### ۳.۵ Ingress +**Staging:** ```yaml -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: foursat-ingress - annotations: - nginx.ingress.kubernetes.io/ssl-redirect: "true" - nginx.ingress.kubernetes.io/proxy-body-size: "50m" spec: + ingressClassName: nginx rules: - - host: foursat.ir - http: - paths: - - path: / - backend: - service: - name: frontoffice - port: { number: 5003 } - - path: /admin - backend: - service: - name: backoffice - port: { number: 80 } + - host: cms.se.kbs1.ir ``` -> ⚠️ **هشدار:** Ingress-nginx نسخه‌های قبل از 1.9.0 مشکل امنیتی CVE-2023-5044 دارند. حتماً بروزرسانی کنید. +**Production:** +```yaml +spec: + ingressClassName: nginx + tls: + - hosts: [cms.kbs1.ir, cms.kbs2.ir] + secretName: cms-tls + rules: + - host: cms.kbs2.ir + - host: cms.kbs1.ir +``` + +> ⚠️ **هشدار:** از `spec.ingressClassName: nginx` استفاده کنید، نه `kubernetes.io/ingress.class` annotation (deprecated). --- ## ۴. CI/CD Pipeline -### ۴.۱ Gitea Actions Workflow +### ۴.۱ Gitea Actions Workflows (CMS) -```yaml -name: Build and Deploy -on: - push: - branches: [kub-stage, production] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: '9.0.x' - - - name: Restore - run: dotnet restore - - - name: Build - run: dotnet build --no-restore -c Release - - - name: Test - run: dotnet test --no-build -c Release - - - name: Docker Build & Push - run: | - docker build -t $REGISTRY/foursat/cms:${{ github.sha }} . - docker push $REGISTRY/foursat/cms:${{ github.sha }} - - - name: Deploy to K8s - if: github.ref == 'refs/heads/production' - run: | - kubectl set image deployment/cms cms=$REGISTRY/foursat/cms:${{ github.sha }} +فایل‌های پایپلاین: +``` +CMS/.gitea/workflows/ +├── kub-deploy.yml ← Staging (branch: kub-stage) +├── prod-deploy.yml ← Production (branch: production) +└── cms-stage.yml ← قدیمی (IIS روی Windows — غیرفعال) ``` -### ۴.۲ شاخه‌ها +### ۴.۲ فلوی Staging (`kub-deploy.yml`) -| شاخه | محیط | Deploy | -|------|------|--------| -| `kub-stage` | Staging (194.5.195.53) | Auto | -| `production` | Production (45.149.79.127) | Manual trigger | -| `main` | — | Development only | +```mermaid +flowchart TD + A["Push to kub-stage"] --> B["Start Docker daemon"] + B --> C["Clone repo"] + C --> D["Pack & Push Proto NuGet"] + D --> E["Docker build → tag :latest"] + E --> F["Push to 194.5.195.53:30080"] + F --> G["SCP manifest to server"] + G --> H["kubectl apply -f cms-deployment.yaml"] + H --> I["kubectl rollout restart"] + I --> J["✅ Deployed to Staging"] +``` + +### ۴.۳ فلوی Production (`prod-deploy.yml`) + +```mermaid +flowchart TD + A["Push to production"] --> B["Start Docker daemon"] + B --> C["Clone repo"] + C --> D["Pack & Push Proto NuGet"] + D --> E["Docker build → tag :sha + :prod"] + E --> F["Push to 194.5.195.53:30080"] + F --> G["SCP manifest to server"] + G --> H["kubectl apply -f cms-deployment.yaml"] + H --> I["kubectl set image → sha"] + I --> J["✅ Deployed to Production"] +``` + +### ۴.۴ شاخه‌ها و محیط‌ها + +| شاخه | محیط | سرور | Image Tag | Deploy | +|------|------|------|-----------|--------| +| `kub-stage` | Staging | 194.5.195.53 | `:latest` | Auto | +| `production` | Production | 45.149.79.127 | `:sha` + `:prod` | Auto | + +### ۴.۵ نکات مهم CI/CD + +- **Proto NuGet:** هر deploy ابتدا proto packages رو build و به Nexus push می‌کنه +- **Manifest apply:** پایپلاین مانیفست K8s رو SCP به سرور و `kubectl apply` می‌زنه + → PVC، Deployment، Service و Ingress هر بار اعمال می‌شه +- **Image registry:** `194.5.195.53:30080` (داخلی Nexus) — نه `git.se.kbs1.ir` +- **appsettings حفاظت:** `.gitattributes` با `merge=ours` مانع overwrite شدن `appsettings.Production.json` موقع merge می‌شه --- @@ -328,6 +396,19 @@ flowchart TD | **FrontOffice** | `kub-stage` → `production` | `f02d082` | 21 فایل، 400 insertion + فیکس GwUrl به `cms.kbs2.ir` | | **BackOffice** | `kub-stage` → `production` | `bdea2e8` | 36 فایل، بدون conflict | +### ۹.۲ کامیت‌های PVC و اصلاحات K8s (تیر ۱۴۰۴) + +| commit | شرح | +|--------|------| +| `3153fd8` | feat: add PersistentVolume for CMS uploads + apply manifests in CI/CD | +| `68da3f4` | fix: staging uses namespace default, not foursat | +| `e41747a` | fix: production ingress — add cms.kbs2.ir, use ingressClassName | +| `2d6c95e` | fix: use local registry 194.5.195.53:30080 instead of git.se.kbs1.ir | +| `f8dc4ab` | fix: staging ASPNETCORE_ENVIRONMENT=Staging, remove secretKeyRef | +| `de83c31` | fix: production uses namespace default + remove foursat namespace references | + +> همه کامیت‌ها به هر دو شاخه `kub-stage` و `production` push شده‌اند. + **تنظیمات محیطی Production (`appsettings.Production.json`):** | تنظیم | مقدار | @@ -340,10 +421,14 @@ flowchart TD | `ConnectionStrings.Default` | `Server=mssql-svc;Database=KBS` | ```bash -# k8s-health-check.sh -kubectl get pods -n foursat -kubectl top pods -n foursat -kubectl logs deployment/cms -n foursat --tail=50 +# k8s-health-check.sh (namespace = default) +kubectl get pods +kubectl top pods +kubectl logs deployment/cms --tail=50 + +# بررسی PVC +kubectl get pvc cms-uploads-pvc +kubectl exec deployment/cms -- ls /app/Uploads | wc -l # تست سرویس‌ها grpcurl -plaintext localhost:5001 list # لیست سرویس‌ها