CI/CD-Pipelines implementieren
Bis zu diesem Punkt war jeder Schritt im Prozess manuell. Erstellen Sie das Projekt, führen Sie SqlPackage aus, überprüfen Sie den Bereitstellungsbericht. Eine CI/CD-Pipeline wandelt diese Sequenz in etwas um, das bei jedem Commit automatisch mit denselben Schritten in derselben Reihenfolge geschieht. Keine vergessenen Flags, keine Tippfehler in Verbindungszeichenfolgen, keine "es hat auf meinem Computer funktioniert.".
Entwerfen der Pipelinestruktur
Die meisten Datenbankpipelines folgen einem zweistufigen Muster:
-
Build: Kompilieren Sie das SQL-Datenbankprojekt, und erstellen Sie das
.dacpacArtefakt. -
Bereitstellen: Veröffentlichen Sie diesen
.dacpaczu Zieldatenbanken über Umgebungen hinweg (Entwicklung, Staging, Produktion).
Das Erstellen einmal und die Bereitstellung desselben Artefakts überall beseitigt das Problem "Arbeiten in Dev, Unterbrechungen in Prod". Die Datei .dacpac, die die Validierung im Staging bestanden hat, ist dieselbe Datei, die in die Produktion überführt wird.
Implementieren einer CI/CD-Pipeline mit GitHub-Aktionen
GitHub Actions Workflows befinden sich in .github/workflows/ und definieren Ihre Pipeline als YAML-Datei. Die azure/sql-action Aktion übernimmt die .dacpac Bereitstellung auf Azure SQL Database.
Dies ist ein Workflow, der bei jedem Push zu main erstellt und zur Produktionsumgebung bereitgestellt wird:
# .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'
📝 Die azure/sql-action unterstützt .dacpac, .sqlproj und .sql Skripte. Es funktioniert mit SQL-Authentifizierung, Microsoft Entra-ID und Dienstprinzipalauthentifizierung.
Wenn Ihre Azure SQL-Datenbank Firewallregeln aktiviert hat, benötigt der GitHub Actions Runner Zugriff auf die IP-Adresse. Beim Koppeln von azure/login mit azure/sql-action fügt die Aktion während der Bereitstellung eine temporäre Firewallregel zur Runner-IP-Adresse hinzu und entfernt sie anschließend wieder.
Implementieren einer CI/CD-Pipeline mit Azure DevOps
Azure DevOps stellt die SqlAzureDacpacDeployment-Aufgabe für die .dacpac-Bereitstellung zur Verfügung. Dies ist die entsprechende Pipeline:
# 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'
Verwenden Sie SqlPackage direkt für Linux-Agents oder für mehr Kontrolle während des Prozesses:
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'
Unabhängig davon, ob Sie GitHub-Aktionen oder Azure DevOps verwenden, benötigen beide Pipelines Anmeldeinformationen, um eine Verbindung mit Ihrer Datenbank herzustellen. Der nächste Schritt besteht darin sicherzustellen, dass diese Anmeldeinformationen nicht in Ihren YAML-Dateien enthalten sind.
Eine in einer YAML-Datei fest codierte Verbindungszeichenfolge führt zu Sicherheitsverletzungen. Sowohl GitHub-Aktionen als auch Azure DevOps bieten Mechanismen zum Speichern und Einfügen von Geheimschlüsseln zur Laufzeit, ohne sie in der Quellcodeverwaltung verfügbar zu machen.
GitHub-Repository- und Umgebungsgeheimnisse
Speichern Sie vertrauliche Werte als geheime Repositoryschlüssel oder geheime Umgebungsgeheimnisse. In Ihrem GitHub-Repository auf github.com:
- Wählen Sie Einstellungen>Geheimnisse und Variablen>Aktionen aus.
- Wählen Sie "Neuer Repositoryschlüssel" aus.
- Fügen Sie einen Namen (wie
AZURE_SQL_CONNECTION_STRING) und den Wert hinzu.
Verweisen Sie in Ihrem Workflow mit ${{ secrets.SECRET_NAME }} auf Geheimnisse. Umgebungsgeheimnisse gelten nur für bestimmte Bereitstellungsumgebungen, sodass Produktionsanmeldeinformationen nur für Produktionsaufträge verfügbar sind.
Dienstprinzipal- und OpenID Connect-Authentifizierung
Noch besser: Überspringen Sie Kennwörter vollständig. OpenID Connect (OIDC) authentifiziert mithilfe von Verbundanmeldeinformationen, ohne dass ein geheimer Clientschlüssel irgendwo gespeichert wird. Sie benötigen drei Werte:
-
AZURE_CLIENT_ID: Die Anwendungs-ID (Client-ID) des Dienstprinzipals. -
AZURE_TENANT_ID: Ihre Microsoft Entra ID-Mandanten-ID. -
AZURE_SUBSCRIPTION_ID: Die ID Ihres Azure-Abonnements.
Der Dienstprinzipal wird über Verbundanmeldeinformationen authentifiziert. Es gibt keine Kennwörter, die rotiert oder kompromittiert werden können.
Azure-Schlüsseltresor-Integration
Speichern Sie Verbindungszeichenfolgen und Anmeldeinformationen in der Azure Key Vault für die zentrale Geheimnisverwaltung, und lassen Sie diese von Ihrer Pipeline zum Zeitpunkt der Bereitstellung abrufen. In Azure DevOps ruft die Azure Key Vault-Aufgabe geheime Schlüssel in Pipelinevariablen ab. Verwenden Sie in GitHub Actions azure/login, gefolgt von Azure CLI-Befehlen, um aus dem Schlüsseltresor zu lesen.
Von Bedeutung
Datenbankanmeldeinformationen regelmäßig ändern. Azure Key Vault kann mit Azure Functions integriert werden, um die Geheimnisrotation zu automatisieren, was das Risiko für die Kompromittierung von Anmeldeinformationen reduziert.
Implementiere Steuerelemente für die Bereitstellungspipeline
Eine Pipeline, die bei jedem Push ohne Überprüfungsschritt ins Produktivsystem deployt wird, birgt ein Risiko für Datenbankänderungen. Sie benötigen Kontrollmechanismen, die verhindern, dass nicht überprüfte Änderungen in die Produktion gelangen.
Umgebungsschutzregeln
Sowohl GitHub als auch Azure DevOps unterstützen Umgebungen mit Schutzregeln, die Bereitstellungen steuern.
- Erforderliche Prüfer: Mindestens ein Teammitglied muss dies genehmigen, bevor der Bereitstellungsauftrag ausgeführt wird. Konfigurieren Sie diese Einstellung in GitHub unter Einstellungen>Umgebungen>Schutzregeln.
- Wartezeiten: Fügen Sie eine Verzögerung zwischen Genehmigung und Ausführung hinzu, damit das Team die Möglichkeit hat, die Entscheidung zu überdenken.
-
Bereitstellungszweige: Bestimmen, welche Branches auf eine Umgebung abzielen können. Beispielsweise wird nur
mainin der Produktion eingesetzt.
Branchrichtlinien
Branch-Richtlinien schützen Ihren Hauptzweig und dienen als erste Verteidigungslinie. Konfigurieren Sie in Azure DevOps Folgendes:
- Mindestanzahl der Prüfer für Pullanforderungen.
- Buildüberprüfung, um den SQL-Projektbuild als PR-Prüfung vor dem Zusammenführen auszuführen.
- Kommentarauflösung, was die Behebung aller Prüfkommentare erfordert.
- Automatisch einbezogene Prüfer, damit bestimmte Personen zu PRs hinzugefügt werden, die Datenbankdateien betreffen.
GitHub bietet ähnliche Schutzmaßnahmen durch Branch-Schutzregeln oder Regelsätze.
Codebesitzer
Eine CODEOWNERS Datei (GitHub) oder automatisch eingeschlossene Prüferrichtlinie (Azure DevOps) stellt sicher, dass die richtigen Personen Datenbankänderungen überprüfen. Es wird keine SQL-Datei zusammengeführt, ohne dass das Datenbankteam sie sieht:
# .github/CODEOWNERS
/Database/ @db-team
*.sql @db-team @dba-lead
Diese Regel erfordert, dass die Mitglieder der db-team alle Pull-Anforderungen überprüfen, die SQL-Dateien oder den Datenbankprojektordner ändern.
Zweigsteuerungsprüfungen
In Azure DevOps schränkt eine Verzweigungsprüfung für Serviceverbindungen die Pipelines ein, die auf Produktionsanmeldeinformationen zugreifen können. Nur Pipelines, die im Kontext von main ausgeführt werden, erhalten Zugriff. Auch wenn eine Person eine Pipeline in einer Featureverzweigung modifiziert, sodass sie auf die Produktion ausgerichtet ist, lehnt die Dienstverbindung die Anforderung ab.
Wichtige Erkenntnisse
Verwenden Sie azure/sql-action (GitHub-Aktionen) oder SqlAzureDacpacDeployment (Azure DevOps), um .dacpac-Dateien aus Ihrer CI/CD-Pipeline bereitzustellen. Speichern Sie Verbindungszeichenfolgen und Anmeldeinformationen als Repositoryschlüssel, geheime Umgebungsgeheimnisse oder in Azure Key Vault, und codieren Sie sie nie in YAML-Dateien. Um sich zu authentifizieren, ohne Kennwörter zu speichern, verwenden Sie OpenID Connect (OIDC) mit Verbundanmeldeinformationen. Schützen Sie Produktionsbereitstellungen durch Umgebungsschutzregel, die Erfordernis von Prüfern und Einschränkungen für Bereitstellungsverzweigungen. Verwenden Sie CODEOWNERS Dateien oder automatische Prüfer, um sicherzustellen, dass die richtigen Personen die Datenbankänderungen überprüfen.