Desired State Configuration – Einfache SQL Server Administration mit DSC

Ich hatte mich vor etwa zwei Jahren erstmalig mit DSC auseinandergestzt, um für den SQLSaturday #605 eine Demo zu zaubern, die die Konfiguragtion des SQL Servers ständig überwacht und gffs korrigiert. Jetzt habe ich wieder ein sehr schönes Kundenprojekt, bei dem ich die Wahl habe zwischen kompletter Umsetzung in Powershell (via dbatools) oder eben ein wenig DSC in Verbindung mit dbatools.

Aufgabenstellung

Auf “Knopfdruck” sollen zwei neue SQL Server installiert und konfiguriert werden, auf denen dann mehrere Datenbanken in Basic Availibility Groups laufen. Hierzu habe ich mir also meine Azure-Test-Umgebung erweitert und möchte euch nun meinen Weg zur einer funktionierenden SQL Server Umgebung darstellen.

Folgenden Themen werde ich in den nächsten Wochen entsprechend beleuchten:

  • Vorbereitung der Server
  • Installation des SQL Servers
  • Konfiguration des SQL Servers
  • Backup/Restore Automatisierung
  • Erstellung der BAGs aus den Backups
  • Aktivierung und Abschluss der neuen Server

Voraussetzungen für DSC schaffen

Ich gehe von folgender Ausgangslage aus:

Die neuen Server sind bis Oberkante Betriebssystem installiert und konfiguriert, hängen in einer Domäne und habe das aktuelle Windows Management Framework installiert, idealerweise ist auch bereits Windows Remote Management (WinRM) installiert und aktiviert… wenn nicht überprüfen wir das und holen dies ggfs nach.

Anfänglich wollte ich auch den Server noch mit Powershell in die Domäne hängen, hätte mich aber dabei ein wenig im Kreis gedreht ohne zu einer zufriedenstellenden Lösung zu kommen… daher hier nur ein Versuch mittles Screenshot… 😉

Ok, also weiter… wie bekomme ich also auf allen Zielservern WinRM automatisch ausgerollt und konfiguriert, sowie alle dazugehörigen Firewall-Ports geöffnet… Google half mir etwas bei der Ideenfindung, aber meine Gedanken liefen auch so schon in die richtige Richtung => Domänen-Gruppen-Richtlinien (aka Group-Policies).

Dazu also in der GruppenRichtlinienVerwaltung der Domäne eine Gruppenrichtlinie erstellen, damit man auch eine ordentliche und nachvollziehbare Struktur aufbauen kann.

1.) Service einrichten

Neuen Service hinzufügen und entsprechend konfigurieren

Computer Configuration > Preferences > Control Panel Settings > Services

2.) Zugriff auf Windows Remote Shell erlauben

Zumindest dem Service den Zugriff erlauben, falls das nicht ausreichend sein sollte, auch noch der RemoteShell den Zugriff erlauben.

Computer Configuration > Policies > Administrative Templates > Windows Components > Windows Remote Management (WinRM) > WinRM Services

Nun zu den Löchern in der Firewall

3.) Firewall öffnen für winRM

Letzte Konfiguration, damit alle Server in der Domäne mittles dieser Gruppenrichtlinie konfiguriert werden, um später in der Lage zu sein über DSC (Desired State Configuration) einen SQL Server zu installieren.

Computer Configurations > Policies > Windows Settings > Security Settings > Windows Firewall and Advanced Security > Windows Firewall and Advanced Security 

Nun eine neue Inbound-Rule erstellen, damit auch Zugriffe von aussen (hier vom DomainController auf die SQL Server) ermöglicht werden.

Diese Regel wird explizit für das Windows Remote Management erstellt, um damit alle Verbindungen innerhalb der Private und Domain-Netzwerkes zu erlauben, das Public-Netzwerk wird sicherheitshalber nicht berücksichtigt.

Nun kann man diese neue Gruppen-Richtlinie auf alle Server ausrollen und sollte danach in der Lage sein, alle Server mittels DSC zu konfigurieren und administrieren.

4.) Gruppen-Richtlinien aktualisieren

