Terraform & cloud-init & vmware

Automatisiertes Deployment von virtuellen Maschinen in eine VMWare Umgebung mit Hilfe von Terraform und cloud-init.

als wird ein Terraform Konfiguration benötigt. Ich habe das alles in 3 Dateien aufgeteilt.
  • main.tf
  • terraform.tfvars
  • variables.tf
zuerst erstellen wir die Datei variables.tf um warm zu werden ;-)
variable "vsphere_server" {}
variable "vsphere_user" {}
variable "vsphere_password" {}
variable "vsphere_name" {}
variable "vsphere_dom" {}
variable "vsphere_datacenter" {}
variable "vsphere_datacenter_folder" {}
variable "vsphere_datastore" {}
variable "vsphere_resource_pool" {}
variable "vsphere_network" {}
variable "vsphere_template" {}
variable "vsphere_guest_id" {}
dann setzen wir die Variablen in der neuen Datei terraform.tfvars
# define the vsphere server
vsphere_server = "dev-vm-test-cl-01.demo.local"
# the username to access (use \\ instead \)
vsphere_user = "vsphere.local\\dev"
# password for the user
vsphere_password = "..................."
# name of the guest system
vsphere_name = "demo-vm"
# domain name 
vsphere_dom = ".demo.local"
# datacenter in vmware
vsphere_datacenter = "demo-dc"
# if you use folders define here
vsphere_datacenter_folder = "DEMO"
# datastore to store the machine
vsphere_datastore = "DEMOSAN"
# resource pool 
vsphere_resource_pool = "DEMO"
# the name of the network who the machine should use
vsphere_network = "DEMO-NETZ"
# which template should terraform use to build the machine ?
vsphere_template = "CENTOS-7-DEMO"
# define the guest id
vsphere_guest_id = "centos7_64Guest"
um das deploment durchzuführen benötigen wir noch einen user für die Anmeldung am Gast den wir in der main.tf definieren können hierzu erstellen wir uns erstmal den passwort hash. Ich hab hier mal einfach TEST genommen für ein produktives Deployment nicht zu empfehlen !
python3 -c 'import crypt,getpass; print(crypt.crypt(getpass.getpass(), crypt.mksalt(crypt.METHOD_SHA512)))'
Password:
xxxxxxxxxxxxxxxxxxxxx1Q0T3BfTTFcA.T7byqXbNyyyyyyyyyyyyyyyyyyy
jetzt kümmern wir uns um die main.tf die das eigentliche deployment übernimmt. Die user-data und meta-data werden der Maschine direkt als Template mitgegeben, für mehr Informationen zu cloud-init könnt ihr hier die Doku lesen.
provider "vsphere" {
        vsphere_server = "${var.vsphere_server}"
        user = "${var.vsphere_user}"
        password = "${var.vsphere_password}"
        allow_unverified_ssl= true
}

data "vsphere_datacenter" "dc" {
         name = "${var.vsphere_datacenter}"
}

data "vsphere_datastore" "datastore" {
        name = "${var.vsphere_datastore}"
        datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_resource_pool" "pool" {
  name          = "${var.vsphere_resource_pool}"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_network" "network" {
  name          = "${var.vsphere_network}"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_virtual_machine" "template" {
  name          = "${var.vsphere_template}"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "template_file" "meta_init" {
        template = <<EOF
{
        "local-hostname": "$${local_hostname}"
}
EOF

vars = {
        local_hostname = "${var.vsphere_name}${var.vsphere_dom}"
}
}

data "template_file" "cloud_init" {
        template = <<EOF
#cloud-config
# set hostname & keyboard layout
bootcmd:
  - [ sh, -c, "echo 'DEPLOY-DATE-TIME - $${deploy_date}' > /cloud-init-info.txt"]
  - [ localectl, set-keymap, de ]
  - [ hostnamectl, set-hostname, $${hostname} ]
  - [ setenforce, 0 ]
  - [ sed, -i, 's/enforcing/disabled/g', /etc/selinux/config ]
growpart:
  mode: auto
  devices: ['/']
  ignore_growroot_disabled: false
users:
  - name: demo
    groups: wheel
    lock_passwd: false
    passwd: xxxxxxxxxxxxxxxxxxxxx1Q0T3BfTTFcA.T7byqXbNyyyyyyyyyyyyyyyyyyy
    shell: /bin/bash
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    ssh-authorized-keys:
      - ssh-rsa AAAAB................. DEPLOY@HOST
# set root password 
chpasswd:
  list: |
     root:xxxxxxxxxxxxxxxx4IlB$pLkby1WsExxxxxxxxxxxxxxxx
EOF
        vars = {
                hostname = "${var.vsphere_name}${var.vsphere_dom}"
                deploy_date = formatdate ("DD'.'MM'.'YYYY hh:mm ZZZ",timestamp())
        }
}

resource "vsphere_virtual_machine" "vm" {
  name             = "${var.vsphere_name}${var.vsphere_dom}"
  resource_pool_id = "${data.vsphere_resource_pool.pool.id}"
  datastore_id     = "${data.vsphere_datastore.datastore.id}"
  folder           = "${var.vsphere_datacenter_folder}"
  num_cpus = 4
  memory   = 8096
  guest_id = "${var.vsphere_guest_id}"

  network_interface {
    network_id = "${data.vsphere_network.network.id}"
  }

  disk {
    label = "disk0"
    size  = 150
  }

  clone {
    template_uuid = "${data.vsphere_virtual_machine.template.id}"
  }

  extra_config = {
        "guestinfo.metadata" = "${base64gzip(data.template_file.meta_init.rendered)}"
        "guestinfo.metadata.encoding" = "gzip+base64"
        "guestinfo.userdata" = "${base64gzip(data.template_file.cloud_init.rendered)}"
        "guestinfo.userdata.encoding" = "gzip+base64"
        }
}
Terrafom & cloud-init wäre dann fertig , jetzt müssen wir uns noch ein Image bauen. Ich habe dafür das CentOS-7-x86_64-GenericCloud.qcow2 Image von CentOs heruntergeladen. Und wie hier beschrieben konvertiert. Für die Anpassung des Templates musste ich mir eine extra cloud-config schreiben die nur eins macht, einen Benutzer mit login anlegen ;-) Dazu habe ich mir unter Ubuntu das Packet cloud-utils installiert. Dann erstellst du eine Datei config.yaml mit diesem Inhalt.
#cloud-init
users:
  - name: image
    groups: wheel
    lock_passwd: false
    passwd: $6$..............................zVjyZr4fj1
    shell: /bin/bash
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    ssh-authorized-keys:
      - DEIN SSH KEY
