From 465c9fbf2eadd098bd3609ea916c083ae21522c6 Mon Sep 17 00:00:00 2001 From: Cody Lundquist Date: Tue, 13 Jun 2017 03:40:08 -0700 Subject: [PATCH] rethinkdb: Initial Commit (#1018) * rethinkdb-cluster: Initial Commit * Fix chart name. * Make the NOTES.txt file more accurate. * Use k8s 1.6 storageClassName notation for PVC. * RethinkDB directory needs to be initially empty. When using a provisioned volume from something like GCE, the mounted directory has a folder inside of it. This breaks RethinkDB when initializing. * Add an extra k8s script to create a StorageClass on GCE. * Addressing PR Comments. * Rename to Recursively removing directory /Users/codyl/dev-files/charts/rethinkdb_data/tmp Initializing directory /Users/codyl/dev-files/charts/rethinkdb_data Running rethinkdb 2.3.4 (CLANG 7.3.0 (clang-703.0.31))... Running on Darwin 16.6.0 x86_64 Loading data from directory /Users/codyl/dev-files/charts/rethinkdb_data and move to stable. * Shorten down .gitignore file. * Make using the RethinkDB Admin Console easier. * Fix some wrong names/paths. * Due to a bug with secrets, don't auto-gen a password. https://github.com/kubernetes/charts/issues/980 * Remove extra file. * Addressing PR comments and some other changes - Updated NOTES.txt to include more tailored instructions based on proxy service type. - Added an optional StorageClass. - Simplified rethink config to not use a ConfigMap. - Added optional RethinkDB Driver TLS configuration. - Updated README.md to reflect new config changes. * Tiny fix in README.md. * Use github username for Chart.yaml. * Default to ClusterIP for proxy service. --- stable/rethinkdb/.gitignore | 3 + stable/rethinkdb/.helmignore | 22 +++ stable/rethinkdb/Chart.yaml | 14 ++ stable/rethinkdb/README.md | 132 ++++++++++++++++++ stable/rethinkdb/init/Dockerfile | 31 ++++ stable/rethinkdb/init/Makefile | 30 ++++ stable/rethinkdb/init/files/run.sh | 86 ++++++++++++ .../init/rethinkdb-probe/Dockerfile.build | 10 ++ .../init/rethinkdb-probe/build-probe.sh | 18 +++ .../rethinkdb/init/rethinkdb-probe/probe.go | 42 ++++++ stable/rethinkdb/templates/NOTES.txt | 33 +++++ stable/rethinkdb/templates/_helpers.tpl | 16 +++ .../templates/rethinkdb-admin-service.yaml | 17 +++ .../templates/rethinkdb-cluster-service.yaml | 22 +++ .../rethinkdb-cluster-stateful-set.yaml | 107 ++++++++++++++ .../rethinkdb-cluster-storage-class.yaml | 16 +++ .../templates/rethinkdb-proxy-deployment.yaml | 78 +++++++++++ .../templates/rethinkdb-proxy-service.yaml | 33 +++++ .../templates/rethinkdb-secrets.yaml | 16 +++ stable/rethinkdb/values.yaml | 75 ++++++++++ 20 files changed, 801 insertions(+) create mode 100644 stable/rethinkdb/.gitignore create mode 100644 stable/rethinkdb/.helmignore create mode 100644 stable/rethinkdb/Chart.yaml create mode 100644 stable/rethinkdb/README.md create mode 100644 stable/rethinkdb/init/Dockerfile create mode 100644 stable/rethinkdb/init/Makefile create mode 100644 stable/rethinkdb/init/files/run.sh create mode 100644 stable/rethinkdb/init/rethinkdb-probe/Dockerfile.build create mode 100755 stable/rethinkdb/init/rethinkdb-probe/build-probe.sh create mode 100644 stable/rethinkdb/init/rethinkdb-probe/probe.go create mode 100644 stable/rethinkdb/templates/NOTES.txt create mode 100644 stable/rethinkdb/templates/_helpers.tpl create mode 100644 stable/rethinkdb/templates/rethinkdb-admin-service.yaml create mode 100644 stable/rethinkdb/templates/rethinkdb-cluster-service.yaml create mode 100644 stable/rethinkdb/templates/rethinkdb-cluster-stateful-set.yaml create mode 100644 stable/rethinkdb/templates/rethinkdb-cluster-storage-class.yaml create mode 100644 stable/rethinkdb/templates/rethinkdb-proxy-deployment.yaml create mode 100644 stable/rethinkdb/templates/rethinkdb-proxy-service.yaml create mode 100644 stable/rethinkdb/templates/rethinkdb-secrets.yaml create mode 100644 stable/rethinkdb/values.yaml diff --git a/stable/rethinkdb/.gitignore b/stable/rethinkdb/.gitignore new file mode 100644 index 0000000000..b5a3858c94 --- /dev/null +++ b/stable/rethinkdb/.gitignore @@ -0,0 +1,3 @@ +# Local Files # +############### +init/rethinkdb-probe/rethinkdb-probe diff --git a/stable/rethinkdb/.helmignore b/stable/rethinkdb/.helmignore new file mode 100644 index 0000000000..ed9450feca --- /dev/null +++ b/stable/rethinkdb/.helmignore @@ -0,0 +1,22 @@ +# 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 +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +init/ diff --git a/stable/rethinkdb/Chart.yaml b/stable/rethinkdb/Chart.yaml new file mode 100644 index 0000000000..059841108a --- /dev/null +++ b/stable/rethinkdb/Chart.yaml @@ -0,0 +1,14 @@ +name: rethinkdb +description: The open-source database for the realtime web +version: 0.0.1 +keywords: +- rethinkdb +- database +- nosql +home: https://www.rethinkdb.com +sources: +- https://hub.docker.com/r/codylundquist/helm-rethinkdb-cluster/ +icon: http://i.imgur.com/bZ75N6r.jpg +maintainers: +- name: meenie + email: cody.lundquist@gmail.com diff --git a/stable/rethinkdb/README.md b/stable/rethinkdb/README.md new file mode 100644 index 0000000000..d64d9ef9b8 --- /dev/null +++ b/stable/rethinkdb/README.md @@ -0,0 +1,132 @@ +# RethinkDB 2.3.5 Helm Chart + +## Prerequisites Details +* Kubernetes 1.5+ with Beta APIs enabled. +* PV support on the underlying infrastructure. + +## StatefulSet Details +* https://kubernetes.io/docs/concepts/abstractions/controllers/statefulsets/ + +## StatefulSet Caveats +* https://kubernetes.io/docs/concepts/abstractions/controllers/statefulsets/#limitations + +## Acknowledgment of Previous Works + +I have heavily borrowed and extended code (peer discovery and probe) from the following project to build this Helm Chart and Docker image: https://github.com/rosskukulinski/kubernetes-rethinkdb-cluster + +## Chart Details + +This chart implements a dynamically scalable [RethinkDB Cluster](https://www.rethinkdb.com/docs/sharding-and-replication/) using Kubernetes StatefulSets. + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +$ helm install --name my-release stable/rethinkdb +``` + +## Configuration + +The following table lists the configurable parameters of the rethinkdb chart and their default values. + +Parameter | Description | Default +---|---|--- +`image.name` | Custom RethinkDB image name for auto-joining and probe | `codylundquist/helm-rethinkdb-cluster` +`image.tag` | Custom RethinkDB image tag | `0.1.0` +`image.pullPolicy` | Custom RethinkDB image pull policy | `IfNotPresent` +`cluster.replicas` | Number of RethinkDB Cluster replicas | `3` +`cluster.resources` | Resource configuration for each RethinkDB Cluster Pod | `{}` +`cluster.podAnnotations` | Annotations to be added to RethinkDB Cluster Pods | `{}` +`cluster.service.annotations` | Annotations to be added to RethinkDB Cluster Service | `{}` +`cluster.storageClass.enabled` | If `true`, create a StorageClass for the cluster. **Note**: You must set a provisioner | `false` +`cluster.storageClass.provisioner` | Provisioner definition for StorageClass | `undefined` +`cluster.storageClass.parameters` | Parameters for StorageClass | `undefined` +`cluster.persistentVolume.enabled` | If `true`, persistent volume claims are created | `true` +`cluster.persistentVolume.storageClass` | Persistent volume storage class | `default` +`cluster.persistentVolume.accessMode` | Persistent volume access modes | `[ReadWriteOnce]` +`cluster.persistentVolume.size` | Persistent volume size | `10Gi` +`cluster.persistentVolume.annotations` | Persistent volume annotations | `{}` +`cluster.rethinkCacheSize` | RethinkDB `cache-size` value in MB | `100` +`proxy.replicas` | Number of RethinkDB Proxy replicas | `1` +`proxy.resources` | Resource configuration for each RethinkDB Proxy Pod | `{}` +`proxy.podAnnotations` | Annotations to be added to RethinkDB Proxy Pods | `{}` +`proxy.service.type` | RethinkDB Proxy Service Type | `ClusterIP` +`proxy.service.annotations` | Annotations to be added to RethinkDB Cluster Service | `{}` +`proxy.service.clusterIP` | Internal controller proxy service IP | `""` +`proxy.service.externalIPs` | Controller service external IP addresses | `[]` +`proxy.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` +`proxy.service.loadBalancerSourceRanges` | List of IP CIDRs allowed access to load balancer (if supported) | `[]` +`proxy.driverTLS.enabled` | Should RethinkDB Proxy TLS be enabled. **Note**: If enabled, you must set a key and cert | `false` +`proxy.driverTLS.key` | RSA Private Key | `undefined` +`proxy.driverTLS.cert` | Certificate | `undefined` +`ports.cluster` | RethinkDB Cluster Port | `29015` +`ports.driver` | RethinkDB Driver Port | `28015` +`ports.admin` | RethinkDB Admin Port | `8080` +`rethinkdbPassword` | Password for the RethinkDB Admin user | `rethinkdb` + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```console +$ helm install --name my-release -f values.yaml stable/rethinkdb +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +## Important: Admin Password Management ## + +The initial admin password is set by the config value `rethinkdbPassword`. This value is also used by the probe which periodically checks if the RethinkDB Cluster and Proxy are still running. If you change the RethinkDB admin password via a query (i.e. `r.db('rethinkdb').table('users').update({password: 'new-password'})`) this will cause the probe to fail which then restarts the pods over and over. To stablize the cluster, you also need to use `helm upgrade` to update the password in the Kubernetes Secrets storage by doing: +```console +$ helm upgrade --set rethinkdbPassword=new-password my-release stable/rethinkdb +``` + +## Opening Up the RethinkDB Admin Console + +The admin port is not available outside of the cluster for security reasons. The only way to access the admin console is to use a [Kubernetes Proxy](https://kubernetes.io/docs/concepts/cluster-administration/access-cluster/#manually-constructing-apiserver-proxy-urls). To open up the admin console: +```console +$ kubectl proxy +Starting to serve on 127.0.0.1:8001 +``` +Then use the following URL: http://localhost:8001/api/v1/namespaces/NAMESPACE/services/RELEASE_NAME-rethinkdb-admin/proxy +Make sure a replace `NAMEPSPACE` with the correct namespace and `RELEASE_NAME` that was used when installing the chart. + +And then open up your browser to http://localhost:8080 and you should see the admin console + +## Cleanup orphaned Persistent Volumes + +Deleting a StateFul will not delete associated Persistent Volumes. + +Do the following after deleting the chart release to clean up orphaned Persistent Volumes. + +```console +$ kubectl delete pvc -l release=my-release +``` + +## Failover + +If any RethinkDB server fails it gets re-joined eventually. +You can test the scenario by killing process of one of the pods: +```console +$ kubectl get pods -l release=my-release +NAME READY STATUS RESTARTS AGE +my-release-rethinkdb-cluster-0 1/1 Running 0 1m +my-release-rethinkdb-cluster-1 1/1 Running 0 2m +my-release-rethinkdb-cluster-2 1/1 Running 0 2m +my-release-rethinkdb-proxy-2517940628-81dxd 1/1 Running 1 1m + +$ kubectl exec -it my-release-rethinkdb-cluster-0 -- ps aux | grep 'rethinkdb' +root 7 0.1 2.1 233496 43408 ? Ssl 16:56 0:00 rethinkdb --ser +root 26 0.0 0.4 146948 8204 ? S 16:56 0:00 rethinkdb --ser +root 100 0.0 0.7 157192 16060 ? S 16:56 0:00 rethinkdb --ser + +$ kubectl exec -it my-release-rethinkdb-cluster-0 -- kill 7 +``` + +## Scaling + +Scaling should be managed by `helm upgrade`, which is the recommended way. Example: +``` +$ helm upgrade --set cluster.replicas=4 my-release stable/rethinkdb +``` diff --git a/stable/rethinkdb/init/Dockerfile b/stable/rethinkdb/init/Dockerfile new file mode 100644 index 0000000000..22a03f96ef --- /dev/null +++ b/stable/rethinkdb/init/Dockerfile @@ -0,0 +1,31 @@ +# Copyright 2016 The Kubernetes Authors All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM rethinkdb:2.3.5 +MAINTAINER Cody Lundquist + +RUN apt-get update && \ + apt-get install -yq curl && \ + rm -rf /var/cache/apt/* && rm -rf /var/lib/apt/lists/* + +ADD http://stedolan.github.io/jq/download/linux64/jq /usr/bin/jq +RUN chmod +x /usr/bin/jq + +ADD https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 /usr/local/bin/dumb-init +RUN chmod +x /usr/local/bin/dumb-init + +COPY ./files/run.sh ./rethinkdb-probe/rethinkdb-probe / +RUN chmod u+x /run.sh /rethinkdb-probe + +ENTRYPOINT ["/usr/local/bin/dumb-init", "/run.sh"] diff --git a/stable/rethinkdb/init/Makefile b/stable/rethinkdb/init/Makefile new file mode 100644 index 0000000000..641597e691 --- /dev/null +++ b/stable/rethinkdb/init/Makefile @@ -0,0 +1,30 @@ +# Copyright 2016 The Kubernetes Authors All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +all: push + +TAG = 0.1.0 +PREFIX = codylundquist/helm-rethinkdb-cluster + +buildprobe: + (cd ./rethinkdb-probe && ./build-probe.sh) + +container: buildprobe + docker build -t $(PREFIX):$(TAG) . + +push: container + docker push $(PREFIX):$(TAG) + +clean: + docker rmi $(PREFIX):$(TAG) diff --git a/stable/rethinkdb/init/files/run.sh b/stable/rethinkdb/init/files/run.sh new file mode 100644 index 0000000000..9443b635b6 --- /dev/null +++ b/stable/rethinkdb/init/files/run.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +# Copyright 2015 The Kubernetes Authors All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o pipefail + +POD_NAMESPACE=${POD_NAMESPACE:-default} +POD_IP=${POD_IP:-127.0.0.1} +RETHINK_CLUSTER_SERVICE=${RETHINK_CLUSTER_SERVICE:-"rethinkdb"} +POD_NAME=${POD_NAME:-"NO_POD_NAME"} +RETHINKDB_PASSWORD=${RETHINKDB_PASSWORD:-"auto"} + +# Transform - to _ to comply with requirements +SERVER_NAME=$(echo ${POD_NAME} | sed 's/-/_/g') + +echo "Using additional CLI flags: ${@}" +echo "Pod IP: ${POD_IP}" +echo "Pod namespace: ${POD_NAMESPACE}" +echo "Using service name: ${RETHINK_CLUSTER_SERVICE}" +echo "Using server name: ${SERVER_NAME}" + +echo "Checking for other nodes..." +if [[ -n "${KUBERNETES_SERVICE_HOST}" ]]; then + echo "Using endpoints to lookup other nodes..." + URL="https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}/api/v1/namespaces/${POD_NAMESPACE}/endpoints/${RETHINK_CLUSTER_SERVICE}" + echo "Endpoint url: ${URL}" + echo "Looking for IPs..." + token=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) + # try to pick up first different ip from endpoints + IP=$(curl -s ${URL} --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header "Authorization: Bearer ${token}" \ + | jq -s -r --arg h "${POD_IP}" '.[0].subsets | .[].addresses | [ .[].ip ] | map(select(. != $h)) | .[0]') || exit 1 + [[ "${IP}" == null ]] && IP="" + JOIN_ENDPOINTS="${IP}" +fi + +# xargs echo removes extra spaces before/after +# tr removes extra spaces in the middle +JOIN_ENDPOINTS=$(echo ${JOIN_ENDPOINTS} | xargs echo | tr -s ' ') + +if [ -n "${JOIN_ENDPOINTS}" ]; then + echo "Found other nodes: ${JOIN_ENDPOINTS}" + + # Now, transform join endpoints into --join ENDPOINT:29015 + # Put port after each + JOIN_ENDPOINTS=$(echo ${JOIN_ENDPOINTS} | sed -r 's/([0-9.])+/&:29015/g') + + # Put --join before each + JOIN_ENDPOINTS=$(echo ${JOIN_ENDPOINTS} | sed -e 's/^\|[ ]/&--join /g') +else + echo "No other nodes detected, will be a single instance." + if [ -n "$PROXY" ]; then + echo "Cannot start in proxy mode without endpoints." + exit 1 + fi +fi + +if [[ -n "${PROXY}" ]]; then + echo "Starting in proxy mode" + set -x + exec rethinkdb \ + proxy \ + --canonical-address ${POD_IP} \ + --initial-password ${RETHINKDB_PASSWORD} \ + ${JOIN_ENDPOINTS} \ + ${@} +else + set -x + exec rethinkdb \ + --server-name ${SERVER_NAME} \ + --canonical-address ${POD_IP} \ + --initial-password ${RETHINKDB_PASSWORD} \ + ${JOIN_ENDPOINTS} \ + ${@} +fi diff --git a/stable/rethinkdb/init/rethinkdb-probe/Dockerfile.build b/stable/rethinkdb/init/rethinkdb-probe/Dockerfile.build new file mode 100644 index 0000000000..9245e9d9c8 --- /dev/null +++ b/stable/rethinkdb/init/rethinkdb-probe/Dockerfile.build @@ -0,0 +1,10 @@ +FROM golang:1.6 +MAINTAINER Chris Dornsife + +# Build container to have a consistent go build environment + +COPY . /go/src/rethinkdb-probe +WORKDIR /go/src/rethinkdb-probe + +RUN go get ./... \ + && CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-w -s' -o /target/rethinkdb-probe . diff --git a/stable/rethinkdb/init/rethinkdb-probe/build-probe.sh b/stable/rethinkdb/init/rethinkdb-probe/build-probe.sh new file mode 100755 index 0000000000..7294d98f44 --- /dev/null +++ b/stable/rethinkdb/init/rethinkdb-probe/build-probe.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# Author: Chris Dornsife chris@dornsife.com +# This will run a build container and extract a binary. +# This doesn't require the use of a mount so it can be used +# in a build pipeline such as bitbucket. +PROJ=rethinkdb-probe + +HASH=`date +%s` +BUILD_NAME=${PROJ}-build-${HASH} + +docker build -t ${BUILD_NAME} -f ./Dockerfile.build . || exit 1 +docker create --name ${BUILD_NAME} ${BUILD_NAME} /bin/true || exit 1 +docker cp ${BUILD_NAME}:/target/$PROJ ./$PROJ || exit 1 +docker rm ${BUILD_NAME} || exit 1 +docker rmi -f ${BUILD_NAME} || exit 1 + +chmod +x ./$PROJ diff --git a/stable/rethinkdb/init/rethinkdb-probe/probe.go b/stable/rethinkdb/init/rethinkdb-probe/probe.go new file mode 100644 index 0000000000..be3cd2b663 --- /dev/null +++ b/stable/rethinkdb/init/rethinkdb-probe/probe.go @@ -0,0 +1,42 @@ +package main + +import ( + "log" + "os" + r "gopkg.in/gorethink/gorethink.v2" +) + + +func main() { + + url := os.Getenv("RETHINKDB_URL") + password := os.Getenv("RETHINKDB_PASSWORD") + + if url == "" { + url = "localhost:28015" + } + + session, err := r.Connect(r.ConnectOpts{ + Address: url, + Database: "rethinkdb", + Username: "admin", + Password: password, + }) + + if err != nil { + log.Fatalln(err.Error()) + } + + res, err := r.Table("server_status").Pluck("id", "name").Run(session) + if err != nil { + log.Fatalln(err.Error()) + } + defer res.Close() + + if res.IsNil() { + log.Fatalln("no server status results found") + } + + log.Printf("A-OK!") + +} diff --git a/stable/rethinkdb/templates/NOTES.txt b/stable/rethinkdb/templates/NOTES.txt new file mode 100644 index 0000000000..dcbc6744f8 --- /dev/null +++ b/stable/rethinkdb/templates/NOTES.txt @@ -0,0 +1,33 @@ +1. Get RethinkDB Driver Details +{{- if contains "NodePort" .Values.proxy.service.type }} + echo Host: $(kubectl get no --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo Port: $(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "fullname" . }}-proxy -o jsonpath='{.spec.ports[0].nodePort}') +{{- else if contains "LoadBalancer" .Values.proxy.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" . }}-proxy' + + echo Host: $(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "fullname" . }}-proxy -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo Port: $(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "fullname" . }}-proxy -o jsonpath='{.spec.ports[0].port}') + + NOTE: If you are using Minikube, the above will provide a blank Host and the wrong Port. + The following command will open up a browser with the correct Host and Port. + + minikube service {{ template "fullname" . }}-proxy +{{- else if contains "ClusterIP" .Values.proxy.service.type }} + NOTE: You will need to run a Kubernetes Port-Forward to connect to the ClusterIP Service + + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "name" . }}-proxy" -o jsonpath="{.items[0].metadata.name}") + kubectl port-forward $POD_NAME 28015:{{ .Values.ports.driver }} + + Host: 127.0.0.1 + Port: 28015 +{{- end }} + + echo Username: admin + echo Password: $(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "fullname" . }} -o jsonpath="{.data.rethinkdb-password}" | base64 --decode) + +2. Open RethinkDB Admin Console + + NOTE: The RethinkDB Admin Console is not exposed externally, you will need to start a 'kubectl proxy' before you can access it. + + URL: http://localhost:8001/api/v1/namespaces/{{ .Release.Namespace }}/services/{{ template "fullname" . }}-admin/proxy diff --git a/stable/rethinkdb/templates/_helpers.tpl b/stable/rethinkdb/templates/_helpers.tpl new file mode 100644 index 0000000000..f0d83d2edb --- /dev/null +++ b/stable/rethinkdb/templates/_helpers.tpl @@ -0,0 +1,16 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/stable/rethinkdb/templates/rethinkdb-admin-service.yaml b/stable/rethinkdb/templates/rethinkdb-admin-service.yaml new file mode 100644 index 0000000000..ba4a5e78bf --- /dev/null +++ b/stable/rethinkdb/templates/rethinkdb-admin-service.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "fullname" . }}-admin" + labels: + app: "{{ template "name" . }}-admin" + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} +spec: + clusterIP: None + ports: + - port: {{ .Values.ports.admin }} + targetPort: admin + selector: + app: "{{ template "name" . }}-proxy" + release: {{ .Release.Name | quote }} diff --git a/stable/rethinkdb/templates/rethinkdb-cluster-service.yaml b/stable/rethinkdb/templates/rethinkdb-cluster-service.yaml new file mode 100644 index 0000000000..865bca32d0 --- /dev/null +++ b/stable/rethinkdb/templates/rethinkdb-cluster-service.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "fullname" . }}-cluster" + labels: + app: "{{ template "name" . }}-cluster" + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + annotations: + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" + {{- if .Values.cluster.service.annotations }} +{{ toYaml .Values.cluster.service.annotations | indent 4 }} + {{- end }} +spec: + clusterIP: None + ports: + - port: {{ .Values.ports.cluster }} + targetPort: cluster + selector: + app: "{{ template "name" . }}-cluster" + release: {{ .Release.Name | quote }} diff --git a/stable/rethinkdb/templates/rethinkdb-cluster-stateful-set.yaml b/stable/rethinkdb/templates/rethinkdb-cluster-stateful-set.yaml new file mode 100644 index 0000000000..1a90bbf1e5 --- /dev/null +++ b/stable/rethinkdb/templates/rethinkdb-cluster-stateful-set.yaml @@ -0,0 +1,107 @@ +apiVersion: apps/v1beta1 +kind: StatefulSet +metadata: + name: "{{ template "fullname" . }}-cluster" + labels: + app: "{{ template "name" . }}-cluster" + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} +spec: + serviceName: "{{ template "fullname" . }}-cluster" + replicas: {{ .Values.cluster.replicas }} + template: + metadata: + name: "{{ template "fullname" . }}-cluster" + labels: + app: "{{ template "name" . }}-cluster" + heritage: {{.Release.Service | quote }} + release: {{.Release.Name | quote }} + chart: "{{.Chart.Name}}-{{.Chart.Version}}" + annotations: + {{- if .Values.cluster.podAnnotations }} +{{ toYaml .Values.cluster.podAnnotations | indent 8}} + {{- end }} + spec: + containers: + - name: {{ template "name" . }}-cluster + image: "{{ .Values.image.name }}:{{ .Values.image.tag }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + ports: + - name: cluster + containerPort: {{ .Values.ports.cluster }} + args: + - "--directory" + - "/data/db" + - "--bind" + - "all" + - "--no-http-admin" + - "--cache-size" + - {{ .Values.cluster.rethinkCacheSize | quote }} + volumeMounts: + - name: "datadir" + mountPath: "/data" + env: + - name: RETHINK_CLUSTER_SERVICE + value: "{{ template "fullname" . }}-cluster" + - name: RETHINKDB_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "fullname" . }} + key: rethinkdb-password + - name: POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + livenessProbe: + exec: + command: + - /rethinkdb-probe + failureThreshold: 3 + initialDelaySeconds: 15 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + readinessProbe: + exec: + command: + - /rethinkdb-probe + failureThreshold: 3 + initialDelaySeconds: 15 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + resources: +{{ toYaml .Values.cluster.resources | indent 12 }} +{{- if .Values.cluster.persistentVolume.enabled }} + volumeClaimTemplates: + - metadata: + name: datadir + annotations: + {{- if .Values.cluster.storageClass.enabled }} + volume.beta.kubernetes.io/storage-class: {{ template "fullname" . }} + {{- end }} + {{- range $key, $value := .Values.cluster.persistentVolume.annotations }} + {{ $key }}: {{ $value }} + {{- end }} + spec: + accessModes: + {{- range .Values.cluster.persistentVolume.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.cluster.persistentVolume.size | quote }} +{{- else }} + - name: datadir + emptyDir: {} +{{- end }} diff --git a/stable/rethinkdb/templates/rethinkdb-cluster-storage-class.yaml b/stable/rethinkdb/templates/rethinkdb-cluster-storage-class.yaml new file mode 100644 index 0000000000..8aff71ff6b --- /dev/null +++ b/stable/rethinkdb/templates/rethinkdb-cluster-storage-class.yaml @@ -0,0 +1,16 @@ +{{- if .Values.cluster.storageClass.enabled }} +apiVersion: storage.k8s.io/v1beta1 +kind: StorageClass +metadata: + labels: + app: "{{ template "name" . }}-cluster" + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} + name: {{ template "fullname" . }} +provisioner: {{ .Values.cluster.storageClass.provisioner }} +parameters: +{{- range $key, $value := .Values.cluster.storageClass.parameters }} + {{ $key }}: {{ $value }} +{{- end }} +{{- end }} diff --git a/stable/rethinkdb/templates/rethinkdb-proxy-deployment.yaml b/stable/rethinkdb/templates/rethinkdb-proxy-deployment.yaml new file mode 100644 index 0000000000..17da550fbb --- /dev/null +++ b/stable/rethinkdb/templates/rethinkdb-proxy-deployment.yaml @@ -0,0 +1,78 @@ +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: "{{ template "fullname" . }}-proxy" + labels: + app: "{{ template "name" . }}-proxy" + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + heritage: {{ .Release.Service | quote }} + release: {{ .Release.Name | quote }} +spec: + replicas: {{ .Values.proxy.replicas }} + template: + metadata: + name: {{ template "fullname" . }}-proxy + labels: + app: {{ template "name" . }}-proxy + heritage: {{.Release.Service | quote }} + release: {{.Release.Name | quote }} + chart: "{{.Chart.Name}}-{{.Chart.Version}}" + annotations: + {{- if .Values.proxy.podAnnotations }} +{{ toYaml .Values.proxy.podAnnotations | indent 8}} + {{- end }} + spec: + containers: + - name: {{ template "name" . }}-proxy + image: "{{ .Values.image.name }}:{{ .Values.image.tag }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + ports: + - name: cluster + containerPort: {{ .Values.ports.cluster }} + - name: driver + containerPort: {{ .Values.ports.driver }} + - name: admin + containerPort: {{ .Values.ports.admin }} + args: + - "--bind" + - "all" + {{- if .Values.proxy.driverTLS.enabled }} + - "--driver-tls-key" + - "/secrets/driver-key.pem" + - "--driver-tls-cert" + - "/secrets/driver-cert.pem" + {{- end }} + volumeMounts: + - name: "secrets" + mountPath: "/secrets" + env: + - name: PROXY + value: "true" + - name: RETHINK_CLUSTER_SERVICE + value: "{{ template "fullname" . }}-cluster" + - name: RETHINKDB_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "fullname" . }} + key: rethinkdb-password + - name: POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + resources: +{{ toYaml .Values.proxy.resources | indent 12 }} + volumes: + - name: secrets + projected: + sources: + - secret: + name: {{ template "fullname" . }} diff --git a/stable/rethinkdb/templates/rethinkdb-proxy-service.yaml b/stable/rethinkdb/templates/rethinkdb-proxy-service.yaml new file mode 100644 index 0000000000..1fb7d4d23a --- /dev/null +++ b/stable/rethinkdb/templates/rethinkdb-proxy-service.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "fullname" . }}-proxy + labels: + app: {{ template "name" . }}-proxy + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + annotations: + {{- if .Values.proxy.serviceAnnotations }} +{{ toYaml .Values.proxy.serviceAnnotations | indent 4 }} + {{- end }} +spec: + type: {{ .Values.proxy.service.type }} + clusterIP: "{{ .Values.proxy.service.clusterIP }}" +{{- if .Values.proxy.service.externalIPs }} + externalIPs: +{{ toYaml .Values.proxy.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.proxy.service.loadBalancerIP }} + loadBalancerIP: "{{ .Values.proxy.service.loadBalancerIP }}" +{{- end }} +{{- if .Values.proxy.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml .Values.proxy.service.loadBalancerSourceRanges | indent 4 }} +{{- end }} + ports: + - port: {{ .Values.ports.driver }} + targetPort: driver + selector: + app: {{ template "name" . }}-proxy + release: {{ .Release.Name }} diff --git a/stable/rethinkdb/templates/rethinkdb-secrets.yaml b/stable/rethinkdb/templates/rethinkdb-secrets.yaml new file mode 100644 index 0000000000..d9cdc506a2 --- /dev/null +++ b/stable/rethinkdb/templates/rethinkdb-secrets.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "name" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +type: Opaque +data: + rethinkdb-password: {{ .Values.rethinkdbPassword | b64enc | quote }} + {{- if .Values.proxy.driverTLS.enabled }} + driver-key.pem: {{ .Values.proxy.driverTLS.key | b64enc | quote }} + driver-cert.pem: {{ .Values.proxy.driverTLS.cert | b64enc| quote }} + {{- end }} diff --git a/stable/rethinkdb/values.yaml b/stable/rethinkdb/values.yaml new file mode 100644 index 0000000000..ce7335104e --- /dev/null +++ b/stable/rethinkdb/values.yaml @@ -0,0 +1,75 @@ +# Specs for the RethinkDB image +image: + name: codylundquist/helm-rethinkdb-cluster + tag: 0.1.0 + pullPolicy: IfNotPresent + +# RethinkDB Cluster Config +cluster: + replicas: 3 + resources: {} + # limits: + # cpu: 100m + # memory: 512Mi + # requests: + # cpu: 100m + # memory: 512Mi + podAnnotations: {} + service: + annotations: {} + storageClass: + enabled: false + # provisioner: kubernetes.io/gce-pd + # parameters: + # type: pd-ssd + persistentVolume: + enabled: true + # If defined, volume.beta.kubernetes.io/storage-class: + #storageClass: fast + accessModes: + - ReadWriteOnce + size: 1Gi + annotations: {} + # RethinkDB Cache Size in MB + rethinkCacheSize: 100 + +# RethinkDB Proxy Config +proxy: + replicas: 1 + resources: {} + # limits: + # cpu: 100m + # memory: 512Mi + # requests: + # cpu: 100m + # memory: 512Mi + podAnnotations: {} + service: + annotations: {} + type: ClusterIP + clusterIP: "" + # List of IP addresses at which the proxy service is available + # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips + # + externalIPs: [] + loadBalancerIP: "" + loadBalancerSourceRanges: [] + # Secure your RethinkDB Driver using TLS. + # Hint: You'll need to create your cert with a domain that is pointing + # to the External IP Address returned from the LoadBalancer + # More Info: https://www.rethinkdb.com/docs/security/#using-tls + driverTLS: + enabled: false + # key: |- + # << RSA PRIVATE KEY >> + # cert: |- + # << CERTIFICATE >> + +# RethinkDB Ports +ports: + cluster: 29015 + driver: 28015 + admin: 8080 + +# RethinkDB Admin Password +rethinkdbPassword: rethinkdb