Commit 24418e2a by Guangbo Chen

Basecopy mongodb to v3.9.6

parent 380bd960
# 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
install
name: mongodb-replicaset
home: https://github.com/mongodb/mongo
version: 3.3.1
appVersion: 3.6
description: NoSQL document-oriented database that stores JSON-like documents with
dynamic schemas, simplifying the integration of data in content-driven applications.
icon: https://webassets.mongodb.com/_com_assets/cms/mongodb-logo-rgb-j6w271g1xn.jpg
sources:
- https://github.com/mongodb/mongo
maintainers:
- name: foxish
email: ramanathana@google.com
- name: unguiculus
email: unguiculus@gmail.com
approvers:
- foxish
- unguiculus
reviewers:
- foxish
- unguiculus
# MongoDB Helm Chart
## Prerequisites Details
* Kubernetes 1.8+ with Beta APIs enabled.
* PV support on the underlying infrastructure.
## Chart Details
This chart implements a dynamically scalable [MongoDB replica set](https://docs.mongodb.com/manual/tutorial/deploy-replica-set/)
using Kubernetes StatefulSets and Init Containers.
#!/usr/bin/env bash
# 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.
replica_set="$REPLICA_SET"
script_name=${0##*/}
if [[ "$AUTH" == "true" ]]; then
admin_user="$ADMIN_USER"
admin_password="$ADMIN_PASSWORD"
admin_creds=(-u "$admin_user" -p "$admin_password")
auth_args=(--auth --keyFile=/data/configdb/key.txt)
fi
function log() {
local msg="$1"
local timestamp
timestamp=$(date --iso-8601=ns)
echo "[$timestamp] [$script_name] $msg" >> /work-dir/log.txt
}
function shutdown_mongo() {
if [[ $# -eq 1 ]]; then
args="timeoutSecs: $1"
else
args='force: true'
fi
log "Shutting down MongoDB ($args)..."
mongo admin "${admin_creds[@]}" "${ssl_args[@]}" --eval "db.shutdownServer({$args})"
}
my_hostname=$(hostname)
log "Bootstrapping MongoDB replica set member: $my_hostname"
log "Reading standard input..."
while read -ra line; do
if [[ "${line}" == *"${my_hostname}"* ]]; then
service_name="$line"
continue
fi
peers=("${peers[@]}" "$line")
done
# Generate the ca cert
ca_crt=/data/configdb/tls.crt
if [ -f "$ca_crt" ]; then
log "Generating certificate"
ca_key=/data/configdb/tls.key
pem=/work-dir/mongo.pem
ssl_args=(--ssl --sslCAFile "$ca_crt" --sslPEMKeyFile "$pem")
cat >openssl.cnf <<EOL
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $(echo -n "$my_hostname" | sed s/-[0-9]*$//)
DNS.2 = $my_hostname
DNS.3 = $service_name
DNS.4 = localhost
DNS.5 = 127.0.0.1
EOL
# Generate the certs
openssl genrsa -out mongo.key 2048
openssl req -new -key mongo.key -out mongo.csr -subj "/CN=$my_hostname" -config openssl.cnf
openssl x509 -req -in mongo.csr \
-CA "$ca_crt" -CAkey "$ca_key" -CAcreateserial \
-out mongo.crt -days 3650 -extensions v3_req -extfile openssl.cnf
rm mongo.csr
cat mongo.crt mongo.key > $pem
rm mongo.key mongo.crt
fi
log "Peers: ${peers[*]}"
log "Starting a MongoDB instance..."
mongod --config /data/configdb/mongod.conf --dbpath=/data/db --replSet="$replica_set" --port=27017 "${auth_args[@]}" --bind_ip_all >> /work-dir/log.txt 2>&1 &
log "Waiting for MongoDB to be ready..."
until mongo "${ssl_args[@]}" --eval "db.adminCommand('ping')"; do
log "Retrying..."
sleep 2
done
log "Initialized."
# try to find a master and add yourself to its replica set.
for peer in "${peers[@]}"; do
if mongo admin --host "$peer" "${admin_creds[@]}" "${ssl_args[@]}" --eval "rs.isMaster()" | grep '"ismaster" : true'; then
log "Found master: $peer"
log "Adding myself ($service_name) to replica set..."
mongo admin --host "$peer" "${admin_creds[@]}" "${ssl_args[@]}" --eval "rs.add('$service_name')"
sleep 3
log 'Waiting for replica to reach SECONDARY state...'
until printf '.' && [[ $(mongo admin "${admin_creds[@]}" "${ssl_args[@]}" --quiet --eval "rs.status().myState") == '2' ]]; do
sleep 1
done
log '✓ Replica reached SECONDARY state.'
shutdown_mongo "60"
log "Good bye."
exit 0
fi
done
# else initiate a replica set with yourself.
if mongo "${ssl_args[@]}" --eval "rs.status()" | grep "no replset config has been received"; then
log "Initiating a new replica set with myself ($service_name)..."
mongo "${ssl_args[@]}" --eval "rs.initiate({'_id': '$replica_set', 'members': [{'_id': 0, 'host': '$service_name'}]})"
sleep 3
log 'Waiting for replica to reach PRIMARY state...'
until printf '.' && [[ $(mongo "${ssl_args[@]}" --quiet --eval "rs.status().myState") == '1' ]]; do
sleep 1
done
log '✓ Replica reached PRIMARY state.'
if [[ "$AUTH" == "true" ]]; then
log "Creating admin user..."
mongo admin "${ssl_args[@]}" --eval "db.createUser({user: '$admin_user', pwd: '$admin_password', roles: [{role: 'root', db: 'admin'}]})"
fi
log "Done."
fi
shutdown_mongo
log "Good bye."
# 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 alpine:3.7
MAINTAINER Anirudh Ramanathan <foxish@google.com>
RUN apk update && apk add bash openssl && wget -qO /peer-finder http://storage.googleapis.com/kubernetes-release/pets/peer-finder
ENTRYPOINT ["/install.sh"]
COPY install.sh /
RUN chmod -c 755 /install.sh /peer-finder
# 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.6
PREFIX = staging-k8s.gcr.io/mongodb-install
container:
docker build -t $(PREFIX):$(TAG) .
push: container
gcloud docker -- push $(PREFIX):$(TAG)
clean:
docker rmi $(PREFIX):$(TAG)
#!/usr/bin/env bash
# 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.
# This volume is assumed to exist and is shared with the peer-finder
# init container. It contains on-start/change configuration scripts.
WORKDIR_VOLUME="/work-dir"
for i in "$@"; do
case "$i" in
-w=*|--work-dir=*)
WORKDIR_VOLUME="${i#*=}"
shift
;;
*)
# unknown option
;;
esac
done
echo Installing config scripts into "${WORKDIR_VOLUME}"
mkdir -p "${WORKDIR_VOLUME}"
cp /peer-finder "${WORKDIR_VOLUME}"/
categories:
- Database
- NoSQL
questions:
- variable: defaultImage
default: true
description: "Use default Docker images"
label: Use Default Images
type: boolean
show_subquestion_if: false
group: "Container Images"
subquestions:
- variable: installImage.repository
default: "k8s.gcr.io/mongodb-install"
description: "Image name for the install container"
type: string
label: Init-Container Image Name
- variable: installImage.tag
default: "0.6"
description: "Image tag for the install container"
type: string
label: Init-Container Image Tag
- variable: image.repository
default: "mongo"
description: "MongoDB image name"
type: string
label: MongoDB Image Name
- variable: image.tag
default: "3.6"
description: "MongoDB image tag"
type: string
label: Image Tag
- variable: replicas
default: 3
description: "Number of replicas in the replica set"
type: int
min: 3
max: 12
label: Number of Replicas
required: true
group: "MongoDB Settings"
- variable: port
default: "27017"
description: "MongoDB port"
type: string
label: MongoDB port
required: true
group: "MongoDB Settings"
- variable: replicaSetName
default: "rs0"
description: "The name of the replica set"
type: string
label: ReplicaSet Name
required: true
group: "MongoDB Settings"
- variable: auth.enabled
default: true
description: "If true, keyfile access control is enabled"
type: boolean
label: Enable Auth
required: true
show_subquestion_if: true
group: "MongoDB Settings"
subquestions:
- variable: auth.key
default: "myauthkey"
description: "Key for internal authentication, https://docs.mongodb.com/v3.0/tutorial/enable-internal-authentication/"
type: string
label: Auth Key
required: true
- variable: auth.adminUser
default: "admin"
description: "MongoDB admin user"
type: string
label: MongoDB Admin User
required: true
- variable: auth.adminPassword
default: ""
description: "MongoDB admin password"
type: password
label: MongoDB Admin Password
required: true
- variable: persistentVolume.enabled
default: false
description: "Enable persistent volume for MongoDB"
type: boolean
required: true
label: MongoDB Persistent Volume Enabled
show_subquestion_if: true
group: "Persistent Volume"
subquestions:
- variable: persistentVolume.size
default: "10Gi"
description: "MongoDB Persistent Volume Size"
type: string
label: MongoDB Volume Size
- variable: persistentVolume.storageClass
default: ""
description: "If unndefined or null, uses the default StorageClass. Defaults to null."
type: storageclass
label: Storage Class for MongoDB
1. After the statefulset is created completely, one can check which instance is primary by running:
$ for ((i = 0; i < {{ .Values.replicas }}; ++i)); do kubectl exec --namespace {{ .Release.Namespace }} {{ template "mongodb-replicaset.fullname" . }}-$i -- sh -c 'mongo --eval="printjson(rs.isMaster())"'; done
2. One can insert a key into the primary instance of the mongodb replica set by running the following:
MASTER_POD_NAME must be replaced with the name of the master found from the previous step.
$ kubectl exec --namespace {{ .Release.Namespace }} MASTER_POD_NAME -- mongo --eval="printjson(db.test.insert({key1: 'value1'}))"
3. One can fetch the keys stored in the primary or any of the slave nodes in the following manner.
POD_NAME must be replaced by the name of the pod being queried.
$ kubectl exec --namespace {{ .Release.Namespace }} POD_NAME -- mongo --eval="rs.slaveOk(); db.test.find().forEach(printjson)"
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "mongodb-replicaset.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).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "mongodb-replicaset.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "mongodb-replicaset.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create the name for the admin secret.
*/}}
{{- define "mongodb-replicaset.adminSecret" -}}
{{- if .Values.auth.existingAdminSecret -}}
{{- .Values.auth.existingAdminSecret -}}
{{- else -}}
{{- template "mongodb-replicaset.fullname" . -}}-admin
{{- end -}}
{{- end -}}
{{/*
Create the name for the key secret.
*/}}
{{- define "mongodb-replicaset.keySecret" -}}
{{- if .Values.auth.existingKeySecret -}}
{{- .Values.auth.existingKeySecret -}}
{{- else -}}
{{- template "mongodb-replicaset.fullname" . -}}-keyfile
{{- end -}}
{{- end -}}
{{- if and (.Values.auth.enabled) (not .Values.auth.existingAdminSecret) -}}
apiVersion: v1
kind: Secret
metadata:
labels:
app: {{ template "mongodb-replicaset.name" . }}
chart: {{ template "mongodb-replicaset.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "mongodb-replicaset.adminSecret" . }}
type: Opaque
data:
user: {{ .Values.auth.adminUser | b64enc }}
password: {{ .Values.auth.adminPassword | b64enc }}
{{- end -}}
{{- if .Values.tls.enabled -}}
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
labels:
app: {{ template "mongodb-replicaset.name" . }}
chart: {{ template "mongodb-replicaset.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "mongodb-replicaset.fullname" . }}-ca
data:
tls.key: {{ .Values.tls.cakey }}
tls.crt: {{ .Values.tls.cacert }}
{{- end -}}
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: {{ template "mongodb-replicaset.name" . }}
chart: {{ template "mongodb-replicaset.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "mongodb-replicaset.fullname" . }}-init
data:
on-start.sh: |
{{ .Files.Get "init/on-start.sh" | indent 4 }}
{{- if and (.Values.auth.enabled) (not .Values.auth.existingKeySecret) -}}
apiVersion: v1
kind: Secret
metadata:
labels:
app: {{ template "mongodb-replicaset.name" . }}
chart: {{ template "mongodb-replicaset.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "mongodb-replicaset.keySecret" . }}
type: Opaque
data:
key.txt: {{ .Values.auth.key | b64enc }}
{{- end -}}
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: {{ template "mongodb-replicaset.name" . }}
chart: {{ template "mongodb-replicaset.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "mongodb-replicaset.fullname" . }}-mongodb
data:
mongod.conf: |
{{ toYaml .Values.configmap | indent 4 }}
{{- if .Values.podDisruptionBudget -}}
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
labels:
app: {{ template "mongodb-replicaset.name" . }}
chart: {{ template "mongodb-replicaset.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "mongodb-replicaset.fullname" . }}
spec:
selector:
matchLabels:
app: {{ template "mongodb-replicaset.name" . }}
release: {{ .Release.Name }}
{{ toYaml .Values.podDisruptionBudget | indent 2 }}
{{- end -}}
# A headless service to create DNS records
apiVersion: v1
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
{{- if .Values.serviceAnnotations }}
{{ toYaml .Values.serviceAnnotations | indent 4 }}
{{- end }}
labels:
app: {{ template "mongodb-replicaset.name" . }}
chart: {{ template "mongodb-replicaset.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "mongodb-replicaset.fullname" . }}
spec:
type: ClusterIP
clusterIP: None
ports:
- name: peer
port: {{ .Values.port }}
selector:
app: {{ template "mongodb-replicaset.name" . }}
release: {{ .Release.Name }}
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
labels:
app: {{ template "mongodb-replicaset.name" . }}
chart: {{ template "mongodb-replicaset.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "mongodb-replicaset.fullname" . }}
spec:
podManagementPolicy: {{ .Values.podManagementPolicy }}
selector:
matchLabels:
app: {{ template "mongodb-replicaset.name" . }}
release: {{ .Release.Name }}
serviceName: {{ template "mongodb-replicaset.fullname" . }}
replicas: {{ .Values.replicas }}
template:
metadata:
labels:
app: {{ template "mongodb-replicaset.name" . }}
release: {{ .Release.Name }}
annotations:
{{- if .Values.podAnnotations }}
{{ toYaml .Values.podAnnotations | indent 8 }}
{{- end }}
spec:
securityContext:
{{ toYaml .Values.securityContext | indent 8 }}
initContainers:
- name: copy-config
image: busybox
command:
- "sh"
args:
- "-c"
- |
set -e
set -x
cp /configdb-readonly/mongod.conf /data/configdb/mongod.conf
{{- if .Values.tls.enabled }}
cp /ca-readonly/tls.key /data/configdb/tls.key
cp /ca-readonly/tls.crt /data/configdb/tls.crt
{{- end }}
{{- if .Values.auth.enabled }}
cp /keydir-readonly/key.txt /data/configdb/key.txt
chmod 600 /data/configdb/key.txt
{{- end }}
volumeMounts:
- name: workdir
mountPath: /work-dir
- name: config
mountPath: /configdb-readonly
- name: configdir
mountPath: /data/configdb
{{- if .Values.tls.enabled }}
- name: ca
mountPath: /ca-readonly
{{- end }}
{{- if .Values.auth.enabled }}
- name: keydir
mountPath: /keydir-readonly
{{- end }}
- name: install
image: "{{ .Values.installImage.repository }}:{{ .Values.installImage.tag }}"
args:
- --work-dir=/work-dir
imagePullPolicy: "{{ .Values.installImage.pullPolicy }}"
volumeMounts:
- name: workdir
mountPath: /work-dir
- name: bootstrap
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command:
- /work-dir/peer-finder
args:
- -on-start=/init/on-start.sh
- "-service={{ template "mongodb-replicaset.fullname" . }}"
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: REPLICA_SET
value: {{ .Values.replicaSetName }}
{{- if .Values.auth.enabled }}
- name: AUTH
value: "true"
- name: ADMIN_USER
valueFrom:
secretKeyRef:
name: "{{ template "mongodb-replicaset.adminSecret" . }}"
key: user
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: "{{ template "mongodb-replicaset.adminSecret" . }}"
key: password
{{- end }}
volumeMounts:
- name: workdir
mountPath: /work-dir
- name: init
mountPath: /init
- name: configdir
mountPath: /data/configdb
- name: datadir
mountPath: /data/db
containers:
- name: {{ template "mongodb-replicaset.name" . }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
{{- if .Values.extraVars }}
env:
{{ toYaml .Values.extraVars | indent 12 }}
{{- end }}
ports:
- name: peer
containerPort: 27017
resources:
{{ toYaml .Values.resources | indent 12 }}
command:
- mongod
args:
- --config=/data/configdb/mongod.conf
- --dbpath=/data/db
- --replSet={{ .Values.replicaSetName }}
- --port=27017
- --bind_ip=0.0.0.0
{{- if .Values.auth.enabled }}
- --auth
- --keyFile=/data/configdb/key.txt
{{- end }}
{{- if .Values.tls.enabled }}
- --ssl
- --sslCAFile=/data/configdb/tls.crt
- --sslPEMKeyFile=/work-dir/mongo.pem
{{- end }}
livenessProbe:
exec:
command:
- mongo
{{- if .Values.tls.enabled }}
- --ssl
- --sslCAFile=/data/configdb/tls.crt
- --sslPEMKeyFile=/work-dir/mongo.pem
{{- end }}
- --eval
- "db.adminCommand('ping')"
initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
successThreshold: {{ .Values.livenessProbe.successThreshold }}
readinessProbe:
exec:
command:
- mongo
{{- if .Values.tls.enabled }}
- --ssl
- --sslCAFile=/data/configdb/tls.crt
- --sslPEMKeyFile=/work-dir/mongo.pem
{{- end }}
- --eval
- "db.adminCommand('ping')"
initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
successThreshold: {{ .Values.readinessProbe.successThreshold }}
volumeMounts:
- name: datadir
mountPath: /data/db
- name: configdir
mountPath: /data/configdb
- name: workdir
mountPath: /work-dir
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
volumes:
- name: config
configMap:
name: {{ template "mongodb-replicaset.fullname" . }}-mongodb
- name: init
configMap:
defaultMode: 0755
name: {{ template "mongodb-replicaset.fullname" . }}-init
{{- if .Values.tls.enabled }}
- name: ca
secret:
defaultMode: 0400
secretName: {{ template "mongodb-replicaset.fullname" . }}-ca
{{- end }}
{{- if .Values.auth.enabled }}
- name: keydir
secret:
defaultMode: 0400
secretName: {{ template "mongodb-replicaset.keySecret" . }}
{{- end }}
- name: workdir
emptyDir: {}
- name: configdir
emptyDir: {}
{{- if not .Values.persistentVolume.enabled }}
- name: datadir
emptyDir: {}
{{- end }}
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}
{{- if .Values.persistentVolume.enabled }}
volumeClaimTemplates:
- metadata:
name: datadir
annotations:
{{- range $key, $value := .Values.persistentVolume.annotations }}
{{ $key }}: {{ $value }}
{{- end }}
spec:
accessModes:
{{- range .Values.persistentVolume.accessModes }}
- {{ . | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistentVolume.size | quote }}
{{- if .Values.persistentVolume.storageClass }}
{{- if (eq "-" .Values.persistentVolume.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: "{{ .Values.persistentVolume.storageClass }}"
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.runtest }}
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app: {{ template "mongodb-replicaset.name" . }}
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "mongodb-replicaset.fullname" . }}-tests
data:
mongodb-up-test.sh: |
{{ .Files.Get "tests/mongodb-up-test.sh" | indent 4 }}
{{- end }}
{{- if .Values.runtest }}
apiVersion: v1
kind: Pod
metadata:
labels:
app: {{ template "mongodb-replicaset.name" . }}
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "mongodb-replicaset.fullname" . }}-test
annotations:
"helm.sh/hook": test-success
spec:
initContainers:
- name: test-framework
image: dduportal/bats:0.4.0
command:
- bash
- -c
- |
set -ex
# copy bats to tools dir
cp -R /usr/local/libexec/ /tools/bats/
volumeMounts:
- name: tools
mountPath: /tools
containers:
- name: mongo
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command:
- /tools/bats/bats
- -t
- /tests/mongodb-up-test.sh
env:
- name: FULL_NAME
value: {{ template "mongodb-replicaset.fullname" . }}
- name: REPLICAS
value: "{{ .Values.replicas }}"
volumeMounts:
- name: tools
mountPath: /tools
- name: tests
mountPath: /tests
volumes:
- name: tools
emptyDir: {}
- name: tests
configMap:
name: {{ template "mongodb-replicaset.fullname" . }}-tests
restartPolicy: Never
{{- end }}
#! /bin/bash
# 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.
NS="${RELEASE_NAMESPACE:-default}"
POD_NAME="${RELEASE_NAME:-mongo}-mongodb-replicaset"
MONGOCACRT=/ca/tls.crt
MONGOPEM=/work-dir/mongo.pem
if [ -f $MONGOPEM ]; then
MONGOARGS="--ssl --sslCAFile $MONGOCACRT --sslPEMKeyFile $MONGOPEM"
fi
for i in $(seq 0 2); do
pod="${POD_NAME}-$i"
kubectl exec --namespace $NS $pod -- sh -c 'mongo '"$MONGOARGS"' --eval="printjson(rs.isMaster())"' | grep '"ismaster" : true'
if [ $? -eq 0 ]; then
echo "Found master: $pod"
MASTER=$pod
break
fi
done
kubectl exec --namespace $NS $MASTER -- mongo "$MONGOARGS" --eval='printjson(db.test.insert({"status": "success"}))'
# TODO: find maximum duration to wait for slaves to be up-to-date with master.
sleep 2
for i in $(seq 0 2); do
pod="${POD_NAME}-$i"
if [[ $pod != $MASTER ]]; then
echo "Reading from slave: $pod"
kubectl exec --namespace $NS $pod -- mongo "$MONGOARGS" --eval='rs.slaveOk(); db.test.find().forEach(printjson)'
fi
done
#!/usr/bin/env bash
MONGOCACRT=/ca/tls.crt
MONGOPEM=/work-dir/mongo.pem
if [ -f "$MONGOPEM" ]; then
MONGOARGS="--ssl --sslCAFile $MONGOCACRT --sslPEMKeyFile $MONGOPEM"
fi
pod_name() {
local full_name="${FULL_NAME?Environment variable FULL_NAME not set}"
local index="$1"
echo "$full_name-$index.$full_name"
}
replicas() {
echo "${REPLICAS?Environment variable REPLICAS not set}"
}
master_pod() {
for ((i = 0; i < $(replicas); ++i)); do
response=$(mongo "$MONGOARGS" "--host=$(pod_name "$i")" "--eval=rs.isMaster().ismaster")
if [[ "$response" =~ "true" ]]; then
pod_name "$i"
break
fi
done
}
setup() {
local ready=0
until [[ "$ready" -eq $(replicas) ]]; do
echo "Waiting for application to become ready" >&2
sleep 1
for ((i = 0; i < $(replicas); ++i)); do
response=$(mongo "$MONGOARGS" "--host=$(pod_name "$i")" "--eval=rs.status()" || true)
if [[ "$response" =~ .*ok.* ]]; then
ready=$((ready + 1))
fi
done
done
}
@test "Testing mongodb client is accessible" {
mongo -h
[ "$?" -eq 0 ]
}
@test "Connect mongodb client to mongodb pods" {
for ((i = 0; i < $(replicas); ++i)); do
response=$(mongo "$MONGOARGS" "--host=$(pod_name "$i")" "--eval=rs.status()")
if [[ ! "$response" =~ .*ok.* ]]; then
exit 1
fi
done
}
@test "Write key to master" {
response=$(mongo "$MONGOARGS" --host=$(master_pod) "--eval=db.test.insert({\"abc\": \"def\"}).nInserted")
if [[ ! "$response" =~ "1" ]]; then
exit 1
fi
}
@test "Read key from slaves" {
# wait for slaves to catch up
sleep 10
for ((i = 0; i < $(replicas); ++i)); do
response=$(mongo "$MONGOARGS" --host=$(pod_name "$i") "--eval=rs.slaveOk(); db.test.find({\"abc\":\"def\"})")
if [[ ! "$response" =~ .*def.* ]]; then
exit 1
fi
done
}
replicas: 3
port: 27017
replicaSetName: rs0
podDisruptionBudget: {}
# maxUnavailable: 1
# minAvailable: 2
## Start and stop pods in Parallel or OrderedReady (one-by-one.) Note - Can not change after first release.
## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy
podManagementPolicy: OrderedReady
auth:
enabled: false
# adminUser: username
# adminPassword: password
# key: keycontent
# existingKeySecret:
# existingAdminSecret:
# Specs for the Docker image for the init container that establishes the replica set
installImage:
repository: k8s.gcr.io/mongodb-install
tag: 0.6
pullPolicy: IfNotPresent
# Specs for the MongoDB image
image:
repository: mongo
tag: 3.6
pullPolicy: IfNotPresent
# Additional environment variables to be set in the container
extraVars: {}
# - name: TCMALLOC_AGGRESSIVE_DECOMMIT
# value: "true"
# Annotations to be added to MongoDB pods
podAnnotations: {}
securityContext:
runAsUser: 999
fsGroup: 999
runAsNonRoot: true
resources: {}
# limits:
# cpu: 500m
# memory: 512Mi
# requests:
# cpu: 100m
# memory: 256Mi
## Node selector
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
nodeSelector: {}
affinity: {}
tolerations: []
persistentVolume:
enabled: true
## mongodb-replicaset data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
# storageClass: "-"
accessModes:
- ReadWriteOnce
size: 10Gi
annotations: {}
# Annotations to be added to the service
serviceAnnotations: {}
tls:
# Enable or disable MongoDB TLS support
enabled: false
# Please generate your own TLS CA by generating it via:
# $ openssl genrsa -out ca.key 2048
# $ openssl req -x509 -new -nodes -key ca.key -days 10000 -out ca.crt -subj "/CN=mydomain.com"
# After that you can base64 encode it and paste it here:
# $ cat ca.key | base64 -w0
# cacert:
# cakey:
# Entries for the MongoDB config file
configmap:
## Period to wait for broker graceful shutdown (sigterm) before pod is killed (sigkill)
## ref: https://kubernetes-v1-4.github.io/docs/user-guide/production-pods/#lifecycle-hooks-and-termination-notice
## ref: https://kafka.apache.org/10/documentation.html#brokerconfigs controlled.shutdown.*
terminationGracePeriodSeconds: 30
# Readiness probe
readinessProbe:
initialDelaySeconds: 5
timeoutSeconds: 1
failureThreshold: 3
periodSeconds: 10
successThreshold: 1
# Liveness probe
livenessProbe:
initialDelaySeconds: 30
timeoutSeconds: 5
failureThreshold: 3
periodSeconds: 10
successThreshold: 1
# whether run helm test or nnot
runtest: false
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment