NGINX Modern Apps Reference Architectureバージョン1.0.0を発表

NGINX | 2022年4月28日

2021年8月のSprint 2.0でNGINX Modern Applications Reference Architecture(MARA)を発表した際、私たちは設計目標を明確に示しました。Kubernetes上で稼働し、セキュリティ、スケーラビリティ、信頼性、監視、イントロスペクションをサポートするよう設計された、モダンアプリケーションアーキテクチャの実例を作ることが目標でした。このプロジェクトには、時間のかかる統合作業を行わずに機能コンポーネントを「プラグアンドプレイ」方式で組み合わせ、さまざまなインフラストラクチャにデプロイできることが求められました。

Sprint以降の数か月間、私たちはロードマップに沿って取り組みを進めてきました。他のプロジェクトと同様に、成功も失敗も経験してきました。成功した成果をMARAに取り入れる一方で、得られた教訓を継続的に蓄積しています。こうした問題を文書化し、教訓を設計に反映することで、他の方々が同じ問題に直面するのを避ける一助となれば幸いです。

このたび、MARA version 1.0.0のリリースという節目を迎えました。このバージョンでは、プロジェクトディレクトリを再編成し、環境の作成と破棄のプロセスを変更しています。また、重複するコードを排除し、今後の追加に容易に対応できるディレクトリ構造を構築するとともに、管理スクリプトを標準化しました。このバージョンはMARAの歴史における重要な節目となるため、ここでコミュニティの皆さまに進捗をご報告し、特に重要だと考える教訓を共有するとともに、今後のロードマップについてご案内します。

NGINX Modern Apps Reference Architectureバージョン1.0.0のトポロジ図

テレメトリ — メトリクス、ロギング、トレーシング

MARAの主要コントリビューターは、大規模環境でソフトウェアを運用した経験があり、運用、エンジニアリング、管理の各観点からサービスを提供するために何が必要かを理解しています。アプリケーションが予期せぬ動作をしているのに、問題の正確な原因を簡単に特定できないときの、あの不安な気持ちもよく知っています。DevOps界隈で広まっている次の言葉が、この問題を端的に言い表しています。「マイクロサービスのデバッグは、連続殺人事件の謎を一つずつ解くようなものだ」

この点を踏まえ、短期ロードマップではオブザーバビリティの追加を最優先事項としました。ここでいうオブザーバビリティには、ログ管理、メトリクス、トレースデータが含まれます。ただし、データを収集するだけでは不十分です。データを掘り下げて分析し、環境内で何が起きているのかについて有意義な判断を下せる必要があります。

トレーシングの選択肢を検討した結果、OpenTelemetry(OTEL)にたどり着きました。OTELは、ログ、メトリクス、トレースを含むあらゆるテレメトリデータに対応しているためです。F5が想定した実装では、OTELエージェントがすべてのトレーシングデータを収集、処理、重複排除してから、集約とエクスポートのためにOTELコレクターへ渡し、ワークフローの最後に可視化システムを配置してデータを活用できるようにします。このアプローチでは、OTEL標準を活用して収集や集約などの前段階を簡素化しながら、データの表示と分析について幅広い選択肢をユーザーに提供できます。

実装は2段階で構築しました。

  1. 環境内のOTELコレクターを管理するために、OpenTelemetry Operator for Kubernetesをデプロイします
  2. トレースとメトリクスを出力するように、Bank of Siriusアプリケーションを計装する

MARAの初期バージョンでは、ロギングにElasticsearchとFilebeatを使用していました。これらをGrafana Lokiに置き換えることも検討しましたが、当面は当初の構成を維持することにしました。メトリクスについては、PrometheusとGrafanaをベースとする当初のデプロイメントを見直す必要があると判断しました。そこで、当初使用していた独自のPrometheus設定を、コミュニティによって保守されているkube-prometheus-stack Helmチャートに置き換えました。このチャートにより、Grafana、node exporters、Kubernetes環境の管理に適した事前設定済みの各種ダッシュボードとスクレイプターゲットを含む、完全なPrometheus環境が構築されます。さらに、F5 NGINX Ingress ControllerとBank of Siriusアプリケーション用のダッシュボードも追加しました。

