Appearance
Infrastructure Adapter を作成し、アプリケーションをデプロイする
本チュートリアルでは、Qmonus Value Streamにおいて、持ち込みのKubernetesのManifestからInfrastructure Adapterを生成し、ビルドしたアプリケーションをデプロイする手順を解説します。
Infrastructure Adapterについて
Infrastructure Adapterとは、システムのインフラストラクチャを構成するクラウドリソース(e.g. kubernetesや各種クラウドプロバイダのリソースなど)をパラメータによりカスタマイズ可能な形に抽象化したリソースです。 Official Infrastructure Adapterの一覧については、Official Cloud Native Adapter 公式リポジトリから確認できます。
実施する前に、アプリケーションのコンテナイメージを作成するのチュートリアルが完了していることをご確認ください。
以下のステップを通して、Infrastructure Adapterを生成し、アプリケーションをデプロイします。
- Qmonus Value Stream CLIの
qvsctl adapter importコマンドを使用してサンプルのManifestからInfrastructure Adapterを生成し、パラメータ化を行います。 - AssemblyLineを実行し、Infrastructure Adapterで定義したリソースとコンテナイメージ(アプリケーションのコンテナイメージを作成するでコンテナレジストリにPushしたイメージ)がデプロイされていることを確認します。
本章で使用するサンプルManifestでデプロイされるアプリケーションは、以下の図に示すように、Kubernetes DeploymentリソースとServiceリソース、Ingressリソースで構成されるHTTP APIサーバです。概要・前提条件の前提条件に記載していたGKEクラスタへデプロイします。
(Horizontal Pod Autoscalerは次章のInfrastructure Adapter をカスタマイズし、機能を追加するで追加します。)

