839の日記

趣味の話を書くブログです。

GCP Projectを消しちゃった話

この記事は「本番環境でやらかしちゃった人 Advent Calendar 2019」の7日目です。
qiita.com

個人の趣味でやっていたやらかしなので、あまり大した内容ではありませんがご容赦ください。。

背景

趣味で運用していたVPSのサーバをGKEに移そうとしていました。
段階的に移行を進めていたため問題が発生した時点ではapp群はVPSで動いており、Cloud DNSのみGCPに移行済みな状態でした。

なぜ起こったのか

Firebaseのプロジェクトを消してしまい、それに伴ってGCP側のプロジェクトも消えてしまいました。
背景に記載した通り、段階的に移行を進めていたことと以下のような理由が重なり消した直後は気づいていませんでした。

  • HTTPアクセスによる外形監視を入れていなかったため、VPS上のサービスが接続不可になっていることに気づかなかった
  • VPS上のプロセス監視(mackerel、god)は正常にプロセス数が保たれているため、アラートを上げなかった
  • appレイヤのエラーは出ていないのでSentry等にも通知されておらず、気付きが遅れた
  • 新幹線の中で作業していたため、様々なフィードバック(e.g. twitter)に気づいていなかった

app側のテストで一部データを直接本番から取得するという邪道をとっていたため、手元でテストを回したタイミングで異常に気づきました。
本来ならリクエストをモックしてテスト時に外部アクセスは遮断するほうが良いケースが多いのですが、今回はこれに助けられました。

そもそもなぜFirebaseを消したのか

Firebaseを消した理由はFirestoreの選択するリージョンを間違えたためです。
特に深い理由もなくus-centralリージョンを選んだのですが、以下のような理由で取りやめようとしました。

  • us-centralは冗長化されており、料金が高い
  • us-centralは遠いので自分が作業する際にもレイテンシが大きくなる

流れとしては選択後にリージョンを変える方法を探したのですがプロジェクトを作り直すしかないという結論になり削除しました。
そのとき裏で紐付いているGCP Project側も一緒に消えるとは思わずに…。

GCP ProjectとFirebase Projectの関係性は以下のドキュメントに記載されています。
Firebase プロジェクトについて理解する  |  Firebase

プロジェクトを削除すると、Firebase の GCP の両方で削除されます。

(「Firebaseの」と書かれていますが「Firebaseと」の誤訳ですね)

思い込み

なんとなくGCPとFirebaseが紐付いていることは把握していたのですが、もう少し隔離された形で紐付いているだろう、と内心で決めつけていました。
私がイメージしていたのはFirebaseの状態はGCPのcomposerのWeb UIのようにTenant Projectで別管理されているだろうと思っていました。

f:id:husq:20191204203504j:plain

※図のTenant Project部分がFirebaseのイメージだった

そのためFirebase(Tenant Project)側を削除してもGCP(Customer Project)側は消えないと深層心理で流してしまっていたのですが、
そんなことはドキュメントに書かれていないので危ない思い込みだなぁと今回のことを振り返って思います。
(むしろちゃんと両方削除されると書いてある)

起こったこと

AレコードのTTLが比較的長めに設定していた(ちゃんとした長さを覚えていない)ので、繋がったり繋がらなくなったりということが発生していました。
そのときはGCP Projectが消えているとは思っていなかったので、どうしたのかなーというぐらいの気持ちでした。

テストが手元で通らなくなったりしておかしいとは思っていたものの新幹線の中で4Gテザリング状態だったので、
単純に電波の状態が悪いのかも、という背景も悪影響でした。

結局digコマンドを叩いてみて「DNSがなんかおかしい」ということに気づき、
Cloud DNSの設定を見に行こうとしてGCP Project消えてるじゃん!!!と問題の発見に繋がっていきます。
それに気づいた後は新幹線の中で冷や汗をかきながらプロジェクトの復旧作業を行いました。

GCP Projectは削除後30日まで復旧することが可能です。
どのくらい復旧するのかというと割と全部復旧しました。
うろ覚えですが、一部APIが無効化されていたものもあったような気がします。
移行作業の検証中だったのでGKEクラスタもプロジェクトの中にあったのですが、それも少し待つと正常に稼働し始めました。

