Bauen einer ESXi CentOs8 Box mit Packer

Mit diesem Post wollen wir 2 Schritte abarbeiten.

  1. Erstellen einer CentOs8 ESXi VM
  2. Export in eine OVA Vorlage

Das OpenSource Tool Packer kann dazu benutzt werden einen VMware ESXi Gast in einer unbeaufsichtigten Installation zu erzeugen. Das ganze heisst neumodern Infrastructure as code. Ist der Build erstmal gelungen hat man die Möglichkeit mit weiteren Export Schnittstellen wie in unserem Fall OVA und z. B. Vagrant Base Boxen zu arbeiten. Die Vielzahl der Export Schnittstellen ist sehr groß, so dass man vom AWS EC2 Image bis Azure / Docker etc… alles bauen kann was man heute für die Cloud benötigt.

Das ESXi System für Packer vorbereiten.
Wichtig hierbei ist, dass die Kommunikation vom Packer Host zum ESXi Server mit den Ports für ssh und vnc für unsere Workstation offen sein muss
Das folgende Skript welches auf dem ESXi Host ausgeführt werden muss bereitet den ESXi 6.7 Host für die Packer Kommunikation vor:

#!/bin/sh

# local configuration options

# Note: modify at your own risk! If you do/use anything in this

# script that is not part of a stable API (relying on files to be in

# specific places, specific tools, specific output, etc) there is a

# possibility you will end up with a broken system after patching or

# upgrading. Changes are not supported unless under direction of

# VMware support.

# configuration

firewallConfigFile="/etc/vmware/firewall/service.xml"

# enable guest ip hack

esxcli system settings advanced set -o /Net/GuestIPHack -i 1

# change permissions on firewall config file

chmod 644 "$firewallConfigFile"

chmod +t "$firewallConfigFile"

# remove config root end tag from firewall config file

sed -i -e 's|</ConfigRoot>||g' "$firewallConfigFile"

# add xml block for vnc ports to the end of the firewall config file

cat <<EOT >> "$firewallConfigFile"

<!– Ports opened for Packer VNC commands –>

<service id="1000">

<id>packer-vnc</id>

<rule id="0000">

<direction>inbound</direction>

<protocol>tcp</protocol>

<porttype>dst</porttype>

<port>

<begin>5900</begin>

<end>6000</end>

</port>

</rule>

<enabled>true</enabled>

<required>true</required>

</service>

</ConfigRoot>

EOT

# restore permissions on firewall config file

chmod 444 "$firewallConfigFile"

# restart firewall service

esxcli network firewall refresh

exit 0

Packer installieren
Wir haben packer in einem Centos7 OS installiert.

sudo yum install -y yum-utils

sudo yum-config-manager –add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo

sudo yum -y install packer

Collision mit einen binary namens packer

Deswegen umbenamung von packer in packer_io

mv /usr/bin/packer /usr/bin/packer_io

packer wird nun stattdessen mit packer_io aufgerufen

Ovftool installieren
Wir besorgen uns das Linux Paket VMware-ovftool-4.4.1-16812187-lin.x86_64.bundle von der VMware Seite.

scp VMware-ovftool-4.4.1-16812187-lin.x86_64.bundle /tmp

chmod +x VMware-ovftool-4.4.1-16812187-lin.x86_64.bundle

cd /tmp

./ VMware-ovftool-4.4.1-16812187-lin.x86_64.bundle

Dieses Packer json file erstellt eine VM, und exportiert diese als OVA Vorlage.
Datei: centos8.json

