kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Git リポジトリ URL を書き換える git-config の設定 "insteadOf" と "pushInsteadOf"

git-config(~/.gitconfig など)に url.<base>.insteadOf もしくは url.<base>.pushInsteadOf を設定すると,Git リポジトリ URL(プロトコル含む)を書き換えることができる.例えば GitHub リポジトリを git pull するときは HTTPS URL を強制し,git push するときは SSH URL を強制するなど.今回は実際に設定を試しながら整理する.

git-scm.com

url.<base>.insteadOf を試す

まず,git-config に url.<base>.insteadOf を設定すると,全てのオペレーションに対して Git リポジトリ URL を書き換える.例えば,以下のワンライナーを実行する.

$ git config --global url.git@github.com:.insteadOf https://github.com/

すると,自動的に .gitconfig に設定が追加される.意味としては https://github.com/ を含む HTTPS URLSSH URL に書き換える.

[url "git@github.com:"]
    insteadOf = https://github.com/

実際にサンプルリポジトリ(パブリック)を HTTPS URLgit clone し,リモート設定を確認すると,SSH URL に書き換わっていた.実際に動作確認をすると,git pullgit pushSSH URL の挙動になっていた.

$ git clone https://github.com/kakakakakku/sandbox-public.git
Cloning into 'sandbox-public'...
(中略)

$ git remote -v
origin  git@github.com:kakakakakku/sandbox-public.git (fetch)
origin  git@github.com:kakakakakku/sandbox-public.git (push)

url.<base>.pushInsteadOf を試す

今度は git-config に url.<base>.pushInsteadOf を設定すると,プッシュオペレーションに対して Git リポジトリ URL を書き換える.例えば,以下のワンライナーを実行する.

$ git config --global url.git@github.com:.pushInsteadOf https://github.com/

すると,自動的に .gitconfig に設定が追加される.意味としては https://github.com/ を含む HTTPS URL に対するプッシュオペレーションを SSH URL に書き換える.

[url "git@github.com:"]
    pushInsteadOf = https://github.com/

実際にサンプルリポジトリ(パブリック)を HTTPS URLgit clone し,リモート設定を確認すると,push のみ SSH URL に書き換わっていた.実際に動作確認をすると,git pull のみ SSH URL の挙動になっていた.

$ git remote -v
origin  https://github.com/kakakakakku/sandbox-public.git (fetch)
origin  git@github.com:kakakakakku/sandbox-public.git (push)

HTTPS URL を使う場合は usernamepassword を毎回入力する必要があるけど,GitHub ドキュメントに書いてある通り「認証情報ヘルパー (Credential Helper)」を使えば,キャッシュできる.

help.github.com

url.<base>.insteadOfusername まで含める

git-config ドキュメントを読むと,URL 設定はあくまで「文字列一致(最長一致)」となり,例えば以下のワンライナーのように kakakakakku まで含めることもできる.

$ git config --global url.git@github.com:kakakakakku.insteadOf https://github.com/kakakakakku

すると,https://github.com/kakakakakku を含む HTTPS URLSSH URL に書き換える.URL によって柔軟に url.<base>.insteadOfurl.<base>.pushInsteadOf を設定できるのは,環境が多いほど便利そう.

[url "git@github.com:kakakakakku"]
    insteadOf = https://github.com/kakakakakku

実際に kakakakakku/sandbox-publicrails/rails でリモート設定を確認すると,確かに限定的に適用されていた.

$ git remote -v
origin  git@github.com:kakakakakku/sandbox-public (fetch)
origin  git@github.com:kakakakakku/sandbox-public (push)

$ git remote -v
origin  https://github.com/rails/rails (fetch)
origin  https://github.com/rails/rails (push)

まとめ

git-config(~/.gitconfig など)に設定できる url.<base>.insteadOfurl.<base>.pushInsteadOf を試した.GitHub ドキュメントに HTTPS URL 推奨と書いてあり,HTTPS URL を軸に使いながら,部分的に SSH URL を使ったりすると良さそう.例えば ghq get もデフォルトは HTTPS URLgit clone をするため,url.<base>.insteadOfurl.<base>.pushInsteadOf と組み合わせて使うと便利!