これは、OTELの実装に必要となった膨大な作業の概要にすぎません。同じ険しい学習曲線をたどる方々の負担を軽減するため、プロセス全体をブログ記事「Modern Apps Reference ArchitectureへのOpenTelemetryの統合 – 進捗レポート」にまとめました。

デプロイオプション – Kubeconfig

MARAの初期バージョンでは、デプロイ環境としてAmazon Elastic Kubernetes Service(EKS)を選択しました。その後、多くのユーザーから、コスト上の理由により、ラボやワークステーションなど、必要なリソースが少ない「ローカル」環境でMARAを実行したいという声が寄せられました。移植性は当初からプロジェクトの主要な目標であり、現在も変わっていません。そこで、移植性を実現できることを証明する機会と捉えました。作業を容易にするため、一定の最小要件を満たす任意のKubernetesクラスターで実行できるデプロイ手順を設計することにしました。

最初のステップとして、Kubernetesクラスターと通信するためにkubeconfigファイルを読み込む新しいPulumiプロジェクトをMARAに追加しました。このプロジェクトは、Pulumi Kubernetesプロジェクトとインフラストラクチャプロジェクト(後者の例としては、AWSやDigital Ocean向けのプロジェクトがあります)の間に位置します。実際、kubeconfigプロジェクトを作成することで、新しいインフラストラクチャプロジェクトを統合しやすくなります。インフラストラクチャプロジェクトからkubeconfigプロジェクトにkubeconfigファイル、クラスター名、クラスターコンテキストを渡すことができれば、以降のMARAデプロイ手順はシームレスに機能します。

テストでは、CPUとメモリの要件が小さく、インストールが容易な複数のKubernetesディストリビューションを使用しました。これには、K3s、Canonical MicroK8s、minikubeが含まれます。すべてのディストリビューションは、2 CPU、16 GB RAMを搭載し、Ubuntu 21.10を実行する仮想マシン(VM)にデプロイしました。また、永続ボリュームとKubernetes LoadBalancerをサポートするように構成しました。

このプロセスで最も難しかったのは、プロジェクトに含まれるカスタムビルドのNGINX Ingress Controllerで使用するプライベートレジストリへの対応でした。(MARAをデプロイする際は、このカスタムビルドのNGINX Ingress Controllerに加えて、NGINX Open SourceまたはNGINX Plusをベースとする標準のNGINX Ingress Controllerも使用できます。)よりプラットフォームに依存しないアプローチを採用するには、レジストリのロジックをAmazon Elastic Container Registry(ECR)から切り離す必要があることが判明しました。この作業は現在進行中です。また、エグレスアドレスのホスト名を取得するロジックがAWS Elastic Load Balancing(ELB)に大きく依存しており、他のユースケースにも適用できるよう書き直す必要があることも分かりました。

MARA管理スクリプトとPulumiプロジェクトでは現在、上記の問題を回避するための固有のロジックを使用しています。当面、Kubernetes構成ベースのデプロイでは、公式のNGINXレジストリにあるNGINX Ingress Controller(NGINX Open SourceまたはNGINX Plusをベースとするもの)を使用する必要があります。

クラウドベースのデプロイに必要なリソースを確保できないローカル環境にも対応できるよう、MARA構成ファイルに複数の調整パラメーターを追加しました。ほとんどのパラメーターは、Elastic Stackの各種コンポーネントに要求するレプリカ数に関するものです。テストの進展に伴い、デプロイ環境のリソース制約に応じてMARAを微調整するためのパラメーターも追加される予定です。

これらの変更により、K3s、MicroK8s、Minikubeへのデプロイが可能になり、次の環境でロジックのテストにも成功しました。Azure Kubernetes Service(AKS)、Digital Ocean、Google Kubernetes Engine、Linode、およびRancherのHarvesterです。詳細については、ブログの「MARA Provider Status page」および「MARA: Now Running on a Workstation Near You」をご覧ください。

パートナーとの連携

パートナー各社は、MARAに関するF5の取り組みに高い関心を示し、積極的に支援しています。多くのパートナーから、プロジェクトの詳細、自社製品での活用方法、さらには機能追加についてお問い合わせをいただいています。

