kakakakakku blog

Weekly Tech Blog: Keep on Learning!

プロダクションレディなマイクロサービスを実装するための標準化を学べる「プロダクションレディマイクロサービス」を読んだ

オライリーから出版されている「プロダクションレディマイクロサービス」を読んだ.「プロダクションレディ」という秀逸なタイトルに惹かれただけじゃなく,章ごとのテーマも非常に惹かれる内容になっていた.仕事でアーキテクチャを考えたり,アーキテクチャレビューを担当する場面も多いけど,ベストプラクティスなアーキテクチャをもっと上手に言語化したいなと思っていて,プロダクションレディなマイクロサービスの標準化を学べる本書に興味を持った.

  • 1章 マイクロサービス
  • 2章 本番対応
  • 3章 安定性と信頼性
  • 4章 スケーラビリティとパフォーマンス
  • 5章 耐障害性と大惨事対応
  • 6章 監視
  • 7章 ドキュメントと組織的な理解
  • 付録A 本番対応のチェックリスト
  • 付録B マイクロサービスの評価基準

プロダクションレディマイクロサービス ―運用に強い本番対応システムの実装と標準化

プロダクションレディマイクロサービス ―運用に強い本番対応システムの実装と標準化

  • 作者: Susan J. Fowler,佐藤直生,長尾高弘
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2017/09/13
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

小さなモノリス

「マイクロサービスアーキテクチャ本」にもモノリスを分割する話が載っていたけど,本書でも「モノリスを分割することが1番難しい」と書かれていた.コンテキストの見極めに失敗すると「モノリスを数個の小さなモノリスに分割するだけ」になってしまうと書かれていて,「小さなモノリス」という失敗パターンの表現は刺さった.確かに「小さなモノリス」って言われたらツライ...!

マイクロサービスアーキテクチャ

マイクロサービスアーキテクチャ

逆コンウェイの法則

マイクロサービスの文脈でよく聞く「コンウェイの法則」に対して,本書では「逆コンウェイの法則」というパワーワードが出てきた.意味としては,マイクロサービスを積極的に採用していくと,必然的に独立した小さなチームが多くできるということだけど,さらに「逆コンウェイの法則」は組織構造だけじゃなく,個々のエンジニアにも当てはまるという話が興味深かった.ようするに,担当するマイクロサービスに特化した責任とドメイン知識が強まるため,全体を把握したエンジニアがいなく「集合的に全体を把握する」ことになるということだった.良し悪しを決めるというよりは,法則の納得感があるところが良かった.

インシデント発生時の「緩和」と「フォローアップ」

インシデント(障害)発生時には,以下の5種類の段階があり,モノリスと比較するとマイクロサービスだと「調整」「フォローアップ」が必要になるという話だった.個人的には「緩和」「フォローアップ」の重要さがまとまっているのが素晴らしいと感じた.

  • 評価
  • 調整
  • 緩和
  • 解決
  • フォローアップ

「緩和」というのは「インシデントの影響を小さくする」ことを意味していて,インシデント発生時にすぐバグを直すのではなく,まずはユーザー影響を考えるべきと言い換えることができる.サービスを運用していて「インシデント対応が上手だな」と感じる人は緩和が上手だと思うし,SIer 時代から意識するようにしている.個人的には「緩和」という言葉が定義されていることに意味があるので,仕事でも積極的に使っていこうと思う.また,3章では「ホットフィックスはアンチパターン」という話もあり,すぐに直すのではなく,まずは安定バージョンに切り戻すことで「緩和」できるということにも繋がる.

「フォローアップ」は SRE の文脈で出てくる「ポストモーテム」と同じだった.仕事でも最近はポストモーテムを書くようにしていて,重要なのは「インシデントから学ぶ」姿勢と言える.

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

  • 作者: 澤田武男,関根達夫,細川一茂,矢吹大輔,Betsy Beyer,Chris Jones,Jennifer Petoff,Niall Richard Murphy,Sky株式会社玉川竜司
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2017/08/12
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (1件) を見る