help.github.com

Hatena Blog に関係するメトリクスを Mackerel で可視化する

「継続的アウトプット」を意識して,毎週 kakakakakku blog を更新している.そして振り返りのためにブログに関係するメトリクスを取得している.もちろん Google AnalyticsGoogle Search Console も使っているけど,Hatena Blog に関係するメトリクスも取得している.

長期的な管理としては,数年間ずっと Google Sheets を使っている.さらに2019年後半からは Mackerel も併用している(グラフ表示期間は460日).2019年に「Mackerel アンバサダー」に就任させていただいた経緯もあり,プランの範囲内で Mackerel を日常的に使うネタを作りたかったという背景もある.今回の記事は「仕組み」に特化してまとめておく.

サービスメトリック と アノテーション

現在 Hatena Blog に関係するメトリクスとして「読者数」「総ブックマーク数」を Mackerel の「サービスメトリック」として取得している.さらに「アノテーション」を組み合わせて「ブログ記事情報(記事タイトルと記事 URL)」も同じグラフにプロットしている.ホッテントリに入るなど,メトリクスが大きく変化する場面もあり,振り返るときに便利に使える.参考として,最近「Beyond the Twelve-Factor App」の紹介記事がホッテントリに入ったときのグラフを貼っておく.

f:id:kakku22:20200322102226p:plain

「読者数(680 前後)」「総ブックマーク数(15390 前後)」に大きく差があり,縦軸の変化が確認しにくいけど,実際に総ブックマーク数は 300 以上も増えている.アノテーションは7個もあり「週1記事ノルマ」より多く書けている.

kakakakakku.hatenablog.com

IFTTT 連携

ブログ記事を書いたときに「アノテーション」を登録するため,現在は IFTTT を使っている.具体的には IFTTT を使って RSS と Amazon API Gateway + AWS Lambda で実装した API を連携している.実装自体は Google Apps Script などを使うこともできそう.なお,IFTTT から以下のパラメータを飛ばしている.

  • EntryTitle : 記事タイトル
  • EntryUrl : 記事 URL

f:id:kakku22:20200322105848p:plain

まとめ

ブログメンタリング中に「メトリクスをどう管理していますか?」という質問があり,基本的には Google Sheets をマスタとして使っているけど,最近は Mackerel も併用しているという回答をした.Mackerel を併用している話は今までブログに書いてなく,1度書いておくことにした.なお,例えば Hatena Blog Pro(有料プラン)の特典として「読者数」「総ブックマーク数」を管理するアナリティクス機能を提供してもらえると便利なんだけどねぇー!

関連記事

Mackerel で「アノテーション」を登録するスニペットは以下の記事にまとめてある.参考にどうぞ!

kakakakakku.hatenablog.com

Jupyter Notebook で clear_output() を使って定期的に表示を更新する

Jupyter Notebook を使ってデモ環境を作るときに whileprint を組み合わせて,定期的に表示を更新したかった.例を出すと「時計のように」毎秒表示を更新するイメージとなる.調べたところ IPython.display モジュールに clear_output 関数があり,解決できたので,参考までにまとめておく.

サンプルコード

Python で日付を表示しながら,1秒後に clear_output を実行する.

from datetime import datetime
from time import sleep
from IPython.display import clear_output

while True:
    print(datetime.now())
    sleep(1)
    clear_output(True)

実際に Jupyter Notebook で実行している画面を gif 化した.スムーズに更新できている.

f:id:kakku22:20200318120246g:plain

wait パラメータとは?

ドキュメントを読むと,clear_output に指定できるパラメータとして wait がある.デフォルトは False で,意味としては「次の表示をするまで待機するか?」となる.上の例では意図的に True を指定していた.

IPython.display.clear_output(wait=False)

ipython.org

以下のようにデフォルト Falseclear_output を実行する.

from datetime import datetime
from time import sleep
from IPython.display import clear_output

while True:
    print(datetime.now())
    sleep(1)
    clear_output()

同じく Jupyter Notebook で実行している画面を gif 化した.すぐにクリアされるため,ある程度ガタガタした表示になる.

f:id:kakku22:20200318120310g:plain

まとめ

