はじめに
DevOpsプラットフォームの取り組みを紹介する2回目の記事の前半です。
こんにちは。Qmonus (クモナス) Value Streamの開発チームの松本です。
前回の記事では、Qmonus Value Streamの概要を紹介しました。
連載第2回となる今回は、Qmonus Value Streamの重要で特徴的な機能の1つであるCloud Native Adapterを使い、アプリケーションをデリバリする事例を2つ、前編と後編の2回に分けて紹介します。 前編では、Cloud Native Adapterを用いたクラウド基盤の構築を中心に説明します。
クラウド技術の多様化・複雑化
近年のアプリケーション開発において、GCP/Azure/AWS等のパブリッククラウドの利用はデファクトスタンダードとなりました。 また、多くのプロダクトはコンテナアプリケーションとして開発され、Kubernetesやその他のコンテナ実行環境を使ってサービス提供されています。 システムの基盤はパブリッククラウドを使う事で迅速に構築できるようになりましたが、パブリッククラウドが提供するサービスは多様化・複雑化しており、要件によっては監視や認証、メール送信などで別々のパブリッククラウドやSaaSを組み合わせる必要があります。 それぞれのサービスには適切なパラメータの決定も必要です。 商用提供しているプロダクトでは、開発環境やステージング環境そしてプロダクション環境と複数の環境を適切に構築するために、Infrastructure as Code(以下、「IaC」といいます)の導入も必要となるでしょう。
このように、クラウド技術によりアジリティは大幅に向上したものの、要件に応じてクラウドサービスを組み合わせてアーキテクチャを設計し構築するためには、高い専門性だけではなく多大な労力をも必要とするのが現状の課題です。
Qmonus Value Stream(以下、「QVS」といいます)では、このような課題をCloud Native Adapter(以下、「Adapter」といいます)を提供して解決します。
ユースケース1: KubernetesとGCPによるパブリックAPI公開
アプリケーションのデリバリを実践する1つ目の事例として、GCPのWAF/FirewallであるCloud Armorを適用したWebアプリケーションを構築します。
コンテナでWebアプリケーションを公開する際には、多くの場合GKEのようなマネージドKubernetesサービスを利用しますが、マネージドKubernetesを用意するだけではWebアプリケーションを公開できません。 例えば、WEBアプリケーションをWAFを適用して提供する場合、マネージドKubernetesの準備に付随して次の作業が必要となります。
- グローバルIPアドレスの確保
- 確保したグローバルIPアドレスに名前解決するためのDNSレコードの設定
- SSL/TLSサーバ証明書の発行
- 適切なSSL/TLS暗号スイートの設定
- WAF/Firewallのポリシー設定
- ロードバランサの設定
不適切な設定や設定漏れがあると、アプリケーションが動作しないだけではなく、最悪の場合セキュリティホールを作ってしまいプロダクトの継続に大きな悪影響を与えてしまうので、確実な実施が必要です。
これらのリソースを構築するには、TerraformでCloud ArmorやGCLBなどのGCPリソースを構築し、そして、Kustomizeなどを使ってService・Ingress・BackendConfigなど多くのKubernetesマニフェストを記述し適用する必要があります。 また、これら多くのサービスを相互参照しながら正しく構成する必要があります。意図した動作をしない場合には、利用する複数サービスのログやマニフェストを調査して修正した後に再度動作確認するということを繰り返すこととなります。
このように、QVSを使わない場合には、パブリッククラウド、Kubernetes、IaCツールに対する高い専門性と多くの時間が要求されます。
Qmonus Value Streamを用いたクラウド基盤構築
前回ご紹介したように、Adapterは、クラウド基盤とContinuous Integration/Continuous Delivery(以下、「CI/CD」といいます)パイプラインを構築するためのベストプラクティスをパッケージ化したものです。 アプリケーション開発者は、Adapterを選択しパラメータを指定するだけで、クラウド基盤とCI/CDパイプラインを高い専門知識がなくても構築できます。
Adapterは、デプロイ対象のApplicationマニフェストと、Pipelineマニフェストの両方を生成します。 Applicationマニフェストは、Kubernetesリソースやクラウドリソースにより構成され、デプロイするアプリケーションのシステム構成を示します。 Pipelineマニフェストは、CI/CDパイプラインのビルドからリリースに至る過程において「いつどのようなTaskを実行するか」を定義しています。QVSはCI/CDの実行エンジンとして Tekton を採用しており、PipelineマニフェストはTekton Pipeline/Taskリソースとして記述されます。
Adapterの選択
QVSの設定ファイルであるQVS Configを作成し、その中で使用するAdapterを選択します。
以下に、QVS Configの具体例を示します。Adapterは、 designPatterns
の下に配列で配置されます。
params: - name: namespace type: string - name: imageName type: string designPatterns: - pattern: qmonus.net/adapter/official/kubernetes/deployment/simple params: appName: public-api-test-app namespace: $(params.namespace) imageName: $(params.imageName) port: "5000" replicas: "1" - pattern: qmonus.net/adapter/official/kubernetes/gke/publicapi params: appName: public-api-test-app namespace: $(params.namespace) port: "5000" domainName: public-api-app-demo1.example.com gcpExternalAddressName: matsumoto-gip2 gcpSecurityPolicyName: matsumoto-policy1 gcpSslPolicyName: matsumoto-ssl-policy - pattern: qmonus.net/adapter/official/pipeline/build:buildkit - pattern: qmonus.net/adapter/official/pipeline/deploy:simple
1つ目と2つ目のAdapterは、クラウド基盤の構築を担当し、1つ目は下図の赤破線、2つ目は下図の青破線で囲まれた場所を構築します。 1つ目のAdapterではKubernetesのDeploymentを生成し、2つ目のAdapterではGCPのWAF/FirewallであるCloud ArmorやCloud Load Balancingを構築しつつ、連携するようにKubernetesのService、Ingress、ManagedCertificate、BackendConfig、FrontendConfigを構成します。 これらのリソースを全てTerraformやKubernetesマニフェストで記述すると多くのリソースが必要になり複雑ですが、Adapterを使えば上記の通り簡潔に記述できます。
各Adapterは、実行時にパラメータを外部から注入できます。 1つ目のAdapterでは、外部から注入されたimageNameパラメータによりコンテナイメージとバージョンを受け取り、Kubernetes Deploymentを生成しています。 パラメータとして注入するコンテナイメージとバージョンを変更することで、QVS Config自体に変更を加えることなく簡単にバージョンアップが実現できます。
Adapterにおけるパラメータの正規化・外部インターフェース化の機構はCUE言語の表現力を用いて実現されています。 この詳細については、別の記事で改めて紹介します。
3つ目と4つ目のAdapterは、CI/CDパイプラインを構築するものです。 この部分の詳細は後編で説明します。
今回説明した4つのAdapterは、全てQVS開発チームが提供し保守しているOfficial Cloud Native Adapter(以下、「Official Adapter」といいます)です。 広く一般的に使われるクラウド構成や CI/CDパイプラインの基本となるタスクについては、Official Adapterに含まれているので、そのまま利用できます。
CI/CDパイプラインの構成
QVSでは、AssemblyLineという独自のリソースを用いてCI/CDパイプラインを構成し、Adapterより生成されたTekton Pipelineを実行することでアプリケーションをデリバリします。 AssemblyLineの詳細については、後編でご説明します。
CI/CDパイプラインの実行
AssemblyLineマニフェストをQVSに登録し実行すると、Build PipelineとDeploy Pipelineが実行されて、Adapterより生成される各種ApplicationマニフェストがGCPとGKEに対してデプロイされます。
AssemblyLineを実行すると、QVSのWebUIから進捗状況が確認できます。 Build PipelineとDeploy Pipelineが実行されて、処理が正常終了したことを確認できました。
デプロイ先のGKEにアクセスし、アプリケーションが正常に動作していることを確認します。以下の通り、DeploymentやService、Ingressが正しく作成されていました。
% kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE public-api-test-app 1/1 1 1 1h %kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE public-api-test-app NodePort 10.0.72.51 <none> 5000:32663/TCP 1h %kubectl get ingress NAME CLASS HOSTS ADDRESS PORTS AGE public-api-test-app <none> * 203.0.113.10 80 1h
また、GCPのコンソールからもWebアプリケーション提供に必要となるCloud ArmorやロードバランサなどのGCPリソースが適切に作成されていることが確認できます。
以下のCloud Armorの画面で、ロードバランサにポリシーが適用されています。
以下のロードバランサの画面では、SSLのポリシーや証明書などが設定されておりバックエンドであるKubernetesに転送されるように設定されています。
そして、実際に構築したWebアプリケーション(https://public-api-app-demo1.example.com
)にアクセスすると、サンプルアプリケーションからの応答が確認できました。
前編では、複雑なTerraformやKubernetesマニフェストの記述する代わりに、QVSチームから提供されるOfficial Adapterをいくつか選択し記述するだけでクラウド基盤を構築する事例を紹介しました。
後編に続きます。