dann bauen wir daraus ein ISO File
cloud-localds config.iso config.yaml
Jetzt muss die konvertierte vmdk auf den Datastore hochgeladen werden. Dann eine neue Maschine anlegen und als Festplatte die vorhandene vmdk Datei auswählen, in das CDROM die hochgeladene iso Datei einlegen und verbinden (auch beim einschalten). Beim Bootvorgang sieht cloud-init die cd und erkennt die user-data darauf. Es wird ein User angelegt der zuvor definiert wurde. Ich lasse das ISO auf dem Datastore für kommende Images die ich erstellen muss. Wir ihr das Passwort erstellt habe ich ja bereits weiter oben erklärt.Nach dem erstellen der VM anmelden und dann installieren wir im system noch open-vm-tools und cloud-init-vmware-guestinfo
yum install open-vm-tools
Jetzt machen wir die Kiste noch sauber das man ein sauberes Image ziehen kann. Das ist bereits hier schön erklärt. Wenn du damit fertig bist die virtuelle Maschine ausschalten und in ein Template klonen, am besten nimmst du als Namen für das Template CENTOS-7-DEMO. Jetzt sollte wenn du bootest ein neuer Benutzer angelegt werden mit dem Namen und dem Passwort TEST. selinux sollte ausgeschaltet sein usw....

Quellen :
https://stafwag.github.io/blog/blog/2019/03/03/howto-use-centos-cloud-images-with-cloud-init/
https://superuser.com/questions/1307260/convert-qcow2-image-to-vsphere-vmdk
https://stackoverflow.com/questions/37794846/convert-qcow2-to-vmdk-and-make-it-esxi-6-0-compatible
https://github.com/vmware/cloud-init-vmware-guestinfo
https://github.com/vmware/simple-k8s-test-env/tree/master/e2e
https://blah.cloud/infrastructure/using-cloud-init-for-vm-templating-on-vsphere/
https://community.spiceworks.com/how_to/151558-create-a-rhel-centos-6-7-template-for-vmware-vsphere
https://cloudinit.readthedocs.io/en/latest/

VMWare: Windows Server Installation von Fujitsu ROK Lizenz auf VMWare 6

Problem:
Ich habe versucht meine Windows 2012 R2 Standard ROK Lizenz unter VMware 6 zu installieren. Dabei bin ich gleich am Anfang auf eine Meldung gestoßen, dass diese Version nur mit Fujitsu Servern funktioniert:

"This installer is designed to load only in virtual environments supported by Fujitsu and/or the virtual maschine provider."



Da meine ESX-Host Fujitsu-Server sind, habe ich nach einer Möglichkeit gesucht, die BIOS-Informationen in die VM durchzureichen.
Der Eintrag SMBIOS.reflectHost = "TRUE" hat nichts gebracht.

Lösung:
Das Problem ist, dass man bei VMware 6 bzw. System ab Server 2008R2 noch zwei zusätzliche Parameter in der VM eingeben muss. Ich habe folgende Parameter in die VM-Einstellungen konfiguriert und konnte damit meine ROK erfolgreich installieren und aktivieren:
SMBIOS.reflectHost = "TRUE"
SMBIOS.noOEMStrings = "TRUE"
smbios.addHostVendor = "TRUE"

Die Parameter trägt man nicht direkt in die vmx-Dateien ein, sondern kann diese ganz einfach in den Einstellungen der VM eintragen. Dazu folgende Anleitung:
1. VM-Einstellungen bearbeiten
2. Reiter "VM-Optionen" auswählen
3. Erweitert auswählen
4. Button "Konfiguration bearbeiten"
5. Hier die drei zusätzlichen Parameter hinzufügen
6. Alles mit OK bestätigen
7. Maschine starten und ROK-Lizenz installieren

