スタートアップに複雑なクラウドインフラは本当に必要か?
(hadijaveed.me)- 初期のスタートアップは、初日から Kubernetes やオートスケーリングまで備えるよりも、プロダクトを作り product-market fit を見つけることに時間を使うほうがよい場合がある
- 20〜30個の Lambda 関数 と SQS、CloudWatch に分散したログは、デバッグ・変更・デプロイを難しくしており、単一の NodeJS コンテナや Flask/FastAPI アプリと Redis によって単純化できる余地があった
- EKS 上の 7つの マイクロサービス に CRUD とビジネスロジックを分けた事例では、機能開発よりインフラ運用に多くの時間がかかっていた
- 単一 VM でも EC2、GCP VM、Hetzner、latitude.sh のような選択肢と 40GB RAM・マルチコア 級のサーバーを活用すれば、初期サービスには十分なコンピューティングを提供できる
- シンプルな構成でも、HTTPS、制限付きの SSH/SSM、CI/CD、DNS、DB バックアップ、待機 VM、災害復旧、セキュリティルール、バックアップ保持ポリシーは備えていなければ実務では使えない
初期スタートアップに過剰なインフラが生まれる仕組み
- Pieter Levels は、複数の micro-SaaS を単一サーバーで運用し、クラウドインフラの複雑さを避けて product-market fit に集中した事例として紹介されている
- この方法がすべてのチームに合う答えではないが、デプロイとインフラ管理が 複雑さそのもののために複雑になる 状況をよく示している
- MVP 後の小規模開発チームは、デプロイやデータベース管理で苦労することがあるが、すべてのプロジェクトが初日から Kubernetes、複雑な分散システム、オートスケーリングを必要とするわけではない
- シンプルなインフラは、チームが良いプロダクトを作り、市場適合性を見つけることにより多くの時間を使えるようにしてくれる
- エンタープライズ規模の企業にはコンプライアンスや大規模な人員という別の問題があるが、初期スタートアップがその複雑さをそのままなぞる必要はない
実例: 複雑さが生んだ運用負荷
-
Lambda の過負荷
- 異なるサービスのために 20〜30個の Lambda 関数が存在していた
- SQS と複数のバックグラウンド処理も Lambda ベースで構成されていた
- ログが CloudWatch 全体に散らばっており、原因追跡が難しくなっていた
- デバッグは苦痛で、変更は扱いづらく、モノレポでもデプロイが複雑になっていた
- 単一の NodeJS コンテナや Python Flask/FastAPI アプリ、Redis ベースのバックグラウンド処理で、もっとシンプルにできた可能性がある
-
マイクロサービスの過剰導入
- Kubernetes EKS 上に 7つの小さなマイクロサービスが載っていた
- CRUD とビジネスロジックが別サービスに分離されていた
- Kubernetes は強力だが、そのチームは機能開発よりインフラに多くの時間を使っていた
- その規模でその程度のサービス分離が本当に必要だったのかは疑問として残る
単一サーバーというアプローチが現実的な理由
- 単一サーバー構成 は、現代の VM の性能を積極的に活用する方法である
- Hetzner、latitude.sh では、予算に優しい高性能 VM を入手できる
- GCP VMs、EC2 インスタンスも妥当な価格帯である
- 40GB RAM と複数コアを備えたサーバーは、複数の分散サービス、複数の Lambda、複数の ECS task より良い選択になる場合がある
- すべてが一か所に集まるため、運用と管理がしやすくなる
- 数百万 QPS へのスケールは、本当にその時が来たときに対処すればよく、その頃にはインフラチームがいる可能性が高い
- 安定した単一 VM 運用には基本的な運用装置が必要である
- EC2、GCP VM、Hetzner のような 堅牢なマシン
- Web には HTTPS、デプロイには IP 制限付き SSH や SSM のような 安全なアクセス
- 無停止デプロイのための CI/CD
- DNS 設定
- 定期的なデータベースバックアップ
- 冗長化のための待機 VM
- 堅牢な災害復旧戦略と、検証済みの平均復旧時間が必要であり、バックアップ VM で実現可能である
Docker Compose と Docker Compose Anywhere
- Docker Compose はローカル開発で複数サービスを1つのコマンドで管理するのに適しているが、本番環境ではあまり活用されていない
- Docker Swarm は deprecated になったと言及されている
- Docker Compose は更新時にダウンタイムが発生する可能性がある
- 本番デプロイガイド があり、シンプルさと本番対応のバランスが必要である
- Docker Compose Anywhere は、単一 VM 構成をよりシンプルにするための週末プロジェクトである
- GitHub Actions で Linux サーバーをワンクリック設定する
- GitHub Container Registry と Docker Rollout を使い、無停止の継続的デプロイを支援する
- 環境変数とシークレット管理を提供し、セキュリティ改善のため age や sops を検討している
- GitHub Actions ベースの自動 Postgres バックアップを提供する
- 単一 VM 上で複数アプリをサポートする
- Traefik と Let’s Encrypt で SSL を自動化する
- Next.js、Go、Python、Node.js アプリなどをデプロイできる
シンプルでも欠かせないセキュリティと運用原則
- セキュリティとデータ保護は、シンプルな構成でも省略できない
- 必要なポートだけを開ける厳格なファイアウォールルールが必要である
- SSH キーを安全に管理し、AWS では SSM、GCP では CLI を優先する
- セキュリティ強化のために bastion host を使うことができる
- シークレットを保護し、WAF や Cloudflare の利用を検討する
- 暗号化したデータベースバックアップを S3 または同等に安全なクラウドストレージへ送る
- 追加の冗長化のためにディスクスナップショットを定期的に作成する
- バックアップとスナップショットの保持ポリシーを実装する
- エンジニアの優先順位は、構成の シンプルさ を守り、コアプロダクトに集中することにある
- Google エンジニアリングや大企業のやり方をまねた複雑な構成、新しいツールに簡単に注意が分散してしまうことがある
- スタートアップであろうとなかろうと、最も重要なことはユーザーと対話し、product-market fit を見つけることである
1件のコメント
Hacker News のコメント
いくつものプロジェクトで、流行りの技術のせいで苦労させられたことが多い。
チーム規模は小さいのに「無限のスケーラビリティ」が必要だという理由で、信じがたいほど低品質な成果物を作ってしまったり、LTS が何かもきちんと理解していない未熟なチームが Kubernetes が必要だと決めたりすることもあった。
今では、どのプロバイダーでも望むサイズの堅牢化した VM を作り、その上で Docker サービスや Python バックエンド、静的ファイル配信を動かせる簡潔な Puppet コードを持っている。
Hetzner の VM が 2 コアでも 48 コアでも 5 分以内にサービスを作成し、ソース管理されたマニフェストで設定を統制し、カスタム Naemon プラグインで設定準拠を監視する。
完全に再現可能なプロセスなのに、スタートアップのチームはクラウド上で雪の結晶のような一回限りの構成を作り、毎月数千ユーロを使いながら、2017 年の DevOps 先駆者たちがやっていたことにも及ばない成果物を出している。
このテーマで The Emperor's New clouds という記事も書いた: https://logical.li/blog/emperors-new-clouds/
「Docker やほかの技術なしに、どうやって構成を再現するのか」という質問が理解できたことがない。
スクリプトは決定的で、依存関係のバージョンは固定されており、設定と入力引数と実行順序も同じで、決定的な計算装置上で動いていた。
再現できない理由がなかった。
堅牢化した VM に Docker があると言う代わりに kubelet があると言えばよく、その場しのぎの「docker services」をいくつも使う代わりに、ごく低コストの k8s コントロールプレーンでそれらの VM をすべて制御できる。
その方式がなぜ優れているのか分からないし、むしろ悪く見える。
悪いクラウドインフラとは、AWS が売っているものを全部使おうとして、インフラ全体が過度に高い抽象化レイヤーに縛られ、ほかのプラットフォームへ移行できなくなるような場合だ。
k8s はそれとはまったく違う。
このうち一つでも「自作したもの」や「スクリプト 1 本で済む」と答えるなら、それこそが k8s に価値がある理由だ。
Python バックエンドなら、VPS 上でビルドスクリプトをそのまま再現すればいい:
pip install requirements.txt>python main.py>nano /etc/systemd/system/myservice.service>systemd start myservice> 終わり。インスタンスを増やすなら、これらのコマンドを bash スクリプト
build_my_app.shに入れればよく、それが新しい Dockerfile のような役割を果たし、どのサーバーにも数十秒でインストールできる。IaaS として使えば、他社の VPS を含むほかの方法よりも、はるかに速くプロトタイプを作れる。
特に Google Cloud はロックイン効果が小さく、最小驚きの原則にもよりよく合っている。
ただしプロトタイプを作った後は、より安い場所で作り直すべきかを考える必要がある。
ディスクをほぼ無限に拡張でき、スナップショットも取れる点はよく、クラウドはプロトタイプを本番負荷まで拡張して、実際に必要な規模を測らせてくれる。
しかし Cloud Run や Lambda のような「クラウド魔法」に頼ると、学習やデバッグにかかる時間が結局、従来のやり方で行うのと同じくらいかかった。
小さなスタートアップでは、ほぼこのやり方でやっている
GPU が混在するジョブキューの自動スケーリングのような複雑な部分はあるが、核になるのは単一 VM 上の nginx、Web アプリ、Postgres、Redis だ
B2B なのでトラフィックもほとんどない
開発者は Linux ノート PC や別プラットフォーム上の Linux VM で同じ構成をそのまま動かせるし、デモやテスト用に望めば各自クラウド VM も持てる
新しいシステムのブートストラップは、SSH キーをチェックインしてシェルスクリプトを実行する程度だ
デバッグしやすく、複雑でも高価でもなく、水平スケーリングが必要になるまではかなり 垂直スケーリング できる
誰にでも合うわけではないが、シード段階以前なら完全に適切だと思う
「公開鍵をチェックインする」方式に一段階の間接化を加えたもので、ユーザーは Git の変更なしに自分のキーを入れ替えられる
また元の説明からはかなり外れるが、SSH キーのリースはオフボーディング時の対応をずっと良くしてくれるので本当に良い: https://github.com/hashicorp/vault/blob/v1.12.11/website/con...
リンクを探している途中で、Vault がワンタイムパスワードも提供すると主張しているドキュメントも見つけた <https://github.com/hashicorp/vault/blob/v1.12.11/website/con...>
ただし私は断固たる「PasswordLogin no」派なので、そちらは各自注意して使うべきだ
Postgres は何でもできる
そうした構成では、VM の 設定とアップデート はどう追跡しているのか?
答えは「いや、そうではない」だ
私の SaaS は最初は単一サーバーで動かし、プロダクトマーケットフィットを得た後に複数サーバーへ移した
それらは Hetzner の ベアメタルサーバー で、マイクロサービスはなく Kubernetes も扱っていないが、分散データベースは運用している
このベアメタルサーバー群は、クラウドプロバイダーの仮想マシンに比べて桁違いに強力だ
数年前に自分で測定もした: https://jan.rychter.com/enblog/cloud-server-cpu-performance-...
全体として、このアプローチはばかげているほど効果的だ
Kubernetes のような複雑さに対処しなくてよく、複雑なシステムで必然的に生じる連鎖障害も避けられ、開発時間と保守、月々のサーバー費用を節約できる
よくある反応は「でもスケールはどうするんだ」だが、まだスケールが必要になるかは分からないし、こうした強力なコンピューターと合理的な設計があれば 3〜5台のサーバー でもかなり先まで行ける
もちろん、自宅のクローゼットでビジネスを動かそうという意味ではない
サーバー管理のための自動化は依然として必要で、私は ansible と terraform を使っている
ソフトウェアがごく短期間で大成功するという楽観を刺激し、人々はそれを信じたがる
記事を読んだのか、タイトルだけ見たのか分からない
下のほうにある A few considerations セクションまで進めば、笑ってはいられないだろう
その「いくつかの考慮事項」は、特に非常に機密性の高い情報を保存または送信するなら、相当なセキュリティ作業の塊だ
こういう状況で HIPAA のようなコンプライアンス要件はどう扱うのか?
プログラマーには二種類いる
すべて見てきたと思っている人と、ほとんど何も見ていないと知っている人だ
だから、こういう絶対的な断定にはうんざりする
Kubernetesの中核となる20%は、Deployment、Pod、Service、ブルーグリーンデプロイの扱い方、宣言的定義、名前空間の分離といった部分で、これは本当に良いものです。
このシンプルな基本だけを守り、マネージドなクラウドKubernetesサービスを使い、状態を持つデータベースはクラスターの外に置けば、良い体験になります。
問題が起きるのは、「クラウドネイティブ」の沼に吸い込まれて、あらゆるニッチなオープンソースシステム、Operator、ambassador、サイドカーパターンなどを使い始めたときです。
そうしたものは、互いに独立しつつも連携する複数の技術チームや、多様なプログラミング言語が共存する環境のためのものです。
こういう議論では、人々が互いに別々の2つのものを指して話していることが多いと感じます。
私にとっては、Docker Composeより優れた、均一なデプロイ方法にすぎません。
コントロールプレーンにはごくわずかなコストだけを払い、ワーカーはkubeletの入った普通のVMです。
しかし多くの人にとって「Kubernetes」とは、上の2番目の段落を意味しているようです。
必ずしもそのように使う必要はまったくありません。
k3sクラスターを設定して、ワークロード、Service、Ingressだけを学べば十分です。
その場しのぎのVMやDocker構成を置き換えるのに必要なのは、その程度です。
99%のケースでは、**docker-compose++**程度だけが必要、あるいは求められています。
無停止デプロイが標準でできて、ReplicaSetやその他の複製・分散メカニズムのためのシンプルな設定システムがあれば、ほぼ終わりです。
まさにそれだけをやってくれるものがあればいいのにと思います。
Kubernetesは荷物が多く、Docker Composeは重要な本番要件には少し基本的すぎます。
Kubernetesには、どんな用途にも合わせて調整できるノブやダイヤルが百万個ほどありますが、同じようにそれらを無視して中核機能だけを使い、シンプルに保つこともできます。
まともなデプロイ、とても簡単なログとメトリクス、良い開発者体験をすぐに備えた構成を作れます。
評判がとても悪く、以前に使ったこともなかったので、社内ツール用のサーバーをセットアップしていいか聞いたときは最悪を覚悟しました。
実際には、セットアップした人が30分のチュートリアルをしてくれて、概念全体を説明したうえで、サーバーをデプロイするのに十分な情報をくれ、何の問題もなくデプロイできました。
git pushで自動デプロイされるようにするのも非常に早く終わりました。私には、あまりにも当然の選択に見えました。
サービスが文字どおり1つだけというのでなければ、はるかに使いやすいです。
ただし私は自分でインストールしたわけではないので、悪い評判はおそらくその部分から来ているのかもしれません。
履歴書にk8sがなければ、誰が新しい仕事を得られるでしょうか :)
真面目に言うと、多くの人が大規模インフラを学ぶために、あえて難しい道を選んでいるのだと思います。
また、よくある理由は「顧客がものすごく増えたらずっと楽になる」とか「需要に応じて動的にスケールできる」というものです。
作る側の人間にとってはどれも妥当ですが、創業者や専門のCTOにとっては、それほど妥当ではありません。
潜在顧客の要求やスケジュールには気を配らず、もっともらしい虚像を作ってお金を燃やす人たちがいます。
タイヤ交換に整備工場へ行ったら、整備士が自分の成長欲求のためにローライダー用の油圧装置と回転ホイールキャップを付けたがり、3週間かかったようなものです。
最悪なのは、次の人にとって本質的に曖昧になる点です。
何かがそこにある理由が、実際に必要だからなのか、ただのきらびやかな装飾なのか分かりません。
人々が興味でやっているのか、技術が好きだからやっているのか、それとも言われているように履歴書にk8sを書くため、技術官僚的にスキルを上げようとしているのかはよく分かりません。
私はただ「管理するのが苦痛そうだ」と思うだけです。
だからk8sインフラは、より限られた本当に熟練した人たち、少なくともメンティーを導ける熟練者が設計し、作業するほうがよいと思います。
そして不要な場合、つまり大半のスタートアップ・小企業・一般的な中規模企業は、より使いやすい既存のパラダイムを維持すればよいのです。
彼らはその選択に非常に満足しており、ブログに詳しく書いてきました。
「顧客がものすごく増えたらずっと楽になる」が実際に当てはまったケースです。
古くて何度も繰り返されてきた議論だけど、それでも自分の2セントを付け加える
初日から複雑なフレームワークを選ぶべきかというと、チームにその経験が十分ない限り、おそらく違う
ただ自分が反対しているのは、カスタムプロセスや独自ツールでインフラを管理するほうが、実績あるツールより常に保守の手間が少ないという考え方だ
自作プロセスがまったく単純ではなく、コアプロダクトから多くの時間を奪っているのに、「複雑性」という藁人形を頑なに拒む態度でもある
誰もが、バイナリをVPSにコピーしてサービスを再起動する単純さを好む
しかしすぐに設定やシークレット管理が必要になり、可用性や冗長性のためにサーバーが複数台になると、段階的デプロイ、ロードバランシング、ロールバックなどが必要になる
ステージング環境も欲しくなるし、このワークフローを簡単に複製できなければならない
チームが大きくなると、本番に近い環境をローカルで動かせないことも明らかになる
そうやって要求は増え続ける
結局、新しい要求のたびに、他の人たちがすでに解いている標準的な解法に頼る代わりに、自分たちだけの特別なやり方で解決しなければならなくなる
後になればサンクコストの問題になる
知っていて理解しているカスタムツールを捨てて、知らない「複雑性」へ移るのか?
投資すればするほど、後で移行しづらくなる
自分の提案は、後で標準ツールへ移行しやすくするプラクティスを最初から採用することだ
つまり1日目からコンテナでデプロイし、12要素アプリの方法論を採用する、といったことだ
そして必要な機能で苦労し始めたら、遅すぎるより早めに実績あるツールへ移行するほうがよい
未知への恐れには根拠がなかったと分かる可能性が高く、長期的にはインフラに費やす時間が減るはずだ
自分が検討したアプローチは、初日から標準ツール、つまり k8s + gitops で始めつつ、それでも単一VM上で動かすというもの
どう思う?
一方で、こうした「複雑な」クラウドシステムを理解し、terraformでデプロイ・保守できる「クラウドエンジニア」はたくさん見つけられる
すぐに投入できるスキルセットだ
VM、ブロック/Blobストレージ、DNS、IdP、ドメインレジストラ
クラウドで自分が快適に使えたのはこの程度だけだ
FaaSとその仲間たちに踏み込むと、自分には本当に奇妙に感じる
本番環境が動いているマシンを覗けないというのは受け入れがたい
クラウドのダッシュボードでデバッグする体験はひどい
Microsoftのアプローチが実際に「動く」ものに最も近いとは思うが、それでも本当にひどく、二度と触りたくない
10年たった後でも、自分の理想のアーキテクチャは依然として、単一VM上でモノリシックなコードベースがローカルのSQLiteインスタンス群と通信する形だ
NVMeストレージの登場は、この方式にかなり大きな追い風を与えた
バックアップはブロックストレージのスナップショットで処理し、トランザクションの耐久性は必要ならWALレプリケーションで処理する
ばかみたいに単純だ
ビジネスと顧客に集中できるようにしてくれる
顧客はこういうことにはまったく関心がなく、金も払わない
すべてのコードとインフラは純粋なマイナス要素なので、できるだけ少なく持つべきだ
人々がクラウドはオンプレミスより高いと言うとき、理由はしばしばこれだ
VMを24時間365日動かすつもりなら、もっとよい選択肢がある
マイクロサービスの本でも、まずモノリスを作れと言っている
実際のユーザーの反応を得る前には、システムをどう分割すべきか分からないし、サービスを再構成するよりモノリスを分割するほうが簡単だ
モノリスを永遠に分割する必要がないかもしれない
Stripeも最終的にはRailsモノリスから一部を切り出したが、モノリスは驚くほど遠くまで行ける
Django/Railsのようなモノリスよりデバッグが簡単になることはなかなかない
ただし、インフラがどこへ向かうかを少し見通しておくのは役に立つ
うちの会社の初期バージョンは単一VM上のDjango Dockerコンテナで作り、デプロイは手動の
docker pull; docker stop; docker startだったこの構成で思ったより長く持ちこたえた
Dockerは依存関係のパッケージング問題を避ける方法としてよい
初期には、新しいDBドライバをインストールしたときにサーバーに必要なCヘッダファイルがあるか、Macと設定が違うかといった問題が面倒になり得る
私たちはシード延長ラウンドの後、信頼性とスケーラビリティというビジネス要件のためにk8sへ移行し、k8sはシリーズBまでうまく持ちこたえてくれた
すべてをDocker化していたおかげで移行も簡単だったが、初期段階では複雑性を積極的に削っていた
そしてフレームワークが提供する機能の粗悪な劣化版を作り直すのではなく、フレームワークを正しく使うべきだ
この点では、熟練者1人のほうが未熟練者10人よりよい成果を出す
時間がたつほど差は蓄積する
人々がモノリスにうんざりする本当の理由の半分は、出来が悪く、きちんと運用されていないモノリスにあると思う
データは独自のサービスに保存すべきだと言い、リレーショナル検索や全文検索のようなマルチパラダイムなアプローチが必要なら、複数のサービスになることもある
ユーザー体験も独自のサービスを使うべきだ
少なくともその間にさらに別のサービスが必要で、通常はDjangoやRailsがここに入る
任意で、認証や金融取引のような追加サービスも必要になる可能性があるという
あるプロジェクトを約6年間、月額10ドルのVPS 1台で運用した
lowendtalkで得た恒久割引のおかげで実際にはもっと少なく払っていて、ゲームサーバー中心のVPSプロバイダーだった
自分が設定を壊してクリーンなOS再インストールのために丸1日落ちた一度と、プロバイダーが事前告知のうえでIPアドレスを変更した一度を除けば、ほぼ99.999レベルの安定性だった
VPS技術は本当に大きく進歩しており、非常に安定している
ノードのディスクはRAID 1で構成されていて、ノードメンテナンス時にはVM自体も別のマシンへ簡単にライブマイグレーションできる
スナップショットも取れる
自分にとってクラウドインフラは、より高い安定性のためではなく、IAM、シークレット管理、Infrastructure as Codeのような協業や運用管理機能、またはHIPAAのようなデータセンター準拠の理由で選ぶことになりそうだ
状況による
個人的には、クラウドベースの解決策は時間を大きく節約してくれるので気に入っている
ただし、何を使うかはかなり選別して選ぶべきで、複雑すぎて明らかに逆効果な解決策もある
私は小さなブートストラップ型スタートアップを運営している
私たちには自分たちに給料を払うお金も足りず、私は副業のコンサルティングで生計を立てている
このように予算と時間が限られているので、何を使うかには非常に慎重でなければならない
だから Google Cloud のようなものが好きだ
GCP の請求額は月に数百ユーロで、かなり低い
もっと安いプロバイダーに移ることもできるが、その時間投資を正当化するのは難しく、以前使っていた AWS と比べると Google の UI やツールも気に入っている
Kubernetes は使う機会がない
空のクラスターを動かす費用だけでも、現在の月間 GCP 請求額より高くなるだろう
マイクロサービスの罠にはまっていないので、必要でもない
しかし Docker は気に入っている
ソフトウェアのデプロイを馬鹿みたいに簡単にしてくれる
私たちのウェブサイトは、ロードバランサーと Google CDN 経由で配信される Google Storage バケットだ
同じロードバランサーが REST 呼び出しを、モノリスを実行する 2 台の VM にルーティングしている
これらの VM は、マネージド DB、マネージド Elasticsearch、マネージド Redis と通信している
DB と Elasticsearch は高いが、マネージドで使うと時間と手間を大きく節約できる
私たちが持っているものはほぼこれがすべてで、シンプルで、そこまで高くもない
全体を Hetzner のようなところへ移せば、コストを 50% ほど削減できるだろう
試す価値はあるかもしれないが、私にとってはそれほど急ぎではない
そのマネージドサービスを失うと、私の生活はもっと大変になる
一部の顧客は AWS を好むようなので、いつかは AWS に戻らなければならないかもしれず、そういう事情もある