0) Externe Links

Es werden hier einige externe Links verwendet die zum Zeitpunkt der Erstellung auf weiterführende Informationen verweisen. Da es aber natürlich nicht unter meiner Kontrolle ist was andere Personen auf deren Servern machen kann ich weder für die Inhalte noch für eine generelle Funktionsfähigkeit irgendeine Verantwortung übernehmen. Ausserdem gilt natürlich: Vor JEDER Änderung an einem System sollte ein Backup vorhanden sein und das ganze natürlich auch immer auf einem Testsystem erst mal probiert werden. Wenn irgendwas in diesen Informationen falsch ist und/oder Schäden am System verursacht gilt wie immer: Kein Backup, kein Mitleid! Und ganz wichtig: Auch da entziehe ich mich jeder Verantwortung - wer Dinge einfach mal auf nem Live-System ausprobiert ist selbst schuld.

1) Vorbedingungen

Ich denke mal wer soweit ist das überlegt wird Ansible mit Windows zu verwenden wird wohl schon ein Linux installiert haben. Das hier bezieht sich auf ein aktuelles Debian. Ansible muss mind. in der Version 2.9 vorliegen (ansonsten fehlen die Möglichkeiten für die Installation einiger Windows-Module).

2) Installation Ansible

Im besten Fall reicht einfach ein 

apt-get install ansible

aber - wie oft hat man schon den besten Fall? Zumindest bei mir war im Debian-Repo immer noch eine ältere Ansible-Version drin. Dann halt direkt vom Hersteller. In Debian als root in der /etc/apt/source.list den ubuntu-pfad mit aufnehmen (dieser ist kompatibel):

deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main

und dann den Key installieren mit

apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367

Danach reicht ein simplet

apt-get update
apt-get install ansible

aus um Ansible in einer aktuellen Version zu haben. Für andere Systeme (und auch weiterführende Informationen) gehts hier zur Seite des Herstellers.

3) Vorbereitung des Windows Servers

An dieser Stelle gehe ich davon aus das ein Windows 2019 installiert ist. Hierfür muss dann lediglich ein Script ausgeführt werden. Das original des Scriptes liegt hier. Da es aber im Internet ja auch durchaus mal Dinge gibt die sich ändern habe ich es auch einmal bei mir lokal gespeichert. Meine lokale Version wird natürlich nicht gepflegt, daher ist die orignal-Version immer zu bevorzugen! Das Script einfach lokal auf dem Windows-Server speichern (beachten: Dateiendung ps1 !) und ausführen.

Ich würde auch empfehlen einen User für Ansible einzurichten und nicht mit dem normalen Admin-Account zu arbeiten. Dieser braucht z.B. keine Remote-Desktop-Anmeldung usw. -> da wir ja keine Maus schubsen wollen.

4) Einstellungen der Ansible-Umgebung

Nun müssen wir dem Linux mit Ansible ja noch einiges über unsere Umgebung erzählen. 

4.1) Adressauflösung

Diesen Schritt könnte man weglassen - aber es erlaubt ein einfacheres Testen wenn man denselben Hostnamen für die Shell hat wie auch für Ansible. Sonst wundert man sich nur warum ein ping xyz nicht geht aber Ansible den Server erreichen kann. Hier kann man entweder auf den DNS setzen oder - sofern die Server alle statische IPs haben - die Linux Hosts-File nutzen. Ich persönlich nutze lieber die hosts-file da es eine Abhängigkeit vom DNS wegnimmt. Zu diesem Zweck habe ich also einfach folgenden Eintrag zur hosts-file hinzugefügt:

192.168.91.4 WinServer

Dabei ist 192.168.91.4 die IP meines Testservers, den Namen hab ich einfach mal als "WinServer" festgelegt. Bitte darauf achten - da dieser Name später auch noch verwendet wird. Der kann natürlich geändert werden aber muss dann auch im folgenden angepasst werden. 

4.2) Ansible-Hosts

