728x90
반응형
1. K8S Controller란?
- 쿠버네티스에서 클러스터의 상태를 관찰 한 다음, 필요한 경우에 생성 또는 변경을 요청하는 '컨트롤 루프'
- 컨트롤 루프란?
- Control plane은 종료되지 않는 루프(무한루프)를 실행하면서 상태를 제어
- 컨트롤 루프는 크게 3가지 동작 (모니터링, 상태 차이 발견, 액션)
- 위 3가지 동작을 통해 현재 상태를 정의, 의도한 상태와 같아지도록 동작하는 역할을 한다.
- Controller의 종류에는 쿠버네티스에서 자체적으로 제공되는 컨트롤러와 기능 개발을 통한 커스텀 컨트롤러 2가지 방식이 있다.
- K8S에서 기본적으로 제공되는 컨트롤러는 Control plane에서 동작한다.
- 다음과 같이 자체적으로 제공되는 컨트롤러와 오퍼레이터에 의한 컨트롤러에 의한 컨트롤러의 아키텍쳐를 볼 수 있다. 참조 Docs
- 위 그림과 같이 자체적으로 제공되는 컨트롤러는 Control plane에서 실행되지만 오퍼레이터에 의한 컨트롤러는 Worker node에서 실행된다.
- control plane의 controller manager는 모든 컨트롤러를 관리할 수 있으므로, Custom contoller(오퍼레이터 컨트롤러)또한 controller manager의 컨트롤 루프에 추가된다.
- 즉, Control plane의 controller manager가 실행되면 컨트롤 루프가 실행되고 여기서는 control plane에 있는 표준 컨트롤러와 worker node에 있는 Custom contoller(오퍼레이터 컨트롤러)를 모두 실행시킨다.
2. Operator란?
- 오퍼레이터 패턴에 사용되는 쿠버네티스 익스텐션
- 오퍼레이터는 쿠버네티스 원칙, 특히 컨트롤 루프를 따른다.
- 오퍼레이터 패턴은 K8S 자체가 제공하는 기능이 아닌 운영을 하면서 사용자가 작업을 자동화하기 위한 방법이다.
- 즉, 오퍼레이터(extension)은 쿠버네티스 동작을 이용하여 애플리케이션 운영을 자동화하는 것이다.
- ex) 프로메테우스 오퍼레이터
- 프로메테우스는 기본적으로 설정(rule)을 configmap에 설정하고 Pod를 재시작하며 사용한다.
- 위와 같이 사용하게 되면 운영환경에서 운영이 번거롭기 때문에 오퍼레이터를 사용하게 되면 설정(rule)을 쿠버네티스 CRD로 정의하고 오퍼레이터가 설정 적용을 자동화하여 관리할 수 있다.
3. K8S CRD와 Operator의 관계
- K9S CRD(CustomResourceDefinitions)를 이용하여 애플리케이션의 의도한 상태를 정의하며 Operator Custom Controller가 돌면서 현재 상태가 정의한 의도한 상태와 일치하는지 확인하며 일치하도록 동작한다.
4. Mysql Operator 실습
4-1) MySQL Operator for K8S
# helm repo 추가 및 업데이트
$ helm repo add mysql-operator https://mysql.github.io/mysql-operator/
$ helm repo update
# elm을 통해 패키지를 배포
$ helm install mysql-operator mysql-operator/mysql-operator --namespace mysql-operator --create-namespace --version 2.1.1
# maifest 출력
$ helm get manifest mysql-operator -n mysql-operator
# 설치 확인
$ kubectl get deploy,pod -n mysql-operator
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mysql-operator 1/1 1 1 50
NAME READY STATUS RESTARTS AGE
pod/mysql-operator-d6ff8f8f6-as4fa 1/1 Running 0 100s
# CRD 확인
$ kubectl get crd | egrep 'mysql|zalando'
clusterkopfpeerings.zalando.org 2023-10-28T19:25:20Z
innodbclusters.mysql.oracle.com 2023-10-28T19:25:20Z
kopfpeerings.zalando.org 2023-10-28T19:25:20Z
mysqlbackups.mysql.oracle.com 2023-10-28T19:25:20Z
4-2) InnoDB 클러스터(Mysql DB) 배포
- MySQL 서버 자체적으로 페일오버 Failover 를 처리하는 기능을 제공하지 않으므로 사용자는 장애가 발생했을 때 레플리카 서버가 새로운 소스 서버가 될 수 있도록 일련의 작업들을 수행해야 한다.
- 즉 레플리카 서버에 설정된 읽기 모드를 해제해야 하며, 스플릿 브레인 Split-Brain 현상을 방지하기 위해 장애가 발생한 소스 서버에서 데이터 변경을 실행하지 못하도록 해야 한다.
- 그리고 애플리케이션 서버는 새로운 소스 서버를 바라보도록 커넥션 설정을 변경해야 한다.
- 이러한 작업들은 모두 수동으로 처리할 수 밖에 없으며 완료되기까지 적지 않은 시간이 소요된다.
- MySQL 5.7.17 버전에서 빌트인 형태의 HA 솔루션인 InnnDB 클러스터가 도입되면서 사용자는 좀 더 편리하게 고가용성을 실현할 수 있게 됐다.
- Helm chart(mysql-innodbcluster) 배포
# (참고) Helm Chart Default Values 확인
$ helm show values mysql-operator/mysql-innodbcluster
# 파라미터 파일 생성
$ cat <<EOT> mycnf-values.yaml
credentials:
root:
password: leejunho
serverConfig:
mycnf: |
[mysqld]
max_connections=300
default_authentication_plugin=mysql_native_password
tls:
useSelfSigned: true
EOT
# 차트 설치(기본값) : root 사용자(root), 호스트(%), 서버인스턴스(파드 3개), 라우터인스턴스(파드 1개), serverVersion(8.0.35)
# root 사용자 암호(leejunho), tls.useSelfSigned(사용), 네임스페이스 생성 및 적용(mysql-cluster)
$ helm install mycluster mysql-operator/mysql-innodbcluster --namespace mysql-cluster --version 2.1.1 -f mycnf-values.yaml --create-namespace
$ helm get values mycluster -n mysql-cluster
$ helm get manifest mycluster -n mysql-cluster
- helm chart 로 배포된 리소스 확인
$ watch kubectl get innodbcluster,sts,pod,pvc,svc -n mysql-cluster
NAME STATUS ONLINE INSTANCES ROUTERS AGE
innodbcluster.mysql.oracle.com/mycluster ONLINE 3 3 1 1m55s
NAME READY AGE
statefulset.apps/mycluster 3/3 1m55s
NAME READY STATUS RESTARTS AGE
pod/mycluster-0 2/2 Running 0 1m55s
pod/mycluster-1 2/2 Running 0 1m55s
pod/mycluster-2 2/2 Running 0 1m55s
pod/mycluster-router-65469cb756-2xcm8 1/1 Running 0 65s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/datadir-mycluster-0 Bound pvc-b3242d6f-kuh0-832d-129f-23cc034f09c3 2Gi RWO gp2 1m55s
persistentvolumeclaim/datadir-mycluster-1 Bound pvc-20dd0e4b-9cb0-4c9c-b102-a7fae3715687 2Gi RWO gp2 1m55s
persistentvolumeclaim/datadir-mycluster-2 Bound pvc-734a0a91-0a27-82c2-befa-b74eb4b97c19 2Gi RWO gp2 1m55s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/mycluster ClusterIP 10.100.64.124 <none> 3306/TCP,33060/TCP,6446/TCP,6448/TCP,6447/TCP,6449/TCP,8443/TCP 1m55s
service/mycluster-instances ClusterIP None <none> 3306/TCP,33060/TCP,33061/TCP 1m55s
- PV 디스크 통계 확인
$ kubectl df-pv
PV NAME PVC NAME NAMESPACE NODE NAME POD NAME VOLUME MOUNT NAME SIZE USED AVAILABLE %USED IUSED IFREE %IUSED
pvc-b3242d6f-kuh0-832d-129f-23cc034f09c3 datadir-mycluster-0 mysql-cluster ip-192-168-3-11.ap-northeast-2.compute.internal mycluster-0 datadir 1945Mi 198Mi 1731Mi 10.19 219 130853 0.17
pvc-20dd0e4b-9cb0-4c9c-b102-a7fae3715687 datadir-mycluster-1 mysql-cluster ip-192-168-2-33.ap-northeast-2.compute.internal mycluster-1 datadir 1945Mi 198Mi 1731Mi 10.19 219 130853 0.17
pvc-734a0a91-0a27-82c2-befa-b74eb4b97c19 datadir-mycluster-2 mysql-cluster ip-192-168-1-214.ap-northeast-2.compute.internal mycluster-2 datadir 1945Mi 198Mi 1731Mi 10.19 219 130853 0.17
- 프로브, Service, deploy, endpoint 확인
## 프로브 확인(Readiness, Liveness, Startup)
$ kubectl describe pod -n mysql-cluster mycluster-0 | egrep 'Liveness|Readiness:|Startup'
## 서버인스턴스 각각 접속을 위한 헤드리스 Headless 서비스 확인
$ kubectl describe svc -n mysql-cluster mycluster-instances
$ kubectl get svc,ep -n mysql-cluster mycluster-instances
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mycluster-instances ClusterIP None <none> 3306/TCP,33060/TCP,33061/TCP 19m
## 라우터인스턴스(디플로이먼트) 확인 : 1대의 파드 생성 확인
$ kubectl get deploy -n mysql-cluster;kubectl get pod -n mysql-cluster -l app.kubernetes.io/component=router
## 라우터인스턴스 접속을 위한 서비스(ClusterIP) 확인
$ kubectl get svc,ep -n mysql-cluster mycluster
# max_connections 설정 값 확인 : MySQL 라우터를 통한 MySQL 파드 접속 >> Helm 차트 설치 시 파라미터러 기본값(151 -> 300)을 변경함
$ MIC=mycluster.mysql-cluster.svc.cluster.local
$ echo "export MIC=mycluster.mysql-cluster.svc.cluster.local" >> /etc/profile
$ kubectl exec -it -n mysql-operator deploy/mysql-operator -- mysqlsh mysqlx://root@$MIC --password=sakila --sqlx --execute="SHOW VARIABLES LIKE 'max_connections';"
4-3) MySQL 서버 접속 방법
- Headless 서비스를 통해 개별 MySQL 서버(파드)로 직접 접속이 가능하다.
# MySQL 라우터 접속을 위한 서비스 정보 확인 : 실습 환경은 Cluster-IP Type
$ kubectl get svc -n mysql-cluster mycluster
# MySQL 서버(파드) 접속을 위한 서비스 정보 확인 : Headless 서비스
$ kubectl get svc -n mysql-cluster mycluster-instances
$ kubectl get pod -n mysql-cluster -l app.kubernetes.io/component=database -owide
# netshoot 파드에 zsh 접속해서 DNS 쿼리 수행
$ kubectl run -it --rm netdebug --image=nicolaka/netshoot --restart=Never -- zsh
-------
# dig 툴로 도메인 질의 : <서비스명>.<네임스페이스>.svc 혹은 <서비스명>.<네임스페이스>.svc.cluster.local
# 아래 도메인 주소로 접근 시 MySQL 라우터를 통해서 MySQL 서버(파드)로 접속됨
$ dig mycluster.mysql-cluster.svc +search +short
$ dig mycluster.mysql-cluster.svc.cluster.local +search +short
# Headless 서비스 주소로 개별 MySQL 서버(파드)로 직접 접속을 위한 DNS 쿼리
$ dig mycluster-instances.mysql-cluster.svc +search
$ dig mycluster-instances.mysql-cluster.svc.cluster.local +short
# MySQL 서버(파드)마다 고유한 SRV 레코드가 있고, 해당 도메인 주소로 접속 시 MySQL 라우터를 경유하지 않고 지정된 MySQL 서버(파드)로 접속됨
$ dig mycluster-instances.mysql-cluster.svc.cluster.local SRV
# 접속 주소 변수 지정
$ MIC=mycluster.mysql-cluster.svc.cluster.local
$ MDB1=mycluster-0.mycluster-instances.mysql-cluster.svc.cluster.local
$ MDB2=mycluster-1.mycluster-instances.mysql-cluster.svc.cluster.local
$ MDB3=mycluster-2.mycluster-instances.mysql-cluster.svc.cluster.local
# MySQL 라우터를 통한 MySQL 파드 접속
# kubectl exec -it -n mysql-operator deploy/mysql-operator -- mysqlsh mysqlx://root@$MIC --password=sakila
$ kubectl exec -it -n mysql-operator deploy/mysql-operator -- mysqlsh mysqlx://root@$MIC --password=sakila --sqlx --execute='show databases;'
...(생략)...
$ kubectl exec -it -n mysql-operator deploy/mysql-operator -- mysqlsh mysqlx://root@$MIC --password=sakila --sqlx --execute="SHOW VARIABLES LIKE 'max_connections';"
Variable_name Value
max_connections 151
# 개별 MySQL 파드 접속 : 헤드리스 서비스
$ kubectl exec -it -n mysql-operator deploy/mysql-operator -- mysqlsh mysqlx://root@$MDB1 --password=sakila --sqlx --execute='SELECT @@hostname;'
mycluster-0
$ kubectl exec -it -n mysql-operator deploy/mysql-operator -- mysqlsh mysqlx://root@$MDB2 --password=sakila --sqlx --execute='SELECT @@hostname;'
mycluster-1
$ kubectl exec -it -n mysql-operator deploy/mysql-operator -- mysqlsh mysqlx://root@$MDB3 --password=sakila --sqlx --execute='SELECT @@hostname;'
mycluster-2
728x90
반응형
'K8S Operator' 카테고리의 다른 글
[K8S Operator] Vault Secrets Operator(VSO) (1) | 2023.11.26 |
---|---|
[K8S Operator] Kafka & Strimzi Operator (1) | 2023.11.18 |
[K8S Operator] Percona Operator for MongoDB (1) | 2023.11.12 |
[K8S Operator] Cloud Native PostgreSQL 오퍼레이터 (0) | 2023.11.04 |