Wdrożenie potoków CI/CD

Ukończone

Do tego momentu każdy krok w procesie był ręczny. Skompiluj projekt, uruchom pakiet SqlPackage, sprawdź raport wdrożenia. Pipeline CI/CD zamienia tę sekwencję w coś, co dzieje się automatycznie przy każdym commitcie, z tymi samymi krokami, w tej samej kolejności, za każdym razem. Nie zapomniane flagi, nie literówki w parametrach połączenia, nie "działało na mojej maszynie".

Projektowanie struktury pipeline'u

Większość potoków bazy danych stosuje dwuetapowy schemat.

  1. Kompilacja: skompiluj projekt bazy danych SQL i utwórz .dacpac artefakt.
  2. Wdrażanie: opublikuj je .dacpac w docelowych bazach danych, przechodząc przez środowiska (deweloperskie, testowe, produkcyjne).

Kompilowanie raz i wdrażanie tego samego artefaktu aplikacji wszędzie eliminuje problem "działa w środowisku deweloperskim, ale psuje się w środowisku produkcyjnym". .dacpac , które przeszło walidację w środowisku przejściowym, jest tym samym plikiem, który zostanie wdrożony w środowisku produkcyjnym.

Implementowanie rur CI/CD za pomocą GitHub Actions

Przepływy pracy funkcji GitHub Actions znajdują się w .github/workflows/ i definiują potok jako YAML. Akcja azure/sql-action obsługuje wdrażanie w usłudze .dacpac Azure SQL Database.

Oto przepływ pracy, który buduje się na każdej aktualizacji do main i wdraża się w środowisku produkcyjnym:

# .github/workflows/sql-deploy.yml
name: Build and Deploy SQL Project
on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - name: Build SQL project
      run: dotnet build ./Database.sqlproj -o ./output

    - name: Upload dacpac artifact
      uses: actions/upload-artifact@v4
      with:
        name: dacpac
        path: ./output/Database.dacpac

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment: production
    steps:
    - name: Download dacpac artifact
      uses: actions/download-artifact@v4
      with:
        name: dacpac

    - name: Install SqlPackage
      run: dotnet tool install -g microsoft.sqlpackage

    - uses: azure/login@v2
      with:
        client-id: ${{ secrets.AZURE_CLIENT_ID }}
        tenant-id: ${{ secrets.AZURE_TENANT_ID }}
        subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

    - uses: azure/sql-action@v2.3
      with:
        connection-string: ${{ secrets.AZURE_SQL_CONNECTION_STRING }}
        path: './Database.dacpac'
        action: 'publish'

📝 azure/sql-action obsługuje .dacpac, .sqlproj oraz .sql skrypty. Działa z uwierzytelnianiem SQL, identyfikatorem Microsoft Entra ID i uwierzytelnianiem głównej usługi.

Jeśli usługa Azure SQL Database ma włączone reguły zapory, adres IP modułu uruchamiającego funkcję GitHub Actions wymaga dostępu. Gdy sparujesz azure/login z azure/sql-action, akcja dodaje tymczasową regułę zapory dla adresu IP uruchamiacza podczas wdrażania i usuwa ją później.

Tworzenie potoku CI/CD z użyciem Azure DevOps

Usługa Azure DevOps udostępnia SqlAzureDacpacDeployment zadanie wdrożenia .dacpac . Oto równoważny potok:

# azure-pipelines.yml
trigger:
  - main

pool:
  vmImage: 'windows-latest'

steps:
- task: DotNetCoreCLI@2
  inputs:
    command: 'build'
    projects: './Database.sqlproj'
    arguments: '-o $(Build.ArtifactStagingDirectory)'

- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)/Database.dacpac'
    ArtifactName: 'dacpac'

- task: SqlAzureDacpacDeployment@1
  inputs:
    azureSubscription: 'your-service-connection'
    AuthenticationType: 'server'
    ServerName: 'your-server.database.windows.net'
    DatabaseName: 'your-database'
    SqlUsername: '$(SqlUser)'
    SqlPassword: '$(SqlPassword)'
    deployType: 'DacpacTask'
    DeploymentAction: 'Publish'
    DacpacFile: '$(Build.ArtifactStagingDirectory)/Database.dacpac'

W przypadku agentów systemu Linux lub większej kontroli nad procesem zainstaluj pakiet SqlPackage bezpośrednio:

steps:
- script: dotnet tool install --global microsoft.sqlpackage
  displayName: 'Install SqlPackage'

- script: |
    sqlpackage /Action:Publish \
      /SourceFile:$(Build.ArtifactStagingDirectory)/Database.dacpac \
      /TargetConnectionString:"$(ConnectionString)"
  displayName: 'Deploy database'

Niezależnie od tego, czy używasz GitHub Actions, czy Azure DevOps, oba pipeline'y wymagają poświadczeń do połączenia z bazą danych. Następnym krokiem jest upewnienie się, że te poświadczenia pozostają poza plikami YAML.

Zakodowany na sztywno parametr połączenia w pliku YAML to ryzyko naruszenia bezpieczeństwa. Zarówno GitHub Actions, jak i Azure DevOps udostępniają mechanizmy przechowywania i wstrzykiwania sekretów podczas działania bez ujawniania ich w kontroli wersji.

Repozytorium GitHub i sekrety środowiskowe

Przechowuj poufne wartości jako wpisy tajne repozytorium lub wpisy tajne środowiska. W Twoim repozytorium GitHub na witrynie github.com:

  1. Wybierz Ustawienia>Sekrety i zmienne>Akcje.
  2. Wybierz Nowy sekret repozytorium.
  3. Dodaj nazwę (na przykład AZURE_SQL_CONNECTION_STRING) i wartość.

