k8s client-go custom resource 생성(post 사용 시 주의점)
k8s client go에서 custom resource를 생성하기 위해서는 abspath()와 post()를 사용해야 한다.
k8s client go도 내부적으로는 kube-apiserver에게 REST api 콜을 보내는 것이므로, kube-apiserver의 규칙에 따라야 한다.
kongPlugin이라는 custom resource 생성 시 아래와 같이 하면 된다.
kongPlugin := &KongPlugin{
TypeMeta: metav1.TypeMeta{ // 1
APIVersion: "<api>/<version>",
Kind: "KongPlugin",
},
ObjectMeta: metav1.ObjectMeta{
Name: "kongplugin-sample",
Namespace: "<namespace>",
},
...}}
body, err := json.Marshal(kongPlugin)
data, err := clientset.RESTClient().
Post().
AbsPath("/apis/<api>/<version>/namespaces/<namespace>/kongplugins"). // 2
Body(body).
DoRaw(context.TODO())
fmt.Println(string(data)) // 3
fmt.Println(err.Error())
유의할 점은 다음과 같다.
0. RBAC 생성
당연하지만 쉽게 놓칠 수 있는 부분이다.
리소스를 get, watch, create 등을 하려면, pod는 해당 리소스에 대한 권한이 있어야한다.
pod가 사용하는 serviceaccount에 해당 리소스에 대한 권한을 주는 것을 잊지말자.
1. 리소스의 TypeMeta 명시
AbsPath에 apiVersion과 리소스 이름까지 정해져 있기는 하지만,
리소스의 TypeMeta를 명시하지 않으면 오류가 난다.
yaml 작성과 똑같이 한다고 생각하면 된다.
2. /apis/<api>/<version>/namespaces/<namespace>/<kind>규칙 준수
// 올바른 코드
...AbsPath(/apis/<api>/<version>/namespaces/<namespace>/<kind>)...
// 잘못된 코드
...AbsPath(/apis/<api>/<version>/).Namespace(namespace).Resource(kind)...
반드시 위와 같은 형식으로 해야 한다.
아래처럼 네임스페이스를 밖으로 빼내면 어째서인지 동작하지 않는다...
3. 디버깅 시, response data도 확인
잘못된 콜을 하거나 kube-apiserver 문제, RBAC 문제 등으로 에러가 발생할 수 있다.
그러나 이 에러가 반드시 error 타입에 담기지는 않는다. kube-apiserver가 json 객체로 client에게 response 해주기 때문이다.
따라서 정확한 디버깅을 하려면 error 타입뿐만 아니라, response body도 출력하여 확인해야 한다.
참고
- https://stackoverflow.com/questions/63408493/create-get-a-custom-kubernetes-resource