tjtjtjのメモ

自分のためのメモです

cuelang kubernetes チュートリアル#1

cuelang を触っている。まだ入門でたとは言えない感じだが、kubernetes チュートリアルが面白い。2周目で人に説明できるくらいになってきた。

https://github.com/cuelang/cue/tree/master/doc/tutorial/kubernetes

cue import オプション

cue import ./... -p kube -l 'strings.ToCamel(kind)' -l metadata.name -f -R

  -p, --package string           package name for non-CUE files
                                 非CUEファイルのパッケージ名
  -l, --path stringArray         CUE expression for single path component
                                 シングルパスコンポーネントのCUE式
  -f, --force                    force overwriting existing files
                                 ファイル上書き
  -R, --recursive                recursively parse string values
                                 文字列値を再帰的に解析する

cue import ./... -p kube -l 'strings.ToCamel(kind)' -l metadata.name -f で起きること

  1. ./... 下の yaml から cue を生成 kube.cue -> kube.yaml
  2. package kube を付与させる
  3. オブジェクトは -l 'strings.ToCamel(kind)' -l metadata.name 内に格納される オブジェクトを一意にする
  4. ファイル上書き

tree

$ tree . | head
.
└── services
    ├── frontend
    │   ├── bartender
    │   │   ├── kube.cue
    │   │   └── kube.yaml
    │   ├── breaddispatcher
    │   │   ├── kube.cue
    │   │   └── kube.yaml

services/frontend/bartender/kube.yaml

apiVersion: v1
kind: Service
metadata:
  name: bartender
:
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: bartender
:

services/frontend/bartender/kube.cue

package kube

service: bartender: {
    apiVersion: "v1"
    kind:       "Service"
    metadata: {
        name: "bartender"
:
deployment: bartender: {
    apiVersion: "apps/v1"
    kind:       "Deployment"
    metadata: name: "bartender"
:

cat mon/prometheus/configmap.cue

yaml 内に文字列として yaml が埋め込まれている。cue にしてもまだ文字列としてのyamlのまま、これが気に入らないと。

mon/prometheus/configmap.cue

package kube

apiVersion: "v1"
kind:       "ConfigMap"
metadata: name: "prometheus"
data: {
    "alert.rules": """           <--- ここらへんが気に入らない
        groups:
        - name: rules.yaml         

cue import ./... -p kube -l 'strings.ToCamel(kind)' -l metadata.name -f -R で起きること

-Rオプションは、構成ファイルに埋め込まれた構造化されたYAMLまたはJSON文字列を検出し、これらを再帰的に変換しようとする

  • alert.rules の階層に _cue_alert_rules が出現
  • _cue_alert_rules の値は alert.rules の値を再帰的に解析したもの
  • アンダースコア(_)で始まるフィールドは、構成ファイルの出力時(exportとかevalかな)には含まれません
  • "alert.rules" の値は _cue_alert_rules の値をマーシャルしたもの
  • "encoding/yaml" を yaml656e63 としてインポート

mon/prometheus/configmap.cue

package kube

import yaml656e63 "encoding/yaml"                                     <--- yaml656e63

configMap: prometheus: {
    apiVersion: "v1"
    kind:       "ConfigMap"
    metadata: name: "prometheus"
    data: {
        "alert.rules": yaml656e63.Marshal(_cue_alert_rules)   <--- yaml656e63, _cue_alert_rules
        let _cue_alert_rules = {                              <--- _cue_alert_rules
            groups: [{
                name: "rules.yaml"
                rules: [{
                    alert: "InstanceDown"
                    expr:  "up == 0"
                    for:   "30s"
                    labels: severity: "page"
                    annotations: {
                        description: "{{$labels.app}} of job {{ $labels.job }} has been down for more than 30 seconds."

                        summary: "Instance {{$labels.app}} down"

cue eval ./mon/prometheus -e configMap.prometheus

./mon/prometheus 下のファイルのうち オブジェクト configMap.prometheus の内容について評価 次が得られる。eval で出てきたのは cue であって yaml じゃない

$ cue eval ./mon/prometheus -e configMap.prometheus
apiVersion: "v1"
kind:       "ConfigMap"
metadata: {
    name: "prometheus"
}
data: {
    "alert.rules": """       <--- cue内 yaml 文字列
        groups:
          - name: rules.yaml
            rules:
              - alert: InstanceDown
                expr: up == 0
                for: 30s
                labels:
                  severity: page
                annotations:
                  description: '{{$labels.app}} of job {{ $labels.job }} has been down for more than 30 seconds.'
                  summary: Instance {{$labels.app}} down

もとのyaml。完全一致でないが同等と言えるだろう。

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus
data:
  alert.rules: |-
    groups:
    - name: rules.yaml
      rules:
      - alert: InstanceDown
        expr: up == 0
        for: 30s
        labels:
          severity: page
        annotations:
          description: '{{$labels.app}} of job {{ $labels.job }} has been down for
            more than 30 seconds.'
          summary: Instance {{$labels.app}} down

yaml に export。yamlyaml のコメントは消えているが、おなじと言える。

$ cue export ./mon/prometheus -e configMap.prometheus --out yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus
data:
  alert.rules: |
    groups:
      - name: rules.yaml
        rules:
          - alert: InstanceDown
            expr: up == 0
            for: 30s
            labels:
              severity: page
            annotations:
              description: '{{$labels.app}} of job {{ $labels.job }} has been down for more than 30 seconds.'
              summary: Instance {{$labels.app}} down

cue から yaml を生成するときどうするの

yamlからcueを生成できるのは分かった。cueのチュートリアルやったのでcueはサイズを減らしたり、validationできるのは分かる。 cueからyaml生成は cue export --out yaml。 import でオブジェクトを一意にするため -l 'strings.ToCamel(kind)' -l metadata.name で2階層沈めた。 kind は型チェックに用いられ metaname は省略表記に用いられるのだろうなあ。 しかし、これでは取り出すとき -e configMap.prometheus 2階層(kind)(metaname)指定することになる。面倒です。どうすれば? チュートリアル進めればわかるんだけど。