├── traefik ├── .helmignore ├── templates │ ├── extra-objects.yaml │ ├── gatewayclass.yaml │ ├── tlsstore.yaml │ ├── rbac │ │ ├── serviceaccount.yaml │ │ ├── clusterrolebinding.yaml │ │ ├── rolebinding.yaml │ │ ├── role.yaml │ │ ├── podsecuritypolicy.yaml │ │ └── clusterrole.yaml │ ├── NOTES.txt │ ├── poddisruptionbudget.yaml │ ├── ingressclass.yaml │ ├── pvc.yaml │ ├── _service-metrics.tpl │ ├── service-metrics.yaml │ ├── hpa.yaml │ ├── dashboard-ingressroute.yaml │ ├── prometheusrules.yaml │ ├── gateway.yaml │ ├── tlsoption.yaml │ ├── _service-internal.tpl │ ├── daemonset.yaml │ ├── deployment.yaml │ ├── service-internal.yaml │ ├── _service.tpl │ ├── service.yaml │ ├── servicemonitor.yaml │ └── _helpers.tpl ├── tests │ ├── values │ │ ├── hpa.yaml │ │ ├── extra.yaml │ │ ├── antiaffinity.yaml │ │ ├── prometheusrules.yaml │ │ └── servicemonitor.yaml │ ├── gatewayclass-config_test.yaml │ ├── extra-config_test.yaml │ ├── pvc-config_test.yaml │ ├── tlsstore_test.yaml │ ├── hpa-config_test.yaml │ ├── default-install_test.yaml │ ├── service-metrics-config_test.yaml │ ├── prometheusrules-config_test.yaml │ ├── common-metadata_test.yaml │ ├── poddisruptionbudget-config_test.yaml │ ├── ingressclass-config_test.yaml │ ├── podsecuritypolicy-config_test.yaml │ ├── notes_test.yaml │ ├── dashboard-ingressroute_test.yaml │ ├── servicemonitor-config_test.yaml │ ├── gateway-config_test.yaml │ ├── tlsoption_test.yaml │ ├── daemonset-config_test.yaml │ ├── deployment-config_test.yaml │ ├── service-internal-config_test.yaml │ ├── service-config-multiple_test.yaml │ ├── container-config_test.yaml │ ├── ports-config_test.yaml │ ├── rbac-config_test.yaml │ └── service-config_test.yaml ├── crds │ ├── kustomization.yaml │ ├── traefik.io_middlewaretcps.yaml │ ├── traefik.containo.us_middlewaretcps.yaml │ ├── traefik.containo.us_ingressrouteudps.yaml │ ├── traefik.io_tlsstores.yaml │ ├── traefik.containo.us_tlsstores.yaml │ ├── traefik.io_ingressrouteudps.yaml │ ├── traefik.io_tlsoptions.yaml │ ├── traefik.containo.us_tlsoptions.yaml │ ├── traefik.io_serverstransports.yaml │ ├── traefik.containo.us_serverstransports.yaml │ └── traefik.containo.us_ingressroutetcps.yaml ├── Chart.yaml └── Guidelines.md ├── hack ├── test.sh ├── lint.sh └── changelog.sh ├── .github ├── chart-testing.yaml ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature-request.yml │ └── bug_report.yml ├── PULL_REQUEST_TEMPLATE.md ├── workflows │ ├── test.yml │ └── release.yml └── renovate.json ├── .gitignore ├── Makefile ├── CONTRIBUTING.md ├── TESTING.md └── README.md /traefik/.helmignore: -------------------------------------------------------------------------------- 1 | tests/ 2 | crds/kustomization.yaml 3 | -------------------------------------------------------------------------------- /hack/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | /usr/bin/helm unittest --color ./traefik; 4 | -------------------------------------------------------------------------------- /traefik/templates/extra-objects.yaml: -------------------------------------------------------------------------------- 1 | {{- range .Values.extraObjects }} 2 | --- 3 | {{ include "traefik.render" (dict "value" . "context" $) }} 4 | {{- end }} 5 | -------------------------------------------------------------------------------- /.github/chart-testing.yaml: -------------------------------------------------------------------------------- 1 | remote: origin 2 | target-branch: master 3 | debug: true 4 | check-version-increment: true 5 | upgrade: true 6 | validate-chart-schema: true 7 | validate-yaml: true 8 | -------------------------------------------------------------------------------- /traefik/tests/values/hpa.yaml: -------------------------------------------------------------------------------- 1 | autoscaling: 2 | enabled: true 3 | maxReplicas: 2 4 | metrics: 5 | - type: Resource 6 | resource: 7 | name: cpu 8 | target: 9 | type: Utilization 10 | averageUtilization: 60 11 | -------------------------------------------------------------------------------- /hack/lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CT_ARGS="" 4 | GIT_SAFE_DIR="false" 5 | 6 | if [ "$GIT_SAFE_DIR" != "true" ]; then 7 | git config --global --add safe.directory /charts 8 | fi 9 | 10 | CT_ARGS="--charts ${PWD}/charts" 11 | 12 | ct lint --config=./.github/chart-testing.yaml 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Traefik Community Support 4 | url: https://community.traefik.io/ 5 | about: If you have a question, or are looking for advice, please post on our Discuss forum! The community loves to chime in to help. Happy Coding! 6 | -------------------------------------------------------------------------------- /traefik/tests/values/extra.yaml: -------------------------------------------------------------------------------- 1 | extraObjects: 2 | - apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: "extra" 6 | data: 7 | something: "extra" 8 | - | 9 | apiVersion: v1 10 | kind: ConfigMap 11 | metadata: 12 | name: "templated" 13 | data: 14 | something: {{ printf "templated" }} 15 | -------------------------------------------------------------------------------- /traefik/templates/gatewayclass.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.experimental.kubernetesGateway.enabled }} 2 | --- 3 | apiVersion: gateway.networking.k8s.io/v1alpha2 4 | kind: GatewayClass 5 | metadata: 6 | name: traefik 7 | labels: 8 | {{- include "traefik.labels" . | nindent 4 }} 9 | spec: 10 | controllerName: traefik.io/gateway-controller 11 | {{- end }} 12 | -------------------------------------------------------------------------------- /traefik/templates/tlsstore.yaml: -------------------------------------------------------------------------------- 1 | {{- range $name, $config := .Values.tlsStore }} 2 | apiVersion: traefik.io/v1alpha1 3 | kind: TLSStore 4 | metadata: 5 | name: {{ $name }} 6 | namespace: {{ template "traefik.namespace" $ }} 7 | labels: 8 | {{- include "traefik.labels" $ | nindent 4 }} 9 | spec: 10 | {{- toYaml $config | nindent 2 }} 11 | --- 12 | {{- end -}} 13 | -------------------------------------------------------------------------------- /traefik/tests/values/antiaffinity.yaml: -------------------------------------------------------------------------------- 1 | affinity: 2 | podAntiAffinity: 3 | requiredDuringSchedulingIgnoredDuringExecution: 4 | - labelSelector: 5 | matchLabels: 6 | app.kubernetes.io/name: '{{ template "traefik.name" . }}' 7 | app.kubernetes.io/instance: '{{ .Release.Name }}-{{ .Release.Namespace }}' 8 | topologyKey: kubernetes.io/hostname 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | gh-pages.zip 8 | 9 | # Test binary, build with `go test -c` 10 | *.test 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | 15 | # Outputs directories 16 | dist/ 17 | repo/ 18 | 19 | # Unit test for helm 20 | __snapshot__ 21 | 22 | .idea 23 | -------------------------------------------------------------------------------- /traefik/tests/gatewayclass-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: GatewayClass configuration 2 | templates: 3 | - gatewayclass.yaml 4 | tests: 5 | - it: should have one GatewayClass with contollerName value traefik.io/gateway-controller 6 | set: 7 | experimental: 8 | kubernetesGateway: 9 | enabled: true 10 | asserts: 11 | - equal: 12 | path: spec.controllerName 13 | value: traefik.io/gateway-controller 14 | -------------------------------------------------------------------------------- /traefik/templates/rbac/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if not .Values.serviceAccount.name -}} 2 | kind: ServiceAccount 3 | apiVersion: v1 4 | metadata: 5 | name: {{ include "traefik.serviceAccountName" . }} 6 | namespace: {{ template "traefik.namespace" . }} 7 | labels: 8 | {{- include "traefik.labels" . | nindent 4 }} 9 | annotations: 10 | {{- with .Values.serviceAccountAnnotations }} 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | {{- end -}} 14 | -------------------------------------------------------------------------------- /hack/changelog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | chart="./traefik" 4 | 5 | version="$(awk '/^version:/ { print $2} ' ${chart}/Chart.yaml)" 6 | changelog="$(sed -e "1,/^## ${version}/d" -e "/^###/,\$d" -e '/^$/d' -e 's/^* /- /' -e 's/^/ /' ${chart}/Changelog.md | grep '^ - ' | sed -e 's/\ *$//g' | sed 's/ - \(.*\)/ - "\1"/g')" 7 | sed -i -e '/^ artifacthub.io\/changes: |/,$d' ${chart}/Chart.yaml 8 | echo " artifacthub.io/changes: |" >> ${chart}/Chart.yaml 9 | echo "${changelog}" >> ${chart}/Chart.yaml 10 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### What does this PR do? 2 | 3 | 4 | 5 | 6 | ### Motivation 7 | 8 | 9 | 10 | 11 | ### More 12 | 13 | - [ ] Yes, I updated the tests accordingly 14 | - [ ] Yes, I ran `make test` and all the tests passed 15 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /traefik/tests/values/prometheusrules.yaml: -------------------------------------------------------------------------------- 1 | metrics: 2 | prometheus: 3 | prometheusRule: 4 | enabled: true 5 | additionalLabels: 6 | foo: bar 7 | namespace: another-namespace 8 | rules: 9 | - alert: TraefikDown 10 | expr: up{job="traefik"} == 0 11 | for: 5m 12 | labels: 13 | context: traefik 14 | severity: warning 15 | annotations: 16 | summary: "Traefik Down" 17 | description: "{{ $labels.pod }} on {{ $labels.nodename }} is down" 18 | -------------------------------------------------------------------------------- /traefik/tests/extra-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Traefik configuration 2 | templates: 3 | - extra-objects.yaml 4 | tests: 5 | - it: should deploy an extra object 6 | values: 7 | - ./values/extra.yaml 8 | documentIndex: 0 9 | asserts: 10 | - equal: 11 | path: data.something 12 | value: "extra" 13 | - it: should render a templated extra object 14 | values: 15 | - ./values/extra.yaml 16 | documentIndex: 1 17 | asserts: 18 | - equal: 19 | path: data.something 20 | value: "templated" 21 | -------------------------------------------------------------------------------- /traefik/tests/pvc-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Persistent volume claim configuration 2 | templates: 3 | - pvc.yaml 4 | tests: 5 | - it: should have no volumeName by default 6 | set: 7 | persistence: 8 | enabled: true 9 | asserts: 10 | - isNull: 11 | path: spec.volumeName 12 | - it: should have a volumeName when specified via values 13 | set: 14 | persistence: 15 | enabled: true 16 | volumeName: traefik 17 | asserts: 18 | - equal: 19 | path: spec.volumeName 20 | value: traefik 21 | -------------------------------------------------------------------------------- /traefik/templates/rbac/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.rbac.enabled -}} 2 | --- 3 | kind: ClusterRoleBinding 4 | apiVersion: rbac.authorization.k8s.io/v1 5 | metadata: 6 | name: {{ template "traefik.clusterRoleName" . }} 7 | labels: 8 | {{- include "traefik.labels" . | nindent 4 }} 9 | roleRef: 10 | apiGroup: rbac.authorization.k8s.io 11 | kind: ClusterRole 12 | name: {{ template "traefik.clusterRoleName" . }} 13 | subjects: 14 | - kind: ServiceAccount 15 | name: {{ include "traefik.serviceAccountName" . }} 16 | namespace: {{ template "traefik.namespace" . }} 17 | {{- end -}} 18 | -------------------------------------------------------------------------------- /traefik/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | Traefik Proxy {{ .Values.image.tag | default .Chart.AppVersion }} has been deployed successfully 4 | on {{ template "traefik.namespace" . }} namespace ! 5 | 6 | {{- if .Values.persistence }} 7 | {{- if and .Values.persistence.enabled (empty .Values.deployment.initContainer)}} 8 | 9 | 🚨 When enabling persistence for certificates, permissions on acme.json can be 10 | lost when Traefik restarts. You can ensure correct permissions with an 11 | initContainer. See https://github.com/traefik/traefik-helm-chart/issues/396 for 12 | more info. 🚨 13 | 14 | {{- end }} 15 | {{- end }} 16 | -------------------------------------------------------------------------------- /traefik/templates/rbac/rolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.rbac.enabled .Values.rbac.namespaced }} 2 | kind: RoleBinding 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | metadata: 5 | name: {{ template "traefik.fullname" . }} 6 | namespace: {{ template "traefik.namespace" . }} 7 | labels: 8 | {{- include "traefik.labels" . | nindent 4 }} 9 | roleRef: 10 | apiGroup: rbac.authorization.k8s.io 11 | kind: Role 12 | name: {{ template "traefik.fullname" . }} 13 | subjects: 14 | - kind: ServiceAccount 15 | name: {{ include "traefik.serviceAccountName" . }} 16 | namespace: {{ template "traefik.namespace" . }} 17 | {{- end -}} 18 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Test 3 | 4 | on: 5 | workflow_call: 6 | workflow_dispatch: 7 | pull_request: 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v3 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Configure Git 19 | run: | 20 | git config user.name "$GITHUB_ACTOR" 21 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 22 | - name: Lint 23 | run: make lint 24 | 25 | - name: Test 26 | run: make test 27 | 28 | - name: Track docs 29 | run: | 30 | make docs 31 | if ! [ -z "$(git status | grep traefik/VALUES.md)" ]; then 32 | echo "Traefik values have changed. Run make docs" 33 | exit 1 34 | fi 35 | -------------------------------------------------------------------------------- /traefik/templates/poddisruptionbudget.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.podDisruptionBudget.enabled -}} 2 | {{- if .Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} 3 | apiVersion: policy/v1 4 | {{- else }} 5 | apiVersion: policy/v1beta1 6 | {{- end }} 7 | kind: PodDisruptionBudget 8 | metadata: 9 | name: {{ template "traefik.fullname" . }} 10 | namespace: {{ template "traefik.namespace" . }} 11 | labels: 12 | {{- include "traefik.labels" . | nindent 4 }} 13 | spec: 14 | selector: 15 | matchLabels: 16 | {{- include "traefik.labelselector" . | nindent 6 }} 17 | {{- if .Values.podDisruptionBudget.minAvailable }} 18 | minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} 19 | {{- end }} 20 | {{- if .Values.podDisruptionBudget.maxUnavailable }} 21 | maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} 22 | {{- end }} 23 | {{- end -}} 24 | -------------------------------------------------------------------------------- /traefik/crds/kustomization.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: Kustomization 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | resources: 5 | - traefik.containo.us_ingressroutes.yaml 6 | - traefik.containo.us_ingressroutetcps.yaml 7 | - traefik.containo.us_ingressrouteudps.yaml 8 | - traefik.containo.us_middlewares.yaml 9 | - traefik.containo.us_middlewaretcps.yaml 10 | - traefik.containo.us_serverstransports.yaml 11 | - traefik.containo.us_tlsoptions.yaml 12 | - traefik.containo.us_tlsstores.yaml 13 | - traefik.containo.us_traefikservices.yaml 14 | - traefik.io_ingressroutes.yaml 15 | - traefik.io_ingressroutetcps.yaml 16 | - traefik.io_ingressrouteudps.yaml 17 | - traefik.io_middlewares.yaml 18 | - traefik.io_middlewaretcps.yaml 19 | - traefik.io_serverstransports.yaml 20 | - traefik.io_tlsoptions.yaml 21 | - traefik.io_tlsstores.yaml 22 | - traefik.io_traefikservices.yaml 23 | -------------------------------------------------------------------------------- /traefik/tests/values/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | metrics: 2 | prometheus: 3 | serviceMonitor: 4 | additionalLabels: 5 | release: traefik-release 6 | namespace: another-namespace 7 | namespaceSelector: 8 | any: true 9 | metricRelabelings: 10 | - sourceLabels: [__name__] 11 | separator: ; 12 | regex: ^fluentd_output_status_buffer_(oldest|newest)_.+ 13 | replacement: $1 14 | action: drop 15 | relabelings: 16 | - sourceLabels: [__meta_kubernetes_pod_node_name] 17 | separator: ; 18 | regex: ^(.*)$ 19 | targetLabel: nodename 20 | replacement: $1 21 | action: replace 22 | jobLabel: another-label 23 | interval: 30s 24 | scrapeTimeout: 5s 25 | honorLabels: true 26 | honorTimestamps: true 27 | enableHttp2: true 28 | followRedirects: true 29 | 30 | -------------------------------------------------------------------------------- /traefik/templates/ingressclass.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingressClass.enabled -}} 2 | {{- if (semverCompare "<2.3.0" (.Chart.AppVersion)) -}} 3 | {{- fail "ERROR: IngressClass cannot be used with Traefik < 2.3.0" -}} 4 | {{- end -}} 5 | {{- if semverCompare ">=1.19.0-0" .Capabilities.KubeVersion.Version -}} 6 | apiVersion: networking.k8s.io/v1 7 | {{- else if semverCompare ">=1.16.0-0" .Capabilities.KubeVersion.Version }} 8 | apiVersion: networking.k8s.io/v1beta1 9 | {{- else }} 10 | {{- fail "ERROR: You must use at least Kubernetes v1.16 with this Chart" }} 11 | {{- end }} 12 | kind: IngressClass 13 | metadata: 14 | annotations: 15 | ingressclass.kubernetes.io/is-default-class: {{ .Values.ingressClass.isDefaultClass | quote }} 16 | labels: 17 | {{- include "traefik.labels" . | nindent 4 }} 18 | name: {{ template "traefik.fullname" . }} 19 | spec: 20 | controller: traefik.io/ingress-controller 21 | {{- end -}} 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: lint test 2 | 3 | IMAGE_HELM_UNITTEST=docker.io/helmunittest/helm-unittest:3.11.2-0.3.1 4 | IMAGE_CHART_TESTING=quay.io/helmpack/chart-testing:v3.7.1 5 | 6 | traefik/tests/__snapshot__: 7 | @mkdir traefik/tests/__snapshot__ 8 | 9 | test: traefik/tests/__snapshot__ 10 | docker run ${DOCKER_ARGS} --entrypoint /bin/sh --rm -v $(CURDIR):/charts -w /charts $(IMAGE_HELM_UNITTEST) /charts/hack/test.sh 11 | 12 | lint: 13 | docker run ${DOCKER_ARGS} --env GIT_SAFE_DIR="true" --entrypoint /bin/sh --rm -v $(CURDIR):/charts -w /charts $(IMAGE_CHART_TESTING) /charts/hack/lint.sh 14 | 15 | docs: 16 | docker run --rm -v "$(CURDIR):/helm-docs" jnorwood/helm-docs:latest 17 | mv -f "$(CURDIR)/traefik/README.md" "$(CURDIR)/traefik/VALUES.md" 18 | 19 | changelog: 20 | @echo "== Updating Changelogs..." 21 | @docker run -it --rm -v $(CURDIR):/data ghcr.io/mloiseleur/helm-changelog:v0.0.2 22 | @./hack/changelog.sh 23 | @echo "== Updating finished" 24 | -------------------------------------------------------------------------------- /traefik/templates/pvc.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) -}} 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: {{ template "traefik.fullname" . }} 6 | namespace: {{ template "traefik.namespace" . }} 7 | annotations: 8 | {{- with .Values.persistence.annotations }} 9 | {{ toYaml . | nindent 4 }} 10 | {{- end }} 11 | helm.sh/resource-policy: keep 12 | labels: 13 | {{- include "traefik.labels" . | nindent 4 }} 14 | spec: 15 | accessModes: 16 | - {{ .Values.persistence.accessMode | quote }} 17 | resources: 18 | requests: 19 | storage: {{ .Values.persistence.size | quote }} 20 | {{- if .Values.persistence.storageClass }} 21 | storageClassName: {{ .Values.persistence.storageClass | quote }} 22 | {{- end }} 23 | {{- if .Values.persistence.volumeName }} 24 | volumeName: {{ .Values.persistence.volumeName | quote }} 25 | {{- end }} 26 | {{- end -}} 27 | -------------------------------------------------------------------------------- /traefik/templates/_service-metrics.tpl: -------------------------------------------------------------------------------- 1 | {{- define "traefik.metrics-service-metadata" }} 2 | labels: 3 | {{- include "traefik.metricsservicelabels" . | nindent 4 -}} 4 | {{- with .Values.metrics.prometheus.service.labels }} 5 | {{- toYaml . | nindent 4 }} 6 | {{- end }} 7 | {{- end }} 8 | 9 | {{/* Labels used for metrics-relevant selector*/}} 10 | {{/* This is an immutable field: this should not change between upgrade */}} 11 | {{- define "traefik.metricslabelselector" -}} 12 | {{- include "traefik.labelselector" . }} 13 | app.kubernetes.io/component: metrics 14 | {{- end }} 15 | 16 | {{/* Shared labels used in metadata of metrics-service and servicemonitor */}} 17 | {{- define "traefik.metricsservicelabels" -}} 18 | {{ include "traefik.metricslabelselector" . }} 19 | helm.sh/chart: {{ template "traefik.chart" . }} 20 | app.kubernetes.io/managed-by: {{ .Release.Service }} 21 | {{- with .Values.commonLabels }} 22 | {{ toYaml . }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | -------------------------------------------------------------------------------- /traefik/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: traefik 3 | description: A Traefik based Kubernetes ingress controller 4 | type: application 5 | version: 23.0.1 6 | # renovate: image=traefik 7 | appVersion: v2.10.1 8 | kubeVersion: ">=1.16.0-0" 9 | keywords: 10 | - traefik 11 | - ingress 12 | - networking 13 | home: https://traefik.io/ 14 | sources: 15 | - https://github.com/traefik/traefik 16 | - https://github.com/traefik/traefik-helm-chart 17 | maintainers: 18 | - name: emilevauge 19 | email: emile@vauge.com 20 | - name: dtomcej 21 | email: daniel.tomcej@gmail.com 22 | - name: ldez 23 | email: ldez@traefik.io 24 | - name: mloiseleur 25 | email: michel.loiseleur@traefik.io 26 | - name: charlie-haley 27 | email: charlie.haley@traefik.io 28 | icon: https://raw.githubusercontent.com/traefik/traefik/v2.3/docs/content/assets/img/traefik.logo.png 29 | annotations: 30 | artifacthub.io/changes: | 31 | - "⬆️ Upgrade traefik Docker tag to v2.10.1" 32 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guide 2 | 3 | This Helm Chart accepts contributions from GitHub pull requests. 4 | You can find help in this document to get your contribution accepted. 5 | 6 | ## Helm Chart Guidelines 7 | 8 | Please read the [Helm Chart Guidelines](./traefik/Guidelines.md) before editing this chart. 9 | 10 | ## Testing 11 | 12 | Please read the [testing guidelines](./TESTING.md) to learn how testing is done with this chart. 13 | 14 | ## Guidelines 15 | 16 | According to the Traefik HelmChart [philosophy](./README.md#philosophy), 17 | the guidelines for future evolutions are: 18 | 19 | * fix bugs 20 | * improve security 21 | * improve HelmChart support 22 | * improve Kubernetes features support 23 | * improve Traefik default configuration 24 | 25 | While encouraging contributions, the philosophy leads to avoid introducing: 26 | 27 | * specific use cases 28 | * third party CRD 29 | * dashboard exposition tuning 30 | * helm chart variables that shortcuts/expose static or dynamic Traefik configuration -------------------------------------------------------------------------------- /traefik/tests/tlsstore_test.yaml: -------------------------------------------------------------------------------- 1 | suite: TlsStore configuration 2 | templates: 3 | - tlsstore.yaml 4 | tests: 5 | - it: should use helm managed namespace as default behavior 6 | set: 7 | tlsStore: 8 | default: 9 | defaultCertificate: 10 | secretName: tls-cert 11 | asserts: 12 | - equal: 13 | path: metadata.namespace 14 | value: NAMESPACE 15 | - it: should accept overridden namespace 16 | set: 17 | tlsStore: 18 | default: 19 | defaultCertificate: 20 | secretName: tls-cert 21 | namespaceOverride: "traefik-ns-override" 22 | asserts: 23 | - equal: 24 | path: metadata.namespace 25 | value: "traefik-ns-override" 26 | - it: should set tlsStore config 27 | set: 28 | tlsStore: 29 | default: 30 | defaultCertificate: 31 | secretName: tls-cert 32 | asserts: 33 | - isSubset: 34 | path: spec 35 | content: 36 | defaultCertificate: 37 | secretName: tls-cert 38 | -------------------------------------------------------------------------------- /traefik/tests/hpa-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: HPA configuration 2 | templates: 3 | - hpa.yaml 4 | capabilities: 5 | majorVersion: 1 6 | minorVersion: 23 7 | tests: 8 | - it: should use autoscaling/v2 when k8s >= 1.23 9 | values: 10 | - ./values/hpa.yaml 11 | asserts: 12 | - isAPIVersion: 13 | of: autoscaling/v2 14 | - it: should use autoscaling/v2beta2 when k8s < 1.23 15 | capabilities: 16 | majorVersion: 1 17 | minorVersion: 22 18 | values: 19 | - ./values/hpa.yaml 20 | asserts: 21 | - isAPIVersion: 22 | of: autoscaling/v2beta2 23 | - it: should fail without maxReplicas 24 | set: 25 | autoscaling: 26 | enabled: true 27 | asserts: 28 | - failedTemplate: 29 | errorMessage: "maxReplicas is required on HPA" 30 | - it: should not contains metrics nor behavior when they are not set 31 | set: 32 | autoscaling: 33 | enabled: true 34 | maxReplicas: 3 35 | asserts: 36 | - isNull: 37 | path: spec.metrics 38 | - isNull: 39 | path: spec.behavior 40 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "gitmoji", 5 | ":semanticCommits" 6 | ], 7 | "semanticCommits": "enabled", 8 | "gitAuthor": "traefiker <30906710+traefiker@users.noreply.github.com>", 9 | "rebaseWhen": "conflicted", 10 | "bumpVersion": "minor", 11 | "packageRules": [ 12 | { 13 | "matchManagers": ["kubernetes"], 14 | "matchDatasources": ["kubernetes-api"], 15 | "description": "disable kubernetes api updates", 16 | "enabled": false 17 | } 18 | ], 19 | "regexManagers": [ 20 | { 21 | "datasourceTemplate": "docker", 22 | "fileMatch": [ 23 | "(^|/)Chart\\.yaml$" 24 | ], 25 | "matchStrings": [ 26 | "#\\s*renovate: image=(?.*?)\\s+appVersion:\\s*[\"']?(?[\\w+\\.\\-]*)" 27 | ] 28 | }, 29 | { 30 | "datasourceTemplate": "docker", 31 | "fileMatch": [ 32 | "^Makefile$" 33 | ], 34 | "matchStrings": [ 35 | "^IMAGE_(.+)=(?.*?):(?[\\w+\\.\\-]*)$" 36 | ] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /traefik/templates/service-metrics.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.metrics.prometheus }} 2 | {{- if .Values.metrics.prometheus.service }} 3 | {{- if (.Values.metrics.prometheus.service).enabled -}} 4 | 5 | {{- $fullname := include "traefik.fullname" . }} 6 | {{- if ge (len $fullname) 50 }} 7 | {{- fail "ERROR: Cannot create a metrics service when name contains more than 50 characters" }} 8 | {{- end }} 9 | apiVersion: v1 10 | kind: Service 11 | metadata: 12 | name: {{ $fullname }}-metrics 13 | namespace: {{ template "traefik.namespace" . }} 14 | {{- template "traefik.metrics-service-metadata" . }} 15 | annotations: 16 | {{- with .Values.metrics.prometheus.service.annotations }} 17 | {{- toYaml . | nindent 4 }} 18 | {{- end }} 19 | spec: 20 | type: ClusterIP 21 | selector: 22 | {{- include "traefik.labelselector" . | nindent 4 }} 23 | ports: 24 | - port: {{ .Values.ports.metrics.port }} 25 | name: "metrics" 26 | targetPort: metrics 27 | protocol: TCP 28 | {{- if .Values.ports.metrics.nodePort }} 29 | nodePort: {{ .Values.ports.metrics.nodePort }} 30 | {{- end }} 31 | {{- end }} 32 | {{- end }} 33 | {{- end }} 34 | -------------------------------------------------------------------------------- /traefik/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | 3 | {{- if not .Values.autoscaling.maxReplicas }} 4 | {{- fail "ERROR: maxReplicas is required on HPA" }} 5 | {{- end }} 6 | 7 | {{- if semverCompare ">=1.23.0-0" .Capabilities.KubeVersion.Version }} 8 | apiVersion: autoscaling/v2 9 | {{- else }} 10 | apiVersion: autoscaling/v2beta2 11 | {{- end }} 12 | kind: HorizontalPodAutoscaler 13 | metadata: 14 | name: {{ template "traefik.fullname" . }} 15 | namespace: {{ template "traefik.namespace" . }} 16 | labels: 17 | {{- include "traefik.labels" . | nindent 4 }} 18 | spec: 19 | scaleTargetRef: 20 | apiVersion: apps/v1 21 | kind: Deployment 22 | name: {{ template "traefik.fullname" . }} 23 | {{- if .Values.autoscaling.minReplicas }} 24 | minReplicas: {{ .Values.autoscaling.minReplicas }} 25 | {{- end }} 26 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 27 | {{- if .Values.autoscaling.metrics }} 28 | metrics: 29 | {{ toYaml .Values.autoscaling.metrics | indent 4 }} 30 | {{- end }} 31 | {{- if .Values.autoscaling.behavior }} 32 | behavior: 33 | {{ toYaml .Values.autoscaling.behavior | indent 4 }} 34 | {{- end }} 35 | {{- end }} 36 | -------------------------------------------------------------------------------- /traefik/templates/dashboard-ingressroute.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingressRoute.dashboard.enabled -}} 2 | apiVersion: traefik.io/v1alpha1 3 | kind: IngressRoute 4 | metadata: 5 | name: {{ template "traefik.fullname" . }}-dashboard 6 | namespace: {{ template "traefik.namespace" . }} 7 | annotations: 8 | {{- with .Values.ingressRoute.dashboard.annotations }} 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | labels: 12 | {{- include "traefik.labels" . | nindent 4 }} 13 | {{- with .Values.ingressRoute.dashboard.labels }} 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | spec: 17 | entryPoints: 18 | {{- range .Values.ingressRoute.dashboard.entryPoints }} 19 | - {{ . }} 20 | {{- end }} 21 | routes: 22 | - match: {{ .Values.ingressRoute.dashboard.matchRule }} 23 | kind: Rule 24 | services: 25 | - name: api@internal 26 | kind: TraefikService 27 | {{- with .Values.ingressRoute.dashboard.middlewares }} 28 | middlewares: 29 | {{- toYaml . | nindent 6 }} 30 | {{- end -}} 31 | 32 | {{- with .Values.ingressRoute.dashboard.tls }} 33 | tls: 34 | {{- toYaml . | nindent 4 }} 35 | {{- end }} 36 | {{- end -}} 37 | -------------------------------------------------------------------------------- /traefik/templates/prometheusrules.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.metrics.prometheus }} 2 | {{- if .Values.metrics.prometheus.prometheusRule }} 3 | {{- if (not (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1")) }} 4 | {{- if (not (.Values.metrics.prometheus.disableAPICheck)) }} 5 | {{- fail "ERROR: You have to deploy monitoring.coreos.com/v1 first" }} 6 | {{- end }} 7 | {{- end }} 8 | apiVersion: monitoring.coreos.com/v1 9 | kind: PrometheusRule 10 | metadata: 11 | name: {{ template "traefik.fullname" . }} 12 | {{- if .Values.metrics.prometheus.prometheusRule.namespace }} 13 | namespace: {{ .Values.metrics.prometheus.prometheusRule.namespace }} 14 | {{- end }} 15 | labels: 16 | {{- include "traefik.labels" . | nindent 4 }} 17 | {{- with .Values.metrics.prometheus.prometheusRule.additionalLabels }} 18 | {{- toYaml . | nindent 4 }} 19 | {{- end }} 20 | spec: 21 | {{- if .Values.metrics.prometheus.prometheusRule.rules }} 22 | groups: 23 | - name: {{ template "traefik.name" $ }} 24 | rules: 25 | {{- with .Values.metrics.prometheus.prometheusRule.rules }} 26 | {{- toYaml . | nindent 4 }} 27 | {{- end }} 28 | {{- end }} 29 | {{- end }} 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /traefik/templates/gateway.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.experimental.kubernetesGateway.enabled }} 2 | {{- if .Values.experimental.kubernetesGateway.gateway.enabled }} 3 | --- 4 | apiVersion: gateway.networking.k8s.io/v1alpha2 5 | kind: Gateway 6 | metadata: 7 | name: traefik-gateway 8 | namespace: {{ default (include "traefik.namespace" .) .Values.experimental.kubernetesGateway.namespace }} 9 | labels: 10 | {{- include "traefik.labels" . | nindent 4 }} 11 | {{- with .Values.experimental.kubernetesGateway.gateway.annotations }} 12 | annotations: 13 | {{- toYaml . | nindent 4 }} 14 | {{- end }} 15 | spec: 16 | gatewayClassName: traefik 17 | listeners: 18 | - name: web 19 | port: {{ .Values.ports.web.port }} 20 | protocol: HTTP 21 | 22 | {{- if .Values.experimental.kubernetesGateway.certificate }} 23 | - name: websecure 24 | port: {{ $.Values.ports.websecure.port }} 25 | protocol: HTTPS 26 | tls: 27 | certificateRefs: 28 | - name: {{ .Values.experimental.kubernetesGateway.certificate.name }} 29 | group: {{ .Values.experimental.kubernetesGateway.certificate.group }} 30 | kind: {{ .Values.experimental.kubernetesGateway.certificate.kind }} 31 | {{- end }} 32 | {{- end }} 33 | {{- end }} 34 | -------------------------------------------------------------------------------- /traefik/templates/tlsoption.yaml: -------------------------------------------------------------------------------- 1 | {{- range $name, $config := .Values.tlsOptions }} 2 | apiVersion: traefik.io/v1alpha1 3 | kind: TLSOption 4 | metadata: 5 | name: {{ $name }} 6 | namespace: {{ template "traefik.namespace" $ }} 7 | labels: 8 | {{- include "traefik.labels" $ | nindent 4 }} 9 | {{- with $config.labels }} 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | spec: 13 | {{- with $config.alpnProtocols }} 14 | alpnProtocols: 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | {{- with $config.cipherSuites }} 18 | cipherSuites: 19 | {{- toYaml . | nindent 4 }} 20 | {{- end }} 21 | {{- with $config.clientAuth }} 22 | clientAuth: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | {{- with $config.curvePreferences }} 26 | curvePreferences: 27 | {{- toYaml . | nindent 4 }} 28 | {{- end }} 29 | {{- if $config.maxVersion }} 30 | maxVersion: {{ $config.maxVersion }} 31 | {{- end }} 32 | {{- if $config.minVersion }} 33 | minVersion: {{ $config.minVersion }} 34 | {{- end }} 35 | {{- if $config.preferServerCipherSuites }} 36 | preferServerCipherSuites: {{ $config.preferServerCipherSuites }} 37 | {{- end }} 38 | {{- if $config.sniStrict }} 39 | sniStrict: {{ $config.sniStrict }} 40 | {{- end }} 41 | --- 42 | {{- end -}} 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Suggest an idea for this project. 3 | labels: ['status/0-needs-triage'] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | ### How to write a good bug report? 9 | 10 | - Respect the issue template as much as possible. 11 | - The title should be short and descriptive. 12 | - Explain the conditions which led you to report this issue: the context. 13 | - The context should lead to something, an idea or a problem that you’re facing. 14 | - Remain clear and concise. 15 | - Format your messages to help the reader focus on what matters and understand the structure of your message, use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown) 16 | 17 | - type: checkboxes 18 | id: terms 19 | attributes: 20 | label: Welcome! 21 | options: 22 | - label: Yes, I've searched similar issues on [GitHub](https://github.com/traefik/traefik/issues) and didn't find any. 23 | required: true 24 | - label: Yes, I've searched similar issues on the [Traefik community forum](https://community.traefik.io) and didn't find any. 25 | required: true 26 | 27 | - type: textarea 28 | attributes: 29 | label: What did you expect to see? 30 | description: Use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown) if needed. 31 | placeholder: What did you expect to see? 32 | validations: 33 | required: true 34 | -------------------------------------------------------------------------------- /traefik/tests/default-install_test.yaml: -------------------------------------------------------------------------------- 1 | suite: default install 2 | tests: 3 | - it: should generate the default objects for Traefik Ingress Controller 4 | capabilities: 5 | apiVersions: 6 | - networking.k8s.io/v1 7 | asserts: 8 | - isKind: 9 | of: Deployment 10 | template: deployment.yaml 11 | - isKind: 12 | of: Service 13 | template: service.yaml 14 | - isKind: 15 | of: ClusterRole 16 | template: rbac/clusterrole.yaml 17 | - isKind: 18 | of: ClusterRoleBinding 19 | template: rbac/clusterrolebinding.yaml 20 | - isKind: 21 | of: ServiceAccount 22 | template: rbac/serviceaccount.yaml 23 | - it: should have the correct naming for each object 24 | capabilities: 25 | apiVersions: 26 | - networking.k8s.io/v1 27 | asserts: 28 | - equal: 29 | path: metadata.name 30 | value: RELEASE-NAME-traefik 31 | template: deployment.yaml 32 | - equal: 33 | path: metadata.name 34 | value: RELEASE-NAME-traefik 35 | template: service.yaml 36 | - equal: 37 | path: metadata.name 38 | value: RELEASE-NAME-traefik-NAMESPACE 39 | template: rbac/clusterrole.yaml 40 | - equal: 41 | path: metadata.name 42 | value: RELEASE-NAME-traefik-NAMESPACE 43 | template: rbac/clusterrolebinding.yaml 44 | - equal: 45 | path: metadata.name 46 | value: RELEASE-NAME-traefik 47 | template: rbac/serviceaccount.yaml 48 | -------------------------------------------------------------------------------- /traefik/templates/_service-internal.tpl: -------------------------------------------------------------------------------- 1 | {{- define "traefik.service-internal-metadata" }} 2 | labels: 3 | {{- include "traefik.labels" . | nindent 4 -}} 4 | {{- with .Values.service.internal.labels }} 5 | {{- toYaml . | nindent 4 }} 6 | {{- end }} 7 | {{- end }} 8 | 9 | {{- define "traefik.service-internal-spec" -}} 10 | {{- $type := default "ClusterIP" .Values.service.internal.type }} 11 | type: {{ $type }} 12 | {{- with .Values.service.internal.spec }} 13 | {{- toYaml . | nindent 2 }} 14 | {{- end }} 15 | selector: 16 | {{- include "traefik.labelselector" . | nindent 4 }} 17 | {{- if eq $type "LoadBalancer" }} 18 | {{- with .Values.service.internal.loadBalancerSourceRanges }} 19 | loadBalancerSourceRanges: 20 | {{- toYaml . | nindent 2 }} 21 | {{- end -}} 22 | {{- end -}} 23 | {{- with .Values.service.internal.externalIPs }} 24 | externalIPs: 25 | {{- toYaml . | nindent 2 }} 26 | {{- end -}} 27 | {{- with .Values.service.internal.ipFamilyPolicy }} 28 | ipFamilyPolicy: {{ . }} 29 | {{- end }} 30 | {{- with .Values.service.internal.ipFamilies }} 31 | ipFamilies: 32 | {{- toYaml . | nindent 2 }} 33 | {{- end -}} 34 | {{- end }} 35 | 36 | {{- define "traefik.service-internal-ports" }} 37 | {{- range $name, $config := . }} 38 | {{- if $config.expose }} 39 | - port: {{ default $config.port $config.exposedPort }} 40 | name: {{ $name | quote }} 41 | targetPort: {{ default $name $config.targetPort }} 42 | protocol: {{ default "TCP" $config.protocol }} 43 | {{- if $config.nodePort }} 44 | nodePort: {{ $config.nodePort }} 45 | {{- end }} 46 | {{- end }} 47 | {{- end }} 48 | {{- end }} 49 | -------------------------------------------------------------------------------- /traefik/templates/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.rbac.enabled .Values.rbac.namespaced }} 2 | kind: Role 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | metadata: 5 | name: {{ template "traefik.fullname" . }} 6 | namespace: {{ template "traefik.namespace" . }} 7 | labels: 8 | {{- include "traefik.labels" . | nindent 4 }} 9 | rules: 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - services 14 | - endpoints 15 | - secrets 16 | verbs: 17 | - get 18 | - list 19 | - watch 20 | {{- if .Values.providers.kubernetesIngress.enabled }} 21 | - apiGroups: 22 | - extensions 23 | - networking.k8s.io 24 | resources: 25 | - ingresses 26 | verbs: 27 | - get 28 | - list 29 | - watch 30 | - apiGroups: 31 | - extensions 32 | - networking.k8s.io 33 | resources: 34 | - ingresses/status 35 | verbs: 36 | - update 37 | {{- end -}} 38 | {{- if .Values.providers.kubernetesCRD.enabled }} 39 | - apiGroups: 40 | - traefik.io 41 | - traefik.containo.us 42 | resources: 43 | - ingressroutes 44 | - ingressroutetcps 45 | - ingressrouteudps 46 | - middlewares 47 | - middlewaretcps 48 | - tlsoptions 49 | - tlsstores 50 | - traefikservices 51 | - serverstransports 52 | verbs: 53 | - get 54 | - list 55 | - watch 56 | {{- end -}} 57 | {{- if .Values.podSecurityPolicy.enabled }} 58 | - apiGroups: 59 | - extensions 60 | resourceNames: 61 | - {{ template "traefik.fullname" . }} 62 | resources: 63 | - podsecuritypolicies 64 | verbs: 65 | - use 66 | {{- end -}} 67 | {{- end -}} 68 | -------------------------------------------------------------------------------- /traefik/tests/service-metrics-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Metrics Service configuration 2 | templates: 3 | - service-metrics.yaml 4 | tests: 5 | - it: "should not fail with long name by default" 6 | release: 7 | name: thisisaverylongreleasenameinordertotriggerit 8 | asserts: 9 | - hasDocuments: 10 | count: 0 11 | - it: "should support prometheus: null" 12 | set: 13 | metrics: 14 | prometheus: null 15 | asserts: 16 | - hasDocuments: 17 | count: 0 18 | - it: should not provide a dedicated metrics service by default 19 | asserts: 20 | - hasDocuments: 21 | count: 0 22 | - it: should provide a dedicated metrics service when enabled set to true 23 | set: 24 | metrics: 25 | prometheus: 26 | service: 27 | enabled: true 28 | labels: 29 | custom-label: label-value 30 | annotations: 31 | custom-annotation: annotation-value 32 | asserts: 33 | - hasDocuments: 34 | count: 1 35 | - equal: 36 | path: spec.type 37 | value: ClusterIP 38 | - equal: 39 | path: metadata.labels.custom-label 40 | value: label-value 41 | - equal: 42 | path: metadata.annotations.custom-annotation 43 | value: annotation-value 44 | - equal: 45 | path: spec.selector 46 | value: 47 | app.kubernetes.io/name: traefik 48 | app.kubernetes.io/instance: RELEASE-NAME-NAMESPACE 49 | - contains: 50 | path: spec.ports 51 | content: 52 | port: 9100 53 | name: "metrics" 54 | targetPort: metrics 55 | protocol: TCP 56 | -------------------------------------------------------------------------------- /traefik/templates/daemonset.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.deployment.enabled (eq .Values.deployment.kind "DaemonSet") -}} 2 | {{- with .Values.additionalArguments -}} 3 | {{- range . -}} 4 | {{- if contains ".acme." . -}} 5 | {{- fail (printf "ACME functionality is not supported when running Traefik as a DaemonSet") -}} 6 | {{- end -}} 7 | {{- end -}} 8 | {{- end -}} 9 | {{- if eq (default .Chart.AppVersion .Values.image.tag) "latest" }} 10 | {{- fail "\n\n ERROR: latest tag should not be used" }} 11 | {{- end }} 12 | {{- if eq (.Values.updateStrategy.type) "RollingUpdate" }} 13 | {{- if and (lt .Values.updateStrategy.rollingUpdate.maxUnavailable 1.0) (.Values.hostNetwork) }} 14 | {{- fail "maxUnavailable should be greater than 1 when using hostNetwork." }} 15 | {{- end }} 16 | {{- end }} 17 | 18 | --- 19 | apiVersion: apps/v1 20 | kind: DaemonSet 21 | metadata: 22 | name: {{ template "traefik.fullname" . }} 23 | namespace: {{ template "traefik.namespace" . }} 24 | labels: 25 | {{- include "traefik.labels" . | nindent 4 }} 26 | {{- with .Values.deployment.labels }} 27 | {{- toYaml . | nindent 4 }} 28 | {{- end }} 29 | annotations: 30 | {{- with .Values.deployment.annotations }} 31 | {{- toYaml . | nindent 4 }} 32 | {{- end }} 33 | spec: 34 | selector: 35 | matchLabels: 36 | {{- include "traefik.labelselector" . | nindent 6 }} 37 | updateStrategy: {{ toYaml .Values.updateStrategy | nindent 4 }} 38 | minReadySeconds: {{ .Values.deployment.minReadySeconds }} 39 | {{- if .Values.deployment.revisionHistoryLimit }} 40 | revisionHistoryLimit: {{ .Values.deployment.revisionHistoryLimit }} 41 | {{- end }} 42 | template: {{ template "traefik.podTemplate" . }} 43 | {{- end -}} 44 | -------------------------------------------------------------------------------- /traefik/tests/prometheusrules-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: PrometheusRules configuration 2 | templates: 3 | - prometheusrules.yaml 4 | tests: 5 | - it: should not provide PrometheusRules by default 6 | asserts: 7 | - hasDocuments: 8 | count: 0 9 | - it: should fail to provide PrometheusRules without the API 10 | values: 11 | - ./values/prometheusrules.yaml 12 | asserts: 13 | - failedTemplate: 14 | errorMessage: "You have to deploy monitoring.coreos.com/v1 first" 15 | - it: should successfully provide PrometheusRules when disabling API check 16 | values: 17 | - ./values/prometheusrules.yaml 18 | set: 19 | metrics: 20 | prometheus: 21 | disableAPICheck: true 22 | asserts: 23 | - hasDocuments: 24 | count: 1 25 | - it: should successfully provide PrometheusRules with the API and example values 26 | values: 27 | - ./values/prometheusrules.yaml 28 | capabilities: 29 | apiVersions: 30 | - monitoring.coreos.com/v1 31 | asserts: 32 | - hasDocuments: 33 | count: 1 34 | - equal: 35 | path: metadata.namespace 36 | value: another-namespace 37 | - equal: 38 | path: metadata.labels.foo 39 | value: bar 40 | - contains: 41 | path: spec.groups 42 | content: 43 | name: traefik 44 | rules: 45 | - alert: TraefikDown 46 | annotations: 47 | description: '{{ $labels.pod }} on {{ $labels.nodename }} is down' 48 | summary: Traefik Down 49 | expr: up{job="traefik"} == 0 50 | for: 5m 51 | labels: 52 | context: traefik 53 | severity: warning 54 | -------------------------------------------------------------------------------- /traefik/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | {{/* check helm version */}} 2 | {{- if (semverCompare "= 3.9.0 is required" -}} 4 | {{- end -}} 5 | 6 | {{- if and .Values.deployment.enabled (eq .Values.deployment.kind "Deployment") -}} 7 | {{- if gt (int .Values.deployment.replicas) 1 -}} 8 | {{- with .Values.additionalArguments -}} 9 | {{- range . -}} 10 | {{- if contains ".acme." . -}} 11 | {{- fail (printf "You can not enable acme if you set more than one traefik replica") -}} 12 | {{- end -}} 13 | {{- end -}} 14 | {{- end -}} 15 | {{- end -}} 16 | {{- if eq (default .Chart.AppVersion .Values.image.tag) "latest" }} 17 | {{- fail "\n\n ERROR: latest tag should not be used" }} 18 | {{- end }} 19 | 20 | --- 21 | apiVersion: apps/v1 22 | kind: Deployment 23 | metadata: 24 | name: {{ template "traefik.fullname" . }} 25 | namespace: {{ template "traefik.namespace" . }} 26 | labels: 27 | {{- include "traefik.labels" . | nindent 4 }} 28 | {{- with .Values.deployment.labels }} 29 | {{- toYaml . | nindent 4 }} 30 | {{- end }} 31 | annotations: 32 | {{- with .Values.deployment.annotations }} 33 | {{- toYaml . | nindent 4 }} 34 | {{- end }} 35 | spec: 36 | {{- if not .Values.autoscaling.enabled }} 37 | replicas: {{ default 1 .Values.deployment.replicas }} 38 | {{- end }} 39 | {{- if .Values.deployment.revisionHistoryLimit }} 40 | revisionHistoryLimit: {{ .Values.deployment.revisionHistoryLimit }} 41 | {{- end }} 42 | selector: 43 | matchLabels: 44 | {{- include "traefik.labelselector" . | nindent 6 }} 45 | strategy: {{ toYaml .Values.updateStrategy | nindent 4 }} 46 | minReadySeconds: {{ .Values.deployment.minReadySeconds }} 47 | template: {{ template "traefik.podTemplate" . }} 48 | {{- end -}} 49 | -------------------------------------------------------------------------------- /traefik/tests/common-metadata_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Resources contains metadata 2 | templates: 3 | - dashboard-ingressroute.yaml 4 | - deployment.yaml 5 | - gatewayclass.yaml 6 | - gateway.yaml 7 | - hpa.yaml 8 | - ingressclass.yaml 9 | - poddisruptionbudget.yaml 10 | - prometheusrules.yaml 11 | - pvc.yaml 12 | - service-internal.yaml 13 | - servicemonitor.yaml 14 | - service.yaml 15 | - tlsoption.yaml 16 | - tlsstore.yaml 17 | - rbac/clusterrole.yaml 18 | - rbac/clusterrolebinding.yaml 19 | - rbac/podsecuritypolicy.yaml 20 | - rbac/role.yaml 21 | - rbac/rolebinding.yaml 22 | - rbac/serviceaccount.yaml 23 | 24 | tests: 25 | - it: "should contains labels metadata" 26 | set: 27 | experimental.kubernetesGateway.enabled: true 28 | experimental.kubernetesGateway.gateway.enabled: true 29 | autoscaling.enabled: true 30 | autoscaling.maxReplicas: 10 31 | podDisruptionBudget.enabled: true 32 | metrics.prometheus.prometheusRule.namespace: test 33 | metrics.prometheus.serviceMonitor.namespace: test 34 | metrics.prometheus.service.enabled: true 35 | service.internal.a: {} 36 | persistence.enabled: true 37 | tlsStore.a: {} 38 | tlsOptions.a: {} 39 | podSecurityPolicy.enabled: true 40 | rbac.enabled: true 41 | rbac.namespaced: true 42 | commonLabels: 43 | globalLabel: isConfigured 44 | capabilities: 45 | majorVersion: 1 46 | minorVersion: 16 47 | apiVersions: 48 | - monitoring.coreos.com/v1 49 | - autoscaling/v2beta1 50 | asserts: 51 | - isNotEmpty: 52 | path: metadata.labels 53 | - isSubset: 54 | path: metadata.labels 55 | content: 56 | app.kubernetes.io/managed-by: Helm 57 | - isSubset: 58 | path: metadata.labels 59 | content: 60 | globalLabel: isConfigured 61 | -------------------------------------------------------------------------------- /traefik/templates/rbac/podsecuritypolicy.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.podSecurityPolicy.enabled }} 2 | {{- if semverCompare ">=1.25.0-0" .Capabilities.KubeVersion.Version }} 3 | {{- fail "ERROR: PodSecurityPolicy has been removed in Kubernetes v1.25+" }} 4 | {{- end }} 5 | --- 6 | apiVersion: policy/v1beta1 7 | kind: PodSecurityPolicy 8 | metadata: 9 | annotations: 10 | seccomp.security.alpha.kubernetes.io/allowedProfileNames: runtime/default 11 | seccomp.security.alpha.kubernetes.io/defaultProfileName: runtime/default 12 | name: {{ template "traefik.fullname" . }} 13 | labels: 14 | {{- include "traefik.labels" . | nindent 4 }} 15 | spec: 16 | privileged: false 17 | allowPrivilegeEscalation: false 18 | requiredDropCapabilities: 19 | - ALL 20 | {{- if not .Values.securityContext.runAsNonRoot }} 21 | allowedCapabilities: 22 | - NET_BIND_SERVICE 23 | {{- end }} 24 | hostNetwork: {{ .Values.hostNetwork }} 25 | hostIPC: false 26 | hostPID: false 27 | fsGroup: 28 | {{- if .Values.securityContext.runAsNonRoot }} 29 | ranges: 30 | - max: 65535 31 | min: 1 32 | rule: MustRunAs 33 | {{- else }} 34 | rule: RunAsAny 35 | {{- end }} 36 | {{- if .Values.hostNetwork }} 37 | hostPorts: 38 | - max: 65535 39 | min: 1 40 | {{- end }} 41 | readOnlyRootFilesystem: true 42 | runAsUser: 43 | {{- if .Values.securityContext.runAsNonRoot }} 44 | rule: MustRunAsNonRoot 45 | {{- else }} 46 | rule: RunAsAny 47 | {{- end }} 48 | seLinux: 49 | rule: RunAsAny 50 | supplementalGroups: 51 | {{- if .Values.securityContext.runAsNonRoot }} 52 | ranges: 53 | - max: 65535 54 | min: 1 55 | rule: MustRunAs 56 | {{- else }} 57 | rule: RunAsAny 58 | {{- end }} 59 | volumes: 60 | - configMap 61 | - downwardAPI 62 | - secret 63 | - emptyDir 64 | - projected 65 | {{- if .Values.persistence.enabled }} 66 | - persistentVolumeClaim 67 | {{- end -}} 68 | {{- end -}} 69 | -------------------------------------------------------------------------------- /traefik/templates/service-internal.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.service.internal -}} 2 | 3 | {{- $fullname := include "traefik.fullname" . }} 4 | {{- if ge (len $fullname) 50 }} 5 | {{- fail "ERROR: Cannot create an internal service when name contains more than 50 characters" }} 6 | {{- end }} 7 | 8 | {{- $tcpPorts := dict -}} 9 | {{- $udpPorts := dict -}} 10 | {{- $exposedPorts := false -}} 11 | {{- range $name, $config := .Values.ports -}} 12 | {{- if eq (toString $config.protocol) "UDP" -}} 13 | {{ $_ := set $udpPorts $name $config -}} 14 | {{- end -}} 15 | {{- if eq (toString (default "TCP" $config.protocol)) "TCP" -}} 16 | {{ $_ := set $tcpPorts $name $config -}} 17 | {{- end -}} 18 | {{- end -}} 19 | 20 | {{- if (or $tcpPorts .Values.service.single) }} 21 | apiVersion: v1 22 | kind: Service 23 | metadata: 24 | name: {{ $fullname}}-internal 25 | namespace: {{ template "traefik.namespace" . }} 26 | {{- template "traefik.service-internal-metadata" . }} 27 | annotations: 28 | {{- with .Values.service.internal.annotations }} 29 | {{- toYaml . | nindent 4 }} 30 | {{- end }} 31 | spec: 32 | {{- template "traefik.service-internal-spec" . }} 33 | ports: 34 | {{- template "traefik.service-internal-ports" $tcpPorts }} 35 | {{- if .Values.service.single }} 36 | {{- template "traefik.service-internal-ports" $udpPorts }} 37 | {{- end }} 38 | {{- end }} 39 | 40 | {{- if (and $udpPorts (not .Values.service.single)) }} 41 | --- 42 | apiVersion: v1 43 | kind: Service 44 | metadata: 45 | name: {{ $fullname }}-internal-udp 46 | namespace: {{ template "traefik.namespace" . }} 47 | {{- template "traefik.service-internal-metadata" . }} 48 | annotations: 49 | {{- with .Values.service.internal.annotations }} 50 | {{- toYaml . | nindent 4 }} 51 | {{- end }} 52 | spec: 53 | {{- template "traefik.service-internal-spec" . }} 54 | ports: 55 | {{- template "traefik.service-internal-ports" $udpPorts }} 56 | {{- end }} 57 | 58 | {{- end -}} 59 | -------------------------------------------------------------------------------- /traefik/templates/_service.tpl: -------------------------------------------------------------------------------- 1 | {{- define "traefik.service-metadata" }} 2 | labels: 3 | {{- include "traefik.labels" . | nindent 4 -}} 4 | {{- with .Values.service.labels }} 5 | {{- toYaml . | nindent 4 }} 6 | {{- end }} 7 | {{- end }} 8 | 9 | {{- define "traefik.service-spec" -}} 10 | {{- $type := default "LoadBalancer" .Values.service.type }} 11 | type: {{ $type }} 12 | {{- with .Values.service.loadBalancerClass }} 13 | loadBalancerClass: {{ . }} 14 | {{- end}} 15 | {{- with .Values.service.spec }} 16 | {{- toYaml . | nindent 2 }} 17 | {{- end }} 18 | selector: 19 | {{- include "traefik.labelselector" . | nindent 4 }} 20 | {{- if eq $type "LoadBalancer" }} 21 | {{- with .Values.service.loadBalancerSourceRanges }} 22 | loadBalancerSourceRanges: 23 | {{- toYaml . | nindent 2 }} 24 | {{- end -}} 25 | {{- end -}} 26 | {{- with .Values.service.externalIPs }} 27 | externalIPs: 28 | {{- toYaml . | nindent 2 }} 29 | {{- end -}} 30 | {{- with .Values.service.ipFamilyPolicy }} 31 | ipFamilyPolicy: {{ . }} 32 | {{- end }} 33 | {{- with .Values.service.ipFamilies }} 34 | ipFamilies: 35 | {{- toYaml . | nindent 2 }} 36 | {{- end -}} 37 | {{- end }} 38 | 39 | {{- define "traefik.service-ports" }} 40 | {{- range $name, $config := . }} 41 | {{- if $config.expose }} 42 | - port: {{ default $config.port $config.exposedPort }} 43 | name: {{ $name | quote }} 44 | targetPort: {{ default $name $config.targetPort }} 45 | protocol: {{ default "TCP" $config.protocol }} 46 | {{- if $config.nodePort }} 47 | nodePort: {{ $config.nodePort }} 48 | {{- end }} 49 | {{- end }} 50 | {{- if $config.http3 }} 51 | {{- if $config.http3.enabled }} 52 | {{- $http3Port := default $config.exposedPort $config.http3.advertisedPort }} 53 | - port: {{ $http3Port }} 54 | name: "{{ $name }}-http3" 55 | targetPort: {{ default $config.port $config.targetPort }} 56 | protocol: UDP 57 | {{- if $config.nodePort }} 58 | nodePort: {{ $config.nodePort }} 59 | {{- end }} 60 | {{- end }} 61 | {{- end }} 62 | {{- end }} 63 | {{- end }} 64 | -------------------------------------------------------------------------------- /traefik/tests/poddisruptionbudget-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: PodDisruptionBudget configuration 2 | templates: 3 | - poddisruptionbudget.yaml 4 | capabilities: 5 | majorVersion: 1 6 | minorVersion: 16 7 | tests: 8 | - it: should be disabled by default 9 | asserts: 10 | - hasDocuments: 11 | count: 0 12 | - it: should have minAvailable set as int 13 | set: 14 | podDisruptionBudget: 15 | enabled: true 16 | minAvailable: 2 17 | asserts: 18 | - equal: 19 | path: spec.minAvailable 20 | value: 2 21 | - isNull: 22 | path: spec.maxUnavailable 23 | - it: should have maxUnavailable set as int 24 | set: 25 | podDisruptionBudget: 26 | enabled: true 27 | maxUnavailable: 1 28 | asserts: 29 | - equal: 30 | path: spec.maxUnavailable 31 | value: 1 32 | - isNull: 33 | path: spec.minAvailable 34 | - it: should have minAvailable set as percentage 35 | set: 36 | podDisruptionBudget: 37 | enabled: true 38 | minAvailable: 25% 39 | asserts: 40 | - equal: 41 | path: spec.minAvailable 42 | value: 25% 43 | - isNull: 44 | path: spec.maxUnavailable 45 | - it: should have maxUnavailable set as percentage 46 | set: 47 | podDisruptionBudget: 48 | enabled: true 49 | maxUnavailable: 33% 50 | asserts: 51 | - equal: 52 | path: spec.maxUnavailable 53 | value: 33% 54 | - isNull: 55 | path: spec.minAvailable 56 | - it: should use helm managed namespace as default behavior 57 | set: 58 | podDisruptionBudget: 59 | enabled: true 60 | asserts: 61 | - equal: 62 | path: metadata.namespace 63 | value: NAMESPACE 64 | - it: should accept overridden namespace 65 | set: 66 | namespaceOverride: "traefik-ns-override" 67 | podDisruptionBudget: 68 | enabled: true 69 | asserts: 70 | - equal: 71 | path: metadata.namespace 72 | value: "traefik-ns-override" 73 | -------------------------------------------------------------------------------- /traefik/templates/service.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.service.enabled -}} 2 | 3 | {{- $tcpPorts := dict -}} 4 | {{- $udpPorts := dict -}} 5 | {{- $exposedPorts := false -}} 6 | {{- range $name, $config := .Values.ports -}} 7 | {{- if $config.http3 -}} 8 | {{- if $config.http3.enabled -}} 9 | {{- if (not $config.tls.enabled) -}} 10 | {{- fail "ERROR: You cannot enable http3 without enabling tls" -}} 11 | {{- end -}} 12 | {{- end -}} 13 | {{- end -}} 14 | {{- if eq (toString $config.protocol) "UDP" -}} 15 | {{ $_ := set $udpPorts $name $config -}} 16 | {{- end -}} 17 | {{- if eq (toString (default "TCP" $config.protocol)) "TCP" -}} 18 | {{ $_ := set $tcpPorts $name $config -}} 19 | {{- end -}} 20 | {{- if (eq $config.expose true) -}} 21 | {{- $exposedPorts = true -}} 22 | {{- end -}} 23 | {{- end -}} 24 | 25 | {{- if (eq $exposedPorts false) -}} 26 | {{- fail "You need to expose at least one port or set enabled=false to service" -}} 27 | {{- end -}} 28 | 29 | {{- if and $exposedPorts (or $tcpPorts .Values.service.single) }} 30 | apiVersion: v1 31 | kind: Service 32 | metadata: 33 | name: {{ template "traefik.fullname" . }} 34 | namespace: {{ template "traefik.namespace" . }} 35 | {{- template "traefik.service-metadata" . }} 36 | annotations: 37 | {{- with (merge dict .Values.service.annotationsTCP .Values.service.annotations) }} 38 | {{- toYaml . | nindent 4 }} 39 | {{- end }} 40 | spec: 41 | {{- template "traefik.service-spec" . }} 42 | ports: 43 | {{- template "traefik.service-ports" $tcpPorts }} 44 | {{- if .Values.service.single }} 45 | {{- template "traefik.service-ports" $udpPorts }} 46 | {{- end }} 47 | {{- end }} 48 | 49 | {{- if and $exposedPorts (and $udpPorts (not .Values.service.single)) }} 50 | --- 51 | apiVersion: v1 52 | kind: Service 53 | metadata: 54 | name: {{ template "traefik.fullname" . }}-udp 55 | namespace: {{ template "traefik.namespace" . }} 56 | {{- template "traefik.service-metadata" . }} 57 | annotations: 58 | {{- with (merge dict .Values.service.annotationsUDP .Values.service.annotations) }} 59 | {{- toYaml . | nindent 4 }} 60 | {{- end }} 61 | spec: 62 | {{- template "traefik.service-spec" . }} 63 | ports: 64 | {{- template "traefik.service-ports" $udpPorts }} 65 | {{- end }} 66 | 67 | {{- end -}} 68 | -------------------------------------------------------------------------------- /traefik/tests/ingressclass-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: IngressClass configuration 2 | templates: 3 | - ingressclass.yaml 4 | tests: 5 | - it: should not provide an IngressClass when disabled 6 | set: 7 | ingressClass: 8 | enabled: false 9 | asserts: 10 | - hasDocuments: 11 | count: 0 12 | - it: should provide a default IngressClass by default and prefer v1 api 13 | asserts: 14 | - isKind: 15 | of: IngressClass 16 | - isAPIVersion: 17 | of: networking.k8s.io/v1 18 | - equal: 19 | path: metadata.annotations["ingressclass.kubernetes.io/is-default-class"] 20 | value: "true" 21 | - it: should be possible to provide a non-default IngressClass 22 | set: 23 | ingressClass: 24 | isDefaultClass: false 25 | asserts: 26 | - isKind: 27 | of: IngressClass 28 | - isAPIVersion: 29 | of: networking.k8s.io/v1 30 | - equal: 31 | path: metadata.annotations["ingressclass.kubernetes.io/is-default-class"] 32 | value: "false" 33 | - it: should provide an IngressClass with only v1beta1 api on Kubernetes v1.18 34 | capabilities: 35 | majorVersion: 1 36 | minorVersion: 18 37 | asserts: 38 | - isKind: 39 | of: IngressClass 40 | - isAPIVersion: 41 | of: networking.k8s.io/v1beta1 42 | - it: should workaround and provide an IngressClass with v1 with only Capability (#698) 43 | capabilities: 44 | majorVersion: 1 45 | minorVersion: 21 46 | patchVersion: 14-eks-6d3986b 47 | asserts: 48 | - isKind: 49 | of: IngressClass 50 | - isAPIVersion: 51 | of: networking.k8s.io/v1 52 | - it: should fail when asking to deploy IngressClass on Traefik < 2.3 53 | set: 54 | ingressClass: 55 | enabled: true 56 | chart: 57 | appVersion: v2.1.0 58 | asserts: 59 | - failedTemplate: 60 | errorMessage: "IngressClass cannot be used with Traefik < 2.3.0" 61 | - it: should fail when asking to deploy IngressClass on Kubernetes < v1.16 62 | capabilities: 63 | majorVersion: 1 64 | minorVersion: 15 65 | asserts: 66 | - failedTemplate: 67 | errorMessage: "You must use at least Kubernetes v1.16 with this Chart" 68 | -------------------------------------------------------------------------------- /traefik/tests/podsecuritypolicy-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: PodSecurityPolicy configuration 2 | templates: 3 | - rbac/podsecuritypolicy.yaml 4 | - rbac/clusterrole.yaml 5 | capabilities: 6 | majorVersion: 1 7 | minorVersion: 20 8 | tests: 9 | - it: should be disabled by default 10 | asserts: 11 | - hasDocuments: 12 | count: 0 13 | template: rbac/podsecuritypolicy.yaml 14 | - it: should throw an error when enabled on k8s >= v1.25 15 | capabilities: 16 | majorVersion: 1 17 | minorVersion: 25 18 | set: 19 | podSecurityPolicy: 20 | enabled: true 21 | asserts: 22 | - failedTemplate: 23 | errorMessage: "PodSecurityPolicy has been removed in Kubernetes v1.25+" 24 | template: rbac/podsecuritypolicy.yaml 25 | - it: should have privileged set to false 26 | set: 27 | podSecurityPolicy: 28 | enabled: true 29 | asserts: 30 | - equal: 31 | path: spec.privileged 32 | value: false 33 | template: rbac/podsecuritypolicy.yaml 34 | - it: should have hostNetwork set to false by default 35 | set: 36 | podSecurityPolicy: 37 | enabled: true 38 | asserts: 39 | - equal: 40 | path: spec.hostNetwork 41 | value: false 42 | template: rbac/podsecuritypolicy.yaml 43 | - it: should have hostNetwork set to true when enabled 44 | set: 45 | podSecurityPolicy: 46 | enabled: true 47 | hostNetwork: true 48 | asserts: 49 | - equal: 50 | path: spec.hostNetwork 51 | value: true 52 | template: rbac/podsecuritypolicy.yaml 53 | - it: should be enabled in clusterrole 54 | set: 55 | podSecurityPolicy: 56 | enabled: true 57 | asserts: 58 | - equal: 59 | path: rules[4].resources[0] 60 | value: podsecuritypolicies 61 | template: rbac/clusterrole.yaml 62 | - equal: 63 | path: rules[4].verbs[0] 64 | value: use 65 | template: rbac/clusterrole.yaml 66 | - it: should allow persistentVolumeClaim when persistence is enabled 67 | set: 68 | podSecurityPolicy: 69 | enabled: true 70 | persistence: 71 | enabled: true 72 | asserts: 73 | - equal: 74 | path: spec.volumes[5] 75 | value: persistentVolumeClaim 76 | template: rbac/podsecuritypolicy.yaml 77 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Testing Guide 2 | 3 | This Helm Chart requires extensive testing to ensure expected behavior are met for everyone. 4 | 5 | ## Requirements 6 | 7 | All tests are run using Docker; no further dependencies are required. 8 | 9 | ## Test Driven Development 10 | 11 | "TDD" practise (Test Driven Development) should be followed when adding a new feature or fixing a bug. 12 | 13 | It means that you are expected to: 14 | 15 | 1. Start by adding a test describing the expected behaviour, that should fails (either because the bug exists in initial state, or because the new feature had not been implemented), 16 | 2. Then, change the code according to your intent (fixing a bug, adding a feature or refactoring), 17 | 3. Finally, the test suite (including the new test you added earlier) must pass. 18 | 19 | ## Test Kinds 20 | 21 | Please note that this chart has the following kind of tests (see respective sections below for description): 22 | 23 | - [Unit Testing](#unit-testing) 24 | - [Static Testing](#static-testing) 25 | 26 | ### Unit Testing 27 | 28 | Unit test suite is run by invoking the make target `test`: `make test`. 29 | It is run by default on the CI. 30 | 31 | 32 | 33 | ### Static Testing 34 | 35 | The static test suite has the following properties: 36 | 37 | - Static tests are about linting the YAML files, shell scripts and Helm elements. It is also a set of verifications around versions, names, etc. 38 | - Static tests are fast to run, hence it must be run for each commit and pull requests and are considered blocking when failing. 39 | - Static test suite is run by invoking the make target `lint`: `make lint`. It is run by default on the CI. 40 | 41 | The static test suite is implemented with the tool [`ct` (Chart Testing)](https://github.com/helm/chart-testing): 42 | 43 | - The Docker image of `ct` is used to ensure all sub-dependencies (helm, kubectl, yamale, etc.) are met for an easier experience for contributor. 44 | - All configuration of `ct` and linters are stored in the directory `lint/`. In particular, the file `lint/ct.yaml` contains 45 | the `ct` configuration. 46 | - Version Increment Check is done against the against the original repository, with the branch `master`. This repository is added as an additional git remote named `traefik` by the make target `lint`. If you wish to temporarly change this behavior, please edit the files `Makefile` and `lint/ct.yaml`. 47 | -------------------------------------------------------------------------------- /traefik/tests/notes_test.yaml: -------------------------------------------------------------------------------- 1 | suite: NOTES.txt output 2 | templates: 3 | - NOTES.txt 4 | chart: 5 | appVersion: 2.3.0 6 | capabilities: 7 | majorVersion: 1 8 | minorVersion: 16 9 | tests: 10 | - it: should use helm managed namespace in release notes output 11 | set: 12 | rbac: 13 | namespaced: true 14 | asserts: 15 | - equalRaw: 16 | value: |2 17 | 18 | 19 | Traefik Proxy 2.3.0 has been deployed successfully 20 | on NAMESPACE namespace ! 21 | - it: should use helm managed namespace in release notes output 22 | set: 23 | namespaceOverride: "traefik-ns-override" 24 | asserts: 25 | - equalRaw: 26 | value: |2 27 | 28 | 29 | Traefik Proxy 2.3.0 has been deployed successfully 30 | on traefik-ns-override namespace ! 31 | - it: should use tag version in release notes output if set 32 | set: 33 | image: 34 | tag: v3.0 35 | asserts: 36 | - equalRaw: 37 | value: |2 38 | 39 | 40 | Traefik Proxy v3.0 has been deployed successfully 41 | on NAMESPACE namespace ! 42 | - it: should not display a warning when persistence and initContainer are enabled 43 | set: 44 | persistence: 45 | enabled: true 46 | deployment: 47 | initContainer: 48 | - name: volume-permissions 49 | image: busybox:1.35 50 | command: ["sh", "-c", "touch /data/acme.json && chmod -Rv 600 /data/* && chown 65532:65532 /data/acme.json"] 51 | volumeMounts: 52 | - name: data 53 | mountPath: /data 54 | asserts: 55 | - equalRaw: 56 | value: |2 57 | 58 | 59 | Traefik Proxy 2.3.0 has been deployed successfully 60 | on NAMESPACE namespace ! 61 | - it: should display warning when enabling persistence without initContainer 62 | set: 63 | persistence: 64 | enabled: true 65 | asserts: 66 | - equalRaw: 67 | value: | 68 | 69 | 70 | Traefik Proxy 2.3.0 has been deployed successfully 71 | on NAMESPACE namespace ! 72 | 73 | 🚨 When enabling persistence for certificates, permissions on acme.json can be 74 | lost when Traefik restarts. You can ensure correct permissions with an 75 | initContainer. See https://github.com/traefik/traefik-helm-chart/issues/396 for 76 | more info. 🚨 77 | -------------------------------------------------------------------------------- /traefik/templates/rbac/clusterrole.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.rbac.enabled -}} 2 | --- 3 | kind: ClusterRole 4 | apiVersion: rbac.authorization.k8s.io/v1 5 | metadata: 6 | name: {{ template "traefik.clusterRoleName" . }} 7 | labels: 8 | {{- include "traefik.labels" . | nindent 4 }} 9 | {{- range .Values.rbac.aggregateTo }} 10 | rbac.authorization.k8s.io/aggregate-to-{{ . }}: "true" 11 | {{- end }} 12 | rules: 13 | - apiGroups: 14 | - extensions 15 | - networking.k8s.io 16 | resources: 17 | - ingressclasses 18 | {{- if not .Values.rbac.namespaced }} 19 | - ingresses 20 | {{- end }} 21 | verbs: 22 | - get 23 | - list 24 | - watch 25 | {{- if not .Values.rbac.namespaced }} 26 | - apiGroups: 27 | - "" 28 | resources: 29 | - services 30 | - endpoints 31 | - secrets 32 | verbs: 33 | - get 34 | - list 35 | - watch 36 | {{- if .Values.providers.kubernetesIngress.enabled }} 37 | - apiGroups: 38 | - extensions 39 | - networking.k8s.io 40 | resources: 41 | - ingresses/status 42 | verbs: 43 | - update 44 | {{- end -}} 45 | {{- if .Values.providers.kubernetesCRD.enabled }} 46 | - apiGroups: 47 | - traefik.io 48 | - traefik.containo.us 49 | resources: 50 | - ingressroutes 51 | - ingressroutetcps 52 | - ingressrouteudps 53 | - middlewares 54 | - middlewaretcps 55 | - tlsoptions 56 | - tlsstores 57 | - traefikservices 58 | - serverstransports 59 | verbs: 60 | - get 61 | - list 62 | - watch 63 | {{- end -}} 64 | {{- if .Values.podSecurityPolicy.enabled }} 65 | - apiGroups: 66 | - policy 67 | resourceNames: 68 | - {{ template "traefik.fullname" . }} 69 | resources: 70 | - podsecuritypolicies 71 | verbs: 72 | - use 73 | {{- end -}} 74 | {{- if .Values.experimental.kubernetesGateway.enabled }} 75 | - apiGroups: 76 | - "" 77 | resources: 78 | - namespaces 79 | verbs: 80 | - list 81 | - watch 82 | - apiGroups: 83 | - gateway.networking.k8s.io 84 | resources: 85 | - gatewayclasses 86 | - gateways 87 | - httproutes 88 | - tcproutes 89 | - tlsroutes 90 | verbs: 91 | - get 92 | - list 93 | - watch 94 | - apiGroups: 95 | - gateway.networking.k8s.io 96 | resources: 97 | - gatewayclasses/status 98 | - gateways/status 99 | - httproutes/status 100 | - tcproutes/status 101 | - tlsroutes/status 102 | verbs: 103 | - update 104 | {{- end -}} 105 | {{- end -}} 106 | {{- end -}} 107 | -------------------------------------------------------------------------------- /traefik/tests/dashboard-ingressroute_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Dashboard IngressRoute configuration 2 | templates: 3 | - dashboard-ingressroute.yaml 4 | tests: 5 | - it: should allow disabling dashboard exposure using ingressRoute 6 | set: 7 | ingressRoute: 8 | dashboard: 9 | enabled: false 10 | asserts: 11 | - hasDocuments: 12 | count: 0 13 | - it: should have the expected default route match rule 14 | asserts: 15 | - equal: 16 | path: spec.routes[0].match 17 | value: PathPrefix(`/dashboard`) || PathPrefix(`/api`) 18 | - it: should support overwriting the route match rule 19 | set: 20 | ingressRoute: 21 | dashboard: 22 | matchRule: Host(`traefik.example.com`) 23 | asserts: 24 | - equal: 25 | path: spec.routes[0].match 26 | value: Host(`traefik.example.com`) 27 | - it: should have traefik as default entryPoints 28 | asserts: 29 | - equal: 30 | path: spec.entryPoints 31 | value: ["traefik"] 32 | - it: should support setting websecure as entryPoint 33 | set: 34 | ingressRoute: 35 | dashboard: 36 | entryPoints: ["websecure"] 37 | asserts: 38 | - equal: 39 | path: spec.entryPoints 40 | value: ["websecure"] 41 | - it: should support adding specific label on IngressRoute 42 | set: 43 | ingressRoute: 44 | dashboard: 45 | labels: 46 | foo: bar 47 | asserts: 48 | - equal: 49 | path: metadata.labels.foo 50 | value: bar 51 | - it: should not have middlewares by default 52 | asserts: 53 | - isNull: 54 | path: spec.routes[0].middlewares 55 | - it: should support adding middlewares 56 | set: 57 | ingressRoute: 58 | dashboard: 59 | middlewares: 60 | - name: traefik-dashboard-auth 61 | namespace: default 62 | asserts: 63 | - equal: 64 | path: spec.routes[0].middlewares 65 | value: 66 | - name: traefik-dashboard-auth 67 | namespace: default 68 | - it: should not have tls options by default 69 | asserts: 70 | - isNull: 71 | path: spec.tls 72 | - it: should support adding tls options 73 | set: 74 | ingressRoute: 75 | dashboard: 76 | tls: 77 | secretName: traefik-dashboard-auth 78 | options: 79 | name: tls-options 80 | namespace: default 81 | asserts: 82 | - equal: 83 | path: spec.tls 84 | value: 85 | secretName: traefik-dashboard-auth 86 | options: 87 | name: tls-options 88 | namespace: default 89 | -------------------------------------------------------------------------------- /traefik/tests/servicemonitor-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: ServiceMonitor configuration 2 | templates: 3 | - servicemonitor.yaml 4 | tests: 5 | - it: should not provide ServiceMonitor by default 6 | asserts: 7 | - hasDocuments: 8 | count: 0 9 | - it: should fail to provide ServiceMonitor without the API 10 | values: 11 | - ./values/servicemonitor.yaml 12 | asserts: 13 | - failedTemplate: 14 | errorMessage: "You have to deploy monitoring.coreos.com/v1 first" 15 | - it: should succeed to provide ServiceMonitor without the API when disabling API Check 16 | values: 17 | - ./values/servicemonitor.yaml 18 | set: 19 | metrics: 20 | prometheus: 21 | disableAPICheck: true 22 | asserts: 23 | - hasDocuments: 24 | count: 1 25 | - it: should successfully provide ServiceMonitor with example values 26 | values: 27 | - ./values/servicemonitor.yaml 28 | capabilities: 29 | apiVersions: 30 | - monitoring.coreos.com/v1 31 | asserts: 32 | - hasDocuments: 33 | count: 1 34 | - equal: 35 | path: spec.jobLabel 36 | value: another-label 37 | - contains: 38 | path: spec.endpoints 39 | content: 40 | port: metrics 41 | path: /metrics 42 | enableHttp2: true 43 | followRedirects: true 44 | honorLabels: true 45 | honorTimestamps: true 46 | scrapeTimeout: 5s 47 | interval: 30s 48 | metricRelabelings: 49 | - action: drop 50 | regex: ^fluentd_output_status_buffer_(oldest|newest)_.+ 51 | replacement: $1 52 | separator: ; 53 | sourceLabels: 54 | - __name__ 55 | relabelings: 56 | - action: replace 57 | regex: ^(.*)$ 58 | replacement: $1 59 | separator: ; 60 | sourceLabels: 61 | - __meta_kubernetes_pod_node_name 62 | targetLabel: nodename 63 | - equal: 64 | path: spec.namespaceSelector.any 65 | value: true 66 | - equal: 67 | path: spec.selector.matchLabels["app.kubernetes.io/name"] 68 | value: traefik 69 | - it: should provide ServiceMonitor pointing to metrics service, when prometheus.service.enabled is true 70 | capabilities: 71 | apiVersions: 72 | - monitoring.coreos.com/v1 73 | values: 74 | - ./values/servicemonitor.yaml 75 | set: 76 | metrics: 77 | prometheus: 78 | service: 79 | enabled: true 80 | asserts: 81 | - hasDocuments: 82 | count: 1 83 | - equal: 84 | path: spec.selector.matchLabels["app.kubernetes.io/component"] 85 | value: metrics 86 | -------------------------------------------------------------------------------- /traefik/tests/gateway-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Gateway configuration 2 | templates: 3 | - gateway.yaml 4 | tests: 5 | - it: should have one Gateway with the correct class and an http port 6 | set: 7 | experimental: 8 | kubernetesGateway: 9 | enabled: true 10 | asserts: 11 | - equal: 12 | path: spec.gatewayClassName 13 | value: "traefik" 14 | - equal: 15 | path: spec.listeners[0].port 16 | value: 8000 17 | - equal: 18 | path: metadata.namespace 19 | value: "NAMESPACE" 20 | - it: should have one Gateway with the correct class and an http port as well as an https port 21 | set: 22 | experimental: 23 | kubernetesGateway: 24 | enabled: true 25 | certificate: 26 | name: "my-name" 27 | group: "my-group" 28 | kind: "my-kind" 29 | asserts: 30 | - equal: 31 | path: spec.gatewayClassName 32 | value: "traefik" 33 | - equal: 34 | path: spec.listeners[0].port 35 | value: 8000 36 | - equal: 37 | path: spec.listeners[1].name 38 | value: websecure 39 | - equal: 40 | path: spec.listeners[1].port 41 | value: 8443 42 | - equal: 43 | path: spec.listeners[1].tls.certificateRefs[0].name 44 | value: "my-name" 45 | - equal: 46 | path: spec.listeners[1].tls.certificateRefs[0].group 47 | value: "my-group" 48 | - equal: 49 | path: spec.listeners[1].tls.certificateRefs[0].kind 50 | value: "my-kind" 51 | - it: should install Gateway in custom namespace 52 | set: 53 | experimental: 54 | kubernetesGateway: 55 | enabled: true 56 | namespace: "default" 57 | asserts: 58 | - equal: 59 | path: metadata.namespace 60 | value: "default" 61 | - it: should install Gateway in default namespace 62 | set: 63 | experimental: 64 | kubernetesGateway: 65 | enabled: true 66 | asserts: 67 | - equal: 68 | path: metadata.namespace 69 | value: "NAMESPACE" 70 | - it: should install Gateway in namespaceOverride 71 | set: 72 | experimental: 73 | kubernetesGateway: 74 | enabled: true 75 | namespaceOverride: "traefik-ns-override" 76 | asserts: 77 | - equal: 78 | path: metadata.namespace 79 | value: "traefik-ns-override" 80 | - it: should have one Gateway with the correct annotations 81 | set: 82 | experimental: 83 | kubernetesGateway: 84 | enabled: true 85 | gateway: 86 | enabled: true 87 | annotations: 88 | cert-manager.io/issuer: letsencrypt 89 | asserts: 90 | - equal: 91 | path: metadata.annotations 92 | value: 93 | cert-manager.io/issuer: letsencrypt 94 | -------------------------------------------------------------------------------- /traefik/templates/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.metrics.prometheus }} 2 | {{- if .Values.metrics.prometheus.serviceMonitor }} 3 | {{- if (not (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1")) }} 4 | {{- if (not (.Values.metrics.prometheus.disableAPICheck)) }} 5 | {{- fail "ERROR: You have to deploy monitoring.coreos.com/v1 first" }} 6 | {{- end }} 7 | {{- end }} 8 | apiVersion: monitoring.coreos.com/v1 9 | kind: ServiceMonitor 10 | metadata: 11 | name: {{ template "traefik.fullname" . }} 12 | {{- with .Values.metrics.prometheus.serviceMonitor.namespace }} 13 | namespace: {{ . }} 14 | {{- end }} 15 | labels: 16 | {{- if (.Values.metrics.prometheus.service).enabled }} 17 | {{- include "traefik.metricsservicelabels" . | nindent 4 }} 18 | {{- else }} 19 | {{- include "traefik.labels" . | nindent 4 }} 20 | {{- end }} 21 | {{- with .Values.metrics.prometheus.serviceMonitor.additionalLabels }} 22 | {{- toYaml . | nindent 4 }} 23 | {{- end }} 24 | spec: 25 | jobLabel: {{ .Values.metrics.prometheus.serviceMonitor.jobLabel | default .Release.Name }} 26 | endpoints: 27 | - port: metrics 28 | path: /{{ .Values.metrics.prometheus.entryPoint }} 29 | {{- with .Values.metrics.prometheus.serviceMonitor.honorLabels }} 30 | honorLabels: {{ . }} 31 | {{- end }} 32 | {{- with .Values.metrics.prometheus.serviceMonitor.honorTimestamps }} 33 | honorTimestamps: {{ . }} 34 | {{- end }} 35 | {{- with .Values.metrics.prometheus.serviceMonitor.enableHttp2 }} 36 | enableHttp2: {{ . }} 37 | {{- end }} 38 | {{- with .Values.metrics.prometheus.serviceMonitor.followRedirects }} 39 | followRedirects: {{ . }} 40 | {{- end }} 41 | {{- with .Values.metrics.prometheus.serviceMonitor.interval }} 42 | interval: {{ . }} 43 | {{- end }} 44 | {{- with .Values.metrics.prometheus.serviceMonitor.scrapeTimeout }} 45 | scrapeTimeout: {{ . }} 46 | {{- end }} 47 | {{- if .Values.metrics.prometheus.serviceMonitor.metricRelabelings }} 48 | metricRelabelings: 49 | {{ tpl (toYaml .Values.metrics.prometheus.serviceMonitor.metricRelabelings | indent 6) . }} 50 | {{- end }} 51 | {{- if .Values.metrics.prometheus.serviceMonitor.relabelings }} 52 | relabelings: 53 | {{ toYaml .Values.metrics.prometheus.serviceMonitor.relabelings | indent 6 }} 54 | {{- end }} 55 | {{- if .Values.metrics.prometheus.serviceMonitor.namespaceSelector }} 56 | namespaceSelector: 57 | {{ toYaml .Values.metrics.prometheus.serviceMonitor.namespaceSelector | indent 4 -}} 58 | {{ else }} 59 | namespaceSelector: 60 | matchNames: 61 | - {{ template "traefik.namespace" . }} 62 | {{- end }} 63 | selector: 64 | matchLabels: 65 | {{- if (.Values.metrics.prometheus.service).enabled }} 66 | {{- include "traefik.metricslabelselector" . | nindent 6 }} 67 | {{- else }} 68 | {{- include "traefik.labelselector" . | nindent 6 }} 69 | {{- end }} 70 | {{- end }} 71 | {{- end }} 72 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Charts 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | env: 9 | tag_prefix: v 10 | 11 | jobs: 12 | test: 13 | uses: "traefik/traefik-helm-chart/.github/workflows/test.yml@master" 14 | release: 15 | needs: test 16 | runs-on: ubuntu-latest 17 | steps: 18 | 19 | - name: Checkout 20 | uses: actions/checkout@v3 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Configure Git 25 | run: | 26 | git config user.name "$GITHUB_ACTOR" 27 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 28 | git config --global --add safe.directory /charts 29 | 30 | - name: Copy LICENSE and README.md for packaging 31 | run: | 32 | cp ./README.md ./traefik/README.md 33 | cp ./LICENSE ./traefik/LICENSE 34 | 35 | - name: Generate default static install 36 | run: | 37 | kustomize build traefik/crds > traefik.yaml 38 | helm template traefik ./traefik -n traefik >> traefik.yaml 39 | 40 | - name: Get chart verison 41 | id: chart_version 42 | run: | 43 | echo "CHART_VERSION=$(cat traefik/Chart.yaml | awk -F"[ ',]+" '/version:/{print $2}')" >> $GITHUB_OUTPUT 44 | 45 | - name: Check if tag exists 46 | id: tag_exists 47 | run: | 48 | TAG_EXISTS=true 49 | if ! [ $(git tag -l "${{ env.tag_prefix }}${{ steps.chart_version.outputs.CHART_VERSION }}") ]; then 50 | TAG_EXISTS=false 51 | fi 52 | echo TAG_EXISTS=$TAG_EXISTS >> $GITHUB_OUTPUT 53 | 54 | - name: Tag release 55 | id: tag_version 56 | uses: mathieudutour/github-tag-action@v6.1 57 | with: 58 | github_token: ${{ secrets.GITHUB_TOKEN }} 59 | custom_tag: ${{ steps.chart_version.outputs.CHART_VERSION }} 60 | tag_prefix: ${{ env.tag_prefix }} 61 | if: steps.tag_exists.outputs.TAG_EXISTS == 'false' 62 | 63 | - name: Create release 64 | uses: ncipollo/release-action@v1 65 | with: 66 | tag: ${{ steps.tag_version.outputs.new_tag }} 67 | name: ${{ steps.tag_version.outputs.new_tag }} 68 | body: ${{ steps.tag_version.outputs.changelog }} 69 | prerelease: ${{ contains(steps.chart_version.outputs.CHART_VERSION, '-') }} 70 | artifacts: "traefik.yaml" 71 | if: steps.tag_exists.outputs.TAG_EXISTS == 'false' 72 | 73 | - name: Publish Helm chart 74 | uses: stefanprodan/helm-gh-pages@master 75 | with: 76 | token: ${{ secrets.CHARTS_TOKEN }} 77 | charts_dir: . 78 | charts_url: https://traefik.github.io/charts 79 | owner: traefik 80 | repository: charts 81 | branch: master 82 | target_dir: traefik 83 | index_dir: . 84 | commit_username: traefiker 85 | commit_email: 30906710+traefiker@users.noreply.github.com 86 | if: steps.tag_exists.outputs.TAG_EXISTS == 'false' 87 | -------------------------------------------------------------------------------- /traefik/crds/traefik.io_middlewaretcps.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.6.2 8 | creationTimestamp: null 9 | name: middlewaretcps.traefik.io 10 | spec: 11 | group: traefik.io 12 | names: 13 | kind: MiddlewareTCP 14 | listKind: MiddlewareTCPList 15 | plural: middlewaretcps 16 | singular: middlewaretcp 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: 'MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. 23 | More info: https://doc.traefik.io/traefik/v2.10/middlewares/overview/' 24 | properties: 25 | apiVersion: 26 | description: 'APIVersion defines the versioned schema of this representation 27 | of an object. Servers should convert recognized schemas to the latest 28 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 29 | type: string 30 | kind: 31 | description: 'Kind is a string value representing the REST resource this 32 | object represents. Servers may infer this from the endpoint the client 33 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 34 | type: string 35 | metadata: 36 | type: object 37 | spec: 38 | description: MiddlewareTCPSpec defines the desired state of a MiddlewareTCP. 39 | properties: 40 | inFlightConn: 41 | description: InFlightConn defines the InFlightConn middleware configuration. 42 | properties: 43 | amount: 44 | description: Amount defines the maximum amount of allowed simultaneous 45 | connections. The middleware closes the connection if there are 46 | already amount connections opened. 47 | format: int64 48 | type: integer 49 | type: object 50 | ipWhiteList: 51 | description: IPWhiteList defines the IPWhiteList middleware configuration. 52 | properties: 53 | sourceRange: 54 | description: SourceRange defines the allowed IPs (or ranges of 55 | allowed IPs by using CIDR notation). 56 | items: 57 | type: string 58 | type: array 59 | type: object 60 | type: object 61 | required: 62 | - metadata 63 | - spec 64 | type: object 65 | served: true 66 | storage: true 67 | status: 68 | acceptedNames: 69 | kind: "" 70 | plural: "" 71 | conditions: [] 72 | storedVersions: [] 73 | -------------------------------------------------------------------------------- /traefik/crds/traefik.containo.us_middlewaretcps.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.6.2 8 | creationTimestamp: null 9 | name: middlewaretcps.traefik.containo.us 10 | spec: 11 | group: traefik.containo.us 12 | names: 13 | kind: MiddlewareTCP 14 | listKind: MiddlewareTCPList 15 | plural: middlewaretcps 16 | singular: middlewaretcp 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: 'MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. 23 | More info: https://doc.traefik.io/traefik/v2.9/middlewares/overview/' 24 | properties: 25 | apiVersion: 26 | description: 'APIVersion defines the versioned schema of this representation 27 | of an object. Servers should convert recognized schemas to the latest 28 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 29 | type: string 30 | kind: 31 | description: 'Kind is a string value representing the REST resource this 32 | object represents. Servers may infer this from the endpoint the client 33 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 34 | type: string 35 | metadata: 36 | type: object 37 | spec: 38 | description: MiddlewareTCPSpec defines the desired state of a MiddlewareTCP. 39 | properties: 40 | inFlightConn: 41 | description: InFlightConn defines the InFlightConn middleware configuration. 42 | properties: 43 | amount: 44 | description: Amount defines the maximum amount of allowed simultaneous 45 | connections. The middleware closes the connection if there are 46 | already amount connections opened. 47 | format: int64 48 | type: integer 49 | type: object 50 | ipWhiteList: 51 | description: IPWhiteList defines the IPWhiteList middleware configuration. 52 | properties: 53 | sourceRange: 54 | description: SourceRange defines the allowed IPs (or ranges of 55 | allowed IPs by using CIDR notation). 56 | items: 57 | type: string 58 | type: array 59 | type: object 60 | type: object 61 | required: 62 | - metadata 63 | - spec 64 | type: object 65 | served: true 66 | storage: true 67 | status: 68 | acceptedNames: 69 | kind: "" 70 | plural: "" 71 | conditions: [] 72 | storedVersions: [] 73 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Create a report to help us improve. 3 | labels: ['status/0-needs-triage'] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | ### How to write a good bug report? 9 | 10 | - Respect the issue template as much as possible. 11 | - The title should be short and descriptive. 12 | - Explain the conditions which led you to report this issue: the context. 13 | - The context should lead to something, an idea or a problem that you’re facing. 14 | - Remain clear and concise. 15 | - Format your messages to help the reader focus on what matters and understand the structure of your message, use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown) 16 | 17 | - type: checkboxes 18 | id: terms 19 | attributes: 20 | label: Welcome! 21 | options: 22 | - label: Yes, I've searched similar issues on [GitHub](https://github.com/traefik/traefik-helm-chart/issues) and didn't find any. 23 | required: true 24 | - label: Yes, I've searched similar issues on the [Traefik community forum](https://community.traefik.io) and didn't find any. 25 | required: true 26 | 27 | - type: input 28 | attributes: 29 | label: What version of the Traefik's Helm Chart are you using? 30 | description: | 31 | `latest` is not considered as a valid version. 32 | We need a release number! 33 | placeholder: Your version here. 34 | validations: 35 | required: true 36 | 37 | - type: input 38 | attributes: 39 | label: What version of Traefik are you using? 40 | description: | 41 | `latest` is not considered as a valid version. 42 | We need a release number! 43 | placeholder: Your version here. 44 | validations: 45 | required: true 46 | 47 | - type: textarea 48 | attributes: 49 | label: What did you do? 50 | description: Use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown) if needed. 51 | placeholder: What did you do? 52 | validations: 53 | required: true 54 | 55 | - type: textarea 56 | attributes: 57 | label: What did you see instead? 58 | description: Use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown) if needed. 59 | placeholder: What did you see instead? 60 | validations: 61 | required: true 62 | 63 | - type: textarea 64 | attributes: 65 | label: What is your environment & configuration? 66 | description: | 67 | platform, arguments, YAML, TOML, platform, etc. 68 | 69 | Use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown) if needed. 70 | placeholder: Add information here. 71 | validations: 72 | required: true 73 | 74 | - type: textarea 75 | attributes: 76 | label: Additional Information 77 | description: Use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown) if needed. 78 | placeholder: Add information here. 79 | render: shell 80 | validations: 81 | required: false 82 | -------------------------------------------------------------------------------- /traefik/Guidelines.md: -------------------------------------------------------------------------------- 1 | # Traefik Helm Chart Guidelines 2 | 3 | This document outlines the guidelines for developing, managing and extending the Traefik helm chart. 4 | 5 | This Helm Chart is documented using field description from comments with [helm-docs](https://github.com/norwoodj/helm-docs). 6 | 7 | Optionallity 8 | All non-critical features (Features not mandatory to starting Traefik) in the helm chart must be optional. All non-critical features should be disabled (commented out) in the values.yaml file. All optional non-critical features should be disabled (commented out) in the values.yaml file, and have a comment # (Optional) in the line above. This allows minimal configuration, and ease of extension. 9 | 10 | ## Feature Example 11 | 12 | ```yaml 13 | image: 14 | # -- Traefik image host registry 15 | registry: docker.io 16 | ``` 17 | 18 | This feature is expected and therefore is defined clearly in the values.yaml file. 19 | 20 | ## Optional Feature Example 21 | 22 | ```yaml 23 | # storage: 24 | # controlNode: 25 | # type: emptyDir 26 | ``` 27 | 28 | This feature is optional, non-critical, and therefore is commented out by default in the values.yaml file. 29 | 30 | To allow this, template blocks that use this need to recursively test for existence of values before using them: 31 | 32 | ```yaml 33 | {{- if .Values.storage}} 34 | {{- if .Values.storage.controlNode }} 35 | //code 36 | {{ .Values.storage.controlNode.type }} 37 | {{- end }} 38 | {{- end }} 39 | ``` 40 | 41 | The non-critical feature defaults should be populated so that they can be enabled by simply uncommenting the section in the values.yaml file. 42 | 43 | ## Optional Non-Critical Feature Example 44 | 45 | ```yaml 46 | # storage: 47 | # controlNode: 48 | # type: emptyDir 49 | # # (Optional) 50 | # # volume: 1Gi 51 | ``` 52 | 53 | The volume option is clearly optional, and non-critical. It is commented out (apart from the storage section comment block), and is also preceeded by a comment of # (Optional) in the preceeding line. This facilitates configuration, when the storage section is uncommented, the optional features are still disabled by default. 54 | 55 | Similar to non-critical feaures, these options need to be tested for existance before use in the template. 56 | 57 | Note 58 | There can be optional values in critical features. These should just be added as an uncommented non-critical feature: 59 | 60 | ```yaml 61 | image: 62 | name: traefik 63 | tag: 2.0.0 64 | # (Optional) 65 | # pullPolicy: IfNotPresent 66 | ``` 67 | 68 | Also, the first value under the primary value key does not require an optional comment: 69 | 70 | ```yaml 71 | # ports: 72 | # http: 80 73 | # # (Optional) 74 | # # https: 443 75 | ``` 76 | 77 | This is because if the main subkey is not defined, the entirety of the feature is optional. 78 | 79 | ## Whitespace 80 | 81 | Extra whitespace is to be avoided in templating. Conditionals should chomp whitespace: 82 | 83 | ```yaml 84 | {{- if .Values }} 85 | {{- end }} 86 | ``` 87 | 88 | There should be an empty commented line between each primary key in the values.yaml file to separate features from each other. 89 | 90 | ## Values YAML Design 91 | 92 | The values.yaml file is designed to be user-friendly. It does not have to resemble the templated configuration if it is not conducive. Similarly, value names to not have to correspond to fields in the tempate if it is not condusive. 93 | -------------------------------------------------------------------------------- /traefik/tests/tlsoption_test.yaml: -------------------------------------------------------------------------------- 1 | suite: TlsOption configuration 2 | templates: 3 | - tlsoption.yaml 4 | tests: 5 | - it: should use helm managed namespace as default behavior 6 | set: 7 | tlsOptions: 8 | default: 9 | labels: 10 | foo: bar 11 | asserts: 12 | - equal: 13 | path: metadata.namespace 14 | value: NAMESPACE 15 | - it: should set tlsoption name 16 | set: 17 | tlsOptions: 18 | default: 19 | labels: 20 | foo: bar 21 | asserts: 22 | - equal: 23 | path: metadata.name 24 | value: default 25 | - it: should set additional labels 26 | set: 27 | tlsOptions: 28 | default: 29 | labels: 30 | label: label 31 | asserts: 32 | - equal: 33 | path: metadata.labels.label 34 | value: label 35 | - it: should set cipherSuites 36 | set: 37 | tlsOptions: 38 | default: 39 | labels: 40 | cipherSuites: 41 | - cipherSuite 42 | asserts: 43 | - equal: 44 | path: spec.cipherSuites[0] 45 | value: cipherSuite 46 | - it: should set alpnProtocols 47 | set: 48 | tlsOptions: 49 | default: 50 | labels: 51 | alpnProtocols: 52 | - alpnProtocol 53 | asserts: 54 | - equal: 55 | path: spec.alpnProtocols[0] 56 | value: alpnProtocol 57 | - it: should set clientAuthConfig 58 | set: 59 | tlsOptions: 60 | default: 61 | labels: 62 | clientAuth: 63 | clientAuthType: clientAuthType 64 | asserts: 65 | - equal: 66 | path: spec.clientAuth 67 | value: 68 | clientAuthType: clientAuthType 69 | - it: should set curvePreferences 70 | set: 71 | tlsOptions: 72 | default: 73 | labels: 74 | curvePreferences: 75 | - curvePreference 76 | asserts: 77 | - equal: 78 | path: spec.curvePreferences[0] 79 | value: curvePreference 80 | - it: should set minVersion 81 | set: 82 | tlsOptions: 83 | default: 84 | labels: 85 | minVersion: minVersion 86 | asserts: 87 | - equal: 88 | path: spec.minVersion 89 | value: minVersion 90 | - it: should set maxVersion 91 | set: 92 | tlsOptions: 93 | default: 94 | labels: 95 | maxVersion: maxVersion 96 | asserts: 97 | - equal: 98 | path: spec.maxVersion 99 | value: maxVersion 100 | - it: should set preferServerCipherSuites 101 | set: 102 | tlsOptions: 103 | default: 104 | labels: 105 | preferServerCipherSuites: true 106 | asserts: 107 | - equal: 108 | path: spec.preferServerCipherSuites 109 | value: true 110 | - it: should set sniStrict 111 | set: 112 | tlsOptions: 113 | default: 114 | labels: 115 | sniStrict: true 116 | asserts: 117 | - equal: 118 | path: spec.sniStrict 119 | value: true 120 | - it: should render config without labels 121 | chart: 122 | version: 1.0.0 123 | set: 124 | tlsOptions: 125 | default: 126 | minVersion: minVersion 127 | asserts: 128 | - equal: 129 | path: metadata 130 | value: 131 | name: default 132 | namespace: NAMESPACE 133 | labels: 134 | app.kubernetes.io/instance: RELEASE-NAME-NAMESPACE 135 | app.kubernetes.io/managed-by: Helm 136 | app.kubernetes.io/name: traefik 137 | helm.sh/chart: traefik-1.0.0 138 | - equal: 139 | path: spec 140 | value: 141 | minVersion: minVersion 142 | -------------------------------------------------------------------------------- /traefik/crds/traefik.containo.us_ingressrouteudps.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.6.2 8 | creationTimestamp: null 9 | name: ingressrouteudps.traefik.containo.us 10 | spec: 11 | group: traefik.containo.us 12 | names: 13 | kind: IngressRouteUDP 14 | listKind: IngressRouteUDPList 15 | plural: ingressrouteudps 16 | singular: ingressrouteudp 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: IngressRouteUDP is a CRD implementation of a Traefik UDP Router. 23 | properties: 24 | apiVersion: 25 | description: 'APIVersion defines the versioned schema of this representation 26 | of an object. Servers should convert recognized schemas to the latest 27 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 28 | type: string 29 | kind: 30 | description: 'Kind is a string value representing the REST resource this 31 | object represents. Servers may infer this from the endpoint the client 32 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 33 | type: string 34 | metadata: 35 | type: object 36 | spec: 37 | description: IngressRouteUDPSpec defines the desired state of a IngressRouteUDP. 38 | properties: 39 | entryPoints: 40 | description: 'EntryPoints defines the list of entry point names to 41 | bind to. Entry points have to be configured in the static configuration. 42 | More info: https://doc.traefik.io/traefik/v2.9/routing/entrypoints/ 43 | Default: all.' 44 | items: 45 | type: string 46 | type: array 47 | routes: 48 | description: Routes defines the list of routes. 49 | items: 50 | description: RouteUDP holds the UDP route configuration. 51 | properties: 52 | services: 53 | description: Services defines the list of UDP services. 54 | items: 55 | description: ServiceUDP defines an upstream UDP service to 56 | proxy traffic to. 57 | properties: 58 | name: 59 | description: Name defines the name of the referenced Kubernetes 60 | Service. 61 | type: string 62 | namespace: 63 | description: Namespace defines the namespace of the referenced 64 | Kubernetes Service. 65 | type: string 66 | port: 67 | anyOf: 68 | - type: integer 69 | - type: string 70 | description: Port defines the port of a Kubernetes Service. 71 | This can be a reference to a named port. 72 | x-kubernetes-int-or-string: true 73 | weight: 74 | description: Weight defines the weight used when balancing 75 | requests between multiple Kubernetes Service. 76 | type: integer 77 | required: 78 | - name 79 | - port 80 | type: object 81 | type: array 82 | type: object 83 | type: array 84 | required: 85 | - routes 86 | type: object 87 | required: 88 | - metadata 89 | - spec 90 | type: object 91 | served: true 92 | storage: true 93 | status: 94 | acceptedNames: 95 | kind: "" 96 | plural: "" 97 | conditions: [] 98 | storedVersions: [] 99 | -------------------------------------------------------------------------------- /traefik/crds/traefik.io_tlsstores.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.6.2 8 | creationTimestamp: null 9 | name: tlsstores.traefik.io 10 | spec: 11 | group: traefik.io 12 | names: 13 | kind: TLSStore 14 | listKind: TLSStoreList 15 | plural: tlsstores 16 | singular: tlsstore 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: 'TLSStore is the CRD implementation of a Traefik TLS Store. For 23 | the time being, only the TLSStore named default is supported. This means 24 | that you cannot have two stores that are named default in different Kubernetes 25 | namespaces. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#certificates-stores' 26 | properties: 27 | apiVersion: 28 | description: 'APIVersion defines the versioned schema of this representation 29 | of an object. Servers should convert recognized schemas to the latest 30 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 31 | type: string 32 | kind: 33 | description: 'Kind is a string value representing the REST resource this 34 | object represents. Servers may infer this from the endpoint the client 35 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: TLSStoreSpec defines the desired state of a TLSStore. 41 | properties: 42 | certificates: 43 | description: Certificates is a list of secret names, each secret holding 44 | a key/certificate pair to add to the store. 45 | items: 46 | description: Certificate holds a secret name for the TLSStore resource. 47 | properties: 48 | secretName: 49 | description: SecretName is the name of the referenced Kubernetes 50 | Secret to specify the certificate details. 51 | type: string 52 | required: 53 | - secretName 54 | type: object 55 | type: array 56 | defaultCertificate: 57 | description: DefaultCertificate defines the default certificate configuration. 58 | properties: 59 | secretName: 60 | description: SecretName is the name of the referenced Kubernetes 61 | Secret to specify the certificate details. 62 | type: string 63 | required: 64 | - secretName 65 | type: object 66 | defaultGeneratedCert: 67 | description: DefaultGeneratedCert defines the default generated certificate 68 | configuration. 69 | properties: 70 | domain: 71 | description: Domain is the domain definition for the DefaultCertificate. 72 | properties: 73 | main: 74 | description: Main defines the main domain name. 75 | type: string 76 | sans: 77 | description: SANs defines the subject alternative domain names. 78 | items: 79 | type: string 80 | type: array 81 | type: object 82 | resolver: 83 | description: Resolver is the name of the resolver that will be 84 | used to issue the DefaultCertificate. 85 | type: string 86 | type: object 87 | type: object 88 | required: 89 | - metadata 90 | - spec 91 | type: object 92 | served: true 93 | storage: true 94 | status: 95 | acceptedNames: 96 | kind: "" 97 | plural: "" 98 | conditions: [] 99 | storedVersions: [] 100 | -------------------------------------------------------------------------------- /traefik/crds/traefik.containo.us_tlsstores.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.6.2 8 | creationTimestamp: null 9 | name: tlsstores.traefik.containo.us 10 | spec: 11 | group: traefik.containo.us 12 | names: 13 | kind: TLSStore 14 | listKind: TLSStoreList 15 | plural: tlsstores 16 | singular: tlsstore 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: 'TLSStore is the CRD implementation of a Traefik TLS Store. For 23 | the time being, only the TLSStore named default is supported. This means 24 | that you cannot have two stores that are named default in different Kubernetes 25 | namespaces. More info: https://doc.traefik.io/traefik/v2.9/https/tls/#certificates-stores' 26 | properties: 27 | apiVersion: 28 | description: 'APIVersion defines the versioned schema of this representation 29 | of an object. Servers should convert recognized schemas to the latest 30 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 31 | type: string 32 | kind: 33 | description: 'Kind is a string value representing the REST resource this 34 | object represents. Servers may infer this from the endpoint the client 35 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: TLSStoreSpec defines the desired state of a TLSStore. 41 | properties: 42 | certificates: 43 | description: Certificates is a list of secret names, each secret holding 44 | a key/certificate pair to add to the store. 45 | items: 46 | description: Certificate holds a secret name for the TLSStore resource. 47 | properties: 48 | secretName: 49 | description: SecretName is the name of the referenced Kubernetes 50 | Secret to specify the certificate details. 51 | type: string 52 | required: 53 | - secretName 54 | type: object 55 | type: array 56 | defaultCertificate: 57 | description: DefaultCertificate defines the default certificate configuration. 58 | properties: 59 | secretName: 60 | description: SecretName is the name of the referenced Kubernetes 61 | Secret to specify the certificate details. 62 | type: string 63 | required: 64 | - secretName 65 | type: object 66 | defaultGeneratedCert: 67 | description: DefaultGeneratedCert defines the default generated certificate 68 | configuration. 69 | properties: 70 | domain: 71 | description: Domain is the domain definition for the DefaultCertificate. 72 | properties: 73 | main: 74 | description: Main defines the main domain name. 75 | type: string 76 | sans: 77 | description: SANs defines the subject alternative domain names. 78 | items: 79 | type: string 80 | type: array 81 | type: object 82 | resolver: 83 | description: Resolver is the name of the resolver that will be 84 | used to issue the DefaultCertificate. 85 | type: string 86 | type: object 87 | type: object 88 | required: 89 | - metadata 90 | - spec 91 | type: object 92 | served: true 93 | storage: true 94 | status: 95 | acceptedNames: 96 | kind: "" 97 | plural: "" 98 | conditions: [] 99 | storedVersions: [] 100 | -------------------------------------------------------------------------------- /traefik/tests/daemonset-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: DaemonSet configuration 2 | templates: 3 | - daemonset.yaml 4 | tests: 5 | - it: should have a rollingUpdate strategy with default values on k8s > 1.21 6 | capabilities: 7 | majorVersion: 1 8 | minorVersion: 21 9 | set: 10 | deployment: 11 | kind: DaemonSet 12 | asserts: 13 | - equal: 14 | path: spec.updateStrategy.type 15 | value: RollingUpdate 16 | - equal: 17 | path: spec.updateStrategy.rollingUpdate.maxUnavailable 18 | value: 0 19 | - equal: 20 | path: spec.updateStrategy.rollingUpdate.maxSurge 21 | value: 1 22 | - it: should have annotations with specified values 23 | set: 24 | deployment: 25 | kind: DaemonSet 26 | annotations: 27 | traefik/powpow: annotations 28 | podAnnotations: 29 | traefik/powpow: podAnnotations 30 | asserts: 31 | - equal: 32 | path: metadata.annotations.traefik/powpow 33 | value: annotations 34 | - equal: 35 | path: spec.template.metadata.annotations.traefik/powpow 36 | value: podAnnotations 37 | - it: should have labels with specified values 38 | set: 39 | deployment: 40 | kind: DaemonSet 41 | labels: 42 | traefik/powpow: labels 43 | podLabels: 44 | traefik/powpow: podLabels 45 | asserts: 46 | - equal: 47 | path: metadata.labels.traefik/powpow 48 | value: labels 49 | - equal: 50 | path: spec.template.metadata.labels.traefik/powpow 51 | value: podLabels 52 | - it: should have minReadySeconds with specified value 53 | set: 54 | deployment: 55 | kind: DaemonSet 56 | minReadySeconds: 30 57 | asserts: 58 | - equal: 59 | path: spec.minReadySeconds 60 | value: 30 61 | - it: should have revisionHistoryLimit with specified value 62 | set: 63 | deployment: 64 | kind: DaemonSet 65 | revisionHistoryLimit: 1 66 | asserts: 67 | - equal: 68 | path: spec.revisionHistoryLimit 69 | value: 1 70 | - it: should have a preStop hook with specified values 71 | set: 72 | deployment: 73 | kind: DaemonSet 74 | lifecycle: 75 | preStop: 76 | exec: 77 | command: ["/bin/sh", "-c", "sleep 40"] 78 | asserts: 79 | - equal: 80 | path: spec.template.spec.containers[0].lifecycle.preStop.exec.command 81 | value: ["/bin/sh", "-c", "sleep 40"] 82 | - it: should have a postStart hook with specified values 83 | set: 84 | deployment: 85 | kind: DaemonSet 86 | lifecycle: 87 | postStart: 88 | httpGet: 89 | path: /ping 90 | port: 9000 91 | host: localhost 92 | scheme: HTTP 93 | asserts: 94 | - equal: 95 | path: spec.template.spec.containers[0].lifecycle.postStart.httpGet.path 96 | value: /ping 97 | - equal: 98 | path: spec.template.spec.containers[0].lifecycle.postStart.httpGet.port 99 | value: 9000 100 | - equal: 101 | path: spec.template.spec.containers[0].lifecycle.postStart.httpGet.host 102 | value: localhost 103 | - equal: 104 | path: spec.template.spec.containers[0].lifecycle.postStart.httpGet.scheme 105 | value: HTTP 106 | - it: should fail when hostNetwork and default maxUnavailable 0 107 | set: 108 | deployment: 109 | kind: DaemonSet 110 | updateStrategy: 111 | type: RollingUpdate 112 | rollingUpdate: 113 | maxUnavailable: 0 114 | hostNetwork: true 115 | asserts: 116 | - failedTemplate: 117 | errorMessage: "maxUnavailable should be greater than 1 when using hostNetwork." 118 | - it: should have an OnDelete updateStrategy when set 119 | set: 120 | deployment: 121 | kind: DaemonSet 122 | updateStrategy: 123 | type: OnDelete 124 | asserts: 125 | - equal: 126 | path: spec.updateStrategy.type 127 | value: OnDelete 128 | - it: should use helm managed namespace as default behavior 129 | set: 130 | deployment: 131 | kind: DaemonSet 132 | asserts: 133 | - equal: 134 | path: metadata.namespace 135 | value: NAMESPACE 136 | - it: should accept overridden namespace 137 | set: 138 | namespaceOverride: "traefik-ns-override" 139 | deployment: 140 | kind: DaemonSet 141 | asserts: 142 | - equal: 143 | path: metadata.namespace 144 | value: "traefik-ns-override" 145 | -------------------------------------------------------------------------------- /traefik/crds/traefik.io_ingressrouteudps.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.6.2 8 | creationTimestamp: null 9 | name: ingressrouteudps.traefik.io 10 | spec: 11 | group: traefik.io 12 | names: 13 | kind: IngressRouteUDP 14 | listKind: IngressRouteUDPList 15 | plural: ingressrouteudps 16 | singular: ingressrouteudp 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: IngressRouteUDP is a CRD implementation of a Traefik UDP Router. 23 | properties: 24 | apiVersion: 25 | description: 'APIVersion defines the versioned schema of this representation 26 | of an object. Servers should convert recognized schemas to the latest 27 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 28 | type: string 29 | kind: 30 | description: 'Kind is a string value representing the REST resource this 31 | object represents. Servers may infer this from the endpoint the client 32 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 33 | type: string 34 | metadata: 35 | type: object 36 | spec: 37 | description: IngressRouteUDPSpec defines the desired state of a IngressRouteUDP. 38 | properties: 39 | entryPoints: 40 | description: 'EntryPoints defines the list of entry point names to 41 | bind to. Entry points have to be configured in the static configuration. 42 | More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ 43 | Default: all.' 44 | items: 45 | type: string 46 | type: array 47 | routes: 48 | description: Routes defines the list of routes. 49 | items: 50 | description: RouteUDP holds the UDP route configuration. 51 | properties: 52 | services: 53 | description: Services defines the list of UDP services. 54 | items: 55 | description: ServiceUDP defines an upstream UDP service to 56 | proxy traffic to. 57 | properties: 58 | name: 59 | description: Name defines the name of the referenced Kubernetes 60 | Service. 61 | type: string 62 | namespace: 63 | description: Namespace defines the namespace of the referenced 64 | Kubernetes Service. 65 | type: string 66 | nativeLB: 67 | description: NativeLB controls, when creating the load-balancer, 68 | whether the LB's children are directly the pods IPs 69 | or if the only child is the Kubernetes Service clusterIP. 70 | The Kubernetes Service itself does load-balance to the 71 | pods. By default, NativeLB is false. 72 | type: boolean 73 | port: 74 | anyOf: 75 | - type: integer 76 | - type: string 77 | description: Port defines the port of a Kubernetes Service. 78 | This can be a reference to a named port. 79 | x-kubernetes-int-or-string: true 80 | weight: 81 | description: Weight defines the weight used when balancing 82 | requests between multiple Kubernetes Service. 83 | type: integer 84 | required: 85 | - name 86 | - port 87 | type: object 88 | type: array 89 | type: object 90 | type: array 91 | required: 92 | - routes 93 | type: object 94 | required: 95 | - metadata 96 | - spec 97 | type: object 98 | served: true 99 | storage: true 100 | status: 101 | acceptedNames: 102 | kind: "" 103 | plural: "" 104 | conditions: [] 105 | storedVersions: [] 106 | -------------------------------------------------------------------------------- /traefik/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | 3 | {{/* 4 | Expand the name of the chart. 5 | */}} 6 | {{- define "traefik.name" -}} 7 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 8 | {{- end -}} 9 | 10 | {{/* 11 | Create chart name and version as used by the chart label. 12 | */}} 13 | {{- define "traefik.chart" -}} 14 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 15 | {{- end -}} 16 | 17 | {{/* 18 | Create the chart image name. 19 | */}} 20 | 21 | {{- define "traefik.image-name" -}} 22 | {{- printf "%s/%s:%s" .Values.image.registry .Values.image.repository (.Values.image.tag | default .Chart.AppVersion) }} 23 | {{- end -}} 24 | {{/* 25 | Create a default fully qualified app name. 26 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 27 | If release name contains chart name it will be used as a full name. 28 | */}} 29 | {{- define "traefik.fullname" -}} 30 | {{- if .Values.fullnameOverride -}} 31 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 32 | {{- else -}} 33 | {{- $name := default .Chart.Name .Values.nameOverride -}} 34 | {{- if contains $name .Release.Name -}} 35 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 36 | {{- else -}} 37 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 38 | {{- end -}} 39 | {{- end -}} 40 | {{- end -}} 41 | 42 | {{/* 43 | Allow customization of the instance label value. 44 | */}} 45 | {{- define "traefik.instance-name" -}} 46 | {{- default (printf "%s-%s" .Release.Name .Release.Namespace) .Values.instanceLabelOverride | trunc 63 | trimSuffix "-" -}} 47 | {{- end -}} 48 | 49 | {{/* Shared labels used for selector*/}} 50 | {{/* This is an immutable field: this should not change between upgrade */}} 51 | {{- define "traefik.labelselector" -}} 52 | app.kubernetes.io/name: {{ template "traefik.name" . }} 53 | app.kubernetes.io/instance: {{ template "traefik.instance-name" . }} 54 | {{- end }} 55 | 56 | {{/* Shared labels used in metada */}} 57 | {{- define "traefik.labels" -}} 58 | {{ include "traefik.labelselector" . }} 59 | helm.sh/chart: {{ template "traefik.chart" . }} 60 | app.kubernetes.io/managed-by: {{ .Release.Service }} 61 | {{- with .Values.commonLabels }} 62 | {{ toYaml . }} 63 | {{- end }} 64 | {{- end }} 65 | 66 | {{/* 67 | Construct the namespace for all namespaced resources 68 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 69 | Preserve the default behavior of the Release namespace if no override is provided 70 | */}} 71 | {{- define "traefik.namespace" -}} 72 | {{- if .Values.namespaceOverride -}} 73 | {{- .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} 74 | {{- else -}} 75 | {{- .Release.Namespace -}} 76 | {{- end -}} 77 | {{- end -}} 78 | 79 | {{/* 80 | The name of the service account to use 81 | */}} 82 | {{- define "traefik.serviceAccountName" -}} 83 | {{- default (include "traefik.fullname" .) .Values.serviceAccount.name -}} 84 | {{- end -}} 85 | 86 | {{/* 87 | The name of the ClusterRole and ClusterRoleBinding to use. 88 | Adds the namespace to name to prevent duplicate resource names when there 89 | are multiple namespaced releases with the same release name. 90 | */}} 91 | {{- define "traefik.clusterRoleName" -}} 92 | {{- (printf "%s-%s" (include "traefik.fullname" .) .Release.Namespace) | trunc 63 | trimSuffix "-" }} 93 | {{- end -}} 94 | 95 | {{/* 96 | Construct the path for the providers.kubernetesingress.ingressendpoint.publishedservice. 97 | By convention this will simply use the / to match the name of the 98 | service generated. 99 | Users can provide an override for an explicit service they want bound via `.Values.providers.kubernetesIngress.publishedService.pathOverride` 100 | */}} 101 | {{- define "providers.kubernetesIngress.publishedServicePath" -}} 102 | {{- $defServiceName := printf "%s/%s" .Release.Namespace (include "traefik.fullname" .) -}} 103 | {{- $servicePath := default $defServiceName .Values.providers.kubernetesIngress.publishedService.pathOverride }} 104 | {{- print $servicePath | trimSuffix "-" -}} 105 | {{- end -}} 106 | 107 | {{/* 108 | Construct a comma-separated list of whitelisted namespaces 109 | */}} 110 | {{- define "providers.kubernetesIngress.namespaces" -}} 111 | {{- default .Release.Namespace (join "," .Values.providers.kubernetesIngress.namespaces) }} 112 | {{- end -}} 113 | {{- define "providers.kubernetesCRD.namespaces" -}} 114 | {{- default .Release.Namespace (join "," .Values.providers.kubernetesCRD.namespaces) }} 115 | {{- end -}} 116 | 117 | {{/* 118 | Renders a complete tree, even values that contains template. 119 | */}} 120 | {{- define "traefik.render" -}} 121 | {{- if typeIs "string" .value }} 122 | {{- tpl .value .context }} 123 | {{ else }} 124 | {{- tpl (.value | toYaml) .context }} 125 | {{- end }} 126 | {{- end -}} 127 | -------------------------------------------------------------------------------- /traefik/tests/deployment-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Deployment configuration 2 | templates: 3 | - deployment.yaml 4 | tests: 5 | - it: should have 1 replica by default 6 | asserts: 7 | - equal: 8 | path: spec.replicas 9 | value: 1 10 | - it: should have the specified amount of replicas when specified via values 11 | set: 12 | deployment: 13 | replicas: 3 14 | asserts: 15 | - equal: 16 | path: spec.replicas 17 | value: 3 18 | - it: should have revisionHistoryLimit with specified value 19 | set: 20 | deployment: 21 | revisionHistoryLimit: 1 22 | asserts: 23 | - equal: 24 | path: spec.revisionHistoryLimit 25 | value: 1 26 | - it: should have a rollingUpdate strategy with default values 27 | asserts: 28 | - equal: 29 | path: spec.strategy.type 30 | value: RollingUpdate 31 | - equal: 32 | path: spec.strategy.rollingUpdate.maxUnavailable 33 | value: 0 34 | - equal: 35 | path: spec.strategy.rollingUpdate.maxSurge 36 | value: 1 37 | - it: should have a custom merged rollingUpdate strategy with specified values 38 | set: 39 | updateStrategy: 40 | rollingUpdate: 41 | maxUnavailable: 4 42 | vegetaForce: 9000 43 | asserts: 44 | - equal: 45 | path: spec.strategy.type 46 | value: RollingUpdate 47 | - equal: 48 | path: spec.strategy.rollingUpdate.maxUnavailable 49 | value: 4 50 | - equal: 51 | path: spec.strategy.rollingUpdate.maxSurge 52 | value: 1 53 | - equal: 54 | path: spec.strategy.rollingUpdate.vegetaForce 55 | value: 9000 56 | - it: should have annotations with specified values 57 | set: 58 | deployment: 59 | annotations: 60 | traefik/powpow: annotations 61 | podAnnotations: 62 | traefik/powpow: podAnnotations 63 | asserts: 64 | - equal: 65 | path: metadata.annotations.traefik/powpow 66 | value: annotations 67 | - equal: 68 | path: spec.template.metadata.annotations.traefik/powpow 69 | value: podAnnotations 70 | - it: should have labels with specified values 71 | set: 72 | deployment: 73 | labels: 74 | traefik/powpow: labels 75 | podLabels: 76 | traefik/powpow: podLabels 77 | asserts: 78 | - equal: 79 | path: metadata.labels.traefik/powpow 80 | value: labels 81 | - equal: 82 | path: spec.template.metadata.labels.traefik/powpow 83 | value: podLabels 84 | - it: should have minReadySeconds with specified value 85 | set: 86 | deployment: 87 | minReadySeconds: 30 88 | asserts: 89 | - equal: 90 | path: spec.minReadySeconds 91 | value: 30 92 | - it: should have a preStop hook with specified values 93 | set: 94 | deployment: 95 | lifecycle: 96 | preStop: 97 | exec: 98 | command: ["/bin/sh", "-c", "sleep 40"] 99 | asserts: 100 | - equal: 101 | path: spec.template.spec.containers[0].lifecycle.preStop.exec.command 102 | value: ["/bin/sh", "-c", "sleep 40"] 103 | - it: should have a postStart hook with specified values 104 | set: 105 | deployment: 106 | lifecycle: 107 | postStart: 108 | httpGet: 109 | path: /ping 110 | port: 9000 111 | host: localhost 112 | scheme: HTTP 113 | asserts: 114 | - equal: 115 | path: spec.template.spec.containers[0].lifecycle.postStart.httpGet.path 116 | value: /ping 117 | - equal: 118 | path: spec.template.spec.containers[0].lifecycle.postStart.httpGet.port 119 | value: 9000 120 | - equal: 121 | path: spec.template.spec.containers[0].lifecycle.postStart.httpGet.host 122 | value: localhost 123 | - equal: 124 | path: spec.template.spec.containers[0].lifecycle.postStart.httpGet.scheme 125 | value: HTTP 126 | - it: should have affinity with specified value 127 | values: 128 | - ./values/antiaffinity.yaml 129 | asserts: 130 | - equal: 131 | path: spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[0].topologyKey 132 | value: kubernetes.io/hostname 133 | - it: should have an OnDelete strategy when set 134 | set: 135 | updateStrategy: 136 | type: OnDelete 137 | asserts: 138 | - equal: 139 | path: spec.strategy.type 140 | value: OnDelete 141 | - it: should use helm managed namespace as default behavior 142 | asserts: 143 | - equal: 144 | path: metadata.namespace 145 | value: NAMESPACE 146 | - it: should accept overridden namespace 147 | set: 148 | namespaceOverride: "traefik-ns-override" 149 | asserts: 150 | - equal: 151 | path: metadata.namespace 152 | value: "traefik-ns-override" 153 | -------------------------------------------------------------------------------- /traefik/crds/traefik.io_tlsoptions.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.6.2 8 | creationTimestamp: null 9 | name: tlsoptions.traefik.io 10 | spec: 11 | group: traefik.io 12 | names: 13 | kind: TLSOption 14 | listKind: TLSOptionList 15 | plural: tlsoptions 16 | singular: tlsoption 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: 'TLSOption is the CRD implementation of a Traefik TLS Option, 23 | allowing to configure some parameters of the TLS connection. More info: 24 | https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' 25 | properties: 26 | apiVersion: 27 | description: 'APIVersion defines the versioned schema of this representation 28 | of an object. Servers should convert recognized schemas to the latest 29 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 30 | type: string 31 | kind: 32 | description: 'Kind is a string value representing the REST resource this 33 | object represents. Servers may infer this from the endpoint the client 34 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 35 | type: string 36 | metadata: 37 | type: object 38 | spec: 39 | description: TLSOptionSpec defines the desired state of a TLSOption. 40 | properties: 41 | alpnProtocols: 42 | description: 'ALPNProtocols defines the list of supported application 43 | level protocols for the TLS handshake, in order of preference. More 44 | info: https://doc.traefik.io/traefik/v2.10/https/tls/#alpn-protocols' 45 | items: 46 | type: string 47 | type: array 48 | cipherSuites: 49 | description: 'CipherSuites defines the list of supported cipher suites 50 | for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#cipher-suites' 51 | items: 52 | type: string 53 | type: array 54 | clientAuth: 55 | description: ClientAuth defines the server's policy for TLS Client 56 | Authentication. 57 | properties: 58 | clientAuthType: 59 | description: ClientAuthType defines the client authentication 60 | type to apply. 61 | enum: 62 | - NoClientCert 63 | - RequestClientCert 64 | - RequireAnyClientCert 65 | - VerifyClientCertIfGiven 66 | - RequireAndVerifyClientCert 67 | type: string 68 | secretNames: 69 | description: SecretNames defines the names of the referenced Kubernetes 70 | Secret storing certificate details. 71 | items: 72 | type: string 73 | type: array 74 | type: object 75 | curvePreferences: 76 | description: 'CurvePreferences defines the preferred elliptic curves 77 | in a specific order. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#curve-preferences' 78 | items: 79 | type: string 80 | type: array 81 | maxVersion: 82 | description: 'MaxVersion defines the maximum TLS version that Traefik 83 | will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12, 84 | VersionTLS13. Default: None.' 85 | type: string 86 | minVersion: 87 | description: 'MinVersion defines the minimum TLS version that Traefik 88 | will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12, 89 | VersionTLS13. Default: VersionTLS10.' 90 | type: string 91 | preferServerCipherSuites: 92 | description: 'PreferServerCipherSuites defines whether the server 93 | chooses a cipher suite among his own instead of among the client''s. 94 | It is enabled automatically when minVersion or maxVersion is set. 95 | Deprecated: https://github.com/golang/go/issues/45430' 96 | type: boolean 97 | sniStrict: 98 | description: SniStrict defines whether Traefik allows connections 99 | from clients connections that do not specify a server_name extension. 100 | type: boolean 101 | type: object 102 | required: 103 | - metadata 104 | - spec 105 | type: object 106 | served: true 107 | storage: true 108 | status: 109 | acceptedNames: 110 | kind: "" 111 | plural: "" 112 | conditions: [] 113 | storedVersions: [] 114 | -------------------------------------------------------------------------------- /traefik/crds/traefik.containo.us_tlsoptions.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.6.2 8 | creationTimestamp: null 9 | name: tlsoptions.traefik.containo.us 10 | spec: 11 | group: traefik.containo.us 12 | names: 13 | kind: TLSOption 14 | listKind: TLSOptionList 15 | plural: tlsoptions 16 | singular: tlsoption 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: 'TLSOption is the CRD implementation of a Traefik TLS Option, 23 | allowing to configure some parameters of the TLS connection. More info: 24 | https://doc.traefik.io/traefik/v2.9/https/tls/#tls-options' 25 | properties: 26 | apiVersion: 27 | description: 'APIVersion defines the versioned schema of this representation 28 | of an object. Servers should convert recognized schemas to the latest 29 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 30 | type: string 31 | kind: 32 | description: 'Kind is a string value representing the REST resource this 33 | object represents. Servers may infer this from the endpoint the client 34 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 35 | type: string 36 | metadata: 37 | type: object 38 | spec: 39 | description: TLSOptionSpec defines the desired state of a TLSOption. 40 | properties: 41 | alpnProtocols: 42 | description: 'ALPNProtocols defines the list of supported application 43 | level protocols for the TLS handshake, in order of preference. More 44 | info: https://doc.traefik.io/traefik/v2.9/https/tls/#alpn-protocols' 45 | items: 46 | type: string 47 | type: array 48 | cipherSuites: 49 | description: 'CipherSuites defines the list of supported cipher suites 50 | for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.9/https/tls/#cipher-suites' 51 | items: 52 | type: string 53 | type: array 54 | clientAuth: 55 | description: ClientAuth defines the server's policy for TLS Client 56 | Authentication. 57 | properties: 58 | clientAuthType: 59 | description: ClientAuthType defines the client authentication 60 | type to apply. 61 | enum: 62 | - NoClientCert 63 | - RequestClientCert 64 | - RequireAnyClientCert 65 | - VerifyClientCertIfGiven 66 | - RequireAndVerifyClientCert 67 | type: string 68 | secretNames: 69 | description: SecretNames defines the names of the referenced Kubernetes 70 | Secret storing certificate details. 71 | items: 72 | type: string 73 | type: array 74 | type: object 75 | curvePreferences: 76 | description: 'CurvePreferences defines the preferred elliptic curves 77 | in a specific order. More info: https://doc.traefik.io/traefik/v2.9/https/tls/#curve-preferences' 78 | items: 79 | type: string 80 | type: array 81 | maxVersion: 82 | description: 'MaxVersion defines the maximum TLS version that Traefik 83 | will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12, 84 | VersionTLS13. Default: None.' 85 | type: string 86 | minVersion: 87 | description: 'MinVersion defines the minimum TLS version that Traefik 88 | will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12, 89 | VersionTLS13. Default: VersionTLS10.' 90 | type: string 91 | preferServerCipherSuites: 92 | description: 'PreferServerCipherSuites defines whether the server 93 | chooses a cipher suite among his own instead of among the client''s. 94 | It is enabled automatically when minVersion or maxVersion is set. 95 | Deprecated: https://github.com/golang/go/issues/45430' 96 | type: boolean 97 | sniStrict: 98 | description: SniStrict defines whether Traefik allows connections 99 | from clients connections that do not specify a server_name extension. 100 | type: boolean 101 | type: object 102 | required: 103 | - metadata 104 | - spec 105 | type: object 106 | served: true 107 | storage: true 108 | status: 109 | acceptedNames: 110 | kind: "" 111 | plural: "" 112 | conditions: [] 113 | storedVersions: [] 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Traefik 2 | 3 | [Traefik](https://traefik.io/) is a modern HTTP reverse proxy and load balancer made to deploy 4 | microservices with ease. 5 | 6 | ## Introduction 7 | 8 | This chart bootstraps Traefik version 2 as a Kubernetes ingress controller, 9 | using Custom Resources `IngressRoute`: . 10 | 11 | ### Philosophy 12 | 13 | The Traefik HelmChart is focused on Traefik deployment configuration. 14 | 15 | To keep this HelmChart as generic as possible we tend 16 | to avoid integrating any third party solutions nor any specific use cases. 17 | 18 | Accordingly, the encouraged approach to fulfill your needs: 19 | 20 | 1. Override the default Traefik configuration values ([yaml file or cli](https://helm.sh/docs/chart_template_guide/values_files/)) 21 | 2. Append your own configurations (`kubectl apply -f myconf.yaml`) 22 | 23 | If needed, one may use [extraObjects](./traefik/tests/values/extra.yaml) or extend this HelmChart [as a Subchart](https://helm.sh/docs/chart_template_guide/subcharts_and_globals/) 24 | 25 | ## Installing 26 | 27 | ### Prerequisites 28 | 29 | 1. [x] Helm **v3 > 3.9.0** [installed](https://helm.sh/docs/using_helm/#installing-helm): `helm version` 30 | 2. [x] Traefik's chart repository: `helm repo add traefik https://traefik.github.io/charts` 31 | 32 | ### Kubernetes Version Support 33 | 34 | Due to changes in CRD version support, the following versions of the chart are usable and supported on the following Kubernetes versions: 35 | 36 | | | Kubernetes v1.15 and below | Kubernetes v1.16-v1.21 | Kubernetes v1.22 and above | 37 | |-------------------------|-----------------------------|------------------------|----------------------------| 38 | | Chart v9.20.2 and below | [x] | [x] | | 39 | | Chart v10.0.0 and above | | [x] | [x] | 40 | | Chart v22.0.0 and above | | | [x] | 41 | 42 | ### Deploying Traefik 43 | 44 | ```bash 45 | helm install traefik traefik/traefik 46 | ``` 47 | 48 | You can customize the install with a `values` file. There are some [EXAMPLES](./EXAMPLES.md) provided. 49 | Complete documentation on all available parameters is in the [default file](./traefik/values.yaml). 50 | 51 | ```bash 52 | helm install -f myvalues.yaml traefik traefik/traefik 53 | ``` 54 | 55 | 🛂 **Warning**: Helm v2 support was removed in the chart version 10.0.0. 56 | 57 | ## Upgrading 58 | 59 | One can check what has changed in the [Changelog](./traefik/Changelog.md). 60 | 61 | ```bash 62 | # Update repository 63 | helm repo update 64 | # See current Chart & Traefik version 65 | helm search repo traefik/traefik 66 | # Upgrade Traefik 67 | helm upgrade traefik traefik/traefik 68 | ``` 69 | 70 | New major version indicates that there is an incompatible breaking change. 71 | 72 | ### Upgrading CRDs 73 | 74 | With Helm v3, CRDs created by this chart can not be updated, cf the [Helm Documentation on CRDs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions). Please read carefully release notes of this chart before upgrading CRDs. 75 | 76 | ```bash 77 | kubectl apply --server-side --force-conflicts -k https://github.com/traefik/traefik-helm-chart/traefik/crds/ 78 | ``` 79 | 80 | ### Upgrading after 18.X+ 81 | 82 | It's detailed in [release notes](https://github.com/traefik/traefik-helm-chart/releases). 83 | 84 | ### Upgrading from 17.x to 18.x 85 | 86 | Since v18.x, this chart by default merges TCP and UDP ports into a single (LoadBalancer) `Service`. 87 | Load balancers with mixed protocols are available since v1.20 and in 88 | [beta as of Kubernetes v1.24](https://kubernetes.io/docs/concepts/services-networking/service/#load-balancers-with-mixed-protocol-types). 89 | Availability may depend on your Kubernetes provider. 90 | 91 | To retain the old default behavior, set `service.single` to `false` in your values. 92 | 93 | When using TCP and UDP with a single service, you may encounter 94 | [this issue](https://github.com/kubernetes/kubernetes/issues/47249#issuecomment-587960741) 95 | from Kubernetes. 96 | 97 | On HTTP/3, if you want to avoid this issue, you can set 98 | `ports.websecure.http3.advertisedPort` to an other value than `443` 99 | 100 | If you were previously using HTTP/3, you should update your values as follows: 101 | - Replace the old value (`true`) of `ports.websecure.http3` with a key `enabled: true` 102 | - Remove `experimental.http3.enabled=true` entry 103 | 104 | ### Upgrading from 16.x to 17.x 105 | 106 | Since v17.x, this chart provides unified labels following 107 | [Kubernetes recommendation](https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/). 108 | 109 | This version needs to change an immutable field, which is not supported by 110 | Kubernetes and Helm, see [this issue](https://github.com/helm/helm/issues/7350) 111 | for more details. 112 | So you will have to delete your `Service`, `Deployment` or `DaemonSet` in 113 | order to be able to upgrade. 114 | 115 | You may also upgrade by deploying another Traefik to a different namespace and 116 | removing after your first Traefik. 117 | 118 | Alternatively, since version 20.3.0 of this chart, you may set `instanceLabelOverride` to the previous value of that label. 119 | This will override the new `Release.Name-Release.Namespace` pattern to avoid any (longer) downtime. 120 | 121 | ## Contributing 122 | 123 | If you want to contribute to this chart, please read the [Contributing Guide](./CONTRIBUTING.md). 124 | 125 | Thanks to all the people who have already contributed! 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /traefik/tests/service-internal-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Internal Service configuration 2 | templates: 3 | - service-internal.yaml 4 | tests: 5 | - it: should not provide an internal service by default 6 | asserts: 7 | - hasDocuments: 8 | count: 0 9 | - it: should be possible to configure an internal LoadBalancer Service 10 | set: 11 | service: 12 | internal: 13 | type: LoadBalancer 14 | asserts: 15 | - equal: 16 | path: spec.type 17 | value: LoadBalancer 18 | - it: should be possible to configure only an internal Service 19 | set: 20 | service: 21 | enabled: false 22 | internal: 23 | type: LoadBalancer 24 | asserts: 25 | - equal: 26 | path: spec.type 27 | value: LoadBalancer 28 | - it: should fail when the name is too long 29 | release: 30 | name: yesthisnameiscontainingwaymorethan50charactersinit 31 | set: 32 | service: 33 | internal: 34 | type: ClusterIP 35 | asserts: 36 | - failedTemplate: 37 | errorMessage: "Cannot create an internal service when name contains more than 50 characters" 38 | - it: should have internal customized annotations when specified via values 39 | set: 40 | service: 41 | internal: 42 | annotations: 43 | azure-load-balancer-internal: true 44 | asserts: 45 | - equal: 46 | path: metadata.annotations.azure-load-balancer-internal 47 | value: true 48 | - it: should have customized labels when specified via values 49 | set: 50 | service: 51 | internal: 52 | labels: 53 | custom-label: custom-value 54 | asserts: 55 | - equal: 56 | path: metadata.labels.custom-label 57 | value: custom-value 58 | - it: should have custom spec elements when specified via values 59 | set: 60 | service: 61 | internal: 62 | enabled: true 63 | spec: 64 | externalTrafficPolicy: Cluster 65 | loadBalancerIP: "1.2.3.4" 66 | clusterIP: "2.3.4.5" 67 | loadBalancerSourceRanges: 68 | - 192.168.0.1/32 69 | - 172.16.0.0/16 70 | externalIPs: 71 | - "1.2.3.4" 72 | asserts: 73 | - equal: 74 | path: spec.ports[0].name 75 | value: web 76 | - equal: 77 | path: spec.ports[0].protocol 78 | value: TCP 79 | - equal: 80 | path: spec.externalTrafficPolicy 81 | value: Cluster 82 | - equal: 83 | path: spec.loadBalancerIP 84 | value: "1.2.3.4" 85 | - equal: 86 | path: spec.clusterIP 87 | value: "2.3.4.5" 88 | - equal: 89 | path: spec.loadBalancerSourceRanges[0] 90 | value: 192.168.0.1/32 91 | - equal: 92 | path: spec.loadBalancerSourceRanges[1] 93 | value: 172.16.0.0/16 94 | - equal: 95 | path: spec.externalIPs[0] 96 | value: "1.2.3.4" 97 | - it: should use helm managed namespace as default behavior UDP 98 | set: 99 | service: 100 | internal: 101 | enabled: true 102 | spec: 103 | externalTrafficPolicy: Cluster 104 | loadBalancerIP: "1.2.3.4" 105 | clusterIP: "2.3.4.5" 106 | loadBalancerSourceRanges: 107 | - 192.168.0.1/32 108 | - 172.16.0.0/16 109 | externalIPs: 110 | - "1.2.3.4" 111 | ports: 112 | udp: 113 | port: 3000 114 | protocol: UDP 115 | asserts: 116 | - equal: 117 | path: metadata.namespace 118 | value: NAMESPACE 119 | - it: should use helm managed namespace as default behavior TCP 120 | set: 121 | service: 122 | internal: 123 | enabled: true 124 | spec: 125 | externalTrafficPolicy: Cluster 126 | loadBalancerIP: "1.2.3.4" 127 | clusterIP: "2.3.4.5" 128 | loadBalancerSourceRanges: 129 | - 192.168.0.1/32 130 | - 172.16.0.0/16 131 | externalIPs: 132 | - "1.2.3.4" 133 | ports: 134 | tcp: 135 | port: 3000 136 | protocol: TCP 137 | asserts: 138 | - equal: 139 | path: metadata.namespace 140 | value: NAMESPACE 141 | - it: should accept overridden namespace UDP 142 | set: 143 | namespaceOverride: "traefik-ns-override" 144 | service: 145 | internal: 146 | enabled: true 147 | spec: 148 | externalTrafficPolicy: Cluster 149 | loadBalancerIP: "1.2.3.4" 150 | clusterIP: "2.3.4.5" 151 | loadBalancerSourceRanges: 152 | - 192.168.0.1/32 153 | - 172.16.0.0/16 154 | externalIPs: 155 | - "1.2.3.4" 156 | ports: 157 | udp: 158 | port: 3000 159 | protocol: UDP 160 | asserts: 161 | - equal: 162 | path: metadata.namespace 163 | value: "traefik-ns-override" 164 | - it: should accept overridden namespace TCP 165 | set: 166 | namespaceOverride: "traefik-ns-override" 167 | service: 168 | internal: 169 | enabled: true 170 | spec: 171 | externalTrafficPolicy: Cluster 172 | loadBalancerIP: "1.2.3.4" 173 | clusterIP: "2.3.4.5" 174 | loadBalancerSourceRanges: 175 | - 192.168.0.1/32 176 | - 172.16.0.0/16 177 | externalIPs: 178 | - "1.2.3.4" 179 | ports: 180 | tcp: 181 | port: 3000 182 | protocol: TCP 183 | asserts: 184 | - equal: 185 | path: metadata.namespace 186 | value: "traefik-ns-override" 187 | -------------------------------------------------------------------------------- /traefik/crds/traefik.io_serverstransports.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.6.2 8 | creationTimestamp: null 9 | name: serverstransports.traefik.io 10 | spec: 11 | group: traefik.io 12 | names: 13 | kind: ServersTransport 14 | listKind: ServersTransportList 15 | plural: serverstransports 16 | singular: serverstransport 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: 'ServersTransport is the CRD implementation of a ServersTransport. 23 | If no serversTransport is specified, the default@internal will be used. 24 | The default@internal serversTransport is created from the static configuration. 25 | More info: https://doc.traefik.io/traefik/v2.10/routing/services/#serverstransport_1' 26 | properties: 27 | apiVersion: 28 | description: 'APIVersion defines the versioned schema of this representation 29 | of an object. Servers should convert recognized schemas to the latest 30 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 31 | type: string 32 | kind: 33 | description: 'Kind is a string value representing the REST resource this 34 | object represents. Servers may infer this from the endpoint the client 35 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: ServersTransportSpec defines the desired state of a ServersTransport. 41 | properties: 42 | certificatesSecrets: 43 | description: CertificatesSecrets defines a list of secret storing 44 | client certificates for mTLS. 45 | items: 46 | type: string 47 | type: array 48 | disableHTTP2: 49 | description: DisableHTTP2 disables HTTP/2 for connections with backend 50 | servers. 51 | type: boolean 52 | forwardingTimeouts: 53 | description: ForwardingTimeouts defines the timeouts for requests 54 | forwarded to the backend servers. 55 | properties: 56 | dialTimeout: 57 | anyOf: 58 | - type: integer 59 | - type: string 60 | description: DialTimeout is the amount of time to wait until a 61 | connection to a backend server can be established. 62 | x-kubernetes-int-or-string: true 63 | idleConnTimeout: 64 | anyOf: 65 | - type: integer 66 | - type: string 67 | description: IdleConnTimeout is the maximum period for which an 68 | idle HTTP keep-alive connection will remain open before closing 69 | itself. 70 | x-kubernetes-int-or-string: true 71 | pingTimeout: 72 | anyOf: 73 | - type: integer 74 | - type: string 75 | description: PingTimeout is the timeout after which the HTTP/2 76 | connection will be closed if a response to ping is not received. 77 | x-kubernetes-int-or-string: true 78 | readIdleTimeout: 79 | anyOf: 80 | - type: integer 81 | - type: string 82 | description: ReadIdleTimeout is the timeout after which a health 83 | check using ping frame will be carried out if no frame is received 84 | on the HTTP/2 connection. 85 | x-kubernetes-int-or-string: true 86 | responseHeaderTimeout: 87 | anyOf: 88 | - type: integer 89 | - type: string 90 | description: ResponseHeaderTimeout is the amount of time to wait 91 | for a server's response headers after fully writing the request 92 | (including its body, if any). 93 | x-kubernetes-int-or-string: true 94 | type: object 95 | insecureSkipVerify: 96 | description: InsecureSkipVerify disables SSL certificate verification. 97 | type: boolean 98 | maxIdleConnsPerHost: 99 | description: MaxIdleConnsPerHost controls the maximum idle (keep-alive) 100 | to keep per-host. 101 | type: integer 102 | peerCertURI: 103 | description: PeerCertURI defines the peer cert URI used to match against 104 | SAN URI during the peer certificate verification. 105 | type: string 106 | rootCAsSecrets: 107 | description: RootCAsSecrets defines a list of CA secret used to validate 108 | self-signed certificate. 109 | items: 110 | type: string 111 | type: array 112 | serverName: 113 | description: ServerName defines the server name used to contact the 114 | server. 115 | type: string 116 | type: object 117 | required: 118 | - metadata 119 | - spec 120 | type: object 121 | served: true 122 | storage: true 123 | status: 124 | acceptedNames: 125 | kind: "" 126 | plural: "" 127 | conditions: [] 128 | storedVersions: [] 129 | -------------------------------------------------------------------------------- /traefik/crds/traefik.containo.us_serverstransports.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.6.2 8 | creationTimestamp: null 9 | name: serverstransports.traefik.containo.us 10 | spec: 11 | group: traefik.containo.us 12 | names: 13 | kind: ServersTransport 14 | listKind: ServersTransportList 15 | plural: serverstransports 16 | singular: serverstransport 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: 'ServersTransport is the CRD implementation of a ServersTransport. 23 | If no serversTransport is specified, the default@internal will be used. 24 | The default@internal serversTransport is created from the static configuration. 25 | More info: https://doc.traefik.io/traefik/v2.9/routing/services/#serverstransport_1' 26 | properties: 27 | apiVersion: 28 | description: 'APIVersion defines the versioned schema of this representation 29 | of an object. Servers should convert recognized schemas to the latest 30 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 31 | type: string 32 | kind: 33 | description: 'Kind is a string value representing the REST resource this 34 | object represents. Servers may infer this from the endpoint the client 35 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: ServersTransportSpec defines the desired state of a ServersTransport. 41 | properties: 42 | certificatesSecrets: 43 | description: CertificatesSecrets defines a list of secret storing 44 | client certificates for mTLS. 45 | items: 46 | type: string 47 | type: array 48 | disableHTTP2: 49 | description: DisableHTTP2 disables HTTP/2 for connections with backend 50 | servers. 51 | type: boolean 52 | forwardingTimeouts: 53 | description: ForwardingTimeouts defines the timeouts for requests 54 | forwarded to the backend servers. 55 | properties: 56 | dialTimeout: 57 | anyOf: 58 | - type: integer 59 | - type: string 60 | description: DialTimeout is the amount of time to wait until a 61 | connection to a backend server can be established. 62 | x-kubernetes-int-or-string: true 63 | idleConnTimeout: 64 | anyOf: 65 | - type: integer 66 | - type: string 67 | description: IdleConnTimeout is the maximum period for which an 68 | idle HTTP keep-alive connection will remain open before closing 69 | itself. 70 | x-kubernetes-int-or-string: true 71 | pingTimeout: 72 | anyOf: 73 | - type: integer 74 | - type: string 75 | description: PingTimeout is the timeout after which the HTTP/2 76 | connection will be closed if a response to ping is not received. 77 | x-kubernetes-int-or-string: true 78 | readIdleTimeout: 79 | anyOf: 80 | - type: integer 81 | - type: string 82 | description: ReadIdleTimeout is the timeout after which a health 83 | check using ping frame will be carried out if no frame is received 84 | on the HTTP/2 connection. 85 | x-kubernetes-int-or-string: true 86 | responseHeaderTimeout: 87 | anyOf: 88 | - type: integer 89 | - type: string 90 | description: ResponseHeaderTimeout is the amount of time to wait 91 | for a server's response headers after fully writing the request 92 | (including its body, if any). 93 | x-kubernetes-int-or-string: true 94 | type: object 95 | insecureSkipVerify: 96 | description: InsecureSkipVerify disables SSL certificate verification. 97 | type: boolean 98 | maxIdleConnsPerHost: 99 | description: MaxIdleConnsPerHost controls the maximum idle (keep-alive) 100 | to keep per-host. 101 | type: integer 102 | peerCertURI: 103 | description: PeerCertURI defines the peer cert URI used to match against 104 | SAN URI during the peer certificate verification. 105 | type: string 106 | rootCAsSecrets: 107 | description: RootCAsSecrets defines a list of CA secret used to validate 108 | self-signed certificate. 109 | items: 110 | type: string 111 | type: array 112 | serverName: 113 | description: ServerName defines the server name used to contact the 114 | server. 115 | type: string 116 | type: object 117 | required: 118 | - metadata 119 | - spec 120 | type: object 121 | served: true 122 | storage: true 123 | status: 124 | acceptedNames: 125 | kind: "" 126 | plural: "" 127 | conditions: [] 128 | storedVersions: [] 129 | -------------------------------------------------------------------------------- /traefik/tests/service-config-multiple_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Service configuration (split TCP/UDP services) 2 | templates: 3 | - service.yaml 4 | tests: 5 | - it: should have TCP only annotations when specified via values 6 | set: 7 | service: 8 | single: false 9 | annotationsTCP: 10 | dns-hostname: tcp.example.com 11 | ports: 12 | udp: 13 | port: 3000 14 | expose: true 15 | exposedPort: 80 16 | protocol: UDP 17 | asserts: 18 | - equal: 19 | path: metadata.annotations.dns-hostname 20 | value: tcp.example.com 21 | documentIndex: 0 22 | - isNull: 23 | path: metadata.annotations 24 | documentIndex: 1 25 | - it: should have UDP only annotations when specified via values 26 | set: 27 | service: 28 | single: false 29 | annotationsUDP: 30 | dns-hostname: udp.example.com 31 | ports: 32 | udp: 33 | port: 3000 34 | expose: true 35 | exposedPort: 80 36 | protocol: UDP 37 | asserts: 38 | - isNull: 39 | path: metadata.annotations 40 | documentIndex: 0 41 | - equal: 42 | path: metadata.annotations.dns-hostname 43 | value: udp.example.com 44 | documentIndex: 1 45 | - it: should merge protocol specific service annotations when specified via values 46 | set: 47 | service: 48 | single: false 49 | annotations: 50 | azure-load-balancer-internal: true 51 | annotationsTCP: 52 | dns-hostname: tcp.example.com 53 | annotationsUDP: 54 | dns-hostname: udp.example.com 55 | ports: 56 | udp: 57 | port: 3000 58 | expose: true 59 | exposedPort: 80 60 | protocol: UDP 61 | asserts: 62 | - equal: 63 | path: metadata.annotations 64 | value: 65 | azure-load-balancer-internal: true 66 | dns-hostname: tcp.example.com 67 | documentIndex: 0 68 | - equal: 69 | path: metadata.annotations 70 | value: 71 | azure-load-balancer-internal: true 72 | dns-hostname: udp.example.com 73 | documentIndex: 1 74 | - it: should merge protocol specific service annotations with annotationsTCP unspecified when specified via values 75 | set: 76 | service: 77 | single: false 78 | annotations: 79 | azure-load-balancer-internal: true 80 | annotationsUDP: 81 | dns-hostname: udp.example.com 82 | ports: 83 | udp: 84 | port: 3000 85 | expose: true 86 | exposedPort: 80 87 | protocol: UDP 88 | asserts: 89 | - equal: 90 | path: metadata.annotations 91 | value: 92 | azure-load-balancer-internal: true 93 | documentIndex: 0 94 | - equal: 95 | path: metadata.annotations 96 | value: 97 | azure-load-balancer-internal: true 98 | dns-hostname: udp.example.com 99 | documentIndex: 1 100 | - it: should merge protocol specific service annotations with annotationsUDP unspecified when specified via values 101 | set: 102 | service: 103 | single: false 104 | annotations: 105 | azure-load-balancer-internal: true 106 | annotationsTCP: 107 | dns-hostname: tcp.example.com 108 | ports: 109 | udp: 110 | port: 3000 111 | expose: true 112 | exposedPort: 80 113 | protocol: UDP 114 | asserts: 115 | - equal: 116 | path: metadata.annotations 117 | value: 118 | azure-load-balancer-internal: true 119 | dns-hostname: tcp.example.com 120 | documentIndex: 0 121 | - equal: 122 | path: metadata.annotations 123 | value: 124 | azure-load-balancer-internal: true 125 | documentIndex: 1 126 | - it: should have custom spec elements when specified via values for UDP ports 127 | set: 128 | service: 129 | single: false 130 | ports: 131 | udp: 132 | port: 3000 133 | expose: true 134 | exposedPort: 80 135 | protocol: UDP 136 | documentIndex: 1 137 | asserts: 138 | - equal: 139 | path: spec.ports[0].name 140 | value: udp 141 | - equal: 142 | path: spec.ports[0].protocol 143 | value: UDP 144 | - it: should not have ipFamilyPolicy on either service when not specified 145 | set: 146 | service: 147 | single: false 148 | ports: 149 | udp: 150 | port: 3000 151 | protocol: UDP 152 | asserts: 153 | - isNull: 154 | path: spec.ipFamilyPolicy 155 | documentIndex: 0 156 | - isNull: 157 | path: spec.ipFamilyPolicy 158 | documentIndex: 1 159 | - it: should have custom ipFamilyPolicy on both services when specified via values 160 | set: 161 | service: 162 | single: false 163 | ipFamilyPolicy: PreferDualStack 164 | ports: 165 | udp: 166 | port: 3000 167 | protocol: UDP 168 | asserts: 169 | - equal: 170 | path: spec.ipFamilyPolicy 171 | value: PreferDualStack 172 | documentIndex: 0 173 | - equal: 174 | path: spec.ipFamilyPolicy 175 | value: PreferDualStack 176 | documentIndex: 1 177 | - it: should not have ipFamilies on either service when not specified 178 | set: 179 | service: 180 | single: false 181 | ports: 182 | udp: 183 | port: 3000 184 | protocol: UDP 185 | asserts: 186 | - isNull: 187 | path: spec.ipFamilies 188 | documentIndex: 0 189 | - isNull: 190 | path: spec.ipFamilies 191 | documentIndex: 1 192 | - it: should have custom ipFamilies on both services when specified via values 193 | set: 194 | service: 195 | single: false 196 | ipFamilies: 197 | - IPv6 198 | ports: 199 | udp: 200 | port: 3000 201 | protocol: UDP 202 | asserts: 203 | - equal: 204 | path: spec.ipFamilies 205 | value: 206 | - IPv6 207 | documentIndex: 0 208 | - equal: 209 | path: spec.ipFamilies 210 | value: 211 | - IPv6 212 | documentIndex: 1 213 | -------------------------------------------------------------------------------- /traefik/tests/container-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Main Container configuration 2 | templates: 3 | - deployment.yaml 4 | chart: 5 | appVersion: v2.3.0 6 | capabilities: 7 | majorVersion: 1 8 | minorVersion: 16 9 | tests: 10 | - it: should have the default Docker image when no value is specified 11 | asserts: 12 | - equal: 13 | path: spec.template.spec.containers[0].image 14 | value: docker.io/traefik:v2.3.0 15 | - it: should change image when image.tag value is specified 16 | set: 17 | image: 18 | tag: v2.0.0-beta1 19 | asserts: 20 | - equal: 21 | path: spec.template.spec.containers[0].image 22 | value: docker.io/traefik:v2.0.0-beta1 23 | - it: should change image when image.repository value is specified 24 | set: 25 | image: 26 | repository: traefik/traefik 27 | asserts: 28 | - equal: 29 | path: spec.template.spec.containers[0].image 30 | value: docker.io/traefik/traefik:v2.3.0 31 | - it: should change image when image.registry value is specified 32 | set: 33 | image: 34 | registry: example.org 35 | asserts: 36 | - equal: 37 | path: spec.template.spec.containers[0].image 38 | value: example.org/traefik:v2.3.0 39 | 40 | - it: should have no resource limit by default 41 | asserts: 42 | - isNull: 43 | path: spec.template.spec.containers[0].resources 44 | - it: should have a custom resource limit when specified 45 | set: 46 | resources: 47 | requests: 48 | cpu: "100m" 49 | memory: "50Mi" 50 | limits: 51 | cpu: "300m" 52 | memory: "150Mi" 53 | asserts: 54 | - equal: 55 | path: spec.template.spec.containers[0].resources.requests.cpu 56 | value: "100m" 57 | - equal: 58 | path: spec.template.spec.containers[0].resources.requests.memory 59 | value: "50Mi" 60 | - equal: 61 | path: spec.template.spec.containers[0].resources.limits.cpu 62 | value: "300m" 63 | - equal: 64 | path: spec.template.spec.containers[0].resources.limits.memory 65 | value: "150Mi" 66 | - it: should not have data volumeMount subPath by default 67 | asserts: 68 | - isNull: 69 | path: spec.template.spec.containers[0].volumeMounts[0].subPath 70 | - it: should have data volumeMount subPath when specified in config 71 | set: 72 | persistence: 73 | subPath: "subdir/traefik" 74 | asserts: 75 | - equal: 76 | path: spec.template.spec.containers[0].volumeMounts[0].subPath 77 | value: "subdir/traefik" 78 | - it: should have templated config map volume 79 | set: 80 | volumes: 81 | - name: '{{ printf "%s-custom-config" .Release.Name }}' 82 | mountPath: /etc/traefik 83 | type: configMap 84 | - name: 'non-templated' 85 | mountPath: /etc/non-templated 86 | type: configMap 87 | asserts: 88 | - equal: 89 | path: spec.template.spec.containers[0].volumeMounts[2].name 90 | value: "RELEASE-NAME-custom-config" 91 | - equal: 92 | path: spec.template.spec.containers[0].volumeMounts[3].name 93 | value: "non-templated" 94 | - equal: 95 | path: spec.template.spec.volumes[2].name 96 | value: "RELEASE-NAME-custom-config" 97 | - equal: 98 | path: spec.template.spec.volumes[2].configMap.name 99 | value: "RELEASE-NAME-custom-config" 100 | - equal: 101 | path: spec.template.spec.volumes[3].name 102 | value: "non-templated" 103 | - equal: 104 | path: spec.template.spec.volumes[3].configMap.name 105 | value: "non-templated" 106 | - it: should have templated secret volume 107 | set: 108 | volumes: 109 | - name: '{{ printf "%s-custom-secret" .Release.Name }}' 110 | mountPath: /etc/secret 111 | type: secret 112 | asserts: 113 | - equal: 114 | path: spec.template.spec.containers[0].volumeMounts[2].name 115 | value: "RELEASE-NAME-custom-secret" 116 | - equal: 117 | path: spec.template.spec.volumes[2].name 118 | value: "RELEASE-NAME-custom-secret" 119 | - equal: 120 | path: spec.template.spec.volumes[2].secret.secretName 121 | value: "RELEASE-NAME-custom-secret" 122 | - it: should set a podAntiaffinity 123 | set: 124 | affinity: 125 | podAntiAffinity: 126 | requiredDuringSchedulingIgnoredDuringExecution: 127 | - labelSelector: 128 | matchExpressions: 129 | - key: app 130 | operator: In 131 | values: 132 | - whatever 133 | topologyKey: kubernetes.io/hostname 134 | asserts: 135 | - equal: 136 | path: spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[0].topologyKey 137 | value: kubernetes.io/hostname 138 | - equal: 139 | path: spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[0].labelSelector.matchExpressions[0].key 140 | value: app 141 | - equal: 142 | path: spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[0].labelSelector.matchExpressions[0].values[0] 143 | value: whatever 144 | - it: should set a topologySpreadConstraints on kubernetes >= 1.19 145 | capabilities: 146 | majorVersion: 1 147 | minorVersion: 19 148 | set: 149 | topologySpreadConstraints: 150 | - labelSelector: 151 | matchLabels: 152 | app: whatever 153 | maxSkew: 1 154 | topologyKey: kubernetes.io/hostname 155 | asserts: 156 | - equal: 157 | path: spec.template.spec.topologySpreadConstraints[0].topologyKey 158 | value: kubernetes.io/hostname 159 | - equal: 160 | path: spec.template.spec.topologySpreadConstraints[0].labelSelector.matchLabels.app 161 | value: whatever 162 | - it: should set a templated topologySpreadConstraints on kubernetes >= 1.19 163 | capabilities: 164 | majorVersion: 1 165 | minorVersion: 19 166 | set: 167 | topologySpreadConstraints: 168 | - labelSelector: 169 | matchLabels: 170 | app: '{{ template "traefik.name" . }}' 171 | maxSkew: 1 172 | topologyKey: kubernetes.io/hostname 173 | asserts: 174 | - equal: 175 | path: spec.template.spec.topologySpreadConstraints[0].topologyKey 176 | value: kubernetes.io/hostname 177 | - equal: 178 | path: spec.template.spec.topologySpreadConstraints[0].labelSelector.matchLabels.app 179 | value: traefik 180 | - it: should set fail to set topologySpreadConstraints on kubernetes 1.18 181 | capabilities: 182 | majorVersion: 1 183 | minorVersion: 18 184 | set: 185 | topologySpreadConstraints: 186 | - maxSkew: 1 187 | topologyKey: kubernetes.io/hostname 188 | asserts: 189 | - failedTemplate: 190 | errorMessage: "topologySpreadConstraints are supported only on kubernetes >= v1.19" 191 | - it: should set instance label to release.name-release.namespace if no override is set 192 | asserts: 193 | - isSubset: 194 | path: spec.selector 195 | content: 196 | matchLabels: 197 | app.kubernetes.io/name: traefik 198 | app.kubernetes.io/instance: RELEASE-NAME-NAMESPACE 199 | - it: should set instance label to instanceLabelOverride if set 200 | set: 201 | instanceLabelOverride: traefik 202 | asserts: 203 | - isSubset: 204 | path: spec.selector 205 | content: 206 | matchLabels: 207 | app.kubernetes.io/name: traefik 208 | app.kubernetes.io/instance: traefik 209 | -------------------------------------------------------------------------------- /traefik/tests/ports-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Traefik configuration 2 | templates: 3 | - deployment.yaml 4 | - service.yaml 5 | tests: 6 | - it: should have port 8000 of pod published to 80 of service by default, and defined as entrypoint "web" 7 | asserts: 8 | - contains: 9 | path: spec.template.spec.containers[0].ports 10 | content: 11 | name: web 12 | containerPort: 8000 13 | protocol: TCP 14 | template: deployment.yaml 15 | - contains: 16 | path: spec.ports 17 | content: 18 | name: web 19 | port: 80 20 | protocol: TCP 21 | targetPort: web 22 | template: service.yaml 23 | - contains: 24 | path: spec.template.spec.containers[0].args 25 | content: "--entrypoints.web.address=:8000/tcp" 26 | template: deployment.yaml 27 | - it: should have port 8443 of pod published to 443 of service by default, and defined as entrypoint "websecure" 28 | asserts: 29 | - contains: 30 | path: spec.template.spec.containers[0].ports 31 | content: 32 | name: websecure 33 | containerPort: 8443 34 | protocol: TCP 35 | template: deployment.yaml 36 | - contains: 37 | path: spec.ports 38 | content: 39 | name: websecure 40 | port: 443 41 | protocol: TCP 42 | targetPort: websecure 43 | template: service.yaml 44 | - contains: 45 | path: spec.template.spec.containers[0].args 46 | content: "--entrypoints.websecure.address=:8443/tcp" 47 | template: deployment.yaml 48 | - it: should have port 9000 of pod exposed for probes but NOT published to the service by default 49 | asserts: 50 | - contains: 51 | path: spec.template.spec.containers[0].ports 52 | content: 53 | name: traefik 54 | containerPort: 9000 55 | protocol: TCP 56 | template: deployment.yaml 57 | - notContains: 58 | path: spec.ports 59 | content: 60 | name: traefik 61 | port: 9000 62 | targetPort: traefik 63 | template: service.yaml 64 | - contains: 65 | path: spec.template.spec.containers[0].args 66 | content: "--entrypoints.traefik.address=:9000/tcp" 67 | template: deployment.yaml 68 | - it: should have a custom port when specified via values 69 | set: 70 | ports: 71 | ssh: 72 | port: 22 73 | expose: true 74 | asserts: 75 | - contains: 76 | path: spec.template.spec.containers[0].ports 77 | content: 78 | name: ssh 79 | containerPort: 22 80 | protocol: TCP 81 | template: deployment.yaml 82 | - contains: 83 | path: spec.ports 84 | content: 85 | name: ssh 86 | port: 22 87 | protocol: TCP 88 | targetPort: ssh 89 | template: service.yaml 90 | - contains: 91 | path: spec.template.spec.containers[0].args 92 | content: "--entrypoints.ssh.address=:22/tcp" 93 | template: deployment.yaml 94 | - it: should have a hostPort when specified via values 95 | set: 96 | ports: 97 | ssh: 98 | port: 22 99 | expose: true 100 | hostPort: 22 101 | asserts: 102 | - contains: 103 | path: spec.template.spec.containers[0].ports 104 | content: 105 | name: ssh 106 | containerPort: 22 107 | hostPort: 22 108 | protocol: TCP 109 | template: deployment.yaml 110 | - contains: 111 | path: spec.ports 112 | content: 113 | name: ssh 114 | port: 22 115 | protocol: TCP 116 | targetPort: ssh 117 | template: service.yaml 118 | - contains: 119 | path: spec.template.spec.containers[0].args 120 | content: "--entrypoints.ssh.address=:22/tcp" 121 | template: deployment.yaml 122 | - it: should have a UDP custom port when specified via values 123 | set: 124 | ports: 125 | udp: 126 | port: 51 127 | expose: true 128 | protocol: UDP 129 | asserts: 130 | - contains: 131 | path: spec.template.spec.containers[0].ports 132 | content: 133 | name: udp 134 | containerPort: 51 135 | protocol: UDP 136 | template: deployment.yaml 137 | - contains: 138 | path: spec.ports 139 | content: 140 | name: udp 141 | port: 51 142 | protocol: UDP 143 | targetPort: udp 144 | template: service.yaml 145 | documentIndex: 0 146 | - contains: 147 | path: spec.template.spec.containers[0].args 148 | content: "--entrypoints.udp.address=:51/udp" 149 | template: deployment.yaml 150 | 151 | - it: should set entrypoint to default when configured 152 | template: deployment.yaml 153 | set: 154 | experimental: 155 | v3: 156 | enabled: true 157 | ports: 158 | web: 159 | asDefault: true 160 | websecure: 161 | asDefault: false 162 | asserts: 163 | - contains: 164 | path: spec.template.spec.containers[0].args 165 | content: "--entrypoints.web.asDefault=true" 166 | - notContains: 167 | path: spec.template.spec.containers[0].args 168 | content: "--entrypoints.websecure.asDefault=false" 169 | - notContains: 170 | path: spec.template.spec.containers[0].args 171 | content: "--entrypoints.websecure.asDefault=true" 172 | 173 | - it: should throw and error when default entrypoint is enabled without traefik v3 174 | template: deployment.yaml 175 | set: 176 | experimental: 177 | v3: 178 | enabled: false 179 | ports: 180 | web: 181 | asDefault: true 182 | websecure: 183 | asDefault: false 184 | asserts: 185 | - failedTemplate: 186 | errorMessage: "Default entrypoints are only available on Traefik v3. Please set `experimental.v3.enabled` to true and update `image.tag` to `v3.0`." 187 | 188 | - it: should be possible to use a different containerPort 189 | set: 190 | ports: 191 | ssh: 192 | port: 2222 193 | expose: true 194 | containerPort: 22 195 | asserts: 196 | - contains: 197 | path: spec.template.spec.containers[0].ports 198 | content: 199 | name: ssh 200 | containerPort: 22 201 | protocol: TCP 202 | template: deployment.yaml 203 | - contains: 204 | path: spec.ports 205 | content: 206 | name: ssh 207 | port: 2222 208 | protocol: TCP 209 | targetPort: ssh 210 | template: service.yaml 211 | - contains: 212 | path: spec.template.spec.containers[0].args 213 | content: "--entrypoints.ssh.address=:2222/tcp" 214 | template: deployment.yaml 215 | - it: should be possible to use same custom containerPort and keep default exposedPort 216 | set: 217 | ports: 218 | web: 219 | port: 666 220 | expose: true 221 | containerPort: 666 222 | asserts: 223 | - contains: 224 | path: spec.template.spec.containers[0].ports 225 | content: 226 | name: web 227 | containerPort: 666 228 | protocol: TCP 229 | template: deployment.yaml 230 | - contains: 231 | path: spec.ports 232 | content: 233 | name: web 234 | port: 80 235 | protocol: TCP 236 | targetPort: web 237 | template: service.yaml 238 | - contains: 239 | path: spec.template.spec.containers[0].args 240 | content: "--entrypoints.web.address=:666/tcp" 241 | template: deployment.yaml 242 | 243 | -------------------------------------------------------------------------------- /traefik/tests/rbac-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: RBAC configuration 2 | templates: 3 | - rbac/clusterrole.yaml 4 | - rbac/clusterrolebinding.yaml 5 | - rbac/role.yaml 6 | - rbac/rolebinding.yaml 7 | - rbac/serviceaccount.yaml 8 | - deployment.yaml 9 | tests: 10 | - it: should create default RBAC related objects 11 | asserts: 12 | - isKind: 13 | of: ClusterRole 14 | template: rbac/clusterrole.yaml 15 | - isKind: 16 | of: ClusterRoleBinding 17 | template: rbac/clusterrolebinding.yaml 18 | - hasDocuments: 19 | count: 0 20 | template: rbac/role.yaml 21 | - hasDocuments: 22 | count: 0 23 | template: rbac/rolebinding.yaml 24 | - isKind: 25 | of: ServiceAccount 26 | template: rbac/serviceaccount.yaml 27 | - equal: 28 | path: metadata.name 29 | value: RELEASE-NAME-traefik 30 | template: rbac/serviceaccount.yaml 31 | - equal: 32 | path: spec.template.spec.serviceAccountName 33 | value: RELEASE-NAME-traefik 34 | template: deployment.yaml 35 | - equal: 36 | path: subjects[0].name 37 | value: RELEASE-NAME-traefik 38 | template: rbac/clusterrolebinding.yaml 39 | - it: should not create RBAC related objects when disabled 40 | set: 41 | rbac: 42 | enabled: false 43 | asserts: 44 | - hasDocuments: 45 | count: 0 46 | template: rbac/clusterrole.yaml 47 | - hasDocuments: 48 | count: 0 49 | template: rbac/clusterrolebinding.yaml 50 | - hasDocuments: 51 | count: 0 52 | template: rbac/role.yaml 53 | - hasDocuments: 54 | count: 0 55 | template: rbac/rolebinding.yaml 56 | - it: should create RBAC related objects at namespace scope 57 | set: 58 | rbac: 59 | namespaced: true 60 | asserts: 61 | - isKind: 62 | of: Role 63 | template: rbac/role.yaml 64 | - isKind: 65 | of: RoleBinding 66 | template: rbac/rolebinding.yaml 67 | - notContains: 68 | path: rules 69 | content: 70 | - apiGroups: 71 | - extensions 72 | - networking.k8s.io 73 | resources: 74 | - ingresses 75 | verbs: 76 | - get 77 | - list 78 | - watch 79 | template: rbac/clusterrole.yaml 80 | - matchRegex: 81 | path: metadata.name 82 | pattern: ^.*-NAMESPACE$ 83 | template: rbac/clusterrole.yaml 84 | - matchRegex: 85 | path: metadata.name 86 | pattern: ^.*-NAMESPACE$ 87 | template: rbac/clusterrolebinding.yaml 88 | 89 | - it: should use existing ServiceAccount 90 | set: 91 | serviceAccount: 92 | name: foobar 93 | asserts: 94 | - hasDocuments: 95 | count: 0 96 | template: rbac/serviceaccount.yaml 97 | - equal: 98 | path: spec.template.spec.serviceAccountName 99 | value: foobar 100 | template: deployment.yaml 101 | - equal: 102 | path: subjects[0].name 103 | value: foobar 104 | template: rbac/clusterrolebinding.yaml 105 | - it: ClusterRole should not be able to update ingresses/status when kubernetesIngress is disabled 106 | set: 107 | providers: 108 | kubernetesIngress: 109 | enabled: false 110 | asserts: 111 | - notContains: 112 | path: rules 113 | content: 114 | - apiGroups: 115 | - extensions 116 | - networking.k8s.io 117 | resources: 118 | - ingresses/status 119 | verbs: 120 | - update 121 | template: rbac/clusterrole.yaml 122 | - it: ClusterRole should not be able to read CRDs when kubernetesCRD is disabled 123 | set: 124 | providers: 125 | kubernetesCRD: 126 | enabled: false 127 | asserts: 128 | - notContains: 129 | path: rules 130 | content: 131 | - apiGroups: 132 | - traefik.containo.us 133 | resources: 134 | - ingressroutes 135 | - ingressroutetcps 136 | - ingressrouteudps 137 | - middlewares 138 | - middlewaretcps 139 | - tlsoptions 140 | - tlsstores 141 | - traefikservices 142 | - serverstransports 143 | verbs: 144 | - get 145 | - list 146 | - watch 147 | template: rbac/clusterrole.yaml 148 | - it: "ClusterRole should not have aggregate-to-admin label by default" 149 | template: rbac/clusterrole.yaml 150 | asserts: 151 | - isNull: 152 | path: metadata.labels["rbac.authorization.k8s.io/aggregate-to-admin"] 153 | - it: "ClusterRole should be configurable with multiples aggregate-to- label" 154 | set: 155 | rbac: 156 | aggregateTo: [ "admin", "edit" ] 157 | template: rbac/clusterrole.yaml 158 | asserts: 159 | - equal: 160 | path: metadata.labels["rbac.authorization.k8s.io/aggregate-to-admin"] 161 | value: "true" 162 | - equal: 163 | path: metadata.labels["rbac.authorization.k8s.io/aggregate-to-edit"] 164 | value: "true" 165 | - it: should use helm managed namespace as default behavior 166 | set: 167 | rbac: 168 | namespaced: true 169 | asserts: 170 | - equal: 171 | path: metadata.namespace 172 | value: NAMESPACE 173 | template: rbac/role.yaml 174 | - equal: 175 | path: metadata.namespace 176 | value: NAMESPACE 177 | template: rbac/serviceaccount.yaml 178 | - it: should accept overridden namespace 179 | set: 180 | namespaceOverride: "traefik-ns-override" 181 | rbac: 182 | namespaced: true 183 | asserts: 184 | - equal: 185 | path: metadata.namespace 186 | value: "traefik-ns-override" 187 | template: rbac/role.yaml 188 | - equal: 189 | path: metadata.namespace 190 | value: "traefik-ns-override" 191 | template: rbac/serviceaccount.yaml 192 | - it: should use helm managed namespace for clusterrolebinding sa 193 | set: 194 | rbac: 195 | namespaced: true 196 | asserts: 197 | - equal: 198 | path: subjects[0].namespace 199 | value: NAMESPACE 200 | template: rbac/clusterrolebinding.yaml 201 | - it: should accept overridden namespace for clusterrolebinding sa 202 | set: 203 | namespaceOverride: "traefik-ns-override" 204 | rbac: 205 | namespaced: true 206 | asserts: 207 | - equal: 208 | path: subjects[0].namespace 209 | value: "traefik-ns-override" 210 | template: rbac/clusterrolebinding.yaml 211 | - it: should use helm managed namespace for rolebinding sa 212 | set: 213 | rbac: 214 | namespaced: true 215 | asserts: 216 | - equal: 217 | path: subjects[0].namespace 218 | value: NAMESPACE 219 | template: rbac/rolebinding.yaml 220 | - it: should accept overridden namespace for rolebinding sa 221 | set: 222 | namespaceOverride: "traefik-ns-override" 223 | rbac: 224 | namespaced: true 225 | asserts: 226 | - equal: 227 | path: subjects[0].namespace 228 | value: "traefik-ns-override" 229 | template: rbac/rolebinding.yaml 230 | - it: cluster rbac should be on both traefik.io and containo.us API group 231 | set: 232 | asserts: 233 | - template: rbac/clusterrole.yaml 234 | contains: 235 | path: rules 236 | content: 237 | apiGroups: 238 | - traefik.io 239 | - traefik.containo.us 240 | resources: 241 | - ingressroutes 242 | - ingressroutetcps 243 | - ingressrouteudps 244 | - middlewares 245 | - middlewaretcps 246 | - tlsoptions 247 | - tlsstores 248 | - traefikservices 249 | - serverstransports 250 | verbs: 251 | - get 252 | - list 253 | - watch 254 | - it: namespaced rbac should be on both traefik.io and containo.us API group 255 | set: 256 | rbac: 257 | namespaced: true 258 | asserts: 259 | - template: rbac/role.yaml 260 | contains: 261 | path: rules 262 | content: 263 | apiGroups: 264 | - traefik.io 265 | - traefik.containo.us 266 | resources: 267 | - ingressroutes 268 | - ingressroutetcps 269 | - ingressrouteudps 270 | - middlewares 271 | - middlewaretcps 272 | - tlsoptions 273 | - tlsstores 274 | - traefikservices 275 | - serverstransports 276 | verbs: 277 | - get 278 | - list 279 | - watch 280 | -------------------------------------------------------------------------------- /traefik/tests/service-config_test.yaml: -------------------------------------------------------------------------------- 1 | suite: Service configuration 2 | templates: 3 | - service.yaml 4 | tests: 5 | - it: should be a type LoadBalancer by default 6 | asserts: 7 | - equal: 8 | path: spec.type 9 | value: LoadBalancer 10 | - it: should be a custom type when specified via values 11 | set: 12 | service: 13 | type: NodePort 14 | asserts: 15 | - equal: 16 | path: spec.type 17 | value: NodePort 18 | - it: should have no annotations by default 19 | asserts: 20 | - isNull: 21 | path: metadata.annotations 22 | - it: should have customized annotations when specified via values 23 | set: 24 | service: 25 | annotations: 26 | azure-load-balancer-internal: true 27 | asserts: 28 | - equal: 29 | path: metadata.annotations.azure-load-balancer-internal 30 | value: true 31 | - it: should have customized labels when specified via values 32 | set: 33 | service: 34 | labels: 35 | custom-label: custom-value 36 | asserts: 37 | - equal: 38 | path: metadata.labels.custom-label 39 | value: custom-value 40 | - it: should have no load balancer class by default 41 | asserts: 42 | - isNull: 43 | path: spec.loadBalancerClass 44 | - it: should have custom spec elements when specified via values 45 | set: 46 | service: 47 | spec: 48 | externalTrafficPolicy: Cluster 49 | loadBalancerIP: "1.2.3.4" 50 | clusterIP: "2.3.4.5" 51 | loadBalancerClass: myclass 52 | loadBalancerSourceRanges: 53 | - 192.168.0.1/32 54 | - 172.16.0.0/16 55 | externalIPs: 56 | - "1.2.3.4" 57 | documentIndex: 0 58 | asserts: 59 | - equal: 60 | path: spec.ports[0].name 61 | value: web 62 | - equal: 63 | path: spec.ports[0].protocol 64 | value: TCP 65 | - equal: 66 | path: spec.externalTrafficPolicy 67 | value: Cluster 68 | - equal: 69 | path: spec.loadBalancerIP 70 | value: "1.2.3.4" 71 | - equal: 72 | path: spec.clusterIP 73 | value: "2.3.4.5" 74 | - equal: 75 | path: spec.loadBalancerSourceRanges[0] 76 | value: 192.168.0.1/32 77 | - equal: 78 | path: spec.loadBalancerSourceRanges[1] 79 | value: 172.16.0.0/16 80 | - equal: 81 | path: spec.externalIPs[0] 82 | value: "1.2.3.4" 83 | - equal: 84 | path: spec.loadBalancerClass 85 | value: myclass 86 | - it: should have custom spec elements when specified via values for TCP ports 87 | set: 88 | ports: 89 | web: 90 | expose: false 91 | websecure: 92 | expose: false 93 | tcp: 94 | port: 3000 95 | expose: true 96 | exposedPort: 8080 97 | protocol: TCP 98 | documentIndex: 0 99 | asserts: 100 | - equal: 101 | path: spec.ports[0].name 102 | value: tcp 103 | - equal: 104 | path: spec.ports[0].protocol 105 | value: TCP 106 | - equal: 107 | path: spec.ports[0].port 108 | value: 8080 109 | - it: should have custom spec elements when specified via values for UDP ports 110 | set: 111 | ports: 112 | web: 113 | expose: false 114 | websecure: 115 | expose: false 116 | udp: 117 | port: 3000 118 | expose: true 119 | exposedPort: 8080 120 | protocol: UDP 121 | documentIndex: 0 122 | asserts: 123 | - equal: 124 | path: spec.ports[0].name 125 | value: udp 126 | - equal: 127 | path: spec.ports[0].protocol 128 | value: UDP 129 | - equal: 130 | path: spec.ports[0].port 131 | value: 8080 132 | - it: should not have ipFamilyPolicy when not specified 133 | set: 134 | ports: 135 | udp: 136 | port: 3000 137 | protocol: UDP 138 | asserts: 139 | - isNull: 140 | path: spec.ipFamilyPolicy 141 | documentIndex: 0 142 | - it: should have custom ipFamilyPolicy when specified via values 143 | set: 144 | service: 145 | ipFamilyPolicy: PreferDualStack 146 | ports: 147 | udp: 148 | port: 3000 149 | protocol: UDP 150 | asserts: 151 | - equal: 152 | path: spec.ipFamilyPolicy 153 | value: PreferDualStack 154 | documentIndex: 0 155 | - it: should not have ipFamilies when not specified 156 | set: 157 | ports: 158 | udp: 159 | port: 3000 160 | protocol: UDP 161 | asserts: 162 | - isNull: 163 | path: spec.ipFamilies 164 | documentIndex: 0 165 | - it: should have custom ipFamilies when specified via values 166 | set: 167 | service: 168 | ipFamilies: 169 | - IPv6 170 | ports: 171 | udp: 172 | port: 3000 173 | protocol: UDP 174 | asserts: 175 | - equal: 176 | path: spec.ipFamilies 177 | value: 178 | - IPv6 179 | documentIndex: 0 180 | - it: should use default websecure UDP port when http3 is enabled 181 | set: 182 | ports: 183 | websecure: 184 | http3: 185 | enabled: true 186 | tls: 187 | enabled: true 188 | documentIndex: 0 189 | asserts: 190 | - equal: 191 | path: spec.ports[2].name 192 | value: "websecure-http3" 193 | - equal: 194 | path: spec.ports[2].port 195 | value: 443 196 | - equal: 197 | path: spec.ports[2].targetPort 198 | value: 8443 199 | - equal: 200 | path: spec.ports[2].protocol 201 | value: UDP 202 | - it: should be possible to advertise a different http3 UDP port 203 | set: 204 | ports: 205 | websecure: 206 | http3: 207 | enabled: true 208 | advertisedPort: 4443 209 | tls: 210 | enabled: true 211 | documentIndex: 0 212 | asserts: 213 | - equal: 214 | path: spec.ports[2].name 215 | value: "websecure-http3" 216 | - equal: 217 | path: spec.ports[2].port 218 | value: 4443 219 | - equal: 220 | path: spec.ports[2].targetPort 221 | value: 8443 222 | - equal: 223 | path: spec.ports[2].protocol 224 | value: UDP 225 | - it: should fail when there is no exposed port 226 | set: 227 | ports: 228 | web: 229 | expose: false 230 | websecure: 231 | expose: false 232 | asserts: 233 | - failedTemplate: 234 | errorMessage: "You need to expose at least one port or set enabled=false to service" 235 | documentIndex: 1 236 | - it: should not be possible to use http3 without enabling tls 237 | set: 238 | ports: 239 | websecure: 240 | tls: 241 | enabled: false 242 | http3: 243 | enabled: true 244 | asserts: 245 | - failedTemplate: 246 | errorMessage: "You cannot enable http3 without enabling tls" 247 | path: items[1].spec.ports[0].protocol 248 | value: UDP 249 | - it: should use helm managed namespace as default behavior UDP 250 | set: 251 | ports: 252 | udp: 253 | port: 3000 254 | protocol: UDP 255 | asserts: 256 | - equal: 257 | path: metadata.namespace 258 | value: NAMESPACE 259 | - it: should use helm managed namespace as default behavior TCP 260 | set: 261 | ports: 262 | tcp: 263 | port: 3000 264 | protocol: TCP 265 | asserts: 266 | - equal: 267 | path: metadata.namespace 268 | value: NAMESPACE 269 | - it: should accept overridden namespace UDP 270 | set: 271 | namespaceOverride: "traefik-ns-override" 272 | ports: 273 | udp: 274 | port: 3000 275 | protocol: UDP 276 | asserts: 277 | - equal: 278 | path: metadata.namespace 279 | value: "traefik-ns-override" 280 | - it: should accept overridden namespace TCP 281 | set: 282 | namespaceOverride: "traefik-ns-override" 283 | ports: 284 | tcp: 285 | port: 3000 286 | protocol: TCP 287 | asserts: 288 | - equal: 289 | path: metadata.namespace 290 | value: "traefik-ns-override" 291 | - it: should have different target port when targetPort is different from port 292 | set: 293 | ports: 294 | web: 295 | port: 8080 296 | exposedPort: 80 297 | expose: true 298 | targetPort: 80 299 | websecure: 300 | port: 443 301 | exposedPort: 443 302 | expose: true 303 | targetPort: 80 304 | documentIndex: 0 305 | asserts: 306 | - equal: 307 | path: spec.ports[0].port 308 | value: 80 309 | - equal: 310 | path: spec.ports[0].targetPort 311 | value: 80 312 | - equal: 313 | path: spec.ports[1].port 314 | value: 443 315 | - equal: 316 | path: spec.ports[1].targetPort 317 | value: 80 -------------------------------------------------------------------------------- /traefik/crds/traefik.containo.us_ingressroutetcps.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.6.2 8 | creationTimestamp: null 9 | name: ingressroutetcps.traefik.containo.us 10 | spec: 11 | group: traefik.containo.us 12 | names: 13 | kind: IngressRouteTCP 14 | listKind: IngressRouteTCPList 15 | plural: ingressroutetcps 16 | singular: ingressroutetcp 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: IngressRouteTCP is the CRD implementation of a Traefik TCP Router. 23 | properties: 24 | apiVersion: 25 | description: 'APIVersion defines the versioned schema of this representation 26 | of an object. Servers should convert recognized schemas to the latest 27 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 28 | type: string 29 | kind: 30 | description: 'Kind is a string value representing the REST resource this 31 | object represents. Servers may infer this from the endpoint the client 32 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 33 | type: string 34 | metadata: 35 | type: object 36 | spec: 37 | description: IngressRouteTCPSpec defines the desired state of IngressRouteTCP. 38 | properties: 39 | entryPoints: 40 | description: 'EntryPoints defines the list of entry point names to 41 | bind to. Entry points have to be configured in the static configuration. 42 | More info: https://doc.traefik.io/traefik/v2.9/routing/entrypoints/ 43 | Default: all.' 44 | items: 45 | type: string 46 | type: array 47 | routes: 48 | description: Routes defines the list of routes. 49 | items: 50 | description: RouteTCP holds the TCP route configuration. 51 | properties: 52 | match: 53 | description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.9/routing/routers/#rule_1' 54 | type: string 55 | middlewares: 56 | description: Middlewares defines the list of references to MiddlewareTCP 57 | resources. 58 | items: 59 | description: ObjectReference is a generic reference to a Traefik 60 | resource. 61 | properties: 62 | name: 63 | description: Name defines the name of the referenced Traefik 64 | resource. 65 | type: string 66 | namespace: 67 | description: Namespace defines the namespace of the referenced 68 | Traefik resource. 69 | type: string 70 | required: 71 | - name 72 | type: object 73 | type: array 74 | priority: 75 | description: 'Priority defines the router''s priority. More 76 | info: https://doc.traefik.io/traefik/v2.9/routing/routers/#priority_1' 77 | type: integer 78 | services: 79 | description: Services defines the list of TCP services. 80 | items: 81 | description: ServiceTCP defines an upstream TCP service to 82 | proxy traffic to. 83 | properties: 84 | name: 85 | description: Name defines the name of the referenced Kubernetes 86 | Service. 87 | type: string 88 | namespace: 89 | description: Namespace defines the namespace of the referenced 90 | Kubernetes Service. 91 | type: string 92 | port: 93 | anyOf: 94 | - type: integer 95 | - type: string 96 | description: Port defines the port of a Kubernetes Service. 97 | This can be a reference to a named port. 98 | x-kubernetes-int-or-string: true 99 | proxyProtocol: 100 | description: 'ProxyProtocol defines the PROXY protocol 101 | configuration. More info: https://doc.traefik.io/traefik/v2.9/routing/services/#proxy-protocol' 102 | properties: 103 | version: 104 | description: Version defines the PROXY Protocol version 105 | to use. 106 | type: integer 107 | type: object 108 | terminationDelay: 109 | description: TerminationDelay defines the deadline that 110 | the proxy sets, after one of its connected peers indicates 111 | it has closed the writing capability of its connection, 112 | to close the reading capability as well, hence fully 113 | terminating the connection. It is a duration in milliseconds, 114 | defaulting to 100. A negative value means an infinite 115 | deadline (i.e. the reading capability is never closed). 116 | type: integer 117 | weight: 118 | description: Weight defines the weight used when balancing 119 | requests between multiple Kubernetes Service. 120 | type: integer 121 | required: 122 | - name 123 | - port 124 | type: object 125 | type: array 126 | required: 127 | - match 128 | type: object 129 | type: array 130 | tls: 131 | description: 'TLS defines the TLS configuration on a layer 4 / TCP 132 | Route. More info: https://doc.traefik.io/traefik/v2.9/routing/routers/#tls_1' 133 | properties: 134 | certResolver: 135 | description: 'CertResolver defines the name of the certificate 136 | resolver to use. Cert resolvers have to be configured in the 137 | static configuration. More info: https://doc.traefik.io/traefik/v2.9/https/acme/#certificate-resolvers' 138 | type: string 139 | domains: 140 | description: 'Domains defines the list of domains that will be 141 | used to issue certificates. More info: https://doc.traefik.io/traefik/v2.9/routing/routers/#domains' 142 | items: 143 | description: Domain holds a domain name with SANs. 144 | properties: 145 | main: 146 | description: Main defines the main domain name. 147 | type: string 148 | sans: 149 | description: SANs defines the subject alternative domain 150 | names. 151 | items: 152 | type: string 153 | type: array 154 | type: object 155 | type: array 156 | options: 157 | description: 'Options defines the reference to a TLSOption, that 158 | specifies the parameters of the TLS connection. If not defined, 159 | the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.9/https/tls/#tls-options' 160 | properties: 161 | name: 162 | description: Name defines the name of the referenced Traefik 163 | resource. 164 | type: string 165 | namespace: 166 | description: Namespace defines the namespace of the referenced 167 | Traefik resource. 168 | type: string 169 | required: 170 | - name 171 | type: object 172 | passthrough: 173 | description: Passthrough defines whether a TLS router will terminate 174 | the TLS connection. 175 | type: boolean 176 | secretName: 177 | description: SecretName is the name of the referenced Kubernetes 178 | Secret to specify the certificate details. 179 | type: string 180 | store: 181 | description: Store defines the reference to the TLSStore, that 182 | will be used to store certificates. Please note that only `default` 183 | TLSStore can be used. 184 | properties: 185 | name: 186 | description: Name defines the name of the referenced Traefik 187 | resource. 188 | type: string 189 | namespace: 190 | description: Namespace defines the namespace of the referenced 191 | Traefik resource. 192 | type: string 193 | required: 194 | - name 195 | type: object 196 | type: object 197 | required: 198 | - routes 199 | type: object 200 | required: 201 | - metadata 202 | - spec 203 | type: object 204 | served: true 205 | storage: true 206 | status: 207 | acceptedNames: 208 | kind: "" 209 | plural: "" 210 | conditions: [] 211 | storedVersions: [] 212 | --------------------------------------------------------------------------------