Murga

個人的に言いたいコト・主張・気持ち。

本番作業でのミスをなくすためのアレコレ

みんなが知っておくべき運用設計のノウハウ

みんなが知っておくべき運用設計のノウハウ

ITシステムの罠31 システム導入・運用で絶対に失敗しないための本

ITシステムの罠31 システム導入・運用で絶対に失敗しないための本

個人の開発環境と違って、間違えてしまった時に甚大な被害を引き起こしてしまうのが本番環境。誰もがミスをしたくてするワケではないが、様々な要因の積み重ねで、問題を起こしやすいチーム、起こしにくいチームの差が生まれる。

今回は、本番作業でのミスをなくしていくための対策を色々と考えたいと思う。

「ミスしないようにする方法」と「ミスしても大丈夫なようにしておく方法」

本番作業による障害を防止するには、「ミスをしないようにする対策」を取るのはもちろんのこと。一方、忘れられがちなのが「万が一ミスしてしまっても大丈夫なようにしておく」という視点だ。

例えば、「rm コマンドでファイルを消す前に確認を怠らない」は「ミスしないようにする」考え方。一方、「ウッカリ rm コマンドを実行しても、いきなりファイルが消失しないように設定を入れておく」というのが「ミスしても大丈夫なようにしておく」という考え方に基づいた対策だ。

このように、間違えたり失敗したりしては困る作業に対して、間違えても元に戻せるようにする仕組みを準備しておけば、ヒヤリ・ハットで済ませられる。

ミスがそもそも起こりえない環境作りも大事ですね。(master branch にいきなり push できないようにする等)

こうした視点は個人の開発環境においても有用で、「設定変更やバージョンアップによってこれまでの環境が動かなくなってしまった」といったときのために、作業環境のバックアップをとっておいたり、実行前に「何かあった時に元に戻すためのコマンド」を用意しておいたりすることが、余計な時間を浪費せずに済ませるテクニックだ。

作業環境が区別できるようにしておく

「検証環境を触っていたつもりが、間違えて本番環境を触ってしまっていた」といった事態を防ぐためのアイデア。簡単にいえば、環境を絶対に間違えない目印を用意すれば良い、ということ。

コチラはコンソールのプロンプトに色付けを行い、検証環境と本番環境を色で見分けられるようにする、というアイデア。Red-Hat Linux や CentOS サーバなど CUI 環境で作業する際はこうした設定が有効だろう。なんなら ~/.bashrcecho 本番環境です といった echo 文を仕込んでおく程度だって良い。

Windows Server など GUI 環境のサーバにリモートデスクトップでアクセスする場合は、壁紙やウィンドウバーのカラーリングを変えたりしておくと良いだろうか。設定が自由に変えられなければ、デスクトップに「本番環境です.txt」みたいな空ファイルを置いておくだけでも効果はある。

大事なのは、こうした環境を区別する仕組みを用意した後に、メンバに共有しておくことだ。それを確認事項として手順書に盛り込んだりして定着させよう。

作業者の心構え