Jupyter Notebook で定期的に表示を更新する場合は IPython.display モジュールの clear_output 関数を使う.要件によって wait パラメータを指定して調整できる.

「The Twelve-Factor App」を15項目に見直した「Beyond the Twelve-Factor App」を読んだ

2012年に Heroku のエンジニアによって提唱された「The Twelve-Factor App」は素晴らしく,アプリケーションをうまく開発し,うまく運用するための「ベストプラクティス」として知られている.2020年になった現在でもよく引用されていると思う.日本語訳もある.

12factor.net

Beyond the Twelve-Factor App とは?

クラウド化が進むなど,提唱された2012年と比較すると技術的な変化もあり,今までの「The Twelve-Factor App」で宣言されていた観点以外にも必要な観点やベストプラクティスがあるのでは?という意見もある.そこで,2016年に Pivotal のエンジニアが「Beyond the Twelve-Factor App」を提唱した.The Twelve-Factor App にあった「12項目をアップデート」し,新しく「3項目を追加」した.「計15項目」となる.

今回は Beyond the Twelve-Factor App を読んで,興味を持った箇所を中心にメモ程度に残しておく(正確に言うと,もっと前に読み終わっていたけど,記事を書いていなかった).オリジナルの The Twelve-Factor App よりは具体的に書かれているけど,それでもまだ抽象的なところもある.とは言え,議論の種になって良いと思う.以下のサイトにメールアドレスを登録すると,無料で PDF をダウンロードできる.

tanzu.vmware.com

The Twelve-Factor App と Beyond the Twelve-Factor App

まず,The Twelve-Factor AppBeyond the Twelve-Factor App に宣言されている項目を一覧しておく.Beyond the Twelve-Factor App には正式な日本語訳がなく,個人的に載せているため,参考程度にしてもらればと!Beyond the Twelve-Factor App で新しく追加された項目は「2. API first」「14. Telemetry」「15. Authentication and authorization」となる.

  • The Twelve-Factor App
    1. Codebase(コードベース)
    2. Dependencies(依存関係)
    3. Config(設定)
    4. Backing services(バックエンドサービス)
    5. Build, release, run(ビルド、リリース、実行)
    6. Processes(プロセス)
    7. Port binding(ポートバインディング)
    8. Concurrency(並行性)
    9. Disposability(廃棄容易性)
    10. Dev/prod parity(開発/本番一致)
    11. Logs(ログ)
    12. Admin processes(管理プロセス)
  • Beyond the Twelve-Factor App
    1. One codebase, one application(1 コードベース、1 アプリケーション)
    2. API first(API ファースト)
    3. Dependency management(依存関係管理)
    4. Design, build, release, and run(デザイン、ビルド、リリース、実行)
    5. Configuration, credentials, and code(設定、機密情報、コード)
    6. Logs(ログ)
    7. Disposability(廃棄容易性)
    8. Backing services(バックエンドサービス)
    9. Environment parity(環境一致)
    10. Administrative processes(管理プロセス)
    11. Port binding(ポートバインディング)
    12. Stateless processes(ステートレスプロセス)
    13. Concurrency(並行性)
    14. Telemetry(テレメトリ)
    15. Authentication and authorization(認証/認可)

1. One codebase, one application

The Twelve-Factor App では「Codebase」という項目だったけど,Beyond the Twelve-Factor App では「One codebase, one application」という項目になり,より具体的な名前に変わった.とは言え,内容は「コードベースとアプリケーションを 1対1 にすること」となり,大きく変わっていないと思う.なお,リポジトリ構成で議論になることもある「モノレポ」に関しては明確な言及はなかった.

ただし「キューを使った非同期アプリケーション」を題材とし,「メインアプリケーション」「密結合ワーカー」が同じリポジトリルートを共有する場合は項目に違反していると書いてあったり,1個の EAR ファイルを複数の起動スクリプトによって制御している場合も,複数のアプリケーションを管理していることになり項目に違反していると書いてある.さらに「コンウェイの法則」に対する言及もあり,より具体的に解説されている点は Beyond the Twelve-Factor App の素晴らしい点だと思う.

2. API first

