operator-sdk를 통해 두 세개의 operator 개발은 해봤지만, 내부 동작원리는 어떻게 되는지는 정확히 알기가 어려웠다.
그래서 호기심에 찾아보다가 아주 잘 정리된 글을 찾아서 내 나름대로 정리할겸 공유한다.
원 출처는 아래 블로그이다.
https://ssup2.github.io/programming/Kubernetes_Kubebuilder/
0. CRD와 Operator
먼저 간단하게 쿠버네티스에서 operator의 역할이 무엇인지 짚고 넘어가자.
아주 간단히 설명하자면
operator는 특정 리소스(오브젝트)의 상태가 변화하면, 이를 감지해서 Object를 원하는 상태로 일치시키도록 로직을 수행한다.
- 특정 리소스 : 직접 정의한 CRD(Custom Resource Definition)
- 감지 : CRD의 상태 변화를 감지
- 로직을 수행 : object가 원하는 상태가 되도록 로직을 수행하는 operator의 핵심 부분, Reconciler라는 함수가 이를 수행
이 메커니즘의 원리를 파악하는 것이다.
어떻게 리소스를 감지해서, 어떻게 reconciler까지 전달을해 로직을 수행하는지를 말이다.
1. 메커니즘
operator의 manager 컨테이너 안에는 k8s cache, k8s client, workt queue가 있다.
ㄱ. 리소스 감지
k8s에서 무엇인가를 하려면 일단 무조건 k8s api server를 거쳐야한다.
즉, 수많은 모듈들이 k8s api server에게 여러 요청을 한다는 것이고, 부하가 심하다는 뜻이다.
k8s cache의 존재 이유는 그 부하를 줄이기 위해 k8s api server를 캐싱한다.
그리고 그 안에 존재하는 informer는 operator가 관리하는 리소스를 watch하며, 리소스의 생성/수정/삭제 등의 상태 변화가 있을 때마다 event로 받는다. 이 때, informer가 받는 정보는 그 리소스의 name과 namespace 뿐이다.
그리고 이 정보를 work queue에 넣는다. work queue는 컨트롤러마다 존재한다.
k8s client는 controller가 k8s api 서버와 통신하기 위한 역할을 수행하며, manager에 하나의 client가 존재한다. object write의 경우에는 k8s api 서버에게 바로 전달하지만, read 요청은 기본적으로 k8s cache의 있는 것을 읽도록 되어있다.
ㄴ. 로직 수행
Reconciler는 work queue에 저장된 event를 가져온다.
그리고 k8s client를 이용하여 object가 원하는 상태가 되도록 일치시키기 위한 로직을 수행하게 된다.
이 로직을 성공하면 문제가 없지만, 실패했을 경우에는 성공할 때까지 work queue에 넣고 빼내어 로직을 계속해서 수행한다.
2. 예시
아래는 operator-sdk 공식 문서에 있는 예시이다.
func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// Lookup the Memcached instance for this reconcile request
memcached := &cachev1alpha1.Memcached{}
err := r.Get(ctx, req.NamespacedName, memcached)
...
}
reconciler는 object의 name, namespace에 대한 정보밖에 없다.
따라서, 실제 해당 object를 가져오기 위해서는 위 코드 처럼 k8s client를 통해 가져와야 한다.
Reconcile 함수의 return값을 보면 ctrl.Result가 있는데, 이것이 위에서 말한 work queue에 다시 넣는 것과 관련된 것이다.
문제 없이 로직을 수행한 경우에는 빈 큐를 리턴하면 된다.
ctrl.Result{}
문제가 있는 경우 다시 work queue에 집어 넣는다.
ctrl.Result{Requeue: true}
error 리턴 값은 error가 있는 경우 error 타입을 반환하고, 아니면 nil을 반환하면 된다.
즉, 정상적인 경우의 리턴 값은
return ctrl.Result{}, nil
이 될 것이다.
위 내용은 controller pod의 manager 컨테이너에 대한 내용만 포함했다.
kube-proxy 컨테이너를 포함한 자세한 내용은 생략했다.
상세한 내용은 맨 위 출처를 참고 바란다.
'공부 > Kubernetes' 카테고리의 다른 글
Kubernetes Pod-to-Service 통신 매커니즘 (0) | 2021.09.15 |
---|---|
docker image 경량화 build 하기 (0) | 2021.09.10 |
Kubernetes Audit (감사로그) (3) | 2021.08.09 |
nginx-ingress의 SSL/TLS/HTTPS 설정 (0) | 2021.07.12 |
Mount multiple files with one configmap (0) | 2021.06.24 |