1. サンプルManifestの準備(CLI)
本チュートリアルでは、持ち込みのKubernetesのManifestからInfrastructure Adapterを生成してQmonus Value Streamを実行することを想定し、サンプルのManifestを使用して手順を解説します。
アプリケーションのコンテナイメージを作成するで使用したプライベートリポジトリを使用します。 まず、作業用ブランチを作成します。
bash
# ローカルリポジトリへ移動
cd <repository name>
# 本チュートリアル用のブランチをmainブランチから作成
git switch -c deploy-own-application main
# 作業ディレクトリへ移動
cd .valuestream準備として、サンプルのKubernetes Manifestを作成します。
Kubernetes Ingress、Service、Deploymentのリソース群を定義します。
REPLACE_NSおよびREPLACE_IMAGEは、後ほどInfrastructure Adapterのパラメータ化にて置換するため、このままで進めてください。
bash
# サンプルのKubernetes Manifestを作成する
vim sample-manifests.yamlyaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-demo
namespace: REPLACE_NS
spec:
replicas: 1
selector:
matchLabels:
app: flask-demo
template:
metadata:
labels:
app: flask-demo
spec:
containers:
- name: flask-demo
image: REPLACE_IMAGE
ports:
- containerPort: 5000
resources:
requests:
cpu: 5m
memory: 32Mi
limits:
cpu: 100m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: flask-demo
namespace: REPLACE_NS
spec:
type: ClusterIP
ports:
- name: http
port: 80
protocol: TCP
targetPort: 5000
selector:
app: flask-demo
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: flask-demo
namespace: REPLACE_NS
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: flask-demo
port:
name: http2. CUEモジュールファイルの作成
自作したAdapterをQmonus Value Streamで利用するためには、CUE のパッケージ機能を使用します。 以下のコマンドを実行し、cue mod initコマンドでモジュールを定義することにより、モジュールルートとなるcue.mod/module.cueファイルが生成され、自作のAdapterを作成する準備が整います。
CUEのモジュールファイルの詳細についてはCloud Native Adapterのパッケージ仕様を参照してください。
bash
# CUEのモジュールを定義
cue mod init github.com/qmonus/sample
# catコマンドを実行し、モジュールのパスが出力されることを確認
cat cue.mod/module.cue
module: "github.com/qmonus/sample"3. Infrastructure Adapterの生成(CLI)
qvsctl adapter import コマンドを使用して、サンプルのKubernetes ManifestからInfrastructure Adapterを生成し、ローカルリポジトリへ出力します。
bash
# Kubernetes ManifestからInfrastructure Adapterを生成
qvsctl adapter import -f sample-manifests.yaml -o local/flask-app.cueこの時点でのフォルダ構成は以下のようになります。
<repository name>/
├── .valuestream/
│ ├── cue.mod/
│ │ └── module.cue
│ ├── local/
│ │ └── flask-app.cue
│ ├── output/
│ │ └── pipeline.yaml
│ ├── assemblyline-dev.yaml
│ ├── qvs.yaml
│ └── sample-manifests.yaml
├── app.py
├── Dockerfile
└── requirements.txt4. Infrastructure Adapterのパラメータ化(CLI)
出力されたInfrastructure Adapterに対し、生成元のManifestへ割り当てていたパラメータを継承します。 変更箇所はDIFF、正式なコードはCODEブロックを確認ください。
packageにはアプリケーションに対するKubernetesリソースとしてflaskappというpackage名を入力しています。- Deployment、Service、Ingressに使用される
k8sNamespaceとDeploymentで使用されるimageNameは、QVS ConfigやAssemblyLineから値を指定できるようにするため、Infrastructure Adapterのparametersとして定義しています。 _constとして、name(アプリケーションの名前)、port(Serviceのポート番号)、targetPort(アプリケーションのコンテナがリッスンするポート番号)として定義し、DeploymentとServiceの両方で参照するように変更しています。- 自作で作成するアプリケーションのポート番号が5000番と異なる場合は、
targetPortの番号を変更してください。
- 自作で作成するアプリケーションのポート番号が5000番と異なる場合は、
bash
# Infrastructure Adapterをパラメータ化する
vim local/flask-app.cuego
package REPLACE_ME
package flaskapp
DesignPattern: {
name: "REPLACE_ME"
description: "REPLACE_ME"
name: "flaskapp"
description: "Flask application deployment with Infrastructure Adapter."
parameters: {
k8sNamespace: string
imageName: string
}
_const: {
#name : "flask-demo"
#port : 80
#targetPort: 5000
}
resources: {
app: {
resource0: {
apiVersion: "apps/v1"
kind: "Deployment"
metadata: {
name: "flask-demo"
namespace: "REPLACE_NS"
name: _const.#name
namespace: parameters.k8sNamespace
}
spec: {
replicas: 1
selector: {
matchLabels: {
app: "flask-demo"
app: _const.#name
}
}
template: {
metadata: {
labels: {
app: "flask-demo"
app: _const.#name
}
}
spec: {
containers: [{
name: "flask-demo"
image: "REPLACE_IMAGE"
name: _const.#name
image: parameters.imageName
ports: [{
containerPort: 5000
containerPort: _const.#targetPort
}]
resources: {
requests: {
cpu: "5m"
memory: "32Mi"
}
limits: {
cpu: "100m"
memory: "128Mi"
}
}
}]
}
}
}
}
resource1: {
apiVersion: "v1"
kind: "Service"
metadata: {
name: "flask-demo"
namespace: "REPLACE_NS"
name: _const.#name
namespace: parameters.k8sNamespace
}
spec: {
type: "ClusterIP"
ports: [{
name: "http"
port: 80
protocol: "TCP"
targetPort: 5000
targetPort: _const.#targetPort
}]
selector: {
app: "flask-demo"
app: _const.#name
}
}
}
resource2: {
apiVersion: "networking.k8s.io/v1"
kind: "Ingress"
metadata: {
name: "flask-demo"
namespace: "REPLACE_NS"
name: _const.#name
namespace: parameters.k8sNamespace
}
spec: {
rules: [{
http: {
paths: [{
path: "/"
pathType: "Prefix"
backend: {
service: {
name: "flask-demo"
name: _const.#name
port: {
name: "http"
}
}
}
}]
}
}]
}
}
}
}
}go
package flaskapp
DesignPattern: {
name: "flaskapp"
description: "Flask application deployment with Infrastructure Adapter."
parameters: {
k8sNamespace: string
imageName: string
}
_const: {
#name : "flask-demo"
#port : 80
#targetPort: 5000
}
resources: {
app: {
resource0: {
apiVersion: "apps/v1"
kind: "Deployment"
metadata: {
name: _const.#name
namespace: parameters.k8sNamespace
}
spec: {
replicas: 1
selector: {
matchLabels: {
app: _const.#name
}
}
template: {
metadata: {
labels: {
app: _const.#name
}
}
spec: {
containers: [{
name: _const.#name
image: parameters.imageName
ports: [{
containerPort: _const.#targetPort
}]
resources: {
requests: {
cpu: "5m"
memory: "32Mi"
}
limits: {
cpu: "100m"
memory: "128Mi"
}
}
}]
}
}
}
}
resource1: {
apiVersion: "v1"
kind: "Service"
metadata: {
name: _const.#name
namespace: parameters.k8sNamespace
}
spec: {
type: "ClusterIP"
ports: [{
name: "http"
port: 80
protocol: "TCP"
targetPort: _const.#targetPort
}]
selector: {
app: _const.#name
}
}
}
resource2: {
apiVersion: "networking.k8s.io/v1"
kind: "Ingress"
metadata: {
name: _const.#name
namespace: parameters.k8sNamespace
}
spec: {
rules: [{
http: {
paths: [{
path: "/"
pathType: "Prefix"
backend: {
service: {
name: _const.#name
port: {
name: "http"
}
}
}
}]
}
}]
}
}
}
}
}5. QVS Configの修正(CLI)
アプリケーションのコンテナイメージを作成するで使用したQVS Configを修正します。
ここでは、手順4で作成したInfrastructure Adapterflaskappをコンパイルするように指定しています。
またアプリケーションをデプロイするPipelineとして、以下のOfficial CI/CD Adapterを利用します。
deploy:simple: Infrastructure Adapterで定義されたKubernetesリソースをデプロイするパイプライン
bash
vim qvs.yamlyaml
params:
- name: k8sNamespace
type: string
- name: imageName
type: string
modules:
- name: github.com/qmonus/sample # 2.CUEモジュールファイルの作成で定義したモジュール名
local:
path: . # QVS Configがあるディレクトリから、CUEモジュールのルートディレクトリまでの相対パス
- name: qmonus.net/adapter/official
designPatterns:
# Infrastructure Adapter
- pattern: github.com/qmonus/sample/local:flaskapp # 4.Infrastructure Adapterのパラメータ化で作成したpackage名を指定
params:
k8sNamespace: $(params.k8sNamespace)
imageName: $(params.imageName)
# CI/CD Adapter
- pattern: qmonus.net/adapter/official/pipeline/build:buildkitGcp
- pattern: qmonus.net/adapter/official/pipeline/deploy:simpleyaml
params:
- name: k8sNamespace
type: string
- name: imageName
type: string
modules:
- name: github.com/qmonus/sample # 2.CUEモジュールファイルの作成で定義したモジュール名
local:
path: . # QVS Configがあるディレクトリから、CUEモジュールのルートディレクトリまでの相対パス
- name: qmonus.net/adapter/official
designPatterns:
# Infrastructure Adapter
- pattern: github.com/qmonus/sample/local:flaskapp # 4.Infrastructure Adapterのパラメータ化で作成したpackage名を指定
params:
k8sNamespace: $(params.k8sNamespace)
imageName: $(params.imageName)
# CI/CD Adapter
- pattern: qmonus.net/adapter/official/pipeline/build:buildkitGcp
- pattern: qmonus.net/adapter/official/pipeline/deploy:simple6. Infrastructure Adapterの動作確認(CLI)
本手順では、qvsctl manifest compileコマンドとparams.jsonのパラメータファイルを用いて、Infrastructure Adapterが正しく動作するかどうかを確認します。
qvsctl manifest compileとparams.jsonについて
qvsctl manifest compile コマンドは、Infrastructure Adapterをローカル環境でコンパイルし、生成されるKubernetes Manifestを事前に確認するためのコマンドです。 params.jsonはローカルでの動作確認時に、パラメータを明示的に指定するために用意します。 これにより、デプロイ前にInfrastructure Adapterの構成やパラメータ展開が正しく動作するかを検証できます。
bash
# params.jsonを作成する(実際にはQmonus Value Streamの中で自動的に作成される)
vim params.jsonjson
{
"params": [
{
"name": "k8sNamespace",
"value": "flask-demo"
},
{
"name": "imageName",
"value": "dummyimage"
}
]
}Infrastructure Adapterが正しくコンパイルできるかどうかを確認します。
bash
# qvsctlでKubernetes Manifestにコンパイル
qvsctl manifest compile -m . -c qvs.yaml -p params.json -o output/manifest.yaml
less output/manifest.yamlこの時点でのフォルダ構成は以下のようになります。
<repository name>/
├── .valuestream/
│ ├── cue.mod/
│ │ └── module.cue
│ ├── local/
│ │ └── flask-app.cue
│ ├── output/
│ │ ├── manifest.yaml
│ │ └── pipeline.yaml
│ ├── assemblyline-dev.yaml
│ ├── params.json
│ ├── qvs.yaml
│ └── sample-manifests.yaml
├── app.py
├── Dockerfile
└── requirements.txt7. Pipeline Manifestの生成および登録 (CLI)
アプリケーションのコンテナイメージを作成すると同様に、qvsctl pipeline compileコマンドを用いてPipeline Manifestを生成し、Qmonus Value Streamへ登録します。
bash
# コンパイルする
qvsctl pipeline compile -c qvs.yaml --prefix flask-demo -o output/pipeline.yaml
# qvsctl auth コマンド使用して認証する(出力されたurlへアクセスしてください)
qvsctl auth
# Project Nameを取得する
qvsctl project list
# 取得したProject Nameを環境変数に設定する
export projectName=<PROJECT NAME>
# Pipeline Manifestを登録する
qvsctl pipeline apply -p ${projectName} -f output/pipeline.yaml新たに1つのpipelineflask-demo-deployと2つのtaskflask-demo-compile-design-pattern、flask-demo-deployment-workerが生成されることを確認してください。
8. AssemblyLineの修正(CLI)
AssemblyLineに、deployのStageを定義し、作成したPipelineおよびDeploymentを指定します。 デプロイ対象であるimageNameはresultsとして定義していた$(stages.build.results.imageFullNameTag)を指定します。 また、artifactsを定義し、デプロイするリソースのKubernetes ManifestをAssemblyLine実行後にダウンロードできるようにします。
bash
# assemblyline-dev.yamlを編集する
vim assemblyline-dev.yamlyaml
apiVersion: vs.axis-dev.io/v1
kind: AssemblyLine
metadata:
name: flask-demo-dev
spec:
params:
- name: gitRevision
type: string
stages:
- name: build
spec:
pipeline: flask-demo-build
deployment:
app: flask-demo
name: flask-demo-dev
params:
- name: gitRevision
value: $(inputs.gitRevision)
- name: deploy
spec:
pipeline: flask-demo-deploy
deployment:
app: flask-demo
name: flask-demo-dev
params:
- name: gitRevision
value: $(inputs.gitRevision)
- name: imageName
value: $(stages.build.results.imageFullNameTag)
runAfter:
- build
results:
- name: gitRevision
value: $(inputs.gitRevision)
- name: imageName
value: $(stages.build.results.imageFullNameTag)
artifacts:
- path: manifestsyaml
apiVersion: vs.axis-dev.io/v1
kind: AssemblyLine
metadata:
name: flask-demo-dev
spec:
params:
- name: gitRevision
type: string
stages:
- name: build
spec:
pipeline: flask-demo-build
deployment:
app: flask-demo
name: flask-demo-dev
params:
- name: gitRevision
value: $(inputs.gitRevision)
- name: deploy
spec:
pipeline: flask-demo-deploy
deployment:
app: flask-demo
name: flask-demo-dev
params:
- name: gitRevision
value: $(inputs.gitRevision)
- name: imageName
value: $(stages.build.results.imageFullNameTag)
runAfter:
- build
results:
- name: gitRevision
value: $(inputs.gitRevision)
- name: imageName
value: $(stages.build.results.imageFullNameTag)
artifacts:
- path: manifestsartifactsについて
spec.artifactsフィールドを定義すると、AssemblyLine実行中にコンパイル・生成されたファイルを、AssemblyLineの実行結果からダウンロードできるようになります。 manifestsを指定した場合は、Infrastructure AdapterからコンパイルされたKubernetes Manifestをダウンロードできるようになります。 そのほかにも.の全ファイル指定や、特定のフォルダ・ファイルの指定が可能です。仕様については、What is AssemblyLineを確認ください。 
9. AssemblyLineの登録 (CLI)
修正したAssemblyLineを Qmonus Value Stream のProjectへ登録します。
bash
# AssemblyLineをApplyして更新する
qvsctl pipeline apply -p ${projectName} -f assemblyline-dev.yamlgit add、 git commit、 git pushを行い、リモートリポジトリに変更を反映します。 またコミットIDをAssemblyLineを実行するときに指定するため控えておきます。
bash
# リモートリポジトリにpushする
git add --all
git commit -m "Deploy Own Application QVS Tutorial"
git push origin deploy-own-application
# コミットIDを控える
git log -110. Environmentの準備
アプリケーションのコンテナイメージを作成するにて作成したQmonus Value StreamのEnvironmentのProvisioning TargetにKubernetesを追加します。
- 左メニューより、Environmentを選択します。
flask-demo-devを選択します。- 画面右上の
Editボタンをクリックします。 - Provisioning Targetセクションで、
+ボタンをクリックします。 - 各フォームに以下の値を入力します。
- Kind:
kubernetes - Display Name:
k8s-cluster-dev - Alias: (空白)
- Kind:
以下は入力例です。

