WEB+DB Press vol.111 Perl Hackers Hub に「AWS X-Rayによる分散トレーシング」を寄稿しました

技術評論社 WEB+DB Press vol.111 の連載 Perl Hackers Hub に、「AWS X-Rayによる分散トレーシング……マイクロサービスのボトルネック,障害箇所の特定」という記事を書きました。

WEB+DB PRESS Vol.111

WEB+DB PRESS Vol.111

  • 作者: 松田明,y-yagi,佐藤建太,夜道,村田賢太,伊藤英明,見川孝太,新井剛,関陽介,海老原圭吾,長田洸明,大原壯太,藤原俊一郎,松本宏太,末永恭正,久保田祐史,牧大輔,笹田耕一,竹馬光太郎,池田拓司,はまちや2,竹原
  • 出版社/メーカー: 技術評論社
  • 発売日: 2019/06/24
  • メディア: 単行本
  • この商品を含むブログを見る

内容は1月にあった YAPC::Tokyo の発表をベースにしたものです。

sfujiwara.hatenablog.com

YAPC での発表をしたときの印象で、どうも分散トレーシングはそこまでメジャーじゃなさそうだぞ、ということで、Perl の連載枠ですが前半半分は分散トレーシングというものの概念、AWS X-Ray についての説明に割きました。なので、Perl 以外の言語をお使いのかたでも、分散トレーシングをなんとなく把握してみたいというかたにも参考になる内容になっていると思います。

後半は ISUCON 8 の Perl 実装を X-Ray で解析して可視化するという内容です。今年も ISUCON の季節がもうすぐやってきますね。ISUCON 9 の攻略のためにも是非参考にしていただければと思います。


さらに今号から1年間の予定で、勤務しているカヤックの SRE チーム持ち回りで「インフラ運用のアイデア&テクニック ── 小さなチームでマネージドサービスを活用」という連載が始まりました。

ここ数年のインフラ連載枠は、大規模!最先端!みたいな雰囲気が多かったと思うのですが、今年はそこまで先端でも大規模でもないけど少人数でクラウドを上手く活用していこう、レガシーなのもいい感じにマイグレーションしていこう、みたいな雰囲気になる計画です。

こちらも是非ごひいきにお願いします。


そのほかの記事も、Rails 6 (カヤックでは受託案件のサーバはRailsが多いので気になります)、Julia (データ解析との親和性が高そう)、見える化大作戦 (アナログも大事だなあと)、などなど、毎度ながら充実の記事ですので、是非お買い求めください。

Amazon ECS タスク定義のコンテナ依存関係を可視化する

Amazon ECS のタスク定義には、タスク内のコンテナの起動と終了の順序を制御する依存関係が定義できます。

docs.aws.amazon.com

アプリケーションのコンテナと、アプリケーションが依存しているミドルウェアのコンテナがあった場合、依存を定義すると

  • タスク開始時にミドルウェアが起動してからアプリケーションが起動する
  • タスク終了時にアプリケーションが停止してからミドルウェアが停止する

というような制御が可能です。

graphviz による可視化

しかし依存関係が複雑になると、JSON で文字列で書いただけでは実際にどう依存しているのかがよく分からないし、間違ってループを作ってしまうと起動できないので事前に確認したい、ということで可視化してみました。

f:id:sfujiwara:20190529144138p:plain

これはとあるアプリケーションタスクの依存関係を、task definition の JSON から graphviz 用の .dot ファイルを生成して画像にしたものです。

gist.github.com

taskdef の JSON を引数にして実行すると .dot を吐き出すので、それを dot コマンドで画像化します。

$ perl graph-depends-on.pl  app.json > app.dot
$ dot -Tpng app.dot -o app.png

グラフの各ノードがコンテナで、定義された dependsOn に従ってノードが接続されています。

内部的にそれぞれ必要そうな依存を全て記述するとこうなったのですが、しかしこれだと ECS task が起動しないということが判明。具体的には xray コンテナが起動したあと、他のコンテナが PENDING のまま起動できない状態になりました。

各コンテナから依存先に到達する経路が一意でないのがよくないのかと思いついて、依存を整理したのが次の画像です。

f:id:sfujiwara:20190529144154p:plain

これは無事に起動できました。

まとめ

  • Amazon ECS のコンテナ依存関係は依存を一意にしないと起動できないことがある
  • 依存を可視化できると便利
  • graphviz で可視化するスクリプトPerlRuby で書いたのでご利用ください

