お試し K8ssandra
はじめに
今回は K8ssandra をお試ししていきます。
K8ssandra は Kubernetes 上に Cassandra をデプロイ・管理するためのソフトウェアです。
こちらの素敵な資料がチーム内で共有されてきたので、お試しでということで実際に構築して記事にしました。
今回は実際に K8ssandra を使って、Cassandra を構築し、クライアントツールを使ってアクセスしたいと思います。デプロイは以下を参考にさせて頂きました。
環境情報
Kubernetes:v1.20.6
※PV に Cephを利用しています
helm:v3.5.4
K8ssandra:v1.3.0
Cassandra:3.11.10
以下、リソースについてサイトより抜粋します。
推奨
RAM:16GB
CPU:4core(8vCPU)QuickStart
RAM:8GB
CPU:4vCPU
K8ssandra 構成
まずは K8ssandra の構成を確認していきます。
各コンポーネント毎に、Helm Chart が用意されています。
Apache Cassandra
- Cassandra 本体
- cass-operator を利用して、Cassandra がデプロイ、管理される。
- 以下の機能が自動的に起動するように追加で構成されている。
- MAAC(Management API for Apache Cassandra):Cassandra 管理用の API
- MCAC(Metrics Collector for Apache Cassandra):メトリクスの収集とダッシュボード
Stargate
- Cassandra へ REST / GraphQL / Document API でのアクセスを提供
Reaper
- Apache Cassandra の Repair(データ同期) を自動的にスケジューリング、管理
- Repair の進行状況を視覚化できる Web インターフェイスを提供
Medusa
- Apache Cassandra のバックアップ・リストアを提供
デプロイ準備
デプロイの前に準備作業を行います。
最初に helm
のリポジトリを登録します。
$ helm repo add k8ssandra https://helm.k8ssandra.io/stable
"k8ssandra" has been added to your repositories
$ helm repo update
・・・
...Successfully got an update from the "k8ssandra" chart repository
Update Complete. ⎈Happy Helming!⎈
登録したリポジトリ内のチャートは以下のとおりです。
$ helm search repo k8ssandra
NAME CHART VERSION APP VERSION DESCRIPTION
k8ssandra/k8ssandra 1.3.0 Provisions and configures an instance of the en...
k8ssandra/k8ssandra-common 0.28.3 Helper library containing functions used by man...
k8ssandra/backup 0.26.0 Creates a CassandraBackup custom resource insta...
k8ssandra/cass-operator 0.29.4 1.7.1 Kubernetes operator which handles the provision...
k8ssandra/medusa-operator 0.30.1 0.1.0 Installs and configures the Medusa Operator for...
k8ssandra/reaper-operator 0.32.0 0.1.0 Configures and installs the Reaper Operator for...
k8ssandra/restore 0.27.1 Creates a CassandraRestore custom resource inst...
変数定義用のテンプレートファイル(values.yaml)を取得したいので、helm pull
コマンドでチャート情報を取得します。
# --untar で zip ファイルを自動で解凍
$ helm pull k8ssandra/k8ssandra --untar
$ cd k8ssandra
$ ls
Chart.lock Chart.yaml README.md charts dashboards templates values.yaml
values.yaml
の以下を書き換えて利用します。
- cassandra.version:Cassandra のバージョン
- cassandra.cassandraLibDirVolume.storageClass:作成する PVC の StorageClass
- cassandra.allowMultipleNodesPerWorker:複数ワーカーへのデプロイ可否(
true
にした場合は、以下のresources
を設定する必要がある) - cassandra.heap:ヒープメモリのサイズ
- cassandra.resources:Cassandra Pod のリソース設定
- cassandra.datacenters.size:データセンター(クラスタ)内のCassandra ノード(Pod)数
@@ -7,7 +7,7 @@
# - 3.11.9
# - 3.11.10
# - 4.0.0
- version: "4.0.0"
+ version: "3.11.10"
# -- Specifies the image to use for a particular Cassandra version. Exercise
# care and caution with changing these values! cass-operator is not designed to work with
# arbitrary Cassandra images. It expects the cassandra container to be running
@@ -101,7 +101,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: rook-ceph-block-wffc
# -- 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
@@ -110,7 +110,7 @@
size: 5Gi
# -- Permits running multiple Cassandra pods per Kubernetes worker. If enabled
# resources.limits and resources.requests **must** be defined.
- allowMultipleNodesPerWorker: false
+ allowMultipleNodesPerWorker: true
# -- Optional additional contact points for the Cassandra cluster to connect to.
additionalSeeds: []
# -- The management-api runs as pid 1 in the cassandra container which means
@@ -136,9 +136,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.
@@ -188,7 +188,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: []
@@ -199,7 +205,7 @@
# -- Number of nodes within the datacenter. This value should, at a minimum,
# match the number of racks and be no less than 3 for non-development
# environments.
- size: 1
+ size: 3
# -- Number of tokens within the datacenter. If not defined, the default values will be
# used, which are 256 tokens for 3.11 releases and 16 tokens for 4.0 releases.
# num_tokens: 16
デプロイ
準備ができたの k8ssandra をデプロイしていきます。
# namespace 作成
$ kubectl create ns k8ssandra
namespace/k8ssandra created
# デプロイ
# helm install -f < 変数ファイル > -n < namespace > < Release 名 > < Chart 名 >
$ helm install -f values.yaml -n k8ssandra k8ssandra k8ssandra/k8ssandra
W0819 18:07:07.122775 5166 warnings.go:70] apiextensions.k8s.io/v1beta1 CustomResourceDefinition is deprecated in v1.16+, unavailable in v1.22+; use apiextensions.k8s.io/v1 CustomResourceDefinition
NAME: k8ssandra
LAST DEPLOYED: Thu Aug 19 18:07:10 2021
NAMESPACE: k8ssandra
STATUS: deployed
REVISION: 1
# Pod 起動確認
$ kubectl get po -n k8ssandra
NAME READY STATUS RESTARTS AGE
k8ssandra-cass-operator-7db77874bb-nb2t4 1/1 Running 0 7m45s
k8ssandra-dc1-default-sts-0 2/2 Running 0 7m18s
k8ssandra-dc1-default-sts-1 2/2 Running 0 7m18s
k8ssandra-dc1-default-sts-2 2/2 Running 0 7m18s
k8ssandra-dc1-stargate-6455bc4898-5t2fl 1/1 Running 0 7m45s
k8ssandra-grafana-74db456fdb-ms8n2 2/2 Running 0 7m45s
k8ssandra-kube-prometheus-operator-8487f5df79-q8xg5 1/1 Running 0 7m45s
k8ssandra-reaper-694cf49b96-kv9hw 1/1 Running 0 2m42s
k8ssandra-reaper-operator-77588cffc4-zj7r7 1/1 Running 0 7m45s
prometheus-k8ssandra-kube-prometheus-prometheus-0 2/2 Running 1 7m39s
起動確認を行うため、各オブジェクトを確認していきます。
# CustomResource (CR)
$ kubectl get cassandradatacenters -n k8ssandra
NAME AGE
dc1 6m48s
$ kubectl describe CassandraDataCenter dc1 | grep "Cassandra Operator Progress:"
Cassandra Operator Progress: Ready
# Service
$ kubectl get svc -n k8ssandra
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cass-operator-metrics ClusterIP 10.103.31.229 <none> 8383/TCP,8686/TCP 9m56s
k8ssandra-dc1-all-pods-service ClusterIP None <none> 9042/TCP,8080/TCP,9103/TCP 9m54s
k8ssandra-dc1-service ClusterIP None <none> 9042/TCP,9142/TCP,8080/TCP,9103/TCP,9160/TCP 9m54s
k8ssandra-dc1-stargate-service ClusterIP 10.104.115.103 <none> 8080/TCP,8081/TCP,8082/TCP,8084/TCP,8085/TCP,9042/TCP 10m
k8ssandra-grafana ClusterIP 10.107.28.119 <none> 80/TCP 10m
k8ssandra-kube-prometheus-operator ClusterIP 10.97.212.214 <none> 443/TCP 10m
k8ssandra-kube-prometheus-prometheus ClusterIP 10.98.181.165 <none> 9090/TCP 10m
k8ssandra-reaper-reaper-service ClusterIP 10.109.32.70 <none> 8080/TCP 10m
k8ssandra-seed-service ClusterIP None <none> <none> 9m54s
prometheus-operated ClusterIP None <none> 9090/TCP 10m
3 ノードでのリソースリクエストは以下のとおりです。
QuickStart で提示されている CPU 4 Core、Memory 8 GB で収まっています。
また、ストレージは 15Gi でした。
# CPU / Memory
Name CPU Requests CPU Limits Memory Requests Memory Limits
---- ------------ ---------- --------------- -------------
k8ssandra-cass-operator-7db77874bb-nb2t4 0 (0%) 0 (0%) 0 (0%) 0 (0%)
k8ssandra-dc1-default-sts-0 1100m (27%) 1100m (27%) 2159652Ki (13%) 2159652Ki (13%)
k8ssandra-dc1-default-sts-1 1100m (27%) 1100m (27%) 2159652Ki (13%) 2159652Ki (13%)
k8ssandra-dc1-default-sts-2 1100m (27%) 1100m (27%) 2159652Ki (13%) 2159652Ki (13%)
k8ssandra-dc1-stargate-6455bc4898-5t2fl 200m (5%) 1 (25%) 512Mi (3%) 1Gi (6%)
k8ssandra-grafana-74db456fdb-ms8n2 0 (0%) 0 (0%) 0 (0%) 0 (0%)
k8ssandra-kube-prometheus-operator-8487f5df79-q8xg5 0 (0%) 0 (0%) 0 (0%) 0 (0%)
k8ssandra-reaper-694cf49b96-kv9hw 0 (0%) 0 (0%) 0 (0%) 0 (0%)
k8ssandra-reaper-operator-77588cffc4-zj7r7 0 (0%) 0 (0%) 0 (0%) 0 (0%)
prometheus-k8ssandra-kube-prometheus-prometheus-0 100m (2%) 100m (2%) 50Mi (0%) 50Mi (0%)
# PVC
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
server-data-k8ssandra-dc1-default-sts-0 Bound pvc-048f870d-2e12-416f-8fbb-b2bffc3a7b09 5Gi RWO rook-ceph-block-wffc 34s
server-data-k8ssandra-dc1-default-sts-1 Bound pvc-398155e7-d0b8-447a-92ba-b0117df52f3d 5Gi RWO rook-ceph-block-wffc 34s
server-data-k8ssandra-dc1-default-sts-2 Bound pvc-610c0b99-fa96-43c0-a11a-63c61247877d 5Gi RWO rook-ceph-block-wffc 34s
アクセス確認(SRE/インフラエンジニア版)
各クライアントツールを使って、Cassandra にアクセスします。
まずは接続用のユーザ名とパスワードを確認します。
以下を参考に確認していきます。
# ユーザ名
$ kubectl get secret k8ssandra-superuser -o jsonpath="{.data.username}" | base64 --decode ; echo
k8ssandra-superuser
# パスワード
$ kubectl get secret k8ssandra-superuser -o jsonpath="{.data.password}" | base64 --decode ; echo
3pwT7KvvfgaooVtVdMTW
# 変数にアカウント情報を登録しておく
$ username=`kubectl get secret k8ssandra-superuser -o jsonpath="{.data.username}" | base64 --decode ; echo -n`
$ password=`kubectl get secret k8ssandra-superuser -o jsonpath="{.data.password}" | base64 --decode ; echo -n`
ここから Cassandra にアクセスしていきます。
# Cassandra を操作する nodetool コマンドが実行できる Pod 名を取得
# Cassandra Node の1台を指定
$ pod=`kubectl get po -l cassandra.datastax.com/cluster=k8ssandra -o jsonpath="{.items[0].metadata.name}"`
# Cassandra のバージョン確認
$ kubectl exec -it $pod -c cassandra -- nodetool -u $username -pw $password version
ReleaseVersion: 3.11.10
# ノードの状態を確認
# 3台構成ですべて ```UN(Up Normal)```
$ kubectl exec -it $pod -c cassandra -- nodetool -u $username -pw $password status
Datacenter: dc1
===============
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns Host ID Rack
UN 172.16.53.234 230.71 KiB 256 ? 0b8803e5-757b-4d3a-9d77-e50d7d2bbc63 default
UN 172.16.86.173 230.35 KiB 256 ? d332f17d-e1c3-459e-a9f8-9d6c7d92e16f default
UN 172.16.246.14 222.88 KiB 256 ? 86df7d42-97f6-46d3-a174-4569ec64b248 default
# token ring の状態を確認
$ kubectl exec -it $pod -c cassandra -- nodetool -u $username -pw $password ring
Datacenter: dc1
==========
Address Rack Status State Load Owns Token
9209236103942763965
172.16.86.173 default Up Normal 230.35 KiB ? -9195102402443329457
172.16.86.173 default Up Normal 230.35 KiB ? -9177725703046123506
172.16.86.173 default Up Normal 230.35 KiB ? -9175082155595014679
172.16.53.234 default Up Normal 230.71 KiB ? -9149417071079256963
・・・
# ノードの詳細情報表示
$ kubectl exec -it $pod -c cassandra -- nodetool -u $username -pw $password info
ID : 0b8803e5-757b-4d3a-9d77-e50d7d2bbc63
Gossip active : true
Thrift active : true
Native Transport active: true
Load : 230.71 KiB
Generation No : 1629396520
Uptime (seconds) : 2040
Heap Memory (MB) : 668.33 / 1024.00
Off Heap Memory (MB) : 0.00
Data Center : dc1
Rack : default
Exceptions : 0
Key Cache : entries 46, size 3.69 KiB, capacity 51 MiB, 4114 hits, 4413 requests, 0.932 recent hit rate, 14400 save period in seconds
Row Cache : entries 0, size 0 bytes, capacity 0 bytes, 0 hits, 0 requests, NaN recent hit rate, 0 save period in seconds
Counter Cache : entries 0, size 0 bytes, capacity 25 MiB, 0 hits, 0 requests, NaN recent hit rate, 7200 save period in seconds
Chunk Cache : entries 22, size 1.38 MiB, capacity 224 MiB, 268 misses, 6531 requests, 0.959 recent hit rate, NaN microseconds miss latency
Percent Repaired : 0.0%
Token : (invoke with -T/--tokens to see all 256 tokens)
CLI での確認はここまで。
NodePort の設定を追加して各 WebUI を確認します。
---
apiVersion: v1
kind: Service
metadata:
name: k8ssandra-grafana-np
namespace: k8ssandra
spec:
ports:
- name: service
nodePort: 32080
port: 80
protocol: TCP
targetPort: 3000
selector:
app.kubernetes.io/instance: k8ssandra
app.kubernetes.io/name: grafana
type: NodePort
---
apiVersion: v1
kind: Service
metadata:
name: prometheus-operated-np
namespace: k8ssandra
spec:
ports:
- name: web
nodePort: 32081
port: 9090
protocol: TCP
targetPort: web
selector:
app: prometheus
type: NodePort
---
apiVersion: v1
kind: Service
metadata:
name: k8ssandra-reaper-reaper-service-np
namespace: k8ssandra
spec:
ports:
- name: app
nodePort: 32082
port: 8080
protocol: TCP
targetPort: app
selector:
app.kubernetes.io/managed-by: reaper-operator
reaper.cassandra-reaper.io/reaper: k8ssandra-reaper
type: NodePort
作成した yaml ファイルをデプロイしていきます。
# デプロイ
$ kubectl apply -f NodePort.yaml
service/k8ssandra-grafana-np created
service/prometheus-operated-np created
service/k8ssandra-reaper-reaper-service-np created
# Service 登録後の状態
$ kubectl get svc | grep -e NAME -e NodePort
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
k8ssandra-grafana-np NodePort 10.110.211.96 <none> 80:32080/TCP 8m28s
k8ssandra-reaper-reaper-service-np NodePort 10.103.212.12 <none> 8080:32082/TCP 51s
prometheus-operated-np NodePort 10.107.133.57 <none> 9090:32081/TCP 3m14s
# Node の IP アドレス取得
$ kubectl get nodes -o jsonpath="{.items[0].status.addresses[0].address}"
192.168.10.61
各 Web UI にアクセスしていきます。
Prometheus - http://192.168.10.61:32081
※「Status」⇒「Targets」
Grafana - http://192.168.10.61:32082
※Grafana のアカウントを確認
# ユーザ名
$ helm show values k8ssandra/k8ssandra | grep "adminUser"
adminUser: admin
# パスワード
$ helm show values k8ssandra/k8ssandra | grep "adminPassword"
adminPassword: secret
※「HOME」⇒「Cassandra Overview」
reaper - http://192.168.10.61:32082/webui
アクセス確認(開発者版)
今度は開発者目線でアクセス確認していきます。
以下を参考に確認していきます。
まずは cqlsh
を使って確認します。
# Cassandra Node に cqlsh コマンドで接続
$ kubectl exec -it $pod -c cassandra -- cqlsh -u $username -p $password
Connected to k8ssandra at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 3.11.10 | CQL spec 3.4.4 | Native protocol v4]
Use HELP for help.
k8ssandra-superuser@cqlsh>
※以降、プロンプトは「cqlsh>」
# Kyespace(RDB でいうところの DB)作成
cqlsh> CREATE KEYSPACE k8ssandra_test WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};
# 作成した Keyspace 選択
cqlsh> USE k8ssandra_test;
k8ssandra-superuser@cqlsh:k8ssandra_test>
# テーブル作成
cqlsh> CREATE TABLE users (email text primary key, name text, state text);
# サンプルデータ登録
cqlsh> INSERT INTO users (email, name, state) values ('alice@example.com', 'Alice Smith', 'TX');
cqlsh> INSERT INTO users (email, name, state) values ('bob@example.com', 'Bob Jones', 'VA');
cqlsh> INSERT INTO users (email, name, state) values ('carol@example.com', 'Carol Jackson', 'CA');
cqlsh> INSERT INTO users (email, name, state) values ('david@example.com', 'David Yang', 'NV');
# 登録したデータ参照
cqlsh> SELECT * FROM k8ssandra_test.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)
# 終了
cqlsh> QUIT;
MySQL や PostgreSQL の用に SQL コマンドチックに確認が出来ました。
今度は Stargate 経由で RestAPI を使ったアクセスを行います。
# Stargate Pod の名前を変数に格納
$ pod=`kubectl get po -l app=k8ssandra-dc1-stargate -o jsonpath="{.items[0].metadata.name}"`
# API リクエストのためにトークン情報を取得
$ kubectl exec $pod -- sh -c \
"curl -s -L -X POST 'http://localhost:8081/v1/auth' \
-H 'Content-Type: application/json' \
--data-raw '{\"username\": \"$username\", \"password\": \"$password\"}'"
{"authToken":"xxxxx"}
# 上記トークンを変数に格納
$ token=xxxxx
以下、curl
コマンドでリクエストを発行し、json 結果を表示していきます。
$ kubectl exec $pod -- \
curl -s -L -X GET 'http://localhost:8082/v2/schemas/keyspaces' \
-H "X-Cassandra-Token: $token" \
-H 'Content-Type: application/json' | \
python3 -m json.tool
{
"data": [
{
"name": "k8ssandra_test"
},
{
"name": "system_distributed",
"datacenters": [
{
"name": "dc1",
"replicas": 3
}
]
},
{
"name": "system"
},
{
"name": "data_endpoint_auth"
},
{
"name": "system_schema"
},
{
"name": "stargate_system"
},
{
"name": "reaper_db",
"datacenters": [
{
"name": "dc1",
"replicas": 3
}
]
},
{
"name": "system_auth",
"datacenters": [
{
"name": "dc1",
"replicas": 3
}
]
},
{
"name": "system_traces",
"datacenters": [
{
"name": "dc1",
"replicas": 3
}
]
}
]
}
$ kubectl exec $pod -- \
curl -s -L -X GET 'http://localhost:8082/v2/schemas/keyspaces/k8ssandra_test/tables' \
-H "X-Cassandra-Token: $token" \
-H 'Content-Type: application/json' | \
python3 -m json.tool
{
"data": [
{
"name": "users",
"keyspace": "k8ssandra_test",
"columnDefinitions": [
{
"name": "email",
"typeDefinition": "varchar",
"static": false
},
{
"name": "name",
"typeDefinition": "varchar",
"static": false
},
{
"name": "state",
"typeDefinition": "varchar",
"static": false
}
],
"primaryKey": {
"partitionKey": [
"email"
],
"clusteringKey": []
},
"tableOptions": {
"defaultTimeToLive": 0,
"clusteringExpression": []
}
}
]
}
# Keyspace:k8ssandra_test、Table:users
# where email="alice@example.com"
$ kubectl exec $pod -- \
curl -s -L -X GET 'http://localhost:8082/v2/keyspaces/k8ssandra_test/users?where=\{"email":\{"$eq":\["alice@example.com"\]\}\}' \
-H "X-Cassandra-Token: $token" \
-H 'Content-Type: application/json' | \
python3 -m json.tool
{
"count": 1,
"data": [
{
"name": "Alice Smith",
"email": "alice@example.com",
"state": "TX"
}
]
}
$ kubectl exec $pod -- \
curl -s -L -G 'http://localhost:8082/v2/keyspaces/k8ssandra_test/users' \
-H "X-Cassandra-Token: $token" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data-urlencode 'where={
"email": {"$eq": "alice@example.com"}
}' | \
python3 -m json.tool
{
"count": 1,
"data": [
{
"name": "Alice Smith",
"email": "alice@example.com",
"state": "TX"
}
]
}
まとめ
k8ssandra を使うと簡単に Cassandra を導入することが出来ました。
Operator によって、VMにインストールする作業が減ると同時に、気軽にデプロイし検証が始められるのもメリットかと思います。
監視などの運用系ツールも用意されていることで、単体利用だけでなく運用面でもより使いやすくなっているかと思います。
参考
Github - k8ssandra helm chart
https://github.com/k8ssandra/k8ssandra/tree/main/charts/k8ssandra
Discussion