gcpのイメージをpackerで作ってみた


やってみました。
AWSAzureはやったことあったので3大クラウド制覇したかったとかそういうのじゃなくて、素のイメージに手間取って検証に時間をとられたつらみを二度と起こさなくしておきたかっただけの備忘録です。

作業用インスタンス作成する(APIのスコープGCE許可するのとメタデータのユーザのSSH鍵の設定をしておく)
か、
サービスアカウントのクレデンシャル作ってjsonを実行ユーザ(gitlab-runner)環境の所定のpathに置いとくと動きます。

gitlab-runner@myhost01:~$ mkdir -p .config/gcloud
gitlab-runner@myhost01:~$ vi .config/gcloud/application_default_credentials.json

必要な権限は以下マニュアルに書いてあるので見たほうが早いですが
https://www.packer.io/docs/builders/googlecompute.html

サービスアカウント作るときに、"Compute Engine Instance Admin (v1)" と "Service Account User roles"(日本語コンソールだとコンピュートエンジンインスタンス管理者v1とサービスアカウントユーザ権限というかんじ)の割り当てが要るようでした。

$ wget https://releases.hashicorp.com/packer/1.2.5/packer_1.2.5_linux_amd64.zip
$ unzip packer_1.2.5_linux_amd64.zip 

$ git clone git@mygitserver:namespace/gcp_base_mi.git
$ cd gcp_base_mi/
$ ../packer version
Packer v1.2.5

$ vi test.json 
$ git diff 
diff --git a/test.json b/test.json
index 06a53da..69c2d5c 100644
--- a/test.json
+++ b/test.json
@@ -2,10 +2,10 @@
  "builders": [
  {
  "type": "googlecompute",
- "project_id": "extended-web-xxxxx",
+ "project_id": "komitest-xxxxx",
  "source_image": "centos-7-v20180523",
  "zone": "asia-northeast1-b",
- "ssh_username": "myuser1"
+ "ssh_username": "myuser2"
  }
  ],
  "provisioners": [{


$ ../packer validate ./test.json
Template validated successfully.

$ ../packer build ./test.json
googlecompute output will be in this color.

==> googlecompute: Checking image does not exist...
==> googlecompute: Creating temporary SSH key for instance...
==> googlecompute: Using image: centos-7-v20180523
==> googlecompute: Creating instance...
    googlecompute: Loading zone: asia-northeast1-b
    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: 35.194.103.xxx
==> googlecompute: Waiting for SSH to become available...
==> googlecompute: Connected to SSH!
==> googlecompute: Provisioning with shell script: /tmp/packer-shell508091364
    googlecompute: Loaded plugins: fastestmirror
    googlecompute: Determining fastest mirrors
    googlecompute:  * base: mirrors.cat.pdx.edu
    googlecompute:  * epel: mirrors.develooper.com
~略~
    googlecompute:
    googlecompute: RUNNING HANDLER [baseimage : restart ntpd service] *****************************
    googlecompute: changed: [default]
    googlecompute:
    googlecompute: PLAY RECAP *********************************************************************
    googlecompute: default                    : ok=16   changed=11   unreachable=0    failed=0
    googlecompute:
==> 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: packer-1534523276


templateのjsonは簡単には以下のようなの。

{
 "builders": [
 {
 "type": "googlecompute",
 "project_id": "komitest-xxxx",
 "source_image": "centos-7-v20180523",
 "zone": "asia-northeast1-b",
 "ssh_username": "myuser2"
 }
 ],
 "provisioners": [{
 "type": "shell",
 "inline": [
  "sudo yum -y update",
  "sudo yum -y install epel-release",
  "sudo yum -y install ansible"
 ]
 },
 {
 "type": "ansible",
 "playbook_file": "ansible/local.yml"
 }]
}

ansibleまわりは以下のアッサリした感じでふつうに動いてました。(あとrolesディレクトリがansibleのしたにある感じ)

$ cat ansible/local.yml
---
- hosts: all
  become: yes
  roles:
    - { role: baseimage }

$ cat ansible/inventory 
localhost

variablesとか外にだしてオプション指定しつつオプション足しつつ
gitlabのCIをシェルランナーでやってみると以下のような感じに。

test.json
{
 "variables": {
 "project_id": "",
 "source_image_family": "centos-7",
 "zone": "asia-northeast1-b",
 "ssh_username": "",
 "image_name": "packer",
 "commit_hash": "",
 "create_date": ""
 },
 "builders": [
 {
 "type": "googlecompute",
 "project_id": "{{user `project_id`}}",
 "source_image_family": "{{user `source_image_family`}}",
 "zone": "{{user `zone`}}",
 "ssh_username": "{{user `ssh_username`}}",
 "image_name": "{{user `image_name`}}{{user `create_date`}}",
 "labels": {
   "name": "{{user `image_name`}}",
   "commit_hash": "{{user `commit_hash`}}"
   },
 "scopes": [
   "https://www.googleapis.com/auth/userinfo.email",
   "https://www.googleapis.com/auth/compute",
   "https://www.googleapis.com/auth/devstorage.full_control",
   "https://www.googleapis.com/auth/sqlservice.admin"
   ]
 }
 ],
 "provisioners": [{
 "type": "shell",
 "inline": [
  "sudo yum -y update",
  "sudo yum -y install epel-release",
  "sudo yum -y install ansible"
 ]
 },
 {
 "type": "ansible",
 "playbook_file": "ansible/local.yml"
 }]
}

source_image_familyを指定しているとファミリーの中から最新のOSテンプレートを持ってきて勝手に使ってくれるみたいですね(gitlabCIのスケジュール機能と組み合わせると便利そう。)

.gitlab-ci.yml
#XXX: Packerをインストールする
before_script:
  - rm -f packer.zip
  - rm -rf .packer
  - curl -L -o packer.zip https://releases.hashicorp.com/packer/1.2.5/packer_1.2.5_linux_amd64.zip
  - mkdir -p .packer
  - (cd .packer && unzip ../packer.zip)

# validate
job_validate:
  script:
    - ./.packer/packer validate -var "project_id=komitest-xxxxxx"  -var "ssh_username=myuser1" -var "create_date=`date +%Y%m%d`-`date +%s`" -var "commit_hash=`git rev-parse HEAD`" test.json
  tags:
    - shell
# build
job_build:
  script:
    - ./.packer/packer build -var "project_id=komitest-xxxxxx" -var "ssh_username=myuser1" -var "create_date=`date +%Y%m%d`-`date +%s`" -var "commit_hash=`git rev-parse HEAD`" -color=false test.json
  tags:
    - shell

tagsはrunnerの選別に使うものでこの場合dockerじゃなくてshellで登録したrunnerで動くようにしたかったので指定。(dockerだとイメージの選別と準備が不足してるとcurlがなくて止まったりするし環境を汚すというほどの処理ではないのでshellでいいやと)

さんこう:
https://www.packer.io/docs/builders/googlecompute.html
https://amemo.hatenablog.jp/entry/2017/09/25/030819
http://t-cyrill.hatenablog.jp/entry/2018/03/17/005152
https://ngyuki.hatenablog.com/entry/2017/07/07/093326

cloudstack(IDCF)もやってる人いたんで試しはしたけど今のところうまくいっていないです。
https://qiita.com/quickguard/items/497bed57f92878c703e1