昨年から現在にかけて、クラウドネイティブに取り組んできた中で、ふと思いつき、今年最後の技術ブログとして私の目に映るクラウドネイティブについていくつかの爆論を発表したいと思います。本記事はあくまで個人的な愚痴であり、私の会社の立場とは無関係です。
概要#
クラウドネイティブはおそらく 2014 年から 2015 年頃に正式に提唱された概念です。2015 年に Google が主導してクラウドネイティブコンピューティング財団(Cloud Native Computing Foundation、略称 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、略称 CI)を指し、CD は継続的デリバリー(Continuous Delivery、略称 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)という概念を提唱しました。
ここでは Wikipedia の一段落を引用します。
マイクロサービスは、単一のアプリケーションで構成される小さなサービスであり、それぞれが独自のプロセスを持ち、軽量な処理を行い、ビジネス機能に基づいて設計され、全自動でデプロイされ、他のサービスと HTTP API で通信します。同時に、サービスは最小限の集中管理(例えば Docker)を使用し、異なるプログラミング言語やデータベースなどのコンポーネントで実装できます。
では、開発の観点から、マイクロサービスとそれに対応する従来のモノリスサービス(Monolith)との顕著な違いを説明してみましょう。
-
マイクロサービスのスコープは小さく、特定の機能や機能の一部により多くの焦点を当てています。
-
スコープが小さいため、変更やクラッシュによる影響は従来のモノリスに比べて小さくなります。
-
多言語・多技術スタックのチームにとってよりフレンドリーです。
-
現在のインターネットが求める小さなステップでの迅速な反復という大目標に「適合」しています。
ここで考えるべきは、マイクロサービスのこの体系を実現し、実践するためにはどのような技術的な蓄積が必要かということです。私は主に 2 つの側面、アーキテクチャとガバナンスが必要だと思います。
まず、アーキテクチャについて話しましょう。マイクロサービスにとって最も厄介な問題は、従来のモノリスアプリケーションからの分割です(もちろん、最初からマイクロサービスを構築する場合は別ですが、そうであっても他の問題があります)。
前述のように、マイクロサービスは従来のモノリスアプリケーションに比べてスコープが小さく、特定の機能や機能の一部に焦点を当てています。ここから派生する最大の問題は、機能の境界を合理的に分割することです。
不適切な分割は、サービス間の相互依存を引き起こす可能性があります。例えば、ユーザー認証をショッピングサービスに置くと、フォーラムサービスが必要のないショッピングサービスに依存することになります。分割が過度に細かくなると、面白い現象が発生します。小規模なビジネスが 100 以上のサービスリポジトリに分割されることになります(この状況を「マイクロサービス難民」と呼びます)。
私たちがマイクロサービスの理念を実践するのは、ビジネスとチームの規模が拡大し、多様なニーズとチームメンバーの技術スタックに直面したとき、従来のモノリスアプリケーションの継続的なメンテナンスコストが大きな負担になるからです。私たちはマイクロサービスを導入することで、メンテナンスコストを可能な限り削減し、リスクを低減したいと考えています。しかし、不合理な分割は、メンテナンスコストがモノリスの継続的な実践を超えてしまう結果を招くことになります。
私が考えるもう一つのマイクロサービスの実践を妨げる問題はガバナンスの問題です。マイクロサービス化後に直面するいくつかの問題を見てみましょう。
-
可観測性の問題。前述のように、マイクロサービス化された単一のサービスのスコープは小さく、特定の機能や機能の一部に焦点を当てています。これにより、ビジネスリクエストを完了するために必要なリクエストチェーンが長くなる可能性があります。一般的な見解によれば、チェーンが長くなるほどリスクが大きくなります。サービスに異常が発生した場合(例えば、ビジネス RT が突然増加した場合)、具体的なサービスの問題をどのように特定しますか?
-
設定フレームワークの収束。マイクロサービス化のシナリオでは、基本的な機能を具体的な内部フレームワークに沈めることを選択することがあります(サービス登録、発見、ルーティングなど)。これは、独自のフレームワークを維持し、設定の収束を完了する必要があることを意味します。
-
よく知られたサービスガバナンス(登録、発見、サーキットブレーカーなど)。
-
マイクロサービス化により、完備された CI/CD メカニズムの必要性がより切実になります。爆論 1 の状況が存在する場合、これはマイクロサービスの理念を実践する障害となります。
確かに、現在オープンソースコミュニティ(Spring Cloud、Go-Micro など)や四大クラウドプロバイダー(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 セクションを見て、その盛況を確認できます(多くを語ると涙が出ます)。
まとめ#
私はこの記事が多くの議論を引き起こすことを知っています。しかし、私が常に表現したいポイントは、クラウドネイティブ時代のこの一連のもの(実際には以前の伝統的技術の延長でもあります)の導入は無代価ではなく、無コストではないということです。十分な規模と痛点を持つ企業にとって、このようなコストはビジネスの成長に対して正の促進となりますが、より多くの中小企業にとっては、この一連のものがビジネスの向上に対して非常に小さいか、あるいは負の影響を与える可能性があります。
私たち技術者が技術的な決定を行う際には、必ず自分のチームの技術的蓄積やビジネスの利益を評価した上で、特定の技術や理念を導入するべきであり、単にその技術が先進的であるから、すごいから、私の履歴書を裏付けることができるからという理由で導入すべきではありません。
最後に、以前私が共有した言葉をこの記事の結論として使いたいと思います。
技術の先進性を追求して技術を行う企業は、死に至る。