次に Beyond the Twelve-Factor App で追加された項目「API first」は,今でこそ「言わずもがな」な印象を受けるけど,確かに The Twelve-Factor App には明確に言及されていなかった.具体的には,開発中にうまくサービス間を結合できなかったりすると悪夢だから,API を「ファーストクラス」と考えることにより,干渉せず「公開されたインタフェース」を中心に開発を進められるようになると書いてある.

また,サービスの例としては API Blueprint と Apiary(前職で使ってた)を使ってモックサーバを立てるプラクティスも載っていた.最近だと Swagger や OpenAPI って書いておくと良さそう.

swagger.io

4. Design, build, release, and run

The Twelve-Factor App では「Build, release, run」という項目だったけど,Beyond the Twelve-Factor App では「Design, build, release, and run」という項目になり,「Design」が追加された.

意味としては「設計」だけど,本書を読むと「リリースする小さな機能の設計」と書いてあったり「アプリケーションの依存関係」と書いてあったり「うまく作られた CI/CD パイプラインを使えば Design から Run まで数分で終わる」と書いてあったりする.正直言って「要件を整理する話」なのか「Design Doc のように技術仕様を整理する話」なのか「ライブラリ依存を整理する話」なのか,ハッキリと理解できなかった.ライブラリ依存だとすると「Dependency management」と重複する.もう少し具体例を解説している情報などを探しておく必要がありそう.

5. Configuration, credentials, and code

The Twelve-Factor App では「Config」という項目だったけど,Beyond the Twelve-Factor App では「Configuration, credentials, and code」という項目になり,より具体的な名前に変わった.

例えば「接続する API のエンドポイント情報」だったり「データベースの接続情報」だったり,環境依存な設定を環境変数に入れておくというプラクティスはもともと言及されていた.ただし,言い換えると今までは「環境変数に入れておく」以外に言及されていなかった.

Beyond the Twelve-Factor App では,環境変数を外部化 (Externalizing Configuration) する必要性と,可能なら外部サービスに入れると書いてあった.サービスの例としては Spring Cloud Config Server が載ってて,Git と連携できる Config Server は良さそう.最近だと AWS Systems Manager Parameter Store だったり,HashiCorp Vault だったり,選択肢は多いと思う.

cloud.spring.io

8. Backing services

「Backing services」The Twelve-Factor App から変わってないけど,内容はとても充実していた.「バックエンドサービス」とは何か?を定義しつつ,例えば「クラウドだとファイルシステムを一時的なリソースとして考える」など,クラウド化により活発に議論されるようになった観点も言及されていた.さらに「サーキットブレーカー」に対する言及もあり,誤ったバックエンドサービスに対するアクセスを遮断する必要性も書かれていて良かった.

martinfowler.com

14. Telemetry

Beyond the Twelve-Factor App で追加された項目「Telemetry」は,意味としては「モニタリング全般」と言える.クラウド時代に必要なテレメトリとして「3種類」紹介されていた.

  • APM (Application Performance Monitoring)
  • ドメイン情報
  • 稼働状況/ログ

「ドメイン情報」の具体的な例が載っていて,例えば「秒間 HTTP リクエスト平均数」よりも「直近 20min に iPad 経由で販売された件数」の方がビジネスインパクトがあるよね?という内容だった.稼働状況に関しては,例えば「外形監視」など,ユーザー目線でモニタリングをする重要性が書かれている.また,クラウド時代の「監視戦略」として,例えば「インスタンスが 100台 までスケールしたら,単純計算でログも 100倍 になる可能性がある」など,ログの保存量まで考えることもテレメトリを正しく行うために重要であると書かれていた.

kakakakakku.hatenablog.com

15. Authentication and authorization

最後も Beyond the Twelve-Factor App で追加された項目で,認証と認可など,セキュリティ面にフォーカスした「Authentication and authorization」となる.内容としては,全てのエンドポイントを RBAC (Role-Based Access Control) のような仕組みで保護すると書いてある.ようするに,クライアント側が必要な認可を持っているか確認できるようにすることを意味している.

実現する技術の例としては OAuth2OpenID ConnectSSO (Single Sign-On) が載っていた.最近だと Amazon Cognito だったり,認証認可 SaaS の Auth0 だったり,選択肢は多いと思う.

