我们目前正在开发一个通过Kubernetes管理服务的平台。作为其中的一部分,我们希望添加功能,以允许客户端(通过我们的UI)针对Pod发出Shell命令(使用两者之间的WebSocket)。我们正在尝试利用Kubernetes /exec
API端点来打开到Pod的连接。问题是,虽然套接字的初始设置看起来工作良好,但从UI向容器发出后续命令却无法从容器中获得任何响应-就像容器未收到消息一样。 / p>
我们目前有一个Node.js Express REST服务,作为UI和Kubernetes之间的中间人。 REST服务负责管理两个Web套接字-一个从UI到服务,另一个从服务到Kubernetes。该服务负责在发生交互时通过一个套接字向另一个套接字发送消息。
当UI需要将shell命令发送到Pod时,它通过调用REST服务来启动打开套接字的过程,然后通过以下Kubernetes API调用来打开Pod的套接字
/ api / v1 /命名空间/命名空间-xxxxxx / pods / hello-world-xxxxxxxx / exec?stdin = true&stderr = true&stdout = true&tty = true&command = sh
而Express管理从REST服务到UI的套接字。
REST服务具有一个“管道”功能,该功能具有每个套接字的句柄,并在必要时在两个套接字之间传递数据(为简便起见,删除了调试语句):
const pipe = (podSocket, clientSocket) => {
podSocket.onopen = function (event) {
debug(`podSocket.onopen(event): opened websocket connection at ${new Date()}. Event is ${circularJson.stringify(event)}`);
};
podSocket.onmessage = function (event) {
if (clientSocket.readyState === 1) {
const text = Buffer.from(event.data, 'binary').toString('utf-8');
clientSocket.send(text);
}
};
podSocket.onerror = function (err) {
clientSocket.close(1000);
podSocket.close();
};
podSocket.onclose = function (event) {
debug(`podSocket.onclose(): instance closed connection at ${new Date()} with code ${event.code}, reason [${event.reason}]`);
};
clientSocket.onmessage = function (event) {
const text = Buffer.from(event.data, 'binary').toString('utf-8');
if (clientSocket.readyState === 1) {
if (podSocket.readyState === 3)
clientSocket.send(`Connection to instance has been closed`);
else {
podSocket.send(text); // <----------- Issue seems to be here
}
}
};
clientSocket.onerror = function (err) {
clientSocket.close(1000);
podSocket.close(1000);
};
clientSocket.onclose = function (event) {
debug(`clientSocket.onclose(): instance closed connection at ${new Date()} with code ${event.code}, reason [${event.reason}]`);
podSocket.close(1000);
};
};
如上所示,当REST服务检测到已从客户端接收到一条消息(shell命令)时,它将尝试将该消息转发到打开到容器的套接字。但是我们无法从Pod在其套接字的onmessage()
回调中获得任何响应。
上面未出现的部分调试语句确实表明REST服务正在接收要执行的命令,并且该命令正在通过另一个套接字发送到Pod。我还进行了调试,显示当两个套接字都打开时,两个套接字都显示为“就绪”状态。
这是我们看到的一小段内容:
/app #
是Pod的默认目录,它是websocket初始设置的响应,因此我们知道初始连接是正确的。但是,随后的两个命令完全没有响应,直到套接字超时并且连接被关闭。
我们在这里缺少什么?为什么我们无法将套接字绑定到Pod以响应发送给它的消息?