k8ssandraを試す
こちらの記事に取り上げられたK8ssandraをローカルのDockerを使って動かしてみます。
K8ssandra = Cassandra on Kubernetes (k8s)
Apache Cassandraはオープンソースで開発されている分散データベースです。
現在の安定版はv3.11.7、次のメジャーバージョンである4.0のリリースに向けて開発が進められています。
分散データベースということは、複数台のノードが協調して動きます。
通常は、手順書に沿って1台1台インストール・設定を行ったり、Ansibleなどでそれらの手順をある程度自動化したりしてデータベースを構築します。また、データベースだけでなく、監視や運用の仕組みを別途組み込む必要があることも多々あります。
それがKubernetes基盤上に展開できれば、データベース単体だけでなく、運用や監視に必要な機能も、Kubernetesの仕組みを利用して容易にセットアップが行うことができるようになります。
なお発音に関しては、こちらを見ると、"Kate" + "Sandra" みたいな感じとのこと。
私は"ケイトサンドラ"と呼んでいます。
OverviewやArchitectureのページを確認すると、Apache Cassandra本体の他に
- Prometheus - メトリクス収集
- Grafana - 監視用ダッシュボード
- cassandra-reaper - リペア(データ同期)スケジューラ
がインストールされるようです。バックアップや復元、CassandraへREST APIやGraphQL経由でのアクセスを可能にするStargateも将来は組み込まれるようです。
今回試す環境
筆者のWindowsマシンで、Docker on Windowsを用いて試します。
WSL2は.wslconfig
ファイルで以下のように設定しています。
[wsl2]
memory=12GB
processors=4
必要なツール
複数のワーカーノードを利用したいので、Kubernetes環境はKindで構築します。
手元のKind環境は
❯ kind version
kind v0.9.0 go1.14.4 windows/amd64
です。
Kindクラスターの構築
クラスター用のyamlファイルを用意します。ワーカーノードを3台作成し、後でブラウザからいろいろなサービスのUIにアクセスするため、ホストからのアクセスをマッピングする設定も行います。
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 32080
hostPort: 80
protocol: TCP
- containerPort: 32443
hostPort: 443
protocol: TCP
- role: worker
- role: worker
- role: worker
上のyamlをkind-cluster.yamlとして作成し、Kindクラスターを作成します。
❯ kind create cluster --config=kind-cluster.yaml
Creating cluster "kind" ...
• Ensuring node image (kindest/node:v1.19.1) 🖼 ...
✓ Ensuring node image (kindest/node:v1.19.1) 🖼
• Preparing nodes 📦 📦 📦 📦 ...
✓ Preparing nodes 📦 📦 📦 📦
• Writing configuration 📜 ...
✓ Writing configuration 📜
• Starting control-plane 🕹️ ...
✓ Starting control-plane 🕹️
• Installing CNI 🔌 ...
✓ Installing CNI 🔌
• Installing StorageClass 💾 ...
✓ Installing StorageClass 💾
• Joining worker nodes 🚜 ...
✓ Joining worker nodes 🚜
Set kubectl context to "kind-kind"
You can now use your cluster with:
kubectl cluster-info --context kind-kind
Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
確認してみましょう。
❯ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready master 64s v1.19.1
kind-worker Ready <none> 33s v1.19.1
kind-worker2 Ready <none> 34s v1.19.1
kind-worker3 Ready <none> 34s v1.19.1
K8ssandraのインストール
Getting startedのページに沿って解説しながら進めていきます。
Helmレポジトリの追加
k8ssandraとtraefikのhelmレポジトリを追加し、更新しておきます。
Traefikは、Kubetenetesの外部からKubetenetes内のサービスにアクセスするためのゲートウェイを提供します。
後ほどGrafanaのダッシュボードなどにアクセスするために使います。
helm repo add k8ssandra https://helm.k8ssandra.io/
helm repo add traefik https://helm.traefik.io/traefik
helm repo update
実行してみます。
❯ helm repo add k8ssandra https://helm.k8ssandra.io/
"k8ssandra" has been added to your repositories
❯ helm repo add traefik https://helm.traefik.io/traefik
"traefik" has been added to your repositories
❯ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "k8ssandra" chart repository
...Successfully got an update from the "traefik" chart repository
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈ Happy Helming!⎈
k8ssandraのインストールとCassandraクラスターの構築
Helmを使って、まずはk8ssandraクラスター構築に必要なオペレーターやカスタムリソース定義(CRD)を提供するk8ssandra-tools
をインストールします。
k8ssandra-tools
は今のところKubernetestクラスター全体で利用する方法しかないため、本記事では専用の名前空間に展開します。
helm install -n k8ssandra-tools --create-namespace k8ssandra-tools k8ssandra/k8ssandra
実行してみましょう。
❯ helm install -n k8ssandra-tools --create-namespace k8ssandra-tools k8ssandra/k8ssandra
NAME: k8ssandra-tools
LAST DEPLOYED: Tue Nov 24 09:53:32 2020
NAMESPACE: k8ssandra-tools
STATUS: deployed
REVISION: 1
TEST SUITE: None
❯ kubectl -n k8ssandra-tools get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
cass-operator 1/1 1 1 33s
k8ssandra-tools-kube-prome-operator 1/1 1 1 33s
DataStaxが開発しているApache Cassandraのオペレーターcass-operatorと、
Prometheusをインストールするオペレーターがインストールされました。
次にCassandraクラスターを構築します。こちらもCassandraクラスター用の名前空間にインストールしましょう。
helm install -n cass --create-namespace k8ssandra-cluster-a k8ssandra/k8ssandra-cluster
実行します。
❯ helm install -n cass --create-namespace k8ssandra-cluster-a k8ssandra/k8ssandra-cluster
NAME: k8ssandra-cluster-a
LAST DEPLOYED: Tue Nov 24 10:06:54 2020
NAMESPACE: cass
STATUS: deployed
REVISION: 1
TEST SUITE: None
❯ kubectl -n cass get deploy,sts,job
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/grafana-deployment 1/1 1 1 6m15s
deployment.apps/k8ssandra-cluster-a-grafana-operator-k8ssandra 1/1 1 1 7m
deployment.apps/k8ssandra-cluster-a-reaper-k8ssandra 1/1 1 1 3m7s
deployment.apps/k8ssandra-cluster-a-reaper-operator-k8ssandra 1/1 1 1 7m
NAME READY AGE
statefulset.apps/k8ssandra-dc1-default-sts 1/1 6m49s
statefulset.apps/prometheus-k8ssandra-cluster-a-prometheus-k8ssandra 1/1 6m59s
NAME COMPLETIONS DURATION AGE
job.batch/k8ssandra-cluster-a-reaper-k8ssandra-schema 1/1 3m28s 6m38s
grafana、cassandra-reaperとともにCassandra(k8ssandra-dc1-default-sts)1ノードが起動しました。
Cassandraにアクセスしてみる
クラスター状態の確認
Cassandraクラスターはカスタムリソース(CassandraDatacenter, cassdc)を使って定義されています。
kubectlを使って状態を確認してみましょう。
❯ kubectl -n cass describe cassdc/dc1
Name: dc1
Namespace: cass
Labels: app.kubernetes.io/instance=k8ssandra-cluster-a
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=k8ssandra-cluster
app.kubernetes.io/version=3.11.7
helm.sh/chart=k8ssandra-cluster-0.11.0
Annotations: meta.helm.sh/release-name: k8ssandra-cluster-a
meta.helm.sh/release-namespace: cass
reaper.cassandra-reaper.io/instance: k8ssandra-cluster-a-reaper-k8ssandra
API Version: cassandra.datastax.com/v1beta1
Kind: CassandraDatacenter
...
次に直接コンテナにアクセスして、Cassandraの管理ツールであるnodetoolを使ってみます。
❯ kubectl -n cass get pod
NAME READY STATUS RESTARTS AGE
grafana-deployment-568564cd48-zwmtl 1/1 Running 0 6m37s
k8ssandra-cluster-a-grafana-operator-k8ssandra-5bcb746b8d-8lqdd 1/1 Running 0 8m32s
k8ssandra-cluster-a-reaper-k8ssandra-6cf5b87b8f-vhdpk 1/1 Running 0 4m40s
k8ssandra-cluster-a-reaper-k8ssandra-schema-wnlkr 0/1 Completed 5 8m11s
k8ssandra-cluster-a-reaper-operator-k8ssandra-55dc486998-wjbjl 1/1 Running 0 8m32s
k8ssandra-dc1-default-sts-0 2/2 Running 0 8m22s
prometheus-k8ssandra-cluster-a-prometheus-k8ssandra-0 2/2 Running 1 8m32s
k8ssandra-dc1-default-sts-0
がCassandraのポッドです。その中のcassandra
コンテナにアクセスします。
❯ kubectl -n cass exec -it k8ssandra-dc1-default-sts-0 -c cassandra -- nodetool status
nodetool: Failed to connect to '127.0.0.1:7199' - SecurityException: 'Authentication failed! Credentials required'.
command terminated with exit code 1
ユーザー認証が必要なようですね。nodetoolはJMX経由でアクセスするため、それらしい設定があるか確認してみましょう。
❯ kubectl -n cass get pod k8ssandra-dc1-default-sts-0 -o yaml
...
- env:
- name: LOCAL_JMX
value: "no"
...
env:
- name: JMX_USERNAME
valueFrom:
secretKeyRef:
key: username
name: k8ssandra-cluster-a-reaper-secret-k8ssandra
- name: JMX_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: k8ssandra-cluster-a-reaper-secret-k8ssandra
...
cassandra-reaperを使ってリモートからリペアを実行するためにこのような設定になっているようです。
JMXユーザー名とパスワードはk8ssandra-cluster-a-reaper-secret-k8ssandra
のシークレットにあるので取得します。
❯ kubectl -n cass get secret k8ssandra-cluster-a-reaper-secret-k8ssandra -o jsonpath="{.data.username}" | base64 -d
lcohLJc0cU
❯ kubectl -n cass get secret k8ssandra-cluster-a-reaper-secret-k8ssandra -o jsonpath="{.data.password}" | base64 -d
DKHLYz3xjX
❯ kubectl -n cass exec -it k8ssandra-dc1-default-sts-0 -c cassandra -- nodetool -u lcohLJc0cU -pw DKHLYz3xjX status
Datacenter: dc1
===============
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Owns (effective) Host ID Token Rack
UN 10.244.1.6 153.69 KiB 100.0% f017222c-6e77-4362-a4d4-42a4f3872b0b 5267804669664362995 default
1台のノードのクラスターが構築されていることが確認できました。
cqlshでのアクセス
CassandraにはコマンドラインでCQL(Cassandra Query Language)が実行できるcqlsh
がついています。これを使ってデータを取得してみます。
❯ kubectl -n cass exec -it k8ssandra-dc1-default-sts-0 -c cassandra -- cqlsh
Connected to k8ssandra at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 3.11.7 | CQL spec 3.4.4 | Native protocol v4]
Use HELP for help.
cqlsh> SELECT cluster_name FROM system.local;
cluster_name
--------------
k8ssandra
(1 rows)
こちらはユーザー認証はかかってないようですね。このクラスターのクラスター名はk8ssandra
のようです。
Grafanaおよびcassandra-reaperへのアクセス
Cassaandraクラスターと共にGrafanaやcassandra-reaperが構築されたので、それらにアクセスしてみましょう。このページを参考にします。
Traefik Ingressコントローラーの設定
外部からKubernetes内部のサービスにアクセスするために、IngressコントローラーとしてTraefikを利用します。k8ssandraと同じくhelmコマンドでインストールしますが、Kind環境で動かせるようインストールのカスタマイズを行います。kindクラスターを構築した際の設定と以下の設定を行うことで、http://localhost/ にアクセスした際にTraefikにリクエストが渡るようにします。
ports:
web:
nodePort: 32080
websecure:
nodePort: 32443
service:
type: NodePort
上のyamlをtraefik.values.yamlとしてファイルに保存し、helmでのインストール時に指定します。
❯ helm install -n cass traefik traefik/traefik -f traefik.values.yaml
NAME: traefik
LAST DEPLOYED: Tue Nov 24 16:14:41 2020
NAMESPACE: cass
STATUS: deployed
REVISION: 1
TEST SUITE: None
grafanaおよびcassandra-reaperへのルートを追加します。以下の設定では、ホスト名がgrafana.localhostの場合はgrafana用のサービスへ、reaper.localhostの場合はcassandra-reaper用のサービスへと振り分けます。
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-k8ssandra-route
spec:
entryPoints:
- web
routes:
- match: Host(`grafana.localhost`)
kind: Rule
services:
- name: grafana-service
port: 3000
- match: Host(`reaper.localhost`)
kind: Rule
services:
- name: k8ssandra-cluster-a-reaper-k8ssandra-reaper-service
port: 8080
上のyamlをingress.yamlとしてファイルに保存し、設定を適用します。
❯ kubectl -n cass apply -f ingress.yaml
ingressroute.traefik.containo.us/traefik-k8ssandra-route created
Grafanaへのアクセス
http://grafana.localhost にアクセスするとGrafanaのログイン画面が表示されるはずです。
ユーザー名とパスワードはシークレットに登録されています。
❯ kubectl -n cass get secret grafana-admin-credentials -o jsonpath="{.data.GF_SECURITY_ADMIN_USER}" | base64 -d
admin
❯ kubectl -n cass get secret grafana-admin-credentials -o jsonpath="{.data.GF_SECURITY_ADMIN_PASSWORD}" | base64 -d
secret
左側のメニューから Dashboard > Manage
と選択すると、あらかじめ設定されたダッシュボードを表示することができます。
cassandra-reaperへのアクセス
Cassandraのリペアスケジューラーであるcassandra-reaperには以下のURLでアクセスできます。
すでに構築したクラスターが登録されていますね。ここから、Web UIを用いてリペアをスケジュールできます。
スケールアウト
デフォルトでは1台のクラスターが構築されるため、スケールアウトして3台構成のクラスターにしてみましょう。
helm upgrade コマンドを用いて新しいノード数に変更するだけでスケールアウトします。
❯ helm -n cass upgrade k8ssandra-cluster-a k8ssandra/k8ssandra-cluster --set size=3
Release "k8ssandra-cluster-a" has been upgraded. Happy Helming!
NAME: k8ssandra-cluster-a
LAST DEPLOYED: Tue Nov 24 18:35:18 2020
NAMESPACE: cass
STATUS: deployed
REVISION: 2
TEST SUITE: None
❯ kubectl -n cass get pod
NAME READY STATUS RESTARTS AGE
grafana-deployment-568564cd48-8kdw9 1/1 Running 0 88m
k8ssandra-cluster-a-grafana-operator-k8ssandra-5bcb746b8d-qz95g 1/1 Running 0 90m
k8ssandra-cluster-a-reaper-k8ssandra-6cf5b87b8f-78dtg 1/1 Running 0 86m
k8ssandra-cluster-a-reaper-k8ssandra-schema-48pfq 0/1 Completed 5 90m
k8ssandra-cluster-a-reaper-operator-k8ssandra-55dc486998-855sj 1/1 Running 0 90m
k8ssandra-dc1-default-sts-0 2/2 Running 0 90m
k8ssandra-dc1-default-sts-1 2/2 Running 0 41m
k8ssandra-dc1-default-sts-2 2/2 Running 0 41m
prometheus-k8ssandra-cluster-a-prometheus-k8ssandra-0 2/2 Running 1 90m
traefik-77fdb5c487-ghtfd
Cassandraのポッドk8ssandra-dc1-default-sts-1
とk8ssandra-dc1-default-sts-2
が追加されていますね。
Grafana上でも3ノードのステータスが表示されています。
また、nodetool status
を確認すると
❯# kubectl -n cass exec -it k8ssandra-dc1-default-sts-0 -c cassandra -- nodetool -u lcohLJc0cU -pw DKHLYz3xjX status
Datacenter: dc1
===============
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns (effective) Host ID Rack
UN 10.244.1.6 177.08 KiB 1 16.0% f017222c-6e77-4362-a4d4-42a4f3872b0b default
UN 10.244.2.9 92.55 KiB 1 38.1% ca96d104-458d-4a29-ae3d-9ac7a24e7015 default
UN 10.244.3.10 102.5 KiB 1 45.9% 46de0ae5-7745-4291-a542-badeda88f0aa default
となり3台構成のクラスターに確かにスケールアウトしました。ただ、トークンの数が1で、トークンがランダムに割り振られているため、非常に偏りがありますね。このあたりはCassandraの設定ファイルcassandra.yamlで設定していくのですがそのあたりのカスタマイズがどのようにできるかは今後調べていきたいと思います。
まとめ
まだ登場したばかりなので、細かいCassandraクラスター自身の設定がどのようにできるかは気になりますが、k8cassandraを使うとkubernetes上でCassandraクラスターを運用・監視まで含めて簡単に行えるようです。
今後もバックアップや復元への対応などさらなる周辺技術を組み合わせて進化していくことで、本番環境でも使えるようになってほしいものです。
Discussion