auth0.com

まとめ

2012年に提唱された「The Twelve-Factor App」と,2016年に提唱された「Beyond the Twelve-Factor App」を読んで,興味を持った箇所を整理した.多分意図的に抽象的に書かれているところもあり,そのあたりは議論をして実践的な解釈を深めていければと思う.興味があったら読んでみると良いのではないでしょうか!

tanzu.vmware.com

Envoy の「サーキットブレーカー」を試す検証環境を構築する

マイクロサービスを実現するときに Envoy「サーキットブレーカー (Circuit Breaking)」はよく話題に挙がる.Try Envoy には「サーキットブレーカー」を試すコンテンツがなく,今回ドキュメントを読みながら検証環境を構築し,動作確認をした.もし Try Envoy に興味があったら以下の記事を読んでもらうと良いかなと!

Learn Envoy : Circuit Breaking を読む

試す前に概要を整理するため,今回は Learn Envoy のドキュメントを読んだ.まず,マイクロサービスを運用するときに「連鎖的な障害」を防ぐために「サーキットブレーカー」を使うべきと書いてある.そして,単純な「閾値」によってリクエストを制御するのではなく,プライオリティ機能を使って,例えば「購入などの重要な POST 処理」を優先するなど,実践的なアドバイスも載っている.

www.envoyproxy.io

さらに,Envoy の Route 側に設定する「自動リトライ機能」を使って,例えばレスポンスコードが 5xx のときにリトライすることもできるし,サーキットブレーカーに設定する max_retries によって,Cluster 側でリトライすることもできる.ただし,リトライをするとリクエスト数も増えるため,必要性は適切に検討する必要がある.

www.envoyproxy.io

circuit_breakers で使えるパラメータ

