..

DOIK) keda를 이용한 mysql server 자동 확장 체험기

지난 네트워크 스터디에 이어 데이터베이스 오퍼레이터 스터디도 참여하게 되었다. 오퍼레이터 자체를 처음 접해서 헷갈리는 것들이 있지만… 그럼에도 중간과제는 찾아온다..! 2주차에서 알게된 mysql operator와 3주차에 알게된 KEDA를 사용하여 mysql 서버 파드를 자동확장 테스트를 하였다.

사용할 mysql operator와 keda를 간략하게 소개하자면,

mysql operator는 쿠버네티스 클러스터 내 mysql innoDB 클러스터를 관리해주는 operator 이다. 🔗

# mysql operator와 mysql-innodbcluster 설치
> helm repo add mysql-operator https://mysql.github.io/mysql-operator/
> helm install mysql-operator mysql-operator/mysql-operator --namespace mysql-operator --create-namespace
> helm install mycluster mysql-operator/mysql-innodbcluster --set credentials.root.password='sakila' --set tls.useSelfSigned=true --namespace mysql-cluster --create-namespace

1-2

mysql-operator 네임스페이스에는 deployment로 배포된 InnoDB 클러스터를 관리해주는 mysql-operator가 있다.

1-3

mysql-cluster 네임스페이스에 있는 리소스들이 InnoDB 클러스터 구성한다.

  • statefulset/mycluster : mysql server instance
  • deployment/mycluster-router : mysql router(proxy 역할)
  • service/mycluster : mysql router로 접근됨
  • service/mycluster-instances : 특정 서버 접근 시 사용
  • configmap/mycluster-initconf : mysql config

KEDA(Kubernetes-based Event Driven Autoscaler)는 특정 이벤트 기반으로 자동 확장해주는 도구이다. 🔗

> helm repo add kedacore https://kedacore.github.io/charts
> helm install keda kedacore/keda --version 2.7.2 --namespace keda --create-namespace

2-2

  • deployment/keda-operator : agent 역할
  • deployment/keda-operator-metrics-apiserver : metric server 역할

테스트

먼저, 테스트를 하기 위해 클라이언트 설치 및 데이터베이스를 생성해줬다.

# mysql client 설치
> apt install mariadb-client -y

# mysql 접근시 사용할 svc ip변수지정
> MYSQLIP=$(kubectl get svc -n mysql-cluster mycluster -o jsonpath={.spec.clusterIP})

# 데이터베이스 및 테이블 생성
> mysql -h $MYSQLIP -uroot -psakila <<EOF
  CREATE DATABASE testdb;
  CREATE TABLE testdb.testtable (testcolumn1 INT PRIMARY KEY,testcolumn2 TEXT NOT NULL);
  INSERT INTO testdb.testtable VALUES (1, 'none');
 EOF

3-1

데이터베이스가 생성되고 넣은 값이 잘 들어갔는지 확인

keda.yaml

keda를 사용하기 위해 확장할 개체를 정의해준다. 🔗


apiVersion: v1
kind: Secret
metadata:
  name: mysql-secrets
type: Opaque
# base64로 인코딩하여야함
# $echo -n 'value' | base64

data:
  mysql_host: bXljbHVzdGVyLWluc3RhbmNlcy5teXNxbC1jbHVzdGVyLnN2Yy5jbHVzdGVyLmxvY2Fs
  # mycluster-instances svc domain
  mysql_port: MzMwNg==
  mysql_db: dGVzdGRi
  mysql_user: cm9vdA==
  mysql_password: c2FraWxh

---

apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
  name: keda-trigger-auth-mysql-secret
spec:
  secretTargetRef:
  # 자격증명을 위해 위에서 만들었던 secret 내용들을 넣어줌
  # https://keda.sh/docs/1.4/concepts/authentication/#re-use-credentials-and-delegate-auth-with-triggerauthentication

  # parameter 참고
  # https://keda.sh/docs/2.7/scalers/mysql/

  - parameter: host
    name: mysql-secrets
    key: mysql_host
  - parameter: port
    name: mysql-secrets
    key: mysql_port
  - parameter: dbName
    name: mysql-secrets
    key: mysql_db
  - parameter: username
    name: mysql-secrets
    key: mysql_user
  - parameter: password
    name: mysql-secrets
    key: mysql_password

