LoginSignup
0
0

More than 3 years have passed since last update.

Packer on GCP: Embulkイメージの作成

Last updated at Posted at 2019-12-04

これはなんですか

  • PackerでCompute Engineのマシンイメージを作ってみたので、作業記録を残します。
  • Docker/Kubernetes の時代になって、初めてイメージを焼きました。

つくりたいもの

  • Embulkが動作するGCE VM Machine Image
  • Embulk用にユーザーを作成する
  • とりあえずsudoerが sudo su - embulk でユーザーを切り替えられる様な状態にする
    • 発展形として、外部ユーザーが embulk コマンドの実行やプラグインのインストールをできるようにしたい。

作業記録

作業環境

  • MacBook Pro
    • brew install packer でPackerをインストールする
  • Cloud Shell
    • gcloud project config set [YOUR PROJECT NAME] でプロジェクトを指定しておく。

サービスアカウント作成

Packer の Google Compute Builder ページ
https://www.packer.io/docs/builders/googlecompute.html

Cloud IAM 役割について
https://cloud.google.com/iam/docs/understanding-roles

雑に↓を振ってみる

  • roles/compute.networkUser
  • roles/compute.instanceAdmin.v1
  • roles/iam.serviceAccountUser

Cloud Shell上でサービスアカウント packer を作成する。
https://cloud.google.com/iam/docs/creating-managing-service-accounts?hl=ja#iam-service-accounts-create-gcloud

$ gcloud beta iam service-accounts create packer --description "Allow to build Compute Engine images (for Packer)"

作成したサービスアカウントに役割を付与する。
https://cloud.google.com/iam/docs/granting-roles-to-service-accounts?hl=ja#granting_access_to_a_service_account_for_a_resource

$ gcloud projects add-iam-policy-binding [YOUR_PROJECT_ID] --member serviceAccount:packer@[YOUR_PROJECT_ID].iam.gserviceaccount.com --role roles/compute.networkUser
$ gcloud projects add-iam-policy-binding [YOUR_PROJECT_ID] --member serviceAccount:packer@[YOUR_PROJECT_ID].iam.gserviceaccount.com --role roles/compute.instanceAdmin.v1
$ gcloud projects add-iam-policy-binding [YOUR_PROJECT_ID] --member serviceAccount:packer@[YOUR_PROJECT_ID].iam.gserviceaccount.com --role roles/iam.serviceAccountUse

キーの発行

サービスアカウントはできたので、キーを発行する。Cloud Shell 上でキーを発行してローカルに落とす。
https://cloud.google.com/iam/docs/creating-managing-service-account-keys?hl=ja#creating_service_account_keys

$ gcloud iam service-accounts keys create ~/key.json \
  --iam-account packer@[YOUR_PROJECT_ID].iam.gserviceaccount.com
created key [0fa7b041fb670319ec3400f0432e7f0e13af4425] of type [json] as [/home/username/key.json] for [packer@[YOUR_PROJECT_ID].iam.gserviceaccount.com]

Packer ファイル作成

まとめた。
https://github.com/Hikosaburou/packer_gce_embulk

variables.json
{
    "project_id": "[YOUR_PROJECT_ID]",
    "image_family": "debian-9",
    "account_file_path": "{{ env `GOOGLE_APPLICATION_CREDENTIALS` }}"
}
embulk.json
{
    "builders": [
        {
            "type": "googlecompute",
            "account_file": "{{user `account_file_path`}}",
            "project_id": "{{user `project_id`}}",
            "source_image_family": "{{user `image_family`}}",
            "ssh_username": "packer",
            "zone": "asia-northeast1-a",
            "image_family": "{{user `image_family`}}",
            "image_name": "embulk-{{user `image_family`}}-{{timestamp}}"
        }
    ],
    "provisioners": [
        {
            "type": "shell",
            "script": "install_embulk.sh"
        }
    ]
}
install_embulk.sh
#!/bin/bash -ex

sleep 5
sudo sed -e 's/APT::Periodic::Update-Package-Lists "1";/APT::Periodic::Update-Package-Lists "0";/' \
  -e 's/APT::Periodic::Unattended-Upgrade "1";/APT::Periodic::Unattended-Upgrade "0";/' \
  /etc/apt/apt.conf.d/20auto-upgrades -i

sudo apt-get update -y
sudo apt-get install default-jdk -y

sudo adduser --disabled-password --gecos '' embulk

sudo curl --create-dirs -o /home/embulk/.embulk/bin/embulk --silent -L "https://dl.embulk.org/embulk-latest.jar"
sudo chmod +x /home/embulk/.embulk/bin/embulk
echo 'export PATH="$HOME/.embulk/bin:$PATH"' >> ~/tmp_bashrc
sudo sh -c "cat ${HOME}/tmp_bashrc >> /home/embulk/.bashrc"
sudo chown -R embulk:embulk /home/embulk/
rm ~/tmp_bashrc

sudo su - embulk <<EOF
/home/embulk/.embulk/bin/embulk gem install embulk-input-sqlserver
/home/embulk/.embulk/bin/embulk gem install embulk-output-bigquery
EOF

install_embulk.sh内の sudo apt-get update -y はなんとも微妙。。。でも進める。