オンコールローテーションの定義

マイクロサービスの監視には4種類の構成要素があり,ポイントがまとまっていた.内容的にはマイクロサービスに特化しているようには感じなくて,モノリスでもサービスを運用する上で重要な話だった.

  • ロギング
  • ダッシュボード
  • アラート
  • オンコールローテーション

その中でも「オンコールローテーション」はマイクロサービスだと特に設計が難しそうで,定義が載っているのは参考になった.よくあるのが「1番詳しい人が常にオンコールを受けている状態」だったりするので,マイクロサービスでも,モノリスでも,サービスを運用する前にオンコールローテーションは決めておくべきだと感じた.個人的には,オンコールローテーションを運用しているチームも,運用していないチームも経験があるけど,やはりオンコールローテーションという責任が明確に与えられている方が良かった.

  • 1度にオンコールを受けるのは2名以上
  • オンコールシフトは1週間未満
  • 次のオンコールシフトまで1ヶ月以上の間隔を空ける

マイクロサービスのドキュメント

7章に「リポジトリの README もコードコメントもドキュメントではない」という話があり,刺さった.目指す方向性としては,全てのマイクロサービスのドキュメントが一箇所に集まっていることが重要とのことだった.そして,マイクロサービスのドキュメントとして,まとめるべき項目が整理されているのが目から鱗だった.確かにここまで書けば,包括的で実用的なドキュメントになりそう.特に「オンコールランブック(インシデント発生時の対応方法)」「FAQ(よく聞かれることならなんでも)」は,めちゃめちゃ良かった.

  • 説明
  • アーキテクチャ図
  • 連絡先とオンコール情報
  • リンク
  • オンボーディング/開発ガイド
  • リクエストフロー/エンドポイント/依存関係
  • オンコールランブック
  • FAQ

まとめ

「付録A 本番対応のチェックリスト」も便利で,今回記事にまとめたところ以外にも学びが多く,マイクロサービスを作る前に必読な良書だった.標準化として満たすべき項目が非常に多く「お前のマイクロサービスはマイクロサービスじゃねぇ!」と叱咤激励されているような気分にもなり,気持ちが引き締まる思いだった(笑)

また,マイクロサービスに特化しすぎていなく,モノリスだとしても,サービスを運用するときに必要なポイントがうまく言語化されているのが良かった.オススメ!

f:id:kakku22:20180517011305j:plain

(今回も付箋だらけになった...!)

関連記事

やはり「マイクロサービスアーキテクチャ本」と合わせて読んだり,「マイクロサービスアーキテクチャ本」の筆者 Sam Newman の登壇動画を合わせて見ると,より理解が深まると思う.

www.youtube.com

kakakakakku.hatenablog.com

シェルスクリプトのテストフレームワーク Bats を試してみた

シェルスクリプトのテストフレームワーク Bats を試してみた.

github.com

たまにコントリビュートをしている Amazon ECS (Elastic Container Service) のデプロイツール ecs-deploy のテストコードで Bats が使われているので,少し書いたことがあり,もっと詳しく調べてみようと思った.

github.com

Bats は現在もメンテナンスされている

もともとの Bats は sstephenson/bats にあり,現在は bats-core/bats-core に移っている.以下の Issue などを読むと,コミュニティの動きがわかる.

github.com

github.com

インストール

Bats は様々なインストール方法がある.まず,用意されている install.sh を試してみた.

$ git clone git@github.com:bats-core/bats-core.git
$ cd bats-core
$ sudo ./install.sh /usr/local
$ which bats
/usr/local/bin/bats

Mac の場合は brew でもインストールできる.

$ brew install bats

他にも,サードパーティだけど,npm でもインストールできる.

www.npmjs.com

サンプルコード

まず,README に以下のサンプルコード addition.bats が載っているので実行してみた.テストコードとしては bc で加算をするテストと,dc で逆ポーランド記法の計算をするテストコードが書かれている.