Odwołuj się do wpisów tajnych w przepływie pracy za pomocą polecenia ${{ secrets.SECRET_NAME }}. Wpisy tajne środowiska są ograniczone do określonych środowisk wdrażania, więc poświadczenia produkcyjne są dostępne tylko dla zadań, które są skierowane do środowiska produkcyjnego.

Jednostka usługi i uwierzytelnianie openID Connect

Jeszcze lepiej, całkowicie pomijaj hasła. OpenID Connect (OIDC) z azure/login uwierzytelnianiem przy użyciu poświadczeń federacyjnych, bez klucza tajnego klienta przechowywanego w dowolnym miejscu. Potrzebne są trzy wartości:

  • AZURE_CLIENT_ID: identyfikator aplikacji (klienta) jednostki usługi.
  • AZURE_TENANT_ID: Identyfikator dzierżawy Microsoft Entra ID.
  • AZURE_SUBSCRIPTION_ID: Identyfikator subskrypcji platformy Azure.

Jednostka usługi uwierzytelnia się za pomocą poświadczeń federacyjnych, więc nie ma potrzeby zmiany hasła ani obaw o jego przeciek.

Integracja usługi Azure Key Vault

W przypadku scentralizowanego zarządzania tajemnicami należy przechowywać ciągi połączeń i poświadczenia w usłudze Azure Key Vault i pozwolić, aby twój potok pobrał je w momencie wdrażania. W Azure DevOps zadanie Azure Key Vault pobiera tajne dane do zmiennych potokowych. W GitHub Actions użyj azure/login poleceń Azure CLI do odczytu z repozytorium.

Ważna

Regularnie zmieniaj poświadczenia bazy danych. Usługa Azure Key Vault może zintegrować się z usługą Azure Functions, aby zautomatyzować rotację wpisów tajnych, co zmniejsza ryzyko naruszenia poświadczeń.

Implementowanie kontrolek potoku wdrażania

Ciąg automatyzacji, który jest wdrażany w środowisku produkcyjnym przy każdej aktualizacji kodu bez etapu przeglądu, jest ryzykowny dla zmian w bazie danych. Potrzebujesz mechanizmów kontrolnych, które zapobiegają wprowadzaniu niezrecenzowanych zmian do produkcji.

Reguły ochrony środowiska

Zarówno usługi GitHub, jak i Azure DevOps obsługują środowiska z regułami ochrony, które blokują wdrożenia:

  • Wymagani recenzenci: co najmniej jeden członek zespołu musi zatwierdzić przed uruchomieniem zadania wdrażania. Wusłudze> GitHub skonfiguruj to ustawienie w obszarze Ustawienia>Reguły ochrony środowisk.
  • Czasomierze oczekiwania: dodaj opóźnienie między zatwierdzeniem i wykonaniem, dając zespołowi okno do ponownego rozważenia.
  • Gałęzie wdrażania: ograniczenie gałęzi, które mogą być docelowe dla środowiska. Na przykład main tylko wdraża się w środowisku produkcyjnym.

Zasady gałęzi

Zasady dotyczące gałęzi chronią gałąź główną i służą jako pierwsza linia obrony. W usłudze Azure DevOps skonfiguruj następujące ustawienia:

  • Minimalna liczba recenzentów żądań ściągnięcia.
  • Weryfikacja kompilacji, która uruchamia kompilację projektu SQL jako sprawdzanie żądania ściągnięcia przed scaleniem.
  • Zamknięcie komentarzy, wymagające uwzględnienia wszystkich uwag do przeglądu.
  • Automatycznie dołączani recenzenci, więc określone osoby są dodawane do PR, które dotyczą plików bazy danych.

GitHub zapewnia podobne zabezpieczenia za pośrednictwem reguł ochrony gałęzi lub zestawów reguł.

Właściciele kodu

CODEOWNERS Plik (GitHub) lub automatycznie dołączone zasady dotyczące recenzentów (Azure DevOps) zapewniają, że odpowiednie osoby przeglądają zmiany w bazie danych. Żaden plik SQL nie jest scalany bez sprawdzenia go przez zespół bazy danych.

# .github/CODEOWNERS
/Database/ @db-team
*.sql @db-team @dba-lead

Ta reguła wymaga od członków programu db-team , aby przejrzeli dowolne żądanie ściągnięcia, które modyfikuje pliki SQL lub folder projektu bazy danych.

Kontrola gałęzi

W usłudze Azure DevOps kontrola gałęzi dotycząca połączeń usług określa, które potoki mogą uzyskiwać dostęp do poświadczeń produkcyjnych. Tylko potoki działające w kontekście main mają dostęp. Nawet jeśli ktoś modyfikuje potok na gałęzi funkcjonalnej, aby celować w produkcję, połączenie z serwisem odrzuca żądanie.

Kluczowe wnioski

Użyj azure/sql-action (GitHub Actions) lub SqlAzureDacpacDeployment (Azure DevOps) do wdrażania plików z potoku CI/CD .dacpac. Przechowuj parametry połączenia i poświadczenia jako wpisy tajne repozytorium, wpisy tajne środowiska lub w usłudze Azure Key Vault i nigdy nie zapisuj ich na stałe w plikach YAML. Aby uwierzytelnić się bez przechowywania haseł, użyj protokołu OpenID Connect (OIDC) z poświadczeniami federacyjnymi. Kontroluj wdrożenia produkcyjne z regułami ochrony środowiska IT, z wymaganymi recenzentami i ograniczeniami dla gałęzi wdrożeniowych. Użyj CODEOWNERS plików lub recenzentów automatycznie uwzględnionych, aby upewnić się, że odpowiednie osoby dokonają przeglądu zmian w bazie danych.