{

"builders" : [

{

"boot_command" : [

"<tab><bs><bs><bs><bs><bs>text ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks7.cfg<enter><wait>"

],

"boot_wait" : "{{ user `boot_wait` }}",

"disk_size" : "{{ user `disk_size` }}",

"guest_os_type" : "centos7-64",

"headless" : false,

"http_directory" : "http",

"iso_checksum" : "{{ user `iso_checksum` }}",

"iso_url" : "{{ user `iso_url` }}",

"network_name" : "Management",

"shutdown_command" : "echo 'packer'|sudo -S /sbin/halt -h -p",

"ssh_password" : "{{ user `ssh_password` }}",

"ssh_port" : 22,

"ssh_timeout" : "30m",

"ssh_username" : "{{ user `ssh_username` }}",

"type" : "vmware-iso",

"vm_name" : "{{ user `vm_name` }}",

"keep_registered" : true,

"remote_datastore" : "{{user `esxi_datastore`}}",

"remote_host" : "{{user `esxi_host`}}",

"remote_password" : "{{user `esxi_password`}}",

"remote_type" : "esx5",

"remote_username" : "{{user `esxi_username`}}",

"skip_export" : false,

"vnc_disable_password" : true,

"vmx_data" : {

"format" : "vmx",

"memsize" : "{{ user `memsize` }}",

"numvcpus" : "{{ user `numvcpus` }}",

"virtualHW.version" : "14"

}

}

],

"variables" : {

"boot_wait" : "5s",

"disk_size" : "40960",

"esxi_datastore" : "datastore3",

"esxi_host" : "192.168.17.15",

"esxi_password" : "MyPassword",

"esxi_username" : "root",

"iso_checksum" : "e33d7b1ea7a9e2f38c8f693215dd85254c3a4fe446f93f563279715b68d07987",

"iso_url" : "iso/CentOS-7-x86_64-DVD-2009.iso",

"memsize" : "1024",

"numvcpus" : "1",

"ssh_password" : "packer",

"ssh_username" : "packer",

"ip_addr" : "192.168.17.100",

"vm_name" : "CentOS-7-x86_64"

},

"provisioners" : [

{

"type" : "file",

"source" : "scripts/provision.sh",

"destination" : "/tmp/provision.sh"

},

{

"type" : "shell",

"inline" : [

"chmod u+x /tmp/provision.sh",

"/tmp/provision.sh {{user `ip_addr`}}"

]

}

]

}

Als erstes müssen wir einen ESXi-Host für unsere Builds festlegen. Der Grund, warum wir einen Host und kein vCenter benötigen, ist, dass Packer über SSH eine Verbindung zum Host herstellt und verschiedene vim-cmd-Befehle verwendet (vmware-iso Schnittstelle), um die Arbeit zu erledigen.

Hier müssen die folgenden Variablen im Skript oben angepasst werden:

Item

Value

"network_name"

"Management"

"esxi_datastore"

"datastore3"

"esxi_host"

"192.168.17.15"

"esxi_password"

"MyPassword"

"esxi_username"

"root"

 

 

 

Installation tree
Unser Installations-Verzeichnis sieht folgendermaßen aus:

templates/

├── centos8.json

├── http

│   └── ks.cfg

├── iso

│   ├── CentOS-8.3.2011-x86_64-boot.isoo

├── output-vmware-iso

│   ├── CentOS-8-x86_64-disk1.vmdk

│   ├── CentOS-8-x86_64-file1.nvram

│   ├── CentOS-8-x86_64.mf

│   └── CentOS-8-x86_64.ovf

├── packer_centos8_build.sh

├── scripts

│   ├── ipstatic.sh

Es enthält under anderem unsere kickstart Datei in einem Verzeichniss in dem packer von sich aus einen http Server aufmacht, um es der CentOS Installation anzubieten.
Der Konfig Eintrag ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg macht den http Server auf.

Die kickstart Datei
Datei: ks.cfg
 

# https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/performing_an_advanced_rhel_installation/kickstart-commands-and-options-reference_installing-rhel-as-an-experienced-user

# Set the authentication options for the system

auth –passalgo=sha512 –useshadow

# Install OS instead of upgrade

install

# License agreement

eula –agreed

# Use text mode install

text

# Disable Initial Setup on first boot

firstboot –disable

# Keyboard layout

keyboard –vckeymap=de –xlayouts='de'

# System language

lang de_DE.UTF-8

# Network information

network –bootproto=static –device=ens33 –gateway=192.168.17.1 –ip=192.168.17.100 –nameserver=192.168.17.1 –netmask=255.255.255.0 –noipv6 –activate

