この記事は Kubernetes2 Advent Calendar 2018 6日目の記事です。
はじめに
Kubernetes にリソースを追加するときは YAML を使って記述したマニフェストをクラスタに適用します。
YAMLが書ける = Kubernetesの運用ができる と言っても過言ではありません。
この記事では Kubernetes のマニフェストを YAML で書くためのノウハウを紹介します。
対象者: これからKubernetesを触ろうとしている人
YAMLに慣れる
まずはYAMLの構造を体で覚えます。
デフォルトのkubernetesにはnamespaceなどのリソースがいくつか入っているので、これをYAMLやJSONで出力して比較してみましょう。
$ kubectl get ns -o yaml
apiVersion: v1
items:
- apiVersion: v1
kind: Namespace
metadata:
︙
$ kubectl get ns -o json
{
"apiVersion": "v1",
"items": [
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
︙
Kubernetes本体のテスト用マニフェストを見るのもおすすめです。
https://github.com/kubernetes/kubernetes/tree/master/hack/testdata
YAMLの文法を知る
Kubernetesのマニフェストを書くときにハマりやすい仕様や知っておくと便利な機能を抜粋して紹介します。
型
YAMLで使える型はいろいろあるのですが、基本的には下のものだけ覚えておけばKubernetesの運用には十分です。
- null
-
~
,null
,Null
,NULL
-
- bool
-
true
=>true
,True
,TRUE
,yes
,Yes
,YES
,on
,On
,ON
-
false
=>false
,False
,FALSE
,no
,No
,NO
,off
,Off
,OFF
-
- int, float
- 数字っぽいやつ
- string
- ↑のパターンに当てはまらないもの
-
"
や'
で囲った文字列
数字や特殊な単語以外は基本文字列と思って大丈夫です。
文字列しか受け付けない場所に true
を入れたりしてエラーになることが多いので注意しましょう。
(回避するには "true"
とする必要があります)
文字列にしたい場合はとりあえず "
で囲うのもアリだと思います。
改行
基本的に文字列の中の改行はスペースとして扱われます。
apiVersion: v1
kind: Namespace
metadata:
name: hoge
annotations:
fuga: a
b
c
こう書くと fuga は
a b c
と評価されます。
改行は1段下げて揃える必要があるので注意しましょう。
改行文字を入れたい場合は \n
を使うか |
を使って
apiVersion: v1
kind: Namespace
metadata:
name: hoge
annotations:
fuga: |
a
b
c
のように書きます。
a
b
c
こうすることで複数行の文字列として評価されるようになります。
ConfigMap
などファイルを埋め込みたいときによく使うので覚えておきましょう。
JSON
YAMLにはJSONも書けます。
そのままコピペするときや、コンパクトに記述したいときに便利です。
コンテナを起動するときのコマンド配列などでよく見かけます。
containers:
- command: ["tail", "-f", "/dev/null"]
ドキュメント分割
---
だけの行を書くことで、同じファイルの中でドキュメントを分割することができます。
apiVersion: v1
kind: Namespace
metadata:
name: hoge
---
apiVersion: v1
kind: Namespace
metadata:
name: fuga
書き方を知る
YAML自体の書き方はだいたい理解した(?)と思うので、Kubernetesのマニフェストの書くときにどう調べればいいかを紹介していきます。
ベースになるものを探す
世界は広いので同じようなことをしようとする人は必ずいるはずです。
ググるなりGitHubで検索するなりして叩き台を入手しましょう。
わからない機能を調べる
わからない機能が出てきたらリファレンスを見て調べましょう。
kubectl explain
に見たいリソースとフィールド名を渡すと、使えるフィールドとその型、解説を表示してくれます。
$ kubectl explain deployment
KIND: Deployment
VERSION: extensions/v1beta1
DESCRIPTION:
DEPRECATED - This group version of Deployment is deprecated by
apps/v1beta2/Deployment. See the release notes for more information.
Deployment enables declarative updates for Pods and ReplicaSets.
FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#resources
kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
metadata <Object>
Standard object metadata.
spec <Object>
Specification of the desired behavior of the Deployment.
status <Object>
Most recently observed status of the Deployment.
$ kubectl explain deployment.spec
KIND: Deployment
VERSION: extensions/v1beta1
RESOURCE: spec <Object>
DESCRIPTION:
Specification of the desired behavior of the Deployment.
DeploymentSpec is the specification of the desired behavior of the
Deployment.
FIELDS:
minReadySeconds <integer>
Minimum number of seconds for which a newly created pod should be ready
without any of its container crashing, for it to be considered available.
Defaults to 0 (pod will be considered available as soon as it is ready)
paused <boolean>
Indicates that the deployment is paused and will not be processed by the
deployment controller.
progressDeadlineSeconds <integer>
The maximum time in seconds for a deployment to make progress before it is
considered to be failed. The deployment controller will continue to process
failed deployments and a condition with a ProgressDeadlineExceeded reason
will be surfaced in the deployment status. Note that progress will not be
estimated during the time a deployment is paused. This is not set by
default.
︙
Webでも同じものが見れます。
https://kubernetes.io/docs/reference/
あっているか確かめる
マニフェストが書けたらKubernetesにapplyしてみて問題がないか確認してみましょう。
その場でapplyされると困る場合が多いと思うので、 --dry-run
を付けて実行します。
また、 -o yaml
を付けると標準的なフォーマットに直してくれるのでエラーにならない間違いがあれば気付くこともできます。
$ kubectl apply -f - --dry-run -o yaml << 'EOF'
apiVersion: v1
kind: Namespace
metadata:
name: "hoge"
EOF
apiVersion: v1
kind: Namespace
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Namespace","metadata":{"annotations":{},"name":"hoge","namespace":""}}
name: hoge
namespace: ""
name
の "
が外れました。
last-applied-configuration
という余分なannotationが付いていますが、これは kubectl apply
コマンドが付けるものなので最終成果物には含めないようにしましょう。
エラーが出る例も紹介しておきます。
kubectl apply -f - --dry-run -o yaml << 'EOF'
apiVersion: v1
kind: Namespace
metadeta:
name: "hoge"
EOF
error: error validating "STDIN": error validating data: ValidationError(Namespace): unknown field "metadeta" in io.k8s.api.core.v1.Namespace; if you choose to ignore these errors, turn validation off with --validate=false
metadeta
というフィールドがおかしいと教えてくれています。
また、必要なフィールドがないときも教えてくれます。
$ kubectl apply -f - --dry-run -o yaml << 'EOF'
apiVersion: v1
kind: Namespace
EOF
error: error when retrieving current configuration of:
Resource: "/v1, Resource=namespaces", GroupVersionKind: "/v1, Kind=Namespace"
Name: "", Namespace: ""
Object: &{map["apiVersion":"v1" "kind":"Namespace" "metadata":map["namespace":"" "annotations":map["kubectl.kubernetes.io/last-applied-configuration":""]]]}
from server for: "STDIN": resource name may not be empty
文法チェッカーとして使うこともできますが、requiredなフィールドがなくてもエラーになってしまうので注意しましょう。
まとめ
kubectl explain
を紹介するだけの記事を書くつもりでしたが、どうせならということで普段YAMLを書くときのやり方みたいなものを少し混ぜてみました。
コマンドの中にリファレンスが入っていると調べやすいので重宝しています。
ぜひ使ってみてください。
よいYAMLライフを!!