Open sangheee opened 2 years ago
Application Helm Chart 를 제공하면 그에 따른 CR을 정의하고, 이 CR을 watch
CR이 create/update되면 거기에 따른 helm values.yaml
파일을 생성해 application을 create/update
두 가지 방법 존재
SDK의 new
command는 Operator를 위한 skeleton project files를 생성
$ OPERATOR_NAME=visitor-helm-operator
$ operator-sdk new $OPERATOR_NAME --api-version=example.com/v1 \
--kind=VisitorsApp --type=helm
이 책이 쓰여진 당시 operator-sdk의 버전은 v0.11.1이었다. 현재 최신 버전은 v1.19.1이다.new
command는 deprecate되고 create
를 사용한다.
$ PROJECT_NAME=visitors
$ mkdir $PROJECT_NAME
$ cd $PROJECT_NAME
$ operator-sdk init --plugins helm
// 여기까지하면 create를 위한 example이 엄청 잘 작성되어있어서 적당히 따라하면 된다.
$ operator-sdk create api --group example.com --version v1 --kind VisitorsApp
Writing kustomize manifests for you to edit...
Created helm-charts/visitorsapp
$ ls -alh
total 48
drwxr-xr-x 9 user staff 288B 4 17 17:52 .
drwxr-xr-x 51 user staff 1.6K 4 17 17:52 ..
-rw-r--r-- 1 user staff 126B 4 17 17:52 .gitignore
-rw-r--r-- 1 user staff 194B 4 17 17:52 Dockerfile
-rw-r--r-- 1 user staff 8.0K 4 17 17:52 Makefile
-rw------- 1 user staff 330B 4 17 17:55 PROJECT
drwx------ 10 user staff 320B 4 17 17:55 config
drwxr-xr-x 3 user staff 96B 4 17 17:55 helm-charts
-rw-r--r-- 1 user staff 192B 4 17 17:55 watches.yaml
create
시 생성되는 각 파일들을 살펴보자
Dockerfile 보니까 helm operator에 watches.yaml 써서 특정 CR을 watch하다가 values.yaml 만들어서 차트 배포하는 것 같음 ㅇㅇ
# watches. yaml
# Use the 'create api' subcommand to add watches to this file.
- group: example.com
version: v1
kind: VisitorsApp
chart: helm-charts/visitorsapp
#+kubebuilder:scaffold:watch
# Build the manager binary
FROM quay.io/operator-framework/helm-operator:v1.19.1
ENV HOME=/opt/helm
COPY watches.yaml ${HOME}/watches.yaml
COPY helm-charts ${HOME}/helm-charts
WORKDIR ${HOME}
그리고 이 operator를 쓰려면 이 CR을 watch하는 helm-operator 이미지를 만들고, 이 이미지로 config/manager/manager.yaml
의 이미지를 업데이트해서 config/manifests
를 kube cluster에 배포하면 되겠다.
$ kubectl apply -f config/manifests
SDK는 cluster 외부에서 operator를 동작시킬 수 있게 함으로써 (시간이 드는 image build, hosting 같은 절차를 생략하고)빠른 테스트와 changes debugging을 할 수 있도록 한다.
$ make bundle IMG="example.com/visitorapps:v0.0.1"
$ make bundle-build bundle-push
$ operator-sdk run bundle example.com/visitorapps:v0.0.1
$ mkdir memcached-operator
$ cd memcached-operator
$ operator-sdk init --domain example.com --repo github.com/example/memcached-operator
# 난 여기서 $WORKSPACE/memcached-operator/bin/controller-gen not found error가 발생해서 골좀 썩였다
# 이유는 $GOBIN이 적절하게 설정되어 있지 않아서였다 ㅡㅡ!
# 아무튼 api/${version}/${lowercase_kind}_types.go controller/${lowercase_kind}_controller.go 가 각각 생성된다.
$ operator-sdk create api --group cache --version v1alpha1 --kind Memcached --resource --controller
Writing kustomize manifests for you to edit...
Writing scaffold for you to edit...
api/v1alpha1/memcached_types.go
controllers/memcached_controller.go
Update dependencies:
$ go mod tidy
Running make:
$ make generate
go: creating new go.mod: module tmp
Downloading sigs.k8s.io/controller-tools/cmd/controller-gen@v0.8.0
[...]
/Users/user/workspace/memcached-operator/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
Next: implement your new API and generate the manifests (e.g. CRDs,CRs) with:
$ make manifests
$ ll
total 384
drwxr-xr-x 15 user staff 480 4 17 22:31 .
drwxr-xr-x 52 user staff 1664 4 17 22:29 ..
-rw------- 1 user staff 129 4 17 22:29 .dockerignore
-rw------- 1 user staff 367 4 17 22:29 .gitignore
-rw------- 1 user staff 776 4 17 22:29 Dockerfile
-rw------- 1 user staff 9860 4 17 22:29 Makefile
-rw------- 1 user staff 448 4 17 22:31 PROJECT
drwx------ 3 user staff 96 4 17 22:31 api
drwxr-xr-x 3 user staff 96 4 17 22:31 bin
drwx------ 10 user staff 320 4 17 22:31 config
drwx------ 4 user staff 128 4 17 22:31 controllers
-rw------- 1 user staff 3413 4 17 22:31 go.mod
-rw-r--r-- 1 user staff 94793 4 17 22:29 go.sum
drwx------ 3 user staff 96 4 17 22:29 hack
-rw------- 1 user staff 3192 4 17 22:31 main.go
main.go
initializes and runs the Manager.We run our manager, which in turn runs all of our controllers and webhooks.
// main.go
import (
...
ctrl "sigs.k8s.io/controller-runtime"
...
)
func main() {
...
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{...})
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
...
}
--resource
로 생성한 *_types.go
file 에는 Custom Resource에 해당하는 Go type definitions이 있다
*_types.go
에는 두 가지 struct가 있다.
It is the Operator’s responsibility to determine how to use the values.
After modifying the *_types.go
file always run the following command to update the generated code for that resource type:
make generate
The above makefile target will invoke the controller-gen utility to update the api/${version}/zz_generated.deepcopy.go
file to ensure our API’s Go type definitions implement the runtime.Object
interface that all Kind types must implement.
Once the API is defined with spec/status fields and CRD validation markers, the CRD manifests can be generated and updated with the following command:
make manifests
This makefile target will invoke controller-gen to generate the CRD manifests at config/crd/bases/${group}.${domain}_${kind}.yaml.
controller to watch for changes to CRs and react accordingly.
CRD go type과 마찬가지로 --controller
flag를 통해 생성된 *_controller.go
가 controller go type을 나타낸다.
controller는 특정 resource를 reconciling
할 책임이 있다.
Resources watched by the Controller
*_controller.go
에 SetupWithManager()
는 해당 controller가 소유하고 관리하는 CR과 기타 resouces를 watch하기 위해 controller를 구축하는 방법을 지정
import (
...
appsv1 "k8s.io/api/apps/v1"
cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1"
...
)
func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&cachev1alpha1.Memcached{}).
Owns(&appsv1.Deployment{}).
Complete(r)
}
make deploy