Den neuen Server nun in die Domäne bringen und somit sollte der Server eigentlich die neu erstellten Richtlinien automatisch erhalten. Um aber absolut sicherzustellen, dass dem so ist kann man auch die Gruppen-Richtlinien auf dem Server selber manuell einmal aktualisieren.

Nun sollte der Konfigurator des Server mit DSC nichts mehr im Wege stehen und man kann auf dem zentralen Administrations-Server die entsprechenden Regel erstellen und ausrollen. Dazu aber mehr im nächsten Blogbeitrag 😉

Quelle: How to Enable WinRM via Group Policy

Update der Gruppen-Richtlinien aufgrund von Fehlern in der Skript-Ausführung

Nachdem ich den ersten Beitrag fertig hatte und für weitere Beiträge sowie das Kunden-Projekt recherchiert und getestet habe, musste ich leider feststellen, dass ich im späteren Verlauf des Skriptes darauf angewiesen bin mittels WMI bestimmte Werte wie RAM und CPU zu ermitteln. Dies geht nur, wenn ich eine Verbindung vom zentralen Management-Server aus zum Zielserver aufbauen kann. Hierzu fehlte leider eine Regel in der Firewall der Server, die eine eingehende und ausgehende Kommunikation mit dem RPC-Server/-Service zulässt. Also musste ich noch eine weitere Anpassung an der Gruppen-Richtlinie vornehmen.

SQLDays 2018 in München

Dieses Jahr war ich erstmalig auf den SQLDays in München genauergesagt in Erding (Erdinger Stadthalle), bei den SQLDays handelt es sich um eine Schulungs-Veranstaltung der ppedv. In den zwei bzw vier Tagen geht es vor allem um die namensgebende Microsoft-DataPlatform Umgebung rund um den SQL Server, an zwei Workshop-Tagen und zwei Konferenz-Tagen können die Teilnehmer aus einer Vielzahl von interessanten Sessions von hochrangigen Sprechern auswählen. Zum Beispiel hielt Georg Urban die Keynote und Markus Raatz hielte folgenden Vortrag:

Markus Raatz : Echtzeitdatensets in Power BI: Einführung und HowTo

Von Echtzeit-Daten, wie sie meist im Streaming-Verfahren von IoT-Datenquellen geliefert werden, geht ein großer Reiz aus. Nichts ist schöner, als auf ein Browserfenster zu starren und zu sehen, wie sich der winzige Lieferwagen von allein Meter um Meter auf mein Haus zubewegt! Auch Dashboards, in denen Liniengrafiken auf- und abwärts zucken, können uns stundenlang beschäftigen. Der technische Hintergrund dazu sind Power BI Streaming Datasets, deren Möglichkeiten wir uns in diesem demo-reichen Vortrag einmal ansehen werden. Was sind mögliche Visualisierungen, welche Datenquellen bieten sich an und welche Beschränkungen der Technologie gibt es?

Aber auch die Sponsoren liessen es sich nicht nehmen ihr Wissen zu verbreiten, hier ist Andreas Heberger von Amazon mit seinem Vortrag zu nennen:

Orange Is The New Blue – Warum Amazon Web Services eine gute Wahl für Ihre Microsoft SQL Workloads ist

Wir zeigen Ihnen welche Möglichkeiten die AWS Plattform bietet, Ihre Microsoft SQL Workloads performant, flexibel und kosteneffizient in der Cloud zu betreiben. Desweiteren bietet AWS Möglichkeiten den administrativen Aufwand zu verringern, damit Sie sich wieder auf Kernaufgaben konzentrieren können. Dabei beleuchten wir die Vor – und Nachteile der einzelnen Varianten, von der klassischen Installation auf IaaS VMs, dem AWS managed Service (RDS) sowie Migrationsstrategien. Darüber hinaus wollen wir Wege aufzeigen wie vorhandene Lizenzinvestments weiterverwendet werden können, und wie Sie mithilfe von AWS sogar Ihre Lizenzkosten verringern können.

Neben den genannten waren viele nationale und europäische Sprecher auf den SQLDays und trugen so zu einem ordentlichen Wissenstransfer bei!

