Help us understand the problem. What is going on with this article?

Kubernetes の Garbage Collection

はじめに

この記事では Kubernetes の Garbage Collection についてまとめていきます。

Garbage Collection とは

一般的な Garbage Collection(GC) はプログラムが動的に確保したメモリ領域のうち、不要になった領域を自動的に解放する機能 (by WikiPedia)ですが、Kubernetes で GC と呼ばれているものは以下のものがあります。

  • オブジェクトの GC
    • API Server (etcd) に保持されている Kubernetes のオブジェクトのうち、かつてオーナーがいたが、現時点でもはやオーナーがいないようなオブジェクトの削除を行う GC
  • Pod の GC
    • 存在しない Node に配置されている Pod とスケジュールされずに Terminating になった Pod を削除する GC
  • Image GC
    • Node に保持されているコンテナイメージのうち、かつて起動したが現時点ではもはや利用されなくなったコンテナイメージの削除を行うGC

今回はこれらのうちオブジェクトの GC について詳しく見ていきます。他のものは気が向いたら調査記事を書きたいと思います。

オブジェクトの GC

Kubernetes はオブジェクトを削除するときにそのオブジェクトが親となっている子オブジェクトを削除する必要があることがありますが、そういった場合に子オブジェクトの削除を GC で行なっています。(e.g. kubectl で Deployment を削除するときは ReplicaSet, Pod の削除されると思いますがこういうケースです)
Kubernetes 1.8 以前は kubectl やコントローラが直接子オブジェクトの削除を行っていましたが GC によって削除されるように変更されました。詳細はKEPを参照ください。

また、Kubernetes は分散システムで構成されていることもあり様々な処理をアトミックに更新できていないため、処理の途中で失敗するとオーナーがすでに存在しない孤児のオブジェクトが発生したりすることがあります。オブジェクトの GC はこういった孤児(orphan)となったオブジェクトを定期的に回収(削除)します。

では実際に GC がどのように回収していくかを見ていきたいところですが、その前にいくつか GC が利用しているフィールドを見ていきます。

OwnerReferences

kubectl get pod -o yaml などのコマンドを実行すると metadataownerReferences というフィールドが作られていることがあると思います。例えば以下のような例です。

pod.yaml
apiVersion: v1
kind: Pod
metadata:
  ...
  ownerReferences:
  - apiVersion: apps/v1
    controller: true
    blockOwnerDeletion: true
    kind: ReplicaSet
    name: my-repset
    uid: d9607e19-f88f-11e6-a518-42010a800195
  ...

この ownerReferences は GC がそのオブジェクトのオーナーを判断するために利用していて、主にコントローラがオブジェクトを作成するときに自動的に設定します。

Finalizers

Finalizers は CRD(CustomResourceDefinition) を利用されている方には馴染み深いですが、簡単に言うとオブジェクトを削除する前に実行する処理がある場合に削除をブロックするための機能です。これによってそのオブジェクトによって作成された子オブジェクトの削除だったり、Kubernetes の外のリソースの削除などの終了処理を簡単に含めることができます。
こちらも metadata の中にある finalizers というフィールドに保存され、このフィールドに値がある場合はオブジェクトの削除が行われないという挙動をします。この値の管理はそれを管理するためのコントローラを別に用意することになっており、Finalizer 毎にあるコントローラが責任を持ち終了処理を行います。
詳細はこちらなどを見ると良いと思います。

GC が関係する Finalizers は以下のものがあります。

https://github.com/kubernetes/kubernetes/blob/v1.17.0/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go#L102

  • FinalizerOrphanDependents: "orphan"
    • propagationPolicy Orphan で削除したときに設定される
  • FinalizerDeleteDependents: "foregroundDeletion"
    • propagationPolicy Foreground で削除したときに設定される

これらの Finalizers が設定された場合後述する GC によって削除が行われ、完了すると metadata.finalizers から削除されます。

GC の動き

ソースコードを読み取った限りでは以下のようなコンポーネントがあり、ざっくり説明すると以下のようになるようです。

image.png

回収対象

回収対象はドキュメントなどを探してみましたが具体的に記載があるソースは見当たらなかったため、ソースコードから読み取りました。
基本的には GetDeletableResources で取得したリソースで Ignore に指定されていないリソースが対象になるようです。読み解いた範囲では以下のようでした。

おまけ

DynamicSharedInformer

DynamicSharedInformer が追加されたときに GC のためという話を聞いた気がしましたが、実際のソースを見ると https://github.com/kubernetes/kubernetes/blob/v1.17.0/pkg/controller/garbagecollector/graph_builder.go#L127 のようになっており、個別に Informer で Watch しているようです。DynamicSharedInformer は軽く検索した感じでは k/k では利用されていないようだったのでまだ未実装なだけなのかなにか別の理由があるのか知りたいところです。:thinking:

参考文献

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした