kustomizeやSecretを利用してJavaアプリケーションをデプロイする

2021年5月20日(木)
深見 圭介

はじめに

今回は、これまでの回で学んだことを踏まえて、より複雑で実践的なアプリケーションをデプロイしてみましょう。

サンプルアプリケーションの概要

今回利用するサンプルアプリケーションは、技術ブログサイトをイメージして作成しました。4つのサービスに分かれており、それぞれ「Article」「AccessCount」「Rank」「WebSite」と呼びます。

アプリケーションのソースコードとデプロイ用のマニフェストはGitLab.comの以下のプロジェクトで公開されています。

https://gitlab.com/creationline/thinkit-kubernetes-sample1

  • WebSiteサービス:エンドユーザ向けのWebサイトを提供。記事の一覧と各記事のページが閲覧でき、前日のアクセスランキングがサイドバーに表示される。
  • Articleサービス:ブログ記事の一覧と取得、作成のAPIを提供。また、記事の取得APIは独自のヘッダーX-UIDにユーザ名を指定すると当該ユーザからのアクセスをAccessCountサービスに通知して保存する
  • AccessCountサービス:記事へのアクセス数を記録、集計するAPIを提供。アクセス数は延べアクセス数とユニークユーザ数の両方を計算する
  • Rankサービス:アクセス数順位の取得と更新APIを提供。また、設定された時刻に自発的にアクセス順位表を更新する

また、アプリケーションの詳細には立ち入りませんが、WebSiteはプログラミング言語にTypeScriptを、フレームワークにNuxtJSを利用し、Node.jsでホストされています。Article、AccessCount、Rankサービスはプログラミング言語にJavaを、フレームワークにSpring Frameworkを利用しています。

マニフェスト内容の確認

アプリケーションのマニフェストの内容を確認していきましょう。リポジトリには開発環境を想定したマニフェストとプロダクション環境を想定したマニフェストが含まれており、以下の場所に配置されています。

  • 開発環境向け:deployments/develop/kubernetes/
  • プロダクション環境向け:deployments/production/kubernetes/

それでは、プロダクション環境向けのマニフェストを見ていきます。ファイルを整理すると以下のようになっています(上記のマニフェスト配置場所のディレクトリからの相対パスで表記しています)。

  • マニフェストの統合
    • kustomization.yaml
  • コンポーネント毎のマニフェストと関連ファイル
    • Articleサービス
      • deployment-article.yaml
      • service-article.yaml
      • ingress-article.yaml
      • config/article/config.env.sample
        • 設定のサンプルファイル。実際の設定はこのファイルをconfig.envにコピーして設定する
    • AccessCountサービス
      • deployment-accesscount.yaml
      • service-accesscount.yaml
      • ingress-accesscount.yaml
      • config/accesscount/config.env.sample
        • 設定のサンプルファイル。実際の設定はこのファイルをconfig.envにコピーして設定する
    • Rankサービス
      • deployment-rank.yaml
      • service-rank.yaml
      • ingress-rank.yaml
      • config/rank/config.env.sample
        • 設定のサンプルファイル。実際の設定はこのファイルをconfig.envにコピーして設定する
    • WebSiteサービス
      • deployment-website.yaml
      • service-website.yaml
      • ingress-website.yaml

以下、ファイルごとに見てみましょう。

マニフェストの統合

今回のように複数のアプリケーションを含む場合、1つのYAMLファイルにすべてのマニフェストを書くこともできますが、検索性の観点からも複数のファイルに分けることが多いでしょう。

複数のマニフェストをまとめてデプロイできるように管理するツールとして「kustomize」があります。独立したCLIツールとしても利用できますが、kubectlにも組み込まれています。今回のアプリケーションでもkustomizeを利用します。

今回はkustomizeの機能全体を解説しませんが、マニフェストのデプロイで利用している機能はその都度、解説します。

kustomizeはkustomization.yamlファイルの内容を元に具体的なマニフェストや関連するファイルを組み合わせ、最終的にkubernetesにデプロイする完全なマニフェストを作成します。

kustomization.yamlの内容をざっと見ていきます。ファイルの先頭にはkubernetesマニフェストと同様にapiVersion、kindフィールドがあります。これらの値はツールがサポートするバージョンに合わせます。

apiVersion:kustomize.config.k8s.io/v1beta1
kind:Kustomization

resourcesフィールドにはkubernetesマニフェストファイルが列挙されています。このフィールドで指定されたマニフェストが、ほかのフィールド(transformerとも呼ばれる)で指定された変更を加えてkustomizeの出力マニフェストになります。

resources:
- deployment-article.yaml
- service-article.yaml
- ingress-article.yaml
- deployment-accesscount.yaml
- service-accesscount.yaml
- ingress-accesscount.yaml
- deployment-rank.yaml
- service-rank.yaml
- ingress-rank.yaml
- deployment-website.yaml
- service-website.yaml
- ingress-website.yaml

この後にはimagesフィールドが続きますが、これらは関連するマニフェストと一緒に見ていくほうが分かりやすいので、該当箇所にて解説します。

images:
- name: article
  newName: registry.gitlab.com/thinkit-kubernetes-sample1/article
- name: accesscount
  newName: registry.gitlab.com/thinkit-kubernetes-sample1/accesscount
- name: rank
  newName: registry.gitlab.com/thinkit-kubernetes-sample1/rank
- name: website
  newName: registry.gitlab.com/thinkit-kubernetes-sample1/website

