Packer是由HashiCorp出品的一個開源工具,用於建立相同配置的機器鏡像,以供多個平台使用。在DevOps(開發營運一體化)實踐中,Packer可以協助自動化構建和部署過程,通過預先定義的模板來建立可移植和可重複使用的基礎鏡像,有助於保證在開發、測試和生產環境中的一致性。本文介紹在阿里雲ECS使用Packer建立自訂鏡像的DevOps常用配置(綁定鏡像標籤、配置只基於系統硬碟建立鏡像、設定快照逾時時間等),適用於使用Packer建立ECS自訂鏡像的情境。
綁定鏡像標籤
適用情境:當您的自訂鏡像達到一定的數量時,適當地標記鏡像有利於鏡像管理和檢索。例如,記錄鏡像版本號碼和鏡像包含的應用類型等。阿里雲Builder提供了tags參數,支援為鏡像綁定標籤。產生的鏡像自動包含阿里雲ECS標籤,更多有關標籤的詳情,請參見標籤。
Packer欄位名稱:tags{"key":"value"}。
配置作用:ECS管理主控台鏡像列表頁面和API介面DescribeImages均支援查詢鏡像時返回標籤以及根據標籤過濾鏡像。為鏡像綁定標籤能夠和Terraform一起為企業級標準化DevOps流程提供支援。
配置樣本:以下設定檔為最終產生的鏡像和對應的快照綁定
version=v1.0.0和app=web兩個標籤。{ "variables": { "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" }, "builders": [{ "type":"alicloud-ecs", "access_key":"{{user `access_key`}}", "secret_key":"{{user `secret_key`}}", "region":"cn-beijing", "image_name":"packer_basic", "source_image":"centos_7_03_64_20G_alibase_20170818.vhd", "ssh_username":"root", "instance_type":"ecs.t5-lc1m1.small", "internet_charge_type":"PayByTraffic", "io_optimized":"true", "tags": { "version": "v1.0.0", "app": "web" } }] }
配置只基於系統硬碟建立鏡像
適用情境:預設情況下,Packer直接從ECS執行個體建立鏡像。如果執行個體包含了資料盤,則建立的鏡像會同時包含資料盤快照。
說明建立包含資料盤的執行個體通常有兩種方式:
方式一:通過image_disk_mappings設定資料盤相關參數。更多資訊,請參見《Packer文檔》Alicloud Image Builder。
方式二:選擇預設帶有資料盤的執行個體規格。該類執行個體規格包含的資料盤大多為本地碟,例如ecs.d1ne.2xlarge。但是本地碟並不支援建立快照,所以無法直接通過此類執行個體建立鏡像。
Packer欄位名稱:image_ignore_data_disks,資料類型為Boolean。
配置作用:如果您需要通過包含資料盤的執行個體建立鏡像,但實際上建立鏡像時不需要包含資料盤,可以在設定檔中加上
"image_ignore_data_disks": "true"實現只基於系統硬碟建立鏡像。配置樣本:
{ "variables": { "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" }, "builders": [ { "type":"alicloud-ecs", "access_key":"{{user `access_key`}}", "secret_key":"{{user `secret_key`}}", "region":"cn-hangzhou", "image_name":"packer_basic", "source_image":"aliyun_3_9_x64_20G_alibase_20231219.vhd", "associate_public_ip_address":true, "ssh_username":"root", "instance_type":"ecs.s6-c1m2.large", "internet_charge_type":"PayByTraffic", "io_optimized":true, "skip_image_validation":true, "image_disk_mappings": [ { "disk_snapshot_id": "s-bp1xxxxxx", "disk_device": "dev/xvdb" }], "image_ignore_data_disks": "true" } ] }
設定快照逾時時間
適用情境:建立鏡像依賴於快照,快照的建立時間依賴於磁碟大小。如果您的磁碟較大,建立快照所需時間會相應增加導致逾時錯誤時,您可以設定
wait_snapshot_ready_timeout欄位調大逾時時間。Packer欄位名稱:wait_snapshot_ready_timeout,資料類型為Integer,預設值為3600(秒)。
配置作用:將
wait_snapshot_ready_timeout設定為7200秒。配置樣本:
{ "variables": { "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" }, "builders": [ { "type":"alicloud-ecs", "access_key":"{{user `access_key`}}", "secret_key":"{{user `secret_key`}}", "region":"cn-hangzhou", "image_name":"packer_basic", "source_image":"aliyun_3_9_x64_20G_alibase_20231219.vhd", "associate_public_ip_address":true, "ssh_username":"root", "instance_type":"ecs.s6-c1m2.large", "internet_charge_type":"PayByTraffic", "io_optimized":true, "skip_image_validation":true, "wait_snapshot_ready_timeout": 7200 } ] }
通過私網IP串連執行個體
適用情境:通過私網IP串連執行個體,可以省去公網IP。
Packer欄位名稱:ssh_private_ip,資料類型為Boolean。
配置作用:通過設定
"ssh_private_ip": true,Packer不會分配EIP或者公網IP,而是通過私網IP串連執行個體。重要運行Packer的機器需要和Packer建立的機器在同一個網路環境,即同一個交換器下,才能使用私網串連。
配置樣本:
{ "variables": { "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" }, "builders": [ { "type":"alicloud-ecs", "access_key":"{{user `access_key`}}", "secret_key":"{{user `secret_key`}}", "region":"cn-hangzhou", "image_name":"packer_basic", "source_image":"aliyun_3_9_x64_20G_alibase_20231219.vhd", "ssh_username":"root", "instance_type":"ecs.s6-c1m2.large", "internet_charge_type":"PayByTraffic", "io_optimized":true, "skip_image_validation":true, "ssh_private_ip": true, "vpc_id":"vpc-xxxx", "vswitch_id":"vsw-xxxx" } ] }
設定停止執行個體選項
適用情境:預設情況下,Packer執行完provisioners後,會先停止執行個體再建立鏡像。某些特殊情境,如在Windows執行個體中運行Sysprep,需要執行個體處於運行狀態。
Sysprep的使用情境樣本,請參見執行個體之間無法互相訪問AD域或同時加入AD域怎麼辦?
Packer欄位名稱:disable_stop_instance,資料類型為Boolean。
配置作用:通過設定
"disable_stop_instance": true,Packer不會主動停止執行個體,需要在provisioners中提供停止執行個體的命令或手動停止執行個體。配置樣本:
{ "variables": { "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" }, "builders": [ { "type":"alicloud-ecs", "access_key":"{{user `access_key`}}", "secret_key":"{{user `secret_key`}}", "region":"cn-hangzhou", "image_name":"packer_basic", "source_image":"aliyun_3_9_x64_20G_alibase_20231219.vhd", "ssh_username":"root", "instance_type":"ecs.s6-c1m2.large", "internet_charge_type":"PayByTraffic", "io_optimized":true, "skip_image_validation":true, "associate_public_ip_address":true, "disable_stop_instance": true } ] }
通過UserData啟用WinRM
適用情境:出於安全考慮,Windows鏡像預設關閉了WinRM(Windows Remote Management)。但串連Windows執行個體及之後在執行個體內部執行命令都依賴於WinRM。在執行個體建立時,您可以通過UserData啟用WinRM。
Packer欄位名稱:user_data_file。
配置作用:通過配置
"user_data_file":"examples.ps1"指定UserData檔案的路徑。配置樣本:本樣本假定UserData檔案在給定的相對路徑examples/alicloud/basic/winrm_enable_userdata.ps1下。
{ "variables": { "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" }, "builders": [{ "type":"alicloud-ecs", "access_key":"{{user `access_key`}}", "secret_key":"{{user `secret_key`}}", "region":"cn-beijing", "image_name":"packer_test", "source_image":"win2008r2_64_ent_sp1_zh-cn_40G_alibase_20181220.vhd", "instance_type":"ecs.n1.tiny", "io_optimized":"true", "internet_charge_type":"PayByTraffic", "image_force_delete":"true", "communicator": "winrm", "winrm_port": 5985, "winrm_username": "Administrator", "winrm_password": "Test1234", "user_data_file": "examples/alicloud/basic/winrm_enable_userdata.ps1" }], "provisioners": [{ "type": "powershell", "inline": ["dir c:\\"] }] }說明樣本中與WinRM相關的參數含義如下:
"communicator": "winrm"表示通過WinRM串連執行個體。"winrm_port": 5985表示通訊連接埠為5985。"winrm_username": "Administrator"表示串連時使用Administrator賬戶。"winrm_password": "Test1234"表示密碼採用Test1234。
image_force_delete表示如果存在同名鏡像,則先刪除已有鏡像。
基於本地ISO檔案製作鏡像
適用情境:如果線下ISO檔案環境為其他虛擬化環境,也可以通過Packer完成操作。
Packer欄位名稱:builders{"type":"qemu"},post-processors{"type":"alicloud-import"}。
配置樣本:如果線下環境使用的是QEMU,請參見使用Packer建立並匯入本地鏡像。文檔中包含兩個重要的部分:
您需要使用本地虛擬化環境或軟體對應的Builder,如QEMU Builder。
請通過定義Alicloud Import Post-Processor將產生的本地鏡像檔案匯入阿里雲ECS。
如果您採用匯入自訂鏡像流程,請在本地安裝虛擬化環境,將ISO檔案製作成阿里雲支援的鏡像檔案格式後再匯入,如QCOW2、VHD和RAW。匯入流程請參見匯入鏡像流程。
通過SSH金鑰組私網串連執行個體
適用情境:通過SSH金鑰組私網串連執行個體。
Packer欄位名稱:ssh_keypair_name和ssh_private_key_file。
說明需要在控制台建立ssh_keypair_name,並儲存好私密金鑰。具體操作,請參見建立SSH金鑰組。
配置作用:通過設定
ssh_private_key_file,並將下載的私密金鑰檔案拷貝到執行Packer的機器上。其值為密鑰的絕對路徑。配置樣本:
{ "variables": { "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" }, "builders": [ { "type": "alicloud-ecs", "region": "cn-hangzhou", "image_name": "packer_basic", "source_image": "aliyun_3_x64_20G_alibase_20240819.vhd", "ssh_private_ip": true, "ssh_username": "root", "instance_type": "ecs.g6.large", "internet_charge_type": "PayByTraffic", "io_optimized": true, "skip_image_validation": true, "ssh_keypair_name": "{{user `ssh_keypair_name`}}", "ssh_private_key_file": "{{user `ssh_private_key_file`}}", "vpc_id": "{{user `vpc_id`}}", "vswitch_id": "{{user `vswitch_id`}}", "security_group_id": "{{user `security_group_id`}}" } ], "provisioners": [ { "type": "shell", "inline": [ "sleep 30", "yum install redis.x86_64 -y" ] } ] }
設定系統硬碟和資料盤
適用情境:自行選擇系統硬碟類型和大小,並將某些快照資料作為資料盤掛載在臨時ECS執行個體上,建立自訂鏡像。
Packer欄位名稱:system_disk_mapping(系統硬碟配置)和image_disk_mappings(資料盤配置)。
配置作用:通過設定
system_disk_mapping和image_disk_mappings資訊,新建立的自訂鏡像會包含系統硬碟類型、容量大小、是否隨執行個體釋放、資料盤類型、資料盤分區名稱等詳細資料。配置樣本:
{ "variables": { "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" }, "builders": [ { "type": "alicloud-ecs", "region": "cn-hangzhou", "image_name": "packer_basic", "source_image": "aliyun_3_x64_20G_alibase_20240819.vhd", "associate_public_ip_address":true, "ssh_username": "root", "instance_type": "ecs.g6.large", "internet_charge_type": "PayByTraffic", "io_optimized": true, "skip_image_validation": true, "system_disk_mapping":{ "disk_category":"cloud_essd", "disk_size":20, "disk_delete_with_instance":true }, "image_disk_mappings":[{ "disk_snapshot_id":"s-xxxxxxxxxxxxxxx", "disk_device":"dev/xvdb", "disk_category":"cloud_essd" }] } ], "provisioners": [ { "type": "shell", "inline": [ "sleep 30", "yum install redis.x86_64 -y" ] } ] }
使用鏡像族系建立和定義目標鏡像的鏡像族系
適用情境:無需關注
source_image迭代變化,通過鏡像族系即可實現鏡像迭代更新。Packer欄位名稱:image_family和target_image_family。
配置作用:通過設定
image_family擷取最新版本的鏡像建立ECS執行個體,並為新建立的自訂鏡像賦值target_image_family綁定鏡像族系。配置樣本:
{ "variables": { "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" }, "builders": [ { "type": "alicloud-ecs", "region": "cn-hangzhou", "image_name": "packer_basic", "associate_public_ip_address":true, "ssh_username": "root", "instance_type": "ecs.g6.large", "internet_charge_type": "PayByTraffic", "io_optimized": true, "skip_image_validation": true, "image_family":"acs:centos_7_9_x64", "target_image_family":"test_packer_basic" } ], "provisioners": [ { "type": "shell", "inline": [ "sleep 30", "yum install redis.x86_64 -y" ] } ] }
profile配置
適用情境:適用於多套環境配置,且互不干擾,例如多地區多帳號配置。
Packer欄位名稱:profile。
配置作用:Packer的設定檔,如果配置了該欄位,會優先從設定檔中擷取配置。例如在設定檔配置的參數在Packer模板中也有配置,該設定檔的配置會優先生效。檔案路徑必須是
~/.aliyun/config.json。配置樣本:
{ "builders": [ { "type": "alicloud-ecs", "profile": "packer_sk", "region": "cn-hangzhou", "image_name": "packer_basic", "source_image": "aliyun_3_x64_20G_alibase_20240819.vhd", "ssh_username": "root", "instance_type": "ecs.g6.large", "internet_charge_type": "PayByTraffic", "io_optimized": true, "skip_image_validation": true, "associate_public_ip_address":true } ], "provisioners": [ { "type": "shell", "inline": [ "sleep 30", "yum install redis.x86_64 -y" ] } ] }其中
"profile": "packer_sk"中的packer_sk是設定檔的名稱,該設定檔的路徑必須是~/.aliyun/config.json。設定檔內容如下:{ "current": "ALI", "profiles": [ { "name": "packer_sk", "mode": "AK", "access_key_id": "xxxxxxxxxxxxxxxxxxxxxxx", "access_key_secret": "xxxxxxxxxxxxxxxxxxxx", "sts_token":"", "sts_region": "", "ram_role_name": "", "ram_role_arn": "", "ram_session_name": "", "source_profile": "", "private_key": "", "key_pair_name": "", "expired_seconds": 0, "verified": "", "output_format": "json", "language": "en", "site": "", "retry_timeout": 0, "connect_timeout": 0, "retry_count": 0, "process_command": "", "credentials_uri": "" } ], "meta_path": "" }
通過RAM角色實現無AccessKey調用
適用情境:如果您不期望在模板或環境變數中配置AccessKey,可以為ECS執行個體綁定RAM角色擷取臨時AccessKey。為ECS執行個體綁定RAM角色的操作,請參見執行個體RAM角色。
說明該情境不支援本地操作,必須在ECS執行個體中執行。
RAM角色必須授予以下許可權。為RAM角色的授權操作,請參見RAM角色。
Packer欄位名稱:ram_role_name。
配置作用:擷取ECS綁定RAM角色的臨時AccessKey執行Packer,實現無AccessKey調用。
配置樣本:
{ "builders": [ { "type": "alicloud-ecs", "region": "cn-hangzhou", "image_name": "packer_basic", "source_image": "aliyun_3_x64_20G_alibase_20240819.vhd", "associate_public_ip_address": true, "ssh_username": "root", "instance_type": "ecs.g6.large", "internet_charge_type": "PayByTraffic", "io_optimized": true, "ram_role_name": "ImageTestAle", "skip_image_validation": true } ], "provisioners": [ { "type": "shell", "inline": [ "sleep 30", "yum install redis.x86_64 -y" ] } ] }
給臨時ECS綁定RAM角色
適用情境:給臨時執行個體綁定RAM角色,在Shell指令碼中擷取臨時AccessKey做業務處理。為ECS執行個體綁定RAM角色的操作,請參見執行個體RAM角色。
說明如果您是RAM使用者,還需要授予RAM使用者
ram:PassRole許可權。授權操作可參見3. 為RAM使用者授權。授權的策略內容如下:Packer欄位名稱:ecs_ram_role_name。
配置作用:擷取臨時AccessKey做業務處理。
配置樣本:
{ "variables": { "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" }, "builders": [ { "type": "alicloud-ecs", "region": "cn-hangzhou", "image_name": "packer_basic", "source_image": "aliyun_3_x64_20G_alibase_20240819.vhd", "ssh_username": "root", "instance_type": "ecs.g6.large", "internet_charge_type": "PayByTraffic", "io_optimized": true, "ecs_ram_role_name": "packer-test", "skip_image_validation": true, "associate_public_ip_address": true } ], "provisioners": [ { "type": "shell", "inline": [ "sleep 30", "yum install redis.x86_64 -y" ] } ] }
B帳號扮演A帳號建立鏡像
適用情境:跨帳號訪問、臨時授權等情境。
說明該情境有如下要求:
A帳號已對B帳號建立了一個可信實體類型的RAM角色,並為RAM角色授予相應的資源操作許可權。操作步驟可參考帳號A建立RAM角色並授權。授權的策略內容如下:
如果B帳號是RAM使用者,還需要授予RAM使用者
sts:AssumeRole許可權。授權的策略內容如下:不可配置
ssh_private_ip: true,必須配置associate_public_ip_address:true,通過公網串連。此模板在本地和阿里雲ECS執行個體中皆可運行。在阿里雲ECS執行個體中運行時,必須配置ECS執行個體的公網頻寬大於0,否則訪問RAM服務擷取臨時AccessKey失敗。
Packer欄位名稱:ram_role_arn(RAM角色的ARN)和ram_session_name(RAM角色的名稱)。
配置作用:B帳號扮演A帳號建立自訂鏡像。
配置樣本:
{ "variables": { "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" }, "builders": [ { "type": "alicloud-ecs", "region": "cn-hangzhou", "image_name": "packer_basic", "source_image": "aliyun_3_x64_20G_alibase_20240819.vhd", "associate_public_ip_address":true, "ssh_username": "root", "ram_role_arn": "acs:ram::186xxxxxxxxxx07:role/packer-test", "ram_session_name": "packer-test", "instance_type": "ecs.g6.large", "internet_charge_type": "PayByTraffic", "io_optimized": true, "skip_image_validation": true } ], "provisioners": [ { "type": "shell", "inline": [ "sleep 30", "yum install redis.x86_64 -y" ] } ] }
相關文檔
更多參數和範例,請參見Packer官方文檔Alicloud Image Builder和Examples。