まず、ベースとなる Dockerイメージを構築するのですが、イメージをPullしてくるのは、おもしろくないので、Ubuntuイメージから構築してみます。
では、定番の2つのファイルを作って、起動しましょう。
コンテナは、mariadbcluster2としましょう。
mkdir mariadbcluster2cd mariadbcluster2
Dockerfile
FROM ubuntuRUN bashversion: "3"services: dbsvr: build: context: . privileged: true command: bash hostname: dbsvr tty: true
起動してMariadb環境を構築していきます。docker compose up -d
Shellに接続します。docker exec -it mariadbcluster2-dbsvr-1 bash
では、普通にUbuntuを構築していきます。apt updateapt upgrade -yapt install init systemd language-pack-ja-base language-pack-ja net-tools iputils-ping traceroute dnsutils tzdata vim -ylocale-gen ja_JP.UTF-8echo "export LANG=ja_JP.UTF-8" >> ~/.bashrcexit
ここで、一旦、コンテナに保存です。docker commit mariadbcluster2-dbsvr-1 mariadbcluster2-dbsvr
で、停止です。docker compose down
次は、Dockerfileとdocker-compose.ymlを修正します。
Dockerfile
FROM mariadbcluster2-dbsvrENTRYPOINT [ "/root/start.sh" ]EXPOSE 3306/tcpEXPOSE 4444/tcpEXPOSE 4567/tcpEXPOSE 4568/tcpversion: "3"services: dbsvr: stop_signal: SIGTERM build: context: . dockerfile: Dockerfile privileged: true networks: - backend command: /sbin/init hostname: dbsvr tty: true volumes: - ./mysqldata:/var/lib/mysql - ./conf:/etc/mysql/conf.d/networks: backend: driver: bridgedocker compose up -dShellに接続します。
docker exec -it mariadbcluster2-dbsvr-1 bashapt install mariadb-server mariadb-client galera-4 galera-arbitrator-4 -y
次に、起動シェルを作成します。
/root/start.sh
#!/bin/bashCMDNAME=`basename $0`while getopts adc OPTdo case $OPT in "d" ) DELETE="TRUE" ;; esacdone# safty Exitfunction exit_script(){ echo "Caught SIGTERM" /etc/init.d/mariadb stop exit 0}trap exit_script SIGTERM# Initialize Databaseif [[ $DELETE = "TRUE" ]]; then rm -rf /var/lib/mysql/*fi# Auto boot strap for kubernetesif [ ! -e /etc/mysql/conf.d/galera.cnf ]; then CLUSTER="TRUE" cp /root/galeratmp.cnf /etc/mysql/conf.d/galera.cnfelse CLUSTER="FALSE"fi# Building Databaseif [ ! -d /var/lib/mysql/mysql ]; then /usr/bin/mysql_install_db --user=mysqlfiif [[ $CLUSTER = "TRUE" ]]; then echo 'Start mariadb Cluster' sed -i 's/safe_to_bootstrap: 0/safe_to_bootstrap: 1/' /var/lib/mysql/grastate.dat #Hostadd cp /root/galeratmp.cnf /etc/mysql/conf.d/galera.cnf /etc/init.d/mariadb start --wsrep-new-cluster /root/ghostadd.py > /root/galera.cnf cp /root/galera.cnf /etc/mysql/conf.d/galera.cnfelse echo 'Start mariadb' /usr/bin/sleep 30 #Hostadd /root/ghostadd.py > /root/galera.cnf cp /root/galera.cnf /etc/mysql/conf.d/galera.cnf /etc/init.d/mariadbstartfitrap break ERRwhile [ 1 ]do /usr/bin/sleep 5 mysql -e "show status like 'wsrep_%';" | grep wsrep_incoming_addressesdone
後、ghostadd.pyとgaleratmp.cnfを作成します。
ghostadd.py
#!/usr/bin/python3
import osimport reimport socket# IP Addresshost = socket.gethostname()ip = socket.gethostbyname(host)#Hostnamehname = os.uname()[1]#Currentf = open('/etc/mysql/conf.d/galera.cnf', 'r')data = f.read()f.close()for line in data.split("\n"): result = re.search('gcomm://',line) if result is not None : endchr = line[len(line)-1] if endchr != '/' and endchr != ',': line = line + "," print(line + ip) else: print( line)/root/galeratmp.cnf
[galera]wsrep_cluster_address = gcomm://
起動可能にします。
chmod a+x /root/start.sh
chmod a+x /root/ghostadd.py
初期DBは、いらないので、消去します。
rm -rf /var/lib/mysql/*
次に、mariadbの調整をします。
mv /etc/mysql/conf.d/* /etc/mysql/mariadb.conf.d
#bind-address = 127.0.0.1
/etc/mysql/mariadb.conf.d/60-galera.cnf
[galera]# Mandatory settingswsrep_on = ONwsrep_cluster_name = "MariaDB Galera Cluster"binlog_format = rowdefault_storage_engine = InnoDBinnodb_autoinc_lock_mode = 2# Allow server to accept connections on all interfaces.bind-address = 0.0.0.0# Optional settingswsrep_slave_threads = 2#innodb_flush_log_at_trx_commit = 0wsrep_sst_method = rsyncwsrep_provider = '/usr/lib/galera/libgalera_smm.so'
コンテナからexitし、保存です。docker commit mariadbcluster2-dbsvr-1 mariadbcluster2-dbsvr
で、停止です。docker compose down
さー、ここからが本番です
レジストリの作成
パブリック
リボジトリ名を mariadbcluster2で構築します。
次にリポジトリアクセス用の認証トークンを作成します。
自分のプロファイルから認証トークンを選択して作成します。
すると、謎の文字列を生成してくれるので、記録して下さい。
さっ、Dockerに戻ります。
リポジトリにログインします。 サンプルは、大阪リージョン(kix.ocir.io)ですよ。
サーバーアドレスは、ここに載ってます。
docker login kix.ocir.io
認証するんですが、ユーザー名の前にネームスペースを付けないとダメなんですね。
ネームスペースって何っと思うでしょ。テナンシに割りついている謎の文字列のことです。
テナンシ詳細画面から、オブジェクト・ストレージ・ネームスペースってとこに書かれているので、記録して下さい。
ということで、認証は、以下です。
User:ネームスペース/ユーザー名
Pass:認証トークン
無事認証すると、イメージを構築しリポジトリにプッシュします。
docker image build -t kix.ocir.io/ネームスペース/mariadbcluster2:1.0 .
docker push kix.ocir.io/ネームスペース/mariadbcluster2:1.0
いよいよ、Kubernetesクラスタ(OKE)の出番となります。
とにもかくにも、環境作りです。
kubernetesのクライアント環境を構築します。
apt install apt-transport-https gnupg2 curl sudocurl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.listapt updateapt install kubectl kubelet kubeadmapt-mark hold kubelet kubeadm kubectl
次に、OCI CLI環境を構築します。
apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev wget libbz2-devapt install python3 python3-pip python3-venv
bash -c "$(curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh)"
oci setup config
OCI CLIのセットアップは、公式サイトを参考に構築して下さい。 <- 書くのが疲れました。
では、やっと本作業です
VNCとサブネット、ルート表とかってのは、先に構築しておいて下さいね。
サブネットですが、OCIでは、以下のルールがあるので、ご注意を 当然ですが、各サブネットが疎通可能な状態として下さいね。
Kubernetes APIエンドポイントサブネット
コントロールブレーンが配置されるとこなんで、Privateが良さそうだ
ワーカーノードサブネット
ノード(仮想PC)を配置するところ。PrivateでもPublicでも良さそうだ
このサブネットは、ロードバランサーと同じサブネットに配置出来ないので、注意
ロードバランサーサブネット
LoadBalancerタイプのServiceとして作成されるOCIロードバランサーを配置するサブネット
ここは、外部通信を受け入れることになるので、基本Publicだろう。用途によっては、Privateでも問題無しだ
Pod通信のサブネットは、ロードバランサーと同じサブネットに配置出来ないので、注意
OCI コンソールで、Kubernetes クラスタ(OKE)を構築します。
シェイプは、構築したコンテナイメージとアーキテクチャを合わせて下さいね。
ノードタイプに管理対象を選択した場合、基本的なクラスタの確認 チェックを選択することが可能です。
ここでチェックしないと、ランニングコストがかかってしまうので、お財布と相談して下さいませ。
構築には、まーまーの時間が掛かるので、ゆっくりお茶でも飲んで待ちましょう。
クラスターが完成したら、以下のコマンドで、接続環境を構築しましょう。
クラスタのOCIIDとリージョンを指定してくださいね。
CLUSTERID=ocid1.cluster.oc1.ap-osaka-1.....
oci ce cluster create-kubeconfig --cluster-id ${CLUSTERID} --file $HOME/.kube/config --region ap-osaka-1 --token-version 2.0.0 --kube-endpoint PRIVATE_ENDPOINT
Nodeを確認してみましょう。
kubectl get node -o wide
kubernetesで、OCIのコンテナレジストリにアクセス出きるように、認証情報を登録します。
kubectl create secret docker-registry myrepo --docker-server=kix.ocir.io --docker-username=hogehoge/ユーザー名 --docker-password='パスワード' --docker-email=適当なメールアドレス
いよいよ、超高可用なMariadbサーバーの要である、kubernetesのyamlファイルを作成します。
mariadb-sfull.yaml
kind: StorageClassapiVersion: storage.k8s.io/v1metadata: name: mariadbconf-storageprovisioner: fss.csi.oraclecloud.comparameters: availabilityDomain: NtKM:AP-OSAKA-1-AD-1 mountTargetSubnetOcid: ocid1.subnet.oc1.ap-osaka-1........... compartmentOcid: ocid1.compartment.oc1........... exportPath: /mariadbconf---apiVersion: v1kind: PersistentVolumeClaimmetadata: name: mariadbconfclaimspec: accessModes: - ReadWriteMany storageClassName: "mariadbconf-storage" resources: requests: storage: 10Gi---apiVersion: v1kind: Servicemetadata: labels: app: mariadb-service name: mariadb-svc annotations: oci.oraclecloud.com/load-balancer-type: "nlb" oci-network-load-balancer.oraclecloud.com/backend-policy: "FIVE_TUPLE" oci-network-load-balancer.oraclecloud.com/internal: "true"spec: selector: app: mariadb-dep type: LoadBalancer ports: - port: 3306 protocol: TCP targetPort: 3306---apiVersion: apps/v1kind: StatefulSetmetadata: labels: app: mariadb-pod name: mariadb-depspec: replicas: 3 selector: matchLabels: app: mariadb-dep template: metadata: labels: app: mariadb-dep spec: terminationGracePeriodSeconds: 10 containers: - image: kix.ocir.io/hogehoge/mariadbcluster2:1.0 imagePullPolicy: Always name: mariadb command: [ "/root/start.sh" ] ports: - name: mysql containerPort: 3306 - name: cluster1 containerPort: 4444 - name: cluster2 containerPort: 4567 - name: cluster3 containerPort: 4568 volumeMounts: - name: data mountPath: /var/lib/mysql - name: conf mountPath: /etc/mysql/conf.d imagePullSecrets: - name: myrepo volumes: - name: data persistentVolumeClaim: claimName: mariadbclaim - name: conf persistentVolumeClaim: claimName: mariadbconfclaim volumeClaimTemplates: - metadata: name: data spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "oci-bv" resources: requests: storage: 50Gi - image: kix.ocir.io/hogehoge/mariadbcluster2:1.0 availabilityDomain: NtKM:AP-OSAKA-1-AD-1 mountTargetSubnetOcid: ocid1.subnet.oc1.ap-osaka-1........... compartmentOcid: ocid1.compartment.oc1...........storage: 50Gi replicas: 3何度も確かめて下さいね
良ければ、Goです。
kubectl apply -f ./mariadb-sfull.yaml
すぐには、構築出来ないので、ゆっくり待ちましょう。
確認は、以下で行えます。
kubectl get pod -o wide
kubectl get pvc
kubectl get svc -o wide
適当なpodが完成すると、中にログインして mariadb環境を構築していきましょう。
kubectl exec -it mariadb-dep-0 -- bash
クラスタ状態を確認してみましょう
mysql -u root -e "show status like 'wsrep_%';" | grep wsrep_incoming_addresses
ここからは、mysqlやmariadbの世界なんで、適当にぐぐってもらって、DBの環境構築して下さい。
Network Load Balancerが構築されているので、これに対して接続することで、超高可用データベースの完成となります。
NLBのアドレス確認
kubectl get svc
NLBへの接続
mysql -u [ユーザー名] -h [NLBのアドレス] -p
あっ、これを破棄したい時は、以下で破壊することが出来ます。
kubectl delete -f ./mariadb-sfull.yaml
しかしながら、今回は、Statefulset で構築したので、BlockStorageは、破壊しません。
だから、もう一回、構築すると、データベースが復活するんですね。
まー便利
でも、本当にいらなくなったら、PVCを全部破棄して下さい。
kubectl delete pvc data-mariadb-dep-0 kubectl delete pvc data-mariadb-dep-1 kubectl delete pvc data-mariadb-dep-3
今回は、実験レベルなんですが、十分実用出来そうですね。
本当に可用性を求めるから、nodeとpodの数を考慮する必要がありそうです。
それと、nodeを増やしたりするとpodの再配置を行わないといけません。そういったことは、よくわからんので、chatgptにでも尋ねて下さいな
一度作ってしまえば、clusterを変えて、どんどん作れそうなんで、お試しあれ