Stretcher をご利用中のかたに大切なお知らせ (S3 Signature V2廃止の件)

拙作の pull 型デプロイツール Stretcher をご利用中のかたに大切なお知らせです。

Amazon S3のAWS署名バーション2が、2019年6月24日をもって廃止されます

dev.classmethod.jp

Stretcher v0.x は Amazon S3 からのファイル取得に AdRoll/goamz を利用しており、このライブラリは Signature V2 を使用しているため、2019年6月24日以降 S3 からのファイル取得に失敗するようになります。

現状でも Signature V4のみサポートしているリージョン (us-east-2など) に対して実行すると、以下のようなエラーメッセージで失敗することが確認されています。

Load manifest failed: cannot detect valid credentials or region

ということで、この機に公式 SDK aws-sdk-go に実装を切り替えた v1.0.0 をリリースします。

現在 rc1 を提供していますので、ご利用中のかたは検証の上バージョンアップをお願いします。

(2019-03-17 追記) v1.0.0 をリリースしました。 github.com

基本的に互換性は保っていますが、credential の読みこみを自前のコードから SDK に変更した関係で一部非互換がある可能性があります。 現時点で確認されている非互換としては以下のものがあります。

  • $HOME が設定されていない状態で ~/.aws/credentials の認証情報を読み取れない
    • ホームディレクトリが解決できないため
    • 実行時に適切な $HOME を設定すれば解消します
    • 古い版では mitchellh/go-homedir で自前で解決していたので公式 SDK になって挙動が変わりました

他に何か問題がありましたら https://github.com/fujiwara/stretcher/ まで issue か、Twitter で @fujiwara までお知らせください。

github.com 報告していただいた varusan さん、ありがとうございました!

YAPC::Tokyo 2019でAWS X-Rayによる分散トレーシングの発表をしました

2019年1月26日に開催された YAPC::Tokyo 2019 にて、「Perlでも分散トレーシングしたい! - AWS::XRayによる解析とその実装」というタイトルの最後で発表してきました。

yapcjapan.org

発表資料はこちらです。

speakerdeck.com

ほとんどのクラウドベンダーやマネージドサービスで Perl SDK が提供されていない昨今ですが、AWS X-RayPerl で使いたいがために AWS::XRay を書いたよ、例として ISUCON 8 本選問題を解析してみたよ、という話です。

X-Ray は分散システムでなくても (従来型の RDBMS を使うだけの Web アプリケーションでも) パフォーマンス解析に有用で、使い始めるのに手間もないので興味を持ってもらえた人がいたら幸いです。

会場で挙手してもらった感じでも分散トレーシング自体それほど広く認知されてないようで、そのへんもあってちょっと集客がうまくいかなかったな… というのが反省点ですね。タイトルや内容の工夫の使用がもうちょっとできた気がします。


今回の YAPC でもう7回目の発表で、自分にとっての故郷的な感が強いカンファレンスです。

アクティブな CPAN Author が年々減っていたりと、今後開発のメイン言語として Perl が採用されることはどんどん減っていく流れは明白で寂しい限りなんですが、それでも400人近い人が集まって、Perl入学式などで入門してくる若者もいて、活気があって楽しかったですね。Songmuさんの男泣きにはぐっと来るものがありました。

次回、京都であるかも知れないということなので、楽しみにしています!

graceful restart できない daemon の再起動時のダウンタイムを HAProxy でリトライして救う

とあるネットワーク(Web)サーバがありまして。

  • graceful restart できない
  • graceful stop はできる
    • 処理中のものは全て処理し終わってから終了する
  • 再起動は数秒で完了する

という性質のものを、稼働中に再起動するとダウンタイムがでてしまうのをなんとか誤魔化したかったのです。

最初は nginx から proxy しているところで、繋がらなかったら何秒かおいて何回までリトライ、みたいな設定ができないか探したんですが見つからず、HAProxy を調べたら以下のような設定でできたのでメモ。

frontend absorber
    mode tcp
    default_backend upstream
    bind *:9999

backend upstream
    mode tcp
    server localhost localhost:8888 weight 1
    retries 10

retries 10 で、接続できなかった場合には 1秒間隔(1秒以下のtimeout connect が指定されていればその間隔) で10回までリトライする、という挙動になります。これで10秒以内に再起動できれば救済可能です。

