返回文章列表

Packer自動化建構機器映像檔

本文介紹如何使用 Packer 自動化建構機器映像檔,包含 AWS、Azure 和 Google Cloud Platform 等多個雲端平台。文章涵蓋 Packer 範本檔案的撰寫、組態指令碼的編寫、IAM 使用者的設定以及 Jenkins 的自動化安裝與組態。透過

DevOps 雲端運算

Packer 能夠根據預先定義的範本檔案,自動化建立多個平台的機器映像檔,例如 AWS AMI、Azure 映像檔和 Google Compute Engine 映像檔。此方法有助於標準化伺服器環境,確保跨平台一致性,並減少手動組態的錯誤。透過使用 Packer,開發團隊可以更專注於應用程式開發,而不必花費過多時間在伺服器組態上。Packer 的範本檔案使用 JSON 或 YAML 格式,定義了建構器的型別、所需的資源以及組態指令碼。組態指令碼可以使用 shell、Ansible、Chef 或 Puppet 等工具,根據需求安裝軟體、設定服務和調整系統引數。

使用Packer製作機器映像檔

Packer是一種流行的開源工具,用於建立相同組態的機器映像檔。以下是使用Packer建立機器映像檔的流程:

  1. 使用範本檔案中定義的基礎映像檔啟動臨時例項。
  2. 使用組態管理工具(如Ansible、Chef或Puppet)或簡單的自動化指令碼來組態例項,以達到所需的狀態。
  3. 從臨時執行的例項建立新的機器映像檔,並在映像檔製作完成後關閉臨時例項。

一旦建立了新的機器映像檔,從這個新映像檔啟動新的伺服器將具有與臨時例項相同的組態。這有助於提供平滑的佈署流程,並幫助快速擴充套件服務。

Packer組態

Packer的組態檔案,也稱為範本檔案,可以以JSON或YAML格式編寫。它由以下三個主要部分組成:

使用者變數

此部分用於引數化Packer範本檔案,以便將秘密、環境變數和其他引數排除在範本之外。此部分有助於範本檔案的可移植性,並有助於分離範本中可以修改的部分。變數可以透過命令列、環境變數、HashiCorp Vault(www.vaultproject.io)或檔案傳遞。此部分是變數名稱與預設值的鍵值對映。

建構器

此部分包含Packer用於生成機器映像檔的建構器列表。建構器負責建立例項並從中生成機器映像檔。一個建構器對應一個機器映像檔。此部分包含諸如型別(即建構器的名稱)、存取金鑰和連線到平台(例如AWS)所需的憑證等資訊。

供應器

此部分(可選)包含Packer在建立機器映像檔之前用於在執行中的例項中安裝和組態軟體的供應器列表。型別指定供應器的名稱,例如Shell、Chef或Ansible。

安裝和組態Packer

Packer是用Go語言編寫的,Go是一種編譯語言。因此,安裝Packer非常簡單;只需從www.packer.io/downloads/下載適合您系統和架構的二進位制檔案即可。

驗證安裝

安裝Packer後,透過開啟新的終端會話並發出以下命令來驗證安裝是否正常工作:

packer --version

如果出現錯誤,提示找不到Packer,則您的PATH環境變數未正確設定。否則,Packer已安裝,您就可以開始使用了!

使用Packer建立機器映像檔

安裝Packer後,讓我們深入瞭解並構建我們的第一個映像檔。我們的第一個機器映像檔將是一個Amazon EC2 AMI,其中預先安裝了Jenkins。要建立此AMI,我們需要編寫一個Packer組態檔案。

建立範本檔案

建立一個名為template.json的檔案,並填寫以下內容:

{
  "variables": {
    "region": "AWS區域",
    "aws_profile": "AWS組態檔案",
    "source_ami": "Amazon Linux AMI ID",
    "instance_type": "EC2例項型別"
  },
  "builders": [
    {
      "type": "amazon-ebs",
      "profile": "{{user `aws_profile`}}",
      "region": "{{user `region`}}",
      "instance_type": "{{user `instance_type`}}",
      "source_ami": "{{user `source_ami`}}",
      "ssh_username": "ec2-user",
      "ami_name": "jenkins-master-2.204.1",
      "ami_description": "包含Jenkins伺服器的Amazon Linux映像檔"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "script": "./setup.sh",
      "execute_command": "sudo -E -S sh '{{ .Path }}'"
    }
  ]
}

此範本檔案包含三個主要部分:variablesbuildersprovisioners

變數說明

我們使用變數來代替在範本檔案中硬編碼值。在我們的示例中,我們在表4.1中定義了變數。

變數描述
region要啟動EC2例項以建立AMI的AWS區網域名稱。
aws_profile要使用的AWS組態檔案。
instance_type用於構建AMI的EC2例項型別。
source_ami用於啟動臨時EC2例項的基礎AMI。

使用過濾器查詢AMI ID

您也可以使用Packer中的source_ami_filter屬性以程式設計方式查詢AMI ID。此屬性將根據定義的過濾器自動填充source_ami屬性。

