Slide 1

Slide 1 text

監視せなあかんし 五大紙だけにオオカミってな 日本経済新聞社 デジタル編成ユニット Nikkei Tech Talk #3 Yuta IDE #nikkei_tech_talk

Slide 2

Slide 2 text

自己紹介 { "名前": "Yuta IDE", "所属": [ "デジタル編成ユニットWebチーム", "技術戦略ユニット" ], "職務": "電子版のWeb開発", "マイブーム": “料理" } 2

Slide 3

Slide 3 text

今日話すこと 3 ● 日経では Sentry, StatusCake, PagerDuty などのア ラート基盤(後に詳解)を導入しているが、アラートとし て扱わなくてもいいようなノイズが多く、 オオカミ少年 問題を引き起こしている ● 10~12月の3ヶ月開発を止めてあらゆる負債を返済 する時間を確保したので、そのときにオオカミ少年問 題にも取り組んだ ● オオカミ少年問題の原因はどこにあって、どのように 減らすかを考える

Slide 4

Slide 4 text

オオカミ少年問題とは 4 いわゆるアラート疲れ アラート疲れは、オペレータが頻繁に多くのアラートにさらさ れることで、アラートに鈍感になってしまう場合に起こりま す。オペレータが偽のアラートに慣れてしまうとどんどん鈍 感になっていきアラートへの応答時間が悪化します。これ によりアラートシステムの全体的な有効性が低下します。 https://www.oreilly.co.jp/books/9784873119847/

Slide 5

Slide 5 text

俺たちのイカれたオオカミを紹介するぜ 5

Slide 6

Slide 6 text

俺たちのイカれたオオカミを紹介するぜ 6

Slide 7

Slide 7 text

実はオオカミではありませんでした 7

Slide 8

Slide 8 text

8 https://www.pakutaso.com/20190409116post-20652.html

Slide 9

Slide 9 text

9 https://www.pakutaso.com/20190437112post-20552.html

Slide 10

Slide 10 text

10

Slide 11

Slide 11 text

11 闇

Slide 12

Slide 12 text

日経電子版の闇 12 ● Webチームだけで30個以上の稼働中のレポジトリを管理しており、中には誰も知らない古いサービ スもある ● Sentryなどの導入はされているものの運用を引き継がれていない . って言うと本当に人事に怒られそうなので……

Slide 13

Slide 13 text

日経電子版の光 13 ● 大幅機能アップデートのタイミングで 何度かリプレイスしており、JSP → Handlebars → (p)react + NodeJSで自作SSR と作り替えており、VCL(Fastly Varnishの記述言語) のRust 刷新(C@Eへの 移行)や電子版外では Next.js の運用も始まっている ● 3ヶ月丸々負債返済活動をさせてくれる ほど理解を得られたり、技術選定を現場判断で行えるので ハードスキルとしての技術力を伸ばすには本当に良い環境 ● Developer Experience を大事にしている We are hiring.

Slide 14

Slide 14 text

光があるところには影がある 14 ● とはいえ、リプレイスはユーザー影響の大きいページ のみがメインであり、まだ旧基盤のコードもたくさん 残っている ● 旧基盤のコードは基本的にメンテしなくていいのだ が、昔の人が入れた Sentry は動き続け、載せ替え たデプロイ先の GKE からは Cloud Monitoring は 計測を続け、Datadog はwarn warn warn🐶 ● 監視チャンネルのアラートが暴発しているので直して いく

Slide 15

Slide 15 text

何が監視チャンネルに送っているのか 15 名前 用途 送っているか Datadog コンテナのログの集積地 ❌ Elasticsearch + Kibana アクセスログの集積。 HTTP Status ごとの 集計などが可能になる。オリジンの前段に も対応 ❌ Sentry アラート目的 ⭕ StatusCake 外形監視 ⭕ Pager Duty Status Cake の結果を電話で通知 ⭕ Cloud Monitoring GKE 基盤のログが集まる ⭕ CloudWatch AWS 基盤のログが集まる ⭕

Slide 16

Slide 16 text

CDN Monitoring Log GKE req / res req / res Sync manifests Observe Push Integrate Send log Send log APIGW req / res Push attach Origin Servers 全体感 repo repo repo repo ・ ・ ・ 一覧 ページ req / res 詳細 ページ 検索 ページ ・ ・ ・

Slide 17

Slide 17 text

一個一個設定を見直していくぞ! 17

Slide 18

Slide 18 text

まずは軽めなものから 18

Slide 19

Slide 19 text

Status Cake の設定を見返す 19 ● 外形監視ツール ● 疎通に加え、ドメインや証明書の期限チェックもしてくれる ● これはオオカミ少年になっていなかった

Slide 20

Slide 20 text

Pager Duty の設定を見返す 20 ● オンコールツール ● 問題が起きた時にあらかじめ登録しておいた電話番号に電話がかかってくる ● 当番性があるので当番が電話を受け取る設定にしている ● Status Cake と連動させており、Status Cake の検知で電話がかかる。そのため Status Cake の 設定がOKならこれもOK

Slide 21

Slide 21 text

Cloud Watch の設定を見返す 21 ● エラー通知がたくさんチャンネルに流れてきていた。 Elastic Beanstalk の設定によって送られてく るエラーで何が何だか分からない ● 元々AWS->GCP移行した後にセカンダリとして動作させていた AWS 環境へのデプロイが、デプロ イプロセスで行うヘルスチェクリクエストで必ず失敗するため、デプロイのたびに常にアラート が流 れている ● マルチクラウドする場合も Elastic Beanstalk は使わないので、AWS 系のアラートはそれ用のチャ ンネルに分離した。見なくてもいい運用にもした

Slide 22

Slide 22 text

ここからヘビー級のエラー 22

Slide 23

Slide 23 text

Cloud Logging の設定を見返す 23 ● Cloud Logging は GCP のサービス ● GKE を使うとロギングされアラートの作成も行えて監視にも使える ● コンテナのエラーログだけでなく、コンテナの ハードウェア的なメトリクスも監視できる ● 我々の無邪気な console.error が通知され続ける

Slide 24

Slide 24 text

じゃあ消せばいいじゃん? 24 ● アラートをignoreする設定を入れる? ● 本当に見ないといけないアラートも ignoreされてしまわない? ● 放置してもいいアラートでもスパイクしたら対処しないといけなくならない? 放置していいエラーかどうか分析する必要がある

Slide 25

Slide 25 text

Cloud Monitoring の分析大変 25 ● Incidents 一覧からサービス名・ア ラート名で集計したい ● しかし Incidents ダンプできない ● サポートに問い合わせると「画面をク ロールするとできます」「Slackとかに 集積するといいですよ」と言われる 😵 クロールするぞ!󰝢

Slide 26

Slide 26 text

2段階認証で守られたページをクロール 26 ● Incidents ページはページネーションUIだが連番 IDではない ● 2段階認証はレスポンスのクッキーそのまま使い まわせば突破できる ● Incidents のページのレスポンスをジッと眺める と token をリクエストに付与して、得たレスポン スから nextToken を得られる 連鎖的に呼べば引き抜ける

Slide 27

Slide 27 text

雑な正規表現とreduceで集計する 27 ほとんどが Container Error log

Slide 28

Slide 28 text

Sentry と被るので消す 28 ● Container Error Log の内容はほとんどが Sentry でもカバーできるので、アラートの対象外とする ● なのでハードウェアのメトリクス、コンテナリスタートの異常値だけをアラートとして受け取るようにす る

Slide 29

Slide 29 text

CPU利用率等はアラート対象にすべきか 29 https://www.oreilly.co.jp/books/9784873118642/ ● これらのメトリクスは誰かを叩き起こすには値し ません。 ● 「そのサーバーはやるべき処理はしているんだ ろ?」「それなら何も問題はないじゃないか」 ● 電子版はCDNで9割以上捌くので、CPUやメモ リ利用率が高まるのは注視すべき事項と言え る。電話までは行かないがSlackに通知するくら いはしておく。

Slide 30

Slide 30 text

Sentry に来ているアラートを見返す 30 ● アラートチャンネルに常駐する ● Issue を event 数で sort して、Slack連携されているIssueを全部見る ● 無視していいものか判断する

Slide 31

Slide 31 text

一筋縄では行きませんでした! 31

Slide 32

Slide 32 text

32 どうやってデバッグしろ言うねん! (解決方法は後ほど紹介)

Slide 33

Slide 33 text

苦労したエラー3選 33

Slide 34

Slide 34 text

Bingbot 34 ● 存在しないエンドポイントへのアクセスだが、 出鱈目なパスというわけではない ● ユーザーがそのリンクを辿っているのなら無 効なリンクが残っていると言うことで対処す べき事案 ● kibana で該当リクエストを探し出して HTTP Request を見てみると全て Bing の bot だった ○ 全てbotだったのでignore

Slide 35

Slide 35 text

retry による発火 35 ● 電子版のアプリケーションサーバーはサービス間通信が失敗することが前提で設計しており、 retry 機構がある ● retry に成功したとしても失敗した try が FetchError として Slack に通知される ● HTTP通信のログとしてみると正常系としてレスポンスできているのにアラートが上がる ● 全体で失敗しなければアラートではなくワーニングにすべきだった。 Sentry SDK にもログレベル は存在するので活用すべき

Slide 36

Slide 36 text

node-fetch timeout 36 ● 何も情報がなくてサーバー内部のエラーか、 ネットワーク経路のエラーか分からない ● 大多数のリクエストは成功しているのでネッ トワーク起因の問題もあり得る ● 原因切り分けの一つの選択肢として tcpdump。 パケットキャプチャしてデバッグ する ○ 結局原因分からなくてまだ調査中

Slide 37

Slide 37 text

tcpdump を使うためには 37 ● 普通に tcpdump コマンドを使えばいいが、稼働しているサーバーは TLSで暗号化されているた め覗けない ● 暗号化を解く必要がありそのための仕組みとして –tls-keylog がある ● が、このオプションが使えるのは Node v12.3 からであり、それより前のバージョンで動いている ものにはデバッグを仕掛けられない 日頃から最新にしておきましょう、ということで

Slide 38

Slide 38 text

Node バージョンアップ計画を実施 38 ● 全サービスの Node.js のバージョンを最低でも 16, 理想的には 18 に上げる計画を負債返済活 動期間に実施していた ● 各バージョンでの regression test tool を作ってアップデート ● node-gyp error, node-sass から dart-sass へ, もろもろのパッケージの deprecated と戦う

Slide 39

Slide 39 text

そもそもエラー返ってるけど大丈夫? 39 ● コードを読んでみたところ、該当箇所のエラーが原因で Navigation Request に対して  InternalServerError が返っていることが判明 ● しかし正常系のHTMLはCDNにあり、stale-if-error を設定しているのでユーザーからすると壊れ ない ○ stale-if-error: RFC5861 HTTP Cache-Control Extensions for Stale Contentで追加され た Cache-Control Header の一種。HTTP リクエストに失敗した時にキャッシュを使える ● Fastly様様 :pray:

Slide 40

Slide 40 text

オオカミかどうかの識別を するためにすべきこと 40

Slide 41

Slide 41 text

エラーにはメタ情報を付与する 41 ● name, message, trace の情報を持ち回る ● name を指定しなければ Sentry の Issue タイトルが Error だけになって分類が大変 ● message を指定しなければ undefined だ けになって何の Error か分からない ● Custom Error の定義がおすすめ

Slide 42

Slide 42 text

エラーを握りつぶさない 42 ● ランタイムから上がってきたエラーはそのまま持ち回ること ● Stack Trace の保持や Error Cause の作成などを心がけること ● Error Cause は強力なのでサポートされている Node v18 を使おう

Slide 43

Slide 43 text

オオカミ少年問題を起こさないために すべきこと 43

Slide 44

Slide 44 text

アラートの定義をする 44 ● Sentryなどに(個人的には)なんでもかんでもまず送るのは正しいと思うが、アラートするかどうか はまた別 ○ My Opinion: ログを保存するだけでコストがかかるが、それはなんでもかんでも送るほどエ ラーを連発している状態が問題であって、送る姿勢は間違いではないと考えている。普通の ログもストレージに対してであればドンドン送っていいと思う。 ● 電話をするほどの事態とは、Slackに流すほどの事態とはという合意をチームで持っておこう

Slide 45

Slide 45 text

ログレベルを使い分ける 45 ● SentryはError以外の定義を使える ○ Console: log, debug, info, warn, error ○ Sentry: captureException, captureMessage, fatal, error, warning, log, info, debug ● どういうときにどのレベルを使うかの話し合いもチームでしておこう ● レベルごとにSlackに送るか、電話をかけるかという設定を行える

Slide 46

Slide 46 text

運用手順書を作る 46 ● そもそもアラートの扱いや運用の合意がないことが問題なので、運用手順書を作っておこう ○ アラートが上がった時の初動について ○ アラートは誰が対処するか ○ アラートの調査ログはどこに集約するか ○ アラートをクローズするための条件 ● Sentry SDK の使い方の共有や、ログレベルの合意も忘れずに!

Slide 47

Slide 47 text

まだ完走していないけど感想 47

Slide 48

Slide 48 text

3ヶ月の成果 48 ● Sentryに詳細なメタデータもログとして出るようになった ● 毎日10回以上通知されていたアラートを 1日1,2件に抑えられた ● チームメンバーが alert チャンネルの通知を元に朝8時に 5分で本当のインシデントに対応できた ● 結果として開発者体験の向上に貢献

Slide 49

Slide 49 text

アラート改善活動で自分がしたこと 49 ● 契約中のSaaSの設定、manifest yaml の反映 ● アラートログをdumpして集計し、アラートの傾向を分析 ● エラーログが出た箇所を読み、原因を特定し、アラートとして扱うべきか判断する ● Sentry, Datadog, Kibana 色々なツールを組み合わせてリクエスト一つ一つを分析する ● 情報のないアラートに適切な情報が出るようにする ● フロントエンド起因でなさそうであれば適宜バックエンドのコードを確認したり MTGをセットする アプリケーションからプラットフォームまで、運用という 観点から広く関われて楽しい!

Slide 50

Slide 50 text

アラート改善活動の醍醐味 50 ● 古いアプリケーションを含めて、日経のサービスがどう動いているかを知れる ● サービスがどう動いているかを、チームや職能の垣根を越えて知れる ● 運用を考えることでチームや組織という点に目が向くようになる アプリケーション開発だけではできなかった成長の機会

Slide 51

Slide 51 text

これでアラートが正常化して めでたしめでたし!? 51

Slide 52

Slide 52 text

🌍💥 52

Slide 53

Slide 53 text

📞 53

Slide 54

Slide 54 text

54

Slide 55

Slide 55 text

_人人人人人人人人人人人人人人_ > On Call 当番をすっぽかす <  ̄^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄ 55

Slide 56

Slide 56 text

マナーモードでも特定の番号から電話が なるようにする設定を忘れずに! 56