Kubernetes ラベルセレクターを client-go から使う

この記事は 第二のドワンゴ Advent Calendar 2019 の20日目の記事です。

qiita.com

投稿が遅くなりました。

「Kubernetesのカスタムコントローラーを作ってみた」的な記事を書きたかったのですが、作ってる際にハマったclient-goでのラベルセレクターの扱いについて書いていこうかと思います。

ラベルセレクターとは

kubernetes.io

ラベルはユニーク性を提供しません。通常、多くのオブジェクトが同じラベルを保持することを想定します。 ラベルセレクター を介して、クライアントとユーザーはオブジェクトのセットを指定できます。ラベルセレクターはKubernetesにおいてコアなグルーピング機能となります。

Podをスケジュールする際にNodeを決定する nodeSlector もラベルセレクターの一種で、ラベルを持つノードからこの nodeSelector を利用してPodをスケジュールするノードをグルーピングします。

kubectl get コマンドにおいては --selector オプションにて入力可能です。

たとえば全てのネームスペースから、app = myapp というラベルのついて Pod をグルーピングする場合は、以下のようなコマンドを実行します。

kubectl get pods --all-namespaces --selector='app=myapp'

client-go からラベルセレクターを利用する

Podについてラベルセレクターを利用してフィルタリングを行います。

ラベルセレクターなどを利用せずに全てのネームスペースからPodを取得する場合、以下のようなコードになるかと思います。

Podのリストを取得する際の ListOptions には、それらしい LabelSelector という文字列を与えることができます。

一方で、ラベルセレクターを表すのLabelSelector構造体には、ListOptionsLabelSelector が期待する文字列を生成する関数は定義されていません*1

では、どうするかというと、同パッケージに定義されている FormatLabelSelector(labelSelector *LabelSelector) string を利用します。

labelSelector := &metav1.LabelSelector{
    MatchLabels: map[string]string{
            "app": "myapp",
    },
}
clientset.CoreV1().Pods(metav1.NamespaceAll).List(metav1.ListOptions{
    LabelSelector: metav1.FormatLabelSelector(labelSelector),
})

こうすることで、app = myapp というラベルを持つPodを取得することができます。

また、LabelSelector 構造体を利用せずに、ListOptions.LabelSelector"app=myapp" という文字列を与えることでも同じ結果を得られます。

clientset.CoreV1().Pods(metav1.NamespaceAll).List(metav1.ListOptions{
    LabelSelector: "app=myapp",
})

まとめ

client-go からKubernetesラベルセレクターを利用する方法について説明しました。

以下のリポジトリに本記事で使用したコードがあります。

github.com

ラベルセレクターは強力な仕組みで kubectl や client-go からでも簡単に利用できます。 カスタムコントローラーを開発する際にも役立てていきたいですね!

*1:ここでめちゃくちゃハマった