Skip to content

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の評価によって、以下のようにdeploymentservicematadataをマージした結果を得ることができます。

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ファイル