ガベージコレクション

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は意図的に許可されていません。これは以下のことを意味します。

  1. ネームスペース内のスコープの従属オブジェクトは、同一のネームスペース内のオーナーと、クラスターのスコープ内のオーナーのみ指定できます。
  2. クラスターのスコープ内の従属オブジェクトは、クラスターのスコープ内のオーナーオブジェクトのみ指定でき、ネームスペース内のスコープのオーナーオブジェクトは指定できません。

ガベージコレクターがどのように従属オブジェクトの削除をするかを制御する

ユーザーがオブジェクトを削除するとき、それに紐づく従属オブジェクトも自動で削除するか指定できます。従属オブジェクトの自動削除は、カスケード削除(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フィールドに設定してください。設定可能な値はOrphanForeground、もしくは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にてイシューがトラックされています。

次の項目

Design Doc 1

Design Doc 2