2017年10月20日金曜日

Ubuntu で docker のアップグレードを行おうとしたら Linux カーネルのインストールでエラーになった話

概要

Ubuntu 16.04 で docker-ce のアップグレードを行ってみました
アップグレード自体は apt upgrade コマンドを叩けば終了なのですが、全然別件で Linux カーネルのインストールエラーに直面したので対応してみました

環境

  • Ubuntu 16.04
  • docker-engine 17.03 -> 17.05
  • linux-image-generic 4.4.0.96 -> 4.4.0.97

遭遇したエラー

アップグレードしようとしたときに遭遇したエラーは以下の通りです

[root@localhost /boot Wed Oct 18 10:40:08]# apt upgrade docker-engine
Reading package lists... Done
Building dependency tree
Reading state information... Done
You might want to run 'apt-get -f install' to correct these.
The following packages have unmet dependencies:
 linux-image-extra-4.4.0-97-generic : Depends: linux-image-4.4.0-97-generic but it is not installed
 linux-image-generic : Depends: linux-image-4.4.0-97-generic but it is not installed
                       Recommends: thermald but it is not installed
E: Unmet dependencies. Try using -f.

こんな感じです
実は /boot の領域が足りなくて上記のエラーが発生しています

対応する

単純に /boot の領域を空ければ OK
古いカーネルのファイルが残っているので削除してあげます

  • cd /boot

例えば config 系のファイルでは過去のバージョンがずらっと保存されているのが確認できると思います

[root@localhost /boot Wed Oct 18 10:45:39]# ls -l config-4.4.0-*
-rw-r--r-- 1 root root 189412 Apr 19  2016 config-4.4.0-21-generic
-rw-r--r-- 1 root root 190236 Mar 25  2017 config-4.4.0-71-generic
-rw-r--r-- 1 root root 190356 Jun 14 21:24 config-4.4.0-81-generic
-rw-r--r-- 1 root root 190356 Jun 27 04:45 config-4.4.0-83-generic
-rw-r--r-- 1 root root 190356 Jul 19 00:00 config-4.4.0-87-generic
-rw-r--r-- 1 root root 190356 Aug  1 07:25 config-4.4.0-89-generic
-rw-r--r-- 1 root root 190356 Aug  8 22:58 config-4.4.0-91-generic
-rw-r--r-- 1 root root 190356 Aug 10 20:02 config-4.4.0-92-generic
-rw-r--r-- 1 root root 190356 Aug 12 08:40 config-4.4.0-93-generic

この中の最新版以外 (今回の場合は 4.4.0-93 以外) の古いファイルをすべて削除してあげます
config の他に abi, initrd System.map, vmlinuz があるのでこれも削除するコマンドを実行します

  • rm 4.4.0-21-
  • rm 4.4.0-71-
  • rm 4.4.0-81-
  • rm 4.4.0-83-
  • rm 4.4.0-87-
  • rm 4.4.0-89-
  • rm 4.4.0-91-
  • rm 4.4.0-92-

これでだいぶ /boot が空くと思います
空いたら最新のカーネルをインストールしてあげましょう

  • apt -f install

で該当のエラーが出なくなると思います
無事インストールできたら docker-engine のアップグレードを実施しましょう

  • apt upgrade docker-engine
  • docker -v
Docker version 17.05.0-ce, build 89658be

こんな感じです

最後に

docker-engine を最新版にアップグレードした際に遭遇したカーネルエラーに対応してみました
/boot に空きがあれば遭遇することはないエラーだと思います

もし同じようなエラーに遭遇した場合はやってみてください

参考サイト

2017年10月19日木曜日

Jenkins の API を curl でサラッと試してみた

概要

久しぶりに Jenkins のリモート API に触れたので使い方などをまとめておきます

環境

  • macOS X 10.12.6
  • Jenkins 2.60.3

事前作業

今回は docker 上で動かしました
Jenkins を動かすのはどこでも問題ないです
一番初めのテンポラリーパスワードによる認証とプラグインのインストール、ユーザの作成までは済ませておいてください

今回は root という名前のユーザを作成した体で勧めます

CSRF の無効化

Jenkins -> Jenkins の管理 -> グローバルセキュリティ設定 -> CSRF対策

のチェックをオフにして Apply

API トークンの取得

root -> 設定 -> API トークン -> API トークンの表示

ジョブの作成

適当に作成してください
API でも良いですが面倒なので手動で作成しました
ちなみに API で作成した場合は謎の XML ファイルを作成して FORM として POST すれば作成できます -> 参考

いろいろコールしてみる

つらつらと curl でコールしてみました
ちなみに全部 POST で送っていますが GET でも OK です

ジョブの一覧の取得

curl -X POST --user 'root:bcc000720152bfd435e5c5128705908a' \
'http://localhost:8080/api/json?tree=jobs'

ちなみに件数を指定して取得することもできます

curl --user 'root:bcc000720152bfd435e5c5128705908a' \
'http://localhost:8080/api/json?tree=jobs%5Bname%5D%7B0%2C1%7D'

URL にするとこんなフォーマットです
curl でコールするときは URL エンコードする必要があるので上記のようになっています

http://localhost:8080/api/json?tree=jobs[name]{0,1}

ジョブのビルド

curl -v -X POST --user 'root:bcc000720152bfd435e5c5128705908a' \
'http://localhost:8080/job/test/build'

ここでポイントですがレスポンスの Location ヘッダにキューの情報が付与されています
ここに番号が振られておりそれがビルドの番号にもなるので、実行したビルドの結果を追いたい場合には Location ヘッダの情報を使用してください

Location: http://localhost:8080/queue/item/3/

最後に成功したビルドの結果を取得

curl -X POST --user 'root:bcc000720152bfd435e5c5128705908a' \
'http://localhost:8080/job/test/lastSuccessfulBuild/api/json?pretty=true'

最後に成功したビルドのコンソール結果を取得

curl -X POST --user 'root:bcc000720152bfd435e5c5128705908a' \
'http://localhost:8080/job/test/lastSuccessfulBuild/logText/progressiveText?start=0'

ビルド番号を指定してビルドの結果を取得

curl -X POST --user 'root:bcc000720152bfd435e5c5128705908a' \
'http://localhost:8080/job/test/3/api/json?pretty=true'

ビルド番号を指定してビルドのコンソール結果を取得

curl -X POST --user 'root:bcc000720152bfd435e5c5128705908a' \
'http://localhost:8080/job/test/3/logText/progressiveText?start=0'

ビルド番号を指定してビルドのコンソール結果を HTML で取得

curl -X POST --user 'root:bcc000720152bfd435e5c5128705908a' \
'http://localhost:8080/job/test/3/logText/progressiveHtml?start=0'

Tips

トークンを使わないでも API をコールすることができます
トークンの箇所に作成したユーザのパスワードを入力しても API をコールすることができます

また、良くないですがそもそも認証情報付与するの面倒くさいという場合はグローバルセキュリティ設定から「セキュリティを有効化」のチェックをオフにすればトークンもパスワードもなしで API をコールできます

最後に

Jenkins のリモート API を試してみました
基本は UI で操作していて、その操作を API として使いたいときに URL の最後に /api を付け加えてやるとその操作の API リファレンスがいろいろと表示されるのでそこでやり方を確認するといいと思います