Mein Vortrag zu Azure SQL Database konnte ein wenig auf dem zeitlich früheren Vortrag von Greogor Reimling aufbauen, der den Teilnehmern etwas über die Azure Managed Instance erzählte.

Gregor Reimling - SQLDays 2018 - Azure SQL Managed Instance

Kurz vor der Mittagspause stand ich dann im großen Saal und durfte den interessierten Teilnehmern etwas zu Azure SQL Database und deren Administration mit Powershell näher bringen, für alle die an meinem Vortrag teilgenommen haben, hier auch noch einmal ein Hinweis wegen der gescheiterten Demo => hier ist der Nachtrag bzw die Korrektur

Die Organisation der Veranstaltung war sehr gut, Teilnehmer und Sprecher der SQLDays wurden sehr gut versorgt, man musste sich um nichts Gedanken machen, egal ob Getränke und Snacks zwischen den Sessions oder Mittagessen oder während der gemeinsamen Abendveranstaltung! Ausreichend Getränke und super-leckeres Essen sorgten für eine angenehme Atmosphäre und motivierte Mitwirkende!

Bjoern Peters - Azure SQL Database - SQLDays 2018

Natürlich habe ich auch im Rahmen meiner Anwesenheit (ich war nur den Dienstag auf den SQLDays) auch mehreren Sessions gelauscht, wie zum Beispiel Andre Essing:

The joy of analytics – Lassen Sie uns zusammen ein Data Warehouse in die Cloud malen

Es gibt eine Menge Wege und Möglichkeiten Mehrwerte aus seinen Daten zu ziehen. Seit Jahren machen wir das mit den gleichen Techniken in unseren “klassischen” Data Warehouse Umgebungen. Aber die Welt ist im steten Wandel und so auch die Daten. Wo die Daten vor ein paar Jahren noch ausschließlich strukturiert waren, wächst die Zahl von schemalosen Datentypen ins unermessliche, und eine Ende ist nicht in Sicht. Wir kämpfen mit Daten, bei denen sich ständig das Schemata ändert und versuchen Mehrwerte aus neuen Datentypen wie Soziale Medien, Videos und Bildern zu ziehen. In dieser Whiteboard Session möchte ich mit Ihnen über moderne Wege sprechen, Ihre Daten zu speichern, zu analysieren und zu visualisieren. Zusammen zeichnen wir ein Modern Data Warehouse, schauen uns an welche Möglichkeiten sich bieten verschiedenste Daten zu analysieren und warum uns die Cloud hier hilft. Besuchen Sie meinen Vortrag und zeichnen Sie mit mir zusammen ein modernes Data Warehouse.

Andre Essing - SQLDays 2018

Es hat auf jeden Fall sehr viel Spaß gemacht und es war meine erste Teilnahme an den SQLDays, die meine Münchener Kollegen immer wieder als großartige Veranstaltung erwähnt haben, daher erfüllt es mich auch ein wenig mit Stolz dort als Sprecher dabei sein zu dürfen. Vielleicht klappt es ja auch im nächsten Jahr wieder mit einem spannenden exklusiven Vortrag für die SQLDays 2019 in Erding. Termin steht schon 😉

SQLDays 2019 – Save the date: 14.-17. Okt. 2019 München

Weitere Informationen findet ihr auf der Homepage der SQLDays…

Powershell – Ermitteln aller installierter SQL Server Services

Manchmal sind es die kleinen Dinge, die einem das Leben erleichtern können… 😉
Vor oder nach der Installation des SQL Servers auf einem Windows Server sollte man auch einen entsprechenden Virenschutz installieren, oder man möchte bestimmte Dienste/Services aus dem Monitoring ausklammern… dann benötigt man für die jeweiligen Ausnahmen die Pfade und Namen der ausführenden Programme. Natürlich kann man sich diese Informationen manuell über die Services-Ansicht holen, aber diesen “Klick-Aufwand” kann man sich getrotzt sparen, denn es geht viel einfacher.

Beispiel aus dem Leben