MARAの中核要素としてPulumiを採用したのは、使いやすく、Pythonをサポートしているためです。Pythonは非常に広く普及している言語であるため、多くのコミュニティメンバーがMARAのコードを容易に理解できます。また、Pulumiの活発なコミュニティとプロジェクトへの積極的な関与は、MARAで実現を目指すコミュニティ参加の模範となりました。

2021年後半、F5はSumo Logicと協力し、NGINX Ingress Controllerを使用する同社のクラウド監視ソリューションにMARAを組み込みました。これは、MARAがプラガブルであるという主張を検証する機会となりました。課題は、MARAのGrafana、Prometheus、ElasticをSumo Logicソリューションに置き換えることでした。他のデプロイメントと同じロジックを使用してソリューションを正常に立ち上げ、Sumo Logic SaaSへの接続だけでなく、F5の環境からメトリクスを取得するように構成できたことをうれしく思います。

OpenTelemetryに関する取り組みの一環として、Lightstepと協力し、OTELコレクターを容易に再構成して、トレースとメトリクスをLightstepのSaaSサービスにエクスポートできるようにしました。OTELはオブザーバビリティの未来を担うものだと確信しており、この分野をさらに詳しく検証していきたいと考えています。

これまでに得られた教訓

これまでに得た最大の教訓は、モジュール型アプローチが有効だということです。Sumo Logicとの取り組みにより、MARAのコンポーネントを柔軟に組み合わせられることが実証されました。OTELの環境への統合をさらに進めることで、この点がより明確になると見込んでいます。以前にも触れたとおり、スタックのリソース使用量を削減できることから、ログ管理環境をElasticsearchからGrafana Lokiに置き換えることを検討しています。ただし、あらゆるものをマイクロサービス化するという極端な方法ではなく、「実用的なモジュール化」を推奨します。たとえば、多数のアプリケーションのログを処理できる専用サービスを用意することには合理性がありますが、ログの収集、保存、可視化のそれぞれに個別のマイクロサービスが必要かどうかは明確ではありません。

また、該当するパラメーターを単に省略するのではなく、デフォルト値を設定に明示的に含めることが有用だと分かってきました。これには、管理者にとって2つの利点があります。デフォルト値を覚えておく必要がなく、設定内の適切な位置に正しい構文ですでに記載されているパラメーターを変更するだけで、デフォルト値を簡単に変更できます。

私たちが痛感したもう1つの教訓は、最良だからではなく、インストールが最も簡単だったり、チュートリアルが最も充実していたりするために普及しているソリューションもあるということです。だからこそ、設計プロセスでは前提を疑い、同僚に相談することが非常に重要です。オープンなコミュニケーションを重視する文化は、問題の早期発見と修正に大きく役立ちます。

とはいえ、実際に動作はするものの、後から変更が難しくなったり、別の問題を引き起こしたりするロジックを実装してしまったことが何度かありました。たとえば、Pulumiを介してアプリケーションのデプロイを始めた当初は、ConfigMapsにYAMLマニフェストを使用し、変数の更新にはPulumi transformationsを利用していました。この方法でも動作しましたが、保守性をはじめ、いくつかの理由から理想的とはいえませんでした。次のイテレーションでは、kube2pulumiを使用してマニフェストをPulumiコードに変換し、そのコードからConfigMapsを構築できるようにすることで、コードの可読性と保守性を向上させました。

もう1つの教訓は、マージによってデプロイ用YAMLに無効な設定が挿入されたことから得られました。コードが構文的に正しく、意図したとおりに動作することを確認するため、YAMLの大部分を書き直して慎重にレビューせざるを得ず、手間と時間のかかる作業となりました。今後の問題を回避するため、現在はGitHubへのプッシュ時に、汎用YAMLとKubernetes固有の自動化されたリントおよび検証を実行しています。

