카테고리 없음
mariadb + maxscale
자바바라
2024. 11. 6. 23:28
Kubernetes 환경에서 MariaDB Replication과 MaxScale을 설정하기 위해 필요한 단계와 리소스 정의를 설명하겠습니다. 이 예제는 `kind` 클러스터에서 진행됩니다.
### 1. Kind 클러스터 생성
먼저, Kind 클러스터를 생성한 후 클러스터에 접속합니다.
kind create cluster
kubectl cluster-info
### 2. MariaDB StatefulSets 생성
MariaDB의 복제를 위해 StatefulSet을 사용하여 마스터와 슬레이브를 생성합니다. 아래는 `mariadb-master`와 `mariadb-slave`라는 StatefulSet을 정의하는 YAML 파일입니다.
#### 2.1. MariaDB ConfigMap 및 Secrets 생성
MariaDB의 환경 변수를 관리할 ConfigMap과 Secrets를 생성합니다.
**mariadb-config.yaml**
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mariadb-config
data:
my.cnf: |
[mysqld]
bind-address=0.0.0.0
log_bin=mysql-bin
binlog_do_db=mydb
```
**mariadb-secrets.yaml**
```yaml
apiVersion: v1
kind: Secret
metadata:
name: mariadb-secret
type: Opaque
data:
root-password: <BASE64_ENCODED_ROOT_PASSWORD>
replication-password: <BASE64_ENCODED_REPLICATION_PASSWORD>
```
`<BASE64_ENCODED_ROOT_PASSWORD>` 및 `<BASE64_ENCODED_REPLICATION_PASSWORD>`는 각각의 비밀번호를 Base64로 인코딩하여 넣습니다. 예를 들어, `mypassword`의 경우:
echo -n "mypassword" | base64
#### 2.2. MariaDB Master StatefulSet 생성
**mariadb-master.yaml**
```yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mariadb-master
spec:
serviceName: "mariadb-master"
replicas: 1
selector:
matchLabels:
app: mariadb
role: master
template:
metadata:
labels:
app: mariadb
role: master
spec:
containers:
- name: mariadb
image: mariadb:10.5
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mariadb-secret
key: root-password
- name: MYSQL_DATABASE
value: mydb
- name: MYSQL_USER
value: user
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mariadb-secret
key: replication-password
- name: MYSQL_REPLICATION_USER
value: repl
- name: MYSQL_REPLICATION_PASSWORD
valueFrom:
secretKeyRef:
name: mariadb-secret
key: replication-password
ports:
- containerPort: 3306
volumeMounts:
- name: mariadb-storage
mountPath: /var/lib/mysql
volumes:
- name: mariadb-storage
persistentVolumeClaim:
claimName: mariadb-master-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mariadb-master-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
```
#### 2.3. MariaDB Slave StatefulSet 생성
**mariadb-slave.yaml**
```yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mariadb-slave
spec:
serviceName: "mariadb-slave"
replicas: 2
selector:
matchLabels:
app: mariadb
role: slave
template:
metadata:
labels:
app: mariadb
role: slave
spec:
containers:
- name: mariadb
image: mariadb:10.5
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mariadb-secret
key: root-password
- name: MYSQL_REPLICATION_USER
value: repl
- name: MYSQL_REPLICATION_PASSWORD
valueFrom:
secretKeyRef:
name: mariadb-secret
key: replication-password
- name: MYSQL_MASTER_HOST
value: mariadb-master
ports:
- containerPort: 3306
volumeMounts:
- name: mariadb-storage
mountPath: /var/lib/mysql
volumes:
- name: mariadb-storage
persistentVolumeClaim:
claimName: mariadb-slave-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mariadb-slave-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
```
### 3. MaxScale 설정
MaxScale은 MariaDB 클러스터 앞에 배치되어 로드 밸런싱 및 SQL 라우팅을 제공하는 프록시입니다.
**maxscale.yaml**
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: maxscale
spec:
replicas: 1
selector:
matchLabels:
app: maxscale
template:
metadata:
labels:
app: maxscale
spec:
containers:
- name: maxscale
image: mariadb/maxscale:2.5
ports:
- containerPort: 3306
volumeMounts:
- name: maxscale-config
mountPath: /etc/maxscale.cnf
subPath: maxscale.cnf
volumes:
- name: maxscale-config
configMap:
name: maxscale-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: maxscale-config
data:
maxscale.cnf: |
[maxscale]
threads=4
[MariaDB Monitor]
type=monitor
module=mariadbmon
servers=mariadb-master,mariadb-slave
user=repl
password=<REPLICATION_PASSWORD>
monitor_interval=10000
[Read-Write Service]
type=service
router=readwritesplit
servers=mariadb-master,mariadb-slave
user=user
password=<MYSQL_PASSWORD>
[Read-Only Service]
type=service
router=readconcurrency
servers=mariadb-slave
user=user
password=<MYSQL_PASSWORD>
```
### 4. 리소스 적용
위에서 작성한 YAML 파일들을 Kubernetes 클러스터에 적용합니다.
kubectl apply -f mariadb-config.yaml
kubectl apply -f mariadb-secrets.yaml
kubectl apply -f mariadb-master.yaml
kubectl apply -f mariadb-slave.yaml
kubectl apply -f maxscale.yaml
### 5. 서비스 생성
MariaDB와 MaxScale의 접근을 위해 서비스 리소스를 생성합니다.
**services.yaml**
```yaml
apiVersion: v1
kind: Service
metadata:
name: mariadb-master
spec:
ports:
- port: 3306
selector:
app: mariadb
role: master
---
apiVersion: v1
kind: Service
metadata:
name: mariadb-slave
spec:
ports:
- port: 3306
selector:
app: mariadb
role: slave
---
apiVersion: v1
kind: Service
metadata:
name: maxscale
spec:
ports:
- port: 3306
selector:
app: maxscale
```
이 파일도 클러스터에 적용합니다.
kubectl apply -f services.yaml
### 6. 확인
모든 리소스가 올바르게 생성되었는지 확인합니다.
kubectl get pods
kubectl get services
이제 MaxScale을 통해 MariaDB에 접근할 수 있으며, 읽기 및 쓰기 요청을 분산할 수 있습니다. MaxScale의 IP 주소로 연결하여 MariaDB 클러스터에 접근할 수 있습니다.
### 7. MariaDB 연결 예시
MaxScale에 연결하려면, MaxScale 서비스의 IP 주소 또는 DNS를 사용합니다.
mysql -h <maxscale_service_ip> -u user -p
이렇게 하면 MariaDB Replication과 MaxScale이 설정된 Kubernetes 클러스터가 준비됩니다.
cat <<EOT> kind-metallb.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
networking:
podSubnet: "172.16.0.0/16"
serviceSubnet: "10.200.0.0/24"
kubeProxyMode: "ipvs"
EOT
vi mariadb-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mariadb-configmap
namespace: mariadb
data:
primary.cnf: |
[mariadb]
log-bin
binlog-format=ROW
log_slave_updates=ON
replica.cnf: |
[mariadb]
log-bin
read_only=1
log_slave_updates=ON
primary.sql: |
CREATE USER 'repluser'@'%' IDENTIFIED BY 'replsecret';
GRANT REPLICATION REPLICA ON *.* TO 'repluser'@'%';
CREATE USER 'maxscale'@'%' IDENTIFIED BY 'maxscale_pw';
GRANT SELECT ON mysql.user TO 'maxscale'@'%';
GRANT SELECT ON mysql.db TO 'maxscale'@'%';
GRANT SELECT ON mysql.tables_priv TO 'maxscale'@'%';
GRANT SELECT ON mysql.columns_priv TO 'maxscale'@'%';
GRANT SELECT ON mysql.procs_priv TO 'maxscale'@'%';
GRANT SELECT ON mysql.proxies_priv TO 'maxscale'@'%';
GRANT SELECT ON mysql.roles_mapping TO 'maxscale'@'%';
GRANT SHOW DATABASES ON *.* TO 'maxscale'@'%';
GRANT REPLICATION CLIENT ON *.* TO 'maxscale'@'%';
GRANT SELECT ON mysql.* TO 'maxscale'@'%';
GRANT ALL PRIVILEGES ON *.* TO 'maxscale'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
secondary.sql: |
CHANGE MASTER TO
MASTER_HOST='mariadb-0.mariadb-service.mariadb.svc.cluster.local',
MASTER_USER='repluser',
MASTER_PASSWORD='replsecret',
MASTER_CONNECT_RETRY=10;
kubectl apply -f mariadb-configmap.yaml
vi mariadb-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mariadb
namespace: mariadb
spec:
serviceName: "mariadb-service"
replicas: 3
selector:
matchLabels:
app: mariadb
template:
metadata:
labels:
app: mariadb
spec:
initContainers:
- name: init-mariadb
image: mariadb:10.10.3
command:
- bash
- "-c"
- |
set -ex
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
server_id=$((100 + ordinal))
if [[ $ordinal -eq 0 ]]; then
cp /mnt/config-map/primary.cnf /etc/mysql/conf.d/server-id.cnf
cp /mnt/config-map/primary.sql /docker-entrypoint-initdb.d/
else
cp /mnt/config-map/replica.cnf /etc/mysql/conf.d/server-id.cnf
cp /mnt/config-map/secondary.sql /docker-entrypoint-initdb.d/
fi
volumeMounts:
- name: conf
mountPath: /etc/mysql/conf.d
- name: config-map
mountPath: /mnt/config-map
- name: initdb
mountPath: /docker-entrypoint-initdb.d
containers:
- name: mariadb
image: mariadb:10.10.3
env:
- name: MYSQL_ROOT_PASSWORD
value: "rootpassword"
ports:
- containerPort: 3306
volumeMounts:
- name: datadir
mountPath: /var/lib/mysql
- name: conf
mountPath: /etc/mysql/conf.d
- name: initdb
mountPath: /docker-entrypoint-initdb.d
volumes:
- name: conf
emptyDir: {}
- name: config-map
configMap:
name: mariadb-configmap
- name: initdb
emptyDir: {}
volumeClaimTemplates:
- metadata:
name: datadir
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
kubectl apply -f mariadb-statefulset.yaml
# kubectl scale statefulset mariadb-statefulset --replicas=3
vi mariadb-service.yaml
apiVersion: v1
kind: Service
metadata:
name: mariadb-service
namespace: mariadb
spec:
selector:
app: mariadb
ports:
- port: 3306
clusterIP: None
kubectl apply -f mariadb-service.yaml
vi maxscale-configmap.yaml
kind: ConfigMap
metadata:
name: maxscale-config
namespace: mariadb
data:
maxscale.cnf: |
[maxscale]
threads=auto
admin_host=0.0.0.0
admin_port=8989
admin_secure_gui=false
config_sync_cluster=MariaDB-Monitor
config_sync_user=maxscale
config_sync_password=maxscale_pw
[server1]
type=server
address=mariadb-0.mariadb-service.mariadb.svc.cluster.local
port=3306
protocol=MariaDBBackend
[server2]
type=server
address=mariadb-1.mariadb-service.mariadb.svc.cluster.local
port=3306
protocol=MariaDBBackend
[server3]
type=server
address=mariadb-2.mariadb-service.mariadb.svc.cluster.local
port=3306
protocol=MariaDBBackend
[MariaDB-Monitor]
type=monitor
module=mariadbmon
servers=server1,server2,server3
user=maxscale
password=maxscale_pw
monitor_interval=2000ms
auto_failover=true
auto_rejoin=true
[Read-Write-Service]
type=service
router=readwritesplit
servers=server1,server2,server3
user=maxscale
password=maxscale_pw
causal_reads=true
causal_reads_timeout=10s
causal_reads=fast: 가장 빠른 방법이지만, 슬레이브가 항상 지연되는 경우 마스터에 모든 읽기가 집중될 수 있습니다.
causal_reads=local: 현재 연결에서 데이터 변경이 있을 경우, MaxScale은 슬레이브가 해당 데이터를 복제할 때까지 최대 causal_reads_timeout 시간(기본값 10초) 동안 기다립니다.
causal_reads=global: local과 유사하지만, 모든 사용자의 데이터 변경을 고려합니다.
[Read-Write-Listener]
type=listener
service=Read-Write-Service
protocol=MariaDBClient
port=3306
kubectl apply -f maxscale-configmap.yaml
vi maxscale-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: maxscale
namespace: mariadb
spec:
replicas: 1
selector:
matchLabels:
app: maxscale
template:
metadata:
labels:
app: maxscale
spec:
containers:
- name: maxscale
image: mariadb/maxscale:latest
ports:
- containerPort: 3306
- containerPort: 8989
volumeMounts:
- name: config
mountPath: /etc/maxscale.cnf
subPath: maxscale.cnf
volumes:
- name: config
configMap:
name: maxscale-config
kubectl apply -f maxscale-deployment.yaml
vi maxscale-service.yaml
apiVersion: v1
kind: Service
metadata:
name: maxscale
namespace: mariadb
spec:
selector:
app: maxscale
ports:
- port: 3306
targetPort: 3306
name: db
- port: 8989
targetPort: 8989
name: admin
type: NodePort
kubectl apply -f maxscale-service.yaml