Skip to content

AssemblyLineの拡張

本章では、Qmonus Value StreamのOfficial CI/CD Adapterを用いて、デプロイのみのAssemblyLineを拡張し、デプロイの前にコンテナイメージをビルドするPipelineを追加する手順を解説します。

Getting StartedでのHTTP APIサーバの構築を前提としています。 事前に準備が必要なリソースは以下の通りです。

以降のステップでは、下記の作業を通じて、AssemblyLineを拡張できることを確認します。

  • Qmonus Value Stream CLI(以降, qvsctl)を用いて、Official CI/CD Adapterをダウンロードする
  • QVS Configに、拡張したい Official CI/CD Adapterを追加し、コンパイルする
  • AssemblyLineを編集し、QVS Configに追加した Official CI/CD Adapterから生成されたPipelineを追記する
  • AssemblyLineを実行し、コンテナイメージをビルド、および、そのイメージを使ってデプロイできていることを確認する

1. Deploymentの確認 (GUI)

Getting Startedで登録したDeploymentを使用します。 Applicationに登録してあるDeploymentがAKS用でなければGetting Startedの手順1、4を参考に再登録してください。

2. デプロイするアプリケーションの準備(CLI)

本チュートリアルではGetting Startedで作成した持ち込みのプライベートリポジトリと、getting-started ブランチをそのまま利用します。 今回は簡単なnginxサーバを作成し、指定したWEBページが出力されるようなアプリケーションをデプロイします。

まずWEBページへ出力するindex.htmlを用意します。

bash
# Dockerfileを格納するディレクトリへ移動する
cd applications-qvs-demo/.valuestream/
# index.htmlを作成し、編集する
vim index.html
html
<!DOCTYPE html>
<html>
  <head>
     <title>Hello, Qmonus Value Stream!!</title>
  </head>
  <body>
    <h1>Hello, Qmonus Value Stream!!</h1>
  </body>
</html>

次にnginxのconfファイルを用意します。

bash
# index.htmlを作成し、編集する
vim hello.conf
conf
server {
    listen 80;
    listen [::]:80;
    root /usr/share/nginx/html;
    try_files /index.html =404;
}

そして、nginxのベースイメージを利用したDockerfileを用意します。

