iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 29
0
Cloud Native

30 天準備 LPI DevOps Tools Engineer 證照系列 第 29

[Day 29] Packer

今天來介紹 HashiCorp 的 Packer,它是一個建立映像檔的工具。說到映像檔,到目前為止也在好幾種不同的平台上使用了不同格式的映像檔,像是 VirtualBox、Vagrant、Docker 等等。一般狀況下都是透過這些應用本身去下載管理映像檔,大部分會使用別人已經做好的映像檔,偶爾可能會需要一些客製化,這種時候通常會是使用一個映像檔再加上一些人為的操作或 script 來達成,如果說能把這些客製的內容直接打包在映像檔之中,應該可以省下不少的工夫。之前在 Docker 有學過如何使用 Dockerfile 依照自己的需要來建立一個映像檔,其他的應用平台,多多少少也有這樣的功能,只是可能它們是屬於比較進階的使用技巧,一般人並不會想要去嘗試。Packer 這個工具,就是要讓我們能夠以比較方便的方式來建立映像檔,官方文件說它有一些優點:

  1. 極快速的部署:因為已經把需要的套件及其他設定都放在映像檔中,所以馬上可用。
  2. 跨平台的可攜性:Packer 可針對不同平台打包出完全相同的映像檔,可以在本地、雲端等各種不同平台得到相同的運行環境。
  3. 增加穩定性:因為套件是預先裝好的,若有問題會馬上知道。
  4. 較好的測試性:映像檔一打包完成就可進行各種測試。

那麼就開始吧,一樣從 Get Started 開始,教學從安裝開始,請參考 https://www.packer.io/intro/getting-started/install.html。這一個範例使用的平台是 AWS,必須要申請 AWS 帳號,教學裡有提到如果不想要用雲端環境,可以選擇其他平台,不過因為怕沒有時間試驗,所以還是就用 AWS 吧,然後這裡有一個提示,這裡打包的映像檔雖然符合 free-tier 的規範,但如果之前有申請過帳號,可能會被收取費用,但費用應該不會太多(這邊是寫 few cents,所以就假設不超過 1 美元)。印象中如果是初次申請 AWS 這類型的雲端環境,一開始會有一段免費的體驗期,在這段時間可以使用不超過某個額度的資源,是免費的,這也就是文件中提到的,這個範例中所建立的映像檔,它取用的資源不會超過免費的額度,但如果帳號已經過了免費期間,那就要收費啦。申請 AWS 帳戶請由 https://aws.amazon.com/tw/free/

首先來安裝 Packer。Packer 有提供預先編譯好的版本,請由 https://www.packer.io/downloads.html 依自己的作業環境下載合適的版本,下載後解開就可以使用。以 Ubuntu 環境為例,指令如下:

$ wget https://releases.hashicorp.com/packer/1.3.2/packer_1.3.2_linux_amd64.zip
$ sudo apt-get install unzip
$ unzip packer_1.3.2_linux_amd64.zip
$ sudo mv packer /usr/local/bin/

完成後執行 packer --version 確認一下是否成功。

$ packer --version
1.3.2

按照慣例,會新建一個目錄作為工作目錄,請進入該目錄並建立一新的文字檔案,名稱為 example.json,內容如下:

{
  "variables": {
    "aws_access_key": "",
    "aws_secret_key": ""
  },
  "builders": [{
    "type": "amazon-ebs",
    "access_key": "{{user `aws_access_key`}}",
    "secret_key": "{{user `aws_secret_key`}}",
    "region": "us-east-1",
    "source_ami_filter": {
      "filters": {
        "virtualization-type": "hvm",
        "name": "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*",
        "root-device-type": "ebs"
      },
      "owners": ["099720109477"],
      "most_recent": true
    },
    "instance_type": "t2.micro",
    "ssh_username": "ubuntu",
    "ami_name": "packer-example {{timestamp}}"
  }]
}

這是一個 JSON 格式的樣板,在執行建置命令的時候會需要傳入兩個變數,aws_access_keyaws_secret_key,請到 AWS 的管理介面去設置,頁面在 https://console.aws.amazon.com/iam/home?#/security_credential,access key 為第三項,建立好後下載一個 csv,裡面會有 AWSAccessKeyIdAWSSecretKey 兩個鍵值配對。example.json 其他的部分是一些跟映像檔內容有關的設置,這裡暫時先不管它。

接下來文件說先針對此 JSON 檔案的內容進行驗證,基本上是檢查 JSON 的語法以及設定值是否正確,指令和照理應該會出現的結果如下,但是請先不要執行。

$ packer validate example.json
Template validated successfully.

為什麼不要執行呢,因為這個步驟在我的環境卡了很久,不知道原因是什麼,因為照理說如果只是檢查語法和格式是否正確,應該一下子就可以結束了。先跳過這個步驟,直接進行 build 指令,格式如下,請把 AWSAccessKeyIdAWSSecretKey 剛才下載檔案申請的內容。