Für einige unserer Kunden und deren Anti-Viren-Strategie müssen wir unseren Kollegen immer eine EMail zukommen lassen, welche Dienste (ausführbaren Programme) und deren Verzeichnisse NICHT gescannt werden sollen… wir haben uns also auf ein Format geeinigt, welches wir schnell und einfach liefern können und wo die Kollegen die relevanten Daten auf “einen” Blick entnehmen können, um diese dann in der Administrations-Oberfläche für den jeweiligen SQL Server zu hinterlegen. Da wir nicht nur einen SQL Server installieren, sondern ein paar mehr… musste eine “universelle” Lösung her.

Overview SQLServer Services GUI

Wo bekommen wir also diese Daten idealerweise her? Natürlich aus dem Betriebssystem und dem bereits mitgelieferten WMI-Stack… also ran an die Services-Informationen

Get-WmiObject win32_service

Aber so erhalten wir eben eine Vielzahl von Informationen und Services, die wir für unsere Zwecke gar nicht gebrauchen können, denn wir wollen ja nur die SQL Server relevanten Services identifizieren und an die Kollegen melden… also müssen wir diese Informationsflut mit einem Filter eindämmen.


Jetzt erhalten wir nur noch alle Services mit dem Pattern “*sql*”, was für einen SQL Server völlig ausreichend ist, denn glücklicherweise werden aktuell alle SQL Server auf Windows Dienste mit eben diesem Pattern bezeichnet. Hier fehlen aber die relevanten Informationen wie Pfad und Exe oder der Anzeigename… damit wir nun auch diese weiteren Informationen erhalten muss man ein wenig tricksen und die Pfad-Angabe – welche hier ebenfalls (versteckt) enthalten ist – zerlegen.

Get-WmiObject win32_service | ?{$_.Name -like '*sql*'} | select Name, DisplayName, @{Name="Path"; Expression={$_.PathName.split('"')[1]}}


Theoretisch könnte man das nun an die Kollegen schicken, damit aber dort kein Fehler bei Copy&Paste passiert, formatieren wir das Ergebnis noch mit dem Powershell-Ausgabe-Format “Format-List”, dann verrutscht man nicht mehr so leicht in der Zeile und es ist etwas übersichtlicher (auf meinem Laptop ist nicht viel installiert, aber ihr versteht zumindest was ich meine) 😉

Get-WmiObject win32_service | ?{$_.Name -like '*sql*'} | select Name, DisplayName, @{Name="Path"; Expression={$_.PathName.split('"')[1]}} | Format-List

Dieses Ergebnis können wir nun ohne Bedenken in ein Mail-Template einfügen und den Kollegen schicken…

SQLDays 2018 in München – Nachtrag – Pause aka Restore

Im Rahmen meines Vortrages auf den SQLDays in München hatte ich versucht einen Workaround zu “Wie spare ich Geld? Ich droppe einfach die Datenbank!”… hierzu möchte ich gerne ein Update posten.
Aber der Reihe nach, denn erst einmal möchte ich mich recht herzlich bei der ppedv Event bedanken für die Einladung nach München, zum anderen bei den zahlreichen Teilnehmern, die meine Session besucht haben! Ich hoffe ihr habt alle etwas aus meiner Session mitgenommen und könnt diese Ideen und Anregungen in eurem Alltag umsetzen bzw integrieren.

Unsplash - Photo by kevin Xue - THANK YOU

Powershell – Workaround um Kosten zu sparen

In meiner Demo ist das Wiederherstellen nach dem “Drop Database” leider fehlgeschlagen, so dass ich in meiner Demo nicht zeigen konnte wie man aus dem logischen SQL Server das gespeicherte “Last Deleted Database” entnehmen kann, um daraus einen Restore zu erzeugen. Ich habe diese Code-Zeilen bisher immer nur einmal ausgeführt, also Demo-Umgebung frisch aufsetzen, die Skripte nur auf Syntax überprüfen und hoffen das alles gut geht 😉 Dieses mal hatte ich meine Skripte eben doch einmal vorher ausgeführt, dadurch entstand schon ein Eintrag für “DeletedDatabases”… und somit gab es eben mehr als einen Eintrag und der Restore wußte nicht auf welches Datum er zurück gehen sollte…