bash
# Dockerfileを作成し、編集する
vim Dockerfile
Dockerfile
FROM nginx:latest
RUN rm /etc/nginx/conf.d/*
ADD hello.conf /etc/nginx/conf.d/
ADD index.html /usr/share/nginx/html/

3. QVS Configの編集 (CLI)

QVS Configを編集し、コンパイルするデザインパターンを指定しています。

bash
# vim でQVS Configを編集(エディタは使いなれたもので問題ありません)
vim qvs.yaml

QVS Config

  • build:buildkitAzure: Buildkitを用いたコンテナイメージビルドのパイプライン
yaml
params:
  - name: k8sNamespace
    type: string
  - name: imageName
    type: string

modules:
  - name: github.com/qmonus/sample
    local:
      path: . # relative path to qvs.yaml

designPatterns:
  - pattern: github.com/qmonus/sample/local
    params:
      k8sNamespace: $(params.k8sNamespace)
      imageName: $(params.imageName)
+ - pattern: qmonus.net/adapter/official/pipeline/build:buildkitAzure
  - pattern: qmonus.net/adapter/official/pipeline/deploy:simple
  - pattern: qmonus.net/adapter/official/pipeline/sample:resolveIPAddress
yaml
params:
  - name: k8sNamespace
    type: string
  - name: imageName
    type: string

modules:
  - name: github.com/qmonus/sample
    local:
      path: . # relative path to qvs.yaml

designPatterns:
  - pattern: github.com/qmonus/sample/local
    params:
      k8sNamespace: $(params.k8sNamespace)
      imageName: $(params.imageName)
  - pattern: qmonus.net/adapter/official/pipeline/build:buildkitAzure
  - pattern: qmonus.net/adapter/official/pipeline/deploy:simple
  - pattern: qmonus.net/adapter/official/pipeline/sample:resolveIPAddress

4. Pipeline Manifestの生成および登録 (CLI)

qvsctl pipeline compileコマンドを用いてPipeline Manifestを生成し、Qmonus Value Streamへ登録します。 projectName はQmonus Value StreamのProject Nameです。Project Nameは、qvsctl project list で取得したPROJECT NAMEを指定してください。

bash
# コンパイルする
qvsctl pipeline compile -m . -c qvs.yaml --prefix nginx-demo

# qvsctl auth コマンド使用して認証する(出力されたurlへアクセスしてください)
qvsctl auth

# Project Nameを取得する
qvsctl project list

# Pipeline Manifestを登録する
qvsctl pipeline apply -p ${projectName} -f output/manifests.yml

コンパイルを実行した際に2つのpipelinenginx-demo-build,nginx-demo-deploy,nginx-demo-resolve-ip-address-after-deployと5つのtasknginx-demo-git-checkout,nginx-demo-auth-google-registry,nginx-demo-buildkit,nginx-demo-compile-design-pattern,nginx-demo-deployment-worker,nginx-demo-resolve-ip-addressが生成されることを確認してください。

5. AssemblyLineを編集する (CLI)

プライベートGitリポジトリ内の、前チュートリアルまでで利用しているAssemblyLineを編集する。

bash
#assemblyline-staging.yamlを編集(エディタ普段使用しているもので問題ありません)
vim assemblyline-staging.yaml

assemblyline-staging.yaml

yaml
apiVersion: vs.axis-dev.io/v1
kind: AssemblyLine
metadata:
  name: staging-deploy
spec:
  params:
    - name: gitRevision
      type: string
-    - name: imageName
-      type: string
  stages:
+   - name: build
+     spec:
+       pipeline: nginx-demo-build
+       deployment:
+         app: nginx-demo
+         name: staging
+       params:
+         - name: gitRevision
+           value: $(inputs.gitRevision)
+         - name: cacheImageName
+           value: $(params.imageRegistryPath)/$(params.imageShortName)
    - name: deploy
      spec:
        pipeline: nginx-demo-deploy
        deployment:
          app: nginx-demo
          name: staging
        params:
          - name: gitRevision
            value: $(inputs.gitRevision)
          - name: imageName
-           value: $(inputs.imageName)
+           value: $(stages.build.results.imageFullNameTag)
+     runAfter:
+       - build
    - name: resolve-ip-address
      spec:
        pipeline: nginx-demo-resolve-ip-address-after-deploy
        deployment:
          app: nginx-demo
          name: staging
      runAfter:
        - deploy
  results:
     - name: ipAddress
       value: $(stages.resolve-ip-address.results.ipAddress)
+    - name: imageName
+      value: $(stages.build.results.imageFullNameTag)
+    - name: gitRevision
+      value: $(inputs.gitRevision)
yaml
apiVersion: vs.axis-dev.io/v1
kind: AssemblyLine
metadata:
  name: staging-deploy
spec:
  params:
    - name: gitRevision
      type: string
  stages:
    - name: build
      spec:
        pipeline: nginx-demo-build
        deployment:
          app: nginx-demo
          name: staging
        params:
          - name: gitRevision
            value: $(inputs.gitRevision)
          - name: cacheImageName
            value: $(params.imageRegistryPath)/$(params.imageShortName)
    - name: deploy
      spec:
        pipeline: nginx-demo-deploy
        deployment:
          app: nginx-demo
          name: staging
        params:
          - name: gitRevision
            value: $(inputs.gitRevision)
          - name: imageName
            value: $(stages.build.results.imageFullNameTag)
      runAfter:
        - build
    - name: resolve-ip-address
      spec:
        pipeline: nginx-demo-resolve-ip-address-after-deploy
        deployment:
          app: nginx-demo
          name: staging
      runAfter:
        - deploy
  results:
    - name: ipAddress
      value: $(stages.resolve-ip-address.results.ipAddress)
    - name: imageName
      value: $(stages.build.results.imageFullNameTag)
    - name: gitRevision
      value: $(inputs.gitRevision)

6. AssemblyLineの更新 (CLI)

手順5で編集したAssemblyLineを更新します。

bash
# Qmonus Value Streamから実行可能なDeploy stageを持つAssemblyLine
qvsctl pipeline apply -p ${projectName} -f assemblyline-staging.yaml

git add、 git commit、 git pushを行い、リモートリポジトリに変更を反映します。

bash
# リモートリポジトリにpushする
git add --all
git commit -m "Assemblyline Extension QVS Tutorial"
git push origin getting-started

7. サービスプリンシパルの登録 (GUI)

ACRへビルドしたコンテナイメージをpushするためのサービスプリンシパルをCredentialとして登録します。

  1. 左メニューより、Credentialを選択します。
  2. 画面右上の NEW CREDENTIAL ボタンを押下します。
  3. 各フォームに以下の値を入力し、画面右下の CREATE ボタンを押下します。
  • Name: staging-serviceprincipal
  • Secret Data:
    • Key=appId, Value=サービスプリンシパルのappId
    • Key=password, Value=サービスプリンシパルのpassword

ここで、サービスプリンシパルはazコマンドを使って以下のように生成できます。

bash
# 以下のコマンドを実行して返ってくるappIdおよびpasswordフィールドを控えておく
az ad sp create-for-rbac --name=${any_name} --skip-assignment --scopes="/subscriptions/${subscription_id}"

# 上記コマンド実行で返ってきたappIdを利用してACR操作の権限を付与
az role assignment create --role="AcrPush" --assignee="${appId}"

8. Deployment Configの編集 (GUI)

AssemblyLine詳細画面より、不足している下記のパラメータを入力します。

  • 事前に準備いただいているDockerイメージの格納先を設定します。
  1. 左メニューより、AssemblyLineを選択します。
  2. 画面中央に表示される staging-deploy を選択します。
  3. Pipeline Stagesに表示されている build カードを選択します。
  4. 画面右に表示される Edit Deployment Config ボタンをクリックします。
  5. YAMLモードのEditorが表示されますので、Dockerイメージの格納先をYAML形式で入力します。必要なパラメータ一覧は以下の通りです。
    • imageRegistryPath : イメージ名のないコンテナレジストリのパス (例:acrname.azurecr.io/qmonus)
    • imageShortName : イメージ名 (例:nginx-demo)
    • imageTag : イメージタグ (例:v0.0.1)
    • containerRegistry : コンテナレジストリのエンドポイント。利用しているGARのリージョンに合わせて変更してください。(例: acrname.azurecr.io)
    • pathToContext : Dockerfileの場所
    • k8sNamespace : デプロイ先のKubernetes namespace
    • azServicePrincipalSecretName : サービスプリンシパルをCredentialに登録したときの登録名

以下は入力例です。

yaml
+ imageRegistryPath: ${acr_name}.azurecr.io/qmonus
+ imageShortName: nginx-demo
+ imageTag: v0.0.1
+ containerRegistry: ${acr_name}.azurecr.io
+ pathToContext: .valuestream
+ azServicePrincipalSecretName: staging-serviceprincipal
k8sNamespace: <過去のチュートリアルの値を利用>
yaml
imageRegistryPath: ${acr_name}.azurecr.io/qmonus
imageShortName: nginx-demo
imageTag: v0.0.1
containerRegistry: ${acr_name}.azurecr.io
pathToContext: .valuestream
azServicePrincipalSecretName: staging-serviceprincipal
k8sNamespace: <過去のチュートリアルの値を利用>
  1. Saveボタンを押下し、build, deploy の両方のInput Parameterが全て緑で表示されていることを確認します。

9. AssemblyLineの実行 (GUI)

登録したAssemblyLineを実行し、Nginx demoアプリケーションをKubernetesにデプロイします。

  1. 左メニューより、AssemblyLineを選択します。
  2. 画面中央に表示される staging-deploy を選択します。
  3. Pipelines (Stages) に表示されている build,deploy カードを選択し、それぞれ全てのパラメータが埋まっていることを確認します。
  4. 以下のInput Parameterを入力し、 RUN ボタンを押下してCI/CDを開始します。
    • gitRevision: getting-started

10. AssemblyLineが正常に完了したかを確認する (GUI/CLI)

AssemblyLineの完了後、ビルドされたコンテナイメージが正常にコンテナレジストリへ格納されていることを確認します。 また、そのコンテナイメージを使って、正常にデプロイされているかを確認します。

  1. AssemblyLineがSucceededになっているかを確認します。
  2. ビルドされたコンテナイメージが正常にコンテナレジストリへ格納されていることを確認します
    1. AssemblyLine実行画面の AssemblyLine Results: imageNameを確認します。 (例: asia-northeast1-docker.pkg.dev/gcp-project/qmonus/nginx-demo:v0.0.1)
    2. Azureコンソールへアクセスし、コンテナ レジストリの画面へ移動します。
    3. AssemblyLine Results: imageNameの値と同じ場所にイメージが格納されていることを確認します。
  3. デプロイされたKubernetes Clusterを確認し、PodのimageがAssemblyLine Results: imageNameと同じのもになっているかを確認します
    bash
    # アプリケーションクラスタへ切り替える
    $ kubectl config use-contexts ${アプリケーションクラスタ名}
    
    # デプロイしたPodの確認
    $ kubectl -n ${k8sNamespace} get pods
      NAME         READY   STATUS    RESTARTS   AGE
      {pod_name}   1/1     Running   0          3d10h
    
    # Podのイメージ名を確認
    $ kubectl -n ${k8sNamespace} get pod ${pod_name} -o=jsonpath='{.spec.containers[0].image}'
      ${acr_name}.azurecr.io/qmonus/nginx-demo:v0.0.1
  4. ブラウザからデプロイされたアプリケーションへアクセスできるかを確認します。 AssemblyLine Resultsに表示されているIPアドレスへ自身のWEBブラウザからアクセスします。 http://${ipAddress}:8080 上記のアドレスへ自身のWEBブラウザからアクセスし、Hello, Qmonus Value Stream!!と出力されたWEBページが閲覧できることを確認します。

リソースの削除

チュートリアルで作成したリソースは、Getting Startedで作成したQVS ConfigのInfrastructure Adapterの定義をコメントアウトし、リモートリポジトリに変更を反映した後に、再度AssemblyLineを実行することで削除できます。詳しくは、デプロイしたリソースの削除を参照してください。

解説

Official CI/CD Adapterを用いた、Pipeline/Taskの生成

本チュートリアルではGetting StartedでダウンロードしたOfficial CI/CD Adapterを手順3のQVS Configの編集と手順4qvsctl pipeline compileコマンドでコンパイルを行うことで、Pipeline/Taskを生成できました。 以下に今回編集したQVS ConfigのYAML定義を示しています。 今回使用したqvsctl pipeline compileコマンドでは、アプリケーションのデリバリプロセスを定義する CI/CD AdapterをKubernetes Manifestの形で展開しており、6-7行目で定義しているOfficial CI/CD Adapterのコンパイルを行っています。

yaml
designPatterns:
  - pattern: github.com/qmonus/sample/local
    params:
      k8sNamespace: $(params.k8sNamespace)
      imageName:     $(params.imageName)
+ - pattern: qmonus.net/adapter/official/pipeline/build:buildkitAzure
  - pattern: qmonus.net/adapter/official/pipeline/deploy:simple
  - pattern: qmonus.net/adapter/official/pipeline/sample:resolveIPAddress

Stage間での値の受け渡し

以下に今回利用したAssemblyLineの定義のうち、Stages定義を抜粋したものを示しています。 このAssemblyLineはbuilddeploy,resolve-ip-addressの3つのStageを順番に動作させています。 25行目のrunAfter: 指定することで Stageの実行順を指定できます。 build StageでイメージのビルドとGARにpushしたときのイメージパスを実行結果として出力し、それをdeploy Stage でそのGARのイメージパスからイメージを取得してアプリケーションをデプロイしています。 deploy Stageからbuild Stageへの値の受け渡しについては22-23行目で $(stages.build.results.imageFullNameTag)と記載し、deploy Stageのresult値を取得しています。

yaml
  stages:
    - name: build
      spec:
        pipeline: nginx-demo-build
        deployment:
          app: nginx-demo
          name: staging
        params:
          - name: gitRevision
            value: $(inputs.gitRevision)
          - name: cacheImageName
            value: $(params.imageRegistryPath)/$(params.imageShortName)
    - name: deploy
      spec:
        pipeline: nginx-demo-deploy
        deployment:
          app: nginx-demo
          name: staging
        params:
          - name: gitRevision
            value: $(inputs.gitRevision)
          - name: imageName
            value: $(stages.build.results.imageFullNameTag)
      runAfter:
        - build
    - name: resolve-ip-address
      spec:
        pipeline: nginx-demo-resolve-ip-address-after-deploy
        deployment:
          app: nginx-demo
          name: staging
      runAfter:
        - deploy

AssemblyLine Resultsの設定

以下に今回利用したAssemblyLineの定義のうち、Results定義を抜粋したものを示しています。 AssemblyLineでAssemblyLine Resultsを設定することで、実行されたAssemblyLineからKey-Value形式で実行結果を出力でき、AssemblyLineのPromotion時に入力パラメータとして利用できるようになります。 実際のPromotion時の利用方法については、商用環境へのPromotionにて解説します。 今回はipAddressというパラメータをResolve IP Address Stageから、imageNameというパラメータをbuild Stageから、gitRevisionをInput Parameterから、それぞれ出力するように設定しています。

yaml
  results:
    - name: ipAddress
      value: $(stages.resolve-ip-address.results.ipAddress)
    - name: imageName
      value: $(stages.build.results.imageFullNameTag)
    - name: gitRevision
      value: $(inputs.gitRevision)