セッションの内容と会社紹介

森雄祐氏(以下、森):よろしくお願いします。「ステージング環境でバッチリ検証したけど、本番で沼った話」ということで、失敗した話でできればと思います。

私ですが、株式会社Handiiという会社でCTOをやっている森と言います。ふだんはRustでサーバーサイドのコードを書いていることが多いです。前職ではずっとC++や、C#とかを書いていました。弊社はフロントがTypeScript、Reactで書かれているので、ReactとTypeScriptもちょっと書けます。エンジニア募集中なので、もしよろしければよろしくお願いします。

「そもそもHandiiって何やっている会社なの?」ということで、いわゆるFinTechですが、法人向けの決済というところで、弊社もBtoB向けで、法人で決済ができずクレジットカードが作れないとか、そういう会社さんに向けて、法人向けのプリペイドカードサービスみたいなものを展開しています。

スライドの絵に描いてあるとおり、ポチポチポチとやったらカードが何枚でも作れるみたいな、そういう類のプロダクトです。営業に全部配って、経費精算とかしなくて済むようになる、そういうサービスです。

しくじりが起きたプロジェクトの概要

ということでサービス紹介はほどほどにして、本題の「ステージング環境で検証したんだけど、本番であんま上手くいかなかったよ」という話をします。

まず今回話すプロジェクトに関して、ちょっと概要を説明します。弊社は要するにプリペイドカードの決済サービスなので、Webの画面から明細などがいっぱい見れます。そのデータをとある外部のプレーヤー、サービスから参照してもらい、いわゆるサービス連携を開発しましょうということになって。

そこで、弊社が参照されると。弊社は参照系のAPIをいくつか新規で開発して、開発が終わりました。で、ステージング環境をまずは相手に渡して、そのステージング環境をもとに先方が開発をするようなかたちで進めます。

弊社は「ここおかしいんですけど」というようなところを修正していきながら、先方は先方で本開発が終わったら「よし、せーの」で本番デプロイ、というような流れのプロジェクトです。

ステージング環境の構成

ステージングの環境ですが、弊社はAWSを使っているのでロードバランサーがALBです。その下にコンテナがベロベロとぶら下がっているような構成。簡単に言うとそんな感じです。

スライドの左上に書いてあるのが、普通のクライアントです。ステージング環境なので、実際のユーザーさんが使うわけではありませんが、ステージングの画面です。普通のホスティングされた画面をテスターというか、開発者などが「これ動いているかな」と検証用に使ったりする画面があるので、そこを叩いています。

本番デプロイでエラー発生

左下のサーバーみたいな絵が、要するに今回一緒にやったプレイヤーの場所です。開発終わった、「よし、本番デプロイだ!」と思ったら、メールがきて。

要するに「上手くいっていません」と。エラー内容が共有されて、見てみると「Service Not Found」みたいなことが書いてあるわけです。「えー⁉︎ なんで⁉︎」と。「我々は作ったのだが」みたいな気持ち。で、本番もデプロイしたんです。

「なんで?」となってよくよく考えたら、要するに開発用なので、ドメインをそんなに分けていなかった。本番に関してはサードパーティのサーバーが叩くものと、ユーザーが叩く部分はドメインを分けていて。「あ、そーだそーだ」「ユーザー向けと別ドメインなんだ」と思い、別ドメインの設定を入れなきゃいけない。

しかも別ドメインの設定を入れてもロードバランサーは共有のものなので、「あれ、このままではちょっと想定していたルーティングがされないぞ」「どうしよっかな」という話になり、社内でも相当の混乱がありました。

ルーティングのルールの修正などを、「とりあえずドメインにエイリアス貼って。あれ、でもこれってどのコンテナにどう流すんだっけ?」「どうすればいいんだ!」という話で揉めに揉めて、「あかんあかん!」という感じになりました。

結局ロードバランサーに本来設定されているべきドメインのエイリアスを貼って、アクセスされたドメインに合わせて適切なルーティングがされるような構成に一応修正の開発を入れて、「あ、よかった」と。「いい感じに設定が完了しましたね」と思ったら、またメールがくるわけです。「エラーです」と。

「え⁉︎ なんで?」。証明書不正です。当然HTTPSですが、ドメインが変わったので、今までついてたロードバランサーの証明書だとダメです。

「そうだそうだ。言われてみればそうだわ」と思って、証明書を複数くっつけられるので、いい感じにくっつけて設定完了。「よかったー」「これでいけるやろ」と思って、待っていると、なぜかエラーのログが流れてくるわけです。

「え、なんで?」「今度は何?」。弊社では認証をJWT、JSON Web Tokenでやっていますが、Invalid Issuerというエラーが出ていて。要するにですね、これって「JWTを生成リクエストしたのが誰ですか?」という話です(笑)。