適当に ab でリクエストを流し続けながら再起動してみてもエラーはでなかったので、大丈夫でしょう。

(2018-01-15 18:15 redispatch は関係なく、再試行間隔は timeout connect に依存していたので修正しました)

Mackerel と連携する外形監視エージェント maprobe でマネージドサービスのメトリック収集を自動化する

Mackerel Advent Calendar 2018 22日目の記事です。

ちょっと前に maprobe という、Mackerel のホスト情報と連携して外形監視を行うエージェントツールを作りました。

sfujiwara.hatenablog.com

maprobe は指定した Mackerel のサービス、ロールに存在しているホストに対して外形監視を行った結果をホストメトリックとして投稿するものです。定義にしたがって外から pingTCP, HTTP の疎通を確認した結果を投稿できるのですが、mackerel-agent のメトリックプラグインと互換性のある出力をするコマンドを実行する機能もあります。

今回は AWS インテグレーションで管理されているマネージドサービスのホストに、maprobe でメトリックプラグインで取得したメトリックを追加することで、運用負荷を下げる手法を紹介します。

AWS インテグレーションで管理されたホストにカスタムメトリックを投稿する方法(おさらい)

メトリックプラグインによって得られたメトリックを AWS インテグレーションで管理されているホストに送信することは、mackerel-agent でも可能です。

例として ElastiCache Redis に対してメトリック収集を行いたい場合、どこかのホストで実行されている mackerel-agent の設定に以下のような記述をします。

[plugin.metrics.redis-001]
command = [
  "mackerel-plugin-redis",
  "-host=redis-001.xxxx.apne1.cache.amazonaws.com",
  "-tempfile=/tmp/mackerel-plugin-redis-001",
  "-config-command=",
]
custom_identifier = "redis-001.xxxx.0001.apne1.cache.amazonaws.com"
  • ElastiCache では CONFIG コマンドが実行できないので、-config-command= の設定で CONFIG による値取得を無効化しています
  • -tempfile の指定は、同一 agent で複数の ElastiCahce を監視する場合に状態管理ファイルを分離するために必要です

ポイントは custom_identifier で、ここに mkr hosts --verbose で確認できる customIdentifier の値を指定します。

これによって AWS インテグレーションで認識された ElastiCache のホストに、mackerel-plugin-redis によって取得したメトリックを投稿することができます。

mackerel-agent でメトリック収集する場合の運用負荷

このように maprobe を使わずとも mackerel-agent でもメトリック収集自体は可能なのですが、運用上面倒な点があります。

  • custom_identifier を調べる必要がある
    • 何らかの方法 (mkr コマンドや API) で調べた値を、config に静的に書き込む必要があります
  • ホストが増減した時の設定更新が必要
    • AWS 上でインテグレーション対象のホストを増減した場合、config の記述もそれに合わせて増減する必要があります
    • 具体的には、設定ファイルを再生成して mackerel-agent の reload が必要になります

maprobe で解決すること

maprobe は指定したサービス、ロールのホストを Mackerel API から収集し、その時点で存在している全てのホストに対して外形監視、コマンド実行を行います。メトリック投稿には API で得られた Mackerel のホストIDを使用するので、custom_identifier を調べる必要はありません。

ホストが増減した場合には自動的に追従するため、設定ファイルの変更は必要ありません。

設定ファイルが変更されている場合には自動で再読み込みを行うため、新しい監視設定を追加しても再起動は必要ありません。

maprobe の設定例

先に記述した、ElastiCache Redis にカスタムメトリックを投稿する例は maprobe では以下のようになります。(v0.2.3で command に配列を渡せるようになりました)

probes:
  - service: production
    role: ElastiCache
    command:
      command:
        - "mackerel-plugin-redis"
        - "-host={{.Host.CustomIdentifier}}"
        - "-tempfile=/tmp/mackerel-plugin-redis-{{.Host.ID}}"
        - "-config-command="
      graph_defs: true

graph_defs: true を指定すると、プラグインから得たグラフ定義の投稿 (MACKEREL_AGENT_PLUGIN_META=1 で得られる結果) を自動的に投稿するため、Mackerel 上での見た目は mackerel-agent でメトリック収集したものと同一になります。

