Setting up a base template - Create Ubuntu 18.04 LTS Template
On a separate system install PowerShell, PowerCLI, govc and download the base OS to use for your Kubernetes installation. It is recommended to use Ubuntu 18.04LTS as the base OS for Kubernetes on VMware. DHCP should be configured on the subnet that the Kubernetes nodes are being deployed to.
Creating the template follows this guide
Configure PowerCLI
PowerCLI will need to be configured to bypass certificate validation and the system proxy.
# Install VMware PowerShell Module
PS /> Install-Module -name VMware.PowerCLI -Confirm:$false
# Disable VMware Customer Experience Improvement Program participation
PS /> Set-PowerCLIConfiguration -ProxyPolicy NoProxy -Scope User -ParticipateInCEIP $false -Confirm:$false
Scope ProxyPolicy DefaultVIServerMode InvalidCertificateAction DisplayDeprecationWarnings WebOperationTimeout
Seconds
----- ----------- ------------------- ------------------------ -------------------------- -------------------
Session NoProxy Multiple Unset True 300
User
AllUsers
# Check Version
PS /> Get-Module -Name VMware.VimAutomation.Sdk | select Name, Version
Name Version
---- -------
VMware.VimAutomation.Sdk 11.5.0.14898111
# Ignore certificate errors
PS /> Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
Scope ProxyPolicy DefaultVIServerMode InvalidCertificateAction DisplayDeprecationWarnings WebOperationTimeout
Seconds
----- ----------- ------------------- ------------------------ -------------------------- -------------------
Session NoProxy Multiple Ignore True 300
User Ignore
AllUsers
Setup govc
Configure some environment variables for govc, these values determine where the Ubuntu image and Kubernetes nodes are placed.
$ export GOVC_INSECURE=1 # Don't verify SSL certs on vCenter
$ export GOVC_URL=10.10.10.10 # vCenter IP/FQDN
$ export GOVC_USERNAME=administrator # vCenter username
$ export GOVC_PASSWORD=password # vCenter password
$ export GOVC_DATASTORE=Datastore # Default datastore to deploy to
$ export GOVC_NETWORK="VM Network" # Default network to deploy to
$ export GOVC_RESOURCE_POOL='*/Resources' # Default resource pool to deploy to
Check that govc has access to your vcenter
$ govc about
Name: VMware vCenter Server
Vendor: VMware, Inc.
Version: 6.7.0
Build: 10244857
OS type: linux-x64
API type: VirtualCenter
API version: 6.7.1
Product ID: vpx
UUID: 1bd33d4e-555f-4d8b-9b77-8d155f612155
Create OVF Spec from Ubuntu OVA
$ govc import.spec ~/Downloads/ubuntu-18.04-server-cloudimg-amd64.ova | python -m json.tool > ubuntu.json
Create a new SSH key and store it ~/.ssh
Customize the OVF Spec by updating "Value" for these key fields hostname, public-keys, password, network and name
{
"DiskProvisioning": "thin",
"IPAllocationPolicy": "dhcpPolicy",
"IPProtocol": "IPv4",
"PropertyMapping": [
{
"Key": "instance-id",
"Value": "id-ovf"
},
{
"Key": "hostname",
"Value": "Ubuntu1804Template"
},
{
"Key": "seedfrom",
"Value": ""
},
{
"Key": "public-keys",
"Value": "ssh-rsa [YOUR PUBLIC KEY] [username]"
},
{
"Key": "user-data",
"Value": ""
},
{
"Key": "password",
"Value": "password"
}
],
"NetworkMapping": [
{
"Name": "VM Network",
"Network": "VM Network"
}
],
"MarkAsTemplate": false,
"PowerOn": false,
"InjectOvfEnv": false,
"WaitForIP": false,
"Name": "Ubuntu1804Template"
}
If using Windows you'll need to convert the ubuntu.json to unix format using dos2unix
Deploy the OVA
Import the OVA
$ govc import.ova -options=ubuntu.json ~/Downloads/ubuntu-18.04-server-cloudimg-amd64.ova
Set the VM's resources
$ govc vm.change -vm Ubuntu1804Template -c 4 -m 4096 -e="disk.enableUUID=1"
$ govc vm.disk.change -vm Ubuntu1804Template -disk.label "Hard disk 1" -size 60G
Power on the VM and wait until IP is assigned
$ govc vm.power -on=true Ubuntu1804Template
$ govc vm.info Ubuntu1804Template
Name: Ubuntu1804Template
Path: /vSAN-DC/vm/Discovered virtual machine/Ubuntu1804Template
UUID: 42392966-8d21-ceda-5f23-28584c18703b
Guest name: Ubuntu Linux (64-bit)
Memory: 1024MB
CPU: 2 vCPU(s)
Power state: poweredOn
Boot time: 2019-01-25 18:28:21.978093 +0000 UTC
IP address: 10.198.17.85
Host: 10.198.17.31
Update the VM with open-vm-tools package
$ ssh ubuntu@10.198.17.85
$ sudo apt update
$ sudo apt install open-vm-tools -y
$ sudo apt upgrade -y
$ sudo apt autoremove -y
Remove grub.d from the VMs before you upgrade the hardware version.
$ sudo rm -rf /etc/default/grub.d
$ sudo update-grub
$ sudo shutdown now
Set the Hardware version of the VM to 15. This is required for VMware to recognize the VM as a Kubernetes node.
$ govc vm.upgrade -version=15 -vm '/datacenterName/vm/Ubuntu1804Template'
Verify that the VM's Hardware version was set
$ govc vm.option.info '/datacenterName/vm/Ubuntu1804Template' | grep HwVersion
HwVersion: 15
Install Docker
Power the VM back on and install the libraries needed to install docker
$ govc vm.power -on=true Ubuntu1804Template
$ govc vm.info Ubuntu1804Template
$ ssh ubuntu@10.198.17.85
$ sudo apt install ca-certificates software-properties-common apt-transport-https curl -y
Add Docker offical GPG Key
$ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Add Docker apt repository
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
$ sudo curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
Create the file /etc/apt/sources.list.d/kubernetes.list to point to the Kubernetes repo
# Contents of /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
Update apt with the new repositories just added
$ sudo apt update
Install DockerCE
# install the appropriate version of docker based on the k8s version, refer to the example given below for k8s 1.17
$ sudo apt install docker-ce=5:19.03.4~3-0~ubuntu-bionic -y
Setup Docker's Daemon file /etc/docker/daemon.json
# Contents of /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
Restart the Docker service using the new settings
$ sudo mkdir -p /etc/systemd/system/docker.service.d
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
$ sudo systemctl status docker
docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2019-09-06 12:37:27 UTC; 4min 15s ago
$ sudo docker info | egrep "Server Version|Cgroup Driver"
Server Version: 19.03.4-ce
Cgroup Driver: systemd
Install Kubernetes
# install the desired version of k8s, similar to the example below
$ sudo apt install -qy kubeadm=1.17.0-00 kubelet=1.17.0-00 kubectl=1.17.0-00
Hold Kubernetes packages at their installed version so they do not upgrade unexpectedly on an apt upgrade
$ sudo apt-mark hold kubelet kubeadm kubectl
Install Network for Pod nodes
This example uses Flannel for the kubernetes cluster network. Flannel needs to have IPv4 traffic bridged to iptables chains
$ sudo sysctl net.bridge.bridge-nf-call-iptables=1
Disable cloud-init on VM and use VMware Guest Customization specs instead
$ sudo cloud-init clean --logs
$ sudo touch /etc/cloud/cloud-init.disabled
$ sudo rm -rf /etc/netplan/50-cloud-init.yaml
$ sudo apt purge cloud-init -y
$ sudo apt autoremove -y
# Don't clear /tmp
$ sudo sed -i 's/D \/tmp 1777 root root -/#D \/tmp 1777 root root -/g' /usr/lib/tmpfiles.d/tmp.conf
# Remove cloud-init and rely on dbus for open-vm-tools
$ sudo sed -i 's/Before=cloud-init-local.service/After=dbus.service/g' /lib/systemd/system/open-vm-tools.service
# cleanup current ssh keys so templated VMs get fresh key
$ sudo rm -f /etc/ssh/ssh_host_*
Add check for ssh keys on reboot, create /etc/rc.local
# Contents of /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
test -f /etc/ssh/ssh_host_dsa_key || dpkg-reconfigure openssh-server
exit 0
Clean the VM before making it a template
# make the script executable
$ sudo chmod +x /etc/rc.local
# cleanup apt
$ sudo apt clean
# reset the machine-id (DHCP leases in 18.04 are generated based on this... not MAC...)
$ echo "" | sudo tee /etc/machine-id >/dev/null
# disable swap for K8s
$ sudo swapoff --all
$ sudo sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab
# cleanup shell history and shutdown for templating
$ history -c
$ history -w
$ sudo shutdown -h now
Turn the VM into a Template
$ govc vm.markastemplate Ubuntu1804Template
Define a Customization spec with DNS, Domain, and OSType defined
$ Connect-VIServer <vCenter IP> -User <vCenter Username> -Password <vCenter Password>
$ New-OSCustomizationSpec -Name CustomizationName -OSType Linux -DnsServer 1.1.1.1, 8.8.8.8 -DnsSuffix mydomain.net -Domain mydomain.net -NamingScheme vm
Name Description Type OSType LastUpdate Server
---- ----------- ---- ------ ---------- ------
CustomizationName Persistent Linux 27/01/2019 21:43:40 <vCenter IP>
Create Kubernetes master and worker nodes
$ govc vm.clone -vm Ubuntu1804Template -customization=CustomizationName k8s-master
$ govc vm.clone -vm Ubuntu1804Template -customization=CustomizationName k8s-worker1
$ govc vm.clone -vm Ubuntu1804Template -customization=CustomizationName k8s-worker2
$ govc vm.clone -vm Ubuntu1804Template -customization=CustomizationName k8s-worker3
Now that there are some Kubernetes nodes created it is time to setup a master node and the worker nodes.