이번 포스팅에서는 Statefulset 형태로 구현이 가능한 대표적인 클러스터인 Galera Cluster를 다루어 볼 것이다. 그 중에서도 Galera Cluster의 각 노드(Pod)의 상태를 etcd 데이터 스토어에 기록하고 사용할 수 있도록 etcd cluster를 동시에 활용하는 방식을 적용해 보려 한다. 주요 참조 기술 및 블로그는 글 말미의 Reference 를 참조하기 바란다. 앞서의 포스팅들과는 다르게 여기서는 Kubernetes 의 현 시점의 최신 버전인 1.11.3 을 활용하였다.
Mariadb Galera Cluster 구현을 위한 준비와 개념도
[Prerequisites]
- Running k8s cluster with persistent storage(glusterfs or nfs storageclass, etc.)
- Tested kubernetes version: 1.9.x, 1.11.x
Kubernetes 상에서 동작하는 Galera Cluster Application의 구조는 다음의 그림에 나타나 있다
- galera-cluster-etcd-k8s-mod 프로젝트 clone
# git clone https://github.com/DragOnMe/galera-cluster-etcd-k8s-mod.git
# cd galera-cluster-etcd-k8s-mod.git
- Container image re-building
docker.io/severalnines/mariadb 이미지도 역시 훌륭하게 동작하지만, 한글 데이터, 소문자 테이블명 등의 처리가 가능하도록 하기 위해서, 해당 이미지의 빌드 소스 위치인 github.com/severalnines/galera-docker-mariadb 레포지터리의 my.cnf 설정 파일을 변경하여 새로운 이미지를 빌드 & 푸쉬해서 사용하도록 한다.
여기서는 drlee001 대신에 github.com 사이트에 본인 각자의 account 를 발급 받아 사용하면 된다
# cd galera-docker-mariadb
# docker build -t drlee001/mariadb:10.1-modcnf .
# docker login -u drlee001
# docker push drlee001/mariadb:10.1-modcnf
ETCD와 Galera Cluster 구축
- etcd cluster 생성 및 점검
Galera Cluster 의 각 Mariadb node 상태 정보가 etcd store에 실시간 저장하고 관리되므로 가장 먼저 etcd 저장소를 구축해야 한다. 해당 아키텍처는 위 그림에 표현되어 있으니 참고하자.
실제로는 모든 galera 노드들이 자신의 상태 값을 주기적으로 etcd에 저장하며, 이 값들은 일정 시간이 지나면(TTL: 10초) 자동으로 expire 되는 식으로 동작한다.
# cd ..
# kubectl config set-context $(kubectl config current-context) --namespace=ns-galera-etcd
Context "kubernetes-admin@kubernetes" modified.
# kubectl create -f 00-etcd-cluster.yaml
namespace/ns-galera-etcd created
service/etcd-client created
pod/etcd0 created
service/etcd0 created
pod/etcd1 created
service/etcd1 created
pod/etcd2 created
service/etcd2 created
# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/etcd0 1/1 Running 0 4m
pod/etcd1 1/1 Running 0 4m
pod/etcd2 1/1 Running 0 4m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/etcd-client ClusterIP 10.134.158.165 <none> 2379/TCP 4m
service/etcd0 ClusterIP 10.142.79.41 <none> 2379/TCP,2380/TCP 4m
service/etcd1 ClusterIP 10.136.241.253 <none> 2379/TCP,2380/TCP 4m
service/etcd2 ClusterIP 10.128.106.181 <none> 2379/TCP,2380/TCP 4m
# curl -L http://10.134.158.165:2379/version
{"etcdserver":"3.3.8","etcdcluster":"3.3.0"}
# kubectl exec -it etcd0 -- etcdctl cluster-health
member ade526d28b1f92f7 is healthy: got healthy result from http://etcd1:2379
member cf1d15c5d194b5c9 is healthy: got healthy result from http://etcd0:2379
member d282ac2ce600c1ce is healthy: got healthy result from http://etcd2:2379
cluster is healthy
# kubectl exec -it etcd0 -- etcdctl --version
etcdctl version: 3.3.8
API version: 2
* ETCD의 API 서버로 쿼리를 보내는 방법은 위에 나온 것 처럼 etcdclient 서비스로 curl 명령을 통해서 API 호출을 하거나 또는 각 etcd pod 중 하나로 직접 접속해서 etcdctl 명령을 보내는 2가지 방법이 있다
- Galera Cluster 의 구축 및 etcd 데이터 확인
# kubectl create -f 01-galera-mariadb-ss.yaml
service/galera-hs created
statefulset.apps/galera-ss created
# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
etcd0 1/1 Running 0 20m
etcd1 1/1 Running 0 20m
etcd2 1/1 Running 0 20m
galera-ss-0 0/1 Running 0 38s
galera-ss-0 1/1 Running 0 2m
galera-ss-1 0/1 Pending 0 0s
galera-ss-1 0/1 Pending 0 0s
galera-ss-1 0/1 Pending 0 8s
galera-ss-1 0/1 ContainerCreating 0 8s
galera-ss-1 0/1 Running 0 11s
galera-ss-0 0/1 Running 0 3m
galera-ss-0 1/1 Running 0 3m
galera-ss-1 1/1 Running 0 2m
galera-ss-2 0/1 Pending 0 0s
galera-ss-2 0/1 Pending 0 0s
galera-ss-2 0/1 Pending 0 19s
galera-ss-2 0/1 ContainerCreating 0 19s
galera-ss-2 0/1 Running 0 24s
galera-ss-0 0/1 Running 0 6m
galera-ss-0 1/1 Running 0 6m
galera-ss-2 0/1 Running 1 2m
galera-ss-2 1/1 Running 1 4m
# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/etcd0 1/1 Running 0 32m
pod/etcd1 1/1 Running 0 32m
pod/etcd2 1/1 Running 0 32m
pod/galera-ss-0 1/1 Running 0 12m
pod/galera-ss-1 1/1 Running 0 10m
pod/galera-ss-2 1/1 Running 1 8m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/etcd-client ClusterIP 10.134.158.165 <none> 2379/TCP 32m
service/etcd0 ClusterIP 10.142.79.41 <none> 2379/TCP,2380/TCP 32m
service/etcd1 ClusterIP 10.136.241.253 <none> 2379/TCP,2380/TCP 32m
service/etcd2 ClusterIP 10.128.106.181 <none> 2379/TCP,2380/TCP 32m
service/galera-hs ClusterIP None <none> 3306/TCP 12m
service/glusterfs-dynamic-mysql-datadir-galera-ss-0 ClusterIP 10.139.193.16 <none> 1/TCP 12m
service/glusterfs-dynamic-mysql-datadir-galera-ss-1 ClusterIP 10.136.64.128 <none> 1/TCP 10m
service/glusterfs-dynamic-mysql-datadir-galera-ss-2 ClusterIP 10.138.84.181 <none> 1/TCP 7m
# curl -L http://10.134.158.165:2379/v2/keys
{"action":"get","node":{"dir":true,"nodes":[{"key":"/galera","dir":true,"modifiedIndex":8,"createdIndex":8}]}}
# curl -L http://10.134.158.165:2379/v2/keys/galera/mariadb_galera_ss
{"action":"get","node":{"key":"/galera/mariadb_galera_ss","dir":true,"nodes":[{"key":"/galera/mariadb_galera_ss/10.40.0.3","dir":true,"modifiedIndex":8,"createdIndex":8},{"key":"/galera/mariadb_galera_ss/10.44.0.5","dir":true,"modifiedIndex":49,"createdIndex":49},{"key":"/galera/mariadb_galera_ss/10.32.0.6","dir":true,"modifiedIndex":129,"createdIndex":129}],"modifiedIndex":8,"createdIndex":8}}
# kubectl exec -it etcd0 -- etcdctl ls /galera/mariadb_galera_ss
/galera/mariadb_galera_ss/10.40.0.3
/galera/mariadb_galera_ss/10.44.0.5
/galera/mariadb_galera_ss/10.32.0.6
* 각 데이터 노드(pod)는 0번 부터 하나씩 순차적으로 만들어지며, 클러스터 내의 각 노드(Mariadb Pod)들 끼리는 자동으로 discover 가 이루어 진다
Galera Cluster의 데이터 동기화 점검
Galera Cluster 각 노드의 주요 상태를 조회해 보면 다음과 같다
# ./88-galera-test.sh
+---------------------------+----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+---------------------------+----------------+
| WSREP_CLUSTER_SIZE | 3 |
| WSREP_CLUSTER_STATUS | Primary |
| WSREP_CONNECTED | ON |
| WSREP_LOCAL_INDEX | 1 |
| WSREP_LOCAL_STATE_COMMENT | Synced |
| WSREP_READY | ON |
+---------------------------+----------------+
+---------------------------+----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+---------------------------+----------------+
| WSREP_CLUSTER_SIZE | 3 |
| WSREP_CLUSTER_STATUS | Primary |
| WSREP_CONNECTED | ON |
| WSREP_LOCAL_INDEX | 2 |
| WSREP_LOCAL_STATE_COMMENT | Synced |
| WSREP_READY | ON |
+---------------------------+----------------+
+---------------------------+----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+---------------------------+----------------+
| WSREP_CLUSTER_SIZE | 3 |
| WSREP_CLUSTER_STATUS | Primary |
| WSREP_CONNECTED | ON |
| WSREP_LOCAL_INDEX | 0 |
| WSREP_LOCAL_STATE_COMMENT | Synced |
| WSREP_READY | ON |
+---------------------------+----------------+
데이터 동기화를 위해 각 데이터베이스 노드에서 데이터를 Insert, Select 및 삭제가 정상적으로 동작하고 동기화 되는지 점검한다
# ./89-galera-sync-test.sh
1. Create database & table(node 0):
2. Insert 2 records into table(node 0):
+-------------------+----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+-------------------+----------------+
| WSREP_LOCAL_INDEX | 1 |
+-------------------+----------------+
+------+-----------------+
| id | name |
+------+-----------------+
| aaa | xxx |
| id | this is my name |
+------+-----------------+
3. Show data(node 1):
+-------------------+----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+-------------------+----------------+
| WSREP_LOCAL_INDEX | 2 |
+-------------------+----------------+
+------+-----------------+
| id | name |
+------+-----------------+
| aaa | xxx |
| id | this is my name |
+------+-----------------+
4. Show data(node 2):
+-------------------+----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+-------------------+----------------+
| WSREP_LOCAL_INDEX | 0 |
+-------------------+----------------+
+------+-----------------+
| id | name |
+------+-----------------+
| aaa | xxx |
| id | this is my name |
+------+-----------------+
5. Delete data(node 2):
6. Show data(node 0):
+-------------------+----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+-------------------+----------------+
| WSREP_LOCAL_INDEX | 1 |
+-------------------+----------------+
+------+-----------------+
| id | name |
+------+-----------------+
| id | this is my name |
+------+-----------------+
7. Show data(node 1):
+-------------------+----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+-------------------+----------------+
| WSREP_LOCAL_INDEX | 2 |
+-------------------+----------------+
+------+-----------------+
| id | name |
+------+-----------------+
| id | this is my name |
+------+-----------------+
8. Delete database & table(node 1):
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydatabase |
| mysql |
| performance_schema |
+--------------------+
Galera Cluster 의 리셋, 삭제
Galera Cluster에서 사용하는 etcd 데이터 영역을 Reset 하려면, 먼저 Galera Cluster 정보를 다음과 같이 삭제,
# curl http://10.134.158.165:2379:2379/v2/keys/galera/mariadb_galera_ss?recursive=true -XDELETE
또는
# kubectl exec -it etcd0 -- etcdctl rm /galera/mariadb_galera_ss --recursive
만약 전체 영역을 모두 삭제하고 싶다면 아래 script 를 수행하면 된다.
# ./99-teardown.sh
service "galera-hs" deleted
statefulset.apps "galera-ss" deleted
persistentvolumeclaim "mysql-datadir-galera-ss-0" deleted
persistentvolumeclaim "mysql-datadir-galera-ss-1" deleted
persistentvolumeclaim "mysql-datadir-galera-ss-2" deleted
namespace "ns-galera-etcd" deleted
service "etcd-client" deleted
pod "etcd0" deleted
service "etcd0" deleted
pod "etcd1" deleted
service "etcd1" deleted
pod "etcd2" deleted
service "etcd2" deleted
No resources found.
Id:6d779dbd1e08b7ff7348360190091632 Cluster:60147830250310129f7b11084613a204 Name:heketidbstorage
# kubectl config set-context $(kubectl config current-context) --namespace=default
Context "kubernetes-admin@kubernetes" modified.
Reference
- https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
- https://severalnines.com/blog/mysql-docker-deploy-homogeneous-galera-cluster-etcd
- https://github.com/severalnines/galera-docker-mariadb
- Barracuda -
'Technical > Cloud, Virtualization, Containers' 카테고리의 다른 글
Amazon Route53, Google cloud DNS 를 활용한 kubernetes service DNS 자동화 (2/3) (0) | 2020.09.13 |
---|---|
Amazon Route53, Google cloud DNS 를 활용한 kubernetes service DNS 자동화 (1/3) (0) | 2020.09.10 |
[Kubernetes StatefulSet] Mongodb Replicaset by StatefulSet(2/5) (2) | 2018.09.16 |
[Kubernetes StatefulSet] 개요 & Nginx Web Cluster(1/5) (0) | 2018.05.24 |
[Kubernetes - CI/CD] Customized Jenkins 제작과 활용 - 2/2 (0) | 2018.04.03 |