💬

yttに入門してみた

に公開

今回は、yttをを用いてYAMLファイルを生成する方法について学習してみました。

yttとは?

公式サイトによると、

Template and patch as needed to easily make your configuration reusable and extensible. Works with your own and third-party YAML configuration.

ということで、YAMLファイルについてテンプレートとパッチを適用することで、設定を簡単に再利用・拡張できるツールということです。YAMLファイルは基本的には静的に指定した値を利用するものですが、yttを用いることでファイルの内容を生成することができます。

https://carvel.dev/ytt/

使ってみる

公式サイトにてGetting Startedが提供されているので、その内容をもとにいろいろ試してみます。なお、利用するファイルはKubernetesを想定したものも利用します。

インストール

yttのインストール方法はこちらにまとめられています。私の環境ではmacbookなので以下でインストールしました。

brew tap carvel-dev/carvel
brew install ytt

変数の利用

例えば以下のように、同じラベルが複数設定されているYAMLファイルがあったとします。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: app-name
    app.kubernetes.io/version: v1.0.0
  name: app-name
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/component: controller
      app.kubernetes.io/name: app-name

内容を見ると、app-nameという名前でいくつかの値が登録されていることがわかります。これらの値が変わった時に全てを変更する必要がなくなるようにするのがyttで実現でき、以下のようにします。

config.yaml
#@ app_name = "app-name"
#@ version = "v1.0.0"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: #@ app_name
    app.kubernetes.io/version: #@ version
  name: #@ app_name
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/component: controller
      app.kubernetes.io/name: #@ app_name

それではこの設定ファイルから反映された結果のYAMLを生成させてみましょう。以下のコマンドを実行することで生成できます。

ytt -f config.yaml

すると、出力は当初作成していたファイルが生成されます。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: app-name
    app.kubernetes.io/version: v1.0.0
  name: app-name
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/component: controller
      app.kubernetes.io/name: app-name

フラグメントによる制御

例えばあるフラグが指定されている時とない時で結果を制御したいような場合、以下のようにすることで実現できます。

config.yaml
#@ app_name = "prometheus-operator"
#@ version = "v0.39.0"

#@ def labels(with_version=False):
  app.kubernetes.io/component: controller
  app.kubernetes.io/name: #@ app_name
  #@ if with_version:
  app.kubernetes.io/version: #@ version
  #@ end
#@ end
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels: #@ labels(with_version=False)
  name: #@ app_name
  namespace: default

こちらの設定では、labelsという関数を定義し、with_version=Trueの時はapp.kubernetes.io/versionが指定されますが、with_version=Falseの時は指定されません。その制御は関数呼び出し元で行い、先ほどの例ではlabels: #@ labels(with_version=False) の部分に該当します。

それではそれぞれTrue/Falseにした時の結果をみてみましょう。

`with_version=True`の場合
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: prometheus-operator
    app.kubernetes.io/version: v0.39.0
  name: prometheus-operator
  namespace: default
`with_version=False`の場合
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: prometheus-operator
  name: prometheus-operator
  namespace: default

この結果のように、フラグを用いて制御できていることが確認できます。

別YAMLファイルからデータを読み込む

先ほどまでの例では一つのYAMLファイル内に変数の定義だったりをしていますが、頻繁に変更されるような値をそのファイル内で定義するのはアンチパターンなので、別ファイルで定義したいです。そのような場合にも対応する方法が提供されています。それでは例をみてみましょう。

config.yaml
#@ load("@ytt:data", "data")

apiVersion: apps/v1
kind: Deployment
metadata:
  name: #@ data.values.app_name
  namespace: #@ data.values.namespace
schema.yaml
#@data/values-schema
---
app_name: "app-name"
namespace: "app-namespace"

#@ load("@ytt:data", "data")を実行すると、dataという形で読み込むことができ、値はdata.values.hogehogeの形式で参照できます。この例で言うと、data.values.app_nameapp-namedata.values.namespaceapp-namespaceが取得できると言うことになります。

それではこれを実行してみましょう。単純に-fでファイルを追加するだけで実現できます。

ytt -f config.yaml -f schema.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-name
  namespace: app-namespace

複数ファイルに同時に値を挿入

先ほどの例では1つのファイルに対して値を注入していますが、同時に複数のファイルに対して値を注入できます。サンプルでは便宜上同じ内容のファイルを二つに分けています。

deployment.yaml
#@ load("@ytt:data", "data")

apiVersion: apps/v1
kind: Deployment
metadata:
  name: #@ data.values.app.name
  namespace: #@ data.values.app.namespace
service.yaml
#@ load("@ytt:data", "data")

apiVersion: apps/v1
kind: Service
metadata:
  name: #@ data.values.app.name
  namespace: #@ data.values.app.namespace
value.yaml
#@data/values
---
app:
  name: app-name
  namespace: app-namespace

それでは実行してみましょう。

ytt -f deployment.yaml -f service.yaml -f value.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-name
  namespace: app-namespace
---
apiVersion: apps/v1
kind: Service
metadata:
  name: app-name
  namespace: app-namespace

実行結果を見ると、deployment.yamlservice.yamlに適用した結果を一つのYAMLファイルとしてまとめられていることが確認できます。

まとめ

今回はyttについて入門してみました。実際にはより様々な機能がありYAMLファイルの制御をより複雑にに実行することができます。ユースケースとしてはKubernetesのマニフェストを記載する時に制御する方法の一つとして利用することになるかなと思います。みなさんもぜひ使ってみてください。

Discussion