もともと検証していたissuerはドメインが変更になるので、当然検証すべき値はズレます。「言われてみればそうか」と思って、新しいドメインに合わせて正しいissuerの値で検証するように変更することで、やっといい感じに設定が完了して、今度こそ本番でちゃんと動きました。

本番は本番、ステージングはステージング

最初に言ったとおり、僕はふだんサーバーサイドのコードを書いていることが多いです。インフラ関連とかに対して、そんなに知見が深くないのもあり、「アプリケーションコードを開発しました。ステージングに入れました。相手とも疎通が取れたから、うまくいくでしょ」って思って(笑)。ただやはり本番は本番、準本は準本なので、うまくいくのは本番疎通が取れてから、ということだと思います。

社内でも「もう来週にはたぶん出ると思います」と言ってしまっていたので、けっこうその後の調整などで慌ただしくなってしまって、失敗したなという話です。

一応これ「しくじり先生」という名前なので本家に合わせて1句ということで、「本番で 疎通するまで 気を抜くな」という1句で締めくくりたいとと思います。以上です! ありがとうございました!

質疑応答

田仲紘典氏(以下、田仲):ありがとうございました。本場のしくじり先生どおり、ちゃんと1句を作ってくれたのちょっと初めてで、感動しました(笑)。ヤバいのが3段構成であったと思いますが、まず質問で入っていくところは、ステージング環境と本番環境の設定って実際には全部一緒だったんですか?

:一緒の定義によりますが、ドメインをきちんと使い分けるところは一緒ではありませんでした。要するドメインは使いまわしてた。ただ、他は概ね一緒です。基本的にTerraformで構成管理しているので、コードベース上でも一緒という感じではあるものの、「んー」という感じです。

田仲:いわゆるドメインだけがけっこう大きく引っ張られた感じなんですね。 :そういう意味では社内で開発する時はうちスクラムでしていて、プランニングなどもやります。実はプランニングの時にissueとして挙がってはいましたが、結局ドメインの設定だから、みたいな感じで(笑)。「大丈夫っしょ!」みたいな感じで埋もれてたんです。

田仲:ありがち。せっかくissue挙がってたのに、拾いきれなかった感じですね。あとたぶんALBなどを使っていて、ルールの設定はどんな感じでしたか? 優先順位とか、たぶんいろいろあるとは思いますが。

:ALBのルールの設定は優先順位などはもちろんいろいろ設定されていますが、管理の方法としてはインフラとは切り離していて、アプリケーションコードのデプロイ時にCloudFormationを一緒にデプロイするかたちで対応しているモジュールが多いです。そのため、そのあたりのルーティングはアプリケーション側で責任を持とうね、というのが基本的な方針です。

要するにインフラをやってくれている人もいますが、そこに全部任せきりになるのもちょっと変な話なので。どういうルーティングをして欲しいか、結局コンテナの構成とかによることが多いです。

田仲:アプリケーション側のほうでルーティング設定やルールとかはしている感じですね。優先順位の話とか、たぶんワイルドカード(*)で設定するなどいろいろあったと思いますが、そういった優先順位ってなんとかならなかったのかなと疑問だったんですが、どうなんですかね?

:そういう意味では、結果的にはそのように解決しました。ですが、CloudFormationにデプロイする時に「これってどういう記載で、どういうふうにすればどう動くんだ? 本当にこれ大丈夫か?」みたいな。初めてのケースで、知見がちょっとなかったんです。

田仲:アプリケーション側のほうで設定していると思いますが、インフラ面で強い人たちとコミュニケーションとって解決したみたいなところですか?

:そうです。:基本的にはインフラの人にもガーッと入ってもらって、「いや、このままだとまずいっす」とか(笑)。

田仲:やはりインフラに強い人はけっこうスーパーマン的な存在で入ってきてくれますよね。

:開発の流れとしても、もっと早くからインフラの人に入ってもらえばよかったな、というのは反省としてはあります。

後半、アプリケーションの開発にもそれなりの工数かかったので、「後半ちょっと入ってもらいます」みたいな口ぶりでしたが、最初から話していればいろいろと違う未来があったのかもしれません。

田仲:早い段階でちゃんと相談して、構築してもらうところはちょっと手助けがあったほうがよかったんじゃないか、ということですね。

:はい。「本番環境とステージング環境が違うのは、Terraform側で吸収させたんですかね?」この質問は「ステージングと本番でちょっと違ったんですよね」ということに対して、「Terraformどういう構成になっているんですか?」みたいなことかな?

弊社にはDevとステージングと、本番と環境があって、Terraformで普通にディレクトリを切って、それぞれで構成管理をしています。ただ、共通化するべき部分は、モジュールのようなかたちにしていることも多いので、そういう部分は一部ある感じです。

田仲:ありがとうございます。ではいったんここで終わりにします。森さんありがとうございました!