k8sのpodの中からclient-goでk8sのリソース操作を行う
この例が使える
コードの書き方
重要なのは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)
}
マニフェストの書き方
操作したいリソースに対して必要な権限をPodに割り当てる必要がある。
k8sでは、Role
に対して権限を割り当て、Role
をRoleBindings
でServiceAccount
に割り当て、Pod
にServiceAccount
を指定することで、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リソースに対して操作が可能となります。