「サーキットブレーカー」を使う場合,Envoy の設定ファイル envoy.yaml の Cluster 設定に circuit_breakers を追加する.使えるパラメータの概要を以下に載せる.詳細はドキュメントを見てもらえればと.retry_budgettrack_remaining など,ドキュメントを読んでもよく理解できなかったパラメータもある.

  • priority : DEFAULTHIGH のプライオリティを設定する(デフォルト DEFAULT
  • max_connections : 最大コネクション数を設定する (HTTP/1.1 用)
  • max_pending_requests : 最大保留リクエスト数を設定する(デフォルト 1024
  • max_requests : 最大リクエスト数を設定する (HTTP/2 用)
  • max_retries : 最大リトライ回数を設定する(デフォルト 3
  • retry_budget : 最大リトライ回数を上書きしてリトライ予算を設定する(?)
  • track_remaining : サーキットブレーカーのリソース数をメトリクスとして取得できるようにする(?)
  • max_connection_pools : 最大コネクション数を設定する(デフォルト 上限なし)

www.envoyproxy.io

検証環境

実際に検証環境を構築し,動作確認をした.今回は Docker Compose で「Envoy コンテナ(フロントエンド)」「Sinatra コンテナ(バックエンド)」を起動し,Sinatra では単純に文字列を返すプロトタイプ実装にした.

get '/' do
  'Hello!'
end

構成図は以下のようになる.

f:id:kakku22:20200229233653p:plain

負荷テスト : Vegeta

今回は Vegeta を使って負荷テストを行う.-rate オプションに秒間のリクエスト数を指定し,-duration オプションに継続する時間を指定する.レポートを生成できたり,グラフをプロットできたり,便利な機能が多くあるため,個人的によく使っている.

github.com

検証結果

簡単に「サーキットブレーカー」を試す場合,envoy.yaml を以下のように書く.今回は負荷を低く 5 にした.なお,パラメータの概要に載せた通り HTTP/1.1HTTP/2 は仕組みが異なるため,対象とするパラメータも異なる.HTTP/1.1 の場合は max_connections を使って,HTTP/2 の場合は max_requests を使う.今回は HTTP/1.1 を使うため,基本的には max_connections の値に依存する.そして,保留リクエストをプールする max_pending_requests の値はデフォルト 1024 で検証用途だと大きいため,今回は 128 にした.

(中略)

  clusters:
  - name: backend
    connect_timeout: 0.25s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    circuit_breakers:
      thresholds:
        max_connections: 5
        max_requests: 5
        max_pending_requests: 128

(中略)

検証結果 : -rate=5-duration=1m

まず,Vegeta を使って -rate=5-duration=1m で負荷をかけると,問題なく実行できた.Status Codes の部分を見ると 200:300 となり,300件全てのレスポンスコードが 200 だった.そして vegeta report の結果だと時系列データが確認できないため,今回は jaggrjplot を組み合わせてグラフも生成した.

$ echo 'GET http://localhost:8080' | vegeta attack -rate=5 -duration=1m | tee result.bin | vegeta encode | \
    jaggr hist\[200,500\]:code | \
    jplot code.hist.200+code.hist.500

$ cat result.bin | vegeta report
Requests      [total, rate, throughput]  300, 5.02, 5.02
Duration      [total, attack, wait]      59.804635434s, 59.797234263s, 7.401171ms
Latencies     [mean, 50, 95, 99, max]    12.469781ms, 9.218021ms, 28.394007ms, 82.423598ms, 116.723594ms
Bytes In      [total, mean]              1800, 6.00
Bytes Out     [total, mean]              0, 0.00
Success       [ratio]                    100.00%
Status Codes  [code:count]               200:300
Error Set:

f:id:kakku22:20200302134115p:plain

検証結果 : -rate=20-duration=1m

次に,Vegeta を使って -rate=20-duration=1m で負荷を上げてみても,問題なく実行できた.Status Codes の部分を見ると 200:1200 となり,1200件全てのレスポンスコードが 200 だった.

$ $ echo 'GET http://localhost:8080' | vegeta attack -rate=20 -duration=1m | tee result.bin | vegeta encode | \
    jaggr hist\[200,500\]:code | \
    jplot code.hist.200+code.hist.500

$ cat result.bin | vegeta report
Requests      [total, rate, throughput]  1200, 20.02, 20.01
Duration      [total, attack, wait]      59.965268845s, 59.951868329s, 13.400516ms
Latencies     [mean, 50, 95, 99, max]    53.635778ms, 15.593157ms, 228.294851ms, 572.832074ms, 714.658048ms
Bytes In      [total, mean]              7200, 6.00
Bytes Out     [total, mean]              0, 0.00
Success       [ratio]                    100.00%
Status Codes  [code:count]               200:1200
Error Set:

f:id:kakku22:20200302134128p:plain

検証結果 : -rate=50-duration=1m

最後に,Vegeta を使って -rate=50-duration=1m で負荷をかけると,サーキットブレーカーの機能によって,一部のレスポンスコードが 503 になった.そしてグラフを見ると,途中から 503 が増えている.これはリトライと保留リクエストの結果だと考えられる.

$ echo 'GET http://localhost:8080' | vegeta attack -rate=50 -duration=1m | tee result.bin | vegeta encode | \
    jaggr hist\[200,500\]:code | \
    jplot code.hist.200+code.hist.500

$ cat result.bin | vegeta report
Requests      [total, rate, throughput]  3000, 50.02, 42.52
Duration      [total, attack, wait]      1m3.498684051s, 59.979999578s, 3.518684473s
Latencies     [mean, 50, 95, 99, max]    2.355218631s, 2.643233064s, 3.520133351s, 3.722747469s, 3.787535824s
Bytes In      [total, mean]              40500, 13.50
Bytes Out     [total, mean]              0, 0.00
Success       [ratio]                    90.00%
Status Codes  [code:count]               200:2700  503:300
Error Set:
503 Service Unavailable

f:id:kakku22:20200302134137p:plain

まとめ

今回は Envoy の「サーキットブレーカー (Circuit Breaking)」を検証するため,Mac に Docker Compose で検証環境を構築し,さらに Vegeta も Mac で実行した.リクエスト数も少なく,実用的な負荷テスト環境とは言えないけど,お手軽に試せたのは良かった.とは言え,パラメータチューニングは難易度が高そうに感じた.「サーキットブレーカー」に求めるシナリオなどを検証し,繰り返し検証をするのが良さそう.検証環境の設定などは全て GitHub に置いておいた.

github.com