---

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: mysql-scaledobject
spec:
# 다른 옵션 참고
# https://keda.sh/docs/2.7/concepts/scaling-deployments/

  pollingInterval: 1                    # default 30s
  cooldownPeriod:  10                   # default 300s
  minReplicaCount: 1                    # default 0
  maxReplicaCount: 10                   # default 100
  scaleTargetRef:
    apiVersion: apps/v1   
    kind: StatefulSet                   # default Deployment
    name: mycluster 
    envSourceContainerName: mysql       
    # 미지정시 첫번째 컨테이너 속성을 가져옴 
    # .spec.template.spec.containers[0]
  advanced:                                         
    restoreToOriginalReplicaCount: true # default false
    # ScaledObject 삭제 시 늘어난 복제 수를 유지하지 않고 기존에 지정한 복제 수로 돌아옴    
    horizontalPodAutoscalerConfig:                  
      behavior:                                      
        scaleDown:
          stabilizationWindowSeconds: 300           
          policies:
          - type: Percent
            value: 100
            periodSeconds: 15
  triggers:
  - type: mysql
    metadata:
      # 임계값지정
      queryValue: "3"                  # 단일 숫자여야함
      query: "SELECT CEIL(COUNT(*) / 6) FROM testdb.testtable WHERE testcolumn2='none'"  
    authenticationRef:
      name: keda-trigger-auth-mysql-secret

3-2

배포 후 describe으로 리소스 이벤트를 확인해보면 성공적으로 배포된 것을 확인 할 수 있다.

📈 자동 확장 테스트

# 데이터 추가
> for ((i=1; i<=100; i++)); do mysql -h $MYSQLIP -uroot -psakila -e "SELECT @@HOSTNAME;INSERT INTO testdb.testtable VALUES ($i, 'none');";echo; done

# sql server pod 증가 모니터링
> watch -n 1 -d "kubectl get pod -o wide -n mysql-cluster"

4-1

4-2

100개의 데이터를 넣으면 mycluster-5까지, 500까지 늘렸을 때에는 9까지 파드가 생성되는 것을 확인할 수 있었다.

📉 자동 축소 테스트

# 데이터 삭제
> for ((i=101; i<=500; i++)); do mysql -h $MYSQLIP -uroot -psakila -e "SELECT @@HOSTNAME;INSERT INTO testdb.testtable VALUES ($i, 'none');";echo; done

# sql server pod 감소 모니터링
> watch -n 1 -d "kubectl get pod -o wide -n mysql-cluster"

4-3

4-4

400개를 먼저 지워봤을 때 증가 테스트 시 늘어난만큼 삭제되는 것을 확인할 수 있었다. 나머지 데이터들도 2개 빼고 모두 삭제 시 하나의 파드를 제외하고 모든 파드가 삭제되었다.

🚧 해당 테스트를 진행하며 마주했던 오류들

오류1 Warning KEDAScalerFailed 6s (x12 over 16s) keda-operator error resolving secrets for ScaleTarget: couldn’t find container with name .spec.template.spec.containers[0] on Target object

▶️ ScaledObject를 정의하는 파일에서 spec.scaleTargetRef.envSourceContainerName에 컨테이너 명을 적어야한다. 이런식으로 *spec.template.spec.containers[0] 적어서 발생한 오류였다.

오류2 Warning KEDAScalerFailed 0s (x10 over 3s) keda-operator error establishing MySQL connection: dial 10.200.1.135: unknown network 10.200.1.135

▶️ 처음에 Secret 파일에서 data.mysql_conn_str으로 mycluster svc ip를 넣었었는데 오류가 발생하여 router가 아닌 서버에 직접 연결되는 mycluster-instances svc를 host에 넣었다.


참고