[stable/traefik] Add KV Provider support in order to make Traefik HA (#6813)

This will add:
* the possibility to configure one of the supported KV Provider
* switch to store acme certs in that KV Provider or not
* A Kubernetes Job to create Keys and import certs from a given file into the KV, which can be Mounted threw any given claim, mounted like:
  ```
  acme:
    persistence:
      enabled: true
      existingClaim: acme-certs-pvc
  ```

Fixes: #6772
Copycated a lot from: https://github.com/helm/charts/pull/5563 so many thanks to: @siwyd

Signed-off-by: Alwin Mark <a.mark@crowdfox.com>
This commit is contained in:
alwinmarkcf
2018-08-10 07:43:29 -07:00
committed by k8s-ci-robot
parent 5640ec11dd
commit c0eb1acd38
5 changed files with 223 additions and 4 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
apiVersion: v1
name: traefik
version: 1.38.2
version: 1.39.0
appVersion: 1.6.5
description: A Traefik based Kubernetes ingress controller with Let's Encrypt support
keywords:
+61 -3
View File
@@ -131,6 +131,19 @@ The following table lists the configurable parameters of the Traefik chart and t
| `acme.persistence.accessMode` | `ReadWriteOnce` or `ReadOnly` | `ReadWriteOnce` |
| `acme.persistence.existingClaim` | An Existing PVC name | `nil` |
| `acme.persistence.size` | Minimum size of the volume requested | `1Gi` |
| `kvprovider.storeAcme` | Store acme certificates in KV Provider (needed for [HA](https://docs.traefik.io/configuration/acme/#as-a-key-value-store-entry)) | false |
| `kvprovider.importAcme` | Import acme certificates from acme.json of a mounted pvc (see: acme.persistence.existingClaim) | false |
| `kvprovider.$name.endpoint` | Endpoint of the provider like \<kv-provider-fqdn>:\<port> | none |
| `kvprovider.$name.watch` | Wether traefik should watch for changes | true |
| `kvprovider.$name.prefix` | Prefix where traefik data will be stored | traefik |
| `kvprovider.$name.filename` | Advanced configuration. See: https://docs.traefik.io/ | provider default |
| `kvprovider.$name.username` | Optional username | none |
| `kvprovider.$name.password` | Optional password | none |
| `kvprovider.$name.tls.ca` | Optional TLS certificate authority | none |
| `kvprovider.$name.tls.cert` | Optional TLS certificate | none |
| `kvprovider.$name.tls.key` | Optional TLS keyfile | none |
| `kvprovider.$name.tls.insecureSkipVerify` | Optional Wether to skip verify | none |
| `kvprovider.etcd.useAPIV3 | Use V3 or use V2 API of ETCD | false |
| `dashboard.enabled` | Whether to enable the Traefik dashboard | `false` |
| `dashboard.domain` | Domain for the Traefik dashboard | `traefik.example.com` |
| `dashboard.service.annotations` | Annotations for the Traefik dashboard Service definition, specified as a map | None |
@@ -196,11 +209,56 @@ $ helm install --name my-release --namespace kube-system --values values.yaml st
### Clustering / High Availability
Currently it is possible to specify the number of `replicas` but the implementation is naive.
To enable cluster support, you need one of:
* etcd
* consul
* boltdb
* zookeeper
**Full Traefik clustering with leader election is not yet supported.**
as kvprovider, especially when you are using Let's Encrypt.
If you have already certificates stored as acme.json in an existing persistent volume claim, you can import it.
Given you have:
* a running [etcd operator](https://github.com/helm/charts/tree/master/stable/etcd-operator):
* you have created a master chart requiring this traefik chart
* an existing pvc with an `acme.json` called `acme-certs-pvc`
* you have an etcd template like:
```
apiVersion: "etcd.database.coreos.com/v1beta2"
kind: "EtcdCluster"
metadata:
name: {{ .Values.etcdCluster.name }}
labels:
app: {{ .Values.etcdCluster.name }}
annotations:
etcd.database.coreos.com/scope: clusterwide
spec:
size: 3
version: "3.1.8"
```
* and these values in your values.yaml
```
etcdCluster:
name: traefik-etcd-cluster
traefik:
replicas: 3
acme:
persistence:
enabled: true
existingClaim: acme-certs-pvc
kvprovider:
storeAcme: true
importAcme: true
etcd:
endpoint: "traefik-etcd-cluster-client:2379"
useAPIV3: false
watch: true
prefix: traefik
```
Then you are good to migrate your old certs into the kvprovider and run traefik in HA/Cluster-Mode.
It is heavily advised to not set a value for `replicas` if you also have Let's Encrypt configured. While setting `replicas` will work for many cases, since no leader is elected it has the consequence that each node will end up requesting Let's Encrypt certificates if this is also configured. This will quickly cut into the very modest rate limit that Let's Encrypt enforces. Also, if using challenges, the challenges may fail, as the challenge request may hit a pod without the challenge certificate.
[Basic auth](https://docs.traefik.io/toml/#api-backend) can be specified via `dashboard.auth.basic` as a map of usernames to passwords as below.
See the linked Traefik documentation for accepted passwords encodings.
+64
View File
@@ -107,10 +107,74 @@ data:
{{ printf "\"%s\" = \"%s\"" $header $action }}
{{- end}}
{{- end}}
{{- if .Values.kvprovider.etcd }}
[etcd]
endpoint = "{{ .Values.kvprovider.etcd.endpoint }}"
watch = {{ .Values.kvprovider.etcd.watch }}
prefix = "{{ .Values.kvprovider.etcd.prefix }}"
useAPIV3 = {{ .Values.kvprovider.etcd.useAPIV3 }}
{{- if .Values.kvprovider.etcd.username }}username = {{ .Values.kvprovider.etcd.username }}{{- end }}
{{- if .Values.kvprovider.etcd.password }}password = {{ .Values.kvprovider.etcd.password }}{{- end }}
{{- if .Values.kvprovider.etcd.tls }}
[etcd.tls]
{{- end }}
{{ range $key, $value := .Values.kvprovider.etcd.tls }}
{{ $key }} = {{ $value }}
{{ end }}
{{- end }}
{{- if .Values.kvprovider.consul }}
[consul]
endpoint = "{{ .Values.kvprovider.consul.endpoint }}"
watch = {{ .Values.kvprovider.consul.watch }}
prefix = {{ .Values.kvprovider.consul.prefix }}
{{- if .Values.kvprovider.consul.username }}username = {{ .Values.kvprovider.consul.username }}{{- end }}
{{- if .Values.kvprovider.consul.password }}password = {{ .Values.kvprovider.consul.password }}{{- end }}
{{- if .Values.kvprovider.consul.tls }}
[consul.tls]
{{- end }}
{{ range $key, $value := .Values.kvprovider.consul.tls }}
{{ $key }} = {{ $value }}
{{ end }}
{{- end }}
{{- if .Values.kvprovider.boltdb }}
[boltdb]
endpoint = "{{ .Values.kvprovider.boltdb.endpoint }}"
watch = {{ .Values.kvprovider.boltdb.watch }}
prefix = {{ .Values.kvprovider.boltdb.prefix }}
{{- if .Values.kvprovider.boltdb.username }}username = {{ .Values.kvprovider.boltdb.username }}{{- end }}
{{- if .Values.kvprovider.boltdb.password }}password = {{ .Values.kvprovider.boltdb.password }}{{- end }}
{{- if .Values.kvprovider.boltdb.tls }}
[boltdb.tls]
{{- end }}
{{ range $key, $value := .Values.kvprovider.boltdb.tls }}
{{ $key }} = {{ $value }}
{{ end }}
{{- end }}
{{- if .Values.kvprovider.zookeeper }}
[zookeeper]
endpoint = "{{ .Values.kvprovider.zookeeper.endpoint }}"
watch = {{ .Values.kvprovider.zookeeper.watch }}
prefix = {{ .Values.kvprovider.zookeeper.prefix }}
{{- if .Values.kvprovider.zookeeper.username }}username = {{ .Values.kvprovider.zookeeper.username }}{{- end }}
{{- if .Values.kvprovider.zookeeper.password }}password = {{ .Values.kvprovider.zookeeper.password }}{{- end }}
{{- if .Values.kvprovider.zookeeper.tls }}
[zookeeper.tls]
{{- end }}
{{ range $key, $value := .Values.kvprovider.zookeeper.tls }}
{{ $key }} = {{ $value }}
{{ end }}
{{- end }}
{{- if .Values.acme.enabled }}
[acme]
email = "{{ .Values.acme.email }}"
{{- if .Values.kvprovider.storeAcme }}
storage = "traefik/acme/account"
{{- if .Values.kvprovider.importAcme }}
storageFile = "/acme/acme.json"
{{- end }}
{{- else }}
storage = "/acme/acme.json"
{{- end }}
entryPoint = "https"
onHostRule = true
{{- if .Values.acme.staging }}
@@ -0,0 +1,43 @@
{{- if .Values.kvprovider.storeAcme }}
apiVersion: batch/v1
kind: Job
metadata:
name: "storeconfig-job"
annotations:
"helm.sh/hook": post-install
"helm.sh/hook-delete-policy": hook-succeeded
labels:
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
app: {{ template "traefik.name" . }}
spec:
template:
metadata:
name: "storeconfig-job"
labels:
app: {{ template "traefik.name" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
spec:
restartPolicy: Never
containers:
- name: storeconfig-job
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
args:
- storeconfig
- --configfile=/config/traefik.toml
volumeMounts:
- mountPath: /config
name: config
- mountPath: /acme
name: acme
volumes:
- name: config
configMap:
name: {{ template "traefik.fullname" . }}
- name: acme
{{- if .Values.acme.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.acme.persistence.existingClaim | default (printf "%s-acme" (include "traefik.fullname" .)) }}
{{- else }}
emptyDir: {}
{{- end }}
{{- end }}
+54
View File
@@ -55,6 +55,60 @@ ssl:
# tlsMinVersion: VersionTLS12
defaultCert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVtekNDQTRPZ0F3SUJBZ0lKQUpBR1FsTW1DMGt5TUEwR0NTcUdTSWIzRFFFQkJRVUFNSUdQTVFzd0NRWUQKVlFRR0V3SlZVekVSTUE4R0ExVUVDQk1JUTI5c2IzSmhaRzh4RURBT0JnTlZCQWNUQjBKdmRXeGtaWEl4RkRBUwpCZ05WQkFvVEMwVjRZVzF3YkdWRGIzSndNUXN3Q1FZRFZRUUxFd0pKVkRFV01CUUdBMVVFQXhRTktpNWxlR0Z0CmNHeGxMbU52YlRFZ01CNEdDU3FHU0liM0RRRUpBUllSWVdSdGFXNUFaWGhoYlhCc1pTNWpiMjB3SGhjTk1UWXgKTURJME1qRXdPVFV5V2hjTk1UY3hNREkwTWpFd09UVXlXakNCanpFTE1Ba0dBMVVFQmhNQ1ZWTXhFVEFQQmdOVgpCQWdUQ0VOdmJHOXlZV1J2TVJBd0RnWURWUVFIRXdkQ2IzVnNaR1Z5TVJRd0VnWURWUVFLRXd0RmVHRnRjR3hsClEyOXljREVMTUFrR0ExVUVDeE1DU1ZReEZqQVVCZ05WQkFNVURTb3VaWGhoYlhCc1pTNWpiMjB4SURBZUJna3EKaGtpRzl3MEJDUUVXRVdGa2JXbHVRR1Y0WVcxd2JHVXVZMjl0TUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQwpBUThBTUlJQkNnS0NBUUVBdHVKOW13dzlCYXA2SDROdUhYTFB6d1NVZFppNGJyYTFkN1ZiRUJaWWZDSStZNjRDCjJ1dThwdTNhVTVzYXVNYkQ5N2pRYW95VzZHOThPUHJlV284b3lmbmRJY3RFcmxueGpxelUyVVRWN3FEVHk0bkEKNU9aZW9SZUxmZXFSeGxsSjE0VmlhNVFkZ3l3R0xoRTlqZy9jN2U0WUp6bmg5S1dZMnFjVnhEdUdEM2llaHNEbgphTnpWNFdGOWNJZm1zOHp3UHZPTk5MZnNBbXc3dUhUKzNiSzEzSUloeDI3ZmV2cXVWcENzNDFQNnBzdStWTG4yCjVIRHk0MXRoQkN3T0wrTithbGJ0ZktTcXM3TEFzM25RTjFsdHpITHZ5MGE1RGhkakpUd2tQclQrVXhwb0tCOUgKNFpZazErRUR0N09QbGh5bzM3NDFRaE4vSkNZK2RKbkFMQnNValFJREFRQUJvNEgzTUlIME1CMEdBMVVkRGdRVwpCQlJwZVc1dFhMdHh3TXJvQXM5d2RNbTUzVVVJTERDQnhBWURWUjBqQklHOE1JRzVnQlJwZVc1dFhMdHh3TXJvCkFzOXdkTW01M1VVSUxLR0JsYVNCa2pDQmp6RUxNQWtHQTFVRUJoTUNWVk14RVRBUEJnTlZCQWdUQ0VOdmJHOXkKWVdSdk1SQXdEZ1lEVlFRSEV3ZENiM1ZzWkdWeU1SUXdFZ1lEVlFRS0V3dEZlR0Z0Y0d4bFEyOXljREVMTUFrRwpBMVVFQ3hNQ1NWUXhGakFVQmdOVkJBTVVEU291WlhoaGJYQnNaUzVqYjIweElEQWVCZ2txaGtpRzl3MEJDUUVXCkVXRmtiV2x1UUdWNFlXMXdiR1V1WTI5dGdna0FrQVpDVXlZTFNUSXdEQVlEVlIwVEJBVXdBd0VCL3pBTkJna3EKaGtpRzl3MEJBUVVGQUFPQ0FRRUFjR1hNZms4TlpzQit0OUtCemwxRmw2eUlqRWtqSE8wUFZVbEVjU0QyQjRiNwpQeG5NT2pkbWdQcmF1SGI5dW5YRWFMN3p5QXFhRDZ0YlhXVTZSeENBbWdMYWpWSk5aSE93NDVOMGhyRGtXZ0I4CkV2WnRRNTZhbW13QzFxSWhBaUE2MzkwRDNDc2V4N2dMNm5KbzdrYnIxWVdVRzN6SXZveGR6OFlEclpOZVdLTEQKcFJ2V2VuMGxNYnBqSVJQNFhac25DNDVDOWdWWGRoM0xSZTErd3lRcTZoOVFQaWxveG1ENk5wRTlpbVRPbjJBNQovYkozVktJekFNdWRlVTZrcHlZbEpCemRHMXVhSFRqUU9Xb3NHaXdlQ0tWVVhGNlV0aXNWZGRyeFF0aDZFTnlXCnZJRnFhWng4NCtEbFNDYzkzeWZrL0dsQnQrU0tHNDZ6RUhNQjlocVBiQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
defaultKey: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdHVKOW13dzlCYXA2SDROdUhYTFB6d1NVZFppNGJyYTFkN1ZiRUJaWWZDSStZNjRDCjJ1dThwdTNhVTVzYXVNYkQ5N2pRYW95VzZHOThPUHJlV284b3lmbmRJY3RFcmxueGpxelUyVVRWN3FEVHk0bkEKNU9aZW9SZUxmZXFSeGxsSjE0VmlhNVFkZ3l3R0xoRTlqZy9jN2U0WUp6bmg5S1dZMnFjVnhEdUdEM2llaHNEbgphTnpWNFdGOWNJZm1zOHp3UHZPTk5MZnNBbXc3dUhUKzNiSzEzSUloeDI3ZmV2cXVWcENzNDFQNnBzdStWTG4yCjVIRHk0MXRoQkN3T0wrTithbGJ0ZktTcXM3TEFzM25RTjFsdHpITHZ5MGE1RGhkakpUd2tQclQrVXhwb0tCOUgKNFpZazErRUR0N09QbGh5bzM3NDFRaE4vSkNZK2RKbkFMQnNValFJREFRQUJBb0lCQUhrTHhka0dxNmtCWWQxVAp6MkU4YWFENnhneGpyY2JSdGFCcTc3L2hHbVhuQUdaWGVWcE81MG1SYW8wbHZ2VUgwaE0zUnZNTzVKOHBrdzNmCnRhWTQxT1dDTk1PMlYxb1MvQmZUK3Zsblh6V1hTemVQa0pXd2lIZVZMdVdEaVVMQVBHaWl4emF2RFMyUnlQRmEKeGVRdVNhdE5pTDBGeWJGMG5Zd3pST3ZoL2VSa2NKVnJRZlZudU1melFkOGgyMzZlb1UxU3B6UnhSNklubCs5UApNc1R2Wm5OQmY5d0FWcFo5c1NMMnB1V1g3SGNSMlVnem5oMDNZWUZJdGtDZndtbitEbEdva09YWHBVM282aWY5ClRIenBleHdubVJWSmFnRG85bTlQd2t4QXowOW80cXExdHJoU1g1U2p1K0xyNFJvOHg5bytXdUF1VnVwb0lHd0wKMWVseERFRUNnWUVBNzVaWGp1enNJR09PMkY5TStyYVFQcXMrRHZ2REpzQ3gyZnRudk1WWVJKcVliaGt6YnpsVQowSHBCVnk3NmE3WmF6Umxhd3RGZ3ljMlpyQThpM0F3K3J6d1pQclNJeWNieC9nUVduRzZlbFF1Y0FFVWdXODRNCkdSbXhKUGlmOGRQNUxsZXdRalFjUFJwZVoxMzlYODJreGRSSEdma1pscHlXQnFLajBTWExRSEVDZ1lFQXcybkEKbUVXdWQzZFJvam5zbnFOYjBlYXdFUFQrbzBjZ2RyaENQOTZQK1pEekNhcURUblZKV21PeWVxRlk1eVdSSEZOLwpzbEhXU2lTRUFjRXRYZys5aGlMc0RXdHVPdzhUZzYyN2VrOEh1UUtMb2tWWEFUWG1NZG9xOWRyQW9INU5hV2lECmRSY3dEU2EvamhIN3RZV1hKZDA4VkpUNlJJdU8vMVZpbDBtbEk5MENnWUVBb2lsNkhnMFNUV0hWWDNJeG9raEwKSFgrK1ExbjRYcFJ5VEg0eldydWY0TjlhYUxxNTY0QThmZGNodnFiWGJHeEN6U3RxR1E2cW1peUU1TVpoNjlxRgoyd21zZEpxeE14RnEzV2xhL0lxSzM0cTZEaHk3cUNld1hKVGRKNDc0Z3kvY0twZkRmeXZTS1RGZDBFejNvQTZLCmhqUUY0L2lNYnpxUStQREFQR0YrVHFFQ2dZQmQ1YnZncjJMMURzV1FJU3M4MHh3MDBSZDdIbTRaQVAxdGJuNk8KK0IvUWVNRC92UXBaTWV4c1hZbU9lV2Noc3FCMnJ2eW1MOEs3WDY1NnRWdGFYay9nVzNsM3ZVNTdYSFF4Q3RNUwpJMVYvcGVSNHRiN24yd0ZncFFlTm1XNkQ4QXk4Z0xiaUZhRkdRSDg5QWhFa0dTd1d5cWJKc2NoTUZZOUJ5OEtUCkZaVWZsUUtCZ0V3VzJkVUpOZEJMeXNycDhOTE1VbGt1ZnJxbllpUTNTQUhoNFZzWkg1TXU0MW55Yi95NUUyMW4KMk55d3ltWGRlb3VJcFZjcUlVTXl0L3FKRmhIcFJNeVEyWktPR0QyWG5YaENNVlRlL0FQNDJod294Nm02QkZpQgpvemZFa2wwak5uZmREcjZrL1p2MlQ1TnFzaWxaRXJBQlZGOTBKazdtUFBIa0Q2R1ZMUUJ4Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
kvprovider:
## If you want to run Traefik in HA mode, you will need to setup a KV Provider. Therefore you can choose one of
## * etcd
## * consul
## * boltdb
## * zookeeper
##
## ref: https://docs.traefik.io/user-guide/cluster/
## storeAcme has to be enabled to support HA Support using acme, but at least one kvprovider is needed
storeAcme: false
importAcme: false
# etcd:
# endpoint: etcd-service:2379
# useAPIV3: false
# watch: true
# prefix: traefik
## Override default configuration template.
## For advanced users :)
##
## Optional
# filename: consul.tmpl
# username: foo
# password: bar
# tls:
# ca: "/etc/ssl/ca.crt"
# cert: "/etc/ssl/consul.crt"
# key: "/etc/ssl/consul.key"
# insecureSkipVerify: true
#
# consul:
# endpoint: consul-service:8500
# watch: true
# prefix: traefik
## Override default configuration template.
## For advanced users :)
##
## Optional
# filename: consul.tmpl
# username: foo
# password: bar
# tls:
# ca: "/etc/ssl/ca.crt"
# cert: "/etc/ssl/consul.crt"
# key: "/etc/ssl/consul.key"
# insecureSkipVerify: true
## only relevant for etcd
acme:
enabled: false
email: admin@example.com