Skip to content

Addon: storage classes for dynamically provisioned volumes #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 36 commits into
base: kafka-011
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
1aac57a
Merge pull request #30 from Yolean/kafka-011
solsson Jul 29, 2017
be0d1ac
Adds annotations, assuming gnu sed
solsson Jul 29, 2017
7a1173b
Fixes the sed on OSX
solsson Jul 29, 2017
4ece24c
There's probably a tool out there for combining branches
solsson Jul 29, 2017
5baf8c2
addon-rest isn't quite ready for the world yet. And ...
solsson Jul 31, 2017
1899096
Topic deletion will be enabled by default in Kafka 1.0
solsson Jul 31, 2017
266b75b
Merge pull request #53 from Yolean/delete-topics-enabled-by-default
solsson Jul 31, 2017
a39d09d
Let's postpone merge of RollingUpdate but evaluate it in QA
solsson Aug 2, 2017
a8db336
Rack awareness is candidate for merge
solsson Aug 3, 2017
7cf2a5d
RBAC rights are purely additive so ...
solsson Aug 5, 2017
05107fd
I don't really care, but which yaml indentation is winning?
solsson Aug 5, 2017
a8ee55b
With default service account curl works again
solsson Aug 5, 2017
3597426
Got the feeling from kubectl get clusterrole ...
solsson Aug 5, 2017
8f637b7
Recommends that you create rbac
solsson Aug 5, 2017
27421fb
Shows how to see that you need rbac, but makes readme heavier
solsson Aug 5, 2017
1c6b7bb
Addons can maintain their policies, so moving this to
solsson Aug 5, 2017
79d65fd
Details will live in the respective policies
solsson Aug 5, 2017
13520a6
Moved to its PR, multizone-rack-awareness
solsson Aug 5, 2017
57c343b
Merge pull request #59 from Yolean/rbac-namespace-default
solsson Aug 5, 2017
23e1d9e
Temp commit so that github allows a PR to be created, where I can kee…
solsson Jul 19, 2017
c0645ee
Starts scripting, but the API call gets 403 for anonymous user
solsson Aug 1, 2017
8fe76ff
Looks up zone if kubectl is found, tries to not break config otherwise
solsson Aug 3, 2017
7e7b342
Uses an image with kubectl based on the same debian tag as kafka
solsson Aug 3, 2017
3678ad5
I suppose most init scripts will do fine with curl+kubectl+bash
solsson Aug 3, 2017
ff972b9
Adds RBAC policy for kubectl to look up node's zone
solsson Aug 5, 2017
09e733b
Merge pull request #41 from Yolean/multizone-rack-awareness
solsson Aug 5, 2017
723c514
got merged
solsson Aug 5, 2017
2ca4453
The default is Delete, which violates our no-surpises ambition
solsson Aug 3, 2017
7e83bac
Shorter, possibly clearer
solsson Aug 4, 2017
1f4321e
We prefer Ready:False status instead of restarted pods,
solsson Aug 5, 2017
0295ac5
Don't look like env var interpolation, when it's not
solsson Aug 6, 2017
197eaf3
I think Schema Registry + REST Proxy is ok for production now
solsson Aug 8, 2017
4d3754d
Still short
solsson Aug 8, 2017
11496d2
Merge branch 'persistent-volumes-retain', the readme ...
solsson Aug 8, 2017
c3969a8
Adds storage class for Zookeeper, with sample manifests
solsson Jul 28, 2017
ebcff38
Adds storage class for kafka brokers
solsson Jul 28, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions 10broker-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,21 @@ data:
#!/bin/bash
set -x