network –hostname=centos7.localdomain

# Root password

rootpw $1$+xLTvuVv$vAMwt4RuJqO3qp9nLQj1U0 –iscrypted

# SELinux configuration

selinux –enforcing

# Do not configure the X Window System

skipx

# System timezone

timezone Europe/Paris –isUtc

# Add a user named packer

user –groups=wheel –name=packer –password=$6$Jaa5U0EwAPMMp3.5$m29yTwr0q9ZJVJGMXvOnm9q2z13ldUFTjB1sxPHvaiW4upMSwQ50181wl7SjHjh.BTH7FGHx37wrX..SM0Bqq. –iscrypted –gecos="packer"

user –groups=wheel –name=vagrant –password=$6$dpIioZs4JBTf6l1n$6nySAWfwHTuo2TnszX6nAzrvGixLpgq/zvkLN5G4QULXIplUSR71BTHtFQNGkNEHYYLu6MZFBPfIhTY6fNRwp/ –iscrypted –gecos="vagrant"

# System bootloader configuration

bootloader –location=mbr –append="crashkernel=auto"

# Clear the Master Boot Record

zerombr

# Remove partitions

clearpart –all –initlabel

# Automatically create partitions using LVM

autopart –type=lvm

# Reboot after successful installation

reboot

%packages –ignoremissing

# dnf group info minimal-environment

@^minimal-environment

@development

@guest-agents

@headless-management

@legacy-unix

@rpm-development-tools

@scientific

@standard

@system-tools

kexec-tools

# Exclude unnecessary firmwares

-iwl*firmware

%end

%post –nochroot –logfile=/mnt/sysimage/root/ks-post.log

# Disable quiet boot and splash screen

sed –follow-symlinks -i "s/ rhgb quiet//" /mnt/sysimage/etc/default/grub

sed –follow-symlinks -i "s/ rhgb quiet//" /mnt/sysimage/boot/grub2/grubenv

# Passwordless sudo for the user 'packer'

echo "packer ALL=(ALL) NOPASSWD: ALL" >> /mnt/sysimage/etc/sudoers.d/packer

echo "vagrant ALL=(ALL) NOPASSWD: ALL" >> /mnt/sysimage/etc/sudoers.d/vagrant

%end

Die im ks.cfg File hinterlegten User mit Passwort sind somit:

packer | packer
root | packer
vagrant | vagrant

Das iscypted Password kann mit dem folgenden Aufruf erstellt werden:

python -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'

Start des packer build Vorgangs per shellscript Aufruf

Wir befüllen und starten das folgende Shellscript: packer_centos8_build.sh
 

#!/bin/bash

packer_io build -var "esxi_host=192.168.17.15" -var "esxi_datastore=datastore3" -var "esxi_username=root" -var "esxi_password=MyPassword" centos8.json

Der Build Vorgang läuft nun wie folgt ab:
 

[root@pentaho templates]# ./packer_centos8_build.sh

Warning: Warning when preparing build: "vmware-iso"

Your vmx data contains the following variable(s), which Packer normally sets

when it generates its own default vmx template. This may cause your build to

fail or behave unpredictably: numvcpus, memsize, virtualHW.version

vmware-iso: output will be in this color.

==> vmware-iso: Retrieving ISO

==> vmware-iso: Trying iso/CentOS-8.3.2011-x86_64-boot.iso

==> vmware-iso: Trying iso/CentOS-8.3.2011-x86_64-boot.iso?checksum=sha256%3A2b801bc5801816d0cf27fc74552cf058951c42c7b72b1fe313429b1070c3876c

==> vmware-iso: iso/CentOS-8.3.2011-x86_64-boot.iso?checksum=sha256%3A2b801bc5801816d0cf27fc74552cf058951c42c7b72b1fe313429b1070c3876c => /pentaho/apps/packer/templates/iso/CentOS-8.3.2011-x86_64-boot.iso

==> vmware-iso: Configuring output and export directories…

==> vmware-iso: Remote cache was verified skipping remote upload…

==> vmware-iso: Creating required virtual machine disks

==> vmware-iso: Building and writing VMX file

