|
1. プロジェクト移行の背景 1.1 なぜ「太歳」(木星大公)を邪魔するのか? 現在、当社のテスト環境、UAT環境、本番環境はすべてKubernetesを用いて維持管理されています。ほとんどのプロジェクトはコンテナ化されており、長期間にわたり安定的にオンライン稼働しています。規模の大小を問わずプロジェクトをコンテナ化することで、テスト環境、UAT環境、本番環境のリリースツールとCI/CDプロセスの統合管理が徐々に実現しました。また、Kubernetesを基盤とした社内リリースレビュープラットフォームを開発し、Jiraなどのプロジェクト管理ツールと連携させています。 自社開発プラットフォームへのリリースにおいて、プロジェクトの開発進捗とリリースバージョンを自動的に連携させることができます。最も重要なのは、リリース権限の制御、リリースツールとリリースモードの統一、複数プロジェクトの複数モジュールのワンクリックリリースのサポートです。また、リリースに失敗したアプリケーションの統合ロールバックや、個々のアプリケーションのロールバックも含まれています。 このプロジェクトはこれまでGitRunnerを使用してリリースを行っており、仮想マシン上にデプロイされていたため、リリースレビュープラットフォームへの統合は行っていませんでした。しかし、プロジェクトの重要度と、関連するサービスやマシンの数の多さから、プロジェクトをコンテナ化し、リリースツールを統合することで、社内環境への適応性を高め、次世代クラウドコンピューティングの発展に適切に対応していく必要がありました。 1.2 Git Runner を廃止する理由 まず、Git Runnerのリリースページを見てみましょう。見た目はシンプルですっきりしていますが、実際に問題が発生することも珍しくありません。 1.2.1 マルチブランチ並列開発の問題点 複数のブランチを並行して開発する場合や、本番環境にリリースできるブランチが多数ある場合、手動によるデプロイメントフェーズで間違いが発生したり、間違った点を確認したりすることが起こりやすくなりますが、その可能性は非常に低くなります。 しかし、別の問題も存在します。コミットやマージのたびにビルドがトリガーされるのです。Git Flow のブランチ機能を使用する場合、多くのブランチが同時に開発、テスト、ビルドされる可能性があります。Git Runner を仮想マシンベースで作成すると、ビルドのキューイングが発生する可能性が高くなります。もちろん、このキューイングの問題は解決可能です。 1.2.2 マルチマイクロサービスの構成とメンテナンスの問題 第二に、プロジェクトが少しでも大きくなると、メンテナンスが非常に困難になります。例えば、移行しようとしているこのプロジェクトには、フロントエンドと20以上の業務アプリケーションに加え、Zuul、ConfigServer、Eurekaなど30近くのサービスが含まれています。各サービスはGitリポジトリに対応しており、開発中のブランチが多数存在します。GitLab CIスクリプトをアップグレードしたり、マイクロサービスのマシンにノードを追加したりする場合、これは非常に面倒で退屈な作業になるでしょう。 1.2.3 セキュリティの問題 最後に、セキュリティ上の問題があります。GitLabのCIスクリプトは通常、コードリポジトリに組み込まれているため、プッシュまたはマージ権限を持つユーザーは誰でもCIスクリプトを自由に変更できます。これは予期せぬ結果につながり、サーバーとビジネスのセキュリティを脅かす可能性があります。リリースに関しては、開発者なら誰でもリリースボタンをクリックできる可能性があり、これは常にセキュリティリスクとなっていました。 ただし、これはGit Runnerが推奨されないツールという意味ではありません。GitLabに組み込まれているAuto DevOpsとKubernetes統合の新しいバージョンは依然として非常に便利です。しかし、私たちの場合、多くのデプロイメントでGit Runnerを使用する可能性は低いため、統合されたデプロイメントツールとCIスクリプトの一元管理が必要です。そのため、他のCIツールの方が適しているかもしれません。 1.3 コンテナ化を使用する理由 1.3.1 ポート競合の問題 コンテナ化以前、このプロジェクトは仮想マシンを用いてデプロイされ、各仮想マシンは2~3つのマイクロサービスをクロスプラットフォームで実行していました。そのため、ポート競合という問題が発生していました。プロジェクトに新しいアプリケーションを追加する際には、サーバー間のポート競合を考慮し、各マイクロサービスが異なるポートを使用できるようにする必要がありました。これは、仮想マシンを用いてアプリケーションをデプロイする場合、マシンノードに障害が発生し、アプリケーションを手動で移行する必要があるケースが発生する可能性があるためです。一部のマイクロサービスが同じポートを使用している場合、移行プロセスに支障をきたす可能性があります。 さらに、プロジェクトに含まれるアプリケーションが少数であればポートのメンテナンスは問題にならないかもしれませんが、本プロジェクトのように30以上のマイクロサービスが関わるとなると、面倒な作業となります。しかし、コンテナを使用してデプロイする場合、各コンテナは互いに分離されており、すべてのアプリケーションが同じポートを使用できるため、ポートの問題を心配する必要がありません。 1.3.2 プログラムの健全性の問題 多くのJavaプログラマーは、ポートは開いているのにリクエストが処理されないなど、プログラムがフリーズしたように見える状況に遭遇したことがあるでしょう。これは、仮想マシン(VM)を使用してデプロイする際によく発生します。多くの場合、ヘルスチェックが効果的に実行されておらず、VM上でインターフェースレベルのヘルスチェックが不足している可能性があります。これにより、フリーズが未解決のままになり、自動処理が妨げられる可能性があります。さらに、VM上でインターフェースレベルのヘルスチェックと処理を実行することは簡単な作業ではありません。特に、プロジェクトに多数のマイクロサービスがあり、ヘルスチェックインターフェースに一貫性がない場合は、面倒で反復的な作業となります。 しかし、Kubernetesでは、組み込みのReadプローブとLiveプローブにより、上記の問題への対処が非常に簡単になります。図に示すように、現在3つのヘルスチェック方法がサポートされていることがわかります。
同時に、これらのヘルスチェックは非常に柔軟性が高く、チェック間隔、エラー数、成功数、チェックホストなどのパラメータをカスタマイズできます。さらに、前述のインターフェースレベルのヘルスチェックであるhttpGetは、ホスト名、リクエストヘッダー、チェックパス、HTTPまたはHTTPSなどのカスタム設定もサポートしています。ご覧のとおり、Kubernetesに組み込まれているヘルスチェックを使用することで、多くの作業を削減でき、煩わしいスクリプトを大量にメンテナンスする必要がなくなります。 1.3.3 障害回復の問題 仮想マシンを使用してアプリケーションをデプロイする場合、ホストマシンに障害が発生し、単一ノードのアプリケーションが使用できなくなったり、他のレプリカが利用できなくなったためにサービスに遅延が発生し、高負荷につながるといった状況が発生する可能性があります。ホストマシンが迅速に復旧できない場合は、これらの問題を解決するために、手動でノードや新しいサーバーを追加する必要があるかもしれません。このプロセスは、アプリケーションをデプロイする前に依存関係環境を準備する必要があり、場合によってはCIスクリプトの修正も必要になるため、時間がかかり、面倒な作業となる可能性があります。 Kubernetesオーケストレーションを使用すれば、このような問題を心配する必要はありません。すべての障害復旧および災害復旧メカニズムは、強力なKubernetesによって処理されます。コーヒーを一杯飲んだり、コンピューターを起動してこの問題に対処したりすれば、すべて正常に戻ります。 1.3.4 その他の軽微な問題 もちろん、Kubernetesがもたらす利便性と課題は、上記に挙げたものをはるかに超えています。コンテナイメージは依存環境の問題を解決し、サービスオーケストレーションはフォールトトレランスと災害復旧の問題を解決し、Kubernetesのパッケージ管理ツールを使えばワンクリックで新しい環境を構築でき、Kubernetesのサービスディスカバリを使えば開発者はネットワーク部分の開発に集中する必要がなくなり、Kubernetesのアクセス制御を使えば運用担当者は各サーバーの権限管理をする必要がなくなり、Kubernetesの強力なアプリケーションデプロイメント戦略を使えばゼロダウンタイムのアプリケーションデプロイメントやロールバックを実現する方法について深く考える必要がなくなるなど、これらの利便性は私たちの行動を静かに変えつつあります。 2. 移行計画 2.1 ブルーグリーン移行 まず、移行前のアーキテクチャを見てみましょう。 ほとんどの Spring Cloud アーキテクチャと同様に、このアーキテクチャではフロントエンドとして NodeJS、サービスディスカバリとして Eureka、ルーティングとして Zuul、構成センターとして ConfigServer を使用します。これは、追加コンポーネントをほとんど使用しない、企業で最も一般的な Spring Cloud アーキテクチャでもあります。そのため、最初の移行では深く考えず、他のプロジェクトの移行と同じアプローチを採用しました。つまり、Kubernetes 上に新しい環境(この移行ではミドルウェアは使用しませんでした)を作成し、基本的にはコンテナ化された環境を作成し、同じドメイン名で構成し、テスト用に hosts ファイル解決を追加し、すべてが正しく機能したらドメイン名を切り替えて移行を完了します。これは、アプリケーションリリースのブルーグリーンデプロイメントに似た、最もシンプルで一般的な方法です。Kubernetes 上に新しい環境を作成するためのアーキテクチャ図は次のとおりです。 このプロジェクトでは、テスト中に仮想マシン環境とコンテナ環境の2つの環境を並行して運用していました。コンテナ環境はテスターからのトラフィックのみを受信し、両環境は同じミドルウェアサービスに接続されていました。他の多くのプロジェクトがこのように移行しており、本プロジェクトもテスト環境で同様のプロセスを問題なく実行していたため、このアプローチが本プロジェクトでも機能すると想定されていました。しかし、現実は期待とは大きく異なることがよくあります。テスト中に、2つの環境を共存させたことで、一部の本番環境データが破損しました。コンテナ環境は整合性テストを実施しておらず、ドメイン名の強制切り替えも行われていなかったため、すべてのコンテナを緊急シャットダウンすることでようやく問題が解決しました。時間的制約のため、問題を徹底的に調査することはできず、一部のデータのみを修正しました。その後、移行プロセス中に一部のマイクロサービスのマスターブランチと本番環境のコードに不整合が発生したことが原因ではないかと疑いましたが、原因はそれほど単純ではないかもしれません。このような問題の再発を防ぐため、移行計画を修正する必要がありました。 2.2 グレースケール移行 上記の移行計画にはいくつか問題点があったため、以前の計画よりも少し複雑な新しい計画が考案されました。アプリケーションのカナリアリリースのように、マイクロサービスを一つずつKubernetesに移行するという手法を採用しました。 単一のアプリケーションを移行する場合、コンテナ環境と仮想マシン環境間のコードの一貫性を確保することが非常に重要です。移行中、マイクロサービスはドメイン名を使用して登録する必要があります。つまり、各マイクロサービスは内部ドメイン名で設定され、コンテナのIPアドレスとポートではなく、このドメインを介してEurekaに登録されます(Kubernetes内では内部IPアドレスと仮想マシンは相互接続されていないため)。移行後の環境は次の図に示されています。 この時点で、ドメイン名 service-c.interservice.k8s が ServiceC を指しています。ServiceC が Eureka に登録されると、アドレスがこのドメイン名に変更されます(デフォルトはホストマシンの IP アドレスとポートです)。他のアプリケーションはこのアドレスを介して ServiceC を呼び出します。ServiceC がテストされ、正常に動作していることが確認されると、仮想マシンからオフラインになります。最終的なアーキテクチャは図に示されています。 Zuul、フロントエンドUI、そしてEurekaを除くすべてのサービスは、ブルーグリーンアプローチよりも複雑なカナリアロールアウトアプローチを用いてKubernetesに移行されました。このアプローチでは、マイクロサービスごとに個別のサービスとドメインを作成する必要があり、移行完了後にはこれらを削除する必要があります。この時点で、Eurekaを除くすべてのサービスがKubernetes上にデプロイされています。Eurekaの移行には、さらに複雑な詳細が伴います。 2.3 ユーレカ移行 この時点では、サービスアクセスに関する問題は発生しておらず、Eurekaを除くすべてのサービスがKubernetes上にデプロイされていました。しかし、Eurekaの移行設計にはさらなる課題が伴う可能性があります。高可用性のEurekaクラスターをKubernetes上に直接デプロイし、ConfigServerのマイクロサービス登録アドレスをKubernetes上のEurekaアドレスに変更するだけでは不十分です。2つのEurekaクラスターが独立したゾーンに配置されているため、登録情報が共有されず、構成変更時に登録情報が失われる可能性があります。最終的なアーキテクチャは次のようになります。 つまり、構成置換プロセス中に、ServiceA は以前の Eureka インスタンスに登録されている一方で、ServiceB は Kubernetes Eureka インスタンスに登録されている可能性があります。その結果、ServiceA は ServiceB を見つけられなくなり、逆もまた同様となります。 そのため、KubernetesでEurekaクラスタを構築した後、各Eurekaインスタンスに一時的なドメイン名を設定する必要があります。次に、Kubernetesで以前のEurekaクラスタとEurekaクラスタのゾーン設定を変更し、仮想マシン内のEurekaインスタンスで新しいクラスタを形成します。これにより、登録情報が同期され、サービスがどこに登録されていても、互いを見つけられなくなることがなくなります。この時点でのアーキテクチャ図は次のとおりです(この時点では、すべてのサービスは元のEurekaクラスタに登録されています)。 次のステップは、マイクロサービス構成を変更することです。これには、次の 3 か所の変更が必要です。
最終的なアーキテクチャ図を図に示します。 3. まとめ サービスの可用性を確保するため、私たちはやむを得ずカナリア移行アプローチを採用しました。これはブルーグリーンアプローチよりもはるかに複雑で、より多くの問題を考慮する必要があります。アプリケーションが問題なく動作することを前提とすると、問題が少なく、より迅速かつ容易なブルーグリーン移行アプローチを推奨します。もちろん、大規模なプロジェクトやサービスの中断が許容されないプロジェクトでは、一度の切り替えではテストが必要な領域が漏れてしまう可能性があるため、カナリアアプローチの方が信頼性が高い場合があります。どのアプローチを採用するにせよ、アプリケーションをコンテナ化し、Kubernetesに移行することは非常に重要です。クラウドコンピューティングは未来であり、Kubernetesはクラウドコンピューティングの未来だからです。 オリジナルリンク: https://www.cnblogs.com/dukuan/p/13285941.html |