Search code examples
websocketsignalrkubernetes-ingresscontour

Contour Websocket annotation not working on Ingress resource


I have a Contour Ingress controller setup on my Kubernetes instance. I have also setup an Ingress resource together with an HTTProxy resource, per the Contour specification:

Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: common-api-ingress
  annotations:
    ingress.kubernetes.io/tls-minimum-version: "1.2"
spec:
  ingressClassName: contour
  tls:
  - hosts:
      - dev.mycompany.com
    secretName: dev.mycompany.com-tls
  rules:
  - host: dev.mycompany.com
    http:
      paths:       
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80       
      - path: /swagger
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

HTTProxy

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: signalr-proxy
spec:
  virtualhost:
    fqdn: dev.mycompany.com
    tls:
      secretName: dev.mycompany.com-tls
  routes:
    - conditions:
      - prefix: /api/notificationhub
      enableWebsockets: true # Setting this to true enables websocket for all paths that match /websocket
      services:
        - name: my-service
          port: 80

This configuration is working as expected and when I open the Chrome developer tools for my UI I see the following log on the Console tab:

config vundefined loaded
main.56e2cc4e6f9f283a998a.js:2 [01-003] redirecting...
main.56e2cc4e6f9f283a998a.js:2 Connection to signalR has been established....
2.b4c26156c9f4449d4bbf.js:2 Resetting cache..

I have decided to discard Contour's custom HTTPProxy resource and remain with a plain Ingress resource. To do that I deleted the HTTPProxy resource provided earlier, and on the Ingress resource I added the annotation that enables websocket traffic. The updated Ingress resource is given below:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: common-api-ingress
  annotations:
    ingress.kubernetes.io/tls-minimum-version: "1.2"
    projectcontour.io/websocket-routes: /api/notificationhub/
spec:
  ingressClassName: contour
  tls:
  - hosts:
      - dev.mycompany.com
    secretName: dev.mycompany.com-tls
  rules:
  - host: dev.mycompany.com
    http:
      paths:       
      - path: /api/notificationhub/
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80       
      - path: /swagger
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

When I deploy this update I get the following error in the Chrome developer tools console:

config vundefined loaded
main.56e2cc4e6f9f283a998a.js:2 [01-002] redirecting...
main.56e2cc4e6f9f283a998a.js:2 ERROR e
Wn @ main.56e2cc4e6f9f283a998a.js:2
main.56e2cc4e6f9f283a998a.js:2 Connection to signalR has been established....
api/UserSettings/:1     Failed to load resource: the server responded with a status of 405 ()
2.b4c26156c9f4449d4bbf.js:2 Resetting cache...

Visual:

kdebug

The Contour deployment has the following set of pods:

kubectl -n projectcontour get pods
NAME                                         READY   STATUS    RESTARTS       AGE
contour-controller-contour-b5d6fdxxx-xxxxx   1/1     Running   1 (3d1h ago)   112d
contour-controller-contour-b5d6fdxxx-xx8x8   1/1     Running   1 (17d ago)    150d
contour-controller-contour-b5d6fdxxx-xxxxx   1/1     Running   2 (3d1h ago)   150d
contour-controller-envoy-ncxxx               2/2     Running   0              10d
contour-controller-envoy-wcxxx               2/2     Running   0              150d
contour-controller-envoy-wxxxx             2/2     Running   0              150d
contour-controller-envoy-xkxxx               2/2     Running   2 (69d ago)    146d

However I have another Ingress resource for Grafana that uses websockets and its working perfectly. The Helm values.yaml file is provided below:

adminPassword: "*xxa]{xxxxxxxxxxx"
grafana.ini:
  server:
    root_url: https://dev.mycompany.com/-/grafana
    serve_from_sub_path: true
  smtp:
    enabled: true
    host: mail2.mycompany.com:25
    from_address: dev@mycompany.com
    skip_verify: true
ingress:
  enabled: true
  ingressClassName: contour
  annotations:
    projectcontour.io/websocket-routes: /-/grafana/
  hosts:
    - dev.mycompany.com
  path: /-/grafana/
  tls:
  - hosts:
      - dev.mycompany.com
    secretName: dev.mycompany.com-tls
persistence:
  enabled: true

What am I missing ?


Solution

  • I was configuring the websocket route incorrectly. All I needed was to add a separate path for the websocket route itself:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: common-api-ingress
      annotations:
        ingress.kubernetes.io/tls-minimum-version: "1.2"
        projectcontour.io/websocket-routes: /api/notificationhub
    spec:
      ingressClassName: contour
      tls:
      - hosts:
          - dev.mycompany.com
        secretName: dev.mycompany.com-tls
      rules:
      - host: dev.mycompany.com
        http:
          paths: 
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: my-service
                port:
                  number: 80        
          - path: /api/notificationhub
            pathType: Prefix
            backend:
              service:
                name: my-service
                port:
                  number: 80       
          - path: /swagger
            pathType: Prefix
            backend:
              service:
                name: my-service
                port:
                  number: 80