最後に、メインラインブランチを常に実行可能な状態に保つことは、当初からの目標でした。新しいプロジェクトをチェックアウトした際に、メンテナーがメインラインに持ち込んだ問題への対処を余儀なくされるのは、もどかしいものです。残念ながら、Bank of Siriusサブモジュールに関する以下の例を含め、これまでに何度かこの目標を達成できませんでした。

  • 誤ってURLスキームをssh://からhttps://に変更し忘れていました。私たちは全員、GitHubへの接続にsshを使用しているため、問題にはなりませんでした。しかし、GitHub用のSSHキーを持っていないユーザーがサブモジュールを初期化しようとすると、大量のエラーメッセージが表示されました。
  • 管理スクリプトのあるリリースは、一般的なパッケージに依存していました。私たちは、そのパッケージが自分たちのマシンと同様に、すべてのユーザーのマシンにもインストールされているものと誤って思い込んでいました。
  • 起動ロジックを書き直した際に、サブモジュールのソースを確認する処理を入れ忘れていました。このサブモジュールにはBank of Siriusのデプロイに必要なマニフェストが含まれていますが、残念ながら、これらのマニフェストが利用できない場合に出力されるエラーや警告が非常に分かりにくく、根本原因を突き止めるまで、数日間にわたって不可解な挙動のデバッグに奔走することになりました。

今後の展開

今後数か月の開発では、NGINX Ingress Controllerのビルド、レジストリへのプッシュ、Ingressのホスト名/IPアドレスに関するロジックのリファクタリングなど、大規模な計画を予定しています。

MARAを立ち上げるたびに気付くのは、NGINX Ingress Controllerに対するスキャンや攻撃が非常に早い段階で確認されることです。これを受け、NGINX Ingress ControllerとNGINX App Protect WAFをMARAに統合する取り組みを開始しました。これに伴い、App Protectが生成するログを最適に管理する方法を検討するという課題と機会が生まれています。

今後数か月以内に予定しているもう1つの変更は、すべてのモジュールがPulumiとKubernetesの両方からではなく、Kubernetesからシークレットを取得するようにすることです。これにより、すべてのモジュールが共通のシークレットリポジトリを使用し、管理者がシークレットの格納方法を制御できるようになります。現在、ユーザーが選択したリポジトリからシークレットを読み取り、対応するKubernetesシークレットを作成する新しいモジュールを開発しています。

MARAには現在、負荷生成ツールが含まれています。これは、Bank of Siriusのフォーク元であるオリジナルのBank of Anthosアプリに付属するLocustベースのツールをアップグレードし、一部変更したものです。現在開発中の新しいテストツールCicada Swarmは、負荷を生成するだけでなく、メトリクスが設定済みのしきい値を超えた時点を追跡して報告します。これにより、クラウド上のソフトウェア製品のパフォーマンスを迅速にテストするためのフレームワークとして機能します。並列化技術を使用することで、必要な信頼水準とより高い精度を備えたテスト結果を提供します。また、カスタマイズ可能な回帰分析により、CI/CDパイプライン内のビルドが成功したか失敗したかを判定します。

最後に、負荷テストについて語るうえで、その影響をどのように測定するかは欠かせません。そこで、再びテレメトリの話に戻ります。OpenTelemetryの可能性に期待しており、近いうちに、より包括的な実装を導入したいと考えています。完全な実装に至っていない段階でも、テストを実行してその影響を測定し、得られたデータに基づいて運用上の意思決定を行えるようにすることが目標です。

これまでと同様、皆さまからの「pull requests」、「issues」、「comments」を歓迎します。MARAの目標は、コミュニティが協力してさまざまな解決策について議論、試行、テスト、改善を重ね、モダンアプリケーションを導入・管理する最適な方法への理解を深められるよう促すことです。

関連記事

この記事はシリーズの一部です。MARAに順次機能を追加するのに合わせて、詳細をブログで公開しています。


共有

関連するブログ記事

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
NGINX | 2024/01/18

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する

OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
NGINX | 2023/05/31

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正

Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
NGINX | 2023/02/09

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法

Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINX | 2022/05/24

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング

NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
NGINX | 2018/08/17

SELinuxでNGINXおよびNGINX Plusを使用する

Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。

NGINX PlusによるAWS Auto Scalingグループの負荷分散
NGINX | 2017/03/06

NGINX PlusによるAWS Auto Scalingグループの負荷分散

新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります