쿠버네티스에서 Pod로 Mysql 사용해보자
쿠버네티스 동작 흐름
yaml 파일을 만든다.
컨트롤러를 통해 Pod,Deployment 만든다.
오퍼레이터 동작 흐름
커스텀 리소스 파일
커스텀 컨트롤로를 통해 커스텀 리소스를 만든다.
이미지 출처
https://ccambo.blogspot.com/2020/12/kubernetes-operator-kubernetes-operator.html?zx=2d1bd84d170e0f40
2
CRD Custom Resource Definition : 오퍼레이터로 사용할 상태 관리용 객체들의 Spec 을 정의
CR Custom Resource : CRD의 Spec 를 지키는 객체들의 실제 상태 데이터 조합
CC Custom Controller : CR의 상태를 기준으로 현재의 상태를 규정한 상태로 처리하기 위한 컨트롤 루프
CRD, CR 개념 정리
1
# 기존 CRD 확인 = crontab은 없다.
kubectl get crd
kubectl get crd | grep crontabs
2
# CRD 샘플 YAML 파일 확인
curl -s -O https://raw.githubusercontent.com/gasida/DOIK/main/2/resourcedefinition.yaml
cat resourcedefinition.yaml | yh
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition # 사용자 정의 리소스(CRD) 생성
metadata:
# name must match the spec fields below, and be in the form: <plural>.< group>
name: crontabs.stable.example.com # <NAMES>.<GROUP> 으로 정의
spec:
# group name to use for REST API: /apis/<group>/<version>
group: stable.example.com # apiVersion 그룹 이름(<GROUP>) 을 지정
# list of versions supported by this CustomResourceDefinition
versions: # CRD 버전 정의
- name: v1
# Each version can be enabled/disabled by Served flag.
served: true
# One and only one version must be marked as the storage version.
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
# either Namespaced or Cluster
scope: Namespaced # Cluster 레벨 리소스인지 vs 네임스페이스 레벨 리소스인지 지정
names:
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
plural: crontabs # 복수 이름
# singular name to be used as an alias on the CLI and for display
singular: crontab # 단수 이름
# kind is normally the CamelCased singular type. Your resource manifests use this.
kind: CronTab # Kind 이름
# shortNames allow shorter string to match your resource on the CLI
shortNames: # 축약 이름
- ct
축약 확인
(11-15-access@myeks:default) [root@myeks-bastion-EC2 ~]# k api-resources
NAME SHORTNAMES APIVERSION NAMESPACED KIND
bindings v1 true Binding
componentstatuses cs v1 false ComponentStatus
configmaps cm v1 true ConfigMap
endpoints ep v1 true Endpoints
events ev v1 true Event
limitranges limits v1 true LimitRange
namespaces ns v1 false Namespace
3
# CRD 생성
kubectl apply -f resourcedefinition.yaml
4
# CRD 생성 확인
kubectl get crd | grep crontabs
crontabs.stable.example.com 2022-05-27T14:04:53Z
5
# CR 샘플 YAML 파일 확인
curl -s -O https://raw.githubusercontent.com/gasida/DOIK/main/2/my-crontab.yaml
cat my-crontab.yaml | yh
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
# CR 생성
kubectl apply -f my-crontab.yaml
# 생성된 리소스 확인
kubectl get crontab
NAME AGE
my-new-cron-object 62s
# 리소스 상세 정보 확인 : 축약어(ct) 가능
kubectl get ct -o yaml | yh
apiVersion: v1
items:
- apiVersion: stable.example.com/v1
kind: CronTab
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"stable.example.com/v1","kind":"CronTab","metadata":{"annotations":{},"name":"my-new-cron-object","namespace":"default"},"spec":{"cronSpec":"* * * * */5","image":"my-awesome-cron-image"}}
creationTimestamp: "2022-05-27T14:10:41Z"
generation: 1
name: my-new-cron-object
namespace: default
resourceVersion: "2811"
uid: 19e62ddf-1a31-4b77-a2ed-b04ef17c3b5c
spec:
cronSpec: '* * * * */5'
image: my-awesome-cron-image
kind: List
metadata:
resourceVersion: ""
selfLink: ""
# 현재는 리소스만 생성한 상태이고, 어떤 동작을 수행해야 하는지 아무런 정보가 없습니다.
# 실제 동작을 수행하기 위해서는 Custom Controller 의 도움이 필요합니다.
# Operator 패턴이란 Custom Resource + Custom Controller 조합으로 특정 애플리케이션이나 서비스의 생성과 삭제를 관리하는 패턴을 말함
# Operator 패턴을 통해 쿠버네티스 코어 API에 포함되지 않은 애플리케이션을 마치 쿠버네티스 Native 리소스처럼 동작하게끔 만들 수 있음
# CRD 삭제
kubectl delete -f resourcedefinition.yaml
# 리소스 정보 확인 시 에러 발생
kubectl get crontabs
Error from server (NotFound): Unable to list "stable.example.com/v1, Resource=crontabs": the server could not find the requested resource (get crontabs.stable.example.com)
InnoDB 클러스터
배경 - 링크
클라이언트는 MySQL 서버로 직접 접근해서 쿼리를 실행하는 것이 아니라 MySQL 라우터에 연결해서 쿼리를 실행한다
Pod 3개
Primary - R/W
Secondary R/O
스테이트풀셋 : MySQL Server instances - MySQL 서버
디플로이먼트 : MySQL Routers - Proxy 역할로 애플리케이션의 쿼리를 서버에 전달, RW/RO
서비스 : MySQL Router, 개별 MySQL 서버로 접속 주소 생성 (Headless 서비스, SRV 레코드)
MySQL Shell : MySQL Router 와 MySQL Server 에 툴 포함, MySQL 클라이언트 보다 좀 더 확장 기능 제공, 클러스터 관리 가능(AdminAPI)
그외 : 컨피그맵(MySQL Server 설정) , 시크릿(시스템 등 암호들)
1
kubectl get deploy,pod -n mysql-operator
2
# Repo 추가
helm repo add mysql-operator https://mysql.github.io/mysql-operator/
helm repo update
# 실험 버전 설치 : 차트 버전(--version 2.1.0), 애플리케이션 버전(8.1.0-2.1.4) >> 해당 버전은 '23.10.28 현재 삭제됨 Innovation Release 라서 역시 실습으로도 쓰지 말것
# 안정 버전 설치 : 차트 버전(--version 2.0.12), 애플리케이션 버전(8.0.35-2.0.12) >> General Availability
3
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 --version 2.0.12
helm get manifest mysql-operator -n mysql-operator
# 설치 확인
kubectl get deploy,pod -n mysql-operator
4
# CRD 확인
4개의 CRD가 생성되었다.
오퍼레이터 설치가 되어 이제 이노디비 클러스터를 설치할수 있다.
kubectl get crd | egrep 'mysql|zalando'
clusterkopfpeerings.zalando.org 2023-10-16T13:30:46Z
innodbclusters.mysql.oracle.com 2023-10-16T13:30:46Z
kopfpeerings.zalando.org 2023-10-16T13:30:46Z
mysqlbackups.mysql.oracle.com 2023-10-16T13:30:46Z
## (참고) CRD 상세 정보 확인
kubectl describe crd innodbclusters.mysql.oracle.com
...(생략)...
# (참고) 삭제
helm uninstall mysql-operator -n mysql-operator && kubectl delete ns mysql-operator
# (참고) Helm Chart Default Values 확인
helm show values mysql-operator/mysql-innodbcluster
...(생략)...
# 파라미터 파일 생성
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
2
# 차트 설치(기본값) : root 사용자(root), 호스트(%), 서버인스턴스(파드 3개), 라우터인스턴스(파드 1개), serverVersion(8.0.35)
# root 사용자 암호(sakila), 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 install mycluster mysql-operator/mysql-innodbcluster --namespace mysql-cluster --version 2.0.12 -f mycnf-values.yaml --create-namespace
helm get values mycluster -n mysql-cluster
helm get manifest mycluster -n mysql-cluster
3
# (옵션) 모니터링 << pv 는 왜 mysql-cluster 네임스페이스내에서 안 보일까요?
watch kubectl get innodbcluster,sts,pod,pvc,svc -n mysql-cluster
4
확인
서버인스턴스(파드 3개)
라우터인스턴스(파드 1개)
pvc 확인
pv확인 = 스토리지 클래스 gp3로 변경 되어 배포 됨.
(11-15-access@myeks:default) [root@myeks-bastion-EC2 ~]# k get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
gp2 kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 19h
gp3 (default) ebs.csi.aws.com Delete WaitForFirstConsumer true 18h
SVC 확인
클러스터 IP로 선언 했는데 IP가 없는것은 해드리스 서비스 = 개별 파드로 직접 접속이 가능하다.
# 설치 확인
kubectl get innodbcluster,sts,pod,pvc,svc,pdb,all -n mysql-cluster
디스트 사용률 확인
kubectl df-pv
kubectl resource-capacity
## MySQL InnoDB Cluster 구성요소 확인
kubectl get InnoDBCluster -n mysql-cluster
NAME STATUS ONLINE INSTANCES ROUTERS AGE
mycluster ONLINE 3 3 1 6m20s
## 이벤트 확인
kubectl describe innodbcluster -n mysql-cluster | grep Events: -A30
...(생략)...
## MySQL InnoDB Cluster 초기 설정 확인
kubectl get configmap -n mysql-cluster mycluster-initconf -o json | jq -r '.data["my.cnf.in"]'
kubectl get configmap -n mysql-cluster mycluster-initconf -o yaml | yh
kubectl describe configmap -n mysql-cluster mycluster-initconf
...(생략)...
01-group_replication.cnf:
----
# GR and replication related options
# Do not edit.
[mysqld]
log_bin=mycluster
enforce_gtid_consistency=ON
gtid_mode=ON # 그룹 복제 모드 사용을 위해서 GTID 활성화
relay_log_info_repository=TABLE # 복제 메타데이터는 데이터 일관성을 위해 릴레이로그를 파일이 아닌 테이블에 저장
skip_slave_start=1
...(생략)...
99-extra.cnf:
----
# Additional user configurations taken from spec.mycnf in InnoDBCluster.
# Do not edit directly.
[mysqld]
max_connections=300 # max_connections default 기본값은 151
default_authentication_plugin=mysql_native_password
...(생략)...
5
## 서버인스턴스 확인(스테이트풀셋) : 3개의 노드에 각각 파드 생성 확인, 사이드카 컨테이너 배포
kubectl get sts -n mysql-cluster; echo; kubectl get pod -n mysql-cluster -l app.kubernetes.io/component=database -owide
## 프로브 확인(Readiness, Liveness, Startup)
kubectl describe pod -n mysql-cluster mycluster-0 | egrep 'Liveness|Readiness:|Startup'
## 서버인스턴스가 사용하는 PV(PVC) 확인 : AWS EBS 볼륨 확인해보기
kubectl get sc
kubectl df-pv
kubectl get pvc,pv -n mysql-cluster
6
## 서버인스턴스 각각 접속을 위한 헤드리스 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
클러스터 생성할때 IP를 지정하지 않으면, Headless 서비스가 생성 된다!!!
7
동적 멤버관리가 필요해 라우터가 필요하다.~ 확인
## 라우터인스턴스(디플로이먼트) 확인 : 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
8
# 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';"
WARNING: Using a password on the command line interface can be insecure.
Variable_name Value
max_connections 300
이제 기본 정보 확인이 되었다!!!
9
# (참고) 삭제
;; ANSWER SECTION:
mycluster-instances.mysql-cluster.svc.cluster.local. 5 IN A 192.168.3.140
mycluster-instances.mysql-cluster.svc.cluster.local. 5 IN A 192.168.1.67
mycluster-instances.mysql-cluster.svc.cluster.local. 5 IN A 192.168.2.171
// 핵심
해드리스 서비스는 해당 파드에 도메인 주소를 직접 만들어준다.
직접 접속이 가능하므로 관리가 가능하다
해당 도메인으로 지정되어 있다.
WARNING: Using a password on the command line interface can be insecure.
Database
information_schema
mysql
mysql_innodb_cluster_metadata
performance_schema
sys
WARNING: Using a password on the command line interface can be insecure.
Variable_name Value
max_connections 300
해드리스 클러스터 IP없이 none으로 만들면 되고 , dns에서 svc로 만들어진다.
해당 되는 도메인 서비스명으로 접속하여 사용한다.
WARNING: Using a password on the command line interface can be insecure.
@@hostname
mycluster-0
다음은
https://brunch.co.kr/@topasvga/3489
참고 동영상
오버레이터란 ?
https://www.youtube.com/watch?v=UmIomb8aMkA
주말 CloudNet 스터디 내용 참고하여 정리한 부분입니다.
https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863