client-goでserviceのselectorに合致するpodを検索する
Kubernetesのクライアントであるclient-goを利用して,serviceのselectorに合致するpodを検索する方法を紹介します.コマンドラインではserviceの名前を受け取るが,実際の処理はpodに対して行う必要がある場合に活用できます.
クライアントの生成
準備として,コマンドライン引数からクライアントを生成します.genericclioptions.ConfigFlags
を使うと,kubectlの標準的なフラグを簡単に追加できます.
func run() error { // コマンドライン引数を解析する f := pflag.NewFlagSet("example", pflag.ContinueOnError) type cmdOptions struct { *genericclioptions.ConfigFlags } var o cmdOptions o.ConfigFlags.AddFlags(f) if err := f.Parse(os.Args[1:]); err != nil { return xerrors.Errorf("invalid flag: %w", err) } // kubeconfigからクライアントを生成する config, err := o.ConfigFlags.ToRESTConfig() if err != nil { return xerrors.Errorf("could not load the config: %w", err) } namespace, _, err := o.ConfigFlags.ToRawKubeConfigLoader().Namespace() if err != nil { return xerrors.Errorf("could not determine the namespace: %w", err) } clientset, err := kubernetes.NewForConfig(config) if err != nil { return xerrors.Errorf("could not create a client: %w", err) } }
実際のツール開発では,pflag
を直接利用するのではなく cobra.Command
を利用する方が便利かと思います.
serviceの取得とpodの検索
クライアントを利用してserviceを取得してみましょう.ここでは例として echoserver
というserviceを取得します.
serviceName := "echoserver" service, err := clientset.CoreV1().Services(namespace).Get(serviceName, metav1.GetOptions{}) if err != nil { return nil, "", xerrors.Errorf("could not find the service: %w", err) } log.Printf("Service %s found", service.Name)
serviceに対応するpodを検索するには,serviceのselectorを利用します.例えば,echoserver
サービスで app=echoserver
というselectorが定義されている場合,サービスに対応するpodには app=echoserver
というlabelが付いています.kubectlコマンドでserviceとpodの詳細を表示すると,selectorとlabelの関係がよくわかります.
% kubectl describe svc/echoserver Selector: app=echoserver % kubectl describe pod/echoserver-xxx-xxx Labels: app=echoserver
クライアントを利用してserviceのselectorに合致するpodを検索します.
// serviceで定義されているselectorをkey=value形式に変換する var selectors []string for k, v := range service.Spec.Selector { selectors = append(selectors, fmt.Sprintf("%s=%s", k, v)) } selector := strings.Join(selectors, ",") // selectorに合致するpodを検索する pods, err := clientset.CoreV1().Pods(namespace).List(metav1.ListOptions{LabelSelector: selector}) if err != nil { return nil, "", xerrors.Errorf("could not find the pods by selector %s: %w", selector, err) } log.Printf("Found pod(s): %+v", pods.Items)
これらのコードを実行すると,以下のような結果が表示されます.
2019/08/19 21:37:48 Service echoserver found 2019/08/19 21:37:48 Found pod(s): []Pod{...}
あとは,podのリストを利用して処理を行えばよいです.
まとめ
client-goを利用して,serviceのselectorに合致するpodを検索する方法を紹介しました.