# Do not continue until the cmdlet returns information about the deleted database.
if(![string]::IsNullOrEmpty($deleteddatabase)) {
Write-Host "Now restoring database $databasename_backup ..." -foregroundcolor "DarkYellow"
Restore-AzureRmSqlDatabase -FromDeletedDatabaseBackup `
-ResourceGroupName $resourcegroupname `
-ServerName $servername_backup `
-TargetDatabaseName $databasename_backup `
-ResourceId $deleteddatabase.ResourceID `
-DeletionDate $deleteddatabase.DeletionDate `
-Edition "Standard" `
-ServiceObjectiveName "S0"
}

Bin ich so bisher noch gar nicht drüber gestolpert, aber als ich dann nach der Session das Skript und den Output mir noch einmal angesehen habe…

SQLDays AzureSQLDB DeletedDatabases - Scriptproblem

Ich könnte mir vorstellen, dass es noch eine sichere oder sinnvollere Lösung gibt, aber als Ansatz bzw vorübergehende Lösung kann man das erst einmal so machen 😉
Es gibt zumindest zwei Möglichkeiten…

Möglichkeit 1

Aus meiner Sicht am einfachsten, aber unter Umständen nicht sicher, dass tatsächlich das Datum des letzten Löschvorganges übernommen wird, da das Skript zuvor keinen Einfluss auf die Sortierung der Ergebnisse nimmt.

# Do not continue until the cmdlet returns information about the deleted database.
if(![string]::IsNullOrEmpty($deleteddatabase)) {
Write-Host "Now restoring database $databasename_backup ..." -foregroundcolor "DarkYellow"
Restore-AzureRmSqlDatabase -FromDeletedDatabaseBackup `
-ResourceGroupName $resourcegroupname `
-ServerName $servername_backup `
-TargetDatabaseName $databasename_backup `
-ResourceId $deleteddatabase[0].ResourceID `
-DeletionDate $deleteddatabase[0].DeletionDate `
-Edition "Standard" `
-ServiceObjectiveName "S0"
}

Syntaktisches korrekt, funktioniert auf jeden Fall, ABER eben keine 100%ige Gewissheit, dass auch tatsächlich der gewünschte Zeitpunkt ausgewählt wird.

Möglichkeit 2

Etwas “umständlicher”, aber auf jeden Fall sicherer, denn wir wählen explizit das zu letzt hinzugefügte Datum aus.

