Application Deliveryの紹介

jagaNikumanPosted by

SREの岩立です。
GoogleKubernetesEngineのアドオンとして提供されているApplication Deliveryという機能があります。
今回はこのApplication DeliveryのGettingStartedを通して紹介していきたいと思います。

Application Deliveryとは

 Application Deliveryは、Google Kubernetes Engineのアドオンとして提供されているCIOpsでアプリケーションを配信するためのツールです。もともとはAnthosの機能として開発されていた雰囲気があり、それによってマルチクラスタに対応しているツールになっています。

 Application Deliveryの特徴としては、マルチクラスタに対応していたり、最終的にK8sに適用したManifestの管理が行われるという点があります。
K8sでのCIOpsは、適用するManifestの差分を見ることは出来ても適用したManifestは保存されないことが多く、その点をApplication Deliveryは解消してくれます。適用されたManifestがあるとトラブルシューティングの際などに役立てることができるため、嬉しい機能です。

 Application Deliveryの動きについては次の章から触れていきますが、ざっくりとした構成としては、3つのGit RepositoryによってCIOpsが行われます。
 1つ目はアプリケーションのソースコードを管理しているRepositoryです。GoやらPHPで書かれた各自で用意するアプリケーションのRepositoryになります。
 2つ目はアプリケーションをK8sに展開するためのKubernetesのManifestを格納するRepositoryです。こちらはApplication Deliveryが生成してくれて、中の構造はKustomize形式で管理されます。
 3つ目はApplication DeliveryがK8sに適用するManifestを管理するRepositoryになります。このManifestは、2つ目のManifest RepositoryからKustomizeで生成されて、管理されます。そのため、この3つ目のRepositoryは開発者が直接手を加えることはほぼほぼありません。Application Deliveryが生成するPRのApprove, Mergeくらいになります。

引用: https://www.youtube.com/watch?v=r5_xYtbZPfc

 概要を長く書いていてもしょうがないので、実際に動かして挙動を見ていきます。

Getting Startedやってみる

 手順はドキュメントに乗っているので、これに沿ってやっていきます。

Application Deliveryを有効化したGKEクラスタの構築

まずGKEクラスタを以下のコマンドで用意します。–addonsオプションでApplicationManagerを指定することで、クラスタの作成と同時にApplication Mnagerを有効化することが出来ます

$ gcloud beta container clusters create test-cluster --cluster-version 1.15.12 --zone asia-northeast1-c --addons ApplicationManager

クラスタ作成後、以下のコマンドでApplication Deliveryが正常に導入されているかを確認します。

$ kubectl get pods kalm-controller-manager-0 -n kalm-system
NAME                        READY   STATUS    RESTARTS   AGE
kalm-controller-manager-0   3/3     Running   0          4m57s
$ kubectl get pods -n application-system
NAME                                              READY   STATUS    RESTARTS   AGE
application-controller-manager-7b75cff846-5nmrl   2/2     Running   0          12m
application-controller-manager-7b75cff846-dqsbh   2/2     Running   0          12m

appctlのインストール

次に、gcloudコマンドでappctlをインストールします。

$ gcloud components install appctl

Application Deliveryの設定

クラスタの構築とappctlのインストールが終わったら、いよいよアプリケーションをデプロイする工程に入っていきます。今回はアプリケーションの用意は割愛してnginxをデプロイします。そのため、登場するGit RepositoryはKustomizeを管理するRepositoryと、Application Deliveryが適用するManifestを管理するRepositoryの2つになります。
では、以下のコマンドでRepositoryを作成します。

$ appctl init app-manifest --app-config-repo=github.com/jagaNikuman/app-manifest
This will create a private repo "https://github.com/jagaNikuman/app-manifest". Do you want to continue? (Y/n): y
Private repo https://github.com/jagaNikuman/app-manifest is created.
Add remote "origin" to application git repo "git@github.com:jagaNikuman/app-manifest.git".
Do you want to use the kustomize format for config? If not, an empty `config` folder will be created.  (Y/n): y
"https://github.com/jagaNikuman/app-manifest-deployment" will be your deployment repo and the future release artifact will be uploaded to this repository.
This will create a private repo "https://github.com/jagaNikuman/app-manifest-deployment". Do you want to continue? (Y/n): y
Private repo https://github.com/jagaNikuman/app-manifest-deployment is created.
Add remote "upstream" to deployment git repo.
 Add .appctlconfig to .gitignore.
 Add .deployment/ to .gitignore.
Successfully initialized the GKE application delivery for repo "https://github.com/jagaNikuman/app-manifest".
Now you can `cd app-manifest/` and run `appctl env add <ENV> --cluster` to set up the release environment for your Kubernetes clusters.

実行後、app-manifestリポジトリとapp-manifest-deploymentリポジトリが作成されていることを確認します。app-manifestリポジトリがkustomize管理用で、app-manifest-deploymentが適用するManifestの管理用になります。

次に、デプロイする環境の設定を行います。今回はdevという環境名を用意することにします。そのため以下のコマンドで、dev環境を作成します。このときにGKEのクラスター名やGCPのプロジェクト名を指定していますが、ここを環境ごとに変えることでマルチクラスター構成に対して柔軟にデプロイを行えるようになります。

