データベースクラスタリングシステムVitess
本記事
本記事ではKubenetes上にデータベースクラスタリングシステムの入門として導入して、使い勝手や操作方法、運用方法などの学習します。
目次
Vitessについて
Vitessとは
VitessとはMySQLの水平方向スケールアウトを提供するためのデータベースクラスタリングシステム
Youtubeで2011年から使われていたそうです。
特徴
以下のような特徴があります。
1. スケーラビリティ
一般的にはRDBはスケールするのが難しいという印象でしょう。
特にMySQLはReplicaを置くことができますが、それでもスケール性は高いとは言えません。
しかし、NoSQLのようにすると以下のようにシャーディングすることができます。
しかしVitessを使うことによってNoSQLのようなスケール性を提供します。
これはシャーディングをしているからです。
2. ハイパフォーマンス
Vitessはデータベースパフォーマンスを悪くするクエリを自動で書き換えて効率よくします。
キャッシングや中間クエリを使って重複したクエリが実行されないように自然に置き換えます。
3. マネジメントのしやすさ
Vitessはマスターフェイルオーバーやバックアップというものを自動的に行ってくれます。。
ロックサーバーを使って管理者サーバーを監視して、データベースのトポロジーを意識せずに済む様にします。
4. コネクションプール
MySQLの接続にかかる多大なメモリオーバーヘッドを削減します。gRPCベースのプロトコルは一度に1000以上の接続でも捌けます。
クライアントからもgRPCで接続します。
5. シャードマネジメント
MySQLは本来はシャーディングはサポートしていないが、データベースに対して必要になるときがくるかもしれない。 それをバックエンドで自動でやってくれるので、何もアプリケーションは書く必要がなくなる。
6. ワークフロー
クラスタについてメタデータを常に追跡し続けるのでクラスタ監視は常に最新な状態に保つことができます。
大事なコンセプト
1. Keyspace
論理データベースである。シャードをしていなければMySQLの名前で直接マッピングされます。
シャードされていたら、keyspaceはいくつものMySQLデータベースにマッピングされるが、一つのデータベースにアクセスしているようにみえる。
2. Cell
セルとは特定の範囲で物理的に独立した配置されたサーバとネットワークインフラのグループです。
それぞれのセルはlocal topology serviceがあって、セルの中にホスティングされます。
Vitness tabletsの情報を格納しています。
3. Topology Service
バックエンドで走っている処理をこと。 それぞれはトポロジーデータと分散ロッキングシステムを提供している。
VitnessはKubernetes上だとetcd
を使っていてKey-Value形式になっています。
4. Tablet
mysqldとvttabletプロセスのコンビです。
5. Shard
Keyspaceを分割したもので、MySQLマスターとスレーブから構成されます。
アーキテクチャ
以下のようなアーキテクチャです。
大きくruntime
とadmin
に分かれていてadmin
に関するところが私たちの部分です。
一方でruntime
はデプロイしているアプリケーション側の話です。
ここで役割について解説します。
もしかしたら特にvttablet
などはこっちの図の方がみやすいかもしれません。
1. Topology
Topology Serviceはメタデータを格納して動作しているサーバーの情報を持ち、シャーディングのスキーマなりを保持しています。バックエンドにはデータストアがあり、vtctl
CLIツールとvtctld
というWebインターフェースからアクセスすることができる。
Kubernetesではdata storeにはetcd
が使われています。
これには二つのインスタンスの種類があります。
1.1 Global vs Local
クローバルインスタンスとPer-cell Localインスタンスがある。
- Globalインスタンスはあまり変わらないトポロジーのグローバルなデータを格納しています。例えばKeyspaceやシャードについてです。
- セル一つにつき、一つのローカルインスタンスがあり、セルの設定情報を保持している。また、またrolled-upデータを持っていて、クライアントがデータを探しやすいようにする。
Globalインスタンスが停止してもあまり影響はないが、Localインスタンスが停止すると、そのセルは使わない方がいいです。
Vitnessはクエリを処理するのにTopologyを使うことはなく、起動時やバックグラウンドでTopologyさーばーにアクセスしてTopologyの情報を得ている。
1.2 スキーマ管理
Vitnessでは二つのスキーマがあります。
- MySQLスキーマ: それぞれのMySQLスキーマです
- VSchema: keyspaceとどのようにシャーディングされるかを指定します
シャーディングとは何かというと以下のようにシャードキーによって水平分散をすることです。
引用
2. vtgate
vtgateは軽量なプロキシサーバーで、正しいvttabletにトラフィックをルーティングする役割を持つ。
また、それぞれの結果に対して合算した結果を返します。
クライアントはvtgateさえ見つけられればクエリを投げることができます。
また、ここがシャーディングスキーマなりレイテンシ、tabletsの稼働状況などを持っています。
3. vttablet
vttabletはMySQLのプロキシサーバーである。SidecarのようにそれぞれのMySQLインスタンスの前に存在する。
役割としては、vttabletはスループットを最大化するようにして、MySQLをひどいクエリから守ります。
コネクションプーリング、クエリ書き換え、クエリのキャッシュの機能もある。
これを挟むことによってMySQLドライバではなくて、Vitessクライアントを使うようになる。
4. vtctld
これはWebインターフェース用のサーバーである。
Kubernetesにホストする
リポジトリを取得する
go get vitess.io/vitess/go/cmd/vtctlclient
クラスタを作成する
以下の様にしてクラスタを作成してください。
gcloud container clusters create vitness-example --zone=$(gcloud config get-value compute/zone) --scopes storage-rw
あとあとわかったのですが、--machine-type=n1-standard-4以上にしないとCPU
不足になり起動できませんので注意してください。**
ここでCloud Storageのスコープを付与しています。
バックアップ用のCloud Storageバケットを作成する
以下のように作成します。あまりアクセスしないので安いnearline
にしています。
gsutil mb nearline gs://vitess-backup-tutorial
設定ファイルconfig.shを作成
以下のように実行します。
./configure.sh Vitess Docker image (leave empty for default) []: Backup Storage (file, gcs) [gcs]: Google Cloud Storage bucket for Vitess backups: vitess-backup-tutorial NOTE: If you haven't already created this bucket, you can do so by running: gsutil mb gs://vitess-backup-tutorial
etcd-operatorを作成
etcd-operator
はKubernetes上でのetcdクラスタを管理します。
helm install stable/etcd-operator --name etcd-operator
以下の様に確認できます。
kubectl get pods NAME READY STATUS RESTARTS AGE etcd-operator-etcd-operator-etcd-backup-operator-6b697d96cxxvb4 1/1 Running 0 44s etcd-operator-etcd-operator-etcd-operator-676764c476-24spd 1/1 Running 0 44s etcd-operator-etcd-operator-etcd-restore-operator-7c8d68792nmhg 1/1 Running 0 44s
Topologyの起動
以下のようにクラスタの全てのデータをKey-Valueで持っているTopologyのためのetcd
を起動します。
./etcd-up.sh Creating etcd service for 'global' cell... etcdcluster.etcd.database.coreos.com/etcd-global created Creating etcd service for 'test' cell... etcdcluster.etcd.database.coreos.com/etcd-test created
すると以下のようになっています。
kubectl get pods etcd-global-794b9g2rjd 1/1 Running 0 10s etcd-global-swrt75dz5z 1/1 Running 0 34s etcd-global-tvz66j5vdp 1/1 Running 0 51s etcd-operator-etcd-operator-etcd-backup-operator-6b697d96cxxvb4 1/1 Running 0 2m etcd-operator-etcd-operator-etcd-operator-676764c476-24spd 1/1 Running 0 2m etcd-operator-etcd-operator-etcd-restore-operator-7c8d68792nmhg 1/1 Running 0 2m etcd-test-4qw4zhcqgk 1/1 Running 0 51s etcd-test-g2rrqck4lw 1/1 Running 0 34s etcd-test-vflnqk9n2x 1/1 Running 0 10s
vtcdldを起動
以下のようにしてvtcdld
を起動します。
./vtctld-up.sh Creating vtctld ClusterIP service... service/vtctld created Creating vtctld replicationcontroller... replicationcontroller/vtctld created To access vtctld web UI, start kubectl proxy in another terminal: kubectl proxy --port=8001 Then visit http://localhost:8001/api/v1/namespaces/default/services/vtctld:web/proxy
同じく確認すると以下のようになっています。
kubectl get pods NAME READY STATUS RESTARTS AGE etcd-global-794b9g2rjd 1/1 Running 0 1m etcd-global-swrt75dz5z 1/1 Running 0 1m etcd-global-tvz66j5vdp 1/1 Running 0 1m etcd-operator-etcd-operator-etcd-backup-operator-6b697d96cxxvb4 1/1 Running 0 3m etcd-operator-etcd-operator-etcd-operator-676764c476-24spd 1/1 Running 0 3m etcd-operator-etcd-operator-etcd-restore-operator-7c8d68792nmhg 1/1 Running 0 3m etcd-test-4qw4zhcqgk 1/1 Running 0 1m etcd-test-g2rrqck4lw 1/1 Running 0 1m etcd-test-vflnqk9n2x 1/1 Running 0 1m vtctld-p8n9p 0/1 ContainerCreating 0 27s
ポート転送をしてGUIを確認
以下のようにしてポート転送をします。
そして以下のURLにアクセスして確認してみます。
kubectl proxy --port=8001
port-forward
でもいけます。
kubectl port-forward vtctld-p8n9p 8001:15000
この違いは
kubectl proxy --port=8001
は汎用亭であるがゆえに、コンテナへのアクセスは
http:localhost:[PORT]/api/v1/proxy/namespaces/[ネームスペース]/services/[サービス名:コンテナのPort(ここではweb=15000である)/
であるのに対してkubectl port-forward
特定のPodへのポート転送なので
http://localhost:[PORT]
でアクセスできる違いがある。
ともあれ以下のURLにアクセスします。
http://localhost:8001/api/v1/proxy/namespaces/default/services/vtctld:web/
すると以下のような画面がみられるはずです。
gRPCでクライアントにアクセスする
以下のようにkvtlctl
を使うことでgRPCでアクセスすることができる。
./kvtctl.sh help
vttablesをインストール
Vitess tabletがスケールアウトを実現する上で必要である。以下のようにデプロイをします。
./vttablet-up.sh
ここでリソースが足りなかったのでスケールアウトさせました。
gcloud container clusters resize vitess-cluster --size=5
これでも足りなかったです。というよりCPUが足りないのでスケールアウトというよりはスケールアップをしないといけないのです。
以下のコマンドで確認できます。
./kvtctl.sh ListAllTablets test
MySQLの初期化
./kvtctl.sh InitShardMaster -force test_keyspace/0 vttablet-100
再度確認すると以下のようになっている。
./kvtctl.sh ListAllTablets test test-100 test_keyspace 0 master 10.64.1.6:15002 10.64.1.6:3306 [] test-101 test_keyspace 0 replica 10.64.2.5:15002 10.64.2.5:3306 [] test-102 test_keyspace 0 replica 10.64.0.7:15002 10.64.0.7:3306 [] test-103 test_keyspace 0 rdonly 10.64.1.7:15002 10.64.1.7:3306 [] test-104 test_keyspace 0 rdonly 10.64.2.6:15002 10.64.2.6:3306 []
MySQLのスキーマを書く
./kvtctl.sh ApplySchema -sql "$(cat create_test_table.sql)" test_keyspace
これは以下のようになっています。
CREATE TABLE messages ( page BIGINT(20) UNSIGNED, time_created_ns BIGINT(20) UNSIGNED, message VARCHAR(10000), PRIMARY KEY (page, time_created_ns) ) ENGINE=InnoDB
Backupをとる
以下のようにしてバックアップを取ってみます。
./kvtctl.sh Backup test-104
vgateをデプロイ
このままではルーティングをしてくれるvgate
がないためアクセスできません。
./vtgate-up.sh
のようにして立ち上げます。
アプリケーション側のコードを書いてデプロイ
これをvgate
あてに接続すれば大丈夫です。
今回はコードは省略します。
クリーンアップ
以下のようにしてクリーンアップします。
./vtgate-down.sh ./vttablet-down.sh ./vtctld-down.sh ./etcd-down.sh
Vitess Client Library
Goのライブラリは以下の通りです。
このvt
以下にVitess用のライブラリが入っています。
api一つにつき、Protocol BufferのServiceが一つ定義されているのでimportして使うとAPIを使うことができる。
まとめ
- Vitess ClusterはKubernetes Cluster内で構築されたクラスタであり、決してKubernetesクラスタが二つあるわけではない
- etcd Clusterも構築しないといけないので面倒
- アプリケーション側は特に意識する必要があるものはない