2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
リンクをコピー
記事をブックマーク
原トリ氏:(スライドの「You build it, you run it」を指して)この言葉、聞いたこと、見たことがある方がいるかもしれません。これは、2006年にACM(Association for Computing Machinery)という団体が、Amazon AWSのCTOであるワーナー・ヴォゲルスに対して行ったインタビューの最中に彼が言った言葉です。
ACMは、チューリング賞の表彰をしていることで有名な団体です。この「You build it, you run it」という言葉自体はそれなりに有名だと僕は思っていますが、この言葉をそのまま読むと、「作ったら運用しろ」という意味になりますね。しかし、それだけではない、この言葉に込められた意味を深く理解してもらうために、この言葉が使われた前後の文章も見てみようと思います。
インタビュー全体はそれなりの長さがあります。ほかの部分での会話の意図も汲みながら僕が日本語にしていくので、多少意訳も入りますがご了承ください。
「You build it, you run it」が入っている一節はこんな言葉から始まります。「アプリケーション開発者が運用上の責務を持つことで、サービスのクオリティが、ユーザーあるいはお客さまの視点からもテクノロジーの視点からも、よりよいものになる。
伝統的なモデルでは、一度ソフトウェアを書いたら開発と運用の間にある壁、その向こうに開発したソフトをポンと投げて、あとは忘れてしまう。Amazonはそうではない。
作った者自身がそれを実行・運用する。
この考え方を実践することで、開発者は日々のオペレーション、運用と直接接することになる。それによりサービスを外で触っているお客さまの声が開発者に直接届くようになる。このお客さまからのフィードバックループが、サービスの品質を向上させるうえで非常に重要なんだ」。
この文脈で、Amazon AWSのCTOであるワーナー・ヴォゲルスは「You build it, you run it」と言っているわけです。僕はこの言葉と、その背景にある今話してきた内容がとても好きで、すごく納得感があります。ただ、こう思う方もいるはずです。「とはいえ、運用に知見のある人や、チームに運用業務を集める・運用チームを作るのって自然な流れじゃないか?」。そうです。開発者や運用に限らず、マーケティングもそうだし、人事もそうだし、業務を細分化して専業化するのは、会社組織であれば必然的な流れです。
では何が問題なのかと言うと、「コードを書きました、あとはよろしく、さようなら」という開発者の姿勢が問題だと言っているわけです。組織図上、チームが開発と運用に分かれていること自体は特に問題ではない。開発と運用の両者が共通のゴールを持って、共同して、運用上の責任を持つことがとても大事だと。なぜなら、運用性に優れたソフトウェアは、運用を無視した開発からは生まれないからです。
では、なぜ運用性に優れたソフトウェアが重要なのかについて話しましょう。(スライドを指して)これは見慣れたサプライチェーンです。コードを書き、それがビルドされ、テストされてデプロイされて、デプロイした後はモニタリングをして、うまくいっているようであればさらにロールアウトを進めて、うまくいっていないようであればロールバックをする。非常によくあるサプライチェーンです。
ここで重要なのは、開発した時点のソフトウェアには価値がないということです。運用フェーズに到達して初めて、ユーザー、お客さまに価値を提供できます。
つまり、ソフトウェアというのは価値を提供するために、基本的には運用フェーズに向かいますが、開発段階で見て見ぬふりをした複雑性は、すべて後段にある運用フェーズに押し込まれるわけです。
開発から押し込まれた複雑性はどうなるか。運用に不必要なワークアラウンドを生みます。運用で生まれてしまったワークアラウンドは、将来開発者が新しい機能を作ろうという時や、何か変更しようという時に、予期しない制約を作り出します。
つまり、このサプライチェーンはコードから運用、開発から運用に向かう一方向に見えますが、実際にはここにループがあるんです。ソフトウェア開発者が本質的な機能開発に集中するために、開発者が運用に参加して、運用者が開発に参加して、包括的な、ループするサプライチェーンの品質を向上させるべきだ。これがここまでの結論です。
(スライドを指して)では、「運用性を損なう実装8選」です。たくさんあるのでどれにするか非常に迷ったんですが、今日はライトなものから、忘れがちだけどありそうなものまで8つ用意しました。カジュアルに見ていきましょう。
1つ目は、スケールアウトできない、しにくいアプリ実装です。よくない実装例としてどのようなものがあるか。アプリケーションの状態をローカルディスクに、あるいはローカルディスクから読み書きしているコードです。
(スライドを指して)これはNode.jsのコードです。ユーザーIDのサフィックスをつけたファイルにセッションを書き出している。AWS環境の構築をしている方は、これを見れば笑うと思います。「こんなことしたら、Load BalancerのスティッキーセッションをONにしないとうまくいかないじゃん」と。こういう実装はよく見るし、いろいろなお客さんと話をしていると本当によくあるんです。
では、この実装の何が問題か。こんな実装になってると、マシンの台数を増やせません。この実装が入っていると、Load Balancerが前に置かれてアプリケーションが複数台後ろに並んでいる場合、どこにリクエストが届いたかによって、ユーザーはログアウトした状態みたいになってしまうんです。そのため、マシンの台数を増やせません。
では、マシンの台数が増やせない、スケールアウトできない場合にはどうするか。スループットを上げるために、マシンをスケールアップする必要性が生まれます。そうすると、台数は増えず1台の性能が上がっただけなので、確かにスループットは高まるかもしれませんが、そのマシンが故障した時にサービス全体に与える影響がとても大きい。
さらに、基本的にスケールアップの限界はスケールアウトよりも早いです。そもそもアプリケーションの実装として、スケールアップしたマシンのリソースを全部使い切れないなんてことがあります。例えば、AWS上でEC2インスタンスを使っているのなら、EC2インスタンスのタイプは有限なので「これより上の性能はない」というケースもあり得ます。
では、どう実装すればよいか。アプリケーションの状態は外部に永続化しましょう。例えばRDS(Amazon RDS)のようなRDBMS(Relational DataBase Management System)やS3、あるいはElastiCache Redisもよく使われます。状態を外部に永続化していない、例に挙げたような実装が非常に運用を難しくするわけです。
2つ目は、依存パッケージ解決を自動化できない。よくない実装例を見ていきましょう。「そのライブラリはこのURLからダウンロードしてきて、libフォルダに置いてビルドすればとおりますよ。バージョンはよくわかりませんが、最新を使っておけばいいんじゃないですか。社内共通ライブラリは共有ファイルサーバーにあるので、コピーしてきてください」。最悪です。
何が問題か。新バージョンのデプロイのたびにどのバージョンを使うのか確認したり、開発と運用の間でのやり取りが必要になったりします。あるいは、手作業でダウンロードして配置することが必要になる。チーム間の依存関係が発生することによって、デリバリ速度が低下します。さらに、意図しないライブラリバージョンを入れてしまうようなミスオペレーションが発生する可能性がある。
では、どうすればよかったか。これは当然の解答ですが、利用しているプログラミング言語やフレームワークでサポートされている、依存解決ツールを使いましょう。
社内共通ライブラリは、エンタープライズなみなさんにはよくある話です。僕個人の意見でもありますが、どうしても依存解決ツールをサポートしていない社内共通ライブラリのようなものを使う必要がある場合は、共有ファイルサーバーから持ってくるより、アプリケーションリポジトリにバンドルするほうがマシだと考えています。
3つ目は、安全に停止できないアプリケーションがたくさんあります。よくない実装例として、処理中にSIGTERM(アプリケーションの終了指示)が送られてくる可能性をまったく考慮していないコードが書かれている。
考慮していないだけならまだいいのですが、SIGTERMやSIGKILLを受け取ると異常終了します。SIGKILLの場合はKILLなので、異常終了するのが正しいのかもしれませんが、SIGTERMを受け取って異常終了するのはいただけません。
何が問題か。例えば、異常終了によってデータベースに記録されたデータが不正になってしまう。あるいは、デプロイをする時に、エンドユーザーに500系のエラーが返ってしまう可能性がある。さらに、それらを防ぐために、ワークアラウンドとしてデプロイ時にサービスの提供を中断してデプロイしなければならなくなると、ユーザー体験が悪化する。
では改善策は何か。SIGTERMを受け取ったら、終了処理をきちんと行う実装を追加しましょう。ただし、これは簡単ではなく、処理中のデータの取り扱いまで含めて設計のレベルできちんと考慮されている必要があります。あるいは、Webアプリケーションフレームワークなどによって、一定程度終了処理が実装済みであることも当然必要です。
4つ目は、起動処理が長い。よくない実装例として、メチャクチャでかいデータを起動時にダウンロードする処理が書かれている。何が問題か。起動がコンテナオーケストレータのタイムアウトの範囲内に収まらず、デプロイが失敗します。そうなると運用でなんとかカバーしようとする。これも運用業務を非効率化するのでよくありません。また、基本的にデプロイ処理はサービスが多少不安定になっているタイミングなので、長時間に及ぶこともあまりよろしくない。
では、どうするか。起動時の初期処理から、長い時間ダウンロードするような処理を外す方法を検討しましょう。例えば、コンテナイメージを作る時にバンドルするのはどうでしょう。
5つ目は、ビルド/パッケージング前に手作業が必要なアプリケーション。コードに設定値や環境依存のパラメータが直接記述してあるので、これを手で書き換えるところから、ビルドの前にまずこれを書き直すところからやっています。
これの何が問題か。(スライドを指して)そもそも右の例は非常に危険です。さらに、ビルドやデプロイの前に必ず手作業で設定値の書き換えが必要になるので、非常にアジリティを低下させます。ミスオペも怖いです。環境別にコンテナイメージを作る必要が出る可能性も高まります。では、どうするか。環境変数から設定値や環境依存のパラメータを読み取るように実装を変更しましょう。実行時にパラメータを渡せるようにしましょう。
6つ目は、ビルド/パッケージングの前に手作業が必要の続きです。設定値を実行時に外部から注入できないことってありますよね。環境名、プロダクションならこういうホスト名、ステージングならこういうホスト名ということがあります。あるいは、設定値は設定ファイルからのみ読めるなど、実装が実行環境の環境名などに依存している。まさに(スライドを指して)右の例です。
何が問題か。一番わかりやすいのは、環境を増やそうとした時に、コードを書き換えたり、追記したりすることが必要になります。5つ目と同じで、ビルドやデプロイ前に手作業で設定値を書き換えることが必要になる可能性もあります。環境別にコンテナイメージの作り直しが必要になる可能性も、当然あります。
改善策も同じです。全部ベタ書きしてしまうのではなく、実行時のパラメータとして、環境変数から読み取れるように書き換えましょう。そもそも環境名、プロダクションやステージングは単なるラベルなので、この名前をもとに処理の挙動を変更するようなものではあってはならないですよね。
7つ目は、ログをファイルにしか出力できない。ログのファイル名などがベタッと書かれていて、そこにしか出せない。これの何が問題か。ログを見るためにコンテナの中に入って中を見るのかということです。入ろうとしたコンテナが直前で異常終了して、ログごと全部消えていたら困りますよね。
「では運用でワークアラウンドしましょう。NFS(Network File System)を使えば大丈夫。」これ、ログのためだけに不要に複雑化したアーキテクチャにする必要がありますか?と思いますよね。アプリケーションのログは、ローカルで開発している時はファイルに出ていていいんです。でも設定によって、実行時パラメータによってログがきちんと標準出力/標準エラー出力に流れるように実装しましょう。
最後、8つ目は“Readレプリカ”を使えないアプリケーションがあります。よくない実装例は、RDBMSやMySQLなど接続を永続的に持つタイプのデータストア、わかりやすいやつです。1つの接続先しか想定していないコードがたまにあります。
これの何が問題か。書き込み用と読み取り用のデータベースに分けることによって、システム全体のパフォーマンスを向上させるテクニックが使えなくなってしまいます。それによって何が起きるか。必要以上にデータベースをスケールアップしなければいけなくなる。
改善策として、少なくとも書き込み用と読み取り用の2つのデータベースを接続先として利用するケースを想定してコードを書きましょう。だいたい、どんなWebアプリケーションフレームワークもO/Rマッパーも使えるようになっています。
8つ挙げましたが、他にもたくさんあります。
この辺りについては『The Twelve-Factor App』を読みましょう。僕がセッションをすると毎回出てくると思いますが、自分が運用を意識したコードを書けているかを評価するのに最適です。
(次回に続く)
関連タグ:
2024.12.20
日本の約10倍がん患者が殺到し、病院はキャパオーバー ジャパンハートが描く医療の未来と、カンボジアに新病院を作る理由
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.17
面接で「後輩を指導できなさそう」と思われる人の伝え方 歳を重ねるほど重視される経験の「ノウハウ化」
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05