Я пытаюсь настроить веб-сокеты с TLS в Google Kubernetes Engine и Istio.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: example-back-end
spec:
hosts:
- "api-dev.example.dev"
gateways:
- istio-system/example-gateway
http:
- match:
- uri:
prefix: /worker
route:
- destination:
host: worker
port:
number: 5001
- match:
- uri:
prefix: /
route:
- destination:
host: back-end
port:
number: 5000
- match:
- uri:
prefix: /ws
route:
- destination:
host: service-websocket
port:
number: 8080
websocketUpgrade: true
Я установил сертификат и ключ tls в свой контейнер службы веб-сокетов. (Тот же, который я использую для api.example.com).
apiVersion: v1
kind: Service
metadata:
name: service-websocket
spec:
selector:
app: service-websocket
ports:
- port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: service-websocket
spec:
selector:
matchLabels:
app: service-websocket
template:
metadata:
labels:
app: service-websocket
spec:
volumes:
- name: example-certificate
secret:
secretName: example-certificate
containers:
- name: service-websocket
image: gcr.io/example-project/service-websocket:latest
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 8080
volumeMounts:
- name: example-certificate
mountPath: /var/secrets/tls
Это сервер веб-сокетов, который использует пакет узла ws.
// web server
const https = require("https");
const config = require("./config");
const fs = require("fs");
const server = https.createServer({
cert: fs.readFileSync(config.TLS_CERT),
key: fs.readFileSync(config.TLS_KEY)
});
// websocket
const WebSocket = require("ws");
const url = require("url");
const wss = new WebSocket.Server({ noServer: true });
wss.on("connection", function connection(ws, req) {
const parameters = url.parse(req.url, true);
ws.on("message", function incoming(message) {
wss.clients.forEach(client => {
const msg = {
msg: "hello world from server"
};
client.send(JSON.stringify(msg));
});
});
const msg = {
msg: "something"
};
ws.send(JSON.stringify(msg));
});
wss.on("error", () => console.log("error"));
server.on("upgrade", function upgrade(request, socket, head) {
const pathname = url.parse(request.url).pathname;
if (pathname === "/ws") {
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit("connection", ws, request);
});
} else {
socket.destroy();
}
});
server.listen(8080);
С внешнего интерфейса Я инициализирую Websocket:
const ws = new WebSocket(`wss://api.example.com/ws`);
Однако я получаю сообщение об ошибке:
WebSocket connection to 'wss://api.example.com/ws' failed: Error during WebSocket handshake: Unexpected response code: 404
Кажется, что все нормально работает локально в моей docker -композиционной настройке. Но не могу понять, как заставить это работать на GKE + Istio.
ОБНОВЛЕНИЕ 1/15/20
Я изменил порядок маршрутизации виртуального сервиса. Ранее /ws
было после /
. Но теперь я получаю ошибку 503 от внешнего интерфейса.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: example-back-end
spec:
hosts:
- "api-dev.example.dev"
gateways:
- istio-system/example-gateway
http:
- match:
- uri:
prefix: /ws
route:
- destination:
host: service-websocket
port:
number: 443
websocketUpgrade: true
- match:
- uri:
prefix: /worker
route:
- destination:
host: worker
port:
number: 5001
- match:
- uri:
prefix: /
route:
- destination:
host: back-end
port:
number: 5000