Prepare a CentOS-based virtual machine for Azure
Applies to: ✔️ Linux VMs ✔️ Flexible scale sets
Learn to create and upload an Azure virtual hard disk (VHD) that contains a CentOS-based Linux operating system.
Prerequisites
This article assumes that you've already installed a CentOS (or similar derivative) Linux operating system to a virtual hard disk. Multiple tools exist to create .vhd files, for example a virtualization solution such as Hyper-V. For instructions, see Install the Hyper-V Role and Configure a Virtual Machine.
CentOS installation notes
- For more tips on preparing Linux for Azure, see General Linux Installation Notes.
- The VHDX format isn't supported in Azure, only fixed VHD. You can convert the disk to VHD format using Hyper-V Manager or the convert-vhd cmdlet. If you're using VirtualBox, this means selecting Fixed size as opposed to the default dynamically allocated when creating the disk.
- The vfat kernel module must be enabled in the kernel
- When installing the Linux system, we recommend that you use standard partitions rather than LVM (often the default for many installations). This avoids LVM name conflicts with cloned VMs, particularly if an OS disk ever needs to be attached to another identical VM for troubleshooting. LVM or RAID may be used on data disks.
- Kernel support for mounting UDF file systems is necessary. At first boot on Azure the provisioning configuration is passed to the Linux VM by using UDF-formatted media that is attached to the guest. The Azure Linux agent or cloud-init must mount the UDF file system to read its configuration and provision the VM.
- Linux kernel versions below 2.6.37 don't support NUMA on Hyper-V with larger VM sizes. This issue primarily impacts older distributions using the upstream Centos 2.6.32 kernel and was fixed in Centos 6.6 (kernel-2.6.32-504). Systems running custom kernels older than 2.6.37 or RHEL-based kernels older than 2.6.32-504 must set the boot parameter
numa=off
on the kernel command-line in grub.conf. For more information, see Red Hat KB 436883. - Don't configure a swap partition on the OS disk.
- All VHDs on Azure must have a virtual size aligned to 1 MB. When converting from a raw disk to VHD, you must ensure that the raw disk size is a multiple of 1 MB before conversion. See Linux Installation Notes for more information.
Note
Cloud-init >= 21.2 removes the udf requirement. However, without the udf module enabled, the cdrom won't mount during provisioning, preventing custom data from being applied. A workaround for this is to apply custom data using user data. However, unlike custom data, user data isn't encrypted. https://cloudinit.readthedocs.io/en/latest/topics/format.html
CentOS 6.x
Important
Please note that CentOS 6 has reached its End Of Life (EOL) and is no longer supported by the CentOS community. This means that no further updates or security patches will be released for this version, leaving it vulnerable to potential security risks. We strongly recommend upgrading to a more recent version of CentOS to ensure the safety and stability of your system. Please consult with your IT department or system administrator for further assistance.
In Hyper-V Manager, select the virtual machine.
Click Connect to open a console window for the virtual machine.
In CentOS 6, NetworkManager can interfere with the Azure Linux agent. Uninstall this package by running the following command:
sudo rpm -e --nodeps NetworkManager
Create or edit the file
/etc/sysconfig/network
and add the following text:NETWORKING=yes HOSTNAME=localhost.localdomain
Create or edit the file
/etc/sysconfig/network-scripts/ifcfg-eth0
and add the following text:DEVICE=eth0 ONBOOT=yes BOOTPROTO=dhcp TYPE=Ethernet USERCTL=no PEERDNS=yes IPV6INIT=no
Modify udev rules to avoid generating static rules for the Ethernet interface(s). These rules can cause problems when cloning a virtual machine in Microsoft Azure or Hyper-V:
sudo ln -s /dev/null /etc/udev/rules.d/75-persistent-net-generator.rules sudo rm -f /etc/udev/rules.d/70-persistent-net.rules
Ensure the network service starts at boot time by running the following command:
sudo chkconfig network on
If you would like to use the OpenLogic mirrors that are hosted within the Azure datacenters, then replace the
/etc/yum.repos.d/CentOS-Base.repo
file with the following repositories. This will also add the [openlogic] repository that includes extra packages such as the Azure Linux agent:[openlogic] name=CentOS-$releasever - openlogic packages for $basearch baseurl=http://olcentgbl.trafficmanager.net/openlogic/$releasever/openlogic/$basearch/ enabled=1 gpgcheck=0 [base] name=CentOS-$releasever - Base #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra baseurl=http://olcentgbl.trafficmanager.net/centos/$releasever/os/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6 #released updates [updates] name=CentOS-$releasever - Updates #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra baseurl=http://olcentgbl.trafficmanager.net/centos/$releasever/updates/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6 #additional packages that may be useful [extras] name=CentOS-$releasever - Extras #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra baseurl=http://olcentgbl.trafficmanager.net/centos/$releasever/extras/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6 #additional packages that extend functionality of existing packages [centosplus] name=CentOS-$releasever - Plus #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus&infra=$infra baseurl=http://olcentgbl.trafficmanager.net/centos/$releasever/centosplus/$basearch/ gpgcheck=1 enabled=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6 #contrib - packages by Centos Users [contrib] name=CentOS-$releasever - Contrib #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=contrib&infra=$infra baseurl=http://olcentgbl.trafficmanager.net/centos/$releasever/contrib/$basearch/ gpgcheck=1 enabled=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
Note
The rest of this guide will assume you're using at least the
[openlogic]
repo, which will be used to install the Azure Linux agent below.Add the following line to /etc/yum.conf:
http_caching=packages
Run the following command to clear the current yum metadata and update the system with the latest packages:
sudo yum clean all
Unless you're creating an image for an older version of CentOS, we recommend to update all the packages to the latest:
sudo yum -y update
A reboot may be required after running this command.
(Optional) Install the drivers for the Linux Integration Services (LIS).
Important
The step is required for CentOS 6.3 and earlier, and optional for later releases.
sudo rpm -e hypervkvpd ## (may return error if not installed, that's OK) sudo yum install microsoft-hyper-v
Alternatively, you can follow the manual installation instructions on the LIS download page to install the RPM onto your VM.
Install the Azure Linux Agent and dependencies. Start and enable waagent service:
sudo yum install python-pyasn1 WALinuxAgent sudo service waagent start sudo chkconfig waagent on
The WALinuxAgent package removes the NetworkManager and NetworkManager-gnome packages if they were not already removed as described in step 3.
Modify the kernel boot line in your grub configuration to include additional kernel parameters for Azure. To do this, open
/boot/grub/menu.lst
in a text editor and ensure that the default kernel includes the following parameters:console=ttyS0 earlyprintk=ttyS0 rootdelay=300
This will also ensure all console messages are sent to the first serial port, which can assist Azure support with debugging issues.
In addition to the above, we recommend to remove the following parameters:
rhgb quiet crashkernel=auto
Graphical and
quiet boot
aren't useful in a cloud environment where we want all the logs to be sent to the serial port. Thecrashkernel
option may be left configured if desired, but note that this parameter will reduce the amount of available memory in the VM by 128 MB or more, which may be problematic on the smaller VM sizes.Important
CentOS 6.5 and earlier must also set the kernel parameter
numa=off
. See Red Hat KB 436883.Ensure that the SSH server is installed and configured to start at boot time. This is usually the default.
Don't create swap space on the OS disk.
The Azure Linux Agent can automatically configure swap space using the local resource disk that is attached to the VM after provisioning on Azure. The local resource disk is a temporary disk and might be emptied when the VM is deprovisioned. After installing the Azure Linux Agent (see previous step), modify the following parameters in
/etc/waagent.conf
appropriately:ResourceDisk.Format=y ResourceDisk.Filesystem=ext4 ResourceDisk.MountPoint=/mnt/resource ResourceDisk.EnableSwap=y ResourceDisk.SwapSizeMB=2048 ## NOTE: set this to whatever you need it to be.
Run the following commands to deprovision the virtual machine and prepare it for provisioning on Azure:
sudo waagent -force -deprovision+user sudo export HISTSIZE=0
Note
If you are migrating a specific virtual machine and do not wish to create a generalized image, skip the deprovision step.
- Click Action -> Shut Down in Hyper-V Manager. Your Linux VHD is now ready to be uploaded to Azure.
CentOS 7.0+
Changes in CentOS 7 (and similar derivatives)
Preparing a CentOS 7 virtual machine for Azure is similar to CentOS 6, however there are several significant differences worth noting:
The NetworkManager package no longer conflicts with the Azure Linux agent. This package is installed by default, and we recommend that it's not removed.
GRUB2 is now used as the default bootloader, so the procedure for editing kernel parameters has changed (see below).
XFS is now the default file system. The ext4 file system can still be used if desired.
Since CentOS 8 Stream and newer no longer include
network.service
by default, you need to install it manually:sudo yum install network-scripts sudo systemctl enable network.service
Configuration Steps
In Hyper-V Manager, select the virtual machine.
Click Connect to open a console window for the virtual machine.
Create or edit the file
/etc/sysconfig/network
and add the following text:NETWORKING=yes HOSTNAME=localhost.localdomain
Create or edit the file
/etc/sysconfig/network-scripts/ifcfg-eth0
and add the following text:DEVICE=eth0 ONBOOT=yes BOOTPROTO=dhcp TYPE=Ethernet USERCTL=no PEERDNS=yes IPV6INIT=no NM_CONTROLLED=no
Modify udev rules to avoid generating static rules for the Ethernet interface(s). These rules can cause problems when cloning a virtual machine in Microsoft Azure or Hyper-V:
sudo ln -s /dev/null /etc/udev/rules.d/75-persistent-net-generator.rules
If you would like to use the OpenLogic mirrors that are hosted within the Azure datacenters, then replace the
/etc/yum.repos.d/CentOS-Base.repo
file with the following repositories. This will also add the [openlogic] repository that includes packages for the Azure Linux agent:[openlogic] name=CentOS-$releasever - openlogic packages for $basearch baseurl=http://olcentgbl.trafficmanager.net/openlogic/$releasever/openlogic/$basearch/ enabled=1 gpgcheck=0 [base] name=CentOS-$releasever - Base #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra baseurl=http://olcentgbl.trafficmanager.net/centos/$releasever/os/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 #released updates [updates] name=CentOS-$releasever - Updates #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra baseurl=http://olcentgbl.trafficmanager.net/centos/$releasever/updates/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 #additional packages that may be useful [extras] name=CentOS-$releasever - Extras #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra baseurl=http://olcentgbl.trafficmanager.net/centos/$releasever/extras/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 #additional packages that extend functionality of existing packages [centosplus] name=CentOS-$releasever - Plus #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus&infra=$infra baseurl=http://olcentgbl.trafficmanager.net/centos/$releasever/centosplus/$basearch/ gpgcheck=1 enabled=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Note
The rest of this guide will assume you're using at least the
[openlogic]
repo, which will be used to install the Azure Linux agent below.Run the following command to clear the current yum metadata and install any updates:
sudo yum clean all
Unless you're creating an image for an older version of CentOS, we recommend to update all the packages to the latest:
sudo yum -y update
A reboot may be required after running this command.
Modify the kernel boot line in your grub configuration to include additional kernel parameters for Azure. To do this, open
/etc/default/grub
in a text editor and edit theGRUB_CMDLINE_LINUX
parameter, for example:GRUB_CMDLINE_LINUX="rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0"
This will also ensure all console messages are sent to the first serial port, which can assist Azure support with debugging issues. It also turns off the new CentOS 7 naming conventions for NICs. In addition to the above, we recommend to remove the following parameters:
rhgb quiet crashkernel=auto
Graphical and quiet boot isn't useful in a cloud environment where we want all the logs to be sent to the serial port. The
crashkernel
option may be left configured if desired, but note that this parameter will reduce the amount of available memory in the VM by 128 MB or more, which may be problematic on the smaller VM sizes.Once you're done editing
/etc/default/grub
per above, run the following command to rebuild the grub configuration:sudo grub2-mkconfig -o /boot/grub2/grub.cfg
Note
If uploading an UEFI enabled VM, the command to update grub is grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
. Also, the vfat kernel module must be enabled in the kernel otherwise provisioning will fail.
Make sure the 'udf' module is enabled. Removing/disabling them will cause a provisioning/boot failure. (_Cloud-init >= 21.2 removes the udf requirement. Read top of document for more detail.)
If building the image from VMware, VirtualBox or KVM: Ensure the Hyper-V drivers are included in the initramfs:
Edit
/etc/dracut.conf
, add content:add_drivers+=" hv_vmbus hv_netvsc hv_storvsc "
Rebuild the initramfs:
sudo dracut -f -v
Install the Azure Linux Agent and dependencies for Azure VM Extensions:
sudo yum install python-pyasn1 WALinuxAgent sudo systemctl enable waagent
Install cloud-init to handle the provisioning
sudo yum install -y cloud-init cloud-utils-growpart gdisk hyperv-daemons
- Configure waagent for cloud-init
sudo sed -i 's/Provisioning.Agent=auto/Provisioning.Agent=auto/g' /etc/waagent.conf sudo sed -i 's/ResourceDisk.Format=y/ResourceDisk.Format=n/g' /etc/waagent.conf sudo sed -i 's/ResourceDisk.EnableSwap=y/ResourceDisk.EnableSwap=n/g' /etc/waagent.conf
sudo echo "Adding mounts and disk_setup to init stage" sudo sed -i '/ - mounts/d' /etc/cloud/cloud.cfg sudo sed -i '/ - disk_setup/d' /etc/cloud/cloud.cfg sudo sed -i '/cloud_init_modules/a\\ - mounts' /etc/cloud/cloud.cfg sudo sed -i '/cloud_init_modules/a\\ - disk_setup' /etc/cloud/cloud.cfg
sudo echo "Allow only Azure datasource, disable fetching network setting via IMDS" sudo cat > /etc/cloud/cloud.cfg.d/91-azure_datasource.cfg <<EOF datasource_list: [ Azure ] datasource: Azure: apply_network_config: False EOF if [[ -f /mnt/swapfile ]]; then echo Removing swapfile - RHEL uses a swapfile by default swapoff /mnt/swapfile rm /mnt/swapfile -f fi echo "Add console log file" cat >> /etc/cloud/cloud.cfg.d/05_logging.cfg <<EOF # This tells cloud-init to redirect its stdout and stderr to # 'tee -a /var/log/cloud-init-output.log' so the user can see output # there without needing to look on the console. output: {all: '| tee -a /var/log/cloud-init-output.log'} EOF
Swap configuration
Don't create swap space on the operating system disk.
Previously, the Azure Linux Agent was used to automatically configure swap space by using the local resource disk that is attached to the virtual machine after the virtual machine is provisioned on Azure. However this is now handled by cloud-init, you must not use the Linux Agent to format the resource disk create the swap file, modify the following parameters in
/etc/waagent.conf
appropriately:sudo sed -i 's/ResourceDisk.Format=y/ResourceDisk.Format=n/g' /etc/waagent.conf sudo sed -i 's/ResourceDisk.EnableSwap=y/ResourceDisk.EnableSwap=n/g' /etc/waagent.conf
If you want mount, format, and create swap, you can either:
Pass this in as a cloud-init config every time you create a VM
Use a cloud-init directive baked into the image that will do this every time the VM is created:
sudo echo 'DefaultEnvironment="CLOUD_CFG=/etc/cloud/cloud.cfg.d/00-azure-swap.cfg"' >> /etc/systemd/system.conf sudo cat > /etc/cloud/cloud.cfg.d/00-azure-swap.cfg << EOF #cloud-config # Generated by Azure cloud image build disk_setup: ephemeral0: table_type: mbr layout: [66, [33, 82]] overwrite: True fs_setup: - device: ephemeral0.1 filesystem: ext4 - device: ephemeral0.2 filesystem: swap mounts: - ["ephemeral0.1", "/mnt"] - ["ephemeral0.2", "none", "swap", "sw,nofail,x-systemd.requires=cloud-init.service,x-systemd.device-timeout=2", "0", "0"] EOF
Run the following commands to deprovision the virtual machine and prepare it for provisioning on Azure:
Note
If you are migrating a specific virtual machine and don't wish to create a generalized image, skip the deprovision step.
sudo rm -f /var/log/waagent.log sudo cloud-init clean sudo waagent -force -deprovision+user sudo rm -f ~/.bash_history sudo export HISTSIZE=0
Click Action -> Shut Down in Hyper-V Manager. Your Linux VHD is now ready to be uploaded to Azure.
Next steps
You're now ready to use your CentOS Linux virtual hard disk to create new virtual machines in Azure. If this is the first time that you're uploading the .vhd file to Azure, see Create a Linux VM from a custom disk.
Feedback
Submit and view feedback for