operator 구축을 helm 기반이되 go를 사용한 걸로 만들어보려고 했다
https://www.velotio.com/engineering-blog/getting-started-with-kubernetes-operators-helm-based-part-1
Getting Started With Kubernetes Operators (Helm Based) - Part 1
www.velotio.com
이 절차를 따라가 보려 했으나...
Golang을 한 번도 써보지 않은 나...
go get
이 커맨드가 안 먹혔다!
https://stackoverflow.com/questions/30295146/how-can-i-install-a-package-with-go-get
How can I install a package with go get?
I want to install packages from github to my $GOPATH, I have tried this: go get github.com:capotej/groupcache-db-experiment.git the repository is here.
stackoverflow.com
[How can I install a package with go get?
I want to install packages from github to my $GOPATH, I have tried this: go get github.com:capotej/groupcache-db-experiment.git the repository is here.
stackoverflow.com](https://stackoverflow.com/questions/30295146/how-can-i-install-a-package-with-go-get)
golang을 처음 써봐서 몰랐는데, module을 설정해 줘야한다고 한다...
그래서
go path가 아닌 곳에 파일 만들고? (지워도 되는 듯)
$go mod init <pkg혹은 파일 name>
$go mod tidy
이렇게 하고
이 쉘에서만 적용이 되는 게 불편하므로 export도 해준다
근데 쟤네도 안됐는데 찾아보니까
go mod init
과 go mod tidy
를 실행할 때 여전히 $GOPATH
에 있는 go.mod
파일을 참조하려고 해서 안되었던 거고
먼저, go mod tidy
명령어가 정상적으로 동작하지 않는 이유는 아직 Go가 $GOPATH
경로와 충돌하고 있기 때문에...
해결 방법:
1. GO111MODULE
환경 변수를 설정하여 모듈 활성화
먼저, Go 모듈이 항상 활성화되도록 환경 변수를 설정합니다.
export GO111MODULE=on
이 명령은 현재 셸 세션에서만 유지되므로, 매번 수동으로 설정하기 번거로우면 ~/.bashrc
, ~/.zshrc
(또는 사용하는 쉘 설정 파일)에 추가할 수 있습니다:
echo 'export GO111MODULE=on' >> ~/.zshrc
source ~/.zshrc
이후, 다시 프로젝트 디렉토리로 이동한 후 go mod init
및 go mod tidy
를 실행합니다.
cd /Users/yangdayeon/go_test/hello
go mod init hello
go mod tidy
2. $GOPATH
문제 해결
go mod tidy
명령이 $GOPATH
경로를 계속 참조하는 문제가 발생하는 경우, $GOPATH
설정을 확인하고, 불필요한 설정이 없는지 점검해야 합니다.
echo $GOPATH
위 명령을 통해 $GOPATH
가 어디로 설정되어 있는지 확인하세요. 만약 불필요한 설정이 되어 있다면 해당 경로를 비우거나, $GOPATH
에 Go 파일이 남아있지 않은지 확인 후 정리하세요.
3. 디렉토리 확인
현재 작업 디렉토리가 맞는지 다시 한번 확인하고, go.mod
파일이 정상적으로 생성되었는지도 확인합니다.
ls /Users/yangdayeon/go_test/hello
이 디렉토리에 go.mod
파일이 존재하는지 확인한 후 다시 시도해 보세요.
정리
$GO111MODULE
을on
으로 설정$GOPATH
경로를 확인 및 불필요한go.mod
파일 제거- 적절한 프로젝트 디렉토리에서
go mod init
및go mod tidy
를 다시 시도
이렇게 해줬더니 이 디렉터리 안에서 go get 커멘드를 사용할 수 있었다
뭔가 얼렁뚱땅 하긴 했지만 일단 돌아가긴 함 (응...)
$ go get -d github.com/operator-framework/operator-sdk
go: -d flag is deprecated. -d=true is a no-op
go: downloading github.com/operator-framework/operator-sdk v1.37.0
go: added github.com/operator-framework/operator-sdk v1.37.0
아니... go 세팅이 이렇게 어려운지 몰랐어
https://sdk.operatorframework.io/docs/building-operators/helm/tutorial/
Helm Operator Tutorial
An in-depth walkthrough of building and running a Helm-based operator.
sdk.operatorframework.io
https://sdk.operatorframework.io/docs/building-operators/helm/quickstart/
Quickstart for Helm-based Operators
A simple set of instructions to set up and run a Helm-based operator.
sdk.operatorframework.io
그래서 저녀석을 버리고 operator sdk에서 제공하는 helm-based quickstart 를 해봤다
차례대로 잘 따라하고~
잘 되다가 Bundle img에서 좀 문제가 있었다
makefile에서 bundle기본값이 bundle img을 받아와서 기본 예시용 example.com/nginx-operator-bundle로 설정되어 있어서
bundle img말고 img 받아오는 걸로 바꿔줬더니 됐다 후.후.후...
olm 도 install 잘 해준다 ~_~
operator sdk는 이렇게 install만 해주면 Operator Lifecycle Manager도 바로 이용할 수 있다
그리고 구축 단계가 빠름
## Create a sample Nginx custom resource:
$ kubectl apply -f config/samples/demo_v1alpha1_nginx.yaml
nginx.demo.example.com/nginx-sample created
$ kubectl apply -f config/samples/demo_v1alpha1_nginx.yaml
nginx.demo.example.com/nginx-sample created
## uninstall the operator
$ make undeploy
이 단계를 따르면 되는데, 좀 더 구체적인 단계에서
"다음 단계로 `make undeploy` 명령을 실행하기 전에, 위에서 언급한 커스텀 리소스(Custom Resource)가 삭제되었는지 반드시 확인하세요. `helm-operator`의 컨트롤러가 커스텀 리소스에 'finalizers'를 추가하기 때문에, 그렇지 않으면 클러스터에 삭제할 수 없는 남아 있는 커스텀 리소스 객체가 생길 수 있습니다."
- Custom Resource: Kubernetes에서 사용자 정의 리소스 객체를 의미합니다. 일반적으로 특정 기능을 위해 Operator 또는 컨트롤러가 사용하는 리소스
- finalizers: Kubernetes에서 리소스를 삭제하기 전에 리소스가 정상적으로 정리될 때까지 작업을 완료하는 데 필요한 메커니즘입니다. 리소스에 finalizers가 추가되면, 리소스가 완전히 삭제되기 전까지는 해당 리소스가 '삭제 대기 상태'에 있을 수 있습니다.
- dangling custom resource: '삭제되지 않은 상태로 남아 있는 커스텀 리소스'를 뜻합니다. 만약 finalizers가 있는 리소스를 올바르게 처리하지 않으면, 리소스가 삭제되지 않고 클러스터에 남을 수 있습니다.
-> 따라서 `make undeploy` 명령을 실행하기 전에 커스텀 리소스를 먼저 삭제하지 않으면, 리소스가 클러스터에 남아 있을 위험이 있습니다.
finalizerf랑 dangling cr 이란 걸 첨 알게됐다. 글쿤...
operator를 실제 상황에서 어떤 서비스 로직까지 담아야 할까?
Operator에 포함해야 할 서비스 로직:
Operator에 로직을 포함할 때 고려해야 할 요소는 다음과 같습니다:
1. **상태 관리(Stateful Operations)**:
- **Operator가 적합한 로직**:
- 서비스가 복잡한 상태를 가지고 있고, **외부 리소스**나 **데이터베이스**와 같은 상태 저장 시스템과 상호작용하는 경우.
- 서비스 인스턴스 간의 **종속성 관리**가 필요하거나, 특정 조건에서 상태 전환을 처리해야 할 때.
- 예를 들어, 데이터베이스 클러스터의 자동 복구, 노드 간 리더 선출, 롤링 업데이트, 리소스 확장 등은 Operator에서 처리할 수 있습니다.
2. **애플리케이션 배포 및 설정 관리**:
- **Operator가 적합한 로직**:
- 애플리케이션의 **복잡한 배포 과정**을 관리해야 할 때.
- 각 서비스마다 맞춤형 설정이나 특정 구성 변경이 필요할 때.
- 구성 파일을 자동으로 생성하거나, **애플리케이션 구성 요소 간 연결을 자동화**해야 하는 경우.
- 예시: 애플리케이션 구성이나 시크릿을 동적으로 생성하고, 이를 배포하는 과정에서 Operator가 설정 파일을 생성하고 Kubernetes 리소스를 업데이트할 수 있습니다.
3. **운영 자동화(Operational Automation)**:
- **Operator가 적합한 로직**:
- 애플리케이션을 운영하는 데 반복적인 작업을 자동화해야 할 때 (예: **백업/복구, 스케일링, 모니터링, 장애 복구** 등).
- 애플리케이션 상태를 지속적으로 모니터링하고 **셀프 힐링(self-healing)** 메커니즘을 구현해야 하는 경우.
- 예시: 데이터베이스 클러스터의 상태를 모니터링하고, 장애가 발생하면 자동으로 백업에서 복구하는 로직을 Operator에 포함할 수 있습니다.
4. **버전 관리 및 업그레이드**:
- **Operator가 적합한 로직**:
- 애플리케이션의 버전 관리와 **무중단 업그레이드**(rolling updates, canary releases 등)를 자동으로 처리해야 할 때.
- 애플리케이션 간의 버전 종속성을 관리해야 하거나, 버전 업그레이드 중 데이터 마이그레이션과 같은 복잡한 작업이 필요한 경우.
- 예시: 복잡한 업그레이드 과정 중에 마이그레이션 스크립트를 자동으로 실행하거나, 이전 버전으로 자동 롤백하는 기능을 Operator에 포함할 수 있습니다.
서비스 로직을 Operator로 포함하지 말아야 할 경우:
1. **애플리케이션의 비즈니스 로직**:
- Operator는 인프라나 운영적인 역할에 집중하고, 비즈니스 로직은 애플리케이션의 자체 코드 베이스에 포함되어야 합니다.
- 비즈니스 로직(예: 사용자 입력 처리, 데이터 검증 등)을 Operator로 분리하는 것은 일반적으로 좋지 않습니다. Operator는 주로 배포, 상태 관리, 운영 자동화를 위한 것이며, 애플리케이션의 기능적 요구 사항을 처리하는 데는 적합하지 않습니다.
2. **복잡하지 않은 상태 관리**:
- 애플리케이션이 복잡한 상태 전환이 필요 없고, 기본 Kubernetes 리소스로 상태 관리를 충분히 할 수 있다면 Operator를 사용하는 것은 과도할 수 있습니다.
결론:
- **Operator에 포함할 로직**: 상태 관리, 배포 자동화, 운영 자동화(복구, 스케일링, 백업, 복구 등), 업그레이드 관리 등 복잡한 작업을 다루는 로직.
- **서비스 자체 로직**: 비즈니스 로직, 사용자 입력 처리, 기본적인 애플리케이션 기능은 Operator 외부에서 처리.
Operator를 사용하는 이유가 인프라 자동화와 애플리케이션 상태 관리에 있다는 점을 기억하고, 애플리케이션의 비즈니스 로직은 별도로 유지하는 것이 좋습니다.
라고 하는데, 개인적인 생각으로는 실제 상황에서는...
crd 관리 일일이 하고 controller로 하면 약간 노가다다 -> operator쓰면 노가다 보다는 복잡하지만 나중에 더 편리해 진다. 이러면 선택
하지만 빠른 수정을 해야한다 -> 그냥 Controller만 사용해서 일일이 수정 해버리기?
CRD 관리에 따라 달라질 것 같긴 한데... 🤔🤔
https://overcast.blog/kubernetes-operators-in-depth-guide-with-examples-044a591b690e
Kubernetes Operators: In-Depth Guide with Examples
Kubernetes Operators represent a powerful paradigm for managing complex applications on Kubernetes. By following this guide, you’ll be…
overcast.blog
현업자의 값진 의견 ↓
시계열데이터 (prometheus) stateful 해야함. 일반적인 db, redis같은 Key-value db도 컨테이너로 띄웠을 때 볼륨공급 mounting을 안해놨으면 내부 inmemory 데이터 사라지거나 하는데, 백업 플랜, operator에서 정의한 provisioning 정책을 밀어넣으면 stateful한 친구들의 백업이나 상태유지, 혹은 snapshot같은 걸 불러오는 게 비슷한 맥락인 것 같다. ai/ml → 정확히 말하면 data 쪽인데, spark, airflow …안에서 그 내부가 왜 operator로 하는진 모르겟다!
ConfigMaps and Secrets: configuring applications
Kubernetes에서 애플리케이션을 실행할 때 구성 옵션을 애플리케이션에 전달하는 방법...을 알아보자
- 컨테이너화된 애플리케이션 구성
Kubernetes에서 실행 중인 애플리케이션에 구성 데이터를 전달하는 방법을 살펴보기 전에, 일반적으로 컨테이너화된 애플리케이션을 어떻게 구성하는지?
애플리케이션 자체에 구성을 내장하는 것을 제외하면, 새로운 애플리케이션 개발을 시작할 때 보통 명령줄 인수를 통해 애플리케이션을 구성합니다. 그러다가 설정 옵션 목록이 커지면 구성 파일로 구성을 이동할 수 있습니다.
컨테이너화된 애플리케이션에서 널리 사용되는 또 다른 구성 전달 방법은 환경 변수를 사용하는 것입니다.
애플리케이션이 구성 파일이나 명령줄 인수를 읽는 대신, 특정 환경 변수의 값을 참조하는 방식입니다.
예를 들어, 공식 MySQL 컨테이너 이미지는 `MYSQL_ROOT_PASSWORD`라는 환경 변수를 사용하여 루트 슈퍼유저 계정의 비밀번호를 설정합니다.
그렇다면 왜 환경 변수가 컨테이너에서 인기가 많을까요?
=> Docker 컨테이너 안에서 구성 파일을 사용하는 것은 다소 까다롭습니다.
구성 파일을 컨테이너 이미지에 내장해야 하거나, 파일이 포함된 볼륨을 컨테이너에 마운트해야 하기 때문입니다.
물론, 파일을 이미지에 내장하는 것은 소스 코드에 설정을 하드코딩하는 것과 비슷합니다.
구성을 변경할 때마다 이미지를 다시 빌드해야 하고, 이미지에 접근할 수 있는 모든 사람은 구성 파일을 볼 수 있어야 하며, 이는 자격 증명이나 암호화 키와 같은 정보를 안전하게 보호하지 못합니다.
볼륨을 사용하는 것이 더 나은 방법이지만, 컨테이너가 시작되기 전에 파일을 볼륨에 작성해야 한다는 점에서 여전히 불편합니다.
이전 장을 읽었다면 `gitRepo` 볼륨을 구성 소스로 사용하는 것을 생각해볼 수도 있습니다. 이는 나쁜 생각은 아닙니다.
구성 데이터를 잘 버전 관리할 수 있고, 필요 시 쉽게 구성을 롤백할 수 있기 때문입니다.
하지만 더 간단한 방법으로 구성 데이터를 상위 수준의 Kubernetes 리소스에 넣고, 다른 모든 리소스 정의와 함께 같은 Git 리포지토리 또는 파일 기반 저장소에 저장할 수 있습니다.
Kubernetes에서 구성 데이터를 저장하는 리소스를 ConfigMap이라고 합니다.
ConfigMap을 사용하든 그렇지 않든, 다음 방법들을 통해 애플리케이션을 구성할 수 있습니다:
- 컨테이너에 명령줄 인수를 전달
- 각 컨테이너에 맞는 사용자 정의 환경 변수를 설정
- 특수한 유형의 볼륨을 통해 구성 파일을 컨테이너에 마운트
대부분의 설정 옵션은 민감한 정보를 포함하지 않지만, 자격 증명, 개인 암호화 키와 같은 민감한 데이터는 특별히 보호되어야 합니다.
이를 안전하게 다루기 위해 Kubernetes는 Secret이라는 또 다른 유형의 객체를 제공합니다.
요약:
컨테이너화된 애플리케이션의 구성 방법 세 가지
1. 명령줄 인수를 통해 전달
2. 환경 변수를 통해 전달
3. 구성 파일을 마운트하여 전달
=> 컨테이너에서는 환경 변수를 주로 쓰며, Kubernetes에서는 ConfigMap을 사용해 구성 데이터를 관리할 수 있습니다. 보안이 중요한 설정(자격 증명, 암호화 키 등)은 Secret 리소스를 사용해 보호할 수 있습니다.
env
속성 = 배열 타입, 하위에 각 name과 value 리스트를 명시
env[].name
: 환경 변수 이름
env[].value
: 해당 환경 변수 값
이 때, ConfigMap Key는 DNS subdomain 상 유효한 값이어야 함
가령, alphanumeric characters, dashes, underscores, dots 등을 포함하며,
유효하지 않은 값들이 무엇인지 살펴봐야됨.
혹은 선택적으로 Key는 leading dot (ex. .local.test.com
)이 포함될 수 있습니다.
문제 : 여러 Pod에 지정하거나 정의하고자 하는 환경 변수가 많아질 수록, 한 파일에 여러 환경 변수를 관리하기 어려워 지거나 or 더 독립적으로 정의하고 싶을 때
=> ConfigMap이나 Secret의 값을 가져올 수 있음
config 개념을 좀만 더 알아보자
- ConfigMap은 키/값 쌍을 포함하는 맵이며, 값은 짧은 리터럴부터 전체 구성 파일까지 다양할 수 있습니다.
애플리케이션은 ConfigMap을 직접 읽을 필요가 없으며, 심지어 그것이 존재하는지 알 필요도 없습니다.
ConfigMap의 내용은 컨테이너에 환경 변수나 볼륨 내 파일 전달됩니다 (그림 7.2 참조).
또한 환경 변수는 명령줄 인수에서 `$(ENV_VAR)` 구문을 사용해 참조할 수 있으므로, ConfigMap 항목을 프로세스의 명령줄 인수로도 전달할 수 있습니다.
물론, 애플리케이션이 필요할 경우 Kubernetes의 REST API 엔드포인트를 통해 ConfigMap의 내용을 직접 읽을 수 있지만, 특별한 필요가 없는 한 애플리케이션이 Kubernetes에 종속되지 않도록 유지하는 것이 좋습니다.
애플리케이션이 ConfigMap을 소비하는 방법에 상관없이, 구성 데이터를 이렇게 독립된 객체로 분리함으로써
개발 환경, 테스트 환경, QA 환경, 운영 환경 등 여러 환경에 맞는 ConfigMap 매니페스트를 각각 유지할 수 있습니다.
Pods는 ConfigMap을 이름으로 참조하기 때문에, 같은 Pod 사양을 사용하면서도 각 환경에 따라 다른 구성을 사용할 수 있습니다 (그림 7.3 참조). (오 대박 이제 좀 이해가 되는 듯)
요약:
- Kubernetes의 ConfigMap은 설정 데이터를 키/값 쌍으로 저장하는 객체로, 애플리케이션에 환경 변수나 볼륨을 통해 전달
- ConfigMap을 사용하면 애플리케이션이 Kubernetes에 종속되지 않도록 하고, 여러 환경(개발, 테스트, 운영 등)에서 각기 다른 설정을 쉽게 관리할 수 있음
- Pod는 ConfigMap의 이름을 참조하여 설정을 가져오기 때문에, 같은 Pod 사양을 여러 환경에서 사용할 수 있다
개념은 그렇다고 함.
서칭하다가
https://docs.aws.amazon.com/eks/latest/userguide/auth-configmap.html
Grant IAM users access to Kubernetes with a ConfigMap - Amazon EKS
The role ARN can't include a path such as role/my-team/developers/my-role. The format of the ARN must be arn:aws:iam::111122223333:role/my-role. In this example, my-team/developers/ needs to be removed.
docs.aws.amazon.com
EKS cluster에 IAM규칙 configmap으로 넣는 게 있길래 흥미~ 로워보여서 가져옴
Add IAM Role to Kubernetes Configmap | Online Help
docs.fortinet.com
Kubernetes Configmap에 IAM Role 추가하는거라는데 근데 무슨 사이트인진 잘 모르겠지만 절차 1번 2번만 보면 platform engineering을 구축해 놓은 것 같은 느낌 ㅋㅅㅋ
From the kubernetes community on Reddit
Explore this post and more from the kubernetes community
www.reddit.com
그냥 config file을 넣는것과 configmap을 쓰는 것에 대한 사례와 차이에 대한 이야기가 있었는데 (생각못해봤다)
- If it's something you can change without having to rebuild the container put it in a configmap. If it's something that's tied to a specific version of your application (like database migrations) put it in the container.
라는 의견...
ConfigMap과 컨테이너 내부에 설정 파일을 직접 넣는 것의 차이는 **변경 가능성**과 **애플리케이션 버전 관리**에 있습니다. 이를 좀 더 구체적으로 설명하면 다음과 같습니다:
### ConfigMap 사용:
**ConfigMap**은 Kubernetes에서 설정 데이터를 관리하기 위한 리소스로, 애플리케이션 실행 시 외부에서 설정 값을 전달할 수 있는 방법을 제공합니다.
- **변경 가능성**: ConfigMap을 사용하면 애플리케이션을 **재배포하지 않고**도 설정을 쉽게 변경할 수 있습니다. 설정이 자주 변경되거나, 특정 환경(개발, 테스트, 운영)에 맞춰 수정이 필요한 경우, ConfigMap에 저장된 설정을 업데이트하면 애플리케이션은 자동으로 그 변경된 값을 사용할 수 있습니다.
- 예시: **API 엔드포인트**, **로그 레벨**, **외부 서비스의 URL**과 같은 설정은 환경마다 다를 수 있으므로, ConfigMap으로 관리하면 환경별로 다른 값을 쉽게 제공할 수 있습니다.
- **유연성**: ConfigMap은 여러 환경(예: 개발, QA, 프로덕션)에 맞춰 다른 설정 파일을 적용할 수 있어, 하나의 Pod 템플릿으로도 다양한 설정을 관리할 수 있습니다.
- **보안**: ConfigMap 자체는 암호화되지 않으므로, **민감한 정보**(예: 데이터베이스 비밀번호, API 키)는 ConfigMap 대신 **Secret**으로 관리하는 것이 더 적합합니다.
### 설정 파일을 컨테이너 이미지에 직접 포함:
설정 파일을 애플리케이션이 포함된 **컨테이너 이미지**에 직접 넣는 것은 설정 값이 애플리케이션의 특정 버전과 강하게 결합되어 있음을 의미합니다.
- **버전 관리**: 데이터베이스 마이그레이션이나 특정 버전에 맞춘 설정은 애플리케이션의 동작에 필수적이므로, 컨테이너와 함께 버전 관리가 되어야 합니다. 이 경우, 설정 파일을 이미지 내부에 넣어야 합니다. 이렇게 하면 애플리케이션 버전과 그 설정이 항상 일관되게 관리됩니다.
- 예시: **데이터베이스 마이그레이션 스크립트**는 애플리케이션 버전과 밀접하게 연관되어 있어야 하므로, 컨테이너 이미지에 포함시켜야 합니다. 이는 애플리케이션의 특정 버전에 맞는 설정 파일을 보장할 수 있기 때문입니다.
- **재빌드 필요**: 설정 파일을 이미지에 직접 포함하면 설정을 변경할 때마다 컨테이너 이미지를 다시 빌드하고 배포해야 하므로, **설정이 자주 바뀌지 않는 경우**에 적합합니다.
### 정리:
- **ConfigMap을 사용하는 경우**: 설정이 자주 바뀌거나, 환경별로 달라야 하는 경우. 즉, 애플리케이션을 다시 빌드하지 않고도 설정을 업데이트할 수 있어야 할 때 적합.
- **컨테이너 내부에 설정 파일을 포함하는 경우**: 설정이 애플리케이션 버전에 종속적이거나, 한 번 설정되면 변경할 필요가 없는 경우.
참고
'클라우드 > DevOps' 카테고리의 다른 글
Kubevirt with ansible, Octopus deploy란? (8) | 2024.10.09 |
---|---|
[K8s deepdive] Label 개념, label selector와 차이, auto-labeling with kyverno (7) | 2024.10.09 |
[K8s deepdive] Operator 구축할 때 어떤 Framework를 선택하는 게 좋을까 (3) | 2024.09.25 |
Karpenter note (0) | 2024.09.25 |
[K8s deepdive] Controller pattern과 operator (2) | 2024.09.18 |