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:
  - [ 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

EOF
        vars = {
                hostname = "${var.vsphere_name}${var.vsphere_dom}"
        }
}

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/

Windows 10 und Server: SMBv1 wieder aktivieren/deaktivieren

Problem:
Ab Windows 10 1709 wird das SMBv1-Protokoll nicht mehr standardmäßig installiert. Es stehen nur noch SMBv2 und v3 zur Verfügung. Da ich noch Drucker und NAS-Systeme habe, die leider außschließlich SMBv1 verwenden, musste ich das übergangsweise aktivieren.

Lösung:
Hier die Powershell-Befehl um SMBv1 abzufragen, zu akivieren und wieder zu deaktivieren:
Status abfragen:
Get-WindowsFeature FS-SMB1

Deaktivieren:
Disable-WindowsOptionalFeature -Online -FeatureName smb1protocol

Aktivieren:
Enable-WindowsOptionalFeature -Online -FeatureName smb1protocol

ACHTUNG: ES WIRD NICHT EMPFOHLEN SMBv1 DAUERHAFT ZU AKTIVIEREN AUFGRUND VIELER SICHERHEITSLÜCKEN IN DIESEM PROTOKOL!!!

Quelle: Microsoft Support: Erkennen, Aktivieren und Deaktivieren von SMBv1, SMBv2 und SMBv3 in Windows und Windows Server

HP (Aruba) Switch: traditional WebGUI dauerhaft aktivieren

Problem:
Bei neuen HP Switchen ist standardmäßig die neue WebGUI aktiv. Diese ist mir persönlich zu bunt und unübersichtlich. Ich bevorzuge die traditionelle Ansicht. Leider muss ich das immer umständlich bei jedem Login über "Launch Traditional GUI" umstellen.

Lösung:
Man kann die "traditional WebGUI" dauerhaft aktivieren. Dazu muss man nur die CLI verwenden:

1.) An CLI als Admin anmelden (per Telnet/SSH)
2.) Befehl "config" eingeben (enter config mode (config)# )
3.) Befehl "web-management interface traditional" eingeben (enable traditional interface)
4.) Befehl "write memory" eingeben (save config to memory)

FERTIG!

Docker & QEMU auf einem Rechner

Problem : Ich habe Docker und QEMU auf einem Rechner laufen. Nach der Docker Installation war es der virtuellen Maschine in QEMU nicht mehr möglich ins Internet zu zugreifen.

Lösung :
In meinem Fall waren die Default Einstellungen der Docker-CE Installation Schuld. Durch das korrigieren der IP-Tables konnte ich das Problem in meinem Fall beheben.
iptables -A FORWARD -i br1 -o br1 -j ACCEPT
Der Fehler tritt auch manchmal auf wenn der Linux Server in QEMU installiert ist und die lokale Firewall Einstellung das forwarding nicht zulässt.

Switch HP OfficeConnect 1920S: Telnet/SSH aktivieren

Problem:
Der Switch HP OfficeConnect 1920S ist ein sehr günstiger Full-Gigabit PoE Switch. Man muss ein paar Abstriche am Gerät machen, aber an sich ein sehr guter Switch. Für mich sind folgende Punkt etwas störend, aber für den Zweck der Switche akzeptabel:
- kein Consolen-Port (serieller Anschluss)
- Stromkabel kein Kaltgerätestecker - ist nur für den direkten Anschluss an der USV geeignet.
- Only Web-Managed

Mein Problem war, dass der Switch nur Web-Managed ist und keinen Zugriff per Telnet oder SSH bietet. Da ich kein Freund von GUIs bei Switchen bin wollte ich Telnet und/oder SSH-Zugriff haben um auf die CLI zugreifen zu können.
Per Default leider nicht möglich, aber man kann es über einen kleinen Umweg aktivieren!

Lösung:
1.) Firmware-Update auf die aktuelle Version über die GUI (bei mir PD.02.06)
2.) Eine aktuelle Start-Config exportieren über Maintenance -> Backup and Update Manage
3.) Die exportierte Config editieren und folgende Zeile VOR der Zeile "configure" setzen
ip telnet server enable
Beispiel Startup-Config von mir:
!Current Configuration:
!
!System Description "HPE OfficeConnect Switch 1920S 48G 4SFP PPoE+ (370W) JL386A, PD.02.06, Linux 3.6.5-a07f8920, U-Boot 2012.10-00118-g3773021 (Oct 11 2016 - 15:39:54)"
!System Software Version "PD.02.06"
!System Up Time "0 days 0 hrs 6 mins 39 secs"
!Additional Packages HPE QOS,HPE IPv6 Management,HPE Routing
!Current SNTP Synchronized Time: SNTP Client Mode Is Disabled
!
vlan database
exit
ip telnet server enable
configure
time-range Schedule-1
exit
time-range Schedule-2
exit
no username guest
line console
exit
line telnet
exit
line ssh
exit
!
exit

4.) Neue Startup-Config speichern und über die GUI als Startup-Config importieren (Maintenance -> Backup and Update Manage)
5.) Switch rebooten
6.) Telnet auf die Switch-IP ausführen (Default: Telnet 192.168.1.1)
7.) Mit folgenden Zeilen SSH aktivieren:
enable
configure
crypto key generate rsa
crypto key generate dsa
exit
ip ssh server enable
ip ssh protocol 2
write memory confirm
quit

8.) Wer möchte kann Telnet auch wieder deaktivieren mit dem Befehl:
ip telnet server disable


Kleiner Tipp am Rande: Wenn man die Startup-Config hochlädt, dann werden Kennwörter und sonstige Konfigurationen wieder verworfen! Also bitte erste Telnet/SSH aktivieren und dann Switch konfigurieren!

Quelle für die Hilfe:
Switches 'HPE OfficeConnect 1920S' - Enable SSH / TFTP Services
“Sicher ist, dass nichts sicher ist. Selbst das nicht.”
Joachim Ringelnatz