Erfahrung im Aufbau von Infrastructure-as-Code in VMware. Teil 1: Hinweis auf ein Problem

    Grüße, lieber Leser. Ich beginne eine Reihe von Artikeln darüber, wie wir nach einer Lösung gesucht haben, um den Infrastructure-as-Code-Ansatz in unserer virtuellen VMware VSphere-Umgebung anzuwenden.

    Wir haben ein Puppet Konfigurationsmanagementsystem für Linux, es gibt (im Moment) DSC für Windows Server.

    Wie für Linux - fast alles ist automatisiert. Wir geben die Maschinenkonfigurationen in node.yaml ein, wir geben die Rollen in Hiera ein, bauen die Module auf (oder nehmen vorgefertigte), wir haben PXE, IP-Adressen werden von DHCP über MAC-Adressen verteilt.

    Dies bedeutet, dass vom Start der virtuellen Linux-Maschine bis zur Betriebsbereitschaft der virtuellen Maschine keine Aktion erforderlich ist. Versuchen Sie zu erraten, was in dieser Kette manuell gemacht wird? Richtig, die virtuelle Maschine selbst in VSphere erstellen.

    Als ich dieses Problem zum ersten Mal ansprach, teilten sie mir mit, dass sie nach einer Lösung suchten, probierten Optionen aus, aber nichts funktionierte. „Zum Teufel!“ Ich dachte und setzte auf eine Bierbox, dass ich eine Lösung finden würde, die dem folgenden Szenario entspricht: Der Entwickler oder Techniker stellt eine Pull-Anfrage, in der wir die Konfiguration der virtuellen Maschine (Kernel, Speicher, Netzwerk, Vorlage usw.) haben. .d.) - dann wendet sich etwas Magie an VSphere und erstellt eine Maschine gemäß den Einstellungen in der Datei.

    Lassen Sie mich ein wenig über unsere Umgebung erzählen, damit Sie verstehen, womit ich umgehen muss.

    Wir verwenden VMware VSphere als On-Premise-Virtualisierung - ein paar Rechenzentren, ein Datenspeicher-Cluster und mehrere Resource Pools (RP) für jeden Befehl. Die Teammitglieder haben das Recht, virtuelle Maschinen innerhalb des RP zu erstellen. Die Mitarbeiter der Infrastruktur beeinträchtigen dies nicht und warten lediglich die gesamte Plattform. Entwickler und Ingenieure werden regelmäßig daran erinnert, nicht verwendete Maschinen (nicht aus Gummi stammende Ressourcen) zu bereinigen.

    Wir haben virtuelle Windows-Maschinen, virtuelle Linux-Maschinen, der Umfang der Aufgaben ist riesig - Webserver, Reverse-Proxys, Balancer, Domänencontroller, Anwendungs- und Datenbankserver - und es gibt kein Ende für sie.

    Jetzt werde ich Ihnen sagen, welche Tools ich verwendet habe und warum sie nicht zu mir passten.

    Empirisch ...


    Ansible vsphere_guest


    Wie ich bereits im vorigen Artikel geschrieben habe , liebe ich Ansible sehr und in Sachen Automatisierung sehe ich als Erstes, ob es dafür verwendet werden kann.

    Laut Dokumentation gibt es ein gutes Modul vsphere_guest, mit dem virtuelle Maschinen erstellt und gelöscht werden können. Was du brauchst. So sieht mein Wiedergabebuch "createvm.yaml" aus

    ---
    - name: Create a VM in resource pool
      hosts: localhost
      connection: local
      gather_facts: False
      vars_prompt:
      - name: "user"
        prompt: "Enter your username to virtualcenter"
        private: no
      - name: "password"
        prompt: "Enter your password to virtualcenter"
        private: yes
      - name: "guest"  
        prompt: "Enter you guest VM name: "
        private: no
      tasks:
      - name: create VM
        vsphere_guest:
          vcenter_hostname: vcenter.example.com
          validate_certs: no
          username: '{{ user }}'
          password: '{{ password }}'
          guest: '{{ guest }}'
          state: powered_off
          vm_extra_config:
            vcpu.hotadd: yes
            mem.hotadd: yes
            notes: This is a test VM
          vm_disk:
            disk1:
              size_gb: 10
              type: thick
              datastore: mydatastore
          vm_nic:
            nic1:
              type: vmxnet3
              network: mynetwork
              network_type: standard
          vm_hardware:
            memory_mb: 1024
            num_cpus: 1
            osid: centos64Guest
            scsi: paravirtual
          resource_pool: "/Resources/MyResourcePool"
          esxi:
            datacenter: mysite
            #hostname: myesxhost01
    

    Ich kommentiere absichtlich den Hostnamen esxi, da ich eine virtuelle Maschine direkt in RP und nicht auf dem Host erstelle. DRS entscheidet, wo die virtuelle Maschine platziert wird.

    Wenn ich ein Playbook starte, schwört er, dass der erforderliche Hostnamen-Parameter nicht angegeben ist. Wenn ich ihn auskommentiere, kritisiert er das Fehlen von Rechten zum Erstellen einer virtuellen Maschine auf dem esx-Host (was offensichtlich ist, weil ich nur Rechte für RP habe). Ich habe ein entsprechendes Problem erstellt , daher hoffe ich, dass die Jungs von Ansible dieses Problem beheben, da das Tool wirklich gut ist.

    Terraform


    Ein weiteres Tool, mit dem virtuelle Maschinen in VMware erstellt werden können, ist Terraform, ein Produkt von HashiCorp. Ursprünglich war es für die Interaktion mit Packer inhaftiert und in AWS implementiert, löst aber auch unsere Aufgaben. Hier ist die Konfigurationsdatei selbst:

    provider "vsphere" {
      user           = “mylogin@example.com"
      password       = "${var.vsphere_password}"
      vsphere_server = “virtualcenter.example.com"
      allow_unverified_ssl = "true"
    }
    resource "vsphere_virtual_machine" "test" {
      name   = "${var.machine_name}"
      vcpu   = 1
      memory = 1024
      domain = “test.example.com”
      datacenter = "mysite"
      resource_pool = "Production Cluster #1/Resources/myresourcepool"
      network_interface {
          label = "test"
          ipv4_address = "192.168.1.2"
          ipv4_prefix_length = "24"
          ipv4_gateway = "192.168.1.1"
      }
      disk {
       datastore = "${var.datastore}"
       size = "10"
       name = "${var.datastore}/${var.machine_name}/${var.machine_name}.vmdk"
       template = "mytemplate"
      }
    }
    

    variables.tf
    variable "vsphere_password" {}
    variable "machine_name" {
        type = "string"
        default = "test"
    }
    variable "datastore" {
        type = "string"
        default = "mysite/mydatastore"
    }
    

    Terraform Plan funktioniert super.

     $ terraform plan
    var.vsphere_password
      Enter a value:  supersecurepassword
    Refreshing Terraform state in-memory prior to plan...
    The refreshed state will be used to calculate this plan, but
    will not be persisted to local or remote state storage.
    The Terraform execution plan has been generated and is shown below.
    Resources are shown in alphabetical order for quick scanning. Green resources
    will be created (or destroyed and then created if an existing resource
    exists), yellow resources are being changed in-place, and red resources
    will be destroyed. Cyan entries are data sources to be read.
    Note: You didn't specify an "-out" parameter to save this plan, so when
    "apply" is called, Terraform can't guarantee this is what will execute.
    + vsphere_virtual_machine.test
        datacenter:                             "mysite"
        detach_unknown_disks_on_delete:         "false"
        disk.#:                                 "1"
        disk.1370406802.bootable:               ""
        disk.1370406802.controller_type:        "scsi"
        disk.1370406802.datastore:              ""
        disk.1370406802.iops:                   ""
        disk.1370406802.keep_on_remove:         ""
        disk.1370406802.key:                    ""
        disk.1370406802.name:                   ""
        disk.1370406802.size:                   ""
        disk.1370406802.template:               "mytemplate"
        disk.1370406802.type:                   "eager_zeroed"
        disk.1370406802.uuid:                   ""
        disk.1370406802.vmdk:                   ""
        domain:                                 “test.example.com”
        enable_disk_uuid:                       "false"
        linked_clone:                           "false"
        memory:                                 "1024"
        memory_reservation:                     "0"
        name:                                   "test"
        network_interface.#:                    "1"
        network_interface.0.ip_address:         ""
        network_interface.0.ipv4_address:       “192.168.1.2"
        network_interface.0.ipv4_gateway:       "192.168.1.1"
        network_interface.0.ipv4_prefix_length: "24"
        network_interface.0.ipv6_address:       ""
        network_interface.0.ipv6_gateway:       ""
        network_interface.0.ipv6_prefix_length: ""
        network_interface.0.label:              "test"
        network_interface.0.mac_address:        ""
        network_interface.0.subnet_mask:        ""
        resource_pool:                          "Production Cluster #1/Resources/myresourcepool"
        skip_customization:                     "false"
        time_zone:                              "Etc/UTC"
        uuid:                                   ""
        vcpu:                                   "1"
    Plan: 1 to add, 0 to change, 0 to destroy. 

    Was auch toll ist, Sie können die IP-Adresse und den Domain-Namen festlegen, dh die vollständige Anpassung des Computers über die Vorlage. Ich versuche zu rennen ...

    Error applying plan:
    1 error(s) occurred:
    * vsphere_virtual_machine.test: Datastore 'mysite/mydatastore not found.
    Terraform does not automatically rollback in the face of errors.
    Instead, your Terraform state file has been partially updated with
    any resources that successfully completed. Please address the error
    above and apply again to incrementally change your infrastructure.
    

    Hmm, Datenspeicher nicht gefunden. Wie gesagt, wir haben einen Cluster. Daher versuche ich, dies auf schmutzige Weise zu tun, indem ich einen der Clusterknoten angabe.

    
    Error applying plan:
    1 error(s) occurred:
    * vsphere_virtual_machine.test: Datastore 'mysite/mydatastore/mydatastore-vol01' not found.
    Terraform does not automatically rollback in the face of errors.
    Instead, your Terraform state file has been partially updated with
    any resources that successfully completed. Please address the error
    above and apply again to incrementally change your infrastructure.
    

    Nun ... schon wieder ein Misserfolg. Später stellte sich heraus, dass Terraform nicht mit Datenspeicher-Clustern arbeiten kann. Die entsprechende Ausgabe wurde auf GitHub von meinem Kollegen erstellt, leider auch in diesem Bereich kein Erfolg.

    Powercli


    Nachdem ich bei der Suche nach Arbeitsgeräten von Drittanbietern gescheitert war, entschied ich mich für eine Anbieterlösung.

    Der Anbieter bietet zwei Lösungen an: PowerCLI (Add-On für Powershell) und vmware-cli (Befehlszeilenschnittstelle für * nix).

    Es war nicht möglich, vmware-cli unter CentOS 7 und OS X zum Laufen zu bringen (ein Betroffener schrieb sogar einen Blog darüber), und ich beschloss, sofort ein funktionsfähiges Tool zu verwenden.

    Ein aufmerksamer Leser mag sich fragen, warum ich so viel Zeit mit Ansible und Terraform verbracht habe, während PowerCLI schon lange verwendet wurde. Die Gründe sind einfach: Ich kenne Powershell nicht in der richtigen Stufe, um es mit einem Kinderspiel zu verwenden, und es zwingt mich, eine Windows-Maschine zu verwenden, die sich um eine saubere Versorgung kümmert. Ich habe jedoch keine anderen Optionen.

    Durch ein kurzes Studium der Dokumentation konnte ich ein einfaches Skript schreiben.

    Param(
        [string]$Name,
        [string]$ResourcePool,
        [string]$Location,
        [int]$NumCPU,
        [int]$MemoryGB,
        [int]$DiskGB)
    $ErrorActionPreference = "Stop"
    Try
    {
    $credential = Get-Credential
    Add-PSSnapin VMware.VimAutomation.Core
    [string] $username = $credential.GetNetworkCredential().UserName
    $username = 'example\' + $username
    Connect-VIServer -Server virtualcenter.example.com -User $username -Password $credential.GetNetworkCredential().Password -Force
     $params = @{
        name = $Name
        ResourcePool =  $ResourcePool
        Location =  $Location 
        NumCPU = $NumCPU
        MemoryGB = $MemoryGB
        DiskGB = $DiskGB
     }
     new-vm @params
     }
     Catch [VMware.VimAutomation.ViCore.Types.V1.ErrorHandling.DuplicateName] {"VM exists"}
    

    Dieses Skript funktioniert und erledigt alles Notwendige. Das Skript wird wie folgt ausgeführt:

     .\createvm.ps1 -Name mytestvm -ResourcePool myresourcepool -Location myteam -NumCPI 1 - MemoryGB 1 -DisckGB 10 

    Das Skript fordert mich auf, einen Benutzernamen und ein Kennwort einzugeben, die Variablen erneut abzuspielen und einen Computer mit cmdlet'a new-vm zu erstellen. Der Leser mag sich fragen, warum diese Zeile vorhanden ist:

    [string] $username = $credential.GetNetworkCredential().UserName
    $username = 'example\' + $username

    Lassen Sie mich von erfahrenen Powershell-Leuten korrigieren, wenn ich falsch liege. Get-Credential erstellt ein Objekt bestehend aus Login, Passwort und Domain (falls vorhanden). Das Passwort befindet sich im SecureString-Status. Leider kann PowerCLI weder mit dem Get-Credential-Objekt noch mit SecureString arbeiten. Daher müssen Sie solche Tricks ausführen, um den Benutzernamen und das Kennwort an eine einfache Zeichenfolgenvariable zu übergeben.

    Schlussfolgerungen


    Sehr geehrter Leser, wenn Sie eines Tages die Aufgabe haben, die Erstellung virtueller Maschinen in VMware zu automatisieren, sollten Sie Folgendes berücksichtigen:

    • Verwenden Sie Ressourcenpools?
    • Verwenden Sie Datenspeicher-Cluster?

    Wenn Sie ein ESX-System mit einem einzelnen Knoten haben, empfehle ich die Verwendung von Ansible. Es hat eine niedrige Eintrittsschwelle und ist recht leicht und flink.

    Wenn Sie dieselbe komplexe Infrastruktur haben wie wir, ist es besser, das Rad nicht neu zu erfinden, sondern PowerCLI zu entwickeln.

    Im nächsten Teil werde ich erläutern, wie wir unser Skript intelligenter gemacht und ihm gezeigt haben, wie Anpassungen, die Anzahl der Kerne und andere Ressourcen sowie die Namenskonventionen überprüft werden.

    Jetzt auch beliebt: