ラズパイ4でK8ssandra動かしてみた
はじめに
以前構築したラズパイK8sクラスタが自宅の片隅で文鎮と化していたので、K8ssandra を試してみることにしました。
仕事で DSE を利用していることもあり、前から気になっていたんですよね。
K8ssandraとは
こちらに記載ありました。
CassandraがKubernetes上で実行できるぐらいに思っておけばよいですかね。個人的にはずっとなんて呼ぶんだろうと気になっていましたが、それもしっかり記載されていました。
Any way you want! Many of the team members pronounce it as “Kate” + “Sandra”.
なんでもいいよが一番困る気がしますが、とりあえず「ケイトサンドラ」と呼ぶことにしました。
動作環境
Kubernetes(Rasberry Pi4): v1.19.2
Helm: v3.3.0
K8ssandra:v1.3.0
Cassandra:3.11.10
K8s と Helm は既に導入済みのものを利用しており、バージョンなどは特に気にしていません。
エミュレータの導入
いきなり helm install
でデプロイしたいところですが、今回ラズパイ4で構築した K8s クラスタを使っているの少し下準備が必要です。
K8ssandra で使われているイメージが、ARM 対応してるものとそうでないものがあるので、そのままでは動かすことができません。
今回は Qemu というオープンソースのプロセッサエミュレータを使うことにします。
debパッケージはこちらからダウンロードしました。
$ wget http://ftp.jp.debian.org/debian/pool/main/q/qemu/qemu-user-static_6.1+dfsg-6_arm64.deb
$ sudo dpkg -i qemu-user-static_6.1+dfsg-6_arm64.deb
$ sudo apt install qemu-user-static
$ sudo apt install binfmt-support
$ apt list --installed | grep -e qemu-user-static -e binfmt-support
binfmt-support/focal,now 2.2.0-2 arm64 [installed]
qemu-user-static/now 1:6.1+dfsg-6 arm64 [installed,local]
$ reboot -h now
再起動後にバージョンを確認して、指定したバージョンが入っていれば OK です。
ついでに、x86 の ubuntu イメージを実行して確認してみます。
$ qemu-x86_64-static --version
qemu-x86_64 version 6.1.0 (Debian 1:6.1+dfsg-6)
Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers
$ docker run --rm -it bitnami/ubuntu-base-buildpack:latest /bin/bash -c 'uname -m'
x86_64
上記の操作を Master, Worker 含め全てのノードで実施しました。
K8ssandraデプロイ
dc1 というデータセンターに、バージョン 4.0.1 の Cassandra ノードを1つ持つ K8ssandra クラスタを作成します。
基本的にはこちらを参考にしています。
あとは以下の記事も参考にさせていただきました。
似たような部分も多いです。もしかしたらこちらの記事の方が参考になるかもしれません。Helm のリポジトリを登録します。
K8ssandra 1.0からは、Stable と Next の2つが公開されています。特に理由はないですが、今回はNextを使ってみます。
詳しくはこちらをご確認ください。
$ helm repo add k8ssandra https://helm.k8ssandra.io/next
$ helm repo list
NAME URL
kong https://charts.konghq.com
jenkins https://charts.jenkins.io
nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
k8ssandra https://helm.k8ssandra.io/next
grafana https://grafana.github.io/helm-charts
metallb https://metallb.github.io/metallb
一部設定を変更したいので、Helm の Charts もダウンロードしておきます。
$ helm pull k8ssandra/k8ssandra --untar
values.yaml の以下を書き換えて利用します。
$ cd k8ssandra
$ diff -u values.org.yaml values.yaml
--- values.org.yaml 2021-11-03 18:36:15.000000000 +0900
+++ values.yaml 2021-11-03 17:04:36.000000000 +0900
@@ -123,7 +123,7 @@
# underlying cassandra pods. Depending on your Kubernetes distribution this
# may be named "standard", "hostpath", or "localpath". Run `kubectl get
# storageclass` to identify what is available in your environment.
- storageClass: standard
+ storageClass: nfs
# -- Size of the provisioned persistent volume per node. It is recommended
# to keep the total amount of data per node to approximately 1 TB. With room
# for compactions this value should max out at ~2 TB. This recommendation is
@@ -177,9 +177,9 @@
# Options are commented out for reference. Note that k8ssandra does not
# automatically apply default values for heap size. It instead defers to
# Cassandra's out of box defaults.
- heap: {}
- #size:
- #newGenSize:
+ heap:
+ size: 1G
+ newGenSize: 1G
# -- Optional cluster-level garbage collection configuration. It can be overridden at
# the datacenter level.
@@ -229,7 +229,13 @@
# -- Resource requests for each Cassandra pod. See
# https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
# for background on managing resources.
- resources: {}
+ resources:
+ requests:
+ cpu: 1000m
+ memory: 2Gi
+ limits:
+ cpu: 1000m
+ memory: 2Gi
# Tolerations to apply to the Cassandra pods. See
# https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ for background.
tolerations: []
storageClass
は任意のものを指定してください。今回は nfs-subdir-external-provisioner
を使っています。
helm install
をしてみます。
$ kubectl create ns cassandra
namespace/cassandra created
$ helm install -n cassandra -f values.yaml k8ssandra k8ssandra/k8ssandra
なかなか k8ssandra-dc1-default-sts-0
が立ち上がらないので調べてみるとinit container
が失敗していたようで、原因は放置していた Pod たちでした。
クラスタ全体で見たら CPU/MEM 供に 40% 程度だったのでスルーしていたのですが、Node 単位で確認すると、ワーカーノードの1つが 90% 近くになっていました。
もろもろ整理して再度実行してみました。
$ helm upgrade -n cassandra -f values.yaml k8ssandra k8ssandra/k8ssandra
30分ぐらい待っても Stargate が起動しないので log 見てみたところ、 Service の名前解決ができていないようです。
$ kubectl -n cassandra logs k8ssandra-dc1-stargate-7847f6bfb9-prprt -c wait-for-cassandra
Server: 10.96.0.10
Address: 10.96.0.10:53
** server can't find k8ssandra-seed-service.cassandra.svc.cluster.local: NXDOMAIN
** server can't find k8ssandra-seed-service.cassandra.svc.cluster.local: NXDOMAIN
kubectl -n cassandra run -it --rm=true busybox --image=yauritux/busybox-curl --restart=Never
/home # nslookup k8ssandra-seed-service
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
nslookup: can't resolve 'k8ssandra-seed-service'
いろいろ調べてみたけど解決できず、途方に暮れていたら勝手に起動していました。
ラズパイで動かしていたので、起動に時間がかかった感じですかね。エミュレータ使っているのも影響ある気がします。
そこら辺はまた今後調べてみようと思います。
ちなみに起動したのは実行してから45分ほど経ってからでした。
$ kubectl -n cassandra logs k8ssandra-dc1-stargate-7847f6bfb9-prprt -c wait-for-cassandra -f
Server: 10.96.0.10
Address: 10.96.0.10:53
** server can't find k8ssandra-seed-service.cassandra.svc.cluster.local: NXDOMAIN
** server can't find k8ssandra-seed-service.cassandra.svc.cluster.local: NXDOMAIN
Server: 10.96.0.10
Address: 10.96.0.10:53
** server can't find k8ssandra-seed-service.cassandra.svc.cluster.local: NXDOMAIN
** server can't find k8ssandra-seed-service.cassandra.svc.cluster.local: NXDOMAIN
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: k8ssandra-seed-service.cassandra.svc.cluster.local
Address: 10.244.1.189
Cassandra is ready. Starting Stargate...
デプロイ後は以下のようになっていました。
$ kubectl -n cassandra get po, svc
NAME READY STATUS RESTARTS AGE
pod/k8ssandra-cass-operator-6ffc65b9f6-q6vc9 1/1 Running 0 110m
pod/k8ssandra-dc1-default-sts-0 2/2 Running 0 109m
pod/k8ssandra-dc1-stargate-7847f6bfb9-prprt 1/1 Running 0 110m
pod/k8ssandra-grafana-74db456fdb-q89dz 2/2 Running 0 110m
pod/k8ssandra-kube-prometheus-operator-8487f5df79-4v86v 1/1 Running 0 110m
pod/k8ssandra-reaper-operator-766696f6d4-xq884 1/1 Running 0 110m
pod/prometheus-k8ssandra-kube-prometheus-prometheus-0 2/2 Running 1 110m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/cass-operator-metrics ClusterIP 10.99.180.101 <none> 8383/TCP,8686/TCP 109m
service/k8ssandra-dc1-all-pods-service ClusterIP None <none> 9042/TCP,8080/TCP,9103/TCP 109m
service/k8ssandra-dc1-service ClusterIP None <none> 9042/TCP,9142/TCP,8080/TCP,9103/TCP,9160/TCP 109m
service/k8ssandra-dc1-stargate-service ClusterIP 10.108.191.46 <none> 8080/TCP,8081/TCP,8082/TCP,8084/TCP,8085/TCP,9042/TCP 110m
service/k8ssandra-grafana ClusterIP 10.99.62.237 <none> 80/TCP 110m
service/k8ssandra-kube-prometheus-operator ClusterIP 10.109.162.74 <none> 443/TCP 110m
service/k8ssandra-kube-prometheus-prometheus ClusterIP 10.96.223.229 <none> 9090/TCP 110m
service/k8ssandra-seed-service ClusterIP None <none> <none> 109m
service/prometheus-operated ClusterIP None <none> 9090/TCP 110m
K8ssandra の資格情報を取得
Cassandra ユーティリティにアクセスし、Stargate アクセストークンを生成するなどの操作を行うには、K8ssandra のスーパーユーザー名とパスワードが必要です。
Secret から情報を取得し、デコードします。
$ kubectl -n cassandra get secret k8ssandra-superuser -o jsonpath='{.data.username}{"\n"}{.data.password}' | xargs -I{} sh -c "echo {} | base64 -d; echo"
k8ssandra-superuser
18yKg1APBIiR1AHzXB0D
Cassandra へのアクセス
公式のクイックスタートドキュメントには、K8ssandra 開発者向けと K8ssandra 管理者向けの2種類がありましたが、今回は K8ssandra 開発者向けを試してみます。
外部からCassanndraクラスタにアクセスするために、まずは k8ssandra-dc1-stargate-service
に対してポートフォワーディングをおこないます。
kubectl -n cassandra port-forward svc/k8ssandra-dc1-stargate-service 8080 8081 8082 9042 &
$
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
Forwarding from 127.0.0.1:8081 -> 8081
Forwarding from [::1]:8081 -> 8081
Forwarding from 127.0.0.1:8082 -> 8082
Forwarding from [::1]:8082 -> 8082
Forwarding from 127.0.0.1:9042 -> 9042
Forwarding from [::1]:9042 -> 9042
StargateAPIを使用してCassandraにアクセス
Stargate は、Cassandra に保存されているデータにCRUDアクセスするための Document、REST 、GraphQL APIなどを提供してくれるようです。
詳しくはこちらにあります。
トークンを取得します。
$ curl -L -X POST 'http://localhost:8081/v1/auth' -H 'Content-Type: application/json' --data-raw '{"username": "k8ssandra-superuser", "password": "18yKg1APBIiR1AHzXB0D"}'
Handling connection for 8081
{"authToken":"0aa12133-93f9-477f-bbc8-dcca177c6c6b"}⏎
次に Keyspace の取得を試してみます。
以下を参考にしてます。
$ set AUTH_TOKEN 0aa12133-93f9-477f-bbc8-dcca177c6c6b
$ curl -sL -X GET 'http://localhost:8082/v2/schemas/keyspaces' -H "X-Cassandra-Token: $AUTH_TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" | jq
Handling connection for 8082
{
"data": [
{
"name": "system_schema"
},
{
"name": "system"
},
{
"name": "system_distributed",
"datacenters": [
{
"name": "dc1",
"replicas": 1
}
]
},
{
"name": "system_traces",
"datacenters": [
{
"name": "dc1",
"replicas": 1
}
]
},
{
"name": "system_auth",
"datacenters": [
{
"name": "dc1",
"replicas": 1
}
]
},
{
"name": "stargate_system"
},
{
"name": "data_endpoint_auth"
}
]
}
きちんと Keyspace が取ってこれてますね。
次は Keyspace を作成してみます。
$ curl -sL -X POST 'localhost:8082/v2/schemas/keyspaces' -H "X-Cassandra-Token: $AUTH_TOKEN" -H 'Content-Type: application/json' -d '{"name": "my_k8ssandra_keyspace"}'
Handling connection for 8082
{"name":"my_k8ssandra_keyspace"}⏎
$ curl -sL -X GET 'localhost:8082/v2/schemas/keyspaces' -H "X-Cassandra-Token: $AUTH_TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" | jq
Handling connection for 8082
{
"data": [
{
"name": "system_schema"
},
{
"name": "system"
},
{
"name": "system_distributed",
"datacenters": [
{
"name": "dc1",
"replicas": 1
}
]
},
{
"name": "system_traces",
"datacenters": [
{
"name": "dc1",
"replicas": 1
}
]
},
{
"name": "system_auth",
"datacenters": [
{
"name": "dc1",
"replicas": 1
}
]
},
{
"name": "stargate_system"
},
{
"name": "data_endpoint_auth"
},
{
"name": "my_k8ssandra_keyspace"
}
]
}
my_k8ssandra_keyspace
が追加されていることが確認できました。
CQLSHを使用してCassandraにアクセスする
次はCQL使ってみます。
自分のMacにCQLクライアントは入ってなかったので、コンテナに入って試してみます。
kubectl -n cassandra exec -it k8ssandra-dc1-default-sts-0 -- /bin/bash
Defaulting container name to cassandra.
Use 'kubectl describe pod/k8ssandra-dc1-default-sts-0 -n cassandra' to see all of the containers in this pod.
cassandra@k8ssandra-dc1-default-sts-0:/$ which cqlsh
/opt/cassandra/bin/cqlsh
cassandra@k8ssandra-dc1-default-sts-0:/$
cassandra@k8ssandra-dc1-default-sts-0:/$ cqlsh -u k8ssandra-superuser -p 18yKg1APBIiR1AHzXB0D
Connected to k8ssandra at 127.0.0.1:9042
[cqlsh 6.0.0 | Cassandra 4.0.1 | CQL spec 3.4.5 | Native protocol v5]
Use HELP for help.
k8ssandra-superuser@cqlsh>
先ほど作成した Keyspace があるか確認してみます。
k8ssandra-superuser@cqlsh> desc keyspaces
data_endpoint_auth system_auth system_traces
my_k8ssandra_keyspace system_distributed system_views
system system_schema system_virtual_schema
ありましたね。別の Keyspace も作成して、何かデータを入れて確認してみます。
k8ssandra-superuser@cqlsh> CREATE KEYSPACE my_k8ssandra_cql_keyspac WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};
k8ssandra-superuser@cqlsh> desc keyspaces
data_endpoint_auth system_auth system_views
my_k8ssandra_cql_keyspac system_distributed system_virtual_schema
my_k8ssandra_keyspace system_schema
system system_traces
k8ssandra-superuser@cqlsh> USE my_k8ssandra_cql_keyspac;
k8ssandra-superuser@cqlsh:my_k8ssandra_cql_keyspac> CREATE TABLE users (email text primary key, name text, state text);
k8ssandra-superuser@cqlsh:my_k8ssandra_cql_keyspac> INSERT INTO users (email, name, state) values ('alice@example.com', 'Alice Smith', 'TX');
k8ssandra-superuser@cqlsh:my_k8ssandra_cql_keyspac> INSERT INTO users (email, name, state) values ('bob@example.com', 'Bob Jones', 'VA');
k8ssandra-superuser@cqlsh:my_k8ssandra_cql_keyspac> INSERT INTO users (email, name, state) values ('carol@example.com', 'Carol Jackson', 'CA');
k8ssandra-superuser@cqlsh:my_k8ssandra_cql_keyspac> INSERT INTO users (email, name, state) values ('david@example.com', 'David Yang', 'NV');
SELECTを使用して返される結果をみてみます。
k8ssandra-superuser@cqlsh:my_k8ssandra_cql_keyspac> SELECT * FROM my_k8ssandra_cql_keyspac.users;
email | name | state
-------------------+---------------+-------
alice@example.com | Alice Smith | TX
bob@example.com | Bob Jones | VA
david@example.com | David Yang | NV
carol@example.com | Carol Jackson | CA
(4 rows)
INSERTしたデータがありますね。
基本的なCQLを操作できることを確認できました。
最後にポートフォワーディングは終了させておきます。
$ jobs -l | grep kubectl
37063 running kubectl -n cassandra port-forward svc/k8ssandra-dc1-stargate-service 8080 8081 8082 9042 &
$ kill 37063
kubectl -n cassandra port-forwa…' terminated by signal SIGTERM (Polite quit request)
まとめ
ラズパイK8sクラスタ上でK8ssandraを導入し、Cassanndraを試してみることができました。
Helm使って簡単に構築できるのはいいですね。
Stargateは簡単にしか触れてないので、時間があれば細かく見てみたいと思います。
今回はエミュレータを使って無理やり動作させましたが、今後はARMにも対応していくのかなと思っています。(k8ssandra/cass-management-apiとかはARMイメージ対応しているようでした)
管理用のツールも一緒に導入されるので、次はそっちも触ってみようと思います
参考
https://k8ssandra.io/
https://stargate.io/docs/stargate/1.0/quickstart/quickstart.html
https://zenn.dev/t_ume/articles/e62b1e837e5cd2#アクセス確認(開発者版)
https://zenn.dev/yukim/articles/e12ebb70040068
Discussion