Files
docs/OFFLINE-DEPLOYMENT-GUIDE.md
T

14 KiB

🚀 راهنمای دیپلوی آفلاین FourSat

📋 خلاصه

این داکیومنت تنظیمات انجام شده برای دیپلوی کاملاً آفلاین پروژه FourSat را شرح می‌دهد.


🏗️ معماری

┌─────────────────────────────────────────────────────────────────┐
│                        سرور 194.5.195.53                        │
├─────────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐          │
│  │   Gitea      │  │    Nexus     │  │     K3s      │          │
│  │  (Git Host)  │  │  (Registry)  │  │ (Kubernetes) │          │
│  │              │  │              │  │              │          │
│  │ gitea-svc:   │  │ :32081 UI    │  │ kubectl      │          │
│  │ 3000         │  │ :32082 Docker│  │              │          │
│  └──────────────┘  └──────────────┘  └──────────────┘          │
│                                                                 │
│  ┌──────────────┐  ┌──────────────┐                            │
│  │   Registry   │  │ Gitea Runner │                            │
│  │  (Apps)      │  │   (CI/CD)    │                            │
│  │ :30080       │  │              │                            │
│  └──────────────┘  └──────────────┘                            │
└─────────────────────────────────────────────────────────────────┘

🔧 اطلاعات دسترسی

سرویس آدرس یوزر پسورد
سرور SSH 194.5.195.53 root 87zH26nbqT
Nexus UI http://194.5.195.53:32081 admin 87zH26nbqT
Nexus Docker 194.5.195.53:32082 admin 87zH26nbqT
App Registry 194.5.195.53:30080 admin 87zH26nbqT
NuGet Feed http://194.5.195.53:32081/repository/foursat-nuget-hosted/index.json - -

🐳 ایمیج‌های کش شده در Nexus

این ایمیج‌ها در 194.5.195.53:32082 ذخیره شدن و نیازی به اینترنت ندارن:

ایمیج استفاده
docker-sshpass:latest ایمیج اصلی CI/CD (docker + sshpass)
docker:latest Docker in Docker
dotnet/sdk:9.0 بیلد .NET پروژه‌ها
dotnet/aspnet:9.0 Runtime .NET
nginx:alpine فرانت‌اند‌ها

📦 پکیج‌های NuGet

~500 پکیج .NET در Nexus NuGet hosted repository کش شدن:

  • http://194.5.195.53:32081/repository/foursat-nuget-hosted/index.json

NuGet.config نمونه:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="FourSat-Offline" value="http://194.5.195.53:32081/repository/foursat-nuget-hosted/index.json" />
  </packageSources>
</configuration>

🔄 CI/CD Pipeline

ساختار Workflow (یکسان برای همه پروژه‌ها)

name: Build and Deploy to Kubernetes

on:
  push:
    branches:
      - kub-stage