どれだけベテランだろうが、どれだけ気を付けていようが、ミスをやらかす時はやらかす。とはいえ、普段から注意を怠らないのは大事なことで、じゃあ何に注意するとミスを防げるか、作業者としての心構えを考えよう。

  • コマンド入力後、すぐにエンターキーを叩かない(数秒空けて再度確認)
  • rm, mv コマンドは一度 ls 等で確認しておき ls を rm に置き換えて実行
    • history から↑で戻って ls を backspace で削除し rm 入力
    • (history を使うなんて。。という派もいるので何とも言い難いですね。あくまで一例です
  • 手順書のある作業はコピペのみ、手入力しない
    • コピペで気をつけたいのがコピペミス。改行が含まれていたり
    • 一度エディタに貼り付けて改行コードがないことを確認すると吉
  • 今日こそミスを起こすかもしれないという緊張感を持つ
  • 常に一呼吸を意識する
  • 1人で解決しようとしない
  • 少しでも不安があるなら確認者をつける

パソコン素人がやらかしがちなのはコピペミス。自分はちゃんと目的のコマンドだけをコピーした、と思っていても、後ろに改行が入っていたり、前後にスペースが入っていたりする。「文字列選択はそういうことが多いから、一度メモ帳に貼り付けて確認しよう」という当たり前のことが当たり前にできない人は多い。一番最初は有識者が必ず隣で確認し、エンターは有識者に押させるようにして教育した方がいいかも。

自分がこれからやろうとしていることに本当に誤りがないか、誰が見ても明らかな方法で確認するというのは、本番作業に限らず大事なこと。未確認のまま「僕はちゃんとやりました」と言ったり実際に確かめてもいないのに推測だけで「そこは問題ないと思います」などと言うのは、全く信用ならない。明らかに大丈夫だと思っていることでも、省略せず改めて確認する。だから、何年目だろうと、本番作業が何回目だろうと、毎回必ず「コピペしたテキストを一度メモ帳に貼り付けて確認」するのだ。

ミスした時に周りに助けを求めやすく・復旧しやすくしておく

万が一ミスを犯してしまった時に、周りのメンバに助けを求めやすく、そして原因を特定し復旧を素早く行えるように準備しておくことが大事だ。

  • 現在困っている事や状態をハッキリさせる
  • 時系列を整理してみる
  • 操作履歴は追えるようにしておく

すなわち、「何をどの順で操作して、どういうミスをして、何が起こったか」を簡潔に説明できるようにしておくこと。「いやなんかいつもの流れで操作してたんで順番とか忘れましたけど知らないエラーが出て…」なんて受け答えをしようものなら、回し蹴りモンだ。

何かやらかしてしまったときに、その手順を再現したり、原因を特定する際に役に立つので、作業の履歴を必ず残しておこう。コマンドは History で追いやすいが、GUI 操作は順番や変更箇所を忘れがちなので、毎度紙に細かく記録していくとか、スクリーンショットを撮るとか、面倒でもそういう手間をとろう。

  • 実機上で試行錯誤せずに、まずは仮説を持ってみる

何かやらかした時に、慌てて手順書にない操作をしないこと。さらなる被害を拡大させることに繋がりかねないし、そうした勝手な行動による障害は組織としても個人をフォローしきれなくなるからだ。

責任感だけはいっちょまえなヤツ、もしくはプライドだけは高くて自分のミスを極端に嫌うヤツは要注意。組織の目線、全体最適というものを考えよう。慌てて操作する前に、やらかしたことを整理して周りに共有し、どうすると解消できそうか、周りと相談しながら十分に算段を立ててから実行する。

  • 失敗しても戻せる状態にしておく

まさに「ミスしても大丈夫なようにしておく」ということ。復旧用の操作を始める時は、必ず再鑑者に知らせた方が良い。やるべきでない復旧操作によってさらなる不備を起こさないようにするためだ。

可能な限り自動化する

ヒューマンエラーは人間が関わるから発生する。当たり前のことだが、なぜか人が目視で確認した方が確実だと思っている前時代的な人がいたりとか、「スクリプトが書けない・読めない」とかバカ丸出しのことを言い出したりとか、自動化するには工数が足りないとか言い出したりする。そうやって引き起こした障害対応の工数なんかもらえないのに何考えてるんだろう。

というワケで、バカのことは無視してさっさと自動化。毎回やる操作は些細なことでもスクリプト化しておこう。「今回だけ違う項目を間違えて選択して削除しまった」とか、「うっかりやり忘れた」ということを引き起こさないようにするのだ。

自分はレガシーな環境で何とか自動化していくための Windows バッチスクリプトを結構書いてきた。スクリプトに盛り込んでいた要素は以下のとおり。

  • いきなりスクリプトを実行しても本処理が動かないようにしておく
    • 「実行してよろしいですか?」というプロンプトを表示する作りにし、「y」を入力しないと開始できないような作りにしていた。
    • 事前に満たしておくべき条件がある (スクリプトの実行順序などがある) 場合は、プロンプト表示前に環境チェックなどを行って、その結果も表示しておいた。例えば「○○サービスが起動していません。本当に処理を開始しますか?」といった具合に。
      (前提条件を満たしていない時にスクリプトを実行不可能にするかどうかは場合によりけり。オペレーションによっては「今回はその条件を無視して良い」時もあったりするので。)
  • 実行前に実行前の状態が確認できるようにする
    • 例えばサーバを一時停止させるようなスクリプトを動かす時に、そのサーバのサービスが存在するか、動作中か、といった情報を取得して画面表示しておいた。こうすれば目視確認したいバカちんも安心。
    • その上で「このサーバを停止させます。よろしいですか?」といったプロンプトを用意すれば、一つずつ目視確認しながら作業できる。
  • スクリプトの処理結果も画面表示する
    • ちゃんと意図した操作が行えたのか、操作者が理解できるように画面に出してやる。
    • そのスクリプト以外に目視確認ができる方法があれば、そのやり方をプロンプトで説明したりすると親切。「念のため、タスクマネージャ上でも対象のサービスが起動していることを確認してください。」みたいな。
    • 異常終了する場合は、可能なフォールバック操作を提示したりする。「○○が起動できませんでした。a キーを入力すると本スクリプトを再実行します。手動で作業する際は b キーを入力してください。タスクマネージャを起動します」みたいに。
  • 処理内容をテキストファイルに出力する
    • 操作日時、実行前の状態、実行した処理、実行後の状態などの情報を、画面表示すると同時に、テキストファイルに出力し、証跡をファイルで残せるようにした。

本番作業を行う人は、対象のサーバで使えるスクリプト言語のスキルを付けておくべきだ。一度作ってしまえば二度と間違えない。

とにかく手順書を充実させよう

これほど怖い本番障害なのに、それでもなお「手順書」をまともに書かない、書けないチームが多い。

これは、文章を書く時に「自分にとって必要な情報」しか書けない人が多いからであろう。

例えば、コマンドを暗記している人はコマンドをいちいち書かずに「○○ディレクトリに移動し、プロセスを起動する」といった手順書を書きがちだ。一方、コマンドを覚えていない初心者は「cdstart hoge」などとコマンドを羅列するだけだったりする。

そうではなく、どちらも必要な情報なのだ。「○○を△△にするため、cd コマンドで○○ディレクトリに移動し、start hoge コマンドで hoge を△△にする」と書くのだ。コレが「誰が読んでも同じように理解できる文章」になる方法だ。

こういう配慮や思考が出来ないのであれば、自分一人で考えるのは無駄なので辞める。チームで相談して手順書のフォーマットを決め、そのフォーマットを埋めるように手順書を書くようにしよう。

やらかしたあとの対策の考え方

さて、何かやらかしてしまって、障害自体はなんとか復旧できたが、「二度とこんなことが起こらないように対策を考えろ!」と顧客に怒られる。そこで「もっと確認を徹底します!」と答えてしまうような人間がエンジニアを名乗っているのだからつくづく泣きたくなる。

人間というコンポーネントを再発防止に入れない

何度でもこの一文を読みたい。人間はどれだけ気を付けていようといつかは絶対ミスをするのだ。ゴールド免許のドライバーは、20年・30年無事故だろうと、それはたまたま。明日事故を起こすかもしれないし、実際に事故を起こしたら「でもこれまで30年無事故でしたから」と言ったところで何も変わらないのだ。

良い再発防止策について、順位付けするとしたら、

  1. その種類の問題について二度と意識することがなくなる解決策
  2. その種類の問題を開発時に自動的に検知することができる解決策
  3. その種類の問題が発生しても自動的に復旧することができる解決策
  4. その種類の問題が発生しても影響が局所化される、フールプルーフ、フェールセーフになる解決策

このような順序でしょうか。

つまり、なるべく自動化することと、ミスしても被害が少なくしておくための「仕組み」を整備することが大事なのだ。

悪い再発防止策は、シンプルで人間というコンポーネントを使うことです。

  • 責任回避のため稟議、決済経路を追加する策
  • 他者の努力/忍耐/根性の不足を指摘し改善を求める策
  • 個人/チームの注意力を原因とし、「より注意深く確認します/させます」といった策
  • それっぽい言い訳付きのダブルチェック/トリプルチェック体制
  • ドキュメントにその旨追記します!的な解決策

これは、そんなことやらないよと思っていると、ついついやってしまいがちなので注意が必要です。
「ちゃんと」「しっかり」というフレーズが出てきたら、危険信号です。

「しっかりと」とか「十分に」とかいう言葉って、何をどれだけやるかも不明瞭だし、そもそも障害を起こした時は「(作業者の意識が) きちんとしていなかったのか」というと、大抵は「きちんとやっていたつもり」なのだ。だからこういう気持ちや努力、忍耐みたいなことをほざく連中は顎の骨を砕いて黙らせておいた方が良い。

意味のある対策・予防策をとれますように

レガシーな環境、レガシーな人間に引っ張られておかしなことにならないよう、知識量と実績と仕組み化でぶん殴っていこう。