ガベージコレクション
Kubernetesのガベージコレクターの役割は、かつてオーナーがいたが、現時点でもはやオーナーがいないようなオブジェクトの削除を行うことです。
オーナーとその従属オブジェクト
いくつかのKubernetesオブジェクトは他のオブジェクトのオーナーとなります。例えば、ReplicaSetはPodのセットに対するオーナーです。オーナーによって所有されたオブジェクトは、オーナーオブジェクトの従属オブジェクト(Dependents) と呼ばれます。全ての従属オブジェクトは、オーナーオブジェクトを指し示すmetadata.ownerReferences
というフィールドを持ちます。
時々、KubernetesはownerReference
フィールドに値を自動的にセットします。例えば、ユーザーがReplicaSetを作成したとき、KubernetesはReplicaSet内の各PodのownerReference
フィールドに自動的に値をセットします。Kubernetes1.8において、KubernetesはReplicaController、ReplicaSet、StatefulSet、DaemonSet、Deployment、Job、CronJobによって作成され、適用されたオブジェクトのownerReference
フィールドに自動的にその値をセットします。
ユーザーはまたownerReference
フィールドに手動で値をセットすることにより、オーナーと従属オブジェクト間の関係を指定することができます。
下記の例は、3つのPodを持つReplicaSetの設定ファイルとなります。
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: my-repset
spec:
replicas: 3
selector:
matchLabels:
pod-is-for: garbage-collection-example
template:
metadata:
labels:
pod-is-for: garbage-collection-example
spec:
containers:
- name: nginx
image: nginx
もしユーザーがReplicaSetを作成し、Podのメタデータを見る時、ownerReference
フィールドの値を確認できます。
kubectl apply -f https://k8s.io/examples/controllers/replicaset.yaml
kubectl get pods --output=yaml
その出力結果によると、そのPodのオーナーはmy-repset
という名前のReplicaSetです。
apiVersion: v1
kind: Pod
metadata:
...
ownerReferences:
- apiVersion: apps/v1
controller: true
blockOwnerDeletion: true
kind: ReplicaSet
name: my-repset
uid: d9607e19-f88f-11e6-a518-42010a800195
...
ネームスペースをまたいだownerReferenceは意図的に許可されていません。これは以下のことを意味します。
- ネームスペース内のスコープの従属オブジェクトは、同一のネームスペース内のオーナーと、クラスターのスコープ内のオーナーのみ指定できます。
- クラスターのスコープ内の従属オブジェクトは、クラスターのスコープ内のオーナーオブジェクトのみ指定でき、ネームスペース内のスコープのオーナーオブジェクトは指定できません。
ガベージコレクターがどのように従属オブジェクトの削除をするかを制御する
ユーザーがオブジェクトを削除するとき、それに紐づく従属オブジェクトも自動で削除するか指定できます。従属オブジェクトの自動削除は、カスケード削除(Cascading deletion) と呼ばれます。カスケード削除 には2つのモードがあり、バックグラウンド とフォアグラウンド があります。
もしユーザーが、従属オブジェクトの自動削除なしにあるオブジェクトを削除する場合、その従属オブジェクトはみなしご(orphaned) と呼ばれます。
フォアグラウンドのカスケード削除
フォアグラウンドのカスケード削除 において、そのルートオブジェクトは最初に"削除処理中"という状態に遷移します。その削除処理中 状態において、下記の項目は正となります。
- そのオブジェクトはREST APIを介して確認可能です。
- そのオブジェクトの
deletionTimestamp
がセットされます。 - そのオブジェクトの
metadata.finalizers
フィールドは、foregroundDeletion
という値を含みます。
一度"削除処理中"状態に遷移すると、そのガベージコレクターはオブジェクトの従属オブジェクトを削除します。一度そのガベージコレクターが全ての”ブロッキングしている”従属オブジェクトを削除すると(ownerReference.blockOwnerDeletion=true
という値を持つオブジェクト)、それはオーナーのオブジェクトも削除します。
注意点として、"フォアグラウンドのカスケード削除"において、ownerReference.blockOwnerDeletion=true
フィールドを持つ従属オブジェクトのみ、そのオーナーオブジェクトの削除をブロックします。
Kubernetes1.7では、認証されていない従属オブジェクトがオーナーオブジェクトの削除を遅らせることができないようにするためにアドミッションコントローラーが追加され、それは、オーナーオブジェクトの削除パーミッションに基づいてblockOwnerDeletion
の値がtrueに設定してユーザーアクセスをコントロールします。
もしオブジェクトのownerReferences
フィールドがコントローラー(DeploymentやReplicaSetなど)によってセットされている場合、blockOwnerDeletion
は自動的にセットされ、ユーザーはこのフィールドを手動で修正する必要はありません。
バックグラウンドのカスケード削除
バックグラウンドのカスケード削除 において、Kubernetesはそのオーナーオブジェクトを即座に削除し、ガベージコレクションはその従属オブジェクトをバックグラウンドで削除します。
カスケード削除ポリシーの設定
カスケード削除ポリシーを制御するためには、オブジェクトをいつ設定するかdeleteOptions
引数上のpropagationPolicy
フィールドに設定してください。設定可能な値はOrphan
、Foreground
、もしくはBackground
のどれかです。
下記のコマンドは従属オブジェクトをバックグラウンドで削除する例です。
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
-H "Content-Type: application/json"
下記のコマンドは従属オブジェクトをフォアグラウンドで削除する例です。
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
-H "Content-Type: application/json"
下記のコマンドは従属オブジェクトをみなしご状態になった従属オブジェクトの例です。
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
-H "Content-Type: application/json"
kubectlもまたカスケード削除をサポートしています。
kubectlを使って従属オブジェクトを自動的に削除するためには、--cascade
をtrueにセットしてください。
従属オブジェクトを削除せず、みなしご状態にするには--cascade
をfalseにセットしてください。
--cascade
オプションのデフォルト値はtrueになります。
下記のコマンドは、ReplicaSetを削除し、その従属オブジェクトをみなしご状態にします。
kubectl delete replicaset my-repset --cascade=false
Deploymentsに関する追記事項
Kubernetes1.7以前では、Deploymentに対するカスケード削除において、作成されたReplicaSetだけでなく、それらのPodも削除するためには、ユーザーはpropagationPolicy: Foreground
と指定しなくてはなりません 。もしこのタイプのpropagationPolicyが使われなかった場合、そのReplicaSetは削除されますが、そのPodは削除されずみなしご状態になります。
さらなる詳細に関してはkubeadm/#149を参照してください。
既知の問題について
#26120にてイシューがトラックされています。