For now, this is the last post in this series introducing VMware Photon OS on Azure. Testers often need an environment with newly spinned up Photon OS VMs and docker containers. On vSphere you deploy the ova template through the VMware Host Client. The study script in part2 spins up a Photon OS VM without external Azure connectivity, and part3 gives a Photon virtual hardware and command basics discovery perspective. In this part we will add external connectivity using Azure Powershell cmdlets. The middle part in this last post is about Azure images functionality, and we will run a first docker container.

Let's start with adding a public ip address to the virtual machine created in part2.

Add a public IP

On the Photon VM Properties overview, Azure Portal shows the settings of Virtual Machine, Networking, Size and Disk.

Photon1.pngTo add an external ip, first we must identify the network interface of the virtual machine.

In the following example, the network interface of the virtual machine is identified by name and by the private IP address parsing through all virtual machines' configuration by using get-aznetworkinterface. In a small environment this method is quite straight forward. In a restricted environment, add your NetworkSecurityGroup you are eligible to traverse as -ExpandResource parameter.

$vmName="photon"

$PrivateIPAddress="192.168.1.4"

$nic=get-aznetworkinterface | where-object {($_.VirtualMachine.id -eq (get-azvm -name $vmName).id) -and ($_.IpConfigurations.PrivateIpAddress -eq $PrivateIPAddress)}

The network interface is linked to a virtual network where the ip configuration is stored. The nic' ipconfiguration id is used to retrieve the virtual network and the subnet object. You need to identify the subnet name when you set on the same network interface the ip configuration for the public ip address.

$ipconfiguration = $nic.ipconfigurations | where-object { $_.Id -eq ((get-azvirtualnetwork).subnets.ipconfigurations.Id)[0]}

$vnet = get-azvirtualnetwork | where-object {$_.subnets.IpConfigurations.Id -eq $ipconfiguration.id}

$subnetobject=(get-azvirtualnetwork).subnets | where-object {$_.IpConfigurations.Id -eq $ipconfiguration.id}

$subnet = Get-AzVirtualNetworkSubnetConfig -Name $subnetobject.name -VirtualNetwork $vnet

 

In this example we haven't specified any Resource Group Name. We simply filter the Resource Group Name from the VM' network interface as well.

$resourcegroupname= $nic.ResourceGroupName

To allocate a new public IP Address use New-AzPublicIpAddress. In the following example I used a sku basic and a dynamic allocation method. That said, the public IP might change when the virtual machine is not running. For a static IP address allocation have a look to https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-network-interface-addresses.

The retrieved ipconfiguration name and subnet name are used to set the network interface ip configuration for the public ip address. set-aznetworkinterface activates the values set.

$pip = New-AzPublicIpAddress -Name 'MyPublicIpName' -ResourceGroupName $nic.ResourceGroupName -Location $nic.Location -Sku 'Basic' -AllocationMethod 'Dynamic'

$nic | Set-AzNetworkInterfaceIpConfig -Name $ipconfiguration.name -Subnet $subnet -PublicIpAddress $pip

$nic | Set-AzNetworkInterface

 

On the Photon VM Properties Networking overview, Azure Portal shows the new public ip address.

Photon2.png

 

The extended study script is attached right to this blog post.

 

If you check the ip configuration on the Photon virtual machine you won't find the public ip address.

Photon3.png

Azure network interfaces are not the same as VMware virtual machine nic adapters. Think of it as a dynamic outbound network interface right on a vswitch. This is important to know as even with a 1:1 Azure network interface, provided by Azure Accelerated Networking, this still is the same. For additional information see https://docs.microsoft.com/en-us/azure/virtual-network/create-vm-accelerated-networking-cli.

 

Due to the .vhd builtin Azure Linux VM Agent the Photon OS virtual machine interacts with Azure Fabric, so the Azure Portal shows up the operating system, hostname and agent status. On the networkctl output we can see that a hv_netsvc driver provides network functionality. That driver is a kernel modules' part of the Linux Integration Services (LIS) for Hyper-V and Azure. Not Azure-endorsed os use those LIS drivers for Linux kernel interaction with the Azure fabric. On the VMware Photon OS downloading page you find the latest Azure vhd bits of Photon OS 3.0 Revision 2. It includes the kernel modules needed for Azure.

 

Browse through Azure Marketplace

You may were already hovering in Azure portal through the Azure Marketplace offerings.

To determine offerings in Azure Powershell is simple. The VMware offerings with publisher names vmware-inc, bitnami or pivotal:

$publishers=get-azvmimagepublisher | where-object {($_.publishername -like "*vmware*") -or ($_.publishername -like "*bitnami*") -or ($_.publishername -like "*pivotal*")}

This oneliner shows up the listing with offerings.

$publishers | get-azvmimageoffer

 

Linux on Azure is supported, see https://azure.microsoft.com/de-de/overview/linux-on-azure. Actually there is no Azure-endorsed preconfigured Photon OS image on the Azure Marketplace. For non-endorsed Linux distributions there are some installation notes, see https://docs.microsoft.com/en-us/azure/virtual-machines/linux/create-upload-generic.

In the next part we will have a look to how to create a managed image of a VMware Photon OS release on an Azure subscription. I've written two helper scripts create-AzImage-PhotonOS.ps1 and create-AzVM_FromImage-PhotonOS.ps1 to make work a managed Photon OS image.

 

Create a Photon OS image on Azure

You may download the script from the attachment to this blog post.

How to use create-AzImage-PhotonOS.ps1:

create-AzImage-PhotonOS.ps1 -cred $(Get-credential -message 'Enter a username and password for Azure login.') -ResourceGroupName p1 -Location switzerlandnorth -StorageAccountName p1storage

Per default, the script asks for the Azure subscription credentials and location. The specified resource group name and the storage account name are created if necessary. It may take up to 25 minutes until the uploaded Azure image is created. Without further parameter the image created is from the photon-azure-3.0-9355405.vhd.

 

The script creates a temporary virtual machine of size Standard_E4s_v3 and installed from a sku 2019-datacenter-with-containers-smalldisk-g2. This allows to dynamically pre-store the specified VMware Photon OS bits, to upload them on a so called storage page blob account and to create the managed image with its virtual hardware HyperVGeneration V1 or V2 from the storage page blob account imported disk.

Here the coding description.

Line 1-107: Script comments and input parameters.

Location, Resource group name and Storage Account Name are mandatory parameters. Default settings can be changed for all other parameters storage account type, container name, hyper-v generation, the output image name and its internal disk name as well. SoftwareToProcess contains the download url to the VMware Photon OS Azure.vhd release.

Line 108-131: settings of the temporary virtual machine (do change wisely!)

Line 132-137: The variable adminrole value is used later to check if the script has been started with local administrative privileges. The variable Uri is needed to pass the Url decoded value of SoftwareToProcess to the temporary virtual machine.

Line 138-149: check and install Azure CLI locally. Administrative privileges are necessary!

Line 150-152: Check and install Azure Powershell locally. Administrative privileges are necessary!

Line 153-155: Azure login

Line 156-159: Save Azure context to a temporary file. The file copy will be processed for the Azure login inside the temporary virtual machine.

Line 160-164: Set the context to the subscription Id where Managed Disk exists and where VM will be created if necessary.

Line 165++: The scriptrun variable contains a scriptblock which will be transferred to and processed inside of the temporary virtual machine.

Line 166-185: Scriptblock content of check and install Azure CLI and of Azure Powershell.

Line 186-200: Scriptblock content of decode the Azure context file and import context.

Line 201-235: Scriptblock content of: The Photon Azure .vhd file is downloaded from the url, and extracted using tar and PS7zip. The script part checks if there is enough disk space on the disk specified in temporary vm settings.

Line 236-271: Scriptblock content of: Azure login and upload the extracted Photon azure.vhd file to the storage page blob account.

Line 272-278: create the resource group if it does not exist

Line 279-292: create the storage account if it does not exist. We must wait until the provisioning state is on succeeded.

Line 293-298: create storage container

Line 299-306: check if disk and VM was already created.

Line 307-317: create a network security group configuration to allow traffic for rdp.

Line 318-326: set virtual network, subnet for the temporary virtual machine.

Line 327-333: Populate temporary virtual machine' local admin credentials

Line 334-343: Create a public ip address, create a virtual network interface and associate it to the vm with the public ip and the network security group config

Line 344-362: create the virtual machine configuration

Line 363-367: create the virtual machine

Line 368-374: Check vm and remote install Az module on the temporary virtual machine

Line 375-395: Dynamically populate a script file with scriptblock content, encoded contextfile and additional variables sets.

Line 396-413: Process a block type storage upload of the scriptfile and inject-run the script on the temporary virtual machine. Afterwards, delete the locally stored script file.

Line 414-423: create a disk from the source uri where the processed Photon OS Azure .vhd has been stored.

Line 424-435: create the Azure image with the precreated disk as os disk.

Line 436-456: cleanup the temporary virtual machine and all temporary objects if the image has successfully been created.

 

On All resources on Azure portal you should see the image created. The naming helper ending _V1.vhd is related to the Hyper-v generation V1. You may restart the script to process V2 as well.

Photon4.png

With this, we can deploy virtual machines using the Azure image in an analogous way to vSphere vm templates.

For those who automate and standardize the creation of virtual machines might have a look to the Azure preview of Azure image builder and to Packer of Hashicorp. On vSphere you can use Packer as well.

 

 

 

Photon OS virtual machine provisioning using the Azure image

You may download the script from the attachment to this blog post.

How to use create-AzVM_FromImage-PhotonOS.ps1:

./create-AzVM_FromImage-PhotonOS.ps1 -cred $(Get-credential -message 'Enter a username and password for Azure login.') -Location switzerlandnorth -ResourceGroupNameImage p1 -ImageName photon-azure-3.0-9355405.vhd -ResourceGroupName photon20200919 -StorageAccountName photon20200919storage -VMName Photon3.0rev2

The script asks for Azure subscription credentials and location. The specified image name must reside in the resource group specified. The virtual machine is created on the storage account provided. Specify the virtual machine name using the parameter VMName and the target resource group. The virtual machine size default offering setting is "Standard_B1ms" (1vCPU and 2GB Ram).

The parameter values of VMLocalAdminUser and VMLocalAdminPwd are login settings of the Photon OS virtual machine created. The default username is "LocalAdminUser" with default password "Secure2020123!". The values are case sensitive.

The virtual machine default networking value is a dynamically allocated private ip address in the subnet 192.168.1.0/24 and a dynamically allocated public ip address on the same network interface.

Use the additional parameters to deploy virtual machines with your settings.

Here the coding description.

Line 1-130: Script comments, input parameters and variables. The variable adminrole value is used later to check if the script has been started with local administrative privileges.

Line 131-142: check and install Azure CLI locally. Administrative privileges are necessary!

Line 143-145: Check and install Azure Powershell locally. Administrative privileges are necessary!

Line 146-149: Azure login

Line 150-154: Set the context to the subscription Id where Managed Disk exists and where VM will be created.

Line 155-162: Verify if virtual machine already exists

Line 163-170: Verify if image exists

Line 171-177: create the resource group if it does not exist

Line 178-191: create the storage account if it does not exist. We must wait until the provisioning state is on succeeded.

Line 192-197: create the storage container

Line 198-212: create a network security group to allow traffic for http and ssh. These are suggestions. Modify the settings to your need of the containers later.

Line 213-221: set the virtual network and subnet

Line 222-231: Create a public ip address, create a virtual network interface and associate it to the vm with the public ip and the network security group configuration

Line 232-242: populate the configuration and create the virtual machine

Line 243-245: set the virtual machine' boot diagnostics

 

Each provisioning now takes a couple of minutes to spin up a next Photon OS virtual machine. To login on the virtual machine, you can use ssh and the Azure serial console as well.

In All resources on Azure portal you see the objects created.

Photon5.png

If your virtual machine has been created with a Hyper-V generation V2 Photon OS Azure image, it is reflected on the virtual machine settings object "VM generation".

Photon6.png

 

Configure SSH

Per default, ssh is not configured for password authentication, so you might get the following error.

Photon7.png

Use the Azure serial console, and login with the credentials specified on provisioning. The administrator user is not root but got enough administrative privileges.

To configure sshd password authentication we must change the PasswordAuthentication value in /etc/ssh/sshd_config. Try this:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.0

sudo systemctl stop sshd

sudo bash -c 'sed "s/PasswordAuthentication no/PasswordAuthentication yes/" /etc/ssh/sshd_config.0 > /etc/ssh/sshd_config'

sudo systemctl start sshd

 

Photon8.png

 

Now you can login using ssh.

Photon9.png

 

 

Run a container

We haven't configured any docker container yet. So let's create a first container with a webserver.

 

Execute the following commands.

# issue with iptables workaround

sudo ln -s /usr/bin/iptables-nft /usr/local/bin/iptables

sudo reboot

 

After the reboot, login again and execute the following commands.

sudo mkdir /sample

sudo touch /sample/Dockerfile

 

The docker container consists two components - Photon OS and the httpd webserver.

sudo vi /sample/Dockerfile

Copy the following content to the Dockerfile.

FROM photon: 3.0-20200918

RUN tdnf install -y httpd

CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

And save the Dockerfile (:wq).

The photon image tag in the FROM instruction may be "latest". You can find all valid tags on https://hub.docker.com/_/photon.

The webserver httpd runs on Photon and is started as foreground process.

 

Proceed with the following commands

sudo /sbin/iptables -A INPUT -p tcp --dport 80 -j ACCEPT

sudo docker build /sample -t samplewebserver:v1

sudo docker run -dit -p 80:80 samplewebserver:v1

 

The result on your web browser http://<ip> is

Photon10.png

 

After a while, go and check the average CPU credits consumed. It may be surprising how incredibly low the consumption is, keeping in mind that the Standard_B1ms virtual hardware consists of 1vcpu.

Photon11.png

 

Cleanup

You can list all running docker containers with sudo docker ps -a

To stop the docker containers simply run sudo bash -c 'docker stop $(docker ps -a -q)'

To list all docker container images run sudo docker image ls

To remove all docker images run sudo bash -c 'docker rmi -f $(docker images -a -q)'

 

After the docker cleanup it shouldn't be any images anymore. In some cases you might need to cleanup the docker system. Run

sudo docker system prune -f

sudo docker volume prune -f

 

 

To cleanup the complete installation, delete the Azure resource group. In the example above the resource group name is photon20200919.

 

Lessons learned

I gained some jumpstart experience with Azure powershell as well as on PhotonOS. The cloudnative operating system has many advantages. Actually there is no Azure endorsed PhotonOS, but with small knowledge in scripting you can provision the os on Azure as well.
Photon is a core component of the VMware Tanzu platform. Tanzu Basic and all higher editions include PhotonOS, especially as Kubernetes node os.