読者です 読者をやめる 読者になる 読者になる

新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。気づけば社会人3年目に突入。

学習記録:Docker

参考文献

Dockerエキスパート養成読本[活用の基礎と実践ノウハウ満載!] (Software Design plus)

Dockerエキスパート養成読本[活用の基礎と実践ノウハウ満載!] (Software Design plus)

Kubernetes実践入門

Kubernetesの役割

Dockerは便利だが,クラウド上で少し大きな分散システムを動かすにはまだ課題が多い。
以下にそのようなシステムにおけるKubernetesの役割を示す。

フェールオーバー

Webアプリケーションサーバのコンテナが異常終了した場合,それを検知してコンテナを再起動したい。
更に言えば,あるホストが故障したらそこで動いていたモジュールはすべてほかのホストで再起動させたい。
Kubernetesは個々のコンテナを監視し,コンテナが停止した場合には再起動を試みる。

レプリケーションとスケーリング

フロントエンドのWebサーバは,同じイメージから複数コンテナを起動させて稼働させたい。
同じ種類のコンテナを複数起動し,エラーを検出して必要な数のコンテナを起動するようにするのは少し面倒である。
Kubernetesでは,コンテナの複製数を宣言的に記述すると後の面倒は見てくれる。

スケジューリング

多くのコンテナを多くのホストで動かすとき,個々のコンテナをどのホストで動かすかの割り振りも自動化したい。
Kubernetesでは,特定のホストに負荷が偏らないようコンテナを割り振ってくれる。
また,ホストにラベルを指定することでこのコンテナはこのラベルのついたホストで動かすといった制約も付けられる。

ロードバランス

外部からのWebアプリケーションサーバへのアクセス,アプリケーションサーバからバックエンドサーバへのアクセスは
複製されたコンテナにロードバランスする必要がある。
Kubernetesにはそのためのロードバランサが備わっている。

サービスディスカバリ

各コンテナは依存するモジュールへの接続方法を知る必要がある。
例えば接続先コンテナのIPを知る必要があるが,フェイルオーバーなどもあり事前にIPを知ることはできない。
Kubernetesでは,仮想IP名と仮想ホスト名を割り当て,そこに接続すれば該当するホストにルーティングされる。

ポート管理・ポート変換

Dockerの機能を用いてコンテナとホストのポートを接続していると,コンテナ間での衝突が発生する可能性がある。
Kubernetesは両者が衝突しないよう自動でポートを割り振り,NAT部分でのポート変換も提供する。
これにより衝突は避けつつも,外部からは両者ともに同じ80版ポートで接続できる。

Kubernetesの基礎

Pod

Podとは,同じホストで動作する必要のあるコンテナの集まりである。
例えば,アプリケーションサーバとそのログを集めるfluentdのコンテナは同じホストで動作させる必要がある。
そうした組をPodと呼び,スケジューリングの単位とする。

Replication Controller

Replication Controllerは,Podを複製する作業を宣言的に記述したものである。
バックエンドモジュールが複製を10個持つ必要がある場合には,
「サイズが10でPodにはバックエンドサーバコンテナが入ったReplication Controller」として表現する。

Service

Serviceは,Podの集合によって実装されるシステム内の特定機能を表す抽象的な単位である。
Serviceにはロードバランサと仮想IPが付属し,仮想IP宛のリクエストはロードバランスされて対応するPodにルーティングされる。

Drone入門

Droneとは

drone.ioが開発しているCIツール
ビルドやテストを自動化し,それらを定期的に実行することで品質を向上させる。
2014年に公開され,現在バージョン0.3。

Droneの特徴

Go言語で開発されており,他のCIツールに比べメモリフットプリントが小さく動作が高速。
また,1つのバイナリとして配布することができインストールが非常に高速である。