Quelle: VMs mit ROK Key installieren

VmWare ESXi 4.1 - Windows 2012 R2 Server - CRITICAL_STRUCTURE_CORRUPTION

Problem :
Windows Server 2008 R2 / Windows 8.1 / Windows Server 2012R2 startet auf einer ESXi 4.1 nicht richtig. Es kommt immer zu einem Bluescreen mit der Information CRITICAL_STRUCTURE_CORRUPTION

Lösung :

Ein Update für ihre ESXi Maschine kann dieses Problem beheben.
Da es sich in meinem Fall um einen ESXi 4.1 handelte hier der andere Weg.
Ein Workarround ist eine eigene CPUID Mask für die betroffene Maschine zu erstellen.

1.) ausschalten der betroffenen virtuellen Maschine
2.) Einstellungen der vm bearbeiten
3.) Auf das Register Optionen wechseln
4.) auf CPUID Mask klicken
5.) auf Erweitert klicken und eine CPUMASKID eintragen

Für Intel CPU den Wert unter Level 80000001.edx auf ----:0---:----:----:----:----:----:---- ändern
Für AMD Cpu den Wert unter Level 80000001.edx auf ----0--------------------------- ändern




Quelle :
http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2060019

VmWare ESXi 4.1 - Windows 2012 R2 Server

Problem : Man möchte einen Windows 2012 R2 Server auf einer VMWare ESXi 4.1 Infrastruktur installieren. Dies scheitert leider mit einem Bluescreen von Windows 2012 R2 Server. ESXi 4.1 unterstützt diese Plattform nicht, mit einem kleinen Eingriff kann man es aber überreden.

Lösung :

1.) Erstellen einer virtuellen Maschinen mit dem Gasttemplate Windows 2008 R2 (64Bit) Server
2.) Nach dem erstellen diese Datei herunterladen und im Pfad der Maschine auf der ESXi Kiste abspeichern.
3.) Direkt nach dem erstellen der Maschine muss die vmx Datei angepasst werden.
Diesen Eintrag hinzufügen :
bios440.filename = "bios.440.rom"
mce.enable = TRUE
cpuid.hypervisor.v0 = FALSE
vmGenCounter.enable = FALSE

4.)Anschalten der virtuellen Maschine und installieren ;-)

Kleiner Tipp um das ROM auf den ESXi zu übertragen ist das Tool WinSCP gut geeigent

Für ein produktiv System empfiehlt sich die Vorgehensweise mit der Datei bios.440.rom nicht


Solltet ihr danach einen den Fehler bekommen CRITICAL_STRUCTURE_CORRUPTION lest euch das hier durch :
http://hope-this-helps.de/serendipity/archives/459-VmWare-ESXi-4.1-Windows-2012-R2-Server-CRITICAL_STRUCTURE_CORRUPTION.html

Quelle :
https://jgiffard.wordpress.com/
http://communities.vmware.com/servlet/JiveServlet/download/2139717-98102/bios.440.rom

VMWARE NFS Datastore über cli trennen / verbinden

Problem :

Ein NFS Datastore ist in der VMWare GUI als offline markiert. Ein trennen und neu verbinden ist nicht über die GUI möglich da es hier immer zu einer Fehlermeldung kommt.

Lösung :

Für ESX 5.X :

Trennen und neu Verbinden des NFS Datastore über esxcli

Erstmal lassen wir uns alle NFS Datastores anzeigen die auf dem Server verfügbar sind. Das erledigen wir mit dem Befehl
esxcli storage nfs list
ihr solltet nun einen Output in der Konsole sehen der meinem ähnlich ist.
Volume Name       Host            Share                                 Accessible  Mounted  Read-Only  Hardware Acceleration
----------------  --------------  ------------------------------------  ----------  -------  ---------  ---------------------
NFS Datastore 01  XXX.XXX.XXX.XXX XXXXX_datastore01                       true     true      false  Supported
NFS Datastore 02  XXX.XXX.XXX.XXX  XXXXX_datastore01                      true     true      false  Supported
nas               HOSTNAME_NAS    FREIGABEPFAD_AUF_NAS                   false     true      false  Not Supported


In der Auflistung sehen wir das nas Accessible=false ist. Ein Versuch diesen Datastore über GUI zu löschen bringt einen Fehler.

Wir löschen den Datastore über
esxcli storage nfs remove -v nas


Dannach können wir den Datastore wieder über die GUI hinzufügen oder wir nehmen diesen Befehl im Terminal.
esxcli storage nfs add -H NFS_IP|NFS_HOSTNAME -s Share_mount_point_on_the_NFS -v DatastoreName


Für ESX/ESXi 3.x und 4.x findet man eine gute Anleitung auf der verlinkten Quelle

Quelle : Remounting a disconnected NFS datastore from the ESXi/ESX command line (1005057)
“Sicher ist, dass nichts sicher ist. Selbst das nicht.”
Joachim Ringelnatz