Quickstart for Go-based Operators | Operator SDK
Quickstart for Go-based Operators
A simple set of instructions to set up and run a Go-based operator.
sdk.operatorframework.io
필수 체크 요소
- cluster-admin 권한이 있어야함
- example.com 이 기본 namespace로 된다
프로젝트 생성과 초기화
operator-sdk 초기화
mkdir memcached-operator
cd memcached-operator
operator-sdk init --domain example.com --repo github.com/example/memcached-operator
trace
[root@tech7 memcached-operator]# operator-sdk init --domain example.com --repo github.com/example/memcached-operator
INFO[0000] Writing kustomize manifests for you to edit...
INFO[0000] Writing scaffold for you to edit...
INFO[0000] Get controller runtime:
$ go get sigs.k8s.io/controller-runtime@v0.17.3
INFO[0002] Update dependencies:
$ go mod tidy
Next: define a resource with:
$ operator-sdk create api
Memcached API 생성
Api 와 Controller 를 생성한다
Operator가 어떤 리소스를 관리할지 정의한다
operator-sdk create api --group cache --version v1alpha1 --kind Memcached --resource --controller
- group : CR의 그룹이름 (cache)
- version : API 버전 (v1alpha1)
- kind : CR의 이름 (Memcached)
trace
-bash: 예기치 않은 토큰 ';' 근처에서 문법 오류
[root@tech7 memcached-operator]# ls
Dockerfile Makefile PROJECT README.md cmd config go.mod go.sum hack test
[root@tech7 memcached-operator]# cd ../
[root@tech7 Operator]# ls
kopf kopf-02 memcached-operator operator-sdk test
[root@tech7 Operator]# cd memcached-operator/
[root@tech7 memcached-operator]# ls
Dockerfile Makefile PROJECT README.md cmd config go.mod go.sum hack test
[root@tech7 memcached-operator]# operator-sdk create api --group cache --version v1alpha1 --kind Memcached --resource --controller
INFO[0000] Writing kustomize manifests for you to edit...
INFO[0000] Writing scaffold for you to edit...
INFO[0000] api/v1alpha1/memcached_types.go
INFO[0000] api/v1alpha1/groupversion_info.go
INFO[0000] internal/controller/suite_test.go
INFO[0000] internal/controller/memcached_controller.go
INFO[0000] internal/controller/memcached_controller_test.go
INFO[0000] Update dependencies:
$ go mod tidy
INFO[0000] Running make:
$ make generate
mkdir -p /root/k8s/Operator/memcached-operator/bin
Downloading sigs.k8s.io/controller-tools/cmd/controller-gen@v0.14.0
/root/k8s/Operator/memcached-operator/bin/controller-gen-v0.14.0 object:headerFile="hack/boilerplate.go.txt" paths="./..."
Next: implement your new API and generate the manifests (e.g. CRDs,CRs) with:
$ make manifests
api 폴더 안에 v1alpha 폴더와 bin 폴더가 생성되었다
- before
[root@tech7 memcached-operator]# ls
Dockerfile Makefile PROJECT README.md cmd config go.mod go.sum hack test
- after
[root@tech7 memcached-operator]# ls
Dockerfile Makefile PROJECT README.md api bin cmd config go.mod go.sum hack internal test
api 폴더 안에는 go 파일들이 생성이 된다
[root@tech7 v1alpha1]# pwd
/root/k8s/Operator/memcached-operator/api/v1alpha1
[root@tech7 v1alpha1]# ls
groupversion_info.go memcached_types.go zz_generated.deepcopy.go
bin 폴더 안에는 controller 실행파일이 생성디 되었다
[root@tech7 bin]# pwd
/root/k8s/Operator/memcached-operator/bin
[root@tech7 bin]# ls
controller-gen-v0.14.0
API 코드 살펴보기
경로 : */memcached-operator/api/v1alpha1
파일
1. groupversion_info.go
- API그룹과 Version 정보가 있다
- SchemeBuilder로 CR을 k8s에 등록할때 필요한 객체를 정의한다
- k8s가 API인식할 수 있게 한다
2. memcached_types.go
- 중요
- CRD의 spec 과 status 정의
- spec에선 replica 와 img 등을 정의하고
- Status에서는 현재 리소스의 상태를 관리
3. zz_generated.deepcopy.go:
- DeepCopy 함수를 자동으로 생성한 코드
- Golang에선 객체 복사할때 Deep Copy 함수가 필요하다
- Operator가 Reconcile 함수에서 spec과 status를 업데이트 할 때 필요하다
1. groupversion_info.go
package v1alpha1
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "cache.example.com", Version: "v1alpha1"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)
group 명 (cache) 과 group 버전(v1alpha1)으로 schema를 생성
2. memcached_types.go
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// MemcachedSpec defines the desired state of Memcached
type MemcachedSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Foo is an example field of Memcached. Edit memcached_types.go to remove/update
Foo string `json:"foo,omitempty"`
}
// MemcachedStatus defines the observed state of Memcached
type MemcachedStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
// Memcached is the Schema for the memcacheds API
type Memcached struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec MemcachedSpec `json:"spec,omitempty"`
Status MemcachedStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// MemcachedList contains a list of Memcached
type MemcachedList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Memcached `json:"items"`
}
func init() {
SchemeBuilder.Register(&Memcached{}, &MemcachedList{})
이 부분에서 CR의 스펙과 Status를 정의할 수 있다 .
구조체 : MemcachedSpec , MemcachedStatus , Memcached , MemcachedList
함수 : init
3. zz_generated.deepcopy.go
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Memcached) DeepCopyInto(out *Memcached) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
out.Status = in.Status
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Memcached.
func (in *Memcached) DeepCopy() *Memcached {
if in == nil {
return nil
}
out := new(Memcached)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Memcached) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MemcachedList) DeepCopyInto(out *MemcachedList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Memcached, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedList.
func (in *MemcachedList) DeepCopy() *MemcachedList {
if in == nil {
return nil
}
out := new(MemcachedList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *MemcachedList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MemcachedSpec) DeepCopyInto(out *MemcachedSpec) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedSpec.
func (in *MemcachedSpec) DeepCopy() *MemcachedSpec {
if in == nil {
return nil
}
out := new(MemcachedSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MemcachedStatus) DeepCopyInto(out *MemcachedStatus) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedStatus.
func (in *MemcachedStatus) DeepCopy() *MemcachedStatus {
if in == nil {
return nil
}
out := new(MemcachedStatus)
in.DeepCopyInto(out)
return out
}
docker 이미지 build 하고 push 하기
operaotr를 Docker 이미지로 build 하고 push 한다
k8s 가 Operator 실행할 때 필요한 이미지.
경로
[root@tech7 memcached-operator]# pwd
/root/k8s/Operator/memcached-operator
[root@tech7 memcached-operator]# ls
Dockerfile Makefile PROJECT README.md api bin cmd config go.mod go.sum hack internal test
실행하기
make docker-build docker-push IMG="example.com/memcached-operator:v0.0.1"
에러 발생
[root@tech7 memcached-operator]# make docker-build docker-push IMG="example.com/memcached-operator:v0.0.1"
docker build -t example.com/memcached-operator:v0.0.1 .
Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.
[1/2] STEP 1/11: FROM golang:1.21 AS builder
✔ registry.access.redhat.com/golang:1.21
Trying to pull registry.access.redhat.com/golang:1.21...
Error: creating build container: initializing source docker://registry.access.redhat.com/golang:1.21: reading manifest 1.21 in registry.access.redhat.com/golang: name unknown: Repo not found
make: *** [Makefile:145: docker-build] 오류 125
podname login docker.io 로 login을 한다
OLM은 무엇인가
Operator Lifecycle Manager
Operator의 배포와 관리를 쉽게 하기 위한 툴
k8s에 Operator 설치와 업데이트, 의존성 , 권한 관리 가능
- CSV파일로 Operator를 관리할 수 있다
bundle 로 묶어서 여러 이미지를 한번에 배포하는 걸로 보인다
배포하기
OLM 없이 직접 배포를 해보겠다
1. operator를 k8s에 배포한다
make deploy IMG="example.com/memcached-operator:v0.0.1"
에러 (go 버전이 맞지 않는다)
# internal/race
compile: version "go1.23.2" does not match go tool version "go1.21.11 (Red Hat 1.21.11-1.el9_4)"
[root@tech7 memcached-operator]# go version
go version go1.21.11 (Red Hat 1.21.11-1.el9_4) linux/amd64
버전을 맞춰줬다
[root@tech7 memcached-operator]# go version
go version go1.23.2 linux/amd64
해결
[root@tech7 memcached-operator]# make deploy IMG="suamj/memcached-operator:v0.0.1"
/root/k8s/Operator/memcached-operator/bin/controller-gen-v0.14.0 rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
Downloading sigs.k8s.io/kustomize/kustomize/v5@v5.3.0
cd config/manager && /root/k8s/Operator/memcached-operator/bin/kustomize-v5.3.0 edit set image controller=suamj/memcached-operator:v0.0.1
/root/k8s/Operator/memcached-operator/bin/kustomize-v5.3.0 build config/default | kubectl apply -f -
namespace/memcached-operator-system created
customresourcedefinition.apiextensions.k8s.io/memcacheds.cache.example.com created
serviceaccount/memcached-operator-controller-manager created
role.rbac.authorization.k8s.io/memcached-operator-leader-election-role created
clusterrole.rbac.authorization.k8s.io/memcached-operator-manager-role created
clusterrole.rbac.authorization.k8s.io/memcached-operator-memcached-editor-role created
clusterrole.rbac.authorization.k8s.io/memcached-operator-memcached-viewer-role created
clusterrole.rbac.authorization.k8s.io/memcached-operator-metrics-reader created
clusterrole.rbac.authorization.k8s.io/memcached-operator-proxy-role created
rolebinding.rbac.authorization.k8s.io/memcached-operator-leader-election-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/memcached-operator-manager-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/memcached-operator-proxy-rolebinding created
service/memcached-operator-controller-manager-metrics-service created
deployment.apps/memcached-operator-controller-manager created
2. CR을 K8S에 생성한다
명령 수행에 앞서 파일에 뭐가있는지 본다
kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml
- cache_v1alpha1_memcached.yaml
[root@tech7 samples]# pwd
/root/k8s/Operator/memcached-operator/config/samples
[root@tech7 samples]# cat cache_v1alpha1_memcached.yaml
apiVersion: cache.example.com/v1alpha1 # API 버전
kind: Memcached # 리소스의 종류, 여기서는 Memcached CR
metadata:
labels:
app.kubernetes.io/name: memcached-operator
app.kubernetes.io/managed-by: kustomize
name: memcached-sample # 리소스의 이름
spec:
# TODO(user): Add fields here # 사용자가 정의할 추가 설정 필드
- kustomization.yaml
[root@tech7 samples]# cat kustomization.yaml
## Append samples of your project ##
resources:
- cache_v1alpha1_memcached.yaml
#+kubebuilder:scaffold:manifestskustomizesamples
CR을 등록
[root@tech7 memcached-operator]# kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml
memcached.cache.example.com/memcached-sample created
'k8s' 카테고리의 다른 글
[k8s] operator-sdk(Go)로 memcahce 오퍼레이터 구축하기 - 3 (요약) (1) | 2024.11.18 |
---|---|
[k8s] operator-sdk(Go)로 memcahce 오퍼레이터 구축하기 - 2 (0) | 2024.11.15 |
[k8s] CRD->CR->Operator(kopf python) 만들기 (0) | 2024.08.27 |
[K8s] ClusterIP vs Headless vs Nodeport vs LoadBalancer ( ft. Ingress) (0) | 2024.08.22 |
centos 9 - k8s 구성하기 (master, worker01,worker02) (3) | 2024.08.02 |