Yes, this is a common issue when using Socket.io behind an NGINX Ingress Controller in AKS. The problem is likely caused by NGINX's handling of WebSocket upgrades and path rewriting. The connection works fine and you receive 40{"sid":"<socket_id>"}
, confirming a successful WebSocket handshake but on AKS, the client only gets 40
without the sid
, meaning the connection does not fully establish. Even though you've added nginx.ingress.kubernetes.io/enable-websocket: "true"
To fix this, you can try to add these headers explicitly in your Ingress annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_http_version 1.1;
proxy_set_header Host $host;
This should ensure that WebSocket upgrade requests are properly forwarded.
Also kindly share the output of
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
Look for any errors related to WebSockets.
In general, to set up a Socket.io server on AKS with NGINX Ingress Controller
Deploy NGINX Ingress Controller
Below is a sample Node.js Express Server with Socket.io and it's being deployed on AKS.
socket-server.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: socket-server
spec:
replicas: 2
selector:
matchLabels:
app: socket-server
template:
metadata:
labels:
app: socket-server
spec:
containers:
- name: socket-server
image:arkoacr.azurecr.io/socket-server:latest
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: socket-service
spec:
selector:
app: socket-server
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: ClusterIP
Dockerfile for the same-
FROM node:18
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
server.js file-
const express = require("express");
const http = require("http");
const { Server } = require("socket.io");
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
});
io.on("connection", (socket) => {
console.log("New client connected:", socket.id);
socket.on("disconnect", () => {
console.log("Client disconnected:", socket.id);
});
});
server.listen(3000, () => {
console.log("Socket.io server running on port 3000");
});
package.json
{
"name": "socket-server",
"version": "1.0.0",
"description": "Socket.io server for Kubernetes",
"main": "server.js",
"dependencies": {
"express": "^4.17.1",
"socket.io": "^4.7.5"
}
}
containerise it and push it to your acr
Create Ingress to Expose the Server
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: socket-ingress
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/error-log-level: "debug"
nginx.ingress.kubernetes.io/enable-websocket: "true"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-buffering: "off"
spec:
ingressClassName: nginx
rules:
- host: myapp.example.com
http:
paths:
- path: /socket(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: socket-service
port:
number: 80
finally deploy the Angular Client. If issue persists. Kindly share the outputs for
kubectl logs -l app=socket-server and kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
Adding to your follow up comment-
Since the WebSocket connection initially succeeds but then immediately disconnects, the issue is likely not just NGINX, but also how Socket.io is handling WebSocket upgrades behind a proxy. Could you kindly try to update your server.js as below and let me know?
const express = require("express");
const http = require("http");
const { Server } = require("socket.io");
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
});
io.engine.set("trust proxy", 1);
io.on("connection", (socket) => {
console.log("New client connected:", socket.id);
socket.on("disconnect", () => {
console.log("Client disconnected:", socket.id);
});
});
server.listen(8083, () => {
console.log("Socket.io server running on port 8083");
});
and your ingress yaml as below-
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: socket-ingress
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/error-log-level: "debug"
nginx.ingress.kubernetes.io/enable-websocket: "true"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-buffering: "off"
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
spec:
ingressClassName: nginx
rules:
- host: myapp.example.com
http:
paths:
- path: /socket(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: socket-service
port:
number: 80
and modify your angular client to force Web Sockets
this.socket = io("wss://myapplication.com", {
transports: ["websocket"],
path: "/nodeapp/socket.io/",
reconnectionAttempts: 10,
reconnectionDelay: 1000
});
I requested you for the kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx. Could you kindly share that with me so that I can have a better insight. I have pinged you in Private message. Let's take it forward from there. Thanks