コンソールの結果が平文 or HTML じゃなくてそれっぽい JSON とかに置き換えできれば Jenkins を使って簡単な API サーバが作れそうな気がしました
プラグインとか探せばあるのかな、、、

2017年10月18日水曜日

packer + WindowsServer2016 で vmxnet3 を使う

概要

前回 packer + esxi で WindowsServer2016 を自動構築してみました
しかし Windows2016 はデフォルトでネットワークドライバに vmxnet3 が使えません
packer ビルド時にドライバをインストールすれば使用することができたのでその方法を紹介します

環境

  • ESXi 6.0.0 (Build 3620759)
  • Ubuntu 16.0.4
  • packer 1.0.4

ドライバファイル

こちらです (GoogleDrive なので wget などはできません、手動でダウンロードしてサーバにアップロードしてください)
この中に inf ファイルが含まれています
WindowsServer2016 はこのファイルを自動実行してくれます
そうすることでビルド時にドライバを自動インストールします

テンプレートの修正

ほぼ同じなので一部だけ紹介します
ダウンロードした zip ファイルを展開して drivers 配下に配置します
そしてテンプレートファイル内の floppy_files に含めるようにします

zip ファイルのまま drivers 配下においても inf ファイルが見つからず自動で実行されないので、ちゃんと解凍したファイルたち (.dll や .inf ファイルなど) を drivers 配下に配置してください

"floppy_files": [
    "answer_files/Autounattend.xml",
    "drivers/",
    "scripts/winrm.ps1"
]

動作確認

これでビルドしてみましょう
もちろん Autounattend.xml や winrm.ps1 などもちゃんと配置して実行してください
うまくいくと vmxnet3 のドライバで動作する WindowsServer2016 が作成されると思います

最後に

packer + esxi + WindowsServer2016 で vmxnet3 ドライバを使用する方法を紹介しました
ドライバは以下の参考サイトで紹介されているものをそのまま使用しています
なくなっても問題ないようにキャッシュとして残しているだけなので、Github から持ってきても OK です
おそらく同様にストレージドライバなどをインストールすれば PVSCSI などを利用することもできると思います

参考サイト

2017年10月17日火曜日

packer を使って ESXi 上で WindowsServer2016 を自動構築してみた

概要

前回 Virtualbox 上で Windows Server 2016 の自動構築を行いました
今回は VMware ESXi 上でビルドして vmx + vmdk ファイルを作成してみたいと思います

環境

  • ESXi 6.0.0 (Build 3620759)
  • Ubuntu 16.0.4
  • packer 1.0.4

事前準備

Windows Server 2016 の ISO は事前にダウンロードしておいてください
過去にダウンロードの仕方を紹介しているので参考にしてください
packer を実行するマシン (今回であれば Ubuntu を使っています) 上に配置してください

前回同様 Windows の自動構築の仕組みは Autounattend.xml を使います
これは前回使用したものをそのまま流用できます

Autounattend.xml は Windows の OS 自動インストールを行うための仕組みなので Virtualbox であろうが ESXi であろうが同じものが使えて当然です
そして、内部で使用している WinRM を有効にする Powershell スクリプトも前回と同じものを流用します

テンプレートファイルの準備

ESXi 上で実行するテンプレートファイルを新規で作成します

  • win2016.json
{
    "builders": [{
        "type": "vmware-iso",
        "vm_name": "win2016",
        "guest_os_type": "windows8srv-64",
        "vmx_data": {
            "gui.fitguestusingnativedisplayresolution": "FALSE",
            "memsize": "2048",
            "numvcpus": "2",
            "virtualHW.version": "10",
            "scsi0.virtualDev": "lsisas1068",
            "ethernet0.networkName": "VM Network",
            "ethernet0.virtualDev": "e1000",
            "ethernet0.present": "TRUE",
            "ethernet0.connectionType": "custom",
            "ethernet0.vnet": "vmnet8",
            "ethernet0.startConnected": "TRUE"
        },
        "disk_size": 81920,
        "disk_type_id": "thin",
        "remote_type": "esx5",
        "remote_host": "192.168.100.101",
        "remote_datastore": "datastore12",
        "remote_username": "esxi_user",
        "remote_password": "esxi_password",
        "headless": "false",
        "iso_url": "/vol/win2016.ISO",
        "iso_checksum": "18a4f00a675b0338f3c7c93c4f131beb",
        "iso_checksum_type": "none",
        "communicator": "winrm",
        "winrm_username": "winuser1",
        "winrm_password": "winpass123",
        "winrm_timeout": "12h",
        "floppy_files": [
            "answer_files/Autounattend.xml",
            "scripts/winrm.ps1"
        ]
    }]
}

VirtualBox 時のテンプレートファイルと比較してポイントをいくつか説明します

まず type は vmware-iso を指定します
こうすることで VMware 環境 (今回は ESXi) 上でビルドを行うことができます
ESXi の情報は remote_type, remote_host, remote_datastore, remote_username, remote_password で設定しています

guest_os_type は Windodws8 のものを使用しています
とりあえずこれでも動作します

vmx_data で VM の構成を設定します
ここが一番のポイントです
まず scsi0.virtualDevlsisas1068 を指定してください
これは LSI Logic SAS というドライバなのですが、これでないとハードディスクをうまく認識することができません
これ以外のドライバを使いたい場合は別途ドライバをインストールする必要があります
次に ethernet0.virtualDeve1000 を指定してください
これも e1000 にしないとネットワークアダプタがうまく認識されず IP アドレスが取得できません
IP アドレスが取得できないと WinRM で接続もできないためビルドが失敗します

あとは "iso_checksum_type": "none" ですが、こうすることで ISO のアップロードを毎回行わないようにします
VirtualBox 時は md5 で指定していたのですが、md5 にするとなぜか ESXi に ISO を毎回アップロードしてしまいます
本来であればチェックサムの値が同じであれば既にアップロードしてある ESXi のデータストアにキャッシュされた ISO を使うのですが、なぜか使ってくれません
なので、ワークアラウンド的に none を指定しています

それ以外の項目に関しては前回の VirtualBox で使用したテンプレートとほぼ同じです

実行する

  • packer build win2016.json

で実行しましょう
問題なくビルドが完了すると指定したデータストア上に「output-vmware-iso」というディレクトリが作成されその配下に vmx ファイルと vmdk ファイルが保存されます
packer_vmware_win2016.jpg

今回のテンプレートの設定だとビルドが完了するとサーバは削除されてしまいます

最後に

packer を使って ESXi 上で Windows2016 をビルドしてみました
ハマったのは使用するドライバをテンプレートで指定する箇所で vmxnet3 や VMware Paravirtual (PVSCSI) を使用するとうまくデバイスが認識されませんでした

少し上記で述べましたが vmxnet3 にしていると Windows がネットワークアダプタを認識できず WinRM を使って packer から接続できずにビルドエラーとなります

ちなみに PVSCSI にしていると OS インストール時に Windows could not apply the unattend answer file's <DiskConfiguration> setting というエラーが発生します
うまくハードディスクが認識されないためパーティションの作成と設定に失敗しています
packer_vmware_win2016_2.jpg

