[doik2] 2주차 - 오퍼레이터 & MySQL 오퍼레이터 (작성중)
Published: 2023-10-28 11:43:08

### Overview

CloudNet@ 에서 운영하고 있는 DOIK (Database Operator In Kubernetes) 2주차 스터디에서 MySQL을 쿠버네티스에서 운영하는 실습을 진행하고, MySQL과 내부 엔진인 InnoDB에 대해서 더 학습한 내용을 정리하였습니다.

### InnoDB 란
MySQL 내부에서 구동되는 스토리지 엔진은 대표적으로 MyISAM 과 InnoDB가 있습니다. InnoDB는 주로 대용량의 데이터를 다루는데 효율적으로, MyISAM 은 ReadOnly 기능이 많을 수록 효율적이라고 한다.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v06nirliwnt3qupj9jnw.png)

InnoDB는 인메모리 구조로 Buffer Pool 이라는 저장 영역을 관리하며, 이 저장영역에 데이터와 인덱스를 담는다.


#### Buffer Pool

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gjp1z3a7r724pxseq1bg.png)

- 버퍼풀은 메모리 상에서 데이터와 인덱싱된 데이터가 캐싱된 영역
- 따라서 자주 접근되는 데이터를 버퍼풀에 올려 전체적인 작업속도를 향상시킴.
- MySQL 서버는 최대로 메모리의 80% 까지 InnoDB를 위한 버퍼풀을 할당하여 사용한다.


#### Tablespaces

**시스템 테이블 스페이스**란, 특정 테이블이 아닌 데이터베이스 시스템 전체와 관련된 일반 정보를 저장하는 경우 InnoDB가 쓰는 특정 파일을 시스템 테이블 스페이스라고 함.
```
$ echo datadir
$ innodb_data_home_dir
시스템 변수 내의 ibdata1 파일
```

**File-Per-Table 테이블 스페이스**란, InnoDB 스토리지 엔진을 사용하여 테이블을 만들면 해당 테이블에 기록된 데이터가 저장되는 파일 시스템내 파일 정보.
- 데이터와 인덱스 모두가 포함됨.
- `innodb_file_per_table=On` 으로 설정하면 InnoDB는 테이블 하나당 테이블스페이스 파일 하나를 사용함.
- `innodb_file_per_table=Off` 으로 설정하면 모든 테이블을 InnoDB 시스템 테이블 스페이스에 저장함.

```
테이블 생성시 데이터 디렉터리 레이블을 사용하여 경로 입력

CREATE TABLE test.t1 (
   id INT PRIMARY KEY AUTO_INCREMENT,
   name VARCHAR(50)
) ENGINE=InnoDB
DATA DIRECTORY = "/data/contact";

위와 같이 생성한 테이블은 아래 디렉터리 위치에서 테이블 스페이스 파일을 찾을 수 있음.
$ ls -al /data/contact/test


```

_c.f. InnoDB의 전체적인 성능 향상을 위해 필요한 몇가지 설정._
- 데이터베이스 서버 내 최소 프로세스를 위한 메모리를 제외하고 나머지 메모리를 InnoDB를 위해 사용하기
  - https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-pool-resize.html
- 곧 요청될 것으로 예측된 데이터를 미리 읽어오는 작업 설정하기
  - https://dev.mysql.com/doc/refman/8.0/en/innodb-performance-read_ahead.html


### InnoDB Cluster 란
MySQL을 위한 고가용성 솔루션

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vatpxj9ueasxg3vjku0r.png)

- MySQL Shell 에 포함된 AdminAPI를 통해 최소 3개의 MySQL 서버 인스턴스를 그룹으로 구성하여 InnoDB 클러스터로 동작하도록 함.

#### InnoDB Cluster - Group Replication
- InnoDB 클러스터 내에서 서버 인스턴스간 데이터를 복제하는 메커니즘
- 그룹 커뮤니케이션 시스템 프로토콜에 의해 구동
  - 이 프로토콜은 장애 감지 매커니즘, 그룹 간 멤버 관리, 메시지 전달 기능등을 제공함.
- 시스템이 변경될 때마다 여러 서버가 시스템 상태와 데이터에 대해 동의 및 합의하는 식으로 데이터를 일치화 및 복제

#### InnoDB Cluster - MySQL Router
- 애플리케이션과 MySQL 서버간 라우팅을 제공하는 경량 미들웨어
- InnoDB 클러스터와 함께 사용할 경우 프록시의 역할을 하며 데이터 요청을 클러스터 인스턴스 중 하나에 매핑하는 역할을 함


### 실습 01 - MySQL Operator 배포하기

아래 명령을 통해 현재 General Availability 버전인 MySQL Operator 를 설치한다.
```
$ helm repo add mysql-operator https://mysql.github.io/mysql-operator/
$ helm repo update
$ helm install mysql-operator mysql-operator/mysql-operator --namespace mysql-operator --create-namespace --version 2.1.1

helm install mysql-operator mysql-operator/mysql-operator --namespace mysql-operator --create-namespace --

```

**설치된 리소스 확인**

```
$ kubectl get deploy,pod -n mysql-operator

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/mysql-operator   1/1     1            1           3m48s

NAME                                  READY   STATUS    RESTARTS   AGE
pod/mysql-operator-6f4f77959f-qfqv6   1/1     Running   0          3m48s
```

```
$ kubectl get crd | egrep 'mysql|zalando'

clusterkopfpeerings.zalando.org              2023-10-29T07:43:06Z
innodbclusters.mysql.oracle.com              2023-10-29T07:43:06Z
kopfpeerings.zalando.org                     2023-10-29T07:43:06Z
mysqlbackups.mysql.oracle.com                2023-10-29T07:43:06Z
```

설치된 리소스를 확인해보면 MySQL Operator ( 지난주차에서 학습한 Operator 패턴의 controller 역할을 하는) Deployment 와 커스텀 리소스들이 배포된 것을 확인할 수 있다.

### 실습 02 - MySQL InnoDB Cluster 설치

다음은 helm 차트를 통해 MySQL Cluster 를 쿠버네티스에 배포한다.

MySQL Cluster의 설정을 변경하기 위한 Helm Value 파일을 생성한다.
```
cat <<EOT> mycnf-values.yaml
credentials:
  root:
    password: sakila
serverConfig:
  mycnf: |
    [mysqld]
     max_connections=300
     default_authentication_plugin=mysql_native_password
tls:
  useSelfSigned: true
EOT
```

위에서 생성한 Value 파일과 함께 아래 커맨드를 통해 helm 차트를 배포한다.
```
$ helm install mycluster mysql-operator/mysql-innodbcluster --namespace mysql-cluster -f mycnf-values.yaml --create-namespace
```

### 실습 03 - MySQL 서버 접속하기

MySQL Cluster는 헤드리스 서비스로 배포가 되었기 때문에 서비스 주소는 아래와 같다.
```
$ 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
```

3개의 MySQL 서버가 배포되어 있고 이를 각각 접속하기 위해 mysqlsh Pod를 설치한다.
```
$ kubectl exec -it -n mysql-operator deploy/mysql-operator -- mysqlsh mysqlx://root@$MIC --password=sakila --sqlx --execute="SHOW VARIABLES LIKE 'max_connections';"
```