赞
踩
VM映像做为创建VM的必要条件,各类云环境映像市场均有提供最基础的映像。创建VM后,通常还需要根据组织或用户的需求,安装一些软件、修改配置后才能满足使用需求。这类需求通常可以手动部署或者借助一些配置管理工具,如ansible、puppet、saltstack等来实现,也可以考虑构建自定义的映像,集成软件部署和配置。
通常自定义映像比较繁琐,需要经历如下几个步骤,以Azure云为例:
1)创建构建映像使用的VM
2)部署软件/修改配置
3)通用化
4)关机
5)捕获映像
6)删除构建映像使用的VM
使用packer可以自动完成上述这些步骤
Packer是HashiCorp推出的一款自动构建VM/Docker映像的工具,支持各大主流云平台,可以结合puppet、ansible等配置管理工具高效定制映像。
packer官方文档:https://developer.hashicorp.com/packer/docs
本文分享使用packer构建AVD映像的案例,AVD(Azure Virtual Desktop)是Azure推出的虚拟桌面服务,通过集成一些常用的客户端工具,为用户提供方便快捷的资源访问入口。基于Azure VMSS(Virtual Machine Scale Sets)提供会话主机,VMSS使用的映像需要集成各类客户端工具。本场景中我们使用packer+ansible来实现AVD映像的自动构建。有关AVD的介绍,请参考:https://docs.azure.cn/zh-cn/virtual-desktop/overview
操作系统:CentOS 7
VMSIZE:Standard_D2s_v3
- [localhost]# yum install epel-release -y
- [localhost]# yum install ansible -y
- [localhost]# wget -c 'https://releases.hashicorp.com/packer/1.8.1/packer_1.8.1_linux_amd64.zip'
- [localhost]# unzip packer_1.8.1_linux_amd64.zip -d /usr/bin/
- [localhost]# pip install pywinrm
VM托管标识(Managed Identity)是用来在Azure上做身份认证和授权的,认证可选的方式还有Service Principal(SP)方式,需要在packer的模版文件中声明client_id、client_secret。此处更推荐使用托管标识的方式,无需在packer模版文件配置相关敏感信息,且托管标识方式跟Azure资源绑定后才能使用,更加安全。有关托管标识的说明,请参考:https://learn.microsoft.com/zh-cn/entra/identity/managed-identities-azure-resources/overview
导入azcli仓库key
[localhost]# rpm --import https://packages.microsoft.com/keys/microsoft.asc
添加azcli仓库
- [localhost]# echo -e "[azure-cli]
- name=Azure CLI
- baseurl=https://packages.microsoft.com/yumrepos/azure-cli
- enabled=1
- gpgcheck=1
- gpgkey=https://packages.microsoft.com/keys/microsoft.asc" | sudo tee /etc/yum.repos.d/azure-cli.repo
安装azcli并登录
- [localhost]# yum install -y azure-cli
- [localhost]# az cloud set -n AzureChinaCloud
- [localhost]# az login
开启VM托管标识和授予订阅参与者权限
[localhost]$ az vm identity assign --identities [system] --role Contributor --scope /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx --ids /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx/resourceGroups/RG/providers/Microsoft.Compute/virtualMachines/VM
packer模版语法支持HCL和JSON格式,并且可以从HCL转换到JSON格式,此处为了方便添加注释,使用HCL来描述模版。
- [localhost]# cat avd-images.pkr.hcl
- source "azure-arm" "avd-images" { #avd-images为模版名称
- # use Azure Managed Identity
- client_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx" #VM托管标识的objectID
- cloud_environment_name = "AzureChinaCloud"
- managed_image_resource_group_name = "resourcegroup" #映像所在的资源组
- managed_image_name = "avd-images-test" #映像名称
- os_type = "Windows" #映像操作系统类型和版本
- image_publisher = "MicrosoftWindowsServer"
- image_offer = "WindowsServer"
- image_sku = "2019-Datacenter"
- build_resource_group_name = "resourcegroup" #构建映像时使用的资源组,默认会创建“pkr-Resource-Group-”命名格式的资源组
- virtual_network_name = "virtualnetwork" #构建映像时使用虚拟网络,默认会创建”pkrvn“命名格式的虚拟网络
- virtual_network_subnet_name = "subnetwork" #构建映像时使用的子网
- virtual_network_resource_group_name = "networkresourcegroup" #虚拟网络所在的资源组
- private_virtual_network_with_public_ip = false #构建映像时是否创建公网IP,默认为true
- vm_size = "Standard_DS2_v2" #构建映像时使用的vm型号
- # config winrm
- communicator = "winrm" #winrm连接的相关配置,ansible通过winrm方式来管理windows机器
- winrm_use_ssl = true
- winrm_insecure = true
- winrm_timeout = "5m"
- winrm_username = "packer"
- # define tags #配置一些tag信息
- azure_tags = {
- key1 = "value1"
- key2 = "value2"
- }
- }
- build {
- sources = ["sources.azure-arm.avd-images"]
- # config winrm for ansible
- provisioner "powershell" { #下载和执行powershell脚本,配置winrm
- inline = [
- "$wirmsrc = 'https://xxxxxxxxxxx/ConfigureRemotingForAnsible.ps1'",
- "$wirmdes = 'C:\\ConfigureRemotingForAnsible.ps1'",
- "Invoke-WebRequest -uri $wirmsrc -OutFile $wirmdes",
- "Unblock-File $wirmdes",
- "powershell.exe -ExecutionPolicy Unrestricted -File 'C:\\ConfigureRemotingForAnsible.ps1'",
- "rm 'C:\\ConfigureRemotingForAnsible.ps1'"
- ]
- }
- # exec ansile playbook
- provisioner "ansible" { #调用ansible playbook,执行软件安装配置
- playbook_file = "./playbook.yml"
- user = "packer"
- use_proxy = false
- extra_arguments = [
- "-e",
- "ansible_winrm_server_cert_validation=ignore",
- "-vvv"
- ]
- }
- # generalized image
- provisioner "powershell" { #执行通用化
- inline = [
- "while ((Get-Service RdAgent).Status -ne 'Running') { Start-Sleep -s 5 }",
- "while ((Get-Service WindowsAzureGuestAgent).Status -ne 'Running') { Start-Sleep -s 5 }",
- "& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /quiet /quit",
- "while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10 } else { break } }"
- ]
- }
- }
- [localhost]# cat playbook.yml
- ---
- - hosts: default
- gather_facts: false
- roles:
- - init
- - winrar
- - winscp
- - storageexplorer
- - vscode
- - chrome
- - putty
- ……
- [localhost]# tree -L 1 roles/
- roles/
- ├── chrome
- ├── config_env_variables
- ├── config_proxy
- ├── edge
- ├── fslogix
- ……
- [localhost]# cat roles/winrar/tasks/main.yml
- ---
- # tasks file for winrar
- - name: Download winrar
- win_get_url:
- url: 'https://xxxx/winrar-x64-602.exe'
- dest: C:\TempAvd\
- - name: Install winrar
- win_command: 'C:\TempAvd\winrar-x64-602.exe -S'
- args:
- creates: 'C:\Program Files\WinRAR\WinRAR.exe'
Note
使用ansible或脚本方式在windows上部署软件时,需要使用静默安装的方式,不同安装包支持的参数可能存在差异,可以在命令行使用"/?"来查看帮助,如xxx.exe /?,xxx.msi /?
[localhost]# packer build avd-images.pkr.hcl
看到如下输出表示构建完成
- OSType: Windows
- ManagedImageResourceGroupName: resourcegroup
- ManagedImageName: avd-images-test
- ManagedImageId: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Compute/images/avd-images-test
- ManagedImageLocation: chinaeast2
packer构建映像会执行如下几个步骤:
1)检查或创建资源组、创建VM、创建keyvault
2)配置winrm、调用ansible playbook部署软件
3)执行通用化
4)捕获映像
5)删除构建映像时由packer创建的临时资源
使用构建后的映像部署到AVD的VMSS,可以看到playbook中定义的软件都已安装
随后AVD发布应用效果如下
1)packer使用模版描述构建映像时所需的步骤,自动完成映像构建和临时资源清理工作
2)packer支持集成系统shell和调用配置管理工具实现软件部署、配置管理
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。