$ packer build \
    -var 'aws_access_key=AWSAccessKeyId' \
    -var 'aws_secret_key=AWSSecretKey' \
    example.json

amazon-ebs output will be in this color.

==> amazon-ebs: Prevalidating AMI Name: packer-example 1542001826
    amazon-ebs: Found Image ID: ami-0f9351b59be17920e
==> amazon-ebs: Creating temporary keypair: packer_5be914a3-dc92-8d71-ca22-3f7902983c3e
==> amazon-ebs: Creating temporary security group for this instance: packer_5be914a6-6a0e-70ce-5d87-20191576b91f
==> amazon-ebs: Authorizing access to port 22 from 0.0.0.0/0 in the temporary security group...
==> amazon-ebs: Launching a source AWS instance...
==> amazon-ebs: Adding tags to source instance
    amazon-ebs: Adding tag: "Name": "Packer Builder"
    amazon-ebs: Instance ID: i-08d53b86cbd90937b
==> amazon-ebs: Waiting for instance (i-08d53b86cbd90937b) to become ready...
==> amazon-ebs: Using ssh communicator to connect: 54.209.63.58
==> amazon-ebs: Waiting for SSH to become available...
==> amazon-ebs: Connected to SSH!
==> amazon-ebs: Stopping the source instance...
    amazon-ebs: Stopping instance, attempt 1
==> amazon-ebs: Waiting for the instance to stop...
==> amazon-ebs: Creating unencrypted AMI packer-example 1542001826 from instance i-08d53b86cbd90937b
    amazon-ebs: AMI: ami-01069d2804ef33d63
==> amazon-ebs: Waiting for AMI to become ready...
==> amazon-ebs: Terminating the source AWS instance...
==> amazon-ebs: Cleaning up any extra volumes...
==> amazon-ebs: No volumes to clean up, skipping
==> amazon-ebs: Deleting temporary security group...
==> amazon-ebs: Deleting temporary keypair...
Build 'amazon-ebs' finished.

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created:
us-east-1: ami-01069d2804ef33d63

這樣映像檔就建置好了,可以在 AWS 的管理介面中看到它,依我的例子,網址是 https://console.aws.amazon.com/ec2/home?region=us-east-1#s=Images,畫面範例如下:
https://ithelp.ithome.com.tw/upload/images/20181113/201119532R7ZX2JHZa.png

建立的映像檔為 AMI ( Amazon Machine Image) 格式,可以嘗試用這個映像檔來起一個 instance。接下來將它刪除,請先核取此映像檔,接著在這個頁面上方的 Actions 選擇 Deregister。之後在左側選單 ELASTIC BLOCK STORESnapshots 的選項,進入後將快照刪除。

在這個映像檔中並沒有特別做什麼,如果想要對映像檔先進行 provision,也就是先安裝一些套件或執行某些指令,請參考下面範例。

{
    "variables": {
        "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
        "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}",
        "region":         "us-east-1"
    },
    "builders": [
        {
            "access_key": "{{user `aws_access_key`}}",
            "ami_name": "packer-linux-aws-demo-{{timestamp}}",
            "instance_type": "t2.micro",
            "region": "us-east-1",
            "secret_key": "{{user `aws_secret_key`}}",
            "source_ami_filter": {
              "filters": {
              "virtualization-type": "hvm",
              "name": "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*",
              "root-device-type": "ebs"
              },
              "owners": ["099720109477"],
              "most_recent": true
            },
            "ssh_username": "ubuntu",
            "type": "amazon-ebs"
        }
    ],
    "provisioners": [
        {
            "type": "file",
            "source": "./welcome.txt",
            "destination": "/home/ubuntu/"
        },
        {
            "type": "shell",
            "inline":[
                "ls -al /home/ubuntu",
                "cat /home/ubuntu/welcome.txt"
            ]
        },
        {
            "type": "shell",
            "script": "./example.sh"
        }
    ]
}

下面 provisioners 的區段,先將 welcome.txt 拷貝到映像檔中,接下來執行 lscatexample.sh。其中像 lscat 的執行結果會在 packer build 執行時被印出。此外這裡 credential 是用 env 變數指定的,這樣在執行 packer build 時就不用傳入 credentials。

Get Started 的部分到此結束,其他更深入的內容可參考 https://www.packer.io/docs/index.html。Packer 支援建立多種平台的映像檔,可以看一下左側 builder 的選單,目前大約有二十多種,而每一個 builder 也都會它的設定選項。

關於 Packer 的部分就先作到這裡,大概知道了它的用法以及支援的平台,之後若有需要建立自己的機器映像檔再來試試看吧。


上一篇
[Day 28] Jenkins (2)
下一篇
[Day 30] Prometheus & Intermission
系列文
30 天準備 LPI DevOps Tools Engineer 證照30

尚未有邦友留言

立即登入留言