一. 前言
在微服务大行其道的今天,容器恰巧又是微服务的主要载体,所以我们操作的对象也由最开始的「物理机」到「虚拟机」再到今天的「容器」。由于这些载体的变更,我们的使用方式也需要随之发生一些改变。比如一个最常用的登入操作,「虚拟机」下我们可能通过 ssh 的方式 ,但如果是容器呢?ssh 的方式就需要在每个容器中都运行一个 sshd 进程,这种做法可行但略显繁琐,也不太符合一个容器只运行一个进程的思想。
那么有没有一个即方便快捷又安全的登入方式呢?
有,通过 Web Terminal 的方式,通过 Web 的方式即可以避免对客户端的依赖又能够实现用户权限控制。目前,有很多开源的 Web Terminal 的项目,基本上都是通过 ssh 代理的方式调用并返回一个 shell 的虚拟终端(pty)。
二. 实现容器的 Web Terminal
2.1 架构图
JS虽然可以利用方法来调用命令行等工具,但本身并没有操纵操作系统的能力。这时,Web Terminal在JS中能够实现的只有虚拟终端的部分。JS通过WebSocket与d-terminal相互通信,将d-terminal与数据库交互、与服务器交互的内容经过处理后,展示在界面中。
2.2 前端 Web Termianl 页面
Linux 终端返回的内容会带很多特殊的字符,比如我输入一个 ls
指令,终端返回的结果如下:
'l'
's'
'\r\n'
'\x1b[0;0mRUNNING_PID\x1b[0m \x1b[1;34mbin\x1b[0m
\x1b[1;34mconf\x1b[0m \x1b[1;34mlib\x1b[0m\r\nbash-4.3# '
将这些结果渲染在页面显然是不可以的,这时候就必须要借助一些工具,例如模拟 Terminal 的 JavaScript库 xterm.js、jquery.terminal、ioterm、terminal.js等等。虽然看起来种类很多,但是他们的本质趋于相同,
利用canvas或者各种标签来模拟终端的样式。通过WebSocket与后端通信,把得到的信息展示在界面中。
2.3 d-terminal
d-terminal 是这个系统的核心,它分成两个部分:
一部分用于处理用户端的输入和输出,以及存储和展示后端 Docker Dameon 主机的 IP 和 container_id。因为像 top 这样的监控命令需要服务端定时推送数据给客户端,所以使用了 WebSocket 协议以支持服务端推送。
另一部分用于调用 Docker Daemon 返回虚拟终端。对于终端来说,通常是你输入一个字符就会立马返回,直到你输入一个 “归位键” 终端才会把你输入的字符拼接成一个字符串并发送给 shell 解释器,并将 shell 解释器的结果返回。为了提升使用流畅性,新启用了一个线程去调用 Docker Daemon API,当然也可以使用像 epoll 这样的多路复用技术来实现。
三. 总结
上述仅仅是描述了一个最基本的实现逻辑,具体实现还需要自行编写。