Closed3

k8sのpodの中からclient-goでk8sのリソース操作を行う

esakaesaka

コードの書き方

重要なのはkubeconfigの取得方法

ローカル開発時などは、~/.kubeを読み込む、k8s内のpodで動作する場合は割り当てられたservice accountで動作させたい

アプリのconfigを取得する処理を下記のようにする

func getK8sConfig() (*rest.Config, error) {
	// InClusterConfigの取得処理
	config, err := rest.InClusterConfig()
	// k8s Cluster内でないなら、エラーが返ってくる
	// その場合は次のローカルのkubeconfig取得処理へ
	if err == nil {
		return config, nil
	}

	// ローカルのkubeconfigからconfigを作成する
	var kubeconfig *string
	if home := homedir.HomeDir(); home != "" {
		kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
	} else {
		kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
	}
	flag.Parse()

	return clientcmd.BuildConfigFromFlags("", *kubeconfig)
}

最初にまず、ライブラリのInClusterConfig()を呼び出す。これはマウントされたserviceaccountのsecretから認証情報を取ってきてconfigとするもの。
これでエラーの場合は、次のローカルのkubeconfigから取る処理に移る(エラー全部無視してるけど、パスが存在しないエラーだけ通すって感じで場合分けしたほうがいいかも..?)

これでconfigを元にクライアントが作れるので、ライブラリのexampleなどを参考に操作したいリソース用のクライアントをさらに作る感じになる

    config, err := getK8sConfig()
    if err != nil {
        panic(err)
    }
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err)
    }
esakaesaka

マニフェストの書き方

操作したいリソースに対して必要な権限をPodに割り当てる必要がある。
k8sでは、Roleに対して権限を割り当て、RoleRoleBindingsServiceAccountに割り当て、PodServiceAccountを指定することで、Podの特定の位置に認証情報がマウントされるので、それを読み込むことで、Roleで指定した権限が利用可能となる -> Role Based Access Control(RBAC)というやつ
(厳密にはClusterRoleとか、RoleBindings対象がserviceaccount以外とかもあるけど、やり方の1つということで)

マニフェスト例

sample-saというservice accountを作ります

apiVersion: v1
kind: ServiceAccount
metadata:
  name: sample-sa
  namespace: default

sample roleというroleを作ります。deploymentに対して、情報の取得とreplica数変更用update権限を付与しています。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: sample-role
rules:
  - apiGroups: ["extensions", "apps"]
    resources: ["deployments", "deployments/scale"]
    verbs: ["get", "update"]

RoleBindingsでsample-roleをsample-saに紐づけます

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: sample-rb
  namespace: default
subjects:
  - kind: ServiceAccount
    name: sample-sa
    namespace: default
roleRef:
  kind: Role
  name: sample-role
  apiGroup: rbac.authorization.k8s.io

最後にDeploymentリソースを作成します。sepc.template.spec.serviceAccountNameでsample-saを指定します

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample
  namespace: default
spec:
  replicas: 1
  template:
    spec:
      serviceAccountName: sample-sa
      containers: {}

これでk8s pod内からdeploymentリソースに対して操作が可能となります。

このスクラップは2022/01/19にクローズされました