最後に

正直気をつけましょう以外に言うことはないです。
業務で本番環境のGCP Projectをうっかり消してしまうということはないと思うのですが、こういったケースのために外形監視を早めに導入しておくと安心感があるかもしれません。
色々比較検討したのですが、自分は外形監視に uptimerobot.com というサービスを利用しています。

また、既に稼働しているGCP ProjectでFirebaseのリージョンをミスると大変面倒くさいことになるのでこちらにもご注意ください。

追記 19/12/07 16:00

id:rryu

同時に作成するのではなく既存のGCPプロジェクトにFirebaseを追加するということができるようなのだが、その場合でも問答無用でGCPプロジェクトが消されるのだとしたら怖すぎる。

今回は言及されているパターンで、既存のGCP ProjectにFirebaseを追加し、その際にFirebaseのリージョンをミスったのでFirebase側を消そうとした形です。
このことから考えると既に大きなGCP Projectを運用していて新規でFirebaseを追加したもののリージョン選択をミスってしまい、うっかり消しちゃうとかはあるかもしれませんね…。

k8sのingressでクライアント認証を行う

クライアント証明書をiPhoneに入れる - 839の日記 の続きです。
k8s側にセットするのも書いておきます。

とは言ってもingressにクライアント証明書をセットするのは非常に簡単です。
まず先の記事で作成したkey/certを使ってk8sのsecretを作成します。

kubectl create secret tls hoge-secret --key client.key --cert client-ca.crt

作成したsecretをもとにingressを設定します。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: hoge-ing
  annotations:
    nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
    nginx.ingress.kubernetes.io/auth-tls-secret: hoge-secret
spec:
  rules:
  - host: hoge.com
    http:
      paths:
      - backend:
          serviceName: hoge-svc
          servicePort: 80

上記の設定で指定したホストにアクセスしたときにクライアント認証が走ります。
OAuth認証Basic認証などの代替手段もありますが、クライアント認証が一番手軽でセキュアにできるので個人的によく使っています。

クライアント証明書をiPhoneに入れる

背景

自分しか使わないけどhttp経由で家以外でも見たい、というケースがたまにありクライアント認証を挟むようにしています。
そしてiPhoneにクライアント証明書を入れたくなり、毎回忘れて調べているので記事としてまとめます。
作業はmacOS前提です。

方法

まず以下の手順でkeyとcertを用意し、p12ファイルを作成します。

openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj '/CN=example.app'
openssl x509 -in client.csr -out client-ca.crt -req -signkey client.key -days 3650
# パスワードを要求されますが、後の手順で使うので覚えておいてください
openssl pkcs12 -export -inkey client.key -in client-ca.crt -out mobile-client.p12 -name "Example Client Certificate"

次に以下のアプリを入れます。

Apple Configurator 2

Apple Configurator 2

  • Apple
  • ユーティリティ
  • 無料
apps.apple.com

アプリを開いたらCmd+Nで新規プロファイルを作成し、証明書を選択し先程作成したp12ファイルを選択します。
パスワードはp12ファイルを生成するときに指定したものを入力してください。
Cmd+Sで名前を付けて保存してください(e.g. client-cert.mobileconfig)。

作成されたmobileconfigを渡す方法は一旦Apple Configurator2を閉じ、デバイスmacに繋ぎます。
PCを信頼するか聞いてくるので信頼しておいてください。

その後、Apple Configurator2を開くと自分のデバイスが出ていると思うので選択し、画像左上の方にある追加でプロファイルを選びます。

f:id:husq:20191204233053p:plain

finderが開くので先程生成したmobileconfigファイルを選択するとiPhoneにプロファイルが転送されます。
iPhone側では一般->プロファイルの欄でダウンロード済みプロファイルの欄にプロファイル情報が表示されています。
そのプロファイルをタップしてインストールをするとクライアント証明書として利用可能になります。

クライアント証明書が必要なサイトをPCからChromeで閲覧しようとすると証明書の選択というのが出ますが、iPhoneSafariはそういう表示は出ません。
証明書が適切に選択されていればそのままWebサイトを開くことができます。