Add stable/unbound (#3564)

* Initial commit.

* Change the probe record to return localhost.

* Add support for local data records and restructure the file a bit.

* Moved the health check to healthz in order to keep default restricted acl for the unbound container.

* Added the serverPort reference.

* Defaulted the healthz image to googles public docker registry.

* Reference the image value for healthz

* Added healthz repo to the chart sources.

* Always bind to 0.0.0.0 so the service will be healthy.

* Update the readme.

* Add a section on setting unbound as an upstream for kube-dns.

* Use the auto-built docker image.

* Updated the readme.

* Updated with somewhat meaningful note.

* Fixed a typo.

* Added some more info to the readme.

* The health check will now use the server port from values.

* Moved to stable.

* nslookup on busybox handles the port differently.

* shortened the initial delay for probes to 5s.

* Added some information on the other configurable properties.

* Use github username in the maintainer field.

* Revise templates and use in selectors and metadata to better follow guidelines.

* Restructure the image references.

* Add a cpu limit

* Fixed the image references.

* Lower the cpu limit to half a core.

* Update the readme with changes to values.yaml.

* Bring template funcs in line with helm 2.8

* Bring standard metadata in line with helm 2.8

* Fixed a bug in the fullname function.

* Restructure the values to separate by container where appropriate.

* Bring up to date with new values structure.

* Add some additional documentation.

* Unquote something I missed.

* Bring the readme up to date.

* Add a disruption budget

* Add a table of all supported values

* Fix the indent level for resources

* Fix the quoting of statsCumulative

* Correct the indent level of the ports list in the service template.

* Update api version.
This commit is contained in:
Mark Betz
2018-04-04 12:42:09 -07:00
committed by k8s-ci-robot
parent 4fc3f61343
commit 0141560ad1
10 changed files with 404 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
# 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
+13
View File
@@ -0,0 +1,13 @@
apiVersion: v1
description: Unbound is a fast caching DNS resolver
home: https://www.unbound.net/
name: unbound
version: 0.1.0
appVersion: 1.6.7
sources:
- http://unbound.nlnetlabs.nl/svn/
- https://github.com/Markbnj/unbound-docker
- https://github.com/kubernetes/contrib/tree/master/exec-healthz
maintainers:
- name: Markbnj
email: betz.mark@gmail.com
+112
View File
@@ -0,0 +1,112 @@
# Unbound
[Unbound](http://www.unbound.net) is a caching DNS resolver written in C. It is suitable for use as an upstream DNS resolver for kube-dns. The image is based on alpine and includes unbound, bind-tools and bash and is approximately 20MB in size, making for fast startup. Google's [healthz container](https://hub.docker.com/r/googlecontainer/exechealthz/) is used as a sidecar to probe the unbound container on localhost, which allows unbound to run in a default configuration with restricted network access, and still play nice with kubelet.
## Configuration
The chart values file contains the default settings for the unbound server. In the default configuration unbound will allow queries from localhost only, and will not have any forward zones. This means that queries sent to the clusterip of the service will return access denied, and queries from localhost for anything other than the health check record `health.check.unbound` will return NXDOMAIN.
You can configure unbound for your specific use case by passing a values file that contains the following properties. Most or all of these can also be set from the helm command line using `--set`.
### Access control
Controls which IP address ranges unbound will allow queries from. If you want to use unbound as an upstream for kube-dns, or allow other pods to query the resolver directly, you'll at least need to allow the `clusterIpV4Cidr` range.
```yaml
allowedIpRanges:
- "10.10.10.10/20"
- "10.10.11.11/20"
```
### Forward zones
You can set as many forward zones as needed by specifying the zone name and forward hosts. Forward hosts can be set by hostname or ip.
```yaml
forwardZones:
- name: "fake.net"
forwardHosts:
- "fake1.host.net"
- "fake2.host.net"
- name: "stillfake.net"
forwardIps:
- "10.10.10.10"
- "10.11.10.10"
```
### Local records
Unbound can store DNS records in a "local zone." This facility can be used to assign context-specific names to a given IP address, and could also be used for private DNS if you don't want or have an external resolver.
```yaml
localRecords:
- name: "fake3.host.net"
ip: "10.12.10.10"
- name: "fake4.host.net"
ip: "10.13.10.10"
```
### Other configurable properties
The following properties in values.yaml configure additional aspects of the unbound server. For more information see the [unbound documentation](http://unbound.net/documentation/unbound.conf.html).
```
unbound.verbosity: 1
unbound.numThreads: 1
unbound.statsInterval: 0
unbound.statsCumulative: no
unbound.serverPort: 53
```
### All configurable properties
| Property | Default value |
| ------------------------ | --------------------------- |
| replicaCount | 1 |
| unbound.image.repository | markbnj/unbound-docker |
| unbound.image.tag | 0.1.0 |
| unbound.image.pullPolicy | IfNotPresent |
| unbound.verbosity | 1 |
| unbound.numThreads | 1 |
| unbound.statsInterval | 0 |
| unbound.statsCumulative | no |
| unbound.serverPort | 53 |
| healthz.image.repository | googlecontainer/exechealthz |
| healthz.image.tag | 1.2 |
| healthz.image.pullPolicy | IfNotPresent |
| resources | {} |
| nodeSelector | {} |
| tolerations | [] |
| affinity | {} |
| allowedIpRanges | [] |
| forwardZones | [] |
| localRecords | [] |
### Configuration changes
The unbound deployment template includes the sha256 hash of the configmap as an annotation. This will cause the deployment to update if the configuration is changed. For more information on this and other useful stuff see [chart tips and tricks](https://github.com/kubernetes/helm/blob/master/docs/charts_tips_and_tricks.md).
### Health checks
Liveness and readiness probes are implemented by a side-car [healthz container](https://github.com/kubernetes/contrib/tree/master/exec-healthz). When a http GET is made to port 8080 healthz runs an nslookup against the unbound server on localhost querying for the name `health.check.unbound` which is stored as a local record in the configuration.
## Configuring as an upstream resolver for kube-dns
To configure unbound to act as an upstream resolver for kube-dns edit the `kube-dns` configmap in the kube-system namespace to add the `stubDomains` value as shown below. The forwarding address for the domain should be set to the cluster IP of the unbound service.
```yaml
apiVersion: v1
data:
stubDomains: |
{"fake.net": ["10.10.10.10"]}
kind: ConfigMap
metadata:
creationTimestamp: 2018-01-04T18:09:38Z
labels:
addonmanager.kubernetes.io/mode: EnsureExists
name: kube-dns
namespace: kube-system
resourceVersion: "1825"
selfLink: /api/v1/namespaces/kube-system/configmaps/kube-dns
uid: 6d759f7d-f17a-11e7-898d-42010a800159
```
+1
View File
@@ -0,0 +1 @@
Unbound release has been installed or upgraded. For information on configuring unbound as an upstream resolver for kube-dns see the readme.
+32
View File
@@ -0,0 +1,32 @@
{{/* vim: set filetype=mustache: */}}
{{/*
{{/*
Expand the name of the chart.
*/}}
{{- define "unbound.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a fully qualified app name
*/}}
{{- define "unbound.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 "unbound.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
+53
View File
@@ -0,0 +1,53 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "unbound.fullname" . }}
labels:
app: {{ template "unbound.name" . }}
chart: {{ template "unbound.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
data:
unbound.conf: |-
server:
chroot: ""
num-threads: {{ .Values.unbound.numThreads }}
directory: "/etc/unbound"
port: {{ .Values.unbound.serverPort }}
so-reuseport: yes
do-daemonize: no
logfile: ""
use-syslog: no
auto-trust-anchor-file: "/var/lib/unbound/root.key"
verbosity: {{ .Values.unbound.verbosity }}
statistics-interval: {{ .Values.unbound.statsInterval }}
statistics-cumulative: {{ .Values.unbound.statsCumulative }}
interface: 127.0.0.1
interface: 0.0.0.0
access-control: 127.0.0.1/32 allow
{{- range .Values.allowedIpRanges }}
access-control: {{ . }} allow
{{- end }}
{{- range .Values.localRecords }}
local-data: "{{ .name }} A {{ .ip }}"
local-data-ptr: "{{ .ip }} {{ .name }}"
{{- end }}
local-data: "health.check.unbound A 127.0.0.1"
local-data-ptr: "127.0.0.1 health.check.unbound"
{{- range .Values.forwardZones }}
forward-zone:
name: {{ .name }}
{{- range .forwardHosts }}
forward-host: {{ . }}
{{- end }}
{{- range .forwardIps }}
forward-addr: {{ . }}
{{- end }}
{{- end }}
+83
View File
@@ -0,0 +1,83 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ template "unbound.fullname" . }}
labels:
app: {{ template "unbound.name" . }}
chart: {{ template "unbound.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "unbound.name" . }}
release: {{ .Release.Name }}
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
app: {{ template "unbound.name" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
spec:
containers:
- name: "unbound"
image: {{ .Values.unbound.image.repository }}:{{ .Values.unbound.image.tag }}
imagePullPolicy: {{ .Values.unbound.image.pullPolicy | quote }}
resources:
{{ toYaml .Values.resources | indent 10 }}
ports:
- name: "dns-udp"
containerPort: {{ .Values.unbound.serverPort }}
protocol: "UDP"
volumeMounts:
- name: "unbound-conf"
mountPath: "/etc/unbound/"
readOnly: true
livenessProbe:
httpGet:
path: "/healthz"
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 2
readinessProbe:
exec:
httpGet:
path: "/healthz"
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 2
- name: "healthz"
image: {{ .Values.healthz.image.repository }}:{{ .Values.healthz.image.tag }}
imagePullPolicy: {{ .Values.healthz.image.pullPolicy | quote }}
args:
- "-cmd=nslookup health.check.unbound 127.0.0.1:{{ .Values.unbound.serverPort }} > /dev/null"
ports:
- name: healthz
containerPort: 8080
protocol: TCP
volumes:
- name: "unbound-conf"
configMap:
name: {{ template "unbound.fullname" . }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
@@ -0,0 +1,15 @@
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: {{ template "unbound.fullname" . }}
labels:
app: {{ template "unbound.name" . }}
chart: {{ template "unbound.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
maxUnavailable: 1
selector:
matchLabels:
app: {{ template "unbound.name" . }}
release: {{ .Release.Name }}
+18
View File
@@ -0,0 +1,18 @@
kind: Service
apiVersion: v1
metadata:
name: {{ template "unbound.fullname" . }}
labels:
app: {{ template "unbound.name" . }}
chart: {{ template "unbound.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
selector:
app: {{ template "unbound.name" . }}
release: {{ .Release.Name }}
ports:
- name: dns-udp
protocol: UDP
port: {{ .Values.unbound.serverPort }}
targetPort: dns-udp
+56
View File
@@ -0,0 +1,56 @@
replicaCount: 1
# values that pertain to the unbound container, for more information
# on unbound configuration see http://unbound.net/documentation/unbound.conf.html
unbound:
image:
repository: markbnj/unbound-docker
tag: "0.1.0"
pullPolicy: IfNotPresent
verbosity: 1
numThreads: 1
statsInterval: 0
statsCumulative: "no"
serverPort: 53
# values that pertain to the exechealthz container, for more information see
# https://github.com/kubernetes/contrib/tree/master/exec-healthz
healthz:
image:
repository: googlecontainer/exechealthz
tag: "1.2"
pullPolicy: IfNotPresent
resources: {}
nodeSelector: {}
tolerations: []
affinity: {}
# Controls which IP address ranges unbound will allow queries from.
# If you want to use unbound as an upstream for kube-dns, or allow other pods
# to query the resolver directly, you'll at least need to allow the
# clusterIpV4Cidr range.
# allowedIpRanges:
# - "10.10.10.10/20"
# You can set as many forward zones as needed by specifying the zone name
# and forward hosts. Forward hosts can be set by hostname or ip.
# forwardZones:
# - name: "fake.net"
# forwardHosts:
# - "fake1.host.net"
# forwardIps:
# - "10.10.10.10"
# Unbound can store DNS records in a "local zone." This facility can be used to
# assign context-specific names to a given IP address, and could also be used for
# private DNS if you don't want or have an external resolver.
# localRecords:
# - name: "fake3.host.net"
# ip: "10.12.10.10"