昨年から現在にかけて、クラウドネイティブに取り組んできた中で、ふと思いつき、私の目に映るクラウドネイティブについていくつかの爆論を発表し、今年最後の技術ブログとしたいと思います。本記事はあくまで個人的な意見であり、私の会社の立場とは無関係です。
概要#
クラウドネイティブはおそらく 2014 年から 2015 年頃に正式に提唱された概念です。2015 年に Google が主導してクラウドネイティブコンピューティング財団(Cloud Native Computing Foundation aka CNCF)が設立されました。2018 年、CNCF はCNCF Cloud Native Definition v1.01において、クラウドネイティブの概念を初めて認定しました。
クラウドネイティブ技術は、組織がパブリック、プライベート、ハイブリッドクラウドなどの現代的で動的な環境でスケーラブルなアプリケーションを構築し、実行することを可能にします。コンテナ、サービスメッシュ、マイクロサービス、不変インフラストラクチャ、宣言型 API がこのアプローチの例です。
これらの技術は、弛緩した結合のシステムを可能にし、耐障害性、管理性、観測性を持たせます。堅牢な自動化と組み合わせることで、エンジニアは最小限の手間で頻繁かつ予測可能に高影響の変更を行うことができます。
その中文翻訳は以下の通りです:
クラウドネイティブ技術は、各組織が公有クラウド、私有クラウド、混合クラウドなどの新しい動的環境で、弾力的にスケールするアプリケーションを構築し、実行することを可能にします。クラウドネイティブの代表的な技術には、コンテナ、サービスメッシュ、マイクロサービス、不変インフラストラクチャ、宣言型 API があります。
これらの技術は、耐障害性が高く、管理が容易で、観測が可能な弛緩した結合のシステムを構築します。信頼性の高い自動化手段と組み合わせることで、エンジニアはシステムに対して頻繁かつ予測可能な重大な変更を容易に行うことができます。
公式の定義から見ると、私はこれを定義 (definition) ではなく、ビジョン (vision/landscape) と呼ぶ方が良いと思います。なぜなら、上記の表現にはクラウドネイティブという新しい概念の具体的な範囲や境界が明確に表現されておらず、Cloud NativeとNon-Cloud Nativeの違いも明確に説明されていないからです。
個人的な視点から見ると、クラウドネイティブアプリケーションは以下の特性を持っています。
- コンテナ化
- サービス化
クラウドネイティブを実践する組織は、以下の特性を持つべきです。
-
重度の Kubernetes またはその他のコンテナスケジューリングプラットフォーム(例:Shopee が自社開発したeru22)
-
完全な監視システムを持つ
-
完全な CI/CD システムを持つ
この基盤の上で、最近多くの人がクラウドネイティブという新しい概念について議論しているのを見かけたので、ここで私の個人的な 4 つの爆論について話したいと思います(爆論のデータは個人的な主観的判断であり、軽く流してください)。
- 95% 以上の企業は、CI/CD システムの構築を完了していない。また、オンラインサービスプロセスの収束も完了していない。
- 90% 以上の企業は、マイクロサービス化できる技術的な準備ができていない。
- 90% 以上の企業は、コンテナ化を支える技術的な準備ができていない。
爆論を始める#
1. 95% 以上の企業は、CI/CD システムの構築を完了していない。また、オンラインサービスプロセスの収束も完了していない。#
CI は継続的インテグレーション(Continuous Integration aka CI)を指し、CD は継続的デリバリー(Continuous Delivery aka CD) を指します。一般的に、CI と CD の定義は以下の通りです(ここでは Brent Laster のWhat is CI/CD?3から引用します)。
継続的インテグレーション(CI)は、製品のソースコードが変更される際に、自動的に検出、プル、ビルド、(ほとんどの場合)単体テストを行うプロセスです。CI はパイプラインを開始する活動です(ただし、特定の事前検証 — しばしば「プレフライトチェック」と呼ばれる — が CI の前に組み込まれることがあります)。
CI の目的は、開発者からの新しい変更が「良い」ものであり、コードベースでのさらなる使用に適していることを迅速に確認することです。
継続的デプロイメント(CD)は、CD パイプラインから出てきたコードのリリースを自動的にエンドユーザーに提供できるという考え方を指します。ユーザーによるコードの「インストール」の方法によっては、クラウドに何かを自動的にデプロイしたり、アプリの更新を提供したり、ウェブサイトを更新したり、単に利用可能なリリースのリストを更新したりすることを意味します。
通常、私たちの実践において、CI と CD の境界は明確ではありません。一般的な Jenkins ベースの実践を例にとると、通常の流れは次のようになります。
-
Jenkins プロジェクトを作成し、パイプラインを設定します(コードのプル、ビルド、単体テストなどのタスクを含む)、トリガー条件を設定します。
-
指定されたコードリポジトリにメインブランチのコードがマージされるなどの操作があった場合、パイプラインを実行し、成果物を生成します。
成果物生成後、一般的には 2 つの方法があります。
-
成果物の次のステージで自動デプロイプロセスをトリガーし、デプロイスクリプトに従って生成された成果物 / イメージを直接ターゲットサーバーにデプロイします。
-
生成された成果物を中間プラットフォームにアップロードし、人がデプロイプラットフォームを通じて手動でデプロイタスクをトリガーします。
上記のプロセスにおいて、完備したプロセスを持つ企業は、他の補助プロセス(PR/MR 時の CI プロセス、CR プロセスなど)も持つでしょう。
ターゲットプラットフォームへのデプロイに直面した際、私の別の見解は、大部分の企業がオンラインサービスプロセスの収束を完了していないということです。冗談を一つ:
Q: あなたたちはオンラインサービスをどうデプロイしていますか?A: nohup、tmux、screen
現在において、標準化された CI/CD プロセス、オンラインサービスプロセスの管理の収束は、少なくとも現在の時点で、いくつかの明らかな利点をもたらします。
-
人為的な手動変更によるリスクを可能な限り低減する。
-
基本的な運用依存関係の設定をうまく収束させることができる。
-
現在の主流のオープンソースの systemd、supervisor、pm2 などのプロセス管理ツールに依存し、プロセスに基本的な HA 保証を提供できる(プロセスの生存確認、プロセスの再起動などを含む)。
-
後続のサービス化、コンテナ化などのステップの基盤を築く。
2. 90% 以上の企業は、マイクロサービス化できる技術的な準備ができていない。#
爆論 1 で述べた CI/CD などの手段について、私はこれが技術的障害よりも制度的障害である現実だと感じています。次のいくつかの爆論については、技術的な準備がないと表現したいと思います。
まず、爆論 2 について話しましょう:90% 以上の企業は、マイクロサービス化できる技術的な準備ができていない。
まず、マイクロサービスの概念について話しましょう。マイクロサービスは実際にはコンピュータの歴史の中で異なる議論があり、2014 年に Martin Fowler と James Lewis がMicroservices a definition of this new architectural term4という記事で正式にマイクロサービス(Microservice)という概念を提唱しました。
ここで、ウィキペディアの概要を引用します。
マイクロサービスは、単一のアプリケーションで構成される小さなサービスであり、それぞれが独自のプロセスと軽量な処理を持ち、ビジネス機能に基づいて設計され、完全自動的にデプロイされ、他のサービスと HTTP API で通信します。同時に、サービスは最小限の集中管理能力(例えば Docker)を使用し、異なるプログラミング言語やデータベースなどのコンポーネントで実装できます。
では、開発の観点からマイクロサービスと従来のモノリスサービス(Monolith)との顕著な違いを説明してみましょう。
-
マイクロサービスのスコープは小さく、特定の機能や機能のクラスにより多くの焦点を当てています。
-
スコープが小さいため、変更やクラッシュによる影響は従来のモノリスに比べて小さくなります。
-
多言語・多技術スタックのチームにとってよりフレンドリーです。
-
現在のインターネットが求める小さなステップでの迅速な反復という大目標に「合致」しています。
ここで考えるべきは、マイクロサービスのこの体系を実現し、実践するためにはどのような技術的な準備が必要かということです。私は主に 2 つの側面、アーキテクチャとガバナンスが必要だと思います。
まずアーキテクチャについて話しましょう。マイクロサービスにとって最も面倒な問題は、従来のモノリスアプリケーションからの分割です(もちろん、最初からマイクロサービスを行っている場合は別ですが、そうであっても他の問題があります)。
前述のように、マイクロサービスは従来のモノリスアプリケーションに比べてスコープが小さく、特定の機能や機能のクラスにより多くの焦点を当てています。ここから派生する最大の問題は、機能の境界を合理的に分割し、分割することです。
不適切な分割は、サービス間の相互依存を引き起こす可能性があります。例えば、ユーザー認証をショッピングサービスに置くと、フォーラムサービスが不要なショッピングサービスに依存することになります。分割が細かすぎると、規模の小さなビジネスが 100 以上のサービスリポジトリを分割するという非常に興味深い現象が発生します(この状況を「マイクロサービス難民 2333」と呼びます)。
私たちがマイクロサービスの理念を実践するのは、ビジネスとチームの規模が拡大し、多様なニーズやチームメンバーの技術スタックに直面したとき、従来のモノリスアプリケーションの継続的なメンテナンスコストが大きな支出になるからです。私たちはマイクロサービスを導入することで、メンテナンスコストを可能な限り削減し、リスクを低減したいと考えています。しかし、不適切な分割は、私たちのメンテナンスコストを再びモノリスの継続的な実践を超えるものにしてしまいます。
私が考えるもう一つのマイクロサービスの実践を妨げる問題はガバナンスの問題です。マイクロサービス化後に直面するいくつかの問題を見てみましょう。
-
可観測性の問題。前述のように、マイクロサービス化された単一のサービスのスコープは小さく、特定の機能や機能のクラスにより多くの焦点を当てています。これにより、ビジネスリクエストを完了するために必要なリクエストチェーンが長くなる可能性があります。一般的な見解によれば、チェーンが長くなるほどリスクが大きくなります。サービスに異常が発生した場合(例えばビジネス RT の突然の増加)、具体的なサービスの問題をどのように特定しますか?
-
設定フレームワークの収束。マイクロサービス化のシナリオでは、基本的な機能を具体的な内部フレームワークに沈めることを選択するかもしれません(サービスの登録、発見、ルーティングなど)。これは、独自のフレームワークを維持し、設定の収束を完了する必要があることを意味します。
-
サービスガバナンス(登録、発見、サーキットブレーカーなど)に関する古典的な問題。
-
マイクロサービス化により、完備した CI/CD メカニズムの必要性がより切実になります。爆論 1 の状況が存在する場合、これはマイクロサービスの理念を実践する障害となります。
確かに、現在オープンソースコミュニティ(Spring Cloud、Go-Micro など)や 4 大クラウドプロバイダー(AWS、Azure、阿里云、GCP)は、即使用可能なマイクロサービスソリューションを提供しようとしていますが、上記のようなアーキテクチャの問題をうまく解決できないだけでなく、自らの問題も抱えています。
-
オープンソースコミュニティのソリューションやクラウドプロバイダーのソリューションに依存する場合、使用者は特定の状況でフレームワーク内の問題を特定するための一定の技術的素養を持つ必要があります。
-
ベンダーロックイン。現在の即使用可能なマイクロサービスソリューションには、一般的なオープンソースの事実標準がありません。したがって、特定のオープンソースコミュニティやクラウドプロバイダーのソリューションに依存することは、ベンダーロックインの問題を引き起こします。
-
オープンソースコミュニティのソリューションやクラウドプロバイダーのソリューションには、多言語に対するフレンドリーさが欠けています(皆さんは今、Java が好きなようです(Python には権利がない.jpg)。
したがって、爆論 2 が伝えたい最も核心的なポイントは、マイクロサービス化は無代価の行為ではなく、逆に相応の技術的準備と人的投入を必要とする行為であるということです。したがって、マイクロサービスが万能の良薬であると考えないでください。必要に応じて使用してください。
3. 90% 以上の企業は、コンテナ化を支える技術的な準備ができていない。#
現在非常に主流な見解は、可能な限りコンテナを使用するということです。正直なところ、この考えには一定の合理性があります。この考えを見直すために、コンテナが私たちにもたらす変化を見てみる必要があります。
コンテナはまず疑いなく、非常に多くの利点をもたらします:
- 開発環境と本番環境を真に一致させることは非常に便利なことです。言い換えれば、開発者が「このサービスは私のローカルでは問題ありません」と言うことが有用な発言になります。
- サービスのデプロイがより便利になります。配布やデプロイに関しても。
- 一定の程度でリソースの隔離と配分が可能です。
では、無条件にコンテナを使用できるのでしょうか?いいえ、そうではありません。コンテナ化後に直面する可能性のあるいくつかの欠点を再評価する必要があります:
- コンテナのセキュリティ問題。現在最も主流なコンテナ実装(ここでは Docker を指します)は、本質的に CGroups + NS に基づいてリソースとプロセスの隔離を行っています。したがって、そのセキュリティは非常に考慮すべき問題です。結局のところ、Docker の権限昇格やエスケープの脆弱性は毎年発生しています。これは、コンテナの使用を規範化するためのシステム的なメカニズムを持つ必要があることを意味します。関連する権限昇格ポイントが制御可能な範囲内に収まるようにするためです。もう一つの方向性は、イメージのセキュリティ問題です。皆さんは百度 / CSDN/Google/Stackoverflow でプログラミングをする選手ですから、問題に直面したときに検索して Dockerfile をコピーするという状況が必然的に発生します。このとき、大きなリスクポイントが存在します。結局のところ、誰もがベースイメージに何が追加されているかを知ることはできません。
- コンテナのネットワーク問題。いくつかのイメージを起動した後、コンテナ間のネットワークの相互接続をどう処理しますか?皆さんの本番環境は、確実に 1 台のマシンよりも少なくありません。したがって、複数のホスト間でコンテナ間の通信を行い、ネットワークの安定性を保証するにはどうすればよいでしょうか?
- コンテナのスケジューリングと運用の問題。1 台のマシンが高負荷のとき、どのようにそのマシン上のいくつかのコンテナを他のマシンにスケジューリングしますか?また、コンテナが生存しているかどうかをどうやって確認しますか?コンテナがクラッシュした場合、どのように再起動しますか?
- コンテナの具体的な詳細問題。例えば、イメージはどのように構築し、パッケージ化しますか?どのようにアップロードしますか?(再び爆論 1 に戻ります)さらには、コーナーケースの問題をどのように調査しますか?
- 特定の大規模なイメージ(例えば、機械学習の同僚がよく使用する CUDA の公式イメージや、大量のデータをパッケージ化したイメージなど)をどのように迅速にダウンロードし、迅速にリリースしますか?
ここで、別の見解が出てくるかもしれません。「大丈夫、Kubernetes を使えば、これらの多くの問題が解決できる!」さて、この問題についてもう少し話しましょう。
まず、自己構築の Kubernetes クラスターのシナリオは無視します。なぜなら、それは一般の人が保持できるものではないからです。では、パブリッククラウドを利用する場合を見てみましょう。阿里云を例にとると、ページを開くと次のような図が見えます。
さて、質問です:
- VPC とは何ですか?
- Kubernetes 1.16.9 と 1.14.8 の違いは何ですか?
- Docker 19.03.5 と阿里云のセキュリティサンドボックス 1.1.0 は何ですか?違いは何ですか?
- 専用ネットワークとは何ですか?
- 仮想スイッチとは何ですか?
- ネットワークプラグインとは何ですか?Flannel と Terway は何ですか?違いは何ですか?ドキュメントをめくると、ドキュメントは Terway が阿里云の Calico を改造した CNI プラグインであると教えてくれます。CNI プラグインとは何ですか?Calico とは何ですか?
- Pod CIDR とは何ですか?どう設定しますか?
- Service CIDR とは何ですか?どう設定しますか?
- SNAT とは何ですか?どう設定しますか?
- セキュリティグループはどう設定しますか?
- Kube-Proxy とは何ですか?iptables と IPVS の違いは何ですか?どう選びますか?
皆さんは上記の質問が以下のいくつかの側面をカバーしていることに気づくでしょう。
-
Kubernetes 自体の深い理解(CNI、runtime、kube-proxy など)。
-
合理的なネットワーク計画。
-
クラウドプロバイダーの特定の機能に対する熟知。
私の見解では、これら 3 つの側面のいずれかは、技術チームの技術的準備やビジネスの理解(広義の技術的準備)に対して相応の要求が必要です。
もちろん、ここで少し愚痴を言いますが、実際に Kubernetes を扱うにはかなりのコストがかかります(少し脱線しますが、続けます)。
- イメージリポジトリが必要ですよね?高くはないですが、中国地域の基本版は月 780 元です。
- クラスター内のサービスを外部に公開する必要がありますよね?では、最低限の SLB を購入します。シンプルなタイプで、毎月 200 元です。
- さて、毎月のログにお金がかかりますよね?毎月 20GB のログだと仮定します。多くはないでしょう?では、39.1 元です。
- クラスターの監視はどうしますか?では、毎日 50 万件のログを報告することにしましょう。安くはないですが、毎月 975 元です。
計算すると、1 つのクラスターのコストは、(780+200+39.1+975)*12=23292.2 元 / 年です。クラスターの基本的な ENI、ECS などの費用は含まれていません。美味しいですね。
さらに、Kubernetes には多くの神秘的な問題があり、技術チームには十分な技術的準備が必要です(考えてみると、私は CNI のプロセスがクラッシュして再起動しなかったり、特定のバージョンのカーネルで cgroup が漏れたり、ingress が OOM になる問題に直面したことがあります)。皆さんは Kubernetes の Issue セクションを見れば、その盛況を確認できます(言い過ぎると涙が出ます)。
まとめ#
私はこの記事が多くの議論を引き起こすことを知っています。しかし、私が常に表現したいポイントは、クラウドネイティブ時代のこの一連のもの(実際には以前の伝統的技術の延長でもあります)の導入は無代価ではなく、無コストではないということです。十分な規模と痛点を持つ企業にとって、こうしたコストはビジネスの成長に対して正の促進となりますが、より多くの中小企業にとっては、この一連のものがビジネスの向上に対して非常に小さいか、あるいは負の作用をもたらす可能性があります。
私たち技術者が技術的な決定を行う際には、必ず自分のチームの技術的準備やビジネスの利益を評価した上で、特定の技術や理念を導入するべきであり、単にその技術が先進的であるから、すごいから、私の履歴書を裏付けることができるからという理由で導入するべきではありません。
最後に、以前私が共有した言葉をもってこの記事を締めくくりたいと思います。
技術の先進性を追求している企業は、必ず滅びる。