==> vmware-iso: Starting HTTP server on port 8787

==> vmware-iso: Registering remote VM…

==> vmware-iso: Starting virtual machine…

==> vmware-iso: Connecting to VNC…

==> vmware-iso: Waiting 5s for boot…

==> vmware-iso: Typing the boot command over VNC…

==> vmware-iso: Waiting for SSH to become available…

==> vmware-iso: Connected to SSH!

==> vmware-iso: Gracefully halting virtual machine…

vmware-iso: Waiting for VMware to clean up after itself…

==> vmware-iso: Deleting unnecessary VMware files…

vmware-iso: Deleting: /vmfs/volumes/datastore3/CentOS-8-x86_64-2004/vmware.log

==> vmware-iso: Cleaning VMX prior to finishing up…

vmware-iso: Detaching ISO from CD-ROM device ide0:0…

vmware-iso: Disabling VNC server…

==> vmware-iso: Exporting virtual machine…

vmware-iso: Executing: ovftool –noSSLVerify=true –skipManifestCheck -tt=ovf vi://root:%3Cpassword%3E@192.168.17.15/CentOS-8-x86_64-2004 output-vmware-iso/CentOS-8-x86_64-2004.ovf

==> vmware-iso: Keeping virtual machine registered with ESX host (keep_registered = true)

Build 'vmware-iso' finished after 14 minutes 39 seconds.

==> Wait completed after 14 minutes 39 seconds

==> Builds finished. The artifacts of successful builds are:

–> vmware-iso: VM files in directory: output-vmware-iso

–> vmware-iso: 'vmware' provider box: CentOS-8-x86_64-2004.box

Das Beispiel ließe sich noch mit den verschiedenen Provisioning Möglichkeiten ergänzen.
Vom Shellskript bis Ansible ist alles möglich was das Herz begeht, um zu einem Individuellen System zu kommen.

Hier nur ein Beispiel:
Die Variable ip_addr wird über die Datei centos7.json passend befüllt.

"provisioners" : [

{

"type" : "file",

"source" : "scripts/provision.sh",

"destination" : "/tmp/provision.sh"

},

{

"type" : "shell",

"inline" : [

"chmod u+x /tmp/provision.sh",

"/tmp/provision.sh {{user `ip_addr`}}"

]

}

Das passende Skript dazu:

#!/bin/bash

#– —————————————————————————–

#– Script : provision.sh

#– Task : we are setting the ip address from a packer variable

#– Do : ./provision.sh 192.168.17.101 /24 192.168.17.1

#– Author : Stefan M. Dohn, 18.05.2021

#– 18.05.2021 SDohn Creation from scrap

#– Last updates:

#– —————————————————————————–

#set -x

# declare variables

# Static settings

ip_addr="$1" #we are get our ip address via $1 argument#

ip_cidr="$2" #we are get our ip netmask via $2 argument#

ip_gw="$3" #we are get our gateway via $3 argument#

mgmt_ip='192.168.17.101'

mgmt_cidr='/24'

mgmt_gw='192.168.17.1'

[ -z $ip_addr ] && echo "no ip given, we exit here…" && exit 0

[ -z $ip_cidr ] && ip_cidr=$mgmt_cidr

[ -z $ip_gw ] && ip_gw=$mgmt_gw

# Inline provisioning script

INTERFACE=$(nmcli -t -f DEVICE device | grep e | head -n 1 |xargs)

VVAL=$(nmcli con show | grep $INTERFACE | awk -F " " '{ print $1}')

echo "Change IP for interfacename $VVAL"

sudo /usr/bin/nmcli con mod "$VVAL" ipv4.addresses ${ip_addr}${ip_cidr}

sudo /usr/bin/nmcli con mod "$VVAL" ipv4.gateway ${ip_gw}

sudo /usr/bin/nmcli con mod "$VVAL" ipv4.method manual

sudo /usr/bin/nmcli con mod "$VVAL" connection.autoconnect on

exit 0

Dieser Beitrag wurde unter LINUX veröffentlicht. Setze ein Lesezeichen auf den Permalink.