mirror of
https://github.com/helm/charts.git
synced 2026-08-23 22:37:45 +00:00
Add Cassandra StatefulSet Chart (#667)
* Add Cassandra StatefulSet Chart * Change name truncate size to 21 cause StatefulSet will append 3 characters at the end of each name * Change storage class annotation from alpha to beta * Add seeds size * Add liveness probe and node selector * Rename template files * Update Readme * Remove configmap and update liveness probe * Add readiness probe * Update description and add icon * Comment out nodeSelector as an optional value Add default persistence storage class * Change default image tag from “latest” to “3”
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
@@ -0,0 +1,13 @@
|
||||
name: cassandra
|
||||
version: 0.1.0
|
||||
description: Apache Cassandra is a free and open-source distributed database management system designed to handle large amounts of data across many commodity servers, providing high availability with no single point of failure.
|
||||
icon: https://upload.wikimedia.org/wikipedia/commons/5/5e/Cassandra_logo.svg
|
||||
keywords:
|
||||
- cassandra
|
||||
- database
|
||||
- nosql
|
||||
home: http://cassandra.apache.org
|
||||
maintainers:
|
||||
- name: Siri C
|
||||
email: goonohc@gmail.com
|
||||
engine: gotpl
|
||||
@@ -0,0 +1,112 @@
|
||||
# Cassandra
|
||||
A Cassandra Chart for Kubernetes
|
||||
|
||||
## Install Chart
|
||||
To install the Cassandra Chart into your Kubernetes cluster (This Chart requires persistent volume by default, you may need to create a storage class before install chart. To create storage class, see [Persist data](#persist_data) section)
|
||||
|
||||
```bash
|
||||
helm install --namespace "cassandra" -n "cassandra" incubator/cassandra
|
||||
```
|
||||
|
||||
After installation succuess, you can get a status of Chart
|
||||
|
||||
```bash
|
||||
helm status "cassandra"
|
||||
```
|
||||
|
||||
If you want to delete your Chart, use this command
|
||||
```bash
|
||||
helm delete --purge "cassandra"
|
||||
```
|
||||
|
||||
## Persist data
|
||||
You need to create `StorageClass` before able to persist data in persistent volume.
|
||||
To create a `StorageClass` on Google Cloud, run the following
|
||||
|
||||
```bash
|
||||
kubectl create -f sample/create-storage-gce.yaml
|
||||
```
|
||||
|
||||
And set the following values in `values.yaml`
|
||||
|
||||
```yaml
|
||||
persistence:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
If you want to create a `StorageClass` on other platform, please see documentation here [https://kubernetes.io/docs/user-guide/persistent-volumes/](https://kubernetes.io/docs/user-guide/persistent-volumes/)
|
||||
|
||||
|
||||
## Install Chart with specific cluster size
|
||||
By default, this Chart will create a cassandra with 3 nodes. If you want to change the cluster size during installation, you can use `--set config.cluster_size={value}` argument. Or edit `values.yaml`
|
||||
|
||||
For example:
|
||||
Set cluster size to 5
|
||||
|
||||
```bash
|
||||
helm install --namespace "cassandra" -n "cassandra" --set config.cluster_size=5 incubator/cassandra/
|
||||
```
|
||||
|
||||
## Install Chart with specific resource size
|
||||
By default, this Chart will create a cassandra with CPU 2 vCPU and 4Gi of memery which is suitable for development environment.
|
||||
If you want to use this Chart for production, I would recommend to update the CPU to 4 vCPU and 16Gi. Also increase size of `max_heap_size` and `heap_new_size`.
|
||||
To update the settings, edit `values.yaml`
|
||||
|
||||
## Install Chart with specific node
|
||||
Sometime you may need to deploy your cassandra to specific nodes to allocate resources. You can use node selector by edit `nodes.enabled=true` in `values.yaml`
|
||||
For example, you have 6 vms in node pools and you want to deploy cassandra to node which labeled as `cloud.google.com/gke-nodepool: pool-db`
|
||||
|
||||
Set the following values in `values.yaml`
|
||||
|
||||
```yaml
|
||||
nodes:
|
||||
enabled: true
|
||||
selector:
|
||||
nodeSelector:
|
||||
cloud.google.com/gke-nodepool: pool-db
|
||||
```
|
||||
|
||||
## Scale cassandra
|
||||
When you want to change the cluser size of your cassandra, you can use the helm upgrade command.
|
||||
|
||||
```bash
|
||||
helm upgrade --set config.cluster_size=5 cassandra incubator/cassandra
|
||||
```
|
||||
|
||||
## Get cassandra status
|
||||
You can get your cassandra cluster status by running the command
|
||||
|
||||
```bash
|
||||
kubectl exec -it --namespace cassandra $(kubectl get pods --namespace cassandra -l app=cassandra-cassandra -o jsonpath='{.items[0].metadata.name}') nodetool status
|
||||
```
|
||||
|
||||
Output
|
||||
```bash
|
||||
Datacenter: asia-east1
|
||||
======================
|
||||
Status=Up/Down
|
||||
|/ State=Normal/Leaving/Joining/Moving
|
||||
-- Address Load Tokens Owns (effective) Host ID Rack
|
||||
UN 10.8.1.11 108.45 KiB 256 66.1% 410cc9da-8993-4dc2-9026-1dd381874c54 a
|
||||
UN 10.8.4.12 84.08 KiB 256 68.7% 96e159e1-ef94-406e-a0be-e58fbd32a830 c
|
||||
UN 10.8.3.6 103.07 KiB 256 65.2% 1a42b953-8728-4139-b070-b855b8fff326 b
|
||||
```
|
||||
|
||||
## Benchmark
|
||||
You can use [cassandra-stress](https://docs.datastax.com/en/cassandra/3.0/cassandra/tools/toolsCStress.html) tool to run the benchmark on the cluster by the following command
|
||||
|
||||
```bash
|
||||
kubectl exec -it --namespace cassandra $(kubectl get pods --namespace cassandra -l app=cassandra-cassandra -o jsonpath='{.items[0].metadata.name}') cassandra-stress
|
||||
```
|
||||
|
||||
Example of `cassandra-stress` argument
|
||||
- Run both read and write with ration 9:1
|
||||
- Operator total 1 million keys with uniform distribution
|
||||
- Use QUORUM for read/write
|
||||
- Generate 50 threads
|
||||
- Generate result in graph
|
||||
- Use NetworkTopologyStrategy with replica factor 2
|
||||
|
||||
```bash
|
||||
cassandra-stress mixed ratio\(write=1,read=9\) n=1000000 cl=QUORUM -pop dist=UNIFORM\(1..1000000\) -mode native cql3 -rate threads=50 -log file=~/mixed_autorate_r9w1_1M.log -graph file=test2.html title=test revision=test2 -schema "replication(strategy=NetworkTopologyStrategy, factor=2)"
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
kind: StorageClass
|
||||
apiVersion: storage.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: generic
|
||||
provisioner: kubernetes.io/gce-pd
|
||||
parameters:
|
||||
type: pd-ssd
|
||||
@@ -0,0 +1,27 @@
|
||||
Cassandra CQL can be accessed via port {{ .Values.config.ports.cql }} on the following DNS name from within your cluster:
|
||||
Cassandra Thrift can be accessed via port {{ .Values.config.ports.thrift }} on the following DNS name from within your cluster:
|
||||
|
||||
If you want to connect to the remote instance with your local Cassandra CQL cli. To forward the API port to localhost:9042 run the following:
|
||||
- kubectl port-forward --namespace {{ .Release.Namespace }} $(kubectl get pods --namespace {{ .Release.Namespace }} -l app={{ template "fullname" . }} -o jsonpath='{ .items[0].metadata.name }') 9042:{{ .Values.config.ports.cql }}
|
||||
|
||||
If you want to connect to the Cassandra CQL run the following:
|
||||
{{- if contains "NodePort" .Values.service.type }}
|
||||
- export CQL_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "fullname" . }})
|
||||
- export CQL_HOST=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
- cqlsh $CQL_HOST $CQL_PORT
|
||||
|
||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "fullname" . }}'
|
||||
- export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
||||
- echo cqlsh $SERVICE_IP
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
- kubectl port-forward --namespace {{ .Release.Namespace }} $(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "fullname" . }}" -o jsonpath="{.items[0].metadata.name}") 9042:{{ .Values.config.ports.cql }}
|
||||
echo cqlsh 127.0.0.1 9042
|
||||
{{- end }}
|
||||
|
||||
You can also see the cluster status by run the following:
|
||||
- kubectl exec -it --namespace {{ .Release.Namespace }} $(kubectl get pods --namespace {{ .Release.Namespace }} -l app={{ template "fullname" . }} -o jsonpath='{.items[0].metadata.name}') nodetool status
|
||||
|
||||
To tail the logs for the Cassandra pod run the following:
|
||||
- kubectl logs -f --namespace {{ .Release.Namespace }} $(kubectl get pods --namespace {{ .Release.Namespace }} -l app={{ template "fullname" . }} -o jsonpath='{ .items[0].metadata.name }')
|
||||
@@ -0,0 +1,17 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 21 -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 21 chars because Kubernetes name fields are limited to 24 (by the DNS naming spec)
|
||||
and Statefulset will append -xx at the end of name.
|
||||
*/}}
|
||||
{{- define "fullname" -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 21 -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,128 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "fullname" . }}
|
||||
labels:
|
||||
app: {{ template "fullname" . }}
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
release: "{{ .Release.Name }}"
|
||||
heritage: "{{ .Release.Service }}"
|
||||
spec:
|
||||
clusterIP: None
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- name: intra
|
||||
port: 7000
|
||||
targetPort: 7000
|
||||
- name: tls
|
||||
port: 7001
|
||||
targetPort: 7001
|
||||
- name: jmx
|
||||
port: 7199
|
||||
targetPort: 7199
|
||||
- name: cql
|
||||
port: {{ default 9042 .Values.config.ports.cql }}
|
||||
targetPort: {{ default 9042 .Values.config.ports.cql }}
|
||||
- name: thrift
|
||||
port: {{ default 9160 .Values.config.ports.thrift }}
|
||||
targetPort: {{ default 9160 .Values.config.ports.thrift }}
|
||||
selector:
|
||||
app: {{ template "fullname" . }}
|
||||
---
|
||||
apiVersion: apps/v1beta1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ template "fullname" . }}
|
||||
labels:
|
||||
app: {{ template "fullname" . }}
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
release: "{{ .Release.Name }}"
|
||||
heritage: "{{ .Release.Service }}"
|
||||
spec:
|
||||
serviceName: {{ template "fullname" . }}
|
||||
replicas: {{ .Values.config.cluster_size }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "fullname" . }}
|
||||
spec:
|
||||
{{- if .Values.selector }}
|
||||
{{ toYaml .Values.selector | indent 6 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ template "fullname" . }}
|
||||
image: "{{ .Values.image.repo }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
|
||||
resources:
|
||||
{{ toYaml .Values.resources | indent 10 }}
|
||||
env:
|
||||
{{- $seed_size := default 1 .Values.config.seed_size | int -}}
|
||||
{{- $global := . }}
|
||||
- name: CASSANDRA_SEEDS
|
||||
value: "{{- range $i, $e := until $seed_size }}{{ template "fullname" $global }}-{{ $i }}.{{ template "fullname" $global }}.{{ $global.Release.Namespace }}.svc.cluster.local,{{- end }}"
|
||||
- name: MAX_HEAP_SIZE
|
||||
value: {{ default "8192M" .Values.config.max_heap_size | quote }}
|
||||
- name: HEAP_NEWSIZE
|
||||
value: {{ default "200M" .Values.config.heap_new_size | quote }}
|
||||
- name: CASSANDRA_ENDPOINT_SNITCH
|
||||
value: {{ default "SimpleSnitch" .Values.config.endpoint_snitch | quote }}
|
||||
- name: CASSANDRA_CLUSTER_NAME
|
||||
value: {{ default "Cassandra" .Values.config.cluster_name | quote }}
|
||||
- name: CASSANDRA_DC
|
||||
value: {{ default "DC1" .Values.config.dc_name | quote }}
|
||||
- name: CASSANDRA_RACK
|
||||
value: {{ default "RAC1" .Values.config.rack_name | quote }}
|
||||
- name: POD_IP
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: status.podIP
|
||||
livenessProbe:
|
||||
exec:
|
||||
command: [ "/bin/sh", "-c", "nodetool status | grep -E \"^UN\\s+${POD_IP}\"" ]
|
||||
initialDelaySeconds: 90
|
||||
periodSeconds: 30
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: [ "/bin/sh", "-c", "nodetool status | grep -E \"^UN\\s+${POD_IP}\"" ]
|
||||
initialDelaySeconds: 90
|
||||
periodSeconds: 30
|
||||
ports:
|
||||
- name: intra
|
||||
containerPort: 7000
|
||||
- name: tls
|
||||
containerPort: 7001
|
||||
- name: jmx
|
||||
containerPort: 7199
|
||||
- name: cql
|
||||
containerPort: {{ default 9042 .Values.config.ports.cql }}
|
||||
- name: thrift
|
||||
containerPort: {{ default 9160 .Values.config.ports.thrift }}
|
||||
volumeMounts:
|
||||
- name: data
|
||||
{{- if .Values.persistence.enabled }}
|
||||
mountPath: /var/lib/cassandra
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- if .Values.persistence.enabled }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
labels:
|
||||
app: {{ template "fullname" . }}
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
release: "{{ .Release.Name }}"
|
||||
heritage: "{{ .Release.Service }}"
|
||||
annotations:
|
||||
{{- if .Values.persistence.storageClass }}
|
||||
volume.beta.kubernetes.io/storage-class: {{ .Values.persistence.storageClass | quote }}
|
||||
{{- else }}
|
||||
volume.alpha.kubernetes.io/storage-class: default
|
||||
{{- end }}
|
||||
spec:
|
||||
accessModes:
|
||||
- {{ .Values.persistence.accessMode | quote }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.persistence.size | quote }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,58 @@
|
||||
## Cassandra image version
|
||||
## ref: https://hub.docker.com/r/library/cassandra/
|
||||
image:
|
||||
repo: "cassandra"
|
||||
tag: "3"
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
## Specify a service type
|
||||
## ref: http://kubernetes.io/docs/user-guide/services/
|
||||
service:
|
||||
type: ClusterIP
|
||||
|
||||
## Persist data to a persitent volume
|
||||
persistence:
|
||||
enabled: true
|
||||
## If defined, volume.beta.kubernetes.io/storage-class: <storageClass>
|
||||
## Default: volume.alpha.kubernetes.io/storage-class: default
|
||||
# storageClass: generic
|
||||
accessMode: ReadWriteOnce
|
||||
size: 10Gi
|
||||
|
||||
## Configure resource requests and limits
|
||||
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
|
||||
## Minimum memory for development is 4GB and 2 CPU cores
|
||||
## Minimum memory for production is 8GB and 4 CPU cores
|
||||
## ref: http://docs.datastax.com/en/archived/cassandra/2.0/cassandra/architecture/architecturePlanningHardware_c.html
|
||||
resources:
|
||||
requests:
|
||||
memory: 4Gi
|
||||
cpu: 2
|
||||
limits:
|
||||
memory: 4Gi
|
||||
cpu: 2
|
||||
|
||||
## Change cassandra configuration paramaters below:
|
||||
## ref: http://docs.datastax.com/en/cassandra/3.0/cassandra/configuration/configCassandra_yaml.html
|
||||
## Recommended max heap size is 1/2 of system memory
|
||||
## Recommeneed heap new size is 1/4 of max heap size
|
||||
## ref: http://docs.datastax.com/en/cassandra/3.0/cassandra/operations/opsTuneJVM.html
|
||||
config:
|
||||
cluster_name: cassandra
|
||||
cluster_size: 3
|
||||
seed_size: 2
|
||||
num_tokens: 256
|
||||
dc_name: DC1
|
||||
rack_name: RAC1
|
||||
endpoint_snitch: SimpleSnitch
|
||||
max_heap_size: 2048M
|
||||
heap_new_size: 512M
|
||||
ports:
|
||||
cql: 9042
|
||||
thrift: 9160
|
||||
|
||||
## Configure node selector. Edit code below for adding selector to pods
|
||||
## ref: https://kubernetes.io/docs/user-guide/node-selection/
|
||||
# selector:
|
||||
# nodeSelector:
|
||||
# cloud.google.com/gke-nodepool: pool-db
|
||||
Reference in New Issue
Block a user