Add traefik v2 kubernetes examples

Ref #72 #89 #92
This commit is contained in:
Thom Seddon 2020-05-07 15:47:58 +01:00
parent f802a366de
commit f7a94e7db9
32 changed files with 962 additions and 0 deletions

View File

@ -0,0 +1,39 @@
# Kubernetes - Advanced Separate Pod Example
This is an advanced example of how to deploy traefik-forward-auth in it's own pod. This example is a good starting point for those who already have traefik deployed (e.g. using helm).
This example uses [Individual Authentication](https://github.com/thomseddon/traefik-forward-auth/blob/master/README.md#individual-ingress-authentication-in-kubernetes) to selectively apply forward authentication to each individual ingresses, for example:
```
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami
labels:
app: whoami
spec:
entryPoints:
- https
routes:
- match: Host(`whoami.example.com`)
kind: Rule
services:
- name: whoami
port: 80
middlewares:
- name: traefik-forward-auth
tls:
certresolver: default
```
This example also includes SSL via traefik acme/lesencrypt, auth host mode, and leverages kustomise. A simple example "whoami" application (deployment, service and ingress) is included for completeness.
Example deployment:
```
# Deploy traefik-forward-auth
kubectl apply -k traefik-forward-auth
# Deploy example whoami app
kubectl apply -k whoami
```

View File

@ -0,0 +1,3 @@
bases:
- traefik-forward-auth
- whoami

View File

@ -0,0 +1,8 @@
rule.example_public.action=allow
rule.example_public.rule=Host("stats.example.com") && PathPrefix("/api/public")
rule.example_api.action=allow
rule.example_api.rule=Host("api.example.com") && Headers("X-API-Authorization", "a-long-api-key")
rule.example_api_query.action=allow
rule.example_api_query.rule=Host("api.example.com") && && Query("api_key=a-long-api-key")

View File

@ -0,0 +1,71 @@
#
# Traefik Forward Auth Deployment
#
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik-forward-auth
labels:
app: traefik-forward-auth
spec:
replicas: 1
selector:
matchLabels:
app: traefik-forward-auth
strategy:
type: Recreate
template:
metadata:
labels:
app: traefik-forward-auth
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
containers:
- image: thomseddon/traefik-forward-auth:2
name: traefik-forward-auth
ports:
- containerPort: 4181
protocol: TCP
env:
- name: CONFIG
value: "/config"
- name: DOMAIN
value: "example.com"
# INSECURE_COOKIE is required if not using a https entrypoint
# - name: INSECURE_COOKIE
# value: "true"
# Remove COOKIE_DOMAIN if not using auth host mode
- name: COOKIE_DOMAIN
value: "example.com"
- name: AUTH_HOST
value: "auth.example.com"
- name: LOG_LEVEL
value: "info"
- name: PROVIDERS_GOOGLE_CLIENT_ID
valueFrom:
secretKeyRef:
name: secrets
key: google-client-id
- name: PROVIDERS_GOOGLE_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: secrets
key: google-client-secret
- name: SECRET
valueFrom:
secretKeyRef:
name: secrets
key: secret
volumeMounts:
- name: configs
mountPath: /config
subPath: traefik-forward-auth.ini
volumes:
- name: configs
configMap:
name: configs
- name: secrets
secret:
secretName: secrets

View File

@ -0,0 +1,20 @@
#
# Auth Ingress
#
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-forward-auth
labels:
app: traefik
spec:
entryPoints:
- https
routes:
- match: Host(`auth.example.com`)
kind: Rule
services:
- name: traefik-forward-auth
port: 4181
tls:
certresolver: default

View File

@ -0,0 +1,26 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: default
commonLabels:
app: traefik-forward-auth
resources:
- deployment.yaml
- service.yaml
- ingress.yaml
- middleware.yaml
#
# Configs
#
configMapGenerator:
- name: configs
files:
- configs/traefik-forward-auth.ini
#
# Secrets
#
secretGenerator:
- name: secrets
env: secrets/traefik-forward-auth.env

View File

@ -0,0 +1,9 @@
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: traefik-forward-auth
spec:
forwardAuth:
address: http://traefik-forward-auth:4181
authResponseHeaders:
- X-Forwarded-User

View File

@ -0,0 +1,3 @@
google-client-id=client-id
google-client-secret=client-secret
secret=something-random

View File

@ -0,0 +1,17 @@
#
# Auth Service
#
apiVersion: v1
kind: Service
metadata:
name: traefik-forward-auth
labels:
app: traefik
spec:
type: ClusterIP
selector:
app: traefik
ports:
- name: auth-http
port: 4181
targetPort: 4181

View File

@ -0,0 +1,19 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami
labels:
app: whoami
spec:
replicas: 1
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- image: containous/whoami
name: whoami

View File

@ -0,0 +1,19 @@
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami
labels:
app: whoami
spec:
entryPoints:
- https
routes:
- match: Host(`whoami.example.com`)
kind: Rule
services:
- name: whoami
port: 80
middlewares:
- name: traefik-forward-auth
tls:
certresolver: default

View File

@ -0,0 +1,7 @@
commonLabels:
app: whoami
resources:
- deployment.yaml
- service.yaml
- ingress.yaml

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: whoami
labels:
app: whoami
spec:
type: ClusterIP
ports:
- name: http
port: 80
selector:
app: whoami

View File

@ -0,0 +1,18 @@
# Kubernetes - Advanced Single Pod Example
This is an advanced example of how to deploy traefik and traefik-forward-auth in a single pod. This example is a good starting point for those who already have a manually defined traefik config (e.g. not using helm).
This example uses [Global Authentication](https://github.com/thomseddon/traefik-forward-auth/blob/master/README.md#global-authentication) to apply authentication for the entire `https` entrypoint.
This example also includes SSL via traefik acme/lesencrypt, auth host mode, exposes the traefik dashboard and leverages kustomise. No special config if required for your applications, but a simple example "whoami" application (deployment, service and ingress) is included for completeness.
Example deployment:
```
# Deploy traefik+traefik-forward-auth
kubectl apply -k traefik
# Deploy whoami app
kubectl apply -k whoami
```

View File

@ -0,0 +1,3 @@
bases:
- traefik
- whoami

View File

@ -0,0 +1,8 @@
rule.example_public.action=allow
rule.example_public.rule=Host("stats.example.com") && PathPrefix("/api/public")
rule.example_api.action=allow
rule.example_api.rule=Host("api.example.com") && Headers("X-API-Authorization", "a-long-api-key")
rule.example_api_query.action=allow
rule.example_api_query.rule=Host("api.example.com") && && Query("api_key=a-long-api-key")

View File

@ -0,0 +1,103 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutes.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRoute
plural: ingressroutes
singular: ingressroute
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: middlewares.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: Middleware
plural: middlewares
singular: middleware
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutetcps.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteTCP
plural: ingressroutetcps
singular: ingressroutetcp
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressrouteudps.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteUDP
plural: ingressrouteudps
singular: ingressrouteudp
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsoptions.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSOption
plural: tlsoptions
singular: tlsoption
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsstores.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSStore
plural: tlsstores
singular: tlsstore
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: traefikservices.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TraefikService
plural: traefikservices
singular: traefikservice
scope: Namespaced

View File

@ -0,0 +1,110 @@
#
# Traefik + Traefik Forward Auth Deployment
#
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik
labels:
app: traefik
spec:
replicas: 1
selector:
matchLabels:
app: traefik
strategy:
type: Recreate
template:
metadata:
labels:
app: traefik
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
containers:
- image: traefik:2.2
name: traefik
args:
- --api.dashboard
- --accesslog
- --entryPoints.http.address=:80
- --entryPoints.http.http.redirections.entryPoint.to=https
- --entryPoints.http.http.redirections.entryPoint.scheme=https
- --entryPoints.https.address=:443
# We're using "global authentication", so the middleware is defined here on the entrypoint
# When a kubernetescrd middleware is applied globally it should take the form <kubernetes-namespace>-<middleware>
- --entrypoints.https.http.middlewares=default-traefik-forward-auth
- --providers.kubernetescrd
- --log.level=info
- --log.format=json
- --certificatesresolvers.default.acme.email=foo@you.com
- --certificatesresolvers.default.acme.storage=/acme/acme.json
- --certificatesresolvers.default.acme.storage=/acme/acme.json
- --certificatesresolvers.default.acme.httpchallenge.entrypoint=http
# Please note that this is the staging Let's Encrypt server.
# Once you get things working, you should remove that whole line altogether.
- --certificatesresolvers.default.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
- name: dash
containerPort: 8080
protocol: TCP
volumeMounts:
- mountPath: /acme
name: acme
- image: thomseddon/traefik-forward-auth:2
name: traefik-forward-auth
ports:
- containerPort: 4181
protocol: TCP
env:
- name: CONFIG
value: "/config"
- name: DOMAIN
value: "example.com"
# INSECURE_COOKIE is required if not using a https entrypoint
# - name: INSECURE_COOKIE
# value: "true"
# Remove COOKIE_DOMAIN if not using auth host mode
- name: COOKIE_DOMAIN
value: "example.com"
- name: AUTH_HOST
value: "auth.example.com"
- name: LOG_LEVEL
value: "info"
- name: PROVIDERS_GOOGLE_CLIENT_ID
valueFrom:
secretKeyRef:
name: secrets
key: google-client-id
- name: PROVIDERS_GOOGLE_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: secrets
key: google-client-secret
- name: SECRET
valueFrom:
secretKeyRef:
name: secrets
key: secret
volumeMounts:
- name: configs
mountPath: /config
subPath: traefik-forward-auth.ini
volumes:
- name: configs
configMap:
name: configs
- name: secrets
secret:
secretName: secrets
- name: acme
persistentVolumeClaim:
claimName: traefik-acme

View File

@ -0,0 +1,42 @@
#
# Auth Ingress
#
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-forward-auth
labels:
app: traefik
spec:
entryPoints:
- https
routes:
- match: Host(`auth.example.com`)
kind: Rule
services:
- name: traefik-forward-auth
port: 4181
tls:
certresolver: default
---
#
# Dash Ingress
#
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard
labels:
app: traefik
spec:
entryPoints:
- https
routes:
- match: Host(`traefik.example.com`)
kind: Rule
services:
- name: api@internal
kind: TraefikService
tls:
certresolver: default

View File

@ -0,0 +1,29 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: default
commonLabels:
app: traefik
resources:
- crds.yaml
- deployment.yaml
- service.yaml
- ingress.yaml
- middleware.yaml
- pvc.yaml
- rbac.yaml
#
# Configs
#
configMapGenerator:
- name: configs
files:
- configs/traefik-forward-auth.ini
#
# Secrets
#
secretGenerator:
- name: secrets
env: secrets/traefik-forward-auth.env

View File

@ -0,0 +1,9 @@
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: traefik-forward-auth
spec:
forwardAuth:
address: http://127.0.0.1:4181
authResponseHeaders:
- X-Forwarded-User

View File

@ -0,0 +1,17 @@
# Source: traefik/templates/acme-pvc.yaml
#
# PVC
#
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: traefik-acme
labels:
app: traefik
spec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: "1Gi"
storageClassName: "local-traefik-acme"

View File

@ -0,0 +1,66 @@
#
# RBAC
#
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: default
name: traefik-ingress-controller
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- traefik.containo.us
resources:
- middlewares
- ingressroutes
- traefikservices
- ingressroutetcps
- ingressrouteudps
- tlsoptions
- tlsstores
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: default

View File

@ -0,0 +1,3 @@
google-client-id=client-id
google-client-secret=client-secret
secret=something-random

View File

@ -0,0 +1,39 @@
#
# Traefik Service
#
apiVersion: v1
kind: Service
metadata:
name: traefik
labels:
app: traefik
spec:
# Use NodePort if required
type: LoadBalancer
selector:
app: traefik
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
---
#
# Auth Service
#
apiVersion: v1
kind: Service
metadata:
name: traefik-forward-auth
labels:
app: traefik
spec:
type: ClusterIP
selector:
app: traefik
ports:
- name: auth-http
port: 4181
targetPort: 4181

View File

@ -0,0 +1,19 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami
labels:
app: whoami
spec:
replicas: 1
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- image: containous/whoami
name: whoami

View File

@ -0,0 +1,17 @@
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami
labels:
app: whoami
spec:
entryPoints:
- https
routes:
- match: Host(`whoami.example.com`)
kind: Rule
services:
- name: whoami
port: 80
tls:
certresolver: default

View File

@ -0,0 +1,7 @@
commonLabels:
app: whoami
resources:
- deployment.yaml
- service.yaml
- ingress.yaml

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: whoami
labels:
app: whoami
spec:
type: ClusterIP
ports:
- name: http
port: 80
selector:
app: whoami

View File

@ -0,0 +1,39 @@
# Kubernetes - Simple Separate Pod Example
This is a simple example of how to deploy traefik-forward-auth in it's own pod with minimal configuration. This example is a good starting point for those who already have traefik deployed (e.g. using helm).
This example uses [Individual Authentication](https://github.com/thomseddon/traefik-forward-auth/blob/master/README.md#individual-ingress-authentication-in-kubernetes) to apply forward authentication to selected ingresses. This means ingresses will not be protected by default. Authentication can be applied by adding the `traefik-forward-auth` middleware, for example:
```
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami
labels:
app: whoami
spec:
entryPoints:
- http
routes:
- match: Host(`whoami.example.com`)
kind: Rule
services:
- name: whoami
port: 80
middlewares:
- name: traefik-forward-auth
```
A minimal application example is provided in `k8s-app.yml`.
Example deployment:
```
# Deploy traefik-forward-auth
kubectl apply -f k8s-traefik-forward-auth.yml
# Deploy example whoami app
kubectl apply -f k8s-app.yml
```
Please see the advanced examples for more details.

View File

@ -0,0 +1,60 @@
#
# Example Application Deployment
#
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami
labels:
app: whoami
spec:
replicas: 1
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: emilevauge/whoami
---
#
# Service
#
apiVersion: v1
kind: Service
metadata:
name: whoami
labels:
app: whoami
spec:
ports:
- name: http
port: 80
selector:
app: whoami
---
#
# IngressRoute
#
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami
labels:
app: whoami
spec:
entryPoints:
- http
routes:
- match: Host(`whoami.example.com`)
kind: Rule
services:
- name: whoami
port: 80
middlewares:
- name: traefik-forward-auth

View File

@ -0,0 +1,104 @@
#
# Traefik Forward Auth Deployment
#
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik-forward-auth
labels:
app: traefik-forward-auth
spec:
replicas: 1
selector:
matchLabels:
app: traefik-forward-auth
strategy:
type: Recreate
template:
metadata:
labels:
app: traefik-forward-auth
spec:
terminationGracePeriodSeconds: 60
containers:
- image: thomseddon/traefik-forward-auth:2
name: traefik-forward-auth
ports:
- containerPort: 4181
protocol: TCP
env:
- name: DOMAIN
value: "example.com"
# INSECURE_COOKIE is required unless using https entrypoint
- name: INSECURE_COOKIE
value: "true"
- name: PROVIDERS_GOOGLE_CLIENT_ID
valueFrom:
secretKeyRef:
name: secrets
key: traefik-forward-auth-google-client-id
- name: PROVIDERS_GOOGLE_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: secrets
key: traefik-forward-auth-google-client-secret
- name: SECRET
valueFrom:
secretKeyRef:
name: secrets
key: traefik-forward-auth-secret
---
#
# Auth Service
#
apiVersion: v1
kind: Service
metadata:
name: traefik-forward-auth
labels:
app: traefik-forward-auth
spec:
type: ClusterIP
selector:
app: traefik-forward-auth
ports:
- name: auth-http
port: 4181
targetPort: 4181
---
#
# Auth Middleware
#
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: traefik-forward-auth
spec:
forwardAuth:
address: http://traefik-forward-auth:4181
authResponseHeaders:
- X-Forwarded-User
---
#
# Secrets
#
# Kubernetes requires secret values to be converted to base64 when defined
# explicitly like this. (use `echo -n 'secret-value' | base64`)
#
# These are here for completeness, in reality you may define these elsewhere,
# for example using kustomize (shown in advanced examples)
#
apiVersion: v1
kind: Secret
metadata:
name: traefik-forward-auth-secrets
labels:
app: traefik-forward-auth
type: Opaque
data:
traefik-forward-auth-google-client-id: base64-client-id
traefik-forward-auth-google-client-secret: base64-client-secret
traefik-forward-auth-secret: base64-something-random