"builders": [
  {
    "ami_name": "jenkins-master-2.204.1",
    "ami_description": "包含Jenkins伺服器的Amazon Linux映像檔",
    "source_ami_filter": {
      "filters": {
        "virtualization-type": "hvm",
        "name": "amzn2-ami-hvm-*-x86_64-gp2",
        "root-device-type": "ebs"
      },
      "owners": ["amazon"],
      "most_recent": true
    }
  }
]

圖表翻譯:

此圖表呈現了使用Packer建立機器映像檔的流程。首先,使用範本檔案中定義的基礎映像檔啟動臨時例項。然後,使用組態管理工具或自動化指令碼來組態例項。最後,從臨時執行的例項建立新的機器映像檔,並關閉臨時例項。

圖表翻譯: 此圖表呈現了使用Packer建立機器映像檔的流程。首先,使用範本檔案中定義的基礎映像檔啟動臨時例項。然後,使用組態管理工具或自動化指令碼來組態例項。最後,從臨時執行的例項建立新的機器映像檔,並關閉臨時例項。

程式碼範例說明

以下是一個範例程式碼,用於建立一個包含Jenkins的Amazon EC2 AMI:

{
  // ...
  "builders": [
    {
      // ...
      "source_ami": "{{user `source_ami`}}",
      // ...
    }
  ],
  // ...
}

內容解密:

此程式碼片段定義了一個Packer建構器,用於建立一個Amazon EC2 AMI。其中,source_ami屬性指定了用於啟動臨時EC2例項的基礎AMI。該值透過變數source_ami傳遞。這個變數應該在執行Packer時透過命令列或其他方式提供。

packer build -var 'source_ami=ami-xxxxxxxxxxxxxxxxx' template.json

使用 Packer 製作機器映像檔

Packer 是一個強大的工具,能夠自動化製作多個平台上的機器映像檔。本章節將介紹如何使用 Packer 製作 Amazon Machine Image(AMI)。

Packer 範本檔案

首先,我們需要定義一個 Packer 範本檔案 template.json,內容如下:

{
  "builders": [
    {
      "type": "amazon-ebs",
      "region": "eu-central-1",
      "source_ami_filter": {
        "filters": {
          "virtualization-type": "hvm",
          "name": "Amazon Linux AMI-*",
          "root-device-type": "ebs"
        },
        "owners": ["amazon"],
        "most_recent": true
      },
      "ami_name": "jenkins-master-2.204.1"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "script": "setup.sh"
    }
  ]
}

內容解密:

  • builders 部分定義了要建立的機器映像檔型別,這裡使用的是 amazon-ebs,表示建立一個 EBS-backed AMI。
  • source_ami_filter 用於篩選基礎 AMI,條件包括虛擬化型別、名稱和根裝置型別,並且選擇最新的 Amazon Linux 映像檔。
  • ami_name 定義了產生的 AMI 的名稱。
  • provisioners 部分定義了在建立的例項上執行的組態指令碼,這裡使用了一個名為 setup.sh 的 bash 指令碼。

setup.sh 指令碼內容

#!/bin/bash
yum remove -y java
yum install -y java-1.8.0-openjdk
wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo
rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key
yum install -y jenkins
chkconfig jenkins on
service jenkins start

內容解密:

  • 首先移除現有的 Java 版本並安裝 OpenJDK 1.8。
  • 然後下載 Jenkins 的 Yum 倉函式庫組態檔案並匯入 Jenkins 的 GPG 金鑰。
  • 安裝 Jenkins LTS 版本。
  • 組態 Jenkins 開機自動啟動並立即啟動 Jenkins 服務。

驗證範本檔案語法

執行以下命令驗證範本檔案的語法:

packer validate template.json

若語法正確,將傳回零離開狀態。

為 Packer 組態 IAM 使用者

需要為 Packer 組態一個具有足夠許可權的 IAM 使用者,以允許其佈署 EC2 例項並建立機器映像檔。需為該使用者附加 AmazonEC2FullAccess 策略,或使用具有最小必要許可權的自定義策略。

建立機器映像檔

組態好 IAM 使用者後,可以使用以下命令建立機器映像檔:

packer build template.json

Packer 將根據範本檔案中的組態佈署一個 EC2 例項,執行組態指令碼,並最終建立一個新的 AMI。

多平台支援

相同的範本檔案可以被修改以支援多個雲端平台,例如 Google Compute Cloud 和 Microsoft Azure,只需在 builders 部分新增相應的組態即可。

{
  "builders": [
    {
      "type": "amazon-ebs",
      // Amazon EC2 組態
    },
    {
      "type": "googlecompute",
      // Google Compute Cloud 組態
    },
    {
      "type": "azure-arm",
      // Microsoft Azure 組態
    }
  ],
  // 省略其他組態...
}

圖表翻譯:

此圖示展示瞭如何使用單一 Packer 範本檔案建立多個雲端平台上的機器映像檔。

