VSCodeの操作ミスでGCP Cloud Composerの裏側k8sをお掃除した話

# tl;dr
- 筆者はvim派でVSCode初心者。でも勧められたので数カ月ぶりに起動してみた。
- Pluginを色々入れていたので、サイドバーにはたくさんのアイコン。なにこれ楽しい。
- Cloud Codeタブを触っていたら…指先が震えてトラックパッド誤操作。「Delete Cluster」を押してしまう。
    - その時たまたま偶然、GCPのオーナー権限を持つIAMで認証していた。
- :angel:
- 盛大にやらかして復旧が手間だったが、いくつかの理由で障害として顕在化しなかった。

というお話
# 何をやらかしたのか

やらかし当時、筆者はGCPでデータ処理基盤の開発を行っていました。vimとzshが大好きで、開発のすべてをこの2つで済ませてましたが、同僚にVSCodeを猛プッシュされたので使ってみることにしました。

VSCodeは数ヶ月前にインストールしたもののそのときは結局使わず。数ヶ月ぶりの起動でした。
インストール時にプラグインを色々入れていたようで、左のサイドバーにDockerやk8sなど、面白そうなタブが沢山出てきました。

興味をそそられたので、1つ1つ見ていると、Google Cloud Codeのタブが。
開いてみると、稼働中のGKE(k8s)クラスタが列挙されています。 普段`kubectl`や`gcloud`でlistする項目が一覧できるのに感動。VSCodeではGCPの設定していないのですが、端末上のGoogle Cloud SDKの認証情報を自動的に使ってくれているようです。

なんの気無しに、あるクラスタを右クリックします。クリックしたのはデータ変換のバッチ処理を実行している、Cloud Composer(ManagedなAirflow環境)のバックエンドのk8sクラスタでした。

<img width="299" alt="img1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56445/744b4a05-834f-3fd1-026a-a5c7a1278d3f.png">
右クリックしたところ (後日サンプルPJで再現してみたときのスクショ)

今は使う必要がないので、適当な場所を左クリックしてメニューを閉じた、**はずでした**。
一瞬手が震えてトラックパッドのカーソルが変なところ(例えば「Delete Cluster」の上とか)、に移動した気もしましたが、気のせいでしょう。リストからクラスタ消えてないし。確認ダイアログも出さずにクラスタまるごと消去なんてしないよね。

# やらかしの結果何が起きたか

1時間後、Composerのバッチジョブ停止を表すアラートが発報。事態に気づきました。
急いでGCPコンソールに行くと…Composerは普通に生きてる、ようにみえる。でもより詳しく調べると、なんとバックエンドのk8sが存在していませんでした。これではジョブも実行されません。

恐る恐るGCPのStackdriver Loggingでログを検索すると、自らの手でクラスタを葬ったログが現れました。このときの絶望感たるや。

運の悪いことに、その時GCPのオーナー権限でCloud SDKをActivateしており、VSCodeもそれを継承。オーナー権限でもってk8sを消し飛ばしたようです。

# どうなったのか

結論からいうと、顧客に直接影響する障害は発生しませんでした。

Composerのバックアップとして別のジョブランナーがあり、こちらが働きました。ジョブランナーが2つ存在する設計は好ましくないかもですが、今回は幸いしました。
また仮に2つのジョブランナーが落ちても24時間までは一切機能に影響せず、72時間までは軽微なデグレで済む設計になっていました。

この設計をしたチームメンバーに感謝です。

# どう復旧したのか

まだ障害になっていないとはいえ、早急に復旧させたいところです。
今はComposer環境は生きているが、k8sはまっさらな状態。下図の緑の部分が存在しません。

<img width="694" alt="https___cloud_google_com_composer_docs_images_architecture_svg_hl_ja.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56445/12e6a633-ec2e-bd3d-07d0-9115665a4dec.png">
[Cloud Composerドキュメント](https://cloud.google.com/composer/docs/concepts/overview?hl=ja) より、Composerのリソース説明

環境を維持したままk8sだけ作り直せないか調べると、[ドキュメント](https://cloud.google.com/composer/docs/concepts/overview?hl=ja)に無慈悲な一文
> 注意: Cloud Composer が使用している GKE クラスタを削除した場合は、環境を削除して新しい環境を作成する必要があります。

はい。作り直しました。

バッチ処理の内容を記述するDAGファイル等はGCSに保存されているため、新環境への移行は簡単です。

その一方で想定外に厄介だったのは、処理中に参照するAirflowの環境変数たち。
GCP側で管理しているCloud SQLにおそらく存在したものですが、このSQLサーバーへのアクセス手段が当時は判らず。手動ですべて再設定しました。この作業時にはAirflow中の環境変数をドキュメントで一覧できるようにしていたのが幸いしました。

…今考えると、AirflowのWebUIは生きていたかもしれないので、そこからSQLサーバー叩いて情報バックアップできたかもですね。

環境再構築後、ジョブを再開させて正常な状態に復旧しました。

# 惨劇はなぜおこってしまったのか

直接的な引き金はオペミスですが、

- 本番環境のオーナー権限をActivateしっぱなしにしていたこと
- その状態で、不慣れなツールを使ったこと(ツールに責任転嫁するつもりはないが)

が事故の主要因だと思っています。

    
# 二度と惨劇を起こさないためにどうしたのか

決めたことは平凡・シンプルで

- 本番環境作業後は、シェルのデフォルトプロジェクトを別PJ(Sandbox用)に向ける 
    - 追記: Cloud Codeの場合これでは不十分 [^1] 
- オペミスは起きるので、すぐ復旧できるようにする

の2つを守ろうというもの。

ただ目標は決めたが「後はこれを守れるよう頑張って運用しよう」な状態。これだとまた事故るため、自動的に上記を担保できないか、試行錯誤を進めています。

ところで、今回の事故はVSCode(とCloud Codeプラグイン)が原因だったのですが

- ツールに責任はない。今後も新しいものどんどん使ってゆこう。

との方針は再確認されました。

# 不幸中の幸いだったこと

やらかしの規模の割に被害が出なかったのは、次の理由のおかげと思っています

- 設計が全体的に優秀だった
    - 冗長化や、インシデントの障害化までの時間稼ぎがうまく考えられていた
- アラートがちゃんと出た
    - Composer監視のバッチジョブをComposerで実行していたらアラートは飛ばず、発覚が遅れていた
- 復旧手順がドキュメント化されていた
    - (本文中では書いていませんが)Composerの環境構築法や、環境変数一覧をまとめていたのですぐ復旧できた
    - 本当はスクリプト化までできれば完璧かも　
- バッチジョブの冪等性が担保されていた
    - Composer再構築に伴い、旧環境で実行済みのジョブが再実行されることがあった。でもジョブの冪等性が担保されており問題にならなかった。

特別なことはしていませんが、これらのおかげで助けられました。

もう二度と「やらかし」とは無縁でいたいですが、不注意でのミスは多分また起きます。
その際にいかに障害化させないか、日頃から気をつけてゆきたいです。

[^1]: (2019/12/10追記) 1アカウントに本番環境のプロジェクトとSandbox用プロジェクトの2つを紐付けてあり、必要に応じてデフォルトプロジェクトを切り替えていました。シェルならこの方法でよいのですが、Cloud Codeはアカウントに紐付けられた全プロジェクトを列挙してしまうため、これだと十分な対策になっていませんでした。Cloud Codeにissue立てるか。 (@74th さん、ありがとうございます)