Using websockets with the NGINX Kubernetes ingress controller
Learn how to set up WebSockets with the NGINX ingress controller in Civo Kubernetes to avoid the error code 426 Upgrade Required.
Written by
Marketing Team @ Civo
Written by
Marketing Team @ Civo
As I spent more than two days figuring out how to set up websockets to work with NGINX ingress controller in Civo Kubernetes, I thought I would write it down to save others time. This allows you to get past error code 426 Upgrade Required which you may encounter.
Important note:
There are multiple flavors of NGINX Kubernetes ingress controllers available:
- The Kubernetes NGINX ingress controller is maintained by Kubernetes, and is the one that appears in the Civo app marketplace. I'm using this one.
- NGINX's ingress controller is one that's maintained by NGINX, and has some differences.
Getting around NGINX WebSocket “error 426 upgrade required”
I followed different articles and Stack Overflow links for the solution, but every time I thought it should work, I was getting HTTP error code 426, "Upgrade Required". The connection did not upgrade itself by the NGINX load balancer.
After some help with Amit, I realized that we need to insert some configuration in the location block of NGINX to upgrade the connections for websockets.
Here are some snippets for an example:
deployment.yamlfile:
apiVersion: apps/v1kind: Deploymentmetadata:name: tornado-socketlabels:app: tornado-socketgroup: testingspec:replicas: 1selector:matchLabels:app: tornado-sockettemplate:metadata:labels:app: tornado-socketgroup: testingspec:containers:- name: tornado-socketimage: ajayinnvonix/tornado-demoports:- name: websocketcontainerPort: 8000
service.yamlfile:
apiVersion: v1kind: Servicemetadata:name: tornado-socketlabels:app: tornado-socketgroup: testingspec:type: ClusterIPselector:app: tornado-socketports:- name: websocketprotocol: TCPport: 8000targetPort: 8000
ingress.yamlfile:
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: tornado-socketannotations:nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"nginx.ingress.kubernetes.io/server-snippets: |location / {proxy_set_header Upgrade $http_upgrade;proxy_http_version 1.1;proxy_set_header X-Forwarded-Host $http_host;proxy_set_header X-Forwarded-Proto $scheme;proxy_set_header X-Forwarded-For $remote_addr;proxy_set_header Host $host;proxy_set_header Connection "upgrade";proxy_cache_bypass $http_upgrade;}spec:ingressClassName: nginxrules:- host: tornado-ws.example.comhttp:paths:- path: /pathType: Prefixbackend:service:name: tornado-socketport:number: 8000
The part in nginx.ingress.kubernetes.io/server-snippets is what actually upgrades the connection.
Wrapping up
I tested it on my local system with a simple node websocket server behind NGINX, and without the upgrade headers, I was getting the error 426, even on directly passing proxy to the Node upstream. Once the upgrade headers are set, the error disappears.

References

Marketing Team @ Civo
Civo is the Sovereign Cloud and AI platform designed to help developers and enterprises build without limits. We bridge the gap between the openness of the public cloud and the rigorous security of private environments, delivering full cloud parity across every deployment. As a team, we are dedicated to providing scalable compute, lightning-fast Kubernetes, and managed services that are ready in minutes. Through CivoStack Enterprise and our FlexCore appliance, we empower organizations to maintain total data sovereignty on their own hardware.
Our mission is to make the cloud faster, simpler, and fairer. By providing enterprise-grade NVIDIA GPUs and streamlined model management, we ensure that high-performance AI and machine learning are accessible to everyone. Built for transparency and performance, the Civo Team is here to give you total control over your infrastructure, your data, and your spend.
Share this article
Further Reading
17 February 2022
A/B testing using the NGINX Kubernetes Ingress controller
21 July 2023