- 画面右下の
Saveボタンを押下してEnvironmentを更新します。
11. Deploymentの準備
アプリケーションのコンテナイメージを作成するにて作成したQmonus Value StreamのDeploymentに、デプロイ先のKubernetesクラスタ情報を設定します。
- 左メニューより、Applicationを選択します。
flask-demoを選択します。- 表示されるDeploymentsから、
flask-demo-devを選択します。 - 画面右上の
Editボタンをクリックします。 - Credentialsセクションで、以下の認証情報を追加します。
- Kubernetes
- namespace:
flask-demo- デプロイ先のKubernetesのNamespace
- kubeconfig: Kubernetesクラスタへのアクセス権限を持つKubeconfig(YAML形式)
- Kubeconfigの取得方法は、Kubeconfig の作成(CLI)を参照してください。
- namespace:
- Kubernetes
Kubernetesのnamespaceについて
デプロイ先のKubernetesクラスタに、指定したnamespaceが存在しない場合は、事前に作成してください。
bash
gcloud container clusters get-credentials <クラスタ名> --zone <ノードゾーン名> --project <GCPプロジェクトID>
kubectl create namespace flask-demo以下は入力例です。

- 画面右下の
Validate kubeconfigボタンを押下してValidateが成功することを確認します。Successfully validated your kubeconfigと表示されれば成功です。
- 画面右下の
Saveボタンを押下してDeploymentを更新します。
12. Deployment Configの設定 (GUI)
Qmonus Value StreamのAssemblyLineより、不足している下記のパラメータを入力します。
- 左メニューより、AssemblyLineを選択します。
- 画面中央に表示される
flask-demo-devを選択します。 - Pipeline Stagesに表示されている
deployカードを選択します。 - 画面右に表示される
Edit Deployment Configボタンをクリックします。 - YAMLモードのEditorが表示されますので、デプロイ先のnamespaceをYAML形式で入力します。必要なパラメータ一覧は以下の通りです。
- k8sNamespace :
デプロイ先のKubernetesのNamespace(例:flask-demo)
- k8sNamespace :
以下は入力例です。
yaml
k8sNamespace: flask-demo
imageRegistryPath: asia-northeast1-docker.pkg.dev/gcp-project/qmonus
imageShortName: flask-demo
imageTag: v0.0.1
pathToContext: .Saveボタンを押下し、deployのInput Parameterが全て緑で表示されていることを確認します。
13. AssemblyLineの実行 (GUI)
登録したAssemblyLineを実行し、flask-demoアプリケーションをKubernetesにデプロイします。
- 左メニューより、AssemblyLineを選択します。
- 画面中央に表示される
flask-demo-devを選択します。 - Pipelines(Stages)に表示されている
build,deployカードを選択し、それぞれ全てのパラメータが埋まっていることを確認します。 - 以下のInput Parameterを入力し、
RUNボタンを押下してCI/CDを開始します。- gitRevision:
コミットID- この
コミットIDは、手順9で控えたコミットIDを指定してください。
- この
- gitRevision:
14. デプロイされたアプリケーションの確認(CLI)
Kubernetesにアクセスして、デプロイに成功したリソースとアプリケーションを確認します。 デプロイ完了後、Ingressが機能するまでに時間がかかりますので、5分ほどお待ちして確認ください。
bash
# GKEクラスタへ接続する
gcloud container clusters get-credentials <クラスタ名> --zone <ノードゾーン名> --project <GCPプロジェクトID>
# デプロイしたDeploymentを確認する
kubectl get deployment -n flask-demo
NAME READY UP-TO-DATE AVAILABLE AGE
flask-demo 1/1 1 1 XX
# デプロイしたServiceを確認する
kubectl get service -n flask-demo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
flask-demo ClusterIP XX.XX.XX.XX <none> 80/TCP XX
# デプロイしたIngressを確認する(機能するまでに時間がかかるので、5分程待って実行)
kubectl get ingress -n flask-demo
NAME CLASS HOSTS ADDRESS PORTS AGE
flask-demo <none> * ${external_ip} 80 XX
# 上記IngressにアサインされたEXTERNAL-IPにアクセス
# Hello from Qmonus Value Streamが表示されることを確認
curl http://${external_ip}; echo
Hello from Qmonus Value Stream解説
本チュートリアルでは、Qmonus Value Stream CLIのqvsctl adapter importコマンドを用いて、サンプルのKubernetes ManifestからInfrastructure Adapterを生成できることを確認しました。このように、Kubernetes Manifestを既に利用している場合は、同一のリソースを提供するInfrastructure Adapterのフォーマットに簡単に変換できます。 詳細については、Kubernetes ManifestからInfrastructure Adapterへの変換を参照してください。
Infrastructure Adapterの詳しい仕様については、Infrastructure Adapter Specificationを参照してください。
次のステップ
次は以下のチュートリアルに進んで、Infrastructure Adapterをカスタマイズしてみましょう。