【干货】容器Web Console技术实现

容器Web Console技术实现

1

Web Console背景

现如今,随着容器技术的普及,越来越多的公司都开始尝试将其与自身的业务相结合,以提高生产和运维效率。

在经历了小规模测试后,随着容器数量的增长,如何管理容器是所有人都绕不开的一个主要问题。容器管理平台建立在容器编排引擎之上,抽象了编排引擎的实现细节,为用户提供更方便的功能,比如应用部署、升级、扩缩容等。

当用户部署一个应用后,有许多场景,用户希望能够进入到容器中,直观的查看应用的状态和日志,比如业务故障,此时常见的方法为:

1) 查询容器所在主机的IP

2) ssh到所在主机

3) 使用docker exec 进入到容器中

这种方法的主要缺点在于,需要先ssh到指定的主机上,在许多环境中,主机的用户名和密码都是严格保密的,可能需要向安全管理人员进行申请,这样一来,就可能存在泄漏的风险,同时会耗时很久,造成无法及时定位问题。

针对上面的问题,Web Console提供了一个更优的解决方案,它能在Web中提供一个交互式的界面,然后像直接使用shell一样执行各种命令。

2

Web Console技术原理

Web Console技术通过websocket实现。

在后端和浏览器之间建立websocket连接后,将用户在浏览器中输入的命令通过websocket协议发送到后端,后端提前使用docker exec进入到容器,将收到的命令从docker exec进程的stdin写入,命令执行后,再从docker exec进程的stdout中读取输出,通过websocket协议返回浏览器显示给用户,达到交互的目的。

3

基于GoTTY的Web Console开发

3.1:GoTTY简介

GoTTY 是一个简单的命令行工具,可将CLI工具转换为web应用程序。

Github地址:https://github.com/yudai/gotty

GoTTY是使用go语言开发的,在安装go后,进行编译,然后可进行简单的测试。

如下,让GoTTy执行bash,就可实现在浏览器中访问GoTTy所在的主机,如下:

-w选项表示接收用户的输入,否则无法在浏览器中输入命令。

在浏览器中访问如下:

GoTTy的访问的过程如下:

GoTTY实现细节

  • GoTTY中index.html、favicon.png、hterm.js和gotty.js四个文件都是经gzip压缩过后,直接存放在内存中的,分别为_staticIndexHtml、_staticFaviconPng、_staticJsHtermJs和_staticJsGottyJs。
  • gotty.js会首先执行其内部方法openWs,建立websocket连接。在连接打开以后,创建终端仿真器hterm。随后,通过hterm收到的键盘输入消息,将通过websocket连接发送给GoTTY,同时,从websocket中读取到的消息,将写入到hterm中,最终显示给用户。
  • GoTTY在收到用户请求后,会执行启动时设置的参数,得到进程的stdin和stdout。随后会在单独的goroutine中,循环读取进程的输出写到websocket中,循环从websocket中读取写到进程的输入中。如下:

3.2:基于GoTTY的容器Web Console实现

在了解了GoTTY的实现原理之后,再实现Web Console连接容器的功能,就很简单了。

Web Console功能的开发可以在GoTTY原有的基础之上进行修改,也可以参考GoTTY的实现,将其移植到自己的组件中。

在实现时,可以选择以下两种模型:

分布式 agent

此种模型,在每个节点上都部署一个webconsole agent。

一般情况下,集群中每个节点都会有各种各样的agent负责相关工作,Web Console功能可以直接嵌入到这些组件中。

前端在使用时,需要先确定容器位于哪个节点上,然后带上容器id等必要信息,直接访问对应的Web Console功能。

集中式agent

此种模型,在集群中只部署一个webconsole agent,这里要考虑高可用,防止单点故障。

前端在使用时,直接访问固定的webconsole agent,带上容器所在主机ip、容器id等必要信息。

如果使用docker exec命令访问容器,则需要docker engine监听一个固定的端口,供webconsole agent使用docker exec –H 命令。

如果你的集群是使用kubernetes管理,这里也可以使用kubectl exec命令实现。

以上两种方式,在代码实现上差别很小,只需要修改相应的命令即可,如下:

3.3:安全审计

Web Console给用户进入容器提供了便利,用户可以执行任何操作,同时为了安全,记录下用户的操作也非常有必要。

这里最简单的方法就是从命令进程stdout中读取到内容,通过websocket返回的同时,也输出到一个日志文件中,如下:

日志文件可以根据自身业务规则定义文件名,方便检索。

3.4:容器残留进程清理

在调试过程中,曾出现一个问题,在进入到容器,进行一系列操作后,如果使用exit退出,则一切正常,但是如果直接关闭掉浏览器网页,最后会发现连接到容器中的shell进程没有退出,会一直存在,慢慢积累,残留进程就会越来越多,如下:

这里采用的解决办法是,在连接到容器后,增加一步初始操作,将当前shell的进程id保存到一个文件中,在监测到连接关闭后(不管是正常的关闭还是任何异常关闭),执行清理工作,使用docker exec命令杀掉保存的进程。

如下为保存shell进程号的相关操作:

4

实现效果

Web Console功能最终应该是作为容器管理平台的一个子功能,提供给用户使用。

下面为vivo devops平台的示例,在容器管理界面点击控制台,打开Web Console功能:


关于作者

陈俊超@vivo

vivo云平台工程师,负责vivo CaaSs平台相关设计与开发。目前专注于CaaS技术栈的开发工作。

本文章未经授权,禁止转载,授权请联系小助手微信: Labs2020

本文分享自微信公众号 - vivo互联网技术(vivoVMIC)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-10-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券