Packer コマンドでローカルからビルドする:

$ packer build --var-file=variables.json embulk.json
googlecompute output will be in this color.

==> googlecompute: Checking image does not exist...
==> googlecompute: Creating temporary SSH key for instance...
==> googlecompute: Using image: debian-10-buster-v20191121
==> googlecompute: Creating instance...
    googlecompute: Loading zone: asia-northeast1-a
    googlecompute: Loading machine type: n1-standard-1
    googlecompute: Requesting instance creation...
    googlecompute: Waiting for creation operation to complete...
    googlecompute: Instance has been created!
==> googlecompute: Waiting for the instance to become running...
    googlecompute: IP: 34.84.207.9
==> googlecompute: Using ssh communicator to connect: 34.84.207.9
==> googlecompute: Waiting for SSH to become available...
==> googlecompute: Connected to SSH!
==> googlecompute: Provisioning with shell script: install_embulk.sh
==> googlecompute: + sleep 5
==> googlecompute: + sudo sed -e 's/APT::Periodic::Update-Package-Lists "1";/APT::Periodic::Update-Package-Lists "0";/' -e 's/APT::Periodic::Unattended-Upgrade "1";/APT::Periodic::Unattended-Upgrade "0";/' /etc/apt/apt.conf.d/20auto-upgrades -i

...

==> googlecompute: Deleting instance...
    googlecompute: Instance has been deleted!
==> googlecompute: Creating image...
==> googlecompute: Deleting disk...
    googlecompute: Disk has been deleted!
Build 'googlecompute' finished.

==> Builds finished. The artifacts of successful builds are:
--> googlecompute: A disk image was created: embulk-debian-9-1575458143

通った。

失敗の記録

主にシェルスクリプト力の欠如による失敗の記録。

実行するコマンドも出力したい

Shell Provisionerのドキュメントに書いてあった。
https://www.packer.io/docs/provisioners/shell.html

スクリプトのシェバン(shebang)に -x をつけよ、とのこと。

embulk_install.shのシェバン
#!/bin/bash -ex

inline パラメータでコマンドを渡している場合は inline_shebang で渡してあげれば良いらしい。

curl の出力を省略したい

--silent オプションをつければ、↓みたいなのが出なくなる.

build出力
==> googlecompute:   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
==> googlecompute:                                  Dload  Upload   Total   Spent    Left  Speed
==> googlecompute:   0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
==> googlecompute:   0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
==> googlecompute: 100   607    0   607    0     0   1498      0 --:--:-- --:--:-- --:--:--  5232
==> googlecompute: 100 43.2M  100 43.2M    0     0  10.3M      0  0:00:04  0:00:04 --:--:-- 15.4M

この辺でエラーが出ていたせいで惑わされた。

adduser の対話式インターフェースをスキップしたい

当初はこうやっていた。

yes '' | sudo adduser --disabled-password embulk

けど、もっとちゃんとしたオプションをask ubuntuに教えてもらったので、それに切り替えた。
https://askubuntu.com/questions/94060/run-adduser-non-interactively

sudo adduser --disabled-password --gecos '' embulk

sudo su - embulk でユーザーが切り替えられない

Packerはpackerユーザーとしてシェルスクリプトを実行する。途中 embulk ユーザーに切り替えてプラグインをインストールするところでこけた

失敗した箇所
sudo su - embulk
/home/embulk/.embulk/bin/embulk gem install embulk-input-sqlserver
/home/embulk/.embulk/bin/embulk gem install embulk-output-bigquery
build出力
==> googlecompute: + sudo su - embulk
    googlecompute: -rwxr-xr-x 1 embulk embulk 45378569 Dec  4 11:03 embulk
==> googlecompute: + id
    googlecompute: uid=1000(packer) gid=1001(packer) groups=1001(packer),4(adm),30(dip),44(video),46(plugdev),1000(google-sudoers)

上記はスクリプトに id をかませている。

無知な自分は、これの回避方法をテラテイル様に教えていただいた。
https://teratail.com/questions/138081

sudo su - username にリダイレクトをかけるか、sh -u username -c "..." で引数としてスクリプトを渡せば良いらしい。

修正後
sudo su - embulk <<EOF
/home/embulk/.embulk/bin/embulk gem install embulk-input-sqlserver
/home/embulk/.embulk/bin/embulk gem install embulk-output-bigquery
EOF

/home/embulk/.bashrcPATH の更新をかけてたから embulk コマンドで通せるかと一瞬思ったけど、当然ダメだった。ので、フルパスを渡している。

[ERROR] Embulk does not support Java 11 yet. というエラー

新しい Debian イメージ debian-10 を設定して実行したら、↑のエラーが出た。sudo apt-get install default-jdk -y で入るJavaのバージョンが新しすぎたためにエラーとなっていた。(.shの中で java -version 実行して確認した。。。 )

apt-get でバージョン指定するのが良い。けど、とりあえず debian-9 を指定してお茶を濁した。ただ、sudo apt-get update -y が入ってる時点で結末は見えている。。。

感想

  • Packer 自体はシンプルで簡単だったが、シェルスクリプト力が足りず苦しんだ。
  • GCEは爆速でインスタンスが立ち上がるのでAMI焼きよりは楽だったと思う。
0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0