In der Datei /etc/ansible/hosts wird ebenfalls ein WinServer angelegt:

[WinServer]
192.168.91.4

Das wars eigentlich schon, ab jetzt weiss Ansible zumindest schon mal das es den Server gibt. WinServer kann natürlich auch noch andere enthalten - oder auch mehrere IPs, ganze Gruppen,... Wir machen es aber einfach, eine IP reicht und wir nehmen den als Host und nicht als Gruppe.

4.3) group-vars

Als nächstes wollen wir dem System noch erklären welche Umgebungsvariablen der Server denn benötigt. Da ich bei mir die Scripte eher nicht in /etc/ansible direkt lagere sondern mir unterordner (wie hier z.B. windows) nutze erzeugen wir die Vereichnisse

/etc/ansible/windows
/ect/ansible/windows/group_vars

und erstellen die Datei /etc/ansible/windows/group_vars/WinServer (wichtig: Die muss so heissen wie der Verweis in der /etc/ansible/hosts!). Der Inhalt ist ebenfalls recht simpel:

ansible_user: ansible
ansible_password: an$i6l31
ansible_port: 5986
ansible_connection: winrm
ansible_winrm_server_cert_validation: ignore

Wobei hier natürlich bei User & Password die Windows-Zugangsdaten verwendet werden müssen. Das erklärt auch warum lieber eigene Daten und nicht gleich den (Domain-)Admin Account - diese Datei ist ggf. world-readable auf dem Linux-System (und sei es durch ein versehen) - dann möchte man ggf. das Passwort ja doch mal ändern. Dabei ist es leichter wenn man nicht gleich den Domain-Admin nutzt - und nebenbei ist es auch generell keine gute Idee immer mit dem (Domain-)Admin zu arbeiten.

5) Ansible-Anpassungen

Wer jetzt glaubt "so, das wars" - leider noch nicht. Zumindest in der normalen Installation fehlten noch einige Windows-Pakete für das ansible. Diese werden auf dem Ansible-Server einfach mittels

ansible-galaxy collection install ansible.windows

installiert.

6) Playbooks

Ab jetzt können wir (hoffentlich) ein wenig anfangen zu spielen. Playbooks werden als einfacher Text in einer yml-File gespeichert. Wichtig sind die Einrückungen! Ausgeführt werden die immer mittels

ansible-playbook xyz.yml 

bzw. wenns nur auf einen Teil von Servern ablaufen soll

ansible-playbook xyz.yml --limit WinServer

oder wenns alle hosts AUSSER dem WinServer treffen soll (es können ja auch mehrere Hosts in einer Gruppe oder in einem Playbook angegeben werden):

ansible-playbook xyz.yml --limit 'all:!WinServer'

6.1) Auf dem Windows-Server einen Ordner erzeugen

Dies ist ein recht einfaches Playbook - welches nur einen Ordner auf dem Server erzeugt (z.B. wenn man später irgendwelche Dinge runterladen will/muss)

--- 
- hosts: WinServer
  tasks: 
  - name: create folders
    win_file: 
       path: "C:\\Temp\\ArbeitsFolder"
       state: directory

Das ganze führen wir mal aus - und hoffentlich erscheint jetzt auf dem Server bereits der Ordner c:\Temp\ArbeitsFolder. Bitte am Anfang auch auf die "--- " achten inkl. des Space am Ende!

6.2) Ausführen eines Powershell-Scripts

Dafür legen wir mal auf dem Windows-Server ein Powershell-Script ab - als Beispiel lasse ich einfach mal ne Datei aus dem Web runterladen und lokal ablegen. Dafür wird die Datei c:\down.ps1 mit folgendem Inhalt erstellt:

Invoke-WebRequest -Uri "https://www.martv.de/myDownloadFile.zip" -OutFile "C:\temp\myDownloadFile.zip"

Ausgeführt wird das jetzt mit einem Playbook bei dem die yml-File folgendes enthält