この問題も頑張れば解決することができるらしいので解決できたらその方法を紹介したいと思います

2017年10月13日金曜日

dep で SSH な git リポジトリを使う方法

概要

dep init するときにリポジトリにアクセスするのですが、デフォルトだと https でアクセスしに行きます
もし https でアクセスできないと以下のエラーとなり init に失敗します

emote repository at https://your-domain-git-repo.local/project/repository.git does not exist, or is inaccessible: : exit status 128

こんな場合に SSH + git で対象にリポジトリにアクセスする方法を紹介します

環境

  • Ubuntu 16.04.2
  • git 2.7.4
  • golang 1.8.4
  • dep devel

対応方法

以下のコマンドを実行します

  • git config --global url.git://your-domain-git-repo.local/.insteadOf https://your-domain-git-repo.local/

これで「your-domain-git-repo.local」には https ではなく SSH で接続するようになります
うまくいかない場合は

  • git config --global url.git@your-domain-git-repo.local/.insteadOf https://your-domain-git-repo.local/

も試してみてください

ちなみに global な .gitconfig を直接編集したい場合は ~/.gitconfig にあります

参考サイト

2017年10月12日木曜日

golang 純正のパッケージ管理ツール「dep」を使ってみた

概要

golang 純正のパッケージ管理ツールである dep を使ってみました
ruby で言うところの gem、python で言うところの pip という感じでしょうか

環境

  • macOS X 10.12.6
  • golang 1.9.1
  • dep devel

dep のインストール

  • brew install dep

で今回はインストールしました
homebrew が使えない場合は go get でもインストール可能です

  • go get -u github.com/golang/dep/cmd/dep

GOPATH 配下に作業ディレクトリを作成する

今回 GOPATH は /Users/hawksnowlog/go/ とします
この配下に作業ディレクトリを作成します

  • mkdir -p /Users/hawksnowlog/go/src/github.com/hawksnowlog/dep-test
  • cd /Users/hawksnowlog/go/src/github.com/hawksnowlog/dep-test

初期化

  • dep init

とすると dep 関連のファイルが自動で生成されます

  • Gopkg.lock
  • Gopkg.toml
  • vendor/

Gopkg.toml ファイルに依存パッケージを記載していきます

テスト用のコード

以下を使います
logrus というロギング用のライブラリを使っています

  • vim main.go
package main

import (
        log "github.com/Sirupsen/logrus"
)

func main() {
        log.WithFields(log.Fields{
                "key": "value",
        }).Info("logrus test")
}

依存パッケージを追加する

今回はとりあえず 1 つだけ追加してみます

  • dep ensure -add github.com/Sirupsen/logrus

Gopkg.toml に以下のように定義が追加されていると思います

  • cat Gopkg.toml
[[constraint]]
  name = "github.com/Sirupsen/logrus"
  version = "1.0.3"

パッケージをインストールする

  • dep ensure

と実行すると Gopkg.toml に記載されたパッケージが vendor/ 配下にインストールされます
確認は dep status で確認できます

  • dep status
PROJECT                     CONSTRAINT  VERSION        REVISION  LATEST   PKGS USED
github.com/Sirupsen/logrus  ^1.0.3      v1.0.3         f006c2a   f006c2a  1  
golang.org/x/crypto         *           branch master  9419663   9419663  1  
golang.org/x/sys            *           branch master  ebfc5b4   ebfc5b4  2  

簡単です

動作確認

  • go build
  • go install
  • dep-test

と実行すると以下のようにログが表示されると思います

INFO[0000] logrus test                                   key=value

追加してもコード内で使用されていないと vendor/ 配下には配置されない

試しに使っていないパッケージを追加してみます

  • dep ensure -add github.com/astaxie/beego

まず使っていないパッケージを追加しようとすると警告が出ます

"github.com/astaxie/beego" is not imported by your project, and has been temporarily added to Gopkg.lock and vendor/.
If you run "dep ensure" again before actually importing it, it will disappear from Gopkg.lock and vendor/.

ただ、Gopkg.toml には記載されています

[[constraint]]
  name = "github.com/astaxie/beego"
  version = "1.9.0"

この状態でインストールして確認してみましょう

  • dep ensure
  • dep status