$ appctl env add dev --cluster test-cluster --project gpn-infra-sandbox --zone asia-northeast1-c
Successfully added new release environment "dev" and associated cluster "test-cluster" to it.
 To see appctl changes, run `git log -p *`.
 Now you can edit the kustomize overlay for dev under /home/jaganikuman/temp/app-manifest/config/envs/dev. See examples https://kubectl.docs.kubernetes.io/pages/examples/kustomize.html.
You can commit and tag the change when it's ready. Then run `appctl prepare dev` to prepare and review the configuration changes for env "dev"

git log -p *で確認すると、以下のファイルが追加されていることがわかります。
config/envs/dev/kustomization.yamlはdev環境でoverrayするためのkustomizeのファイルで、開発者が変更をしていくものです。
delivery/envs/dev.yamlはApplication Deliveryがデプロイ先を管理するためのファイルになります。そのため、このファイルはデプロイ先を変更したいなどの理由がない限りは触ることはありません。

$ git log -p *
commit 299903493454403d6ee359159573d35284a1cee4 (HEAD -> master)
Author: jagaNikuman <jaganikuman@gmail.com>
Date:   Wed Sep 23 05:10:42 2020 +0900

    appctl: added scaffolding structure for the new environment: dev.

diff --git a/config/envs/dev/kustomization.yaml b/config/envs/dev/kustomization.yaml
new file mode 100644
index 0000000..e0b9b4f
--- /dev/null
+++ b/config/envs/dev/kustomization.yaml
@@ -0,0 +1,4 @@
+# Please don't change the namespace field
+namespace: app-manifest-dev
+bases:
+   - ../../base
diff --git a/delivery/envs/dev.yaml b/delivery/envs/dev.yaml
new file mode 100644
index 0000000..0621fb7
--- /dev/null
+++ b/delivery/envs/dev.yaml
@@ -0,0 +1,6 @@
+cluster_name: test-cluster
+project: gpn-infra-sandbox
+compute:  # choose "region" or "zone"
+   zone: asia-northeast1-c
+namespace: app-manifest-dev
+no_pr_approval_required: false

NginxのKustomizeの作成

appctlで環境を作成できたら、nginxをデプロイするためのManifestを作成していきます。まず以下のManifestを config/base/nginx.yamlとして作成します。

# myapp/config/base/nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  type: LoadBalancer
  ports:
    - port: 80
  selector:
    app: nginx

今作成したManifestをbaseのkustomize.yamlにresourceとして記述します。

# myapp/config/base/kutsomization.yaml
resources:
  - nginx.yaml

dev環境のkustomizeは既にbaseを参照するようになっているため今回は手を加えません。また、dev環境でどのようなmanifestが作成されるかは、config/envs/devディレクトリ下で以下のコマンドを叩くことで確認できます。(appctlによって付与されるラベルなどは生成されないので、目安程度の確認になります)

$ kubectl kustomize .
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: app-manifest-dev
spec:
  ports:
  - port: 80
  selector:
    app: nginx
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: app-manifest-dev
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80

NginxをApplication Deliveryでデプロイする準備

kustomizeでmanifestが生成できることを確認したら、git commit, pushを行います。また、appctlはtagをもとにデプロイするので、tagを打っておきます。

$ git add -A
$ git commit -m "add: nginx"
$ git tag 0.0.1
$ git push origin HEAD
$ git push origin 0.0.1

以下のコマンドでdev環境へのデプロイの準備を行います。このコマンドが行うこととしては、K8sに適用するManifestの生成とPRの作成を行います。

$ appctl prepare dev --from-tag 0.0.1
Sync-up the latest Refs from remote "https://github.com/jagaNikuman/app-manifest".
Found commit "04d1a3a02bf8a00030d63a26051fe1e707187d78" from tag 0.0.1
Generating kustomize artifacts...
Stash deployment git repo...
Writing release artifact to deployment repo...
Add a new release tag for "dev": "0.0.1-dev-04d1a3a.0" (deployment repo).
Pushing the new git-commit to the deployment repo.
Created a "Pull Request": "https://github.com/jagaNikuman/app-manifest-deployment/pull/1"
Once the "Pull Request" is merged, you can run `appctl apply dev` to install or update the application in dev cluster.

appctl prepareを終えると、以下のようなPRが作成されます。このPRをMergeすることで、デプロイの準備が整います。

Nginxのデプロイと確認

以下のコマンドでdev環境へデプロイを実行します。

$ appctl apply dev

以下のコマンドで正常にデプロイされたか確認します。

$ k get po,svc -n app-manifest-dev
NAME                                        READY   STATUS      RESTARTS   AGE
pod/app-manifest-deployer-467804136-jkq78   0/1     Completed   0          59s
pod/nginx-7bffc778db-hn4kc                  1/1     Running     0          45s
pod/nginx-7bffc778db-m2q4g                  1/1     Running     0          45s
pod/nginx-7bffc778db-shqqx                  1/1     Running     0          45s

NAME            TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
service/nginx   LoadBalancer   10.87.247.250   35.221.108.2   80:31431/TCP   45s

ブラウザからも正常にnginxがデプロイされていることが確認できました。これでApplication Deliveryを用いてデプロイを行うことが出来ました🎉

まとめ

Application DeliveryはCIOpsで使えて、マルチクラスターへのデプロイに対応していて、かつ最終的に適用するManifestを残してくれる便利なツールです。
マルチクラスターであれば本領を発揮できてとても良いですが、シングルクラスター構成でもManifestを残してくれるという点で十分良いツールだと思います。

まだBetaなので本番採用するかどうかは悩みどころですが、今後のアップデートに注目したいと思います。