圖表翻譯: 此圖表示使用 Packer 範本檔案可以建立不同雲端服務商的機器映像檔,包括 Amazon EC2、Google Compute Cloud 和 Microsoft Azure。

使用 Packer 製作 Jenkins 映像檔

Packer 是一款強大的工具,能夠幫助我們為不同的雲端平台建立相同的虛擬機器映像檔。本章節將介紹如何使用 Packer 製作 Jenkins 的 Amazon Machine Image(AMI)、Azure 映像檔和 Google Compute Engine 映像檔。

Packer 的基本設定

首先,我們需要定義一個 Packer 設定檔,用於描述要建立的映像檔。以下是一個範例設定檔:

{
  "builders": [
    {
      "type": "amazon-ebs",
      "profile": "{{user `aws_profile`}}",
      "region": "{{user `region`}}",
      "instance_type": "{{user `instance_type`}}",
      "source_ami": "{{user `source_ami`}}",
      "ssh_username": "ec2-user",
      "ami_name": "jenkins-master-2.204.1",
      "ami_description": "Amazon Linux Image with Jenkins Server"
    },
    {
      "type": "azure-arm",
      "subscription_id": "{{user `subscription_id`}}",
      "client_id": "{{user `client_id`}}",
      "client_secret": "{{user `client_secret`}}",
      "tenant_id": "{{user `tenant_id`}}",
      "managed_image_resource_group_name": "{{user `resource_group`}}",
      "managed_image_name": "jenkins-master-v22041",
      "os_type": "Linux",
      "image_publisher": "OpenLogic",
      "image_offer": "CentOS",
      "image_sku": "8.0",
      "location": "{{user `location`}}",
      "vm_size": "Standard_B1ms"
    },
    {
      "type": "googlecompute",
      "image_name": "jenkins-master-v22041",
      "account_file": "{{user `service_account`}}",
      "project_id": "{{user `project`}}",
      "source_image_family": "centos-8",
      "ssh_username": "packer",
      "zone": "{{user `zone`}}"
    }
  ]
}

內容解密:

此設定檔定義了三個不同的 builder,分別用於建立 Amazon Machine Image、Azure 映像檔和 Google Compute Engine 映像檔。每個 builder 都包含了必要的引數,例如雲端平台的憑證、映像檔的名稱和描述等。

建立 Jenkins 映像檔

當我們定義好 Packer 設定檔後,就可以開始建立 Jenkins 映像檔。Packer 會根據設定檔中的描述,建立多個映像檔,並在建立完成後自動終止臨時的虛擬機器。

測試 Jenkins 映像檔

建立完成後,我們可以測試 Jenkins 映像檔是否正常運作。首先,我們需要在 AWS 上啟動一個新的 EC2 例項,並選擇剛剛建立的 Jenkins 映像檔。然後,我們需要組態安全群組,允許來自任何地方的流量透過 port 8080。

此圖示呈現了允許流量透過 port 8080 的安全群組設定

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Packer自動化建構機器映像檔

package "Docker 架構" {
    actor "開發者" as dev

    package "Docker Engine" {
        component [Docker Daemon] as daemon
        component [Docker CLI] as cli
        component [REST API] as api
    }

    package "容器運行時" {
        component [containerd] as containerd
        component [runc] as runc
    }

    package "儲存" {
        database [Images] as images
        database [Volumes] as volumes
        database [Networks] as networks
    }

    cloud "Registry" as registry
}

dev --> cli : 命令操作
cli --> api : API 呼叫
api --> daemon : 處理請求
daemon --> containerd : 容器管理
containerd --> runc : 執行容器
daemon --> images : 映像檔管理
daemon --> registry : 拉取/推送
daemon --> volumes : 資料持久化
daemon --> networks : 網路配置

@enduml

圖表翻譯: 此圖表顯示了安全群組的設定,允許來自任何地方的流量透過 port 8080,以便存取 Jenkins 網頁控制檯。

組態 Jenkins

當我們啟動 EC2 例項後,就可以透過瀏覽器存取 Jenkins 網頁控制檯。第一次存取時,我們需要輸入初始密碼,該密碼位於 /var/lib/jenkins/secrets/initialAdminPassword 檔案中。

自動化 Jenkins 組態

為了避免手動組態 Jenkins 的麻煩,我們可以使用 Groovy 指令碼自動化 Jenkins 的組態。這些指令碼將在 Jenkins 啟動時執行,從而組態 Jenkins 至所需的狀態。

使用 Groovy 指令碼組態 Jenkins

// 設定 Jenkins 的管理員帳號和密碼
import jenkins.model.Jenkins

def jenkins = Jenkins.getInstance()
def securityRealm = jenkins.getSecurityRealm()
def strategy = new hudson.security.FullControlOnceLoggedInAuthorizationStrategy()
jenkins.setAuthorizationStrategy(strategy)

內容解密:

此 Groovy 指令碼用於設定 Jenkins 的管理員帳號和密碼。它首先取得 Jenkins 的例項,然後設定安全域和授權策略。