export KAFKA_BROKER_ID=${HOSTNAME##*-}
sed -i "s/\${KAFKA_BROKER_ID}/$KAFKA_BROKER_ID/" /etc/kafka/server.properties
KAFKA_BROKER_ID=${HOSTNAME##*-}
sed -i "s/#init#broker.id=#init#/broker.id=$KAFKA_BROKER_ID/" /etc/kafka/server.properties

hash kubectl 2>/dev/null || {
sed -i "s/#init#broker.rack=#init#/#init#broker.rack=# kubectl not found in path/" /etc/kafka/server.properties
} && {
ZONE=$(kubectl get node "$NODE_NAME" -o=go-template='{{index .metadata.labels "failure-domain.beta.kubernetes.io/zone"}}')
if [ $? -ne 0 ]; then
sed -i "s/#init#broker.rack=#init#/#init#broker.rack=# zone lookup failed, see -c init-config logs/" /etc/kafka/server.properties
elif [ "x$ZONE" == "x<no value>" ]; then
sed -i "s/#init#broker.rack=#init#/#init#broker.rack=# zone label not found for node $NODE_NAME/" /etc/kafka/server.properties
else
sed -i "s/#init#broker.rack=#init#/broker.rack=$ZONE/" /etc/kafka/server.properties
fi
}

server.properties: |-
# Licensed to the Apache Software Foundation (ASF) under one or more
Expand All @@ -32,10 +45,12 @@ data:
############################# Server Basics #############################

# The id of the broker. This must be set to a unique integer for each broker.
broker.id=${KAFKA_BROKER_ID}
#init#broker.id=#init#

#init#broker.rack=#init#

# Switch to enable topic deletion or not, default value is false
#delete.topic.enable=true
delete.topic.enable=true

############################# Socket Server Settings #############################

Expand Down Expand Up @@ -170,7 +185,7 @@ data:

# Unspecified loggers and loggers with additivity=true output to server.log and stdout
# Note that INFO only applies to unspecified loggers, the log level of the child logger is used otherwise
log4j.rootLogger=INFO, stdout, kafkaAppender
log4j.rootLogger=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
Expand Down
11 changes: 9 additions & 2 deletions 50kafka.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ spec:
terminationGracePeriodSeconds: 30
initContainers:
- name: init-config
image: solsson/kafka:0.11.0.0@sha256:b27560de08d30ebf96d12e74f80afcaca503ad4ca3103e63b1fd43a2e4c976ce
image: solsson/kafka-initutils@sha256:c275d681019a0d8f01295dbd4a5bae3cfa945c8d0f7f685ae1f00f2579f08c7d
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
command: ['/bin/bash', '/etc/kafka/init.sh']
volumeMounts:
- name: config
Expand Down Expand Up @@ -43,7 +48,7 @@ spec:
requests:
cpu: 100m
memory: 512Mi
livenessProbe:
readinessProbe:
exec:
command:
- /bin/sh
Expand All @@ -61,6 +66,8 @@ spec:
volumeClaimTemplates:
- metadata:
name: data
annotations:
volume.beta.kubernetes.io/storage-class: kafka-broker
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
Expand Down
31 changes: 27 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ How to use:
* Kafka for real: fork and have a look at [addon](https://github.com/Yolean/kubernetes-kafka/labels/addon)s.
* Join the discussion in issues and PRs.

Why?
See for yourself, but we think this project gives you better adaptability than [helm](https://github.com/kubernetes/helm) [chart](https://github.com/kubernetes/charts/tree/master/incubator/kafka)s. No single readable readme or template can properly introduce both Kafka and Kubernets.
No readable readme can properly introduce both [Kafka](http://kafka.apache.org/) and [Kubernets](https://kubernetes.io/),
but we think the combination of the two is a great backbone for microservices.
Back when we read [Newman](http://samnewman.io/books/building_microservices/) we were beginners with both.
Now we've read [Kleppmann](http://dataintensive.net/), [Confluent](https://www.confluent.io/blog/) and [SRE](https://landing.google.com/sre/book.html) and enjoy this "Streaming Platform" lock-in :smile:.

We also think the plain-yaml approach of this project is easier to understand and evolve than [helm](https://github.com/kubernetes/helm) [chart](https://github.com/kubernetes/charts/tree/master/incubator/kafka)s.

## What you get

Keep an eye on `kubectl --namespace kafka get pods -w`.
Expand All @@ -25,6 +27,12 @@ The goal is to provide [Bootstrap servers](http://kafka.apache.org/documentation

Zookeeper at `zookeeper.kafka.svc.cluster.local:2181`.

## Prepare storage classes

For Minikube run `kubectl create -f configure-minikube/`.

There's a similar setup for GKE, in `configure-gke` of course. You might want to tweak it before creating.

## Start Zookeeper

The [Kafka book](https://www.confluent.io/resources/kafka-definitive-guide-preview-edition/) recommends that Kafka has its own Zookeeper cluster with at least 5 instances.
Expand All @@ -50,9 +58,24 @@ kubectl -n kafka logs kafka-0 | grep "Registered broker"
That's it. Just add business value :wink:.
For clients we tend to use [librdkafka](https://github.com/edenhill/librdkafka)-based drivers like [node-rdkafka](https://github.com/Blizzard/node-rdkafka).
To use [Kafka Connect](http://kafka.apache.org/documentation/#connect) and [Kafka Streams](http://kafka.apache.org/documentation/streams/) you may want to take a look at our [sample](https://github.com/solsson/dockerfiles/tree/master/connect-files) [Dockerfile](https://github.com/solsson/dockerfiles/tree/master/streams-logfilter)s.
Don't forget the [addon](https://github.com/Yolean/kubernetes-kafka/labels/addon)s.
And don't forget the [addon](https://github.com/Yolean/kubernetes-kafka/labels/addon)s.

## RBAC

For clusters that enfoce [RBAC](https://kubernetes.io/docs/admin/authorization/rbac/) there's a minimal set of policies in
```
kubectl apply -f rbac-namespace-default/
```

## Caution: `Delete` Reclaim Policy is default

In production you likely want to [manually set Reclaim Policy](https://kubernetes.io/docs/tasks/administer-cluster/change-pv-reclaim-policy/),
our your data will be gone if the generated [volume claim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims)s are deleted.

This can't be done [in manifests](https://github.com/Yolean/kubernetes-kafka/pull/50),
at least not [until Kubernetes 1.8](https://github.com/kubernetes/features/issues/352).

# Tests
## Tests

```
kubectl apply -f test/
Expand Down
7 changes: 7 additions & 0 deletions configure-gke/storageclass-broker-gke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: kafka-broker
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-standard
7 changes: 7 additions & 0 deletions configure-gke/storageclass-zookeeper-gke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: kafka-zookeeper
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
5 changes: 5 additions & 0 deletions configure-minikube/storageclass-broker-minikube.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: kafka-broker
provisioner: k8s.io/minikube-hostpath
5 changes: 5 additions & 0 deletions configure-minikube/storageclass-zookeeper-minikube.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: kafka-zookeeper
provisioner: k8s.io/minikube-hostpath
16 changes: 0 additions & 16 deletions prod-yolean.sh

This file was deleted.

51 changes: 51 additions & 0 deletions qa-yolean.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/bash
# Combines addons into what we 'kubectl apply -f' to production
set -ex

ANNOTATION_PREFIX='yolean.se/kubernetes-kafka-'
BUILD=$(basename $0)
REMOTE=origin
FROM="$REMOTE/"
START=master

[ ! -z "$(git status --untracked-files=no -s)" ] && echo "Working copy must be clean" && exit 1

function annotate {
key=$1
value=$2
file=$3
case $(uname) in
Darwin*)
sed -i '' 's| annotations:| annotations:\
--next-annotation--|' $file
sed -i '' "s|--next-annotation--|${ANNOTATION_PREFIX}$key: '$value'|" $file
;;
*)
sed -i "s| annotations:| annotations:\n ${ANNOTATION_PREFIX}$key: '$value'|" $file
;;
esac
}

git checkout ${FROM}$START
REVS="$START:$(git rev-parse --short ${FROM}$START)"

git checkout -b qa-yolean-$(date +"%Y%m%dT%H%M%S")

for BRANCH in \
addon-storage-classes \
rolling-update \
addon-rest \
addon-metrics \
addon-kube-events-topic
do
git merge --no-ff ${FROM}$BRANCH -m "qa-yolean merge ${FROM}$BRANCH" && \
REVS="$REVS $BRANCH:$(git rev-parse --short ${FROM}$BRANCH)"
done

END_BRANCH_GIT=$(git rev-parse --abbrev-ref HEAD)

for F in ./50kafka.yml ./zookeeper/50pzoo.yml ./zookeeper/51zoo.yml
do
annotate revs "$REVS" $F
annotate build "$END_BRANCH_GIT" $F
done
37 changes: 37 additions & 0 deletions rbac-namespace-default/node-reader.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# To see if init containers need RBAC:
#
# $ kubectl exec kafka-0 -- cat /etc/kafka/server.properties | grep broker.rack
# #init#broker.rack=# zone lookup failed, see -c init-config logs
# $ kubectl logs -c init-config kafka-0
# ++ kubectl get node some-node '-o=go-template={{index .metadata.labels "failure-domain.beta.kubernetes.io/zone"}}'
# Error from server (Forbidden): User "system:serviceaccount:kafka:default" cannot get nodes at the cluster scope.: "Unknown user \"system:serviceaccount:kafka:default\""
#
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: node-reader
labels:
origin: github.com_Yolean_kubernetes-kafka
rules:
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: kafka-node-reader
labels:
origin: github.com_Yolean_kubernetes-kafka
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: node-reader
subjects:
- kind: ServiceAccount
name: default
namespace: kafka
10 changes: 3 additions & 7 deletions zookeeper/50pzoo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,6 @@ spec:
requests:
cpu: 10m
memory: 100Mi
livenessProbe:
exec:
command:
- /bin/sh
- -c
- '[ "imok" = "$(echo ruok | nc -w 1 127.0.0.1 2181)" ]'
readinessProbe:
exec:
command:
Expand All @@ -67,8 +61,10 @@ spec:
volumeClaimTemplates:
- metadata:
name: data
annotations:
volume.beta.kubernetes.io/storage-class: kafka-zookeeper
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
storage: 1Gi
6 changes: 0 additions & 6 deletions zookeeper/51zoo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@ spec:
requests:
cpu: 10m
memory: 100Mi
livenessProbe:
exec:
command:
- /bin/sh
- -c
- '[ "imok" = "$(echo ruok | nc -w 1 127.0.0.1 2181)" ]'
readinessProbe:
exec:
command:
Expand Down