More Related Content
Similar to はてなにおける継続的デプロイメントの現状と Docker の導入 (20)
More from Yu Nobuoka (11)
はてなにおける継続的デプロイメントの現状と Docker の導入
- 10. 参考: Mackerel の話 (Jenkins の話も少し)
https://speakerdeck.com/hakobe/scala-in-perl-company
- 11. 各サービスと Jenkins
● それぞれのサービスで Jenkins を活用
● 昔: master/slave 構成の Jenkins 1 組
● → 最近はサービスごとに Jenkins を用意
● サービスごとに異なる環境
– あるサービス用に変更を加えると別のサービス
のテストが動かなくなる、とか
● 関係者が少ない方がメンテナンスしやすい
- 12. なんのための Jenkins か
● ソフトウェア進化を継続するため
– はてなダイアリーは 10 年超
– はてなブックマークは 10 年
● テスト、ビルド、デプロイ
● 意識しなくてもテストが実行される環境
● 面倒な手順の自動化
- 13. 特にテスト
● 開発時は各自のマシンで
– OS X、Linux、Windows
● 開発者のマシン上ではテストに通っても実際
の環境では動かない可能性
● → 本番に近い環境でのテスト実行
● 面倒なのでいちいち全テスト実行しない
● → 自動でのテスト実行
- 15. Jenkins の管理
● Chef で Jenkins の環境を構築
– 本番サーバーも Chef で構築
● Jenkins 自体だけでなく、各プロジェクトのビ
ルドやテストに必要なコマンドやホストの設
定も Chef で行う
● 本番サーバーと同等の環境を実現
- 16. Jenkins 使用の方針
● Jenkins の設定を複雑にしない
– 秘伝のタレ問題
– コマンド一つで処理を実行できるように
– 環境準備とかも
● 例 : 処理の内容は Shell スクリプトファイル
に記述してプロジェクトのリポジトリに入れる
- 17. スマートフォンアプリと Jenkins
● Android アプリ → Gradle が標準になりビ
ルドやテストの自動化がしやすく
● Jenkins 上でのテスト実行
– Android Emulator Plugin
– Android SDK は用意してくれる
– 必要なコンポーネントは? → Gradle プラグイ
ンでインストール可能!
● iOS アプリも含め、これからという段階
- 24. フロントエンド
● HTML は生
● TypeScript
– TypeScript → JS → minified JS
– ビルドプロセスが必要 (開発者の手元 + Jenkins)
● LESS
– LESS → CSS
– ビルドプロセスが必要 (開発者の手元)
- 25. ビルドツールやデプロイツール
● ビルドツール: gulp (Node.js)
– TS → JS や LESS → CSS
– JS テスト実行
– 静的ファイルにダイジェストハッシュ付与
● デプロイ: Capistrano 3 (Ruby)
● バージョン管理: Git
– 中央リポジトリは GitHub;Enterprise
- 26. 開発に用いるツール
● はてなグループ : 日記 + Wiki システム
– ドキュメント管理
● Slack : チャットツール
● Trello : タスク管理
● GitHub;Enterprise : コード管理 (レビュー
等)
● Jenkins
- 27. 開発プロセス概要
● スクラム、2 週間 1 スプリント
● リリースは毎週
– 自社サービスではないのでどんどん出すという
感じではない
– だが、常に最新の機能をリリースできる状態を
保つ
● 今回はタスク管理などにはあまり触れずに
開発者目線で
- 29. ブランチモデル
● master ブランチ
– 本番反映対象
● staging 系列ブランチ (例: staging-20150101-000000)
– 本番反映ごとに別ブランチ名で毎回作成
● devel ブランチ
– リリース可能なものをマージ
● features
– 開発ブランチ
- 33. pull request を作成
● 開発中に立てるかどうかは任意
– コードレビュー時には必須
● 開発中の様子が見えやすい
● 開発中のコードについて議論しやすい
● Jenkins によるテストの結果の可視化
- 34. 開発時の Jenkins の役割
● Push されるごとにライブラリ更新、JS minify
– 必要な場合のみ
– 結果をコミット
● Push されるごとにテストを実行
– 失敗時には通知する
– Slack、GH;E
● 動作確認のために開発用ホストにデプロイ
(Docker 使用、後述)
- 35. Push されるごとにビルド実行
● Jenkins の GitHub Plugin
● GH;E の Server Hook
● 処理内容は script/jenkins.sh に記述
– Static ファイルの変換処理 → コミット、or
– テスト実行 (Perl、JS)
- 36. GH;E のコミットへの通知
● Shell スクリプトの中に記述
– ブクマなどでは通知用ジョブを下流に用意
curl -X POST -H "Authorization: token $token"
https://github-
enterprise.example.com/api/v3/repos/example/Exa
mple-Project/statuses/$git_head -d "{
"state": "success",
"target_url": "${BUILD_URL}",
"description": "The build has succeeded."
}"
- 38. 良いところと課題
● ○ push したら自動でテスト実行
● ○ 失敗時の通知がされる
– × Slack と GH;E だけなので弱い → XFD?
– × GH;E への通知がビルド処理の中にある
● ○ ファイルの変更結果をコミット
● × ファイル変更とテスト実行が同じ Shell ス
クリプトになっていて管理しづらい
● ○ コマンド 1 つで確認用にデプロイ
- 45. 本番リリース用 pull request 作成
● Staging 系列のブランチを作成して master
ブランチに向けた pull request を作成
– ブランチ作成、pull request 作成をコマンド 1
つで実行
● Staging 系列ブランチを staging 環境にデ
プロイして動作確認
– デプロイは Capistrano 3
- 50. 良いところと課題
● ○ 本番リリース用 pull request をコマンド
1 つで作成できる
● ○ デプロイもコマンド 1 つ
● × staging 環境へのデプロイが自動化され
ていない
- 53. 今後: Jenkins Workflow Plugin 検討
● 2014 年 12 月にバージョン 1.0 リリース
● Scripted control flow
– Shell スクリプトに書いてあることを Workflow
Plugin のスクリプトに置きかえる
● Pause and resume execution
– ユーザーとのインタラクションの機能もあるので
デプロイ処理を Jenkins に乗せやすい
- 64. 既存の方法 (はてなブックマークなど)
● 開発用サーバで複数アプリケーション起動
● 別ポート番号を使用 (or Unix ドメインソケット)
● ポート番号解決 : Nginx 上の Lua で
https://{branch-name}.dev.example.com/ → {ポート 番号}
開発用 proxy
Nginx
開発用サーバー
Nginx
アプリケーション
アプリケーション
アプリケーション
ポート番号
解決
- 67. Docker Engine とは?
● コンテナ型の仮想化技術
– 環境を分離するという目的に適す
● ゲストの状態を Docker イメージとしてバー
ジョン管理
● Dockerfile にビルド処理を記述して
Docker イメージをビルド
● Docker イメージをもとに Docker コンテナ
内でアプリケーションを動作させる
- 70. Docker コンテナを用いた確認環境
● 開発用サーバで複数 Docker コンテナ起動
● 別ポート番号を使用
● ポート番号解決 : Docker API を使用
https://{branch-name}.dev.example.com/ → {ポート 番号}
開発用 proxy
Nginx
開発用サーバー
Proxy 用 Plack
アプリケーション
Docker コンテナ
Docker コンテナ
Docker コンテナ
Docker API
ポート番号解決ポート番号解決
- 71. Docker API を用いたポート番号解決
● ホスト側のポート番号が適当に割り当て
– コンテナ内の web アプリケーションは 80 番
ポートをリッスン
– Docker コンテナは 80 番を EXPOSE
● 各ブランチからイメージをビルドする際、ブラ
ンチ名に対応したタグをイメージに付ける
● ホスト名からブランチ名を抽出 → Docker
API により対応するタグ名のイメージのコン
テナを探す → ポート番号取得
- 72. Docker API を叩くコードの例
my $furl = Furl->new();
my $uri = do {
local $_ = $docker_remote_api->clone;
$_->path('/containers/json');
$_;
};
my $body = decode_json $furl->get($uri)->content };
(grep { $_->{Image} eq "$host:latest" } @$body)[0];
- 74. Dockerfile を準備して docker build
● ライブラリ等インストール → プロジェクトの
ファイルコピー → コマンド登録
FROM debian:stable
# (略)
# config/setup.sh は本番サーバー構築時にも使用される初期化スクリプト。
COPY script/setup.sh /app/shared/script/setup.sh
RUN sh /app/shared/script/setup.sh
# (略)
# Source
RUN mkdir -p /app/src
COPY . /app/src
# (略)
WORKDIR /app/src
EXPOSE 80
CMD ["supervisord", "-c", "/app/src/config/docker/webapp/supervisord.conf"]
- 77. # config/setup.sh は本番サーバー構築時にも使用される
# 初期化スクリプト。
COPY script/setup.sh /app/shared/script/setup.sh
RUN sh /app/shared/script/setup.sh
# CPAN Modules
RUN mkdir -p /app/shared/carton
WORKDIR /app/shared/carton
COPY cpanfile /app/shared/carton/cpanfile
COPY cpanfile.snapshot /app/shared/carton/cpanfile.snapshot
RUN carton install --deployment
- 79. Jenkins 上でのビルドとデプロイ
● Jenkins 上で
– docker build
– docker rm -f : 同じブランチのコンテナを止める
– docker run
● 実際のコマンドは rake タスクにしてある
– ブランチ名 → タグ名変換処理
– 同じブランチの古いコンテナが動いてるか調査
– Shell スクリプトより Ruby の方が書きやすい
- 81. ビルド開始方法
● 現在は手動でビルド開始
– Jenkins API 叩く or Web UI から
– 対象ブランチをパラメータで受け取り
● 本来は次のようにしたい
– devel ブランチへの push で自動的にビルド
– 既に devhost が立っているブランチへの push
で自動的にビルド
- 83. なぜ Jenkins でビルドするのか
● 同じ環境でビルド処理を行わせたい
● ビルドの管理
● 変遷
– Capistrano などで直接開発用サーバー上で
ビルド → 複数人が同時に使うと破滅
– Docker API を使う → キャッシュが効きづらく
て困る
- 84. 今後
● devel ブランチの自動デプロイ
● Pull request との関連付けを強める
– コメントで新規 devhost 作成 (?)
– close 時に自動で devhost 破棄
– 破棄が結構面倒なので自動化したい
● ビルド後にコンテナ内でテストしてそれから
デプロイ
- 85. 小ネタ: 確認環境用の favicon
● ローカルホスト上の web アプリケーションや
確認用の web アプリケーション
● 本番と確認用を間違えたりしてしまう
● Favicon を変えることでタブで識別しやすく
- 88. はてなにおける Jenkins
● GH;E への push に応じたテスト自動実行
や確認用ホストへのデプロイなど
● 開発プロセスの中でビルドやテストの実行を
指揮する大切な役割を果たしている
– 少年ジャンプルーキーでの例を紹介
● Jenkins で Docker ビルドしてデプロイする
という仕組みで手軽に確認環境を用意