# 🚀 استقرار، CI/CD و زیرساخت > **منابع ادغام‌شده:** `CICD-PIPELINE-GUIDE.md`, `DEPLOYMENT-README.md`, `INFRASTRUCTURE-GUIDE.md`, `INGRESS-NGINX-WARNING.md`, `OFFLINE-DEPLOYMENT-GUIDE.md`, `SERVER-MIRRORS-CONFIG.md` > **آخرین بروزرسانی:** اسفند ۱۴۰۴ --- ## ۱. سرورها | سرور | IP | نقش | منابع | |------|-----|------|--------| | **Staging** | 194.5.195.53 | توسعه + تست | 4 CPU, 8GB RAM | | **Production** | 45.149.79.127 | محیط نهایی | 4 CPU, 16GB RAM | | **Git** | git.se.kbs1.ir | Gitea (مخازن کد) | — | | **Registry** | داخلی | Docker Registry / Nexus | — | --- ## ۲. Docker و Container ### ۲.۱ سرویس‌ها ```yaml # docker-compose.yml (production) services: cms: image: foursat/cms:latest ports: ["5001:5001"] # gRPC environment: - ConnectionStrings__Default=Server=db;Database=FourSatCMS - ASPNETCORE_ENVIRONMENT=Production depends_on: [db] backoffice: image: foursat/backoffice:latest ports: ["5002:80"] # Static Blazor WASM frontoffice: image: foursat/frontoffice:latest ports: ["5003:5003"] # Blazor Server db: image: mcr.microsoft.com/mssql/server:2022-CU16-ubuntu-22.04 ports: ["1433:1433"] volumes: ["sqldata:/var/opt/mssql"] nexus: # NuGet + Docker registry image: sonatype/nexus3 ports: ["8081:8081"] volumes: sqldata: ``` ### ۲.۲ Dockerfile (CMS) ```dockerfile FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base WORKDIR /app EXPOSE 5001 FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR /src COPY ["CMSMicroservice/CMSMicroservice.csproj", "CMSMicroservice/"] RUN dotnet restore COPY . . RUN dotnet publish -c Release -o /app/publish FROM base AS final COPY --from=build /app/publish . ENTRYPOINT ["dotnet", "CMSMicroservice.dll"] ``` --- ## ۳. Kubernetes ### ۳.۱ Manifests ساختار ``` 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 ``` ### ۳.۲ مثال Deployment ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: cms namespace: foursat spec: replicas: 2 selector: matchLabels: app: cms template: spec: containers: - name: cms image: foursat/cms:latest ports: - containerPort: 5001 resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" livenessProbe: grpc: port: 5001 initialDelaySeconds: 15 readinessProbe: grpc: port: 5001 ``` ### ۳.۳ Ingress ```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: rules: - host: foursat.ir http: paths: - path: / backend: service: name: frontoffice port: { number: 5003 } - path: /admin backend: service: name: backoffice port: { number: 80 } ``` > ⚠️ **هشدار:** Ingress-nginx نسخه‌های قبل از 1.9.0 مشکل امنیتی CVE-2023-5044 دارند. حتماً بروزرسانی کنید. --- ## ۴. CI/CD Pipeline ### ۴.۱ Gitea Actions Workflow ```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 }} ``` ### ۴.۲ شاخه‌ها | شاخه | محیط | Deploy | |------|------|--------| | `kub-stage` | Staging (194.5.195.53) | Auto | | `production` | Production (45.149.79.127) | Manual trigger | | `main` | — | Development only | --- ## ۵. استقرار آفلاین (Offline Deployment) ### ۵.۱ فلوی آماده‌سازی ```mermaid flowchart TD subgraph ONLINE["🌐 سرور اینترنت‌دار"] A1["pull-base-images.sh\nدانلود Docker images"] --> A2["cache-nuget-packages.sh\nدانلود NuGet packages"] A2 --> A3["save-images.sh\nذخیره تصاویر به tar"] A3 --> A4["بسته‌بندی"] end A4 -->|"💾 انتقال فیزیکی\nUSB / HDD"| B1 subgraph OFFLINE["🔒 سرور آفلاین"] B1["load-images.sh\nبارگذاری تصاویر"] --> B2["setup-nexus-complete.sh\nراه‌اندازی Nexus"] B2 --> B3["build-all-offline.sh\nبیلد با Nexus محلی"] B3 --> B4["k8s-deploy.sh\nاستقرار در K8s"] end ``` ### ۵.۲ اسکریپت‌های کلیدی | اسکریپت | کاربرد | |----------|--------| | `pull-base-images.sh` | دانلود ۱۵+ Docker image پایه | | `save-images.sh` | Export به tar (4-8 GB) | | `load-images.sh` | Import از tar به Docker | | `cache-nuget-packages.sh` | دانلود NuGet offline | | `setup-nexus-complete.sh` | راه‌اندازی NuGet proxy | | `build-all-offline.sh` | بیلد بدون اینترنت | | `k8s-deploy.sh` | Deploy تمام سرویس‌ها | | `k8s-health-check.sh` | بررسی سلامت سرویس‌ها | --- ## ۶. Nexus Repository Manager ### ۶.۱ نقش ```mermaid graph TD NEXUS["Nexus داخلی"] --> NP["NuGet proxy\ncache nuget.org"] NEXUS --> NH["NuGet hosted\nبسته‌های proto داخلی"] NEXUS --> DP["Docker proxy\ncache Docker Hub"] NEXUS --> DH["Docker hosted\nتصاویر داخلی FourSat"] ``` ### ۶.۲ NuGet.config ```xml ``` --- ## ۷. Mirror و Cache ### ۷.۱ Docker Mirror ```json // /etc/docker/daemon.json { "registry-mirrors": [ "https://mirror.gcr.io", "https://docker.arvancloud.ir" ], "insecure-registries": [ "localhost:8082" ] } ``` ### ۷.۲ NuGet Mirror ``` Primary: nuget.org Fallback: Nexus local proxy Proto packages: BaGet (internal) at http://localhost:5555 ``` --- ## ۸. Proto Packages (NuGet) ### ۸.۱ فلوی بسته‌بندی ```mermaid flowchart TD A["CMS/src/Protos/*.proto"] --> B["pack-protos.sh\ndotnet pack → .nupkg"] B --> C["Push to BaGet / Nexus"] C --> D["BackOffice + FrontOffice\ndotnet restore → مصرف proto"] ``` ### ۸.۲ نام بسته ```xml ``` --- ## ۹. مانیتورینگ و Health Check ```bash # k8s-health-check.sh kubectl get pods -n foursat kubectl top pods -n foursat kubectl logs deployment/cms -n foursat --tail=50 # تست سرویس‌ها grpcurl -plaintext localhost:5001 list # لیست سرویس‌ها grpcurl -plaintext localhost:5001 grpc.health.v1.Health/Check # Health curl http://localhost:5002/index.html # BackOffice curl http://localhost:5003/ # FrontOffice ```