Kubernetesのリソースは、その状態と一緒にresourceVersion
というフィールドを持っています。このフィールドは、リソースが最後に変更されたときのバージョンを示す文字列です。そして、これを利用することで楽観ロックのような動作を実現することができます。
Custom Resourceの作成
まず、例としてCustom Resource Definition (CRD)を作成します。以下はそのためのYAMLです:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: myobjects.example.com
spec:
group: example.com
names:
kind: MyObject
plural: myobjects
singular: myobject
listKind: MyObjectList
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
value:
type: string
CRDをクラスタに適用します:
kubectl apply -f myobject.yaml
MyObjectリソースの作成
次に、新しく作成したCRDに基づくMyObjectリソースを作成します:
apiVersion: example.com/v1
kind: MyObject
metadata:
name: hello-world
spec:
value: hello world
リソースをクラスタに適用します:
kubectl apply -f hello-world.yaml
resourceVersionの取得
上で作成したリソースのresourceVersion
を取得するために、以下のコマンドを実行します:
kubectl get -f hello-world.yaml --output jsonpath='{.metadata.resourceVersion}'
結果:
92029503
このresourceVersion
は、リソースを変更する際の楽観ロックに利用できます。
楽観ロックの実験
resourceVersion
をリソースに明示的に指定することで、楽観ロックができます:
apiVersion: example.com/v1
kind: MyObject
metadata:
name: hello-world
resourceVersion: "92029503" # 追加
spec:
value: goodbye world # 変更
1回目の適用:
kubectl apply -f hello-world.yaml
上の適用はresourceVersion=92029503
に対する変更なので、成功します:
myobject.example.com/hello-world configured
この適用でresourceVersion
が増えます。
そのため、同じresourceVersion
を使用して再度変更を適用しようとすると、エラーが発生します:
kubectl apply -f hello-world.yaml
結果:
Error from server (Conflict): error when applying patch:
{"metadata":{"resourceVersion":"92029503"}}
to:
Resource: "example.com/v1, Resource=myobjects", GroupVersionKind: "example.com/v1, Kind=MyObject"
Name: "hello-world", Namespace: "default"
for: "hello-world.yaml": error when patching "hello-world.yaml": Operation cannot be fulfilled on myobjects.example.com "hello-world": the object has been modified; please apply your changes to the latest version and try again
このエラーは、指定されたresourceVersion
での変更が許可されないことを示しています。つまり、他のユーザーやプロセスがリソースを変更して新しいresourceVersion
が割り当てられた後での変更は拒否されます。
まとめ
KubernetesのresourceVersion
を利用することで、リソースの変更の競合を検知し、楽観ロックのような動作を実現することができます。これは、複数のユーザーやプロセスが同時にリソースを変更しようとする際の競合を避けるために非常に役立ちます。