--- 
- hosts: WinServer
  tasks: 
  - name: download file
    win_shell: c:\down.ps1 >> c:\temp\log.txt
    args:
       chdir: c:\temp

Das PS1-Script könnte natürlich jetzt auch beliebige andere Aktionen enthalten. Wichtig ist dabei nur im Kopf zu haben das es mit dem Ansible-Benutzer auf dem Server ausgeführt wird - dieser sollte also entsprechend auch die Berechtigungen haben die Aktionen auszuführen.

Wenn das Script jetzt nicht auf dem Server liegt (es wäre ja blöd wenn man eine zentrale Verwaltung baut die aber dann erfordert das man vorher erst manuell das Script auf den Server kopiert...): Dafür kann man ja eine einfache Windows-Freigabe (oder die administrative c$) nutzen um das Verzeichnis erst eben auf Linux zu mounten, die Daten zu kopieren und dann auszuführen. Es würde zwar auch z.B. für den Download einer Datei das Kommando "ansible.windows.win_get_url" geben - bei mir hat das aber immer nur Fehler erzeugt. 

7) Arbeiten mit HyperV

Zuerst kann man diese Schritte manuell machen um sicherzustellen das die überhaupt funktionieren. Danach kann man die Befehle natürlich einfach in die ps1-File einbauen und hat so ein fertiges Script was auf den Maschinen (remote) ausgeführt werden kann.

Hierfür muss zuerst geprüft werden ob das HyperV-Modul für die Powersell installiert ist (das macht natürlich nur manuell Sinn!):

Get-WindowsOptionalFeature -Online -FeatureName *hyper-v* | select DisplayName, FeatureName, State

zeigt die installierten HyperV-Module erst mal an. Hier sollten die MS-Hyper-V-Management-Powershell Module enthalten mit dem State "Enabled" enthalten sein. Mit dem Kommando

Import-VM -Path '<pfad-zur-vmcx-datei>\<vmcx-datei>' -Copy -VhdDestinationPath '<neuesZielverzeichnis>\Vhd' -VirtualMachinePath '<neuesZielverzeichnis>\VM' 

wird die vorher exportierte VM jetzt auf dem Windows 2019 importiert.

Anpassen der VM

Start/Stop-Action

Set-VM -Name <vm-name> -AutomaticStopAction Shutdown -AutomaticStartAction Start - AutomaticStartDelay 180

setzt die VM auf Autostart mit einer Verzögerung von 180 Sekungen. 

VLAN-Zuweisung

Set-VMNetworkAdapterVlan -VMName <vm-name> -Access -VlanId 104

würde die VM-Netzwerkkarte auf das VLAN 104 setzen

CPU-Einstellung

Set-VMProcessor -VMname <vm-name> -Count 2

weist der VM 2 CPUs zu

Hinzufügen der VM zu einem MS-Cluster

add-ClusterVirtualMachineRole -VirtualMachine <vmName>

fügt die VM in den lokalen Cluster ein.

8) Packen / Entpacken via Powershell

Mit der Powershell können keine Zip-Files entpackt werden die mit dem File-Explorer erstellt wurden (Fehlermeldung: Unsupported Compression Method). Daher wird eine exportierte VM erst mal mittels

compress-archive -path '<pfad-zum-hyperv-export>' -destinationPath '<zipfile-name>' -compressinlevel optimal

gepackt.

Danach kann man die Datei mittels 

Expand-Archive -Path '<pfad-zur-zipfile>' -DestinationPath '<ZielVerzeichnis>' 

entpacken. Alternativ (wenn die Datei zu gross wird) kann man natürlich auch freie Tools verwenden und die zip-File darüber entpacken (ab Win10 z.B. tar -xf <zipfile>)

 

 

Mit diesen wenigen Schritten sollte es möglich sein eine VM von einem zentralen Server runterzuladen, entpacken und bei HyperV zu registrieren. Wenn man das ganze jetzt in die PS1-File packt kann man es direkt per Ansible ausführen lassen und hat eine einfache Verteilung für virtuelle Maschinen.