env:
  REGISTRY: 194.5.195.53:30080
  IMAGE_NAME: admin/<project-name>
  K8S_SERVER: 194.5.195.53

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    container:
      image: 194.5.195.53:32082/docker-sshpass:latest  # ✅ آفلاین
      options: --privileged
    steps:
      - name: Start Docker daemon
        run: |
          mkdir -p /etc/docker
          cat > /etc/docker/daemon.json << 'DAEMON'
          {
            "insecure-registries": ["194.5.195.53:30080", "194.5.195.53:32500", "194.5.195.53:32082"]
          }
          DAEMON
          dockerd &
          for i in $(seq 1 30); do docker info >/dev/null 2>&1 && break || sleep 2; done

      - name: Checkout code
        run: |
          git clone --depth 1 --branch kub-stage http://gitea-svc:3000/admin/<repo>.git .

      # فقط برای پروژه‌های .NET API (CMS, BackOffice.BFF, FrontOffice.BFF)
      - name: Publish Protobuf packages
        run: |
          docker run --rm -v $(pwd):/src -w /src \
            194.5.195.53:32082/dotnet/sdk:9.0 sh -c '
              for proj in $(find . -name "*Protobuf*.csproj" -type f); do
                dotnet restore "$proj"
                dotnet build "$proj" -c Release --no-restore
                dotnet pack "$proj" -c Release --no-build -o "$(dirname $proj)/nupkg"
                for nupkg in $(dirname $proj)/nupkg/*.nupkg; do
                  [ -f "$nupkg" ] && dotnet nuget push "$nupkg" \
                    --source "http://194.5.195.53:32081/repository/foursat-nuget-hosted/index.json" \
                    --api-key "admin:87zH26nbqT" \
                    --skip-duplicate --allow-insecure-connections || true
                done
              done
            '

      - name: Build Docker Image
        run: |
          docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest .

      - name: Push to Registry
        run: |
          echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u admin --password-stdin
          docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest

      - name: Deploy to Kubernetes
        run: |
          export SSHPASS="${{ secrets.SERVER_PASSWORD }}"
          sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} "
            kubectl rollout restart deployment/<deployment-name>
            kubectl rollout status deployment/<deployment-name> --timeout=180s
          "

📂 پروژه‌ها

پروژه IMAGE_NAME Dockerfile Deployment Protobuf
CMS admin/cms ./Dockerfile cms
BackOffice.BFF admin/backoffice-bff src/BackOffice.BFF.WebApi/Dockerfile backoffice-bff
FrontOffice.BFF admin/frontoffice-bff src/FrontOffice.BFF.WebApi/Dockerfile frontoffice-bff
BackOffice admin/backoffice src/BackOffice/Dockerfile backoffice
FrontOffice admin/frontoffice src/FrontOffice.Main/Dockerfile frontoffice

🔐 Gitea Secrets

این secret ها باید در Gitea تنظیم شوند:

روش 1: برای هر Repository جداگانه

https://git.se.kbs1.ir/admin/<repo>/settings/actions/secrets

روش 2: برای کل Organization

https://git.se.kbs1.ir/admin/-/settings/actions/secrets

Secret Name Value
SERVER_PASSWORD 87zH26nbqT
REGISTRY_PASSWORD 87zH26nbqT

🛠️ K3s Registry Configuration

فایل /etc/rancher/k3s/registries.yaml:

mirrors:
  "194.5.195.53:32082":
    endpoint:
      - "http://194.5.195.53:32082"
  "194.5.195.53:32500":
    endpoint:
      - "http://194.5.195.53:32500"
  "194.5.195.53:30080":
    endpoint:
      - "http://194.5.195.53:30080"

🐋 Docker-sshpass Image

ایمیج سفارشی برای CI/CD که sshpass از قبل نصب داره:

FROM 194.5.195.53:32082/docker:latest
RUN apk add --no-cache openssh-client sshpass

Build و Push:

docker build -t 194.5.195.53:32082/docker-sshpass:latest .
docker push 194.5.195.53:32082/docker-sshpass:latest

چک‌لیست آفلاین بودن

  • ایمیج CI/CD از Nexus: 194.5.195.53:32082/docker-sshpass:latest
  • ایمیج dotnet/sdk از Nexus: 194.5.195.53:32082/dotnet/sdk:9.0
  • پکیج‌های NuGet کش شده در Nexus
  • پکیج‌های Protobuf پابلیش به Nexus
  • App images در registry محلی: 194.5.195.53:30080
  • بدون apt-get یا apk add در pipeline
  • دیپلوی با SSH (بدون نیاز به kubeconfig خارجی)

🚨 Troubleshooting

خطای "Permission denied" در Deploy

Permission denied, please try again.

راه‌حل: Secret SERVER_PASSWORD در Gitea تنظیم نشده. برو به: https://git.se.kbs1.ir/admin/<repo>/settings/actions/secrets

خطای "unauthorized" در Push

unauthorized: access denied

راه‌حل: Secret REGISTRY_PASSWORD تنظیم نشده.

خطای Pull Image

failed to pull image

راه‌حل:

  1. چک کن ایمیج در Nexus وجود داره
  2. چک کن insecure-registries درست تنظیم شده

📊 وضعیت نهایی سیستم

سرویس‌های فعال و سالم (17 pod):

سرویس Namespace وضعیت ایمیج
gitea default Running 194.5.195.53:32082/gitea/gitea:latest
gitea-runner default Running 194.5.195.53:32082/gitea/act_runner:latest
nexus default Running 194.5.195.53:32082/sonatype/nexus3:3.38.0
cms default Running 194.5.195.53:30080/admin/cms:latest
backoffice default Running 194.5.195.53:30080/admin/backoffice:latest
backoffice-bff default Running 194.5.195.53:30080/admin/backoffice-bff:latest
frontoffice default Running 194.5.195.53:30080/admin/frontoffice:latest
frontoffice-bff default Running 194.5.195.53:30080/admin/frontoffice-bff:latest
cert-manager cert-manager Running 194.5.195.53:32082/quay.io/jetstack/cert-manager-*
nginx-deploy default Running 194.5.195.53:32082/nginx:alpine
mssql default Running 194.5.195.53:32082/mcr.microsoft.com/mssql/server:2022-latest
coredns kube-system Running rancher/mirrored-coredns-coredns:1.13.1
metrics-server kube-system Running rancher/mirrored-metrics-server:v0.8.0

⚠️ مشکلات جزئی (غیرضروری):

  • netshoot - CrashLoopBackOff (ابزار تست شبکه)
  • ingress-nginx-controller - CrashLoopBackOff (environment variables)
  • local-path-provisioner - CrashLoopBackOff (storage provisioner)

🎯 دستاوردها

قبل از امروز:

  • اکثر سرویس‌ها از Docker Hub و registryهای خارجی ایمیج می‌کشیدن
  • CI/CD pipeline نیاز به اینترنت داشت برای نصب sshpass
  • NuGet packages از internet دانلود می‌شدن

بعد از امروز:

  • 100% آفلاین: تمام ایمیج‌های اصلی از Nexus کش می‌شن
  • CI/CD کاملاً آفلاین: ایمیج docker-sshpass آماده
  • NuGet کش شده: ~500 پکیج .NET در Nexus
  • Auto-deploy: kubectl rollout restart خودکار
  • Protobuf publishing: پکیج‌های محلی به Nexus

🔧 تنظیمات انجام شده امروز

1. ایمیج‌های جدید کش شده:

# K8s System Images
194.5.195.53:32082/quay.io/jetstack/cert-manager-cainjector:v1.14.0
194.5.195.53:32082/quay.io/jetstack/cert-manager-controller:v1.14.0  
194.5.195.53:32082/quay.io/jetstack/cert-manager-webhook:v1.14.0
194.5.195.53:32082/registry.k8s.io/ingress-nginx/controller:v1.14.1
194.5.195.53:32082/rancher/local-path-provisioner:v0.0.32
194.5.195.53:32082/rancher/klipper-helm:v0.9.10-build20251111
194.5.195.53:32082/rancher/klipper-lb:v0.4.13

# Application Images  
194.5.195.53:32082/mcr.microsoft.com/mssql/server:2022-latest
194.5.195.53:32082/nginx:alpine
194.5.195.53:32082/nginx:stable
194.5.195.53:32082/nicolaka/netshoot:latest
194.5.195.53:32082/registry:2

# CI/CD Images
194.5.195.53:32082/docker-sshpass:latest (custom-built)

2. Deployment Updates:

همه deploymentها با kubectl patch آپدیت شدن تا از Nexus استفاده کنن:

# مثال: cert-manager
spec:
  template:
    spec:
      containers:
      - name: cert-manager-cainjector
        image: 194.5.195.53:32082/quay.io/jetstack/cert-manager-cainjector:v1.14.0

3. CI/CD Pipeline بهبودها:

container:
  image: 194.5.195.53:32082/docker-sshpass:latest  # ✅ آفلاین
steps:
  - name: Deploy to Kubernetes
    run: |
      export SSHPASS="${{ secrets.SERVER_PASSWORD }}"
      sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} "
        kubectl rollout restart deployment/<app>
        kubectl rollout status deployment/<app> --timeout=180s
      "

4. مشکلات حل شده:

  • gitea + gitea-runner: از Nexus images استفاده
  • docker-sshpass: ایمیج سفارشی برای CI/CD
  • cert-manager: تمام componentها آپدیت
  • mssql: EULA acceptance اضافه شد
  • ⚠️ seq: temporarily deleted (ایمیج push نشد)

🚀 دستورات مهم برای آینده

تست آفلاین بودن:

# چک کردن ایمیج‌های خارجی
kubectl get pods -A -o jsonpath='{range .items[*]}{.spec.containers[*].image}{"\n"}{end}' | sort | uniq | grep -v '194.5.195.53'

# تست CI/CD
git commit --allow-empty -m "test offline pipeline" && git push

# چک rollout status
kubectl rollout status deployment/<app> --timeout=180s

اضافه کردن ایمیج جدید به Nexus:

# Export از containerd
ctr -n k8s.io images export /tmp/image.tar <image-name>

# Push به Nexus
skopeo copy --dest-tls-verify=false --dest-creds admin:87zH26nbqT \
  docker-archive:/tmp/image.tar docker://194.5.195.53:32082/<image-path>

# Update deployment
kubectl patch deployment <name> --type='merge' \
  -p='{"spec":{"template":{"spec":{"containers":[{"name":"<container>","image":"194.5.195.53:32082/<image>"}]}}}}'

📅 تاریخ آخرین به‌روزرسانی

29 ژانویه 2026 - سیستم کاملاً آفلاین شد