しても先ほどと結果は変わらないです
このように dep はコード内で使用しているパッケージだけを vendor` 配下にインストールしてくれるようです

ちなみに dep で追加したけど使用されていないパッケージは

  • /Users/hawksnowlog/go/pkg/dep/sources/https---github.com-astaxie-beego/

配下にあるようです

最後に

go 純正のパッケージ管理ツール dep を使ってみました
昔は toml ファイルではなく Json ファイルで管理していたようです
dep を使用するには golang のバージョンも 1.8 以上が必要になります

dep は import で参照しているライブラリを管理しているリポジトリにアクセスできる必要があります
今回は Github 上で公開されているライブラリだったので特に問題ないですが例えばプライベートなリポジトリや IP などでアクセス制限をしているライブラリに関しては dep を実行するサーバからもアクセスできる必要があるのでご注いください

参考サイト

2017年10月11日水曜日

VMware VIC の 1.2.1 を使ってみた

概要

VMware VIC の 1.2.1 GA がリリースされていたので試してみました
そのうち正式版がリリースされると思うのでそれを待っても良かったのですが触ってみました

環境

  • vic-machine v.1.2.1-13858-c3db65f
  • docker 17.03.0-ce
  • Ubuntu 16.04
  • vCenter Server 5.5.0

vic-machine コマンドのインストール

  • wget https://storage.googleapis.com/vic-engine-releases/vic_1.2.1.tar.gz

各種コマンド検証

create

./vic-machine-linux create \
--target 192.168.100.101/dc \
--user "vc-user" \
--password "vc-pass" \
--compute-resource cluster \
--image-store datastore2 \
--bridge-network "dvs-for-vch" \
--public-network "VM Network" \
--no-tlsverify --force

特に追加になってそうなオプションはなさそう
--name を指定しないと「virtual-container-host」という名前で vApp が作成され、その配下に VM が作成されます

delete

./vic-machine-linux delete \
--target 192.168.100.101/dc \
--user "vc-user" \
--password "vc-pass" \
--compute-resource cluster \
--name virtual-container-host \
--thumbprint "37:1D:..."

こちらも特になし
--name オプションを指定しないと「virtual-container-host」を削除しにいきます

ls

./vic-machine-linux ls \
--target "192.168.100.101/dc" \
--user "vc-user" \
--password "vc-pass" \
--compute-resource "cluster" \
--thumbprint "37:1D:..."

こちらも特になし

inspect

./vic-machine-linux inspect -\
-target "192.168.100.101/dc" \
--user "vc-user" \
--password "vc-pass" \
--compute-resource "cluster" \
--thumbprint "37:1D:..."

--name の指定が必須ではなくなったようです
指定しない場合は「virtual-container-host」に対して実行します

また今回からか不明なのですが ./vic-machine-linux inspect config というコマンドが追加されており、これを使うと create 時のオプションを確認することができます

debug

./vic-machine-linux debug \
--target "192.168.100.101/dc" \
--user "vc-user" \
--password "vc-pass" \
--compute-resource "cluster" \
--enable-ssh --rootpw password \
--thumbprint "37:1D:..."

こちらも特になし
--name がない場合は「virtual-container-host」に対して実行します

update

./vic-machine-linux update firewall \
--target "192.168.100.101/dc" \
--user "vc-user" \
--password "vc-pass" \
--compute-resource "cluster" \
--deny \
--thumbprint "37:1D:..."

こちらも特になし
firewall しか操作できないのとこのコマンドは ESXi に対して実行するコマンドなのでいろいろと変更したほうが良いと思っているんですが変わらないですね、、、、
--deny--allow にすることもできます

upgrade

./vic-machine-linux upgrade \
--target "192.168.100.101/dc" \
--user "vc-user" \
--password "vc-pass" \
--compute-resource "cluster" \
--name virtual-container-host \
--appliance-iso ./appliance.iso \
--bootstrap-iso ./bootstrap.iso \
--thumbprint "37:1D:..."

今回は 1.1.1 -> 1.2.1 でやってみましたが問題なく行えました
ping を投げ続けてみましたが切断っぽい挙動が 2 回ほどありました

64 bytes from 192.168.200.100: icmp_seq=37 ttl=64 time=0.833 ms
64 bytes from 192.168.200.100: icmp_seq=38 ttl=64 time=17.0 ms
64 bytes from 192.168.200.100: icmp_seq=39 ttl=64 time=0.223 ms
64 bytes from 192.168.200.100: icmp_seq=40 ttl=64 time=0.301 ms
64 bytes from 192.168.200.100: icmp_seq=41 ttl=64 time=0.296 ms
64 bytes from 192.168.200.100: icmp_seq=42 ttl=64 time=0.318 ms
64 bytes from 192.168.200.100: icmp_seq=43 ttl=64 time=0.331 ms
64 bytes from 192.168.200.100: icmp_seq=44 ttl=64 time=8.29 ms
64 bytes from 192.168.200.100: icmp_seq=45 ttl=64 time=0.251 ms

今回は検証していませんが 0.8 や 0.9 から 1.2.1 に upgrade できるのかも気になりました

configure

おそらく新規で追加になったコマンドです
これで作成後の VCH に対していろいろと変更を入れられるようになりました

./vic-machine-linux configure \
--target "192.168.100.101/dc" \
--user "vc-user" \
--password "vc-pass" \
--compute-resource "cluster" \
--ops-user administrator@vsphere.local \
--ops-password adminpass \
--thumbprint "37:1D:..."

ops-user と ops-password を変更します
このユーザとパスワードを使って VCH から vCenter に対して API を発行してコンテナ VM を作成します

./vic-machine-linux configure \
--target "192.168.100.101/dc" \
--user "vc-user" \
--password "vc-pass" \
--compute-resource "cluster" \
--volume-store datastore2/directory:label \
--thumbprint "37:1D:..."

volume-store を追加します
ここで指定したvolume-store 上に docker volume で作成したデータが作成されます

./vic-machine-linux configure \
--target "192.168.100.101/dc" \
--user "vc-user" \
--password "vc-pass" \
--compute-resource "cluster" \
--dns-server 8.8.8.8 \
--thumbprint "37:1D:..."

VCH 上に DNS サーバを変更します
デフォルトだと public-network 上にある DHCP から教えてもらえる DNS が設定されています
それ以外にしたい場合は dns-server オプションで変更できます

他にも

  • 証明書の更新
  • レジストリの設定を変更
  • コンテナ専用ネットワークの変更
  • VCH から外に出るときのプロキシの設定
  • ログレベルの変更
  • メモリとCPU のアロケートサイズの変更

などができたりします
詳しくは configure --help してみると良いと思います

その他

  • version
  • help

docker コマンド検証

一番の特徴は exec が使えるようになっている点です

  • docker -H 192.168.200.100:2375 exec -it 7f4398f4c2d9 /bin/bash

それ以外のコマンドに関してはこれまで通り使えます
docker-compose も対応しています

  • docker-compose -H 192.168.200.100:2375 up -d

当然ですが、イメージは Docker hub で公開していなければありません (registry の設定を VCH にしていれば別)

ただ、swarm コマンドに現在もサポートされていません
おそらく今後のバージョンでも swarm はサポートされないと思います

最後に

VIC の 1.2.1 を試してみました
基本的なことしか試していないのですべてのエンハンス内容を網羅しているわけではありませんのでご注意を

それでも exec が使えるようになっていたり作成後の VCH に対して変更を加えられている点は嬉しいエンハンスかなと思います

個人的には vic-machine-linux コマンドの方法で VCH の操作ができるようになると嬉しいなと思いました (API)

参考サイト

2017年10月10日火曜日

MailClark 使ってみた

概要

前回 Slack の無料プランで slackbot を使ってメールの通知を受け取る方法を紹介しました
直接コメントがあったのですが MailClark という便利なアプリがあるとのことなので使ってみました

環境

  • macOS X 10.12.6
  • Slack App 2.8.0

MailClark アプリの追加

まずアプリを追加します
https://mailclark.ai/ にアクセスして「Add to Slack」を選択します
mailclark0.png

するとチームに対してアプリを追加する画面になるのでアプリに与える権限を確認して「Authorize」を選択します
mailclark1.png

すると Slack App 側に MailClark アプリから追加されたよという通知が来ます
mailclark2.png

とりあえずこれでアプリの追加は完了です

メールアドレスを取得する

次に MailClark 専用の転送アドレスを取得します
先ほどの画面でプルダウンにはチャネルが選択できるようになっています
まず、MailClark アプリを追加したいチャネルを選択しましょう (今回は #general を選択しました)

するとチャネル側に MailClark が追加されたよという通知が届きます
mailclark3.png

そして「Email」「Twitter」「Facebook」と並んでいるボタンから「Email」を選択しましょう
すると「general@team-kaka.mailclark.ai」というアドレスが払い出されます
このメールアドレスのフォーマットは「チャネル名@チーム名.mailclark.ai」になります

動作確認

そのまま「Receive a test email」を選択してみましょう
先ほど発行されたアドレスにテストメールが送信されチャネルにもメールの通知が届くと思います
mailclark4.png

ちなみに払い出されたアドレスに対して Gmail から送信してみたところ問題なく通知が届きました
mailclark5.png

最後に

Slack でメール通知を受け取れる MailClark を使ってみました

そのまま Slack App 上で返信することもでき「Reply」を選択すると対話形式でメールの返信を行うことができます
無料でここまで使えるのはかなり便利かなと思います

Incomming Web Hook などとは違い Integration ではなくアプリになります
権限などを与える必要がありますがそこまで気にならないと思います

2017年10月9日月曜日

packer + VirtualBox で Windows Server 2016 を自動構築してみた

概要

前回 VirtualBox 上に Windows Server 2016 を構築してみました
その際に OS のインストールは手動で行いました
Windows には OS を自動でインストールする仕組みとして Autounattend.xml を使う方法があります
今回は packer と Autounattend.xml を組み合わせて Windows Server 2016 のインストールの自動化を行ってみました

環境

  • macOS X 10.12.6
  • VirtualBox 5.1.26 r117224 (Qt5.6.2)
  • packer 1.0.4

テンプレートファイルの準備

まずは Json テンプレートを作成します
今回はプロビジョニングはせず OS をインストールの基本設定だけを自動化します
テンプレートの全容は以下の通りです

  • vim win2016.json
{
  "builders": [
    {
      "type": "virtualbox-iso",
      "vboxmanage": [
        [ "modifyvm", "{{.Name}}", "--memory", "2048" ],
        [ "modifyvm", "{{.Name}}", "--vram", "48" ],
        [ "modifyvm", "{{.Name}}", "--cpus", "2" ]
      ],
      "guest_additions_mode": "{{ user `guest_additions_mode` }}",
      "guest_os_type": "Windows2016_64",
      "headless": "{{ user `headless` }}",
      "iso_url": "{{ user `iso_url` }}",
      "iso_checksum": "{{ user `iso_checksum` }}",
      "iso_checksum_type": "md5",
      "communicator": "winrm",
      "winrm_username": "winuser1",
      "winrm_password": "winpass123",
      "winrm_timeout": "12h",
      "floppy_files": [
        "answer_files/Autounattend.xml",
        "scripts/winrm.ps1"
      ]
    }
  ],
  "variables": {
    "guest_additions_mode": "attach",
    "headless": "true",
    "iso_checksum": "18a4f00a675b0338f3c7c93c4f131beb",
    "iso_url": "/path/to/win2016.ISO"
  }
}

ISO はファイルは前回ダウンロードした ISO をそのまま使います
すでにローカルにあるのでローカルのパスを指定しています
もちろんここに URL を指定しても OK です

xml と ps1 ファイルはこのあと説明します

Autounattend.xml の準備

今回の肝になります
この XML ファイルを作成することで OS のインストールを自動化します
Linux で言うところの kickstart ファイルです
かなり長いですが全容は以下の通りです

<?xml version="1.0" encoding="UTF-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
   <settings pass="windowsPE">
      <!-- look for drivers on floppy -->
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <DriverPaths>
            <PathAndCredentials wcm:keyValue="1" wcm:action="add">
               <Path>A:\</Path>
            </PathAndCredentials>
         </DriverPaths>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <SetupUILanguage>
            <UILanguage>en-US</UILanguage>
         </SetupUILanguage>
         <InputLocale>en-US</InputLocale>
         <SystemLocale>en-US</SystemLocale>
         <UILanguage>en-US</UILanguage>
         <UILanguageFallback>en-US</UILanguageFallback>
         <UserLocale>en-US</UserLocale>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <DiskConfiguration>
            <Disk wcm:action="add">
               <CreatePartitions>
                  <CreatePartition wcm:action="add">
                     <Type>Primary</Type>
                     <Order>1</Order>
                     <Size>350</Size>
                  </CreatePartition>
                  <CreatePartition wcm:action="add">
                     <Order>2</Order>
                     <Type>Primary</Type>
                     <Extend>true</Extend>
                  </CreatePartition>
               </CreatePartitions>
               <ModifyPartitions>
                  <ModifyPartition wcm:action="add">
                     <Active>true</Active>
                     <Format>NTFS</Format>
                     <Label>boot</Label>
                     <Order>1</Order>
                     <PartitionID>1</PartitionID>
                  </ModifyPartition>
                  <ModifyPartition wcm:action="add">
                     <Format>NTFS</Format>
                     <Label>Windows 2016</Label>
                     <Letter>C</Letter>
                     <Order>2</Order>
                     <PartitionID>2</PartitionID>
                  </ModifyPartition>
               </ModifyPartitions>
               <DiskID>0</DiskID>
               <WillWipeDisk>true</WillWipeDisk>
            </Disk>
         </DiskConfiguration>
         <ImageInstall>
            <OSImage>
               <InstallFrom>
                  <MetaData wcm:action="add">
                     <Key>/IMAGE/NAME</Key>
                     <Value>Windows Server 2016 SERVERDATACENTER</Value>
                  </MetaData>
               </InstallFrom>
               <InstallTo>
                  <DiskID>0</DiskID>
                  <PartitionID>2</PartitionID>
               </InstallTo>
            </OSImage>
         </ImageInstall>
         <UserData>
            <ProductKey>
               <WillShowUI>OnError</WillShowUI>
            </ProductKey>
            <AcceptEula>true</AcceptEula>
            <FullName>winuser1</FullName>
            <Organization>winuser</Organization>
         </UserData>
      </component>
   </settings>
   <settings pass="generalize">
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <SkipRearm>1</SkipRearm>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-PnpSysprep" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <PersistAllDeviceInstalls>false</PersistAllDeviceInstalls>
         <DoNotCleanUpNonPresentDevices>false</DoNotCleanUpNonPresentDevices>
      </component>
   </settings>
   <settings pass="oobeSystem">
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <InputLocale>en-US</InputLocale>
         <SystemLocale>en-US</SystemLocale>
         <UILanguage>en-US</UILanguage>
         <UserLocale>en-US</UserLocale>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <OOBE>
            <HideEULAPage>true</HideEULAPage>
            <HideLocalAccountScreen>true</HideLocalAccountScreen>
            <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
            <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
            <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
            <NetworkLocation>Home</NetworkLocation>
            <ProtectYourPC>1</ProtectYourPC>
         </OOBE>
         <TimeZone>UTC</TimeZone>
         <UserAccounts>
            <AdministratorPassword>
               <Value>adminpass</Value>
               <PlainText>true</PlainText>
            </AdministratorPassword>
            <LocalAccounts>
               <LocalAccount wcm:action="add">
                  <Password>
                     <Value>winpass123</Value>
                     <PlainText>true</PlainText>
                  </Password>
                  <Group>administrators</Group>
                  <DisplayName>winuser1</DisplayName>
                  <Name>winuser1</Name>
                  <Description>Windows User 1</Description>
               </LocalAccount>
            </LocalAccounts>
         </UserAccounts>
         <AutoLogon>
            <Password>
               <Value>winpass123</Value>
               <PlainText>true</PlainText>
            </Password>
            <Enabled>true</Enabled>
            <Username>winuser1</Username>
         </AutoLogon>
         <FirstLogonCommands>
            <SynchronousCommand wcm:action="add">
               <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\winrm.ps1</CommandLine>
               <Order>1</Order>
            </SynchronousCommand>
         </FirstLogonCommands>
      </component>
   </settings>
   <settings pass="specialize">
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-ServerManager-SvrMgrNc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-IE-ESC" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <IEHardenAdmin>false</IEHardenAdmin>
         <IEHardenUser>false</IEHardenUser>
      </component>
      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-OutOfBoxExperience" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
         <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon>
      </component>
   </settings>
</unattend>

自分もすべてを把握しているわけではないですが主に行っているのは

  • Administrator のパスワードの設定
  • 新規ユーザの作成 (winuser1/winpass123)
  • OS をインストールするパーティションの設定
  • winuser1 での Windows への自動ログイン
  • タイムゾーンの設定
  • 言語の設定
  • OOBE (Out-Of-Box Experience) の設定
  • フロッピーにマウントした WinRM を有効にするスクリプトの実行

になります
詳細はそれぞれの XML のタグ名で検索すれば出ると思います

ちょっと余談ですがこんなクソ長い XML を手動で作成するわけにはいきません
普通は Windows System Image Manager と ISO を使って XML を生成するみたいです
でもその手順はかなり面倒なので、調べてみたら Web 上で XML を生成できるサービスがありました

ただ、すべてを網羅しているわけではないのでちゃんと作成するのであれば結局公式のドキュメントを見ながら頑張るしかないと思います

ちなみに自分は参考サイトにある Github のリポジトリから引っ張ってきました

WinRM を有効にする PowerShell の準備

WinRM を有効にするのは packer でプロビジョニングしない場合でも必須です

  • mkdir scripts
  • vim scripts/winrm.ps1
netsh advfirewall firewall add rule name="WinRM-HTTP" dir=in localport=5985 protocol=TCP action=allow
winrm set winrm/config/service/auth '@{Basic="true"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'

Windows ファイアウォールに WinRM で通信できる穴を開けています
これは先ほども説明したように Autounattend.xml 内で実行しています

実行

準備完了です
実行してみましょう

  • packer build win2016.json

成功すると以下のようになります

virtualbox-iso output will be in this color.

Warnings for build 'virtualbox-iso':

* A shutdown_command was not specified. Without a shutdown command, Packer
will forcibly halt the virtual machine, which may result in data loss.

==> virtualbox-iso: Downloading or copying Guest additions
    virtualbox-iso: Downloading or copying: file:///Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso
==> virtualbox-iso: Downloading or copying ISO
    virtualbox-iso: Downloading or copying: file:///Users/hawksnowlog/Documents/work/packer/windows/win2016.ISO
==> virtualbox-iso: Creating floppy disk...
    virtualbox-iso: Copying files flatly from floppy_files
    virtualbox-iso: Copying file: answer_files/Autounattend.xml
    virtualbox-iso: Copying file: scripts/winrm.ps1
    virtualbox-iso: Done copying files from floppy_files
    virtualbox-iso: Collecting paths from floppy_dirs
    virtualbox-iso: Resulting paths from floppy_dirs : []
    virtualbox-iso: Done copying paths from floppy_dirs
==> virtualbox-iso: Creating virtual machine...
==> virtualbox-iso: Creating hard drive...
==> virtualbox-iso: Attaching floppy disk...
==> virtualbox-iso: Creating forwarded port mapping for communicator (SSH, WinRM, etc) (host port 3950)
==> virtualbox-iso: Executing custom VBoxManage commands...
    virtualbox-iso: Executing: modifyvm packer-virtualbox-iso-1507116947 --memory 2048
    virtualbox-iso: Executing: modifyvm packer-virtualbox-iso-1507116947 --vram 48
    virtualbox-iso: Executing: modifyvm packer-virtualbox-iso-1507116947 --cpus 2
==> virtualbox-iso: Starting the virtual machine...
    virtualbox-iso: The VM will be run headless, without a GUI. If you want to
    virtualbox-iso: view the screen of the VM, connect via VRDP without a password to
    virtualbox-iso: rdp://127.0.0.1:5959
==> virtualbox-iso: Waiting 10s for boot...
==> virtualbox-iso: Typing the boot command...
==> virtualbox-iso: Waiting for WinRM to become available...
==> virtualbox-iso: Connected to WinRM!
==> virtualbox-iso: Uploading VirtualBox version info (5.1.26)
==> virtualbox-iso: Halting the virtual machine...
    virtualbox-iso: Removing floppy drive...
    virtualbox-iso: Removing guest additions drive...
==> virtualbox-iso: Preparing to export machine...
    virtualbox-iso: Deleting forwarded port mapping for the communicator (SSH, WinRM, etc) (host port 3950)
==> virtualbox-iso: Exporting virtual machine...
    virtualbox-iso: Executing: export packer-virtualbox-iso-1507116947 --output output-virtualbox-iso/packer-virtualbox-iso-150711
6947.ovf
==> virtualbox-iso: Unregistering and deleting virtual machine...
Build 'virtualbox-iso' finished.

==> Builds finished. The artifacts of successful builds are:
--> virtualbox-iso: VM files in directory: output-virtualbox-iso

作成される成果物は以下の通りです
ovf と vmdk が出来上がりました

  • ls -ltr output-virtualbox-iso/
total 9132296
-rw-------  1 hawksnowlog  staff        7076 10  4 20:43 packer-virtualbox-iso-1507116947.ovf
-rw-------  1 hawksnowlog  staff  4675725312 10  4 20:50 packer-virtualbox-iso-1507116947-disk001.vmdk

試しに ovf を VirtualBox に展開してみると良いと思います
winuser1/winpass123 でログインして Windows Server 2016 が立ち上がってくるのが確認できると思います
ちなみに今回の Windows Server は「Datacenter Evaluation」として構築されます

最後に

packer + Autounattend.xml で Windows Server 2016 の OS インストールを自動化してみました
本当はこのあと chef なり powershell を使ってミドルウェアや OS 上のプロビジョニングを行います
プロビジョニングは結局 WinRM を使うので今回のビルドが成功すればプロビジョニングまではすぐにいくと思います

Github にあるサンプルは chef-solo を使っています
chef-solo を選択すると Windows サーバ上に chef-solo コマンドがインストールされてしまうので注意が必要です

またプロビジョニング用のスクリプトを作成するときは一旦 Windows を立ててその中で try & error を繰り返したほうが効率が良いと思います

参考サイト

2017年10月8日日曜日

VirtualBox 上に Windows Server 2016 を構築してみた

概要

VirtualBox 上に Windows 2016 をインストールしてみました
Windows 2016 は評価版の ISO を使います

環境

  • macOS X 10.12.6
  • VirtualBox 5.1.26 r117224 (Qt5.6.2)

ISO ダウンロード

まずは評価版の ISO をダウンロードします
なぞに公開されている URL があるのでそれを使います

  • wget 'http://care.dlservice.microsoft.com/dl/download/1/6/F/16FA20E6-4662-482A-920B-1A45CF5AAE3C/14393.0.160715-1616.RS1_RELEASE_SERVER_EVAL_X64FRE_EN-US.ISO'

本当はちゃんと公式から利用者登録してダウンロードしたほうが良いかなと思います
上記の URL も変更される可能性があるので

ダウンロード後ファイル名が長かったので「win2016.ISO」に名前を変更しました

VM 作成

VirtualBox 上で VM を作成します
特にポイントはないです
OS を「Windows 2016 (64bit)」にすることくらいです
win2016_on_vb1.png

メモリやディスクのサイズはデフォルトのまま選択しました (2048MB, 32GB)
VM が作成できたら ISO を光学ドライブにマウントしましょう
win2016_on_vb2.png

Windows インストール

VM を起動して Windows をインストールしましょう
基本はポチポチやっていけば OK です
ポイントは 2 つで 1 つはデスクトップあり版をインストールするようにしましょう (上から 3 つ目のスクリーンショット)
もう 1 つはインストールをカスタマイズにしましょう (上から 5 つ目のスクリーンショット)

win2016_on_vb3.png

win2016_on_vb4.png

win2016_on_vb5.png

win2016_on_vb6.png

win2016_on_vb7.png

win2016_on_vb8.png

win2016_on_vb9.png

win2016_on_vb10.png

OS のインストールが完了すると自動で再起動して今度は OS のセットアップ画面がスタートします

OS セットアップ

と入っても Administrator のパスワードを設定するだけです
パスワードポリシーがあるので気をつけましょう
win2016_on_vb11.png

あとは Ctrl + Alt + Delete を送信して
win2016_on_vb12.png

パスワードを入力すれば OK です
win2016_on_vb13.png

動作確認

起動するとこんな感じでサーバマネージャが起動します
win2016_on_vb14.png

VirtualBox のネットワークは NAT だけなので 10.0 台の IP が付与されています
NAT なのでインターネットにも接続できます
win2016_on_vb15.png

Remote Desktop などしたい場合には別途ホストオンリーアダプタを追加して 192 台の IP にアクセスすれば OK かなと思います

最後に

VirtualBox 上で Windows 2016 サーバを構築してみました
評価版のライセンスなので 180 日を過ぎるとライセンスが切れて使えなくなると思います
もしかすると使えるのは普通に使えて Windows update などができなくなるだけかもしれません

結構簡単にインストールできるので Mac or Linux 環境しかない方には便利かなと思います
OS のインストール作業も packer を使えば自動化できそうなのでその辺も検証してみたいなと思います

2017年10月7日土曜日

docker swarm + overlay network 環境を構築してみた

概要

前回 VirtualBox 上で docker swarm 環境を構築してみました
swarm にはコンテナホスト間で横断的にコンテナが通信するために overlay というネットワークドライバがあります
今回はこれを使用して異なるコンテナホスト上で動作させたコンテナ同士を通信させてみたいと思います

また今回は swarm の管理方式を token ではなく consul を使ってクラスタを管理してみたいと思います

環境

  • macOS X 10.12.6
  • docker 17.09.0-ce
  • docker-machine 0.12.2
  • VirtualBox 5.1.26 r117224 (Qt5.6.2)

consul ノードの作成

docker swarm を管理するために必須です

  • docker-machine create --driver virtualbox consul
  • eval "$(docker-machine env consul)"
  • docker run -d -p "8500:8500" -h "consul" progrium/consul -server -bootstrap

consul を動作させるためのコンテナホストを 1 台作成して、その上で consule をサーバとして動作させます

swarm クラスタにコンテナホストを作成する

2 台のコンテナホスト (master と通常ノード) をクラスタに登録します

swarm-master

  • docker-machine create --driver virtualbox --swarm --swarm-master --swarm-discovery="consul://$(docker-machine ip consul):8500" --engine-opt="cluster-store=consul://$(docker-machine ip consul):8500" --engine-opt="cluster-advertise=eth1:2376" swarm-master

node1

  • docker-machine create --driver virtualbox --swarm --swarm-discovery="consul://$(docker-machine ip consul):8500" --engine-opt="cluster-store=consul://$(docker-machine ip consul):8500" --engine-opt="cluster-advertise=eth1:2376" node1

  • docker-machine ls

  • eval $(docker-machine env --swarm swarm-master)
  • docker info

で docker swarm クラスタの情報を確認できます

overlay ネットワークを作成する

コンテナホスト間で横断的に通信するための overlay ネットワークを作成します

  • docker network create --driver overlay --subnet=10.0.9.0/24 overlay-network
  • docker network ls
305a0a49838a        overlay-network                overlay             global

SCOPE が global な overlay ネットワークが作成されていることを確認します

コンテナを作成して動作確認

2 台作成したコンテナホスト上にそれぞれコンテナを作成して通信できるか確認します

swarm-master 上に nginx コンテナ (web) を起動

  • docker run -itd --name=web --net=overlay-network --env="constraint:node==swarm-master" nginx

node1 から swarm-master 上に作成した web コンテナにアクセスできるか確認

  • docker run -it --rm --net=overlay-network --env="constraint:node==node1" busybox wget -O- http://web

で結果的に以下のような HTML が取得できれば異なるコンテナホスト間で通信できていることになります

Connecting to web (10.0.9.2:80)
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
-                    100% |*******************************|   612   0:00:00 ETA

ポイントは node1 上で起動している busybox のコンテナから web コンテナをコンテナ名で引けているところです
もし overlay ネットワークに所属していない状態でコンテナを起動すると web コンテナが見つからず以下のようにエラーとなります

  • docker run -it --rm --env="constraint:node==node1" busybox wget -O- http://web
wget: bad address 'web'

最後に

docker swarm 上で overlay ネットワークを作成して異なるコンテナホスト間でもコンテナ同士が通信できる環境を作成してみました
overlay ネットワークを構築する場合は token 方式ではなく consul 方式を使って docker swarm を管理したほうが無難です

Tips

swarm クラスタ内に存在するノードの確認

  • docker run swarm list consul://$(docker-machine ip consul):8500

docker-machine を使ってノードを新規で追加することもできますが swarm join コマンドを使って既存のコンテナホストを追加することもできます

参考サイト

2017年10月6日金曜日

VirtualBox 上で docker swarm 環境を構築してみた

概要

前回 VirtualBox 上で docker-machine コマンドを試してみました
今回は swarm クラスタを構築してみます

環境

  • macOS X 10.12.6
  • docker 17.09.0-ce
  • docker-machine 0.12.2
  • VirtualBox 5.1.26 r117224 (Qt5.6.2)

swarm コンテナの作成

まず docker swarm を管理するための swarm コンテナを作成します
swarm コンテナを作成することでクラスタを管理するトークンが払い出されます

  • docker run swarm create
Unable to find image 'swarm:latest' locally
latest: Pulling from library/swarm
237b7f0588af: Pull complete 
25637219010c: Pull complete 
5a434bba05af: Pull complete 
Digest: sha256:cc94ce2e6d4603fe9077919db5a4508f7441cad7ae57ccd420fd14af3b3d4383
Status: Downloaded newer image for swarm:latest
Token based discovery is now deprecated and might be removed in the future.
It will be replaced by a default discovery backed by Docker Swarm Mode.
Other mechanisms such as consul and etcd will continue to work as expected.
15600e5fd4539b9bed3247ef6df12a28

最後の文字列がトークンになります

swarm マスタ用のコンテナホストの作成

まずは swarm クラスタ内でマスタとなるコンテナホストを作成します

  • docker-machine create --driver virtualbox --swarm --swarm-master --swarm-discovery token://15600e5fd4539b9bed3247ef6df12a28 swarm-manager

先ほどのトークンを付与してコンテナホストを作成します
名前は swarm-manager にしました

  • docker-machine ls
NAME            ACTIVE   DRIVER       STATE     URL                         SWARM                    DOCKER        ERRORS
dev             *        virtualbox   Running   tcp://192.168.99.100:2376                            v17.09.0-ce   
swarm-manager   -        virtualbox   Running   tcp://192.168.99.101:2376   swarm-manager (master)   v17.09.0-ce   

こんな感じで作成されました
SWARM の欄に (master) が付与されているのがわかると思います

swarm 用のノードを追加する

マスタノードが追加できたら通常のノードの追加してスケールさせてみましょう

  • docker-machine create --driver virtualbox --swarm --swarm-discovery token://15600e5fd4539b9bed3247ef6df12a28 node1

これで node1 というコンテナホストが swarm クラスタに追加されました

  • docker-machine ls
NAME            ACTIVE   DRIVER       STATE     URL                         SWARM                    DOCKER        ERRORS
dev             *        virtualbox   Running   tcp://192.168.99.100:2376                            v17.09.0-ce   
node1           -        virtualbox   Running   tcp://192.168.99.102:2376   swarm-manager            v17.09.0-ce   
swarm-manager   -        virtualbox   Running   tcp://192.168.99.101:2376   swarm-manager (master)   v17.09.0-ce   

コンテナを作成してみる

では swarm クラスタ上にコンテナを作成してみます
docker コマンドは master に対して行います
--swarm オプションを付けて env を eval します

  • eval "$(docker-machine env --swarm swarm-manager)"

クラスタ内に同一ポートで LISTEN する複数の nginx を起動してみましょう
そして後で気がついたのですがクラスタ上のコンテナホストが pull している間はプログレスバーが表示されないのでプロンプトが返ってこないときは少し待ちましょう

  • docker run -d -p 80:80 nginx

本来なら 80 ポートは 1 つしか LISTEN できませんがクラスタ構成を組んでいるため複数の 80 ポートでコンテナを立ち上げても問題ありません

  • docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                     NAMES
667ee2d80055        nginx               "nginx -g 'daemon ..."   29 seconds ago      Up 28 seconds       192.168.99.102:80->80/tcp                 swarm-manager/hungry_jepsen
14a25c2c6a10        nginx               "nginx -g 'daemon ..."   12 minutes ago      Up 12 minutes       192.168.99.101:80->80/tcp                 node1/focused_shirley
b7a6149eaaab        swarm:latest        "/swarm join --adv..."   20 minutes ago      Up 20 minutes       2375/tcp                                  swarm-manager/swarm-agent
508de153df38        swarm:latest        "/swarm manage --t..."   21 minutes ago      Up 21 minutes       2375/tcp, 192.168.99.102:3376->3376/tcp   swarm-manager/swarm-agent-master
5ad4d9075986        swarm:latest        "/swarm join --adv..."   25 minutes ago      Up 25 minutes       2375/tcp                                  node1/swarm-agent

ただ、今回の場合クラスタ内のコンテナホストは 2 台しかないのでもう 1 つ 80 ポートで LISTEN するコンテナを立ち上げようとするとエラーとなります

docker: Error response from daemon: Unable to find a node that satisfies the following conditions 
[port 80 (Bridge mode)].
See 'docker run --help'.

最後に

VirtualBox で docker swarm を試してみました

かつては consul or etcd など KVS が必要だったのですが現在では不要です
代わりにトークンを使って swarm を管理しています
もちろん etcd or consul or zookeeper などの KVS を使って swarm を管理することも可能です

swarm create したコンテナはクラスタ構築後には不要なので rm して問題ないです
ちなみに swarm create したコンテナホストも削除して問題ないです
swarm コマンドを後々叩くのであればとっておいても良いかと思います (failover の設定など)
swarm コマンドは swarm-master 上でも叩けます (docker run swarm list token://15600e5fd4539b9bed3247ef6df12a28)

master ではないコンテナホストが再起動すると内部で動いている swarm-agent 用のコンテナは自動起動しませんでした
なので、コンテナホストが再起動した場合 swarm-agent コンテナは手動で起動する必要があります

docker swarm の failover については別途いろいろと設定が必要になるようです
今回の記事の内容では触れていないので興味があればこちらをご覧ください

今回のように複数のホストをまたがってコンテナを動作させる場合コンテナのロードバランシングも必要になります
コンテナホスト側の IP のバランシングも必要ですが、クラスタ内のコンテナのバランシングも必要になります
docker swarm には service 機能を使った Ingress Load balancing という標準の機能もあります

とまぁ一重に docker swarm と言ってもいろいろと考えることは多いです

次回は docker swarm 上で overlay ネットワークを作成して別ホストにあるコンテナ同士で直接通信させてみたいと思います

参考サイト

2017年10月5日木曜日

VirtualBox 上で docker-machine を使ってみた

概要

VirtualBox 上で docker-machine コマンドを試してみました
事前に VirtualBox および docker for Mac のインストールを行っておいてください

環境

  • macOS X 10.12.6
  • docker 17.09.0-ce
  • docker-machine 0.12.2
  • VirtualBox 5.1.26 r117224 (Qt5.6.2)

コンテナホストの作成

docker-machine には VirtualBox 用のドライバありこれを使うことで簡単にコンテナホストを作成することができます

  • docker-machine create --driver virtualbox dev
Creating CA: /Users/hawksnowlog/.docker/machine/certs/ca.pem
Creating client certificate: /Users/hawksnowlog/.docker/machine/certs/cert.pem
Running pre-create checks...
(dev) Image cache directory does not exist, creating it at /Users/hawksnowlog/.docker/machine/cache...
(dev) No default Boot2Docker ISO found locally, downloading the latest release...
(dev) Latest release for github.com/boot2docker/boot2docker is v17.09.0-ce
(dev) Downloading /Users/hawksnowlog/.docker/machine/cache/boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v17.09.0-ce/boot2docker.iso...
(dev) 0%....10%....20%....30%....40%....50%....60%....70%....80%....90%....100%
Creating machine...
(dev) Copying /Users/hawksnowlog/.docker/machine/cache/boot2docker.iso to /Users/hawksnowlog/.docker/machine/machines/dev/boot2docker.iso...
(dev) Creating VirtualBox VM...
(dev) Creating SSH key...
(dev) Starting the VM...
(dev) Check network to re-create if needed...
(dev) Found a new host-only adapter: "vboxnet1"
(dev) Waiting for an IP...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env dev

作成できたら確認してみましょう

  • docker-machine ls
NAME   ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
dev    -        virtualbox   Running   tcp://192.168.99.100:2376           v17.09.0-ce

ホストオンリーアダプタ (vboxnet1) を自動で追加します
起動は boot2docker.iso を使って ISO からブートしています

VirtualBox を起動して GUI で確認することもできます
docker_machine_with_vb1.png

作成したコンテナホストでコンテナを起動してみる

ではコンテナを作成してみます
まず docker コマンドを対象のホストに対して実行できるように設定を読み込みます

  • eval $(docker-machine env dev)

これで dev コンテナホストに対して docker コマンドを投げられるようになりました

  • docker run -d -p 80:80 nginx

で dev コンテナホスト上にコンテナが作成されます
先ほど docker-machine ls で確認できた IP の 80 番にアクセスしてみましょう

これで nginx のデフォルトのページが確認できると思います
ローカルではなく作成したコンテナホスト上でコンテナが起動しています

その他

コンテナホストの停止
停止後に ls を実行すると Stopped になっています

  • docker-machine stop dev

コンテナホストの起動
--restart=always でコンテナを作成していればコンテナホストの起動後でもコンテナが自動起動します

  • docker-machine start dev

SSH ログイン
直接コンテナホストに入って docker コマンドを実行できます

  • docker-machine ssh dev

最後に

VirtualBox 上で docker-machine を使ってコンテナホストを作成してみました
これを応用すれば docker swarm も簡単にできます
VirtualBox + docker swarm の検証もそのうち紹介できればと思います

参考サイト