最大の特徴は,ビルドやテストを実行する環境にDockerを使用している点である。
ビルドやテストの実行時に新しくDockerコンテナを起動し,その中でビルドやテストを走らせることで,以下のメリットを得ている。

  • クリーンな環境でのビルド・テスト
  • 本番環境と同じ環境でのテスト実行
  • ファイル書き込みなどのテストも安全に実行可能
  • DBを使い捨てにしたテスト実行
  • 環境構築手順がDockerfileとして明確に残る

また,ビルドやテストの定義が.drone.ymlとして明確に残るというメリットもある。
下記の例は,cloujure(JDK7)環境でDBを作った後諸々テストを行い,成果物をDropboxへ送るテストが記述している。

image: mopemope/clojure:jdk7
git:
  path: admin
script:
  - env
  - createdb -h localhost -U postgres -E utf8 --templete=template0 test
  ...
services:
  - postgres
...
publish:
  dropbox:
    access_token: $$DROPBOX_TOKEN
    source: target/admin.jar
    target: /admin.jar
Droneの機能
  • コードホスティングサービスとの連携(イベントによるフック)
  • 処理中のコマンドをWebでリアルタイム表示
  • 処理結果をメールや外部サービスにより通知
  • 作成した成果物や結果をSSHなどで外部配備
  • 複数の Dockerホストへ負荷分散

Droneは特定の言語やテストツールに縛られないため自由度が高い一方で,用途によっては各自で工夫が必要なこともある。
例えば,Droneにはテスト結果をまとめてレポートするUIが存在しない(言語やテストツールで表示を統一できないため)。
テストがすべてOKであるといった通知を受け取ることは簡単だが,結果の詳細やメトリクスを知りたい場合には,
レポートを生成して結果を実行結果画面に表示するか,配布した先で参照するといった工夫が必要になる。

Droneのインストール

Drone自体はDockerizeされており,Dockerコンテナ上にDroneを構築することができる。
インストールに必要な手順は以下。

  • Dockerのインストール
  • Droneのソースの取得
$ git clone git@github.com:drone/drone.git
  • Droneイメージの構築
$ cd drone
$ sudo docker build -t drone/drone .

Droneの設定および起動

DockerによるDroneの起動

Droneコンテナを起動するには,以下のコマンドを実行する。
(Gitlabと連携させる場合の設定)

$ sudo docker run -d -v <PATH>:/var/lib/drone --net=host \
  --name="drone" \
  -e DRONE_SERVER_PORT=:8000 \
  -e DRONE_DATABASE_DATASOURCE=/var/lib/drone/drone.sqlite \
  -e DRONE_WORKER_NODES="tcp://0.0.0.0:2375" \
  -e DRONE_GITLAB_URL="<Your Gitlab URL>" \
  -e DRONE_GITLAB_CLIENT="<Your Gitlab Client ID>" \
  -e DRONE_GITLAB_SECRET="<Your Gitlab Secret Key>"

http://localhost:8000にアクセスして確認できる。

ビルドとテストの実行

リポジトリのアクティベート

Drone上で連携したコードホスティングサービスのリポジトリ一覧を表示し,
使用したいレポジトリを選択してACTIVATE NOWを押下してアクティベートする。
アクティベートが完了すると,pushを待ち受ける状態になるので,
後はビルド・テスト定義である.drone.ymlをリポジトリにコミット/pushすればOK。

ビルドとテスト実行

サンプルのレポジトリを作る。
まず以下のmain.goを記述。

package main

import "fmt"

func Hello(name string) string {
  return fmt.Sptintf("Hello %s !\n", name)
}

func main() {
  s :=  Hello("Drone")
  fmt.Println(s)
}

続いて,main_test.goを記述する。

package main

import "testing"

func TestHello(t *testing.T) {
  s := Hello("Drone")
  e := "Hello Dtone !\n"
  
  if s != e {
    t.Fail()
  }
}

ビルド定義である.drone.ymlを定義する。

image: go1.3
script:
  - go version
  - go test -v
  - go build -v

3つのファイルをコミットし,pushするとDrone上でビルドが実行される。