kustomizeやSecretを利用してJavaアプリケーションをデプロイする
Deploymentマニフェスト
ここからDeploymentマニフェストを見ていきますが、ほとんど同じ設定内容なので、Article サービスのマニフェストを例に見ていきます。
apiVersion: apps/v1 kind: Deployment metadata: labels: app: article name: article spec: replicas: 1 selector: matchLabels: app: article template: metadata: labels: app: article spec: containers: - name: article image: article:prod envFrom: - secretRef: name: article-config resources: requests: cpu: 200m memory: 512Mi limits: cpu: '1' memory: 2Gi ports: - name: web containerPort: 8080 protocol: TCP
articleコンテナで利用するコンテナイメージとして、article:prodというイメージ名が指定されています。このフィールドは、kustomizeを利用することでkustomization.yamlのimagesフィールドでの指定によって変更します。kustomization.yamlの以下の箇所です。
images: - name: article newName: registry.gitlab.com/creationline/kubernetes-thinkit-sample1/article
nameフィールドでarticleが指定されており、newNameフィールドに新しいコンテナイメージ名が指定されています。これはコンテナイメージ名としてarticleが指定されている箇所をnewNameで指定されたコンテナイメージ名に置き換えるという設定です。なお、タグ部分(prod)は同じくnewTagフィールドを設定して変更することもできますが、今回はそのままにしています。
articleコンテナのenvFromフィールドでは、SecretやConfigMapから環境変数を読み込みます。このマニフェストの指定ではarticle-configという名前のSecretを読み込んでコンテナの環境変数に設定することを示しています。
envFrom: - secretRef: name: article-config
ただし、この参照は前のセクションで見たように、kustomizeによってsecretGeneratorが生成したSecretの名前に置き換えられます。全体で見るとconfig/article/config.envファイルで設定される環境変数がそのままアプリケーションの環境変数に追加された動作となります。
また、WebSiteサービスのマニフェストでは、対応する箇所が以下のようにconfigMapRefフィールドによりConfigMapを参照しています。ここではリソースの種類(kind)が異なるだけで、ほぼ同じ利用法となります。
envFrom: - configMapRef: name: website-config
ArticleサービスのDeploymentのマニフェストに戻ります。envFromフィールドの後にはresourcesフィールドがあります。
resources: requests: cpu: 200m memory: 512Mi limits: cpu: '1' memory: 2Gi
これは、コンテナに割り当てるマシンリソースの要求(requires)量と制限(limits)量を設定しています。
requiresフィールドに設定されたリソース量は、Podの起動時に、稼働するために必要なリソースとして考慮されます。KubernetesはPodを起動するNodeにそれだけの空き容量があることを確かめてPodを稼働します。そのため、確実に確保したい容量を設定します。
limitsフィールドに設定されたリソース量は、Podの起動時に、その制限量を超えてリソースを消費しないように設定されます。Kubernetesはコンテナランタイムを通じて設定するため、どのようにリソース制限が強制されるかはコンテナランタイムの実装に依存します。一般的にはアプリケーションが余裕を持って稼働できるリソース量を設定します。
CPUリソースの設定は、割り当てるCPU時間を設定します。値1はCPUの1コアを専有する割り当てに相当し、0.1や100mといった指定は1コアの十分の一の割り当てを意味します。メモリーは使用するバイト数で指定しますが、通常はMiやGといった単位を付けて表記することが多いです。
CPUやメモリー以外のリソースの設定に関するそれぞれの詳細は、公式ドキュメントのコンテナのリソース管理に記載があります。
Deployment マニフェストの最後にportsフィールドの設定があります。
ports: - name: web containerPort: 8080 protocol: TCP
後でServiceリソースからDeploymentへのルーティングを設定しますが、その際にポート番号を直接指定するのではなく、ここで指定したnameフィールドの値を使うことで、コンテナが使うポート番号を変更する際には、このマニフェストの修正だけで済みます。
なお、この記述をしなくても同じクラスタ内からはコンテナの任意のポートにアクセスできます。アクセス制限をしたり許可したりする目的のものではありません。
Service マニフェスト
Serviceのマニフェストファイルservice-article.yamlに移りましょう。
apiVersion: v1 kind: Service metadata: labels: app: article name: article spec: type: ClusterIP selector: app: article ports: - name: web port: 8080 targetPort: web
第3回と名前やラベル以外はそれほど変わりませんが、portsフィールドでnameとtargetPortを指定しています。targetPortフィールドはDeploymentマニフェストでPodテンプレートに設定したポートの名前(nameフィールドの値)を設定して関連付けを明示しています。
nameフィールドは役割を分かりやすくする意味で設定していますが、この後にIngressマニフェストからの参照でも使用します。
Ingressマニフェスト
Ingressのマニフェストファイルingress-article.yamlは、以下のようになっています。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: article annotations: kubernetes.io/ingress.class: traefik spec: rules: - http: paths: - backend: service: name: article port: name: web path: /api/articles pathType: Prefix
backendのポートの指定をポート番号ではなく名前で指定しています。これはすぐ上のServiceマニフェストの中で設定されたnameフィールドの値を参照しています。また、pathフィールドは/api/articlesとなっています。pathを詳しく指定しているのは、他のサービスとの兼ね合いです。
今回のアプリケーションでは4つのサービスがあり、すべてIngressを用いて外部公開しています。AccessCountサービスは内部サービスであり、外部に公開する必要はありませんが、挙動を確認しやすいよう外部に公開しています。
本連載では、使用するKubernetesクラスタへのアクセスをIPアドレスで行うことを想定しているため、Ingressで名前(ホスト名)ベースのルーティングはできません。そこで、パスベースのルーティングを行っています。pathフィールドの値を他のサービスのIngressと並べてみると、以下の通りです。
- Article
path: /api/articles pathType: Prefix
- AccessCount
path: /api/accesscounts pathType: Prefix
- Rank
path: /api/ranks pathType: Prefix
- WebSite
path: / pathType: Prefix
最初のArticle、AccesCount、Rankサービスはそれぞれ異なるパスを指定しているので、クラスタへ到達したリクエストは、パスが前方一致するIngressにより、それぞれのサービスにルーティングされます。WebSiteサービスはどうでしょうか。前方一致だけであれば、スラッシュ(/)だけなので、すべてのリクエストに一致してしまいそうです。しかし、複数のパスに一致した場合は最も長くパスが一致したものが優先される仕様のため、WebSiteサービスは他のIngressのパスに一致しなかったリクエストがルーティングされます。
サンプルアプリケーションのデプロイ
ここまで、プロダクション環境用のマニフェストを見てきましたが、外部のデータベースを準備する必要があるため、開発用データベースのマニフェストを含んだ開発環境用のマニフェストをデプロイします。
前提条件として、前回デプロイしたtraefikが手順通りデプロイされていることを想定しています。マニフェストは、サンプルアプリケーションのリポジトリのdeployment/develop/kubernetes/ディレクトリに配置されています。アプリケーションの構成は変わりませんが、開発用データベースもマニフェストに含んでいます。
WebSiteサービスの設定ファイルが、マニフェストのルートdeployment/develop/kubernetes/からの相対パスでconfig/website/config.env.sampleにあります。このファイルを同じディレクトリのconfig.envに名前を変えてコピーします。内容は以下のようになっているので、
ARTICLE_BASE_URL_FROM_SERVER=http://article:8080 ARTICLE_BASE_URL_FROM_CLIENT= RANK_BASE_URL_FROM_SERVER=http://rank:8080 RANK_BASE_URL_FROM_CLIENT=ARTICLE_BASE_URL_FROM_CLIENTとRANK_BASE_URL_FROM_CLIENTの値を設定します。設定する値はhttp://<ノードのIPアドレス>です。設定した後のconfig.envファイルの例は以下の通りです。
ARTICLE_BASE_URL_FROM_SERVER=http://article:8080 ARTICLE_BASE_URL_FROM_CLIENT=http://203.0.113.10 RANK_BASE_URL_FROM_SERVER=http://rank:8080 RANK_BASE_URL_FROM_CLIENT=http://203.0.113.10
kubectlコマンドが目的のkubernetesクラスタを操作するよう設定されていることを確認して、リポジトリのルートディレクトリに移動し、以下のコマンドを実行します。
kubectl apply -k deployment/develop/kubernetes/
少し待ってkubectlコマンドでPodの動作状況を確認すると、以下のようになると思います。
$ kubectl get po NAME READY STATUS RESTARTS AGE accesscount-68df6bd68c-jmt8t 1/1 Running 0 2m27s accesscountdb-0 1/1 Running 0 2m19s article-569d459544-wclwc 1/1 Running 0 2m27s articledb-0 1/1 Running 0 2m7s rank-99fcd8774-65l2p 1/1 Running 0 2m27s rankdb-0 1/1 Running 0 2m15s website-55f54876dc-6dbbp 1/1 Running 0 2m25s
この状態で、ブラウザにクラスターからアクセスすると、以下のように、まだ記事もランキングもデータがないため表示されません。
リポジトリには、サンプルデータをAPIで投入するスクリプトがあるので、それを使ってデータを作成します。
ARTICLE_URL="http://<ノードのIPアドレス>" ./scripts/post-sample-article.bash ARTICLE_URL="http://<ノードのIPアドレス>" ACCESSCOUNT_URL="http://<ノードのIPアドレス>" ./scripts/dummy-access-at.bash "<前日日付>" RANK_URL="http://<ノードのIPアドレス>" ./scripts/update-daily-rank.bash "<前日日付>"
<前日日付>は操作を行う前日の日付をYYYY-MM-DDの形式で指定します。例えば、作業日が2021年5月21日なら前日は2021年5月20日なので2021-05-20と指定します。ブラウザを更新すると、以下のように記事の一覧やランキングが表示されます。
おわりに
今回は、Javaアプリケーションをデプロイしてみました。kustomizeやSecretなど、今まで取り上げていなかったツールやリソースが出てきて少し複雑だったかもしれません。コマンドで指定したディレクトリにあるマニフェストが、ほぼそのままデプロイされたことが確認できたのではないでしょうか。今回の内容を通じて、各マニフェストの新しい内容について理解していただければと思います。
今回は、特にアプリケーションをデプロイすることに注力し、使っていない機能などについては割愛しました。今後の連載では、kustomizeやSecret、ConfigMapといったツール・リソースも取り上げていく予定ですので、お楽しみに!
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- kustomizeで復数環境のマニフェストファイルを簡単整理
- KubernetesのConfig&Storageリソース(その1)
- HelmfileでKubernetesマニフェストやKustomization、Helm Chartなどで構成されるアプリケーションを効率的に管理する
- StatefulSetとPersistentVolumeを使ってステートフルアプリケーションを動かす
- Kubernetesアプリケーションのトレーシング
- Kubernetesアプリケーションの快適リリースとGitOps
- Kubernetesアプリケーションのモニタリングことはじめ
- Oracle Cloud Hangout Cafe Season7 #1「Kubnernetes 超入門」(2023年6月7日開催)
- NGINX Ingress Controllerの柔軟なアプリケーション制御、具体的なユースケースと設定方法を理解する
- Rancherのカスタムカタログの作成