Skip to content
This repository has been archived by the owner on Feb 22, 2022. It is now read-only.

Commit

Permalink
rethinkdb: Initial Commit (#1018)
Browse files Browse the repository at this point in the history
* 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.

#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.
  • Loading branch information
meenie authored and prydonius committed Jun 13, 2017
1 parent f884009 commit 465c9fb
Show file tree
Hide file tree
Showing 20 changed files with 801 additions and 0 deletions.
3 changes: 3 additions & 0 deletions stable/rethinkdb/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Local Files #
###############
init/rethinkdb-probe/rethinkdb-probe
22 changes: 22 additions & 0 deletions stable/rethinkdb/.helmignore
Original file line number Diff line number Diff line change
@@ -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/
14 changes: 14 additions & 0 deletions stable/rethinkdb/Chart.yaml
Original file line number Diff line number Diff line change
@@ -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
132 changes: 132 additions & 0 deletions stable/rethinkdb/README.md
Original file line number Diff line number Diff line change
@@ -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
```
31 changes: 31 additions & 0 deletions stable/rethinkdb/init/Dockerfile
Original file line number Diff line number Diff line change
@@ -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 <cody.lundquist@gmail.com>

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"]
30 changes: 30 additions & 0 deletions stable/rethinkdb/init/Makefile
Original file line number Diff line number Diff line change
@@ -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)
86 changes: 86 additions & 0 deletions stable/rethinkdb/init/files/run.sh
Original file line number Diff line number Diff line change
@@ -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
10 changes: 10 additions & 0 deletions stable/rethinkdb/init/rethinkdb-probe/Dockerfile.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM golang:1.6
MAINTAINER Chris Dornsife <chris@applariat.com>

# 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 .
18 changes: 18 additions & 0 deletions stable/rethinkdb/init/rethinkdb-probe/build-probe.sh
Original file line number Diff line number Diff line change
@@ -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
42 changes: 42 additions & 0 deletions stable/rethinkdb/init/rethinkdb-probe/probe.go
Original file line number Diff line number Diff line change
@@ -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!")

}
Loading

0 comments on commit 465c9fb

Please sign in to comment.