Skip to content

Commit

Permalink
fix(Gateway API)!: revamp Gateway implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
darkweaver87 committed Jul 24, 2024
1 parent abc6310 commit 5f2705d
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 38 deletions.
102 changes: 102 additions & 0 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -890,3 +890,105 @@ spec:
Once it's applied, whoami should be accessible on http://whoami.docker.localhost/

</details>

# 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
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>
11 changes: 9 additions & 2 deletions traefik/VALUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,18 @@ Kubernetes: `>=1.22.0-0`
| experimental.plugins | object | `{}` | Enable traefik experimental plugins |
| extraObjects | list | `[]` | Extra objects to deploy (value evaluated as a template) In some cases, it can avoid the need for additional, extended or adhoc deployments. See #595 for more details and traefik/tests/values/extra.yaml for example. |
| gateway.annotations | string | `nil` | Additional gateway annotations (e.g. for cert-manager.io/issuer) |
| gateway.certificateRefs | string | `nil` | See [GatewayTLSConfig](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.GatewayTLSConfig) |
| gateway.enabled | bool | `true` | When providers.kubernetesGateway.enabled, deploy a default gateway |
| gateway.listeners | object | `{"web":{"hostname":null,"namespacePolicy":null,"port":8000,"protocol":"HTTP"},"websecure":{"certificateRefs":null,"hostname":null,"mode":null,"namespacePolicy":null,"port":8443,"protocol":"HTTPS"}}` | Define listeners |
| gateway.listeners.web.hostname | string | `nil` | Optional hostname. See [Hostname](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Hostname) |
| gateway.listeners.web.namespacePolicy | string | `nil` | Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.FromNamespaces |
| gateway.listeners.web.port | int | `8000` | Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. The port must match a port declared in ports section. |
| gateway.listeners.websecure.certificateRefs | string | `nil` | Add certificates for TLS or HTTPS protocols. See [GatewayTLSConfig](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.GatewayTLSConfig) |
| gateway.listeners.websecure.hostname | string | `nil` | Optional hostname. See [Hostname](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Hostname) |
| gateway.listeners.websecure.mode | string | `nil` | TLS behavior for the TLS session initiated by the client. See [TLSModeType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.TLSModeType). |
| gateway.listeners.websecure.namespacePolicy | string | `nil` | Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.FromNamespaces) |
| gateway.listeners.websecure.port | int | `8443` | Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. The port must match a port declared in ports section. |
| gateway.name | string | `nil` | Set a custom name to gateway |
| gateway.namespace | string | `nil` | By default, Gateway is created in the same `Namespace` than Traefik. |
| gateway.namespacePolicy | string | `nil` | Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.FromNamespaces) |
| gatewayClass.enabled | bool | `true` | When providers.kubernetesGateway.enabled and gateway.enabled, deploy a default gatewayClass |
| gatewayClass.labels | string | `nil` | Additional gatewayClass labels (e.g. for filtering gateway objects by custom labels) |
| gatewayClass.name | string | `nil` | Set a custom name to GatewayClass |
Expand Down
40 changes: 27 additions & 13 deletions traefik/templates/gateway.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{{- if and (.Values.gateway).enabled (.Values.providers.kubernetesGateway).enabled }}
{{- if not .Values.gateway.listeners }}
{{- fail "ERROR: gateway must have at least one listener or should be disabled" }}
{{- end }}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
Expand All @@ -14,25 +17,36 @@ metadata:
spec:
gatewayClassName: {{ default "traefik" .Values.gatewayClass.name }}
listeners:
- name: web
port: {{ .Values.ports.web.port }}
protocol: HTTP
{{- with .Values.gateway.namespacePolicy }}
allowedRoutes:
namespaces:
from: {{ . }}
{{- range $name, $config := .Values.gateway.listeners }}
- name: {{ $name }}
{{ $found := false }}
{{- range $portName, $portConfig := $.Values.ports -}}
{{- if eq $portConfig.port $config.port -}}
{{ $found = true }}
{{- end -}}
{{- end -}}
{{ if not $found }}
{{- fail (printf "ERROR: port %0.f is not declared in ports" .port ) }}
{{- end -}}
port: {{ .port }}
protocol: {{ .protocol }}
{{- with .hostname }}
hostname: {{ . }}
{{- end }}
{{- if .Values.gateway.certificateRefs }}
- name: websecure
port: {{ $.Values.ports.websecure.port }}
protocol: HTTPS
{{- with .Values.gateway.namespacePolicy }}
{{- with .namespacePolicy }}
allowedRoutes:
namespaces:
from: {{ . }}
{{- end }}
{{ if or .certificateRefs .mode }}
tls:
{{ with .mode }}
mode: {{ . }}
{{- end }}
{{ with .certificateRefs }}
certificateRefs:
{{- toYaml .Values.gateway.certificateRefs | nindent 10 }}
{{- toYaml . | nindent 10 }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
97 changes: 78 additions & 19 deletions traefik/tests/gateway-config_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ tests:
kubernetesGateway:
enabled: true
gateway:
namespacePolicy: All
listeners:
web:
namespacePolicy: All
asserts:
- equal:
path: spec.listeners[0].allowedRoutes.namespaces.from
value: "All"
- it: should configure namespacePolicy within websecure listener
- it: should configure namespacePolicy and certificateRefs within websecure listener
set:
providers:
kubernetesGateway:
enabled: true
gateway:
namespacePolicy: All
certificateRefs:
- group: "core"
kind: "Secret"
name: "mysecret"
listeners:
websecure:
namespacePolicy: All
asserts:
- equal:
path: spec.listeners[1].allowedRoutes.namespaces.from
Expand All @@ -63,10 +63,12 @@ tests:
kubernetesGateway:
enabled: true
gateway:
certificateRefs:
- name: "my-name"
group: "my-group"
kind: "my-kind"
listeners:
websecure:
certificateRefs:
- name: "my-name"
group: "my-group"
kind: "my-kind"
asserts:
- equal:
path: spec.gatewayClassName
Expand Down Expand Up @@ -129,8 +131,7 @@ tests:
gateway:
enabled: false
asserts:
- template: gateway.yaml
hasDocuments:
- hasDocuments:
count: 0
- it: should not deploy a gateway if gatewayClass creation is disabled
set:
Expand All @@ -140,8 +141,7 @@ tests:
gateway:
enabled: false
asserts:
- template: gateway.yaml
hasDocuments:
- hasDocuments:
count: 0
- it: should be possible to customize gatewayClass name
set:
Expand All @@ -151,8 +151,7 @@ tests:
gatewayClass:
name: test
asserts:
- template: gateway.yaml
equal:
- equal:
path: spec.gatewayClassName
value: test
- it: should be possible to customize gateway name
Expand All @@ -163,7 +162,67 @@ tests:
gateway:
name: test
asserts:
- template: gateway.yaml
equal:
- equal:
path: metadata.name
value: test
- it: should be possible to set tls mode
set:
providers:
kubernetesGateway:
enabled: true
gateway:
listeners:
websecure:
mode: Terminate
asserts:
- equal:
path: spec.listeners[1].tls.mode
value: Terminate
- it: should be possible to set protocol
set:
providers:
kubernetesGateway:
enabled: true
gateway:
listeners:
web:
protocol: TCP
asserts:
- equal:
path: spec.listeners[0].protocol
value: TCP
- it: should be possible to set hostname
set:
providers:
kubernetesGateway:
enabled: true
gateway:
listeners:
web:
hostname: test.docker.localhost
asserts:
- equal:
path: spec.listeners[0].hostname
value: test.docker.localhost
- it: should fail when no listeners are defined
set:
providers:
kubernetesGateway:
enabled: true
gateway:
listeners: null
asserts:
- failedTemplate:
errorMessage: "ERROR: gateway must have at least one listener or should be disabled"
- it: should fail when listener port is not declared in ports
set:
providers:
kubernetesGateway:
enabled: true
gateway:
listeners:
web:
port: 8001
asserts:
- failedTemplate:
errorMessage: "ERROR: port 8001 is not declared in ports"
30 changes: 26 additions & 4 deletions traefik/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,36 @@ gateway:
enabled: true
# -- Set a custom name to gateway
name:
# -- Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.FromNamespaces)
namespacePolicy:
# -- See [GatewayTLSConfig](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.GatewayTLSConfig)
certificateRefs:
# -- By default, Gateway is created in the same `Namespace` than Traefik.
namespace:
# -- Additional gateway annotations (e.g. for cert-manager.io/issuer)
annotations:
# -- Define listeners
listeners:
web:
# -- Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules.
# The port must match a port declared in ports section.
port: 8000
# -- Optional hostname. See [Hostname](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Hostname)
hostname:
# Specify expected protocol on this listener. See [ProtocolType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ProtocolType)
protocol: HTTP
# -- Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.FromNamespaces
namespacePolicy:
websecure:
# -- Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules.
# The port must match a port declared in ports section.
port: 8443
# -- Optional hostname. See [Hostname](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Hostname)
hostname:
# Specify expected protocol on this listener See [ProtocolType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ProtocolType)
protocol: HTTPS
# -- Routes are restricted to namespace of the gateway [by default](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.FromNamespaces)
namespacePolicy:
# -- Add certificates for TLS or HTTPS protocols. See [GatewayTLSConfig](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.GatewayTLSConfig)
certificateRefs:
# -- TLS behavior for the TLS session initiated by the client. See [TLSModeType](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.TLSModeType).
mode:

gatewayClass:
# -- When providers.kubernetesGateway.enabled and gateway.enabled, deploy a default gatewayClass
Expand Down

0 comments on commit 5f2705d

Please sign in to comment.