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.
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/
als wird ein Terraform Konfiguration benötigt. Ich habe das alles in 3 Dateien aufgeteilt.
- main.tf
- terraform.tfvars
- variables.tf
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.T7byqXbNyyyyyyyyyyyyyyyyyyyjetzt 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 KEYdann bauen wir daraus ein ISO File
cloud-localds config.iso config.yamlJetzt 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-toolsJetzt 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/