さらに maprobe では、ping, TCP, HTTP による外形監視 (check-{tcp,http} とほぼ同等機能) も行えるため、Redis プロトコルPING, PONG による外形監視も追加できます。

probes:
  - service: production
    role: ElastiCache
    tcp:
      host: "{{ .Host.CustomIdentifier }}"
      port: 6379
      send: "PING\n"
      expect_pattern: "PONG"
    command:
      command:
        - "mackerel-plugin-redis"
        - "-host={{.Host.CustomIdentifier}}"
        - "-tempfile=/tmp/mackerel-plugin-redis-{{.Host.ID}}"
        - "-config-command="
      graph_defs: true

Mackerel 本体で提供されている外形監視は、現時点ではグローバルな HTTP(S) に対するもののみです。マネージドサービスのホストでは mackerel-agent が稼働しないため、Unreachable なアラートも上げられません。そのためダウン検知がむずかしいのですが、maprobe では外形監視によりホストのダウンを素早く検知できます。

まとめ

maprobe は Go で実装された OSS です。Mackerel API を利用して、簡単な設定で指定したサービス、ロールのホストに対する外形監視とメトリック収集、投稿を行えます。

github.com

DockerHub でイメージも公開 しているため、コンテナ環境での利用も容易です。

マネージドサービスのホストが増減しても、特に監視設定の変更を意識せずにメトリック収集、外形監視を追従できるため、運用負荷を下げることができるでしょう。

WEB+DB PRESS vol.108 に18周年記念エッセイを寄稿しました

いつもお世話になっている WEB+DB PRESS誌の vol.108 に、18周年記念エッセイを寄稿しました。2018年12月22日発売です。創刊18周年おめでとうございます。

WEB+DB PRESS Vol.108

これまで WEB+DB PRESS には Perl Hackers Hub (vol. 71) と、特集 (vol.94) で技術記事を書かせていただきましたが、まさかエモい文章を求められるとは。どういう経緯での人選なのかは知るよしもありませんが…

普段カンファレンスなどでも技術の話しかしないので、引き受けようかどうしようかちょっと迷ったのですが、(中を読んでいただければ分かるとおり) こういうお誘いには乗っておくべきだということで快諾しました。

いただいたお題が「私が限界を感じたとき」というもので、普段は「人生なるようにしかならないよ」と適当に生きているのでちょっと困りました。WEB+DB PRESS & 限界というキーワードで思い浮かんだのが20年近く前、WEB+DB PRESS の創刊当初の昔話だったため、完全におじさんの昔語りになっています。ご笑覧ください。

f:id:sfujiwara:20181220233548j:plain

「こんな仕事のしかたをしていては死ぬな」というタイトルは編集の方に提案していただいたもので、特に他にいい案も思い浮かばなかったのでじゃあそれで、と決めたものです。他の3名の方々のエッセイを読み、自分の語りがなんだかちょっと恥ずかしくなったので、今後も基本的には真面目に技術の話をしていきたいと思います…

今号の特集は、スキーマ駆動 Web API 開発 (最近はもう必須ですね)、久々の PostgreSQL 大特集 (いまは MySQL ばかりですが昔使ってて実は PostgreSQL 大好きです)、ZOZOのリプレースノウハウ大公開 (泥臭い、けど価値がある話で大好物) と大変おもしろく読ませていただきました。今号からは Kindle 版も用意されるようで、より多くの環境で読みやすくなりますね。ぜひどうぞ。

WEB+DB PRESS Vol.108

WEB+DB PRESS Vol.108

  • 作者: 大和田純,中野暁人,山本浩平,曽根壮大,ZOZOTOWNリプレースチーム,権守健嗣,茨木暢仁,松井菜穂子,新多真琴,laiso,豊田啓介,藤原俊一郎,牧大輔,向井咲人,大島一将,上川慶,末永恭正,久保田祐史,星北斗,池田拓司,竹馬光太郎,粕谷大輔,WEB+DB PRESS編集部
  • 出版社/メーカー: 技術評論社
  • 発売日: 2018/12/22
  • メディア: 単行本
  • この商品を含むブログを見る

エッセイ中にも出てくる自分にとって転機になったカンファレンス、YAPC が来年1月に東京で開催されます。

yapcjapan.org

自分も分散トレーシングと AWS X-Ray の話をするので、こちらも是非よろしくお願いします。チケットもまだ発売中です!(2019年1月6日までの予定です)