#!/usr/bin/env bats

@test "addition using bc" {
  result="$(echo 2+2 | bc)"
  [ "$result" -eq 4 ]
}

@test "addition using dc" {
  result="$(echo 2 2+p | dc)"
  [ "$result" -eq 4 ]
}

実行をすると,以下のような出力となる.なお,ターミナルで実行する場合は --pretty オプションがデフォルトになっている.

$ bats addition.bats
 ✓ addition using bc
 ✓ addition using dc

2 tests, 0 failures

テストがエラーになると,以下のような出力となる.

$ bats echo.bats
 ✗ echo
   (in test file echo.bats, line 5)
     `[ "${result}" -eq 1000 ]' failed

1 test, 1 failure

--tap オプションを付けると,TAP (Test Anything Protocol) フォーマットで出力される.TAP は今まで聞いたことがなかった.

$ bats --tap addition.bats
1..2
ok 1 addition using bc
ok 2 addition using dc

なお,複数の Bats を実行することもできる.

$ bats *.bats
 ✓ addition using bc
 ✓ addition using dc
 ✓ addition using bc
 ✓ addition using dc

4 tests, 0 failures

setup と teardown

多くのテストフレームワークで使える setupteardown も用意されている(テスト群の最初と最後にフックする).以下のように関数を定義して使う.

#!/usr/bin/env bats

setup() {
  touch bats.log
}

teardown() {
  rm bats.log
}

@test "echo with setup and teardown" {
  result="$(echo 100)"
  [ "${result}" -eq 100 ]
}

関数をテストする

Bats の実行方法がわかったので,次は functions.sh を用意して,引数に渡した文字列を大文字に変換する関数を実装した.

#!/bin/sh

#######################################
# 大文字に変換する
# Arguments:
#   $1 WORD
#######################################
upper_case() {
  echo $1 | tr '[:lower:]' '[:upper:]'
}

Bats は以下のようになる.関数をテストするので setupfunctions.sh を読み込み,Bats の run で関数を呼び出している.

#!/usr/bin/env bats

setup() {
  . functions.sh
}

@test "upper case for ruby" {
  run upper_case ruby
  [ "${status}" -eq 0 ]
  [ "${output}" == "RUBY" ]
}

run の結果は Bats の組み込み変数に入るため,これらをテスト結果として使う.

  • ${status} ... ステータスコード
  • ${output} ... 出力結果
  • ${lines} ... 出力結果(配列)
bats functions.bats
 ✓ upper case for ruby

1 test, 0 failures

Dockerized とは相性が悪そう

CircleCI 2.0 でテストを実行しようと思って,Bats を Dockerized したけど(Alpine と Amazon Linux),Bats を実行するコンテナにライブラリなどが必要になるため,例えば Bats のサンプルコードだと bcdc も入ってなく,エラーになる.ecs-deploy では,必要なライブラリを Dockerfile でインストールしている.

 ✗ addition using bc
   (in test file app/addition.bats, line 4)
     `result="$(echo 2+2 | bc)"' failed with status 127
   /tmp/bats.36.src: line 4: bc: command not found
 ✗ addition using dc
   (in test file app/addition.bats, line 9)
     `result="$(echo 2 2+p | dc)"' failed with status 127
   /tmp/bats.36.src: line 9: dc: command not found

2 tests, 2 failures

試しに Dockerized Bats を使って CircleCI 2.0 でテストできるようにしてみた.ただしこれは,ライブラリに依存しない状態で動いているので,参考程度という感じ.

github.com

まとめ

  • シェルスクリプトのテストフレームワーク Bats を試してみた
  • 運用系でシェルスクリプトを使う場面はまだまだあると思うので,テストコードが書けるとメンテナンスしやすくなる
  • シェルスクリプトの関数ごとにテストを書けるので,そこそこ柔軟にテストコードが書けそう

最新バージョン Redash v4 に対応した「Redash ハンズオン資料」を作った

正式に Redash v4 がリリースされた 🎉🎉🎉

Redash v4 とは?

正確に言うと,4月16日に v4.0.0 がリリースされて,5月2日に v4.0.1 がリリースされた.なお v4.0.1 は「アップグレード推奨」となっている.そして Redash v4 で改善/変更されたポイントは Redash 作者 @arikfr の記事にも,Redash の Change Log にも書かれている.特に「UI/UX が全て見直された点」「ダッシュボードのレイアウトを自由に変更できるようになった点」は良かった.さらに今後の展望として「ユーザーアカウントの無効機能」と「クエリの管理機能」と「パーミッションの改善」を予定していることも書かれていた.

blog.redash.io

また,今回の UI/UX 見直しをリードした Redash コントリビューター @kocsmy の記事には,UI/UX デザイナーとして,どのように Redash を改善したのかがまとまっていて,とにかく素晴らしい記事だった.

  • Redash のデザインが統一されていなかった
  • リーンな手法でステップバイステップに再設計をした
  • フォームのデザインを改善した
  • システムフォントを使うようにした
  • ナビゲーションを目立たないようにした
  • クエリエディタのデザインを再設計した
  • ダッシュボードのレイアウトを自由に変更できるようにした
  • などなど

blog.redash.io

Redash ハンズオン資料

去年に公開した「Redash ハンズオン資料」は,作成時に最新のメジャーバージョンだった Redash v2 をベースにしていた.できる限り,メジャーバージョンに追随したいと考えていたので,正式に Redash v4 がリリースされたら,ハンズオン資料を更新する計画を立てていた.

kakakakakku.hatenablog.com

Redash ハンズオン資料 v4 対応

そして今日「Redash ハンズオン資料 v4 対応」をリリースした 🎉🎉🎉

ハンズオン内容は大きく変えてなく,Redash v4 で改善/変更されたポイントを反映した.例えば「データソースの選択/日付フォーマットの設定/ナビバーの操作/クエリ作成/ダッシュボード作成」など.そして全てのスクリーンキャプチャを取り直した.Redash v4 をすぐに試せるので,興味があれば是非使ってもらえると!なお,今までの Redash v2 対応のハンズオン資料は GitHub のタグ v2.0.1 を切っているので,そこから確認することができる.

github.com

おまけ : コントリビューター

本当に少しのコントリビュートだけど,Redash v4 のコントリビューターに写真が載っていて,嬉しすぎる!

まとめ

Redash v4 に対応した「Redash ハンズオン資料」を使ってもらえるとー 👍

Vue School の無料コース「Vue.js + Firebase Realtime Database」を受講してチャットアプリケーションを実装した

今まで使う機会がなかった Firebase Realtime Database を学びたかったので(今後は Cloud Firestore 中心になりそうだけど),Vue School が公開している無料コース「Vue.js + Firebase Realtime Database」を受講して,Vue.js と Firebase Realtime Database を使ったチャットアプリケーションを実装してみた.動画を見ながら写経するとしても,2時間あれば終わるので,ちょっとしたスキマ時間に学ぶこともできる.Vue.js 初学者と Firebase Realtime Database 初学者にオススメのコースだった.

vueschool.io

Vue.js + Firebase Realtime Database

コースは計8個の動画で構成されている.どの動画もトピックごとに短くまとまっているので,振り返りながら進むことができた.

  • Firebase Introduction
    • What is Firebase and Why is it so Great? ⏲ 2:06
    • Meet Firebase Realtime Database ⏲ 3:06
  • Firebase Actions
    • Read Data from Firebase with Vue.js ⏲ 6:40
    • Write Data to Firebase with Vue.js ⏲ 5:37
    • Delete Data from Firebase with Vue.js ⏲ 4:02
    • Update Data from Firebase with Vue.js ⏲ 7:30
  • Extras
    • Update Multiple References at Once ⏲ 1:23
    • Display Notifications when Things Happen ⏲ 3:36

なお,以下のように英語字幕が出るので,英語が苦手な人でも,問題なく受講できると思う.

f:id:kakku22:20180509135534p:plain

(受講画面例)

実装したチャットアプリケーション

以下のチャットアプリケーションを実装した.

  • メッセージを「送信/編集/削除」することができる
  • 画面をリロードせず,リアルタイムにデータの変更を反映することができる
  • データの変更時にトースト UI で通知することができる

f:id:kakku22:20180509135545p:plain

(実装したチャットアプリケーションの画面)

What is Firebase and Why is it so Great?

  • Firebase Realtime Database のことを Firebase と呼ぶ人もいるけど,他にも多くの機能がある
  • Firebase Realtime Database は NoSQL データベースで,リアルタイムにデータを同期することができる
  • 無料枠で使える

Meet Firebase Realtime Database

Firebase プロジェクト「Vue School Chat Room」を新規作成し,Firebase Realtime Database を作成した.コンソール上で自由にデータを変更することができて,さらにデータは JSON として「インポート/エクスポート」することもできる.今回インポートするサンプル JSON は GitHub に公開されているので,先に git clone をしておくと良いと思う.

github.com

f:id:kakku22:20180509135607p:plain

(プロジェクト新規作成)

f:id:kakku22:20180509135615p:plain

(Firebase Realtime Database コンソール)

なお,今回は検証のため,Firebase Realtime Database のフル権限を許可する流れになっていた.ただし,プロダクション環境で使う場合は Firebase Authentication と連携する必要がある.

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

Read Data from Firebase with Vue.js

まず,Firebase ウェブアプリを新規作成した.次に GitHub に公開されている index.html を取得する.ただし,master ブランチだと完成形の index.html になっているので,写経しながら進める場合は,コミット履歴から1番最初に戻す.

$ git checkout eff91892b1143e2d8e65fba5017f9e7bce24c032 index.html

以下のように,簡単に Firebase Realtime Database に接続できる.

const database = firebase.database()

以下の実装では messages に対して value イベントを取得して console.log に出力をしている.function をアロー関数を使って書き直しているところも良かった.なお,常にデータを同期しているので,コンソール上でデータを変更すると,すぐに console.log に出力される.

database.ref('messages').on('value', snapshot => console.log(snapshot.val()))

他にも child_addedchild_changed など,Firebase Realtime Database のイベントがある.

database.ref('messages').on('child_added', snapshot => console.log(snapshot.val()))

Write Data to Firebase with Vue.js

以下のように .push を使うと,キーを追加することができる.

methods: {
  storeMessage () {
    messagesRef.push({text: this.messageText, nickname: this.nickname})
    this.messageText = ''
  }
},

また,キーは以下のように変数にしておくと DRY に実装できるので,途中にリファクタリングが含まれていた.

const messagesRef = database.ref('messages')

他にも .set を使うと,新規キーを追加することができる.直接 / 区切りで書くこともできるし,階層ごとに .child を使って書くこともできる.

database.ref('who/am/I').set('alex')
database.ref('who').child('am').child('i').set('not alex')

f:id:kakku22:20180509135703p:plain

(新規キーを追加した画面)

Delete Data from Firebase with Vue.js

キーは id を指定して .remove で削除することができる.そして,メッセージごとに id を識別するため,created で id に snapshot.key を指定しておく.

created () {
  messagesRef.on('child_added', snapshot => this.messages.push({...snapshot.val(), id: snapshot.key}))
}

すると,以下のように削除メソッドを実装することができる.

deleteMessage (message) {
  messagesRef.child(message.id).remove()
}

Update Data from Firebase with Vue.js

以下のようにキーを更新する..update は特定のキーの値を更新し,.set は特定のキーを全て書き換える.なお,現在はフル権限を与えているので,Chrome DevTools からキーを更新することもできる.

database.ref('messages').child('-L8HkVXx_jUWUXDIVDlR').update({text: 'updated message!'})
database.ref('messages').child('-L8HkVXx_jUWUXDIVDlR').set({text: 'updated message!'})
database.ref('messages').child('-L8HkVXx_jUWUXDIVDlR').child('text').set('updated message!')

また,メッセージの編集中は UI を変更するため,影響のある箇所に v-ifv-else を追加した.編集中は以下のような画面になる.

f:id:kakku22:20180509141155p:plain

(編集中の画面)

Update Multiple References at Once

Firebase Realtime Database で,複数キーをバルクで(トランザクションを有効にして)追加することができる.今回のアプリケーションでは使っていないけど,参考情報として学んだ.

const payload = {}

payload['users/-XXX/nickname'] = 'xxx'
payload['users/-YYY/nickname'] = 'yyy'
payload['users/-ZZZ/nickname'] = 'zzz'

database.ref().update(payload)

f:id:kakku22:20180509135737p:plain

(複数キーを追加した結果)

Display Notifications when Things Happen

最後はトースト UI を実装し,データの変更時に通知できるようにした.ライブラリは以下の native-toast を使った.

nativeToast({
    message: `New message by ${snapshot.val().nickname}`,
    type: 'success'
})

github.com

まとめ

  • Vue School が公開している無料コース「Vue.js + Firebase Realtime Database」 を受講した
  • 1,2時間で Firebase Realtime Database をデータストアとしたチャットアプリケーションを実装することができた
  • Vue.js 初学者と Firebase Realtime Database 初学者にオススメ 👍

CircleCI 2.0 + Apex で Lambda をデプロイする

Lambda をデプロイする場合,最近だと Serverless Framework もしくは AWS Serverless Application Model を使う場面が多いけど,他の AWS サービスに依存せず Lambda だけをデプロイしたい場合には Apex も積極的に使っている.要件がシンプルな場合に特に便利で,過去にも事例を記事にしている.

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

CircleCI 1.0 + Apex

今までは「CircleCI 1.0 + Apex」という組み合わせで Lambda をデプロイしていた.特に難しいことはなく,以下のようなシンプルな circle.yml を作成して,CircleCI 上で毎回 Apex をインストールしていた.ただし,8月末に CircleCI 1.0 のサポートが終了するため,そろそろ移行を考える必要があった.

machine:
  timezone: Asia/Tokyo

dependencies:
  post:
    - curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sudo sh
    - apex version

deployment:
  master:
    branch: master
    commands:
      - apex deploy

Dockerized Apex

CircleCI 2.0 は Docker コンテナを使ってジョブを実行するため,Apex のコンテナが必要になる.ただし Apex 公式では提供されていなく,あまり良さそうなものもなかったため,今回 Alpine ベースで軽量な Dockerized Apex を作成した.バージョンは v1.0.0-rc2v0.16.0 をサポートしている.Docker イメージは kakakakakku/apex - Docker Hub に公開した.

github.com

CircleCI 2.0 + Apex

「CircleCI 2.0 + Apex」の場合は CircleCI 2.0 の記法で .circleci/config.yml を作成して,Dockerized Apex を使えば,今まで通り Lambda をデプロイできる.Docker コンテナを使うことにより,実行時間の短縮にも繋がり,メリットもある.

version: 2

jobs:
  deploy:
    docker:
      - image: kakakakakku/apex
    steps:
      - checkout
      - run: apex version
      - run: apex deploy

workflows:
  version: 2
  apex:
    jobs:
      - deploy

CircleCI の Environment Variables で,以下の環境変数を設定するのを忘れずに!

  • AWS_REGION
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

f:id:kakku22:20180508090052p:plain

(検証環境でデプロイをしてみた結果)

まとめ

  • CircleCI 2.0 + Apex でも Lambda をデプロイすることができた
  • CircleCI 2.0 のために Dockerized Apex を作成した

関連記事

CircleCI 2.0 の新機能「ワークフロー機能」の紹介を前に書いたから合わせて読んでもらえると!

kakakakakku.hatenablog.com