Appearance
What is Cloud Native Adapter
Cloud Native Adapter(旧称: Design Pattern)とは、コンセプトで示すとおり、アプリケーションを動かすクラウドアーキテクチャを構成する「インフラストラクチャ構成」と、そのアプリケーションのデプロイ・試験を実施する「ワークフロー」を統一的なインターフェースで管理できるQmonus Value Stream独自のInfrastructure as Code(IaC)の実装です。
Cloud Native Adapterには2種類のカテゴリがあり、「インフラストラクチャ構成」を定義する Infrastructure Adapter
と、「ワークフロー」を定義する CI/CD Adapter
になります。それぞれ独立して作成・再利用・組み合わせることが可能です。
CUE
CUE言語は、スケーラブルにデータ/コンフィグを検証、生成するためのデータ記述言語です。 Qmonus Value Streamでは、宣言的APIで設定するコンポーネントを組み合わせるシステム構成や、宣言的APIでタスクを記述するデプロイ手順を生成するために、CUEの強力かつ柔軟な言語仕様を活用します。 以下に、その特徴の一部を記載します。詳細については、CUE言語の公式ドキュメントを参照してください。
柔軟な結合によるデータ生成
CUEでは、データを任意の階層で結合していくことで、最終的なデータを生成します。結合の順序に関係なく一貫した結果を生成(Associative、Commutative、かつIdempotent)するため、実装者の意図/コンテクストでデータをブロック分けして結合処理を書くことで、繰り返し同じ内容を書かずにすみます。
以下のように metadata
部分を全てのリソース定義に結合する形で書くことで、
cue
resources: [string]: metadata: {
name: "app01"
namespace: "test-namespace"
}
resources: deployment: spec: {
replicas: 3
template: spec: containers: [{
name: "container01"
image: "container01"
}]
}
resources: service: spec: type: "NodePort"
CUEの評価によって、以下のようにdeployment
とservice
にmatadata
をマージした結果を得ることができます。
yaml
resources:
deployment:
spec:
replicas: 3
template:
spec:
containers:
- name: container01
image: container01
metadata:
name: app01
namespace: test-namespace
service:
spec:
type: NodePort
metadata:
name: app01
namespace: test-namespace
Type チェック
CUEでは、文字列や数字といった具体的な値を宣言するだけでなく、データの型を宣言できます。型を宣言したデータを、具体的な値を持つデータに結合することで、値が型にマッチするか検証します。
以下のように、#MyConstraint
でデータの型を定義し、deployment.spec
と結合することで、deployment.spec
が型にマッチしているか検証できます。
cue
#MyConstraint: {
replicas: int & >2 // 整数かつ2より大きいこと
template: spec: containers: [{
name: !="" // 空文字じゃないこと
image: !=""
}]
}
resources: deployment: spec: #MyConstraint & {
replicas: 1 // Validationエラー
template: spec: containers: [{
name: "container01"
image: "container01"
}]
}
上記の例では、replicas
が条件を満たさないので、CUEの評価によって、以下の結果を得ます。
resources.deployment.spec.replicas: invalid value 1 (out of bound >2):
継承、オーバーレイ不可
言語仕様上、継承やオーバーレイを認めておらず、一度宣言したデータを、別のデータとの結合によって上書きできません。この制約により、データ結合を繰り返したとしても、各データの値がどこで宣言されたか追いかけることが容易になり、コードベースをシンプルに保つことができます。さらに、各Cloud Native Adapterで導入した値や制約を他のCloud Native Adapterで誤って上書きし、無効にするようなバグを混入することなく、確実に各Cloud Native Adapterで確立したベストプラクティスを適用できます。
以下のように、deployment.spec.replicas
の値を上書きできません。
resources: deployment: spec: {
replicas: 1
template: spec: containers: [{
name: "container01"
image: "container01"
}]
}
// 上書き不可のため、Conflictエラー
resources: deployment: spec: replicas: 3
CUEの評価によって、以下の結果を得ます。
resources.deployment.spec.replicas: conflicting values 3 and 1:
Module
import
文を使うことで、別のCUEファイルで定義されたデータを読み出すことが可能です。これにより、通常のプログラミング言語のように、大きくなりがちなデータを、機能分担や意図/コンテクストごとに小さいファイルに分割し、スケーラブルにコードベースを管理します。
以下のように、builtinモジュールを読み出すことも可能です。
cue
import "encoding/yaml"
_data: {
name: "test"
verbosity: 3
}
resources: configmap: data: yaml.Marshal(_data)
encoding/yaml
モジュールを活用することで、以下のように、_data
をYAML形式のStringに変換し、configmap.data
に結合できます。
yaml
resources:
configmap:
data: |
name: test
verbosity: 3
Schema
API定義などからSchemaを生成し、宣言するデータがAPI定義に従っているかを検証できます。
以下のように、CUEコマンドを利用して、Kubernetes APIのスキーマを生成します。
bash
cue get go k8s.io/api/apps/v1
以下のように生成したスキーマをimport
し、deployment
に結合することで、deployment
のデータがKubernetes Deployment APIにマッチしているか検証できます。
cue
import (
appsv1 "k8s.io/api/apps/v1"
)
resources: deployment: appsv1.#Deployment
resources: deployment: spec: {
replicas: 1
template: spec: containers: [{
name: "container01"
sample: "not allowed" // Deployment APIで定義されていないためエラー
}]
}
ここで、sample
フィールドはDeployment APIで認められていないため、CUEの評価によって、以下の結果を得ます。
resources.deployment.spec.template.spec.containers.0: field not allowed: sample:
Infrastructure AdapterとCI/CD Adapter
Cloud Native Adapterには用途によって2種類のAdapterに分類されます。詳細については、それぞれのリンクを参照してください。
- Infrastructure Adapter: Kubernetes Manifestなど、アプリケーション・インフラストラクチャ構成を記述したYAMLファイルを出力するためのCUEファイル
- CI/CD Adapter: Tekton Pipeline/Taskの構成を記述したYAMLファイルを出力するためのCUEファイル