Hey all!
Im having a few issues with getting the Header Based Routing/Dynamic Routing based on headers working as expected. Please note the following has all been sensitised
My plan is to have a full deployment of an environment, and on-demand
environments running side-by-side. By on-demand
, it will be if a single microserivce out of a list changes, only that single one is deployed, but with a suffix on all Kubernetes resources. We are doing this all through helm. This would include:
- Deployment
- Service
- HTTPRoute
For the values, if the following is provided, the full name of the app changes.
_helpers.tpl
{{- define "app-name.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- if .Values.global.ondemand.enabled }}
{{- printf "%s-%s" .Values.fullnameOverride .Values.global.ondemand.branchName | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
And for the values.yaml
global:
environmentName: ondemand
ondemand:
enabled: true
branchName: "ond-1"
So the full deployment of app-name.fullname
will be app-a
, whereas with on-demand, it will be app-a-ond-1
.
For the HTTPRoute, we have templated it like so:
{{- if .Values.global.ondemand.enabled }}
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: {{ include "app-name.fullname" . }}
labels:
{{- include "app-name.labels" . | nindent 4 }}
spec:
parentRefs:
- name: {{ .Values.fullnameOverride }}-headless
kind: Service
group: core
port: {{ .Values.service.port }}
rules:
- matches:
- headers:
- name: "x-branch-name"
value: "{{ .Values.global.ondemand.branchName }}"
backendRefs:
- name: {{ include "app-name.fullname" . }}-headless
port: {{ .Values.service.port }}
- backendRefs:
- name: {{ .Values.fullnameOverride }}-headless
port: {{ .Values.service.port }}
{{- end -}}
This would mean when an on-demand app is deployed, the spec will be (and what deploys to the cluster):
apiVersion: policy.linkerd.io/v1beta3
kind: HTTPRoute
metadata:
name: app-name-ond-1
namespace: staging-nova
spec:
parentRefs:
- group: core
kind: Service
name: app-name-headless
port: 8080
rules:
- backendRefs:
- group: ""
kind: Service
name: app-name-ond-1-headless
port: 8080
weight: 1
matches:
- headers:
- name: x-branch-name
type: Exact
value: ond-1
path:
type: PathPrefix
value: /
- backendRefs:
- group: ""
kind: Service
name: app-name-headless
port: 8080
weight: 1
matches:
- path:
type: PathPrefix
value: /
The way our traffic flow is on a full deployment:
TRAEFIK-INGRESS > API-GATEWAY > APP-A
We expect that if api-gateway-ond-1
and app-a-ond-1
exists (with associated HTTPRoutes), providing the header x-branch-name: ond-1
will route us to api-gateway-ond-1-headless
and then the subsequent call to app-a-ond-1-headless
.
However what seems to happen is:
TRAEFIK-INGRESS > API-GATEWAY-OND-1 > APP-A
All subsequent calls seem to fail to route correctly with the HTTPRoute in place. The applications themselves are passing on the x-branch-name
header, as it exists in the request call being made from api-gateway-ond-1
within linkerd-viz tap
.
The HTTPRoutes themselves look fine so not sure what’s going on (example status field from HTTPRoute):
status:
parents:
- conditions:
- lastTransitionTime: "2023-09-27T15:07:51Z"
message: ""
reason: NoMatchingParent
status: "False"
type: Accepted
- lastTransitionTime: "2023-09-27T15:07:51Z"
message: ""
reason: ResolvedRefs
status: "True"
type: ResolvedRefs
controllerName: linkerd.io/policy-controller
parentRef:
group: core
kind: Service
name: app-a-ond-1-headless
namespace: demand
Hopefully someone has seen this issue before/can help out on where this may be going wrong
Cheers!
Kris