# Do not continue until the cmdlet returns information about the deleted database.
if(![string]::IsNullOrEmpty($deleteddatabase)) {
Write-Host "Now restoring database $databasename_backup ..." -foregroundcolor "DarkYellow"
Restore-AzureRmSqlDatabase -FromDeletedDatabaseBackup `
-ResourceGroupName $resourcegroupname `
-ServerName $servername_backup `
-TargetDatabaseName $databasename_backup `
-ResourceId ($deleteddatabase.ResourceID | Select-Object -Last 1) `
-DeletionDate ($deleteddatabase.DeletionDate | Select-Object -Last 1) `
-Edition "Standard" `
-ServiceObjectiveName "S0"
}

Syntaktisches korrekt, funktioniert auf jeden Fall, ABER eben keine 100%ige Gewissheit, dass auch tatsächlich der gewünschte Zeitpunkt ausgewählt wird.

SQLDays-AzureSQLDB-DeletedDatabases-Script-optimized

Nun kann ich auch die SQLDays 2018 in München auf jeden Fall als Erfolg verbuchen, da ich wieder etwas an meinen Demos optimieren konnte und den Teilnehmern doch noch zeigen kann, wie dieses Skript funktioniert. In den nächsten Tage werde ich meine Demo-Skripte auf Github entsprechend aktualisieren, damit jeder davon profitieren kann!

Hier findet Ihr/sie nicht nur meine Skripte sondern auch meine Slides als PDF.

Skripte und Slides zu den SQLDays 2018 von SQL_aus_HH auf Github

Azure SQL Database – Probleme beim Löschen von Recovery Service Vault

Ich möchte euch heute von einer Erfahrung berichten, welche ich in den letzten Tagen mehrfach und wiederholt machen musste. Für meine Sessions bei der Imagine Cloud Conference und dem PASS Camp über Azure SQL Databases hatte ich einen Azure Recovery Service Vault angelegt, um dort die Backups für die Langzeit-Archivierung abzulegen. Nachdem die Sessions beendet waren, wollte ich aufräumen bzw für die nächste Session vorbereiten, hierzu wollte ich die ganze Ressource-Gruppe löschen (samt SQL Server, Azure SQL Databases und dem besagten Recovery Service Vault). Egal was ich versucht habe, der Recovery Service Vault ließ sich nicht löschen, der SQL Server mit seinen SQL Databases konnte erfolgreich gelöscht werden, der ARS Vault aber blieb hartnäckig bestehen… Die Fehlermeldung lautete sinngemäß, dass noch registrierte Server / Items vorhanden sind (Please delete any replicated items, registered servers, Hyper-V sites…), welche erst gelöscht werden müssen. In der Service-Übersicht war allerdings nichts hierzu zu finden, keine registrierten Server, keine registrierten Server oder Replicated Items, keine Größen… es konnte nichts gefunden werden, was darauf hindeutete wo sich noch etwas verbirgt.

fast verzweifelt - verzweifelte Suche - StockSnap_27XHUPB48N - aus dem Newsletter von StockSnap

Verzweiflung breitet sich aus

Wie kann ich also nun diesen Azure Recovery Service Vault wieder löschen? Wenn es sich wenigstens um eine generische Ressourcengruppe handeln würde, aber da ich zur Abgrenzung der einzelnen Veranstaltungen bzw der Einfachheit halber alle Ressourcen einer Demo in einer Ressourcengruppe anlege, damit ich sie schneller löschen kann… hätte ich den ARS Vault entweder gerne verschoben oder eben doch ganz gelöscht… (siehe Beitragsbild ganz oben)

Folgende Fehlermeldung habe ich wiederholt bekommen:

Deletion of ARS Vault failed - Error Message

Vault cannot be deleted as there are existing resources within the vault. Please ensure there are no backup items, protected servers or backup management servers associated with this vault. Unregister the following containers associated with this vault before proceeding for deletion : Unregister all containers from the vault and then retry to delete vault

Bei der Kontrolle des Azure Recovery Services, welche Server oder Backup Items noch in dem ASR-Vault konfiguriert sind, schaute ich natürlich als erste in den entsprechenden Service nach… aber egal welche Ansicht ich auch öffnete, ich konnte keinerlei verbliebenen Backups finden.

Deletion of ARS Vault failed - Backup Details on ARS

 

Also erst einmal eine Runde googlen ob jemand anderes dieses Problem schon einmal gehabt hat… und siehe da, so ganz unbekannt ist das Problem mit dem Löschen des Azure Recovery Services nach der Nutzung mit Azure SQL Databases nicht. Felipe de Assis hatte hierzu bereits einen kleinen Beitrag und ein Skript geschrieben => https://social.msdn.microsoft.com/ Der eigentliche Grund liegt darin, dass weder Azure SQL VM Server noch Azure SQL Databases dort als aktiv gelistet werden und diese explizit mittels Powershell zu löschen sind. Ich habe das Skript nach meinen Anpassungen hier unten angehängt, so dass ihr seht was ich meine…

Login-AureRmAccount

$vault = Get-AzureRmRecoveryServicesVault -Name "WingtipDB-LongTime"
Set-AzureRmRecoveryServicesVaultContext -Vault $vault

$containers = Get-AzureRmRecoveryServicesBackupContainer -ContainerType AzureSQL -FriendlyName $vault.Name
ForEach ($container in $containers) {
 $items = Get-AzureRmRecoveryServicesBackupItem -container $container -WorkloadType AzureSQLDatabase
 ForEach ($item in $items) {
 Disable-AzureRmRecoveryServicesBackupProtection -item $item -RemoveRecoveryPoints -ea SilentlyContinue
 }
 Unregister-AzureRmRecoveryServicesBackupContainer -Container $container
}
Remove-AzureRmRecoveryServicesVault -Vault $vault

Damit ließ sich auch der Recovery Service Vault einwandfrei löschen und dann auch die Ressourcegruppe und ich hatte wieder eine saubere Test- bzw Demo-Umgebung.