1015 lines
24 KiB
Markdown
1015 lines
24 KiB
Markdown
|
# Install as a DaemonSet
|
||
|
|
||
|
Default install is using a `Deployment` but it's possible to use `DaemonSet`
|
||
|
|
||
|
```yaml
|
||
|
deployment:
|
||
|
kind: DaemonSet
|
||
|
```
|
||
|
|
||
|
# Configure traefik Pod parameters
|
||
|
|
||
|
## Extending /etc/hosts records
|
||
|
|
||
|
In some specific cases, you'll need to add extra records to the `/etc/hosts` file for the Traefik containers.
|
||
|
You can configure it using [hostAliases](https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/):
|
||
|
|
||
|
```yaml
|
||
|
deployment:
|
||
|
hostAliases:
|
||
|
- ip: "127.0.0.1" # this is an example
|
||
|
hostnames:
|
||
|
- "foo.local"
|
||
|
- "bar.local"
|
||
|
```
|
||
|
## Extending DNS config
|
||
|
|
||
|
In order to configure additional DNS servers for your traefik pod, you can use `dnsConfig` option:
|
||
|
|
||
|
```yaml
|
||
|
deployment:
|
||
|
dnsConfig:
|
||
|
nameservers:
|
||
|
- 192.0.2.1 # this is an example
|
||
|
searches:
|
||
|
- ns1.svc.cluster-domain.example
|
||
|
- my.dns.search.suffix
|
||
|
options:
|
||
|
- name: ndots
|
||
|
value: "2"
|
||
|
- name: edns0
|
||
|
```
|
||
|
|
||
|
# Install in a dedicated namespace, with limited RBAC
|
||
|
|
||
|
Default install is using Cluster-wide RBAC but it can be restricted to target namespace.
|
||
|
|
||
|
```yaml
|
||
|
rbac:
|
||
|
namespaced: true
|
||
|
```
|
||
|
|
||
|
# Install with auto-scaling
|
||
|
|
||
|
When enabling [HPA](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/)
|
||
|
to adjust replicas count according to CPU Usage, you'll need to set resources and nullify replicas.
|
||
|
|
||
|
```yaml
|
||
|
deployment:
|
||
|
replicas: null
|
||
|
resources:
|
||
|
requests:
|
||
|
cpu: "100m"
|
||
|
memory: "50Mi"
|
||
|
limits:
|
||
|
cpu: "300m"
|
||
|
memory: "150Mi"
|
||
|
autoscaling:
|
||
|
enabled: true
|
||
|
maxReplicas: 2
|
||
|
metrics:
|
||
|
- type: Resource
|
||
|
resource:
|
||
|
name: cpu
|
||
|
target:
|
||
|
type: Utilization
|
||
|
averageUtilization: 80
|
||
|
```
|
||
|
|
||
|
# Access Traefik dashboard without exposing it
|
||
|
|
||
|
This Chart does not expose the Traefik local dashboard by default. It's explained in upstream [documentation](https://doc.traefik.io/traefik/operations/api/) why:
|
||
|
|
||
|
> Enabling the API in production is not recommended, because it will expose all configuration elements, including sensitive data.
|
||
|
|
||
|
It says also:
|
||
|
|
||
|
> In production, it should be at least secured by authentication and authorizations.
|
||
|
|
||
|
Thus, there are multiple ways to expose the dashboard. For instance, after enabling the creation of dashboard `IngressRoute` in the values:
|
||
|
|
||
|
```yaml
|
||
|
ingressRoute:
|
||
|
dashboard:
|
||
|
enabled: true
|
||
|
```
|
||
|
|
||
|
The traefik admin port can be forwarded locally:
|
||
|
|
||
|
```bash
|
||
|
kubectl port-forward $(kubectl get pods --selector "app.kubernetes.io/name=traefik" --output=name) 8080:8080
|
||
|
```
|
||
|
|
||
|
This command makes the dashboard accessible on the url: http://127.0.0.1:8080/dashboard/
|
||
|
|
||
|
# Publish and protect Traefik Dashboard with basic Auth
|
||
|
|
||
|
To expose the dashboard in a secure way as [recommended](https://doc.traefik.io/traefik/operations/dashboard/#dashboard-router-rule)
|
||
|
in the documentation, it may be useful to override the router rule to specify
|
||
|
a domain to match, or accept requests on the root path (/) in order to redirect
|
||
|
them to /dashboard/.
|
||
|
|
||
|
```yaml
|
||
|
# Create an IngressRoute for the dashboard
|
||
|
ingressRoute:
|
||
|
dashboard:
|
||
|
enabled: true
|
||
|
# Custom match rule with host domain
|
||
|
matchRule: Host(`traefik-dashboard.example.com`)
|
||
|
entryPoints: ["websecure"]
|
||
|
# Add custom middlewares : authentication and redirection
|
||
|
middlewares:
|
||
|
- name: traefik-dashboard-auth
|
||
|
|
||
|
# Create the custom middlewares used by the IngressRoute dashboard (can also be created in another way).
|
||
|
# /!\ Yes, you need to replace "changeme" password with a better one. /!\
|
||
|
extraObjects:
|
||
|
- apiVersion: v1
|
||
|
kind: Secret
|
||
|
metadata:
|
||
|
name: traefik-dashboard-auth-secret
|
||
|
type: kubernetes.io/basic-auth
|
||
|
stringData:
|
||
|
username: admin
|
||
|
password: changeme
|
||
|
|
||
|
- apiVersion: traefik.io/v1alpha1
|
||
|
kind: Middleware
|
||
|
metadata:
|
||
|
name: traefik-dashboard-auth
|
||
|
spec:
|
||
|
basicAuth:
|
||
|
secret: traefik-dashboard-auth-secret
|
||
|
```
|
||
|
|
||
|
# Publish and protect Traefik Dashboard with an Ingress
|
||
|
|
||
|
To expose the dashboard without IngressRoute, it's more complicated and less
|
||
|
secure. You'll need to create an internal Service exposing Traefik API with
|
||
|
special _traefik_ entrypoint. This internal Service can be created from an other tool, with the `extraObjects` section or using [custom services](#add-custom-internal-services).
|
||
|
|
||
|
You'll need to double check:
|
||
|
1. Service selector with your setup.
|
||
|
2. Middleware annotation on the ingress, _default_ should be replaced with traefik's namespace
|
||
|
|
||
|
```yaml
|
||
|
ingressRoute:
|
||
|
dashboard:
|
||
|
enabled: false
|
||
|
additionalArguments:
|
||
|
- "--api.insecure=true"
|
||
|
# Create the service, middleware and Ingress used to expose the dashboard (can also be created in another way).
|
||
|
# /!\ Yes, you need to replace "changeme" password with a better one. /!\
|
||
|
extraObjects:
|
||
|
- apiVersion: v1
|
||
|
kind: Service
|
||
|
metadata:
|
||
|
name: traefik-api
|
||
|
spec:
|
||
|
type: ClusterIP
|
||
|
selector:
|
||
|
app.kubernetes.io/name: traefik
|
||
|
app.kubernetes.io/instance: traefik-default
|
||
|
ports:
|
||
|
- port: 8080
|
||
|
name: traefik
|
||
|
targetPort: 8080
|
||
|
protocol: TCP
|
||
|
|
||
|
- apiVersion: v1
|
||
|
kind: Secret
|
||
|
metadata:
|
||
|
name: traefik-dashboard-auth-secret
|
||
|
type: kubernetes.io/basic-auth
|
||
|
stringData:
|
||
|
username: admin
|
||
|
password: changeme
|
||
|
|
||
|
- apiVersion: traefik.io/v1alpha1
|
||
|
kind: Middleware
|
||
|
metadata:
|
||
|
name: traefik-dashboard-auth
|
||
|
spec:
|
||
|
basicAuth:
|
||
|
secret: traefik-dashboard-auth-secret
|
||
|
|
||
|
- apiVersion: networking.k8s.io/v1
|
||
|
kind: Ingress
|
||
|
metadata:
|
||
|
name: traefik-dashboard
|
||
|
annotations:
|
||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||
|
traefik.ingress.kubernetes.io/router.middlewares: default-traefik-dashboard-auth@kubernetescrd
|
||
|
spec:
|
||
|
rules:
|
||
|
- host: traefik-dashboard.example.com
|
||
|
http:
|
||
|
paths:
|
||
|
- path: /
|
||
|
pathType: Prefix
|
||
|
backend:
|
||
|
service:
|
||
|
name: traefik-api
|
||
|
port:
|
||
|
name: traefik
|
||
|
```
|
||
|
|
||
|
|
||
|
# Install on AWS
|
||
|
|
||
|
It can use [native AWS support](https://kubernetes.io/docs/concepts/services-networking/service/#aws-nlb-support) on Kubernetes
|
||
|
|
||
|
```yaml
|
||
|
service:
|
||
|
annotations:
|
||
|
service.beta.kubernetes.io/aws-load-balancer-type: nlb
|
||
|
```
|
||
|
|
||
|
Or if [AWS LB controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/service/annotations/#legacy-cloud-provider) is installed :
|
||
|
```yaml
|
||
|
service:
|
||
|
annotations:
|
||
|
service.beta.kubernetes.io/aws-load-balancer-type: nlb-ip
|
||
|
```
|
||
|
|
||
|
# Install on GCP
|
||
|
|
||
|
A [regional IP with a Service](https://cloud.google.com/kubernetes-engine/docs/tutorials/configuring-domain-name-static-ip#use_a_service) can be used
|
||
|
```yaml
|
||
|
service:
|
||
|
spec:
|
||
|
loadBalancerIP: "1.2.3.4"
|
||
|
```
|
||
|
|
||
|
Or a [global IP on Ingress](https://cloud.google.com/kubernetes-engine/docs/tutorials/configuring-domain-name-static-ip#use_an_ingress)
|
||
|
```yaml
|
||
|
service:
|
||
|
type: NodePort
|
||
|
extraObjects:
|
||
|
- apiVersion: networking.k8s.io/v1
|
||
|
kind: Ingress
|
||
|
metadata:
|
||
|
name: traefik
|
||
|
annotations:
|
||
|
kubernetes.io/ingress.global-static-ip-name: "myGlobalIpName"
|
||
|
spec:
|
||
|
defaultBackend:
|
||
|
service:
|
||
|
name: traefik
|
||
|
port:
|
||
|
number: 80
|
||
|
```
|
||
|
|
||
|
Or a [global IP on a Gateway](https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-gateways) with continuous HTTPS encryption.
|
||
|
|
||
|
```yaml
|
||
|
ports:
|
||
|
websecure:
|
||
|
appProtocol: HTTPS # Hint for Google L7 load balancer
|
||
|
service:
|
||
|
type: ClusterIP
|
||
|
extraObjects:
|
||
|
- apiVersion: gateway.networking.k8s.io/v1beta1
|
||
|
kind: Gateway
|
||
|
metadata:
|
||
|
name: traefik
|
||
|
annotations:
|
||
|
networking.gke.io/certmap: "myCertificateMap"
|
||
|
spec:
|
||
|
gatewayClassName: gke-l7-global-external-managed
|
||
|
addresses:
|
||
|
- type: NamedAddress
|
||
|
value: "myGlobalIPName"
|
||
|
listeners:
|
||
|
- name: https
|
||
|
protocol: HTTPS
|
||
|
port: 443
|
||
|
- apiVersion: gateway.networking.k8s.io/v1beta1
|
||
|
kind: HTTPRoute
|
||
|
metadata:
|
||
|
name: traefik
|
||
|
spec:
|
||
|
parentRefs:
|
||
|
- kind: Gateway
|
||
|
name: traefik
|
||
|
rules:
|
||
|
- backendRefs:
|
||
|
- name: traefik
|
||
|
port: 443
|
||
|
- apiVersion: networking.gke.io/v1
|
||
|
kind: HealthCheckPolicy
|
||
|
metadata:
|
||
|
name: traefik
|
||
|
spec:
|
||
|
default:
|
||
|
config:
|
||
|
type: HTTP
|
||
|
httpHealthCheck:
|
||
|
port: 8080
|
||
|
requestPath: /ping
|
||
|
targetRef:
|
||
|
group: ""
|
||
|
kind: Service
|
||
|
name: traefik
|
||
|
```
|
||
|
|
||
|
# Install on Azure
|
||
|
|
||
|
A [static IP on a resource group](https://learn.microsoft.com/en-us/azure/aks/static-ip) can be used:
|
||
|
|
||
|
```yaml
|
||
|
service:
|
||
|
spec:
|
||
|
loadBalancerIP: "1.2.3.4"
|
||
|
annotations:
|
||
|
service.beta.kubernetes.io/azure-load-balancer-resource-group: myResourceGroup
|
||
|
```
|
||
|
|
||
|
Here is a more complete example, using also native Let's encrypt feature of Traefik Proxy with Azure DNS:
|
||
|
|
||
|
```yaml
|
||
|
persistence:
|
||
|
enabled: true
|
||
|
size: 128Mi
|
||
|
certificatesResolvers:
|
||
|
letsencrypt:
|
||
|
acme:
|
||
|
email: "{{ letsencrypt_email }}"
|
||
|
#caServer: https://acme-v02.api.letsencrypt.org/directory # Production server
|
||
|
caServer: https://acme-staging-v02.api.letsencrypt.org/directory # Staging server
|
||
|
dnsChallenge:
|
||
|
provider: azuredns
|
||
|
storage: /data/acme.json
|
||
|
env:
|
||
|
- name: AZURE_CLIENT_ID
|
||
|
value: "{{ azure_dns_challenge_application_id }}"
|
||
|
- name: AZURE_CLIENT_SECRET
|
||
|
valueFrom:
|
||
|
secretKeyRef:
|
||
|
name: azuredns-secret
|
||
|
key: client-secret
|
||
|
- name: AZURE_SUBSCRIPTION_ID
|
||
|
value: "{{ azure_subscription_id }}"
|
||
|
- name: AZURE_TENANT_ID
|
||
|
value: "{{ azure_tenant_id }}"
|
||
|
- name: AZURE_RESOURCE_GROUP
|
||
|
value: "{{ azure_resource_group }}"
|
||
|
deployment:
|
||
|
initContainers:
|
||
|
- name: volume-permissions
|
||
|
image: busybox:latest
|
||
|
command: ["sh", "-c", "ls -la /; touch /data/acme.json; chmod -v 600 /data/acme.json"]
|
||
|
volumeMounts:
|
||
|
- mountPath: /data
|
||
|
name: data
|
||
|
podSecurityContext:
|
||
|
fsGroup: 65532
|
||
|
fsGroupChangePolicy: "OnRootMismatch"
|
||
|
service:
|
||
|
spec:
|
||
|
type: LoadBalancer
|
||
|
annotations:
|
||
|
service.beta.kubernetes.io/azure-load-balancer-resource-group: "{{ azure_node_resource_group }}"
|
||
|
service.beta.kubernetes.io/azure-pip-name: "{{ azure_resource_group }}"
|
||
|
service.beta.kubernetes.io/azure-dns-label-name: "{{ azure_resource_group }}"
|
||
|
service.beta.kubernetes.io/azure-allowed-ip-ranges: "{{ ip_range | join(',') }}"
|
||
|
extraObjects:
|
||
|
- apiVersion: v1
|
||
|
kind: Secret
|
||
|
metadata:
|
||
|
name: azuredns-secret
|
||
|
namespace: traefik
|
||
|
type: Opaque
|
||
|
stringData:
|
||
|
client-secret: "{{ azure_dns_challenge_application_secret }}"
|
||
|
```
|
||
|
|
||
|
# Use an IngressClass
|
||
|
|
||
|
Default install comes with an `IngressClass` resource that can be enabled on providers.
|
||
|
|
||
|
Here's how one can enable it on CRD & Ingress Kubernetes provider:
|
||
|
|
||
|
```yaml
|
||
|
ingressClass:
|
||
|
name: traefik
|
||
|
providers:
|
||
|
kubernetesCRD:
|
||
|
ingressClass: traefik
|
||
|
kubernetesIngress:
|
||
|
ingressClass: traefik
|
||
|
```
|
||
|
|
||
|
# Use HTTP3
|
||
|
|
||
|
By default, it will use a Load balancers with mixed protocols on `websecure`
|
||
|
entrypoint. They are available since v1.20 and in beta as of Kubernetes v1.24.
|
||
|
Availability may depend on your Kubernetes provider.
|
||
|
|
||
|
When using TCP and UDP with a single service, you may encounter [this issue](https://github.com/kubernetes/kubernetes/issues/47249#issuecomment-587960741) from Kubernetes.
|
||
|
If you want to avoid this issue, you can set `ports.websecure.http3.advertisedPort`
|
||
|
to an other value than 443
|
||
|
|
||
|
```yaml
|
||
|
ports:
|
||
|
websecure:
|
||
|
http3:
|
||
|
enabled: true
|
||
|
```
|
||
|
|
||
|
You can also create two `Service`, one for TCP and one for UDP:
|
||
|
|
||
|
```yaml
|
||
|
ports:
|
||
|
websecure:
|
||
|
http3:
|
||
|
enabled: true
|
||
|
service:
|
||
|
single: false
|
||
|
```
|
||
|
|
||
|
# Use PROXY protocol on Digital Ocean
|
||
|
|
||
|
PROXY protocol is a protocol for sending client connection information, such as origin IP addresses and port numbers, to the final backend server, rather than discarding it at the load balancer.
|
||
|
|
||
|
```yaml
|
||
|
.DOTrustedIPs: &DOTrustedIPs
|
||
|
- 127.0.0.1/32
|
||
|
- 10.120.0.0/16
|
||
|
|
||
|
service:
|
||
|
enabled: true
|
||
|
type: LoadBalancer
|
||
|
annotations:
|
||
|
# This will tell DigitalOcean to enable the proxy protocol.
|
||
|
service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
|
||
|
spec:
|
||
|
# This is the default and should stay as cluster to keep the DO health checks working.
|
||
|
externalTrafficPolicy: Cluster
|
||
|
|
||
|
ports:
|
||
|
web:
|
||
|
forwardedHeaders:
|
||
|
trustedIPs: *DOTrustedIPs
|
||
|
proxyProtocol:
|
||
|
trustedIPs: *DOTrustedIPs
|
||
|
websecure:
|
||
|
forwardedHeaders:
|
||
|
trustedIPs: *DOTrustedIPs
|
||
|
proxyProtocol:
|
||
|
trustedIPs: *DOTrustedIPs
|
||
|
```
|
||
|
|
||
|
# Enable plugin storage
|
||
|
|
||
|
This chart follows common security practices: it runs as non root with a readonly root filesystem.
|
||
|
When enabling a plugin which needs storage, you have to add it to the deployment.
|
||
|
|
||
|
Here is a simple example with crowdsec. You may want to replace with your plugin or see complete exemple on crowdsec [here](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/kubernetes/README.md).
|
||
|
|
||
|
```yaml
|
||
|
deployment:
|
||
|
additionalVolumes:
|
||
|
- name: plugins
|
||
|
additionalVolumeMounts:
|
||
|
- name: plugins
|
||
|
mountPath: /plugins-storage
|
||
|
additionalArguments:
|
||
|
- "--experimental.plugins.bouncer.moduleName=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
|
||
|
- "--experimental.plugins.bouncer.version=v1.1.9"
|
||
|
```
|
||
|
|
||
|
# Use Traefik native Let's Encrypt integration, without cert-manager
|
||
|
|
||
|
In Traefik Proxy, ACME certificates are stored in a JSON file.
|
||
|
|
||
|
This file needs to have 0600 permissions, meaning, only the owner of the file has full read and write access to it.
|
||
|
By default, Kubernetes recursively changes ownership and permissions for the content of each volume.
|
||
|
|
||
|
=> An initContainer can be used to avoid an issue on this sensitive file.
|
||
|
See [#396](https://github.com/traefik/traefik-helm-chart/issues/396) for more details.
|
||
|
|
||
|
Once the provider is ready, it can be used in an `IngressRoute`:
|
||
|
|
||
|
```yaml
|
||
|
apiVersion: traefik.io/v1alpha1
|
||
|
kind: IngressRoute
|
||
|
metadata:
|
||
|
name: [...]
|
||
|
spec:
|
||
|
entryPoints: [...]
|
||
|
routes: [...]
|
||
|
tls:
|
||
|
certResolver: letsencrypt
|
||
|
```
|
||
|
|
||
|
:information_source: Change `apiVersion` to `traefik.containo.us/v1alpha1` for charts prior to v28.0.0
|
||
|
|
||
|
See [the list of supported providers](https://doc.traefik.io/traefik/https/acme/#providers) for others.
|
||
|
|
||
|
## Example with CloudFlare
|
||
|
|
||
|
This example needs a CloudFlare token in a Kubernetes `Secret` and a working `StorageClass`.
|
||
|
|
||
|
**Step 1**: Create `Secret` with CloudFlare token:
|
||
|
|
||
|
```yaml
|
||
|
---
|
||
|
apiVersion: v1
|
||
|
kind: Secret
|
||
|
metadata:
|
||
|
name: cloudflare
|
||
|
type: Opaque
|
||
|
stringData:
|
||
|
token: {{ SET_A_VALID_TOKEN_HERE }}
|
||
|
```
|
||
|
|
||
|
**Step 2**:
|
||
|
|
||
|
```yaml
|
||
|
persistence:
|
||
|
enabled: true
|
||
|
storageClass: xxx
|
||
|
certificatesResolvers:
|
||
|
letsencrypt:
|
||
|
acme:
|
||
|
dnsChallenge:
|
||
|
provider: cloudflare
|
||
|
storage: /data/acme.json
|
||
|
env:
|
||
|
- name: CF_DNS_API_TOKEN
|
||
|
valueFrom:
|
||
|
secretKeyRef:
|
||
|
name: cloudflare
|
||
|
key: token
|
||
|
deployment:
|
||
|
initContainers:
|
||
|
- name: volume-permissions
|
||
|
image: busybox:latest
|
||
|
command: ["sh", "-c", "touch /data/acme.json; chmod -v 600 /data/acme.json"]
|
||
|
volumeMounts:
|
||
|
- mountPath: /data
|
||
|
name: data
|
||
|
podSecurityContext:
|
||
|
fsGroup: 65532
|
||
|
fsGroupChangePolicy: "OnRootMismatch"
|
||
|
```
|
||
|
|
||
|
>[!NOTE]
|
||
|
> With [Traefik Hub](https://traefik.io/traefik-hub/), certificates can be stored as a `Secret` on Kubernetes with `distributedAcme` resolver.
|
||
|
|
||
|
# Provide default certificate with cert-manager and CloudFlare DNS
|
||
|
|
||
|
Setup:
|
||
|
|
||
|
* cert-manager installed in `cert-manager` namespace
|
||
|
* A cloudflare account on a DNS Zone
|
||
|
|
||
|
**Step 1**: Create `Secret` and `Issuer` needed by `cert-manager` with your API Token.
|
||
|
See [cert-manager documentation](https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/)
|
||
|
for creating this token with needed rights:
|
||
|
|
||
|
```yaml
|
||
|
---
|
||
|
apiVersion: v1
|
||
|
kind: Secret
|
||
|
metadata:
|
||
|
name: cloudflare
|
||
|
namespace: traefik
|
||
|
type: Opaque
|
||
|
stringData:
|
||
|
api-token: XXX
|
||
|
---
|
||
|
apiVersion: cert-manager.io/v1
|
||
|
kind: Issuer
|
||
|
metadata:
|
||
|
name: cloudflare
|
||
|
namespace: traefik
|
||
|
spec:
|
||
|
acme:
|
||
|
server: https://acme-v02.api.letsencrypt.org/directory
|
||
|
email: email@example.com
|
||
|
privateKeySecretRef:
|
||
|
name: cloudflare-key
|
||
|
solvers:
|
||
|
- dns01:
|
||
|
cloudflare:
|
||
|
apiTokenSecretRef:
|
||
|
name: cloudflare
|
||
|
key: api-token
|
||
|
```
|
||
|
|
||
|
**Step 2**: Create `Certificate` in traefik namespace
|
||
|
|
||
|
```yaml
|
||
|
apiVersion: cert-manager.io/v1
|
||
|
kind: Certificate
|
||
|
metadata:
|
||
|
name: wildcard-example-com
|
||
|
namespace: traefik
|
||
|
spec:
|
||
|
secretName: wildcard-example-com-tls
|
||
|
dnsNames:
|
||
|
- "example.com"
|
||
|
- "*.example.com"
|
||
|
issuerRef:
|
||
|
name: cloudflare
|
||
|
kind: Issuer
|
||
|
```
|
||
|
|
||
|
**Step 3**: Check that it's ready
|
||
|
|
||
|
```bash
|
||
|
kubectl get certificate -n traefik
|
||
|
```
|
||
|
|
||
|
If needed, logs of cert-manager pod can give you more information
|
||
|
|
||
|
**Step 4**: Use it on the TLS Store in **values.yaml** file for this Helm Chart
|
||
|
|
||
|
```yaml
|
||
|
tlsStore:
|
||
|
default:
|
||
|
defaultCertificate:
|
||
|
secretName: wildcard-example-com-tls
|
||
|
```
|
||
|
|
||
|
**Step 5**: Enjoy. All your `IngressRoute` use this certificate by default now.
|
||
|
|
||
|
They should use websecure entrypoint like this:
|
||
|
|
||
|
```yaml
|
||
|
apiVersion: traefik.io/v1alpha1
|
||
|
kind: IngressRoute
|
||
|
metadata:
|
||
|
name: example-com-tls
|
||
|
spec:
|
||
|
entryPoints:
|
||
|
- websecure
|
||
|
routes:
|
||
|
- match: Host(`test.example.com`)
|
||
|
kind: Rule
|
||
|
services:
|
||
|
- name: XXXX
|
||
|
port: 80
|
||
|
```
|
||
|
|
||
|
# Add custom (internal) services
|
||
|
|
||
|
In some cases you might want to have more than one Traefik service within your cluster,
|
||
|
e.g. a default (external) one and a service that is only exposed internally to pods within your cluster.
|
||
|
|
||
|
The `service.additionalServices` allows you to add an arbitrary amount of services,
|
||
|
provided as a name to service details mapping; for example you can use the following values:
|
||
|
|
||
|
```yaml
|
||
|
service:
|
||
|
additionalServices:
|
||
|
internal:
|
||
|
type: ClusterIP
|
||
|
labels:
|
||
|
traefik-service-label: internal
|
||
|
```
|
||
|
|
||
|
Ports can then be exposed on this service by using the port name to boolean mapping `expose` on the respective port;
|
||
|
e.g. to expose the `traefik` API port on your internal service so pods within your cluster can use it, you can do:
|
||
|
|
||
|
```yaml
|
||
|
ports:
|
||
|
traefik:
|
||
|
expose:
|
||
|
# Sensitive data should not be exposed on the internet
|
||
|
# => Keep this disabled !
|
||
|
default: false
|
||
|
internal: true
|
||
|
```
|
||
|
|
||
|
This will then provide an additional Service manifest, looking like this:
|
||
|
|
||
|
```yaml
|
||
|
---
|
||
|
# Source: traefik/templates/service.yaml
|
||
|
apiVersion: v1
|
||
|
kind: Service
|
||
|
metadata:
|
||
|
name: traefik-internal
|
||
|
namespace: traefik
|
||
|
[...]
|
||
|
spec:
|
||
|
type: ClusterIP
|
||
|
selector:
|
||
|
app.kubernetes.io/name: traefik
|
||
|
app.kubernetes.io/instance: traefik-traefik
|
||
|
ports:
|
||
|
- port: 8080
|
||
|
name: "traefik"
|
||
|
targetPort: traefik
|
||
|
protocol: TCP
|
||
|
```
|
||
|
|
||
|
# Use this Chart as a dependency of your own chart
|
||
|
|
||
|
|
||
|
First, let's create a default Helm Chart, with Traefik as a dependency.
|
||
|
```bash
|
||
|
helm create foo
|
||
|
cd foo
|
||
|
echo "
|
||
|
dependencies:
|
||
|
- name: traefik
|
||
|
version: "24.0.0"
|
||
|
repository: "https://traefik.github.io/charts"
|
||
|
" >> Chart.yaml
|
||
|
```
|
||
|
|
||
|
Second, let's tune some values like enabling HPA:
|
||
|
|
||
|
```bash
|
||
|
cat <<-EOF >> values.yaml
|
||
|
traefik:
|
||
|
autoscaling:
|
||
|
enabled: true
|
||
|
maxReplicas: 3
|
||
|
EOF
|
||
|
```
|
||
|
|
||
|
Third, one can see if it works as expected:
|
||
|
```bash
|
||
|
helm dependency update
|
||
|
helm dependency build
|
||
|
helm template . | grep -A 14 -B 3 Horizontal
|
||
|
```
|
||
|
|
||
|
It should produce this output:
|
||
|
|
||
|
```yaml
|
||
|
---
|
||
|
# Source: foo/charts/traefik/templates/hpa.yaml
|
||
|
apiVersion: autoscaling/v2
|
||
|
kind: HorizontalPodAutoscaler
|
||
|
metadata:
|
||
|
name: release-name-traefik
|
||
|
namespace: flux-system
|
||
|
labels:
|
||
|
app.kubernetes.io/name: traefik
|
||
|
app.kubernetes.io/instance: release-name-flux-system
|
||
|
helm.sh/chart: traefik-24.0.0
|
||
|
app.kubernetes.io/managed-by: Helm
|
||
|
spec:
|
||
|
scaleTargetRef:
|
||
|
apiVersion: apps/v1
|
||
|
kind: Deployment
|
||
|
name: release-name-traefik
|
||
|
maxReplicas: 3
|
||
|
```
|
||
|
|
||
|
# Configure TLS
|
||
|
|
||
|
The [TLS options](https://doc.traefik.io/traefik/https/tls/#tls-options) allow one to configure some parameters of the TLS connection.
|
||
|
|
||
|
```yaml
|
||
|
tlsOptions:
|
||
|
default:
|
||
|
labels: {}
|
||
|
sniStrict: true
|
||
|
custom-options:
|
||
|
labels: {}
|
||
|
curvePreferences:
|
||
|
- CurveP521
|
||
|
- CurveP384
|
||
|
```
|
||
|
|
||
|
# Use latest build of Traefik v3 from master
|
||
|
|
||
|
An experimental build of Traefik Proxy is available on a specific repository.
|
||
|
|
||
|
It can be used with those _values_:
|
||
|
|
||
|
```yaml
|
||
|
image:
|
||
|
repository: traefik/traefik
|
||
|
tag: experimental-v3.0
|
||
|
```
|
||
|
|
||
|
# Use Prometheus Operator
|
||
|
|
||
|
An optional support of this operator is included in this Chart. See documentation of this operator for more details.
|
||
|
|
||
|
It can be used with those _values_:
|
||
|
|
||
|
```yaml
|
||
|
metrics:
|
||
|
prometheus:
|
||
|
service:
|
||
|
enabled: true
|
||
|
disableAPICheck: false
|
||
|
serviceMonitor:
|
||
|
enabled: true
|
||
|
metricRelabelings:
|
||
|
- sourceLabels: [__name__]
|
||
|
separator: ;
|
||
|
regex: ^fluentd_output_status_buffer_(oldest|newest)_.+
|
||
|
replacement: $1
|
||
|
action: drop
|
||
|
relabelings:
|
||
|
- sourceLabels: [__meta_kubernetes_pod_node_name]
|
||
|
separator: ;
|
||
|
regex: ^(.*)$
|
||
|
targetLabel: nodename
|
||
|
replacement: $1
|
||
|
action: replace
|
||
|
jobLabel: traefik
|
||
|
interval: 30s
|
||
|
honorLabels: true
|
||
|
prometheusRule:
|
||
|
enabled: true
|
||
|
rules:
|
||
|
- alert: TraefikDown
|
||
|
expr: up{job="traefik"} == 0
|
||
|
for: 5m
|
||
|
labels:
|
||
|
context: traefik
|
||
|
severity: warning
|
||
|
annotations:
|
||
|
summary: "Traefik Down"
|
||
|
description: "{{ $labels.pod }} on {{ $labels.nodename }} is down"
|
||
|
```
|
||
|
|
||
|
# Use kubernetes Gateway API
|
||
|
|
||
|
One can use the new stable kubernetes gateway API provider setting the following _values_:
|
||
|
|
||
|
```yaml
|
||
|
providers:
|
||
|
kubernetesGateway:
|
||
|
enabled: true
|
||
|
```
|
||
|
|
||
|
<details>
|
||
|
|
||
|
<summary>With those values, a whoami service can be exposed with a HTTPRoute</summary>
|
||
|
|
||
|
```yaml
|
||
|
---
|
||
|
apiVersion: apps/v1
|
||
|
kind: Deployment
|
||
|
metadata:
|
||
|
name: whoami
|
||
|
spec:
|
||
|
replicas: 2
|
||
|
selector:
|
||
|
matchLabels:
|
||
|
app: whoami
|
||
|
template:
|
||
|
metadata:
|
||
|
labels:
|
||
|
app: whoami
|
||
|
spec:
|
||
|
containers:
|
||
|
- name: whoami
|
||
|
image: traefik/whoami
|
||
|
|
||
|
---
|
||
|
apiVersion: v1
|
||
|
kind: Service
|
||
|
metadata:
|
||
|
name: whoami
|
||
|
spec:
|
||
|
selector:
|
||
|
app: whoami
|
||
|
ports:
|
||
|
- protocol: TCP
|
||
|
port: 80
|
||
|
|
||
|
---
|
||
|
apiVersion: gateway.networking.k8s.io/v1
|
||
|
kind: HTTPRoute
|
||
|
metadata:
|
||
|
name: whoami
|
||
|
spec:
|
||
|
parentRefs:
|
||
|
- name: traefik-gateway
|
||
|
hostnames:
|
||
|
- whoami.docker.localhost
|
||
|
rules:
|
||
|
- matches:
|
||
|
- path:
|
||
|
type: Exact
|
||
|
value: /
|
||
|
|
||
|
backendRefs:
|
||
|
- name: whoami
|
||
|
port: 80
|
||
|
weight: 1
|
||
|
```
|
||
|
|
||
|
Once it's applied, whoami should be accessible on http://whoami.docker.localhost/
|
||
|
|
||
|
</details>
|
||
|
|
||
|
:information_source: In this example, `Deployment` and `HTTPRoute` should be deployed in the same namespace as the Traefik Gateway: Chart namespace.
|
||
|
|
||
|
# Use Kubernetes Gateway API with cert-manager
|
||
|
|
||
|
One can use the new stable kubernetes gateway API provider with automatic TLS certificates delivery (with cert-manager) setting the following _values_:
|
||
|
|
||
|
```yaml
|
||
|
providers:
|
||
|
kubernetesGateway:
|
||
|
enabled: true
|
||
|
gateway:
|
||
|
enabled: true
|
||
|
annotations:
|
||
|
cert-manager.io/issuer: selfsigned-issuer
|
||
|
listeners:
|
||
|
websecure:
|
||
|
hostname: whoami.docker.localhost
|
||
|
port: 8443
|
||
|
protocol: HTTPS
|
||
|
certificateRefs:
|
||
|
- name: whoami-tls
|
||
|
```
|
||
|
|
||
|
Install cert-manager:
|
||
|
|
||
|
```bash
|
||
|
helm repo add jetstack https://charts.jetstack.io --force-update
|
||
|
helm upgrade --install \
|
||
|
cert-manager jetstack/cert-manager \
|
||
|
--namespace cert-manager \
|
||
|
--create-namespace \
|
||
|
--version v1.15.1 \
|
||
|
--set crds.enabled=true \
|
||
|
--set "extraArgs={--enable-gateway-api}"
|
||
|
```
|
||
|
|
||
|
<details>
|
||
|
|
||
|
<summary>With those values, a whoami service can be exposed with HTTPRoute on both HTTP and HTTPS</summary>
|
||
|
|
||
|
```yaml
|
||
|
---
|
||
|
apiVersion: apps/v1
|
||
|
kind: Deployment
|
||
|
metadata:
|
||
|
name: whoami
|
||
|
spec:
|
||
|
replicas: 2
|
||
|
selector:
|
||
|
matchLabels:
|
||
|
app: whoami
|
||
|
template:
|
||
|
metadata:
|
||
|
labels:
|
||
|
app: whoami
|
||
|
spec:
|
||
|
containers:
|
||
|
- name: whoami
|
||
|
image: traefik/whoami
|
||
|
|
||
|
---
|
||
|
apiVersion: v1
|
||
|
kind: Service
|
||
|
metadata:
|
||
|
name: whoami
|
||
|
spec:
|
||
|
selector:
|
||
|
app: whoami
|
||
|
ports:
|
||
|
- protocol: TCP
|
||
|
port: 80
|
||
|
|
||
|
---
|
||
|
apiVersion: gateway.networking.k8s.io/v1
|
||
|
kind: HTTPRoute
|
||
|
metadata:
|
||
|
name: whoami
|
||
|
spec:
|
||
|
parentRefs:
|
||
|
- name: traefik-gateway
|
||
|
hostnames:
|
||
|
- whoami.docker.localhost
|
||
|
rules:
|
||
|
- matches:
|
||
|
- path:
|
||
|
type: Exact
|
||
|
value: /
|
||
|
|
||
|
backendRefs:
|
||
|
- name: whoami
|
||
|
port: 80
|
||
|
weight: 1
|
||
|
|
||
|
---
|
||
|
apiVersion: cert-manager.io/v1
|
||
|
kind: Issuer
|
||
|
metadata:
|
||
|
name: selfsigned-issuer
|
||
|
spec:
|
||
|
selfSigned: {}
|
||
|
```
|
||
|
|
||
|
Once it's applied, whoami should be accessible on https://whoami.docker.localhost/
|
||
|
|
||
|
</details>
|