Generatorにより生成されるSecret/ConfigMap

kustomization.yamlのsecretGenerator、configMapGeneratorフィールドは実際のマニフェストとは異なる設定ファイルなどから対応するSecretやConfigMapのマニフェストを生成するためのフィールドです。

SecretやConfigMapはアプリケーションの設定を保持するリソースであり、コンテナ外部から環境変数や設定ファイルとしてアプリケーションに読み込むことができます。どちらも大きな機能差はありませんが、Secretは機密情報が格納されることを想定して取り扱われます。例えば、コンテナで利用される際にSecretの内容が永続ストレージではなく一時ストレージに保存されるなどです。Secretの詳細なセキュリティ特性や管理者・利用者の責任となる事項については公式ドキュメントを参照してください。

kustomization.yamlでの設定内容を具体的に見ていきます。

secretGenerator:
- name: article-config
  envs:
  - config/article/config.env

1つ目のsecretGeneratorフィールドの要素が1つのSecretマニフェストを生成します。ここで生成したSecretは後述するDeploymentの環境変数として設定され、アプリケーションが読み取ります。

envsフィールドで指定されているファイルそのものはリポジトリに含まれていません。実際にデプロイするにはconfig/article/config.env.sampleファイルをコピーしてconfig/article/config.env.sampleを作成し、内容を環境に合わせて設定してデプロイします。

config.envは、例えば以下のように設定します。

DATABASE_URL=r2dbc:postgresql://managed.postgresql.example.com:5432/article?someoption=somevalue
DATABASE_USERNAME=username
DATABASE_PASSWORD=password

DATABASE_URLはR2DBCのためのURLです。スキーマが異なりますが、おおよそJDBCの接続URLと同じで、以下の形式となっています。

r2dbc:postgresql://<hostname>:<post>/<database>

DATABASE_USERNAME / DATABASE_PASSWORD はそのままPostgreSQLのユーザ名、パスワードです。上記の内容をconfig.envに設定すると、kustomizeの出力では以下のようなSecretが生成されます(見やすさのためにキーの順序を並べ替えています)。

apiVersion: v1
kind: Secret
metadata:
  name: article-config-dk5g4h2289
type: Opaque
data:
  DATABASE_URL: |
    cjJkYmM6cG9zdGdyZXNxbDovL21hbmFnZWQucG9zdGdyZXNxbC5leGFtcGxlLmNvbTo1ND
    MyL2FydGljbGU/c29tZW9wdGlvbj1zb21ldmFsdWU=
  DATABASE_USERNAME: dXNlcm5hbWU=
  DATABASE_PASSWORD: cGFzc3dvcmQ=

config.envファイルで指定したキーと値のペアがdataフィールドに設定されています。Secretでは値は自動的にBase64でエンコードされるため、例えばdXNlcm5hbWU=は適切なツールでデコードするとusernameとなることが分かります。

例えば、以下のようにします。

$ echo -n 'dXNlcm5hbWU=' | base64 -d
username

また、マニフェストのnameフィールドがsecretGeneratorで指定したarticle-configではなく、-dk5g4h2289という接尾辞が付いています。kustomizeは、生成されたSecretを参照している箇所をほかのマニフェストから見つけて生成された名前に置き換えます。

この接尾辞はSecretを参照しているリソースでも変更を反映するために付与されています。例えばDeploymentがこのSecretを参照しているとき、Secretの内容が変更されるとSecretを参照する名前が変わることでDeploymentは新しいPodをデプロイし、変更されたSecretの内容がコンテナに反映されます。

article-configを例に解説しましたが、残りのaccesscount-configやrank-configも同様です。configMapGeneratorもほとんど同じです。

configMapGenerator:
- name: website-config
  envs:
  - config/website/config.env

website-configのみConfigMapを使っているのは、特に設定内容には機密情報を含まないためです。

config.envの設定例としては、以下のようになります。

ARTICLE_BASE_URL_FROM_SERVER=http://article:8080
ARTICLE_BASE_URL_FROM_CLIENT=http://website.example.com
RANK_BASE_URL_FROM_SERVER=http://rank:8080
RANK_BASE_URL_FROM_CLIENT=http://website.example.com

上記の例でhttp://website.example.comとしている箇所は、第3回と同じくhttp://<ノードのIPアドレス>に変更します。ARTICLE_BASE_URL_FROM_SERVERとRANK_BASE_URL_FROM_SERVERの値はそのままで構いません。

上記の設定から、次のようなConfigMapのマニフェストが生成されます(先ほどと同様にキーの順序を並べ替えています)。

apiVersion: v1
kind: ConfigMap
metadata:
  name: website-config-k9f57c5df5
data:
  ARTICLE_BASE_URL_FROM_SERVER: http://article:8080
  ARTICLE_BASE_URL_FROM_CLIENT: http://website.example.com
  RANK_BASE_URL_FROM_SERVER: http://rank:8080
  RANK_BASE_URL_FROM_CLIENT: http://website.example.com

Secretの場合と異なり、ConfigMapではdataの設定値にBase64エンコードなどは行われません。また、名前はsecretGeneratorのときと同様に接尾辞が付いています。

日立ソリューションズ・クリエイト
日立ソリューションズ・クリエイトに所属し、Webアプリケーション開発に従事したのち、 2019年1月からクリエーションライン株式会社と製造業向けにコンテナ/Kubernetesを活用したデータ分析基盤やIoTアプリケーション基盤の開発に従事。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています