容器 WebConsole 技术小结
BCS 做容器的 WebConsole 也算很久了,这个目前使用频率还是很高的,但是 vim 这类操作一直不支持,最近更新了一个版本,可以完美支持 vi/vim 等操作
容器 WebConsole 技术小结
BCS 做容器的 WebConsole 也算很久了,这个目前使用频率还是很高的,但是 vim 这类操作一直不支持,最近更新了一个版本,可以完美支持 vi/vim 等操作
核心技术
- pseudo-tty 原理
- ANSI_escape_code
- rfc1073-Telnet Window Size Option
数据交互流程
这里是通过 websocket 访问 docker 的数据交换流程,
支持 VIM 等编辑操作
在 BCS WebConsole 的老版本中, 对 VI/VIM 支持是很差的, 使用会变现,无法保存等。
后面在看 rancher的实现, vscode的实现,发下他们对vim支持非常好, 和原生的命令行基本没有差别,在反复对比和测试后,发下主要是一个resize fit没有适配, 编码问题
在完全执行了resize方法后, 同时使用base64编码,可以直接从bytes流修改为字符串,转发到浏览器层
debounceFit
debounce
中文去抖动的意思,在上面的编码中,我们知道需要实时捕获浏览器窗口的大小,同时同步给后端容器的终端环境
但是在浏览器的实现中,一个拖动会触发多次事件, 而我们关心的是最后的稳定状态, 表现就是中间的抖动
过程,需要过滤掉
可以看到,通过去抖动, 原理发送请求有3~6次,可以减少为1次
实现方面, github已经有相关库的封装 throttle-debounce,可以直接使用
代码参考
// debounce 200 毫秒, 减少 resize 事件多次触发问题
const debounceFit = throttleDebounce.debounce(200, false, function() {
fitAddon.fit();
})
term.onResize(function (size) {
data = JSON.stringify({cols: term.cols, rows: term.rows})
// set_pty_size()
if (typeof ws != "undefined") {
// RESIZE_CHANNEL = 4
ws.send('4' + Base64.encode(data));
console.log('set_pty_size: ' + data)
}
});
window.onresize = function (event) {
debounceFit();
};
Bash 命令行 Fallback
我们知道容器中,一般有sh, bash, zsh等, 其中bash, sh2中是最常用的, bash功能强大很多,可以有自动补全等,但是不一定待, sh基本所有容器都会有
在最早的设计中, 其实是想有一个命令行选择, 用用户选择bash, sh, 但是后面还是没有上线,一个是麻烦,二是用户可能也不知道是否有bash, 所以最早进入用户容器统一是sh,如果需要,用户自己只需bash
这个可以使用下面的命令行
DEFAULT_COMMAND = [
'/bin/sh',
'-c',
'TERM=xterm-256color; export TERM; [ -x /bin/bash ] && ([ -x /usr/bin/script ] && /usr/bin/script -q -c "/bin/bash" /dev/null || exec /bin/bash) || exec /bin/sh', # noqa
]
意思是如果有bash,优先使用bash,如果没有,使用sh命令行
镜像最小化
用容器隔离,那么镜像就显得很重要了, 线上也有 bitnami-docker-kubectl,但是考虑了下,还是自己制作, 主要考量:
- 公司内部也需要使用,对某些命令需要限制
- bitnami 只维护了最小的几个版本的kubectl,内部版本最小1.8,这个bitnami是没有的
- 体积可以进一步精简, bitnami依赖的minideb,在目前的场景, 直接alpine会更加友好
不是很多, 直接贴里面了, 但是每行反复验证过, 包括vim,自动补全等
FROM alpine:3.14
ARG KUBECTL_VERSION=v1.8.13
ARG HELM_VERSION=v3.6.1
WORKDIR /root
# 安装依赖包
RUN apk add --update wget bash-completion vim
# 添加 kubectl 命令行
RUN wget -q https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl && \
mv kubectl /usr/local/bin && \
chmod a+x /usr/local/bin/kubectl && \
kubectl version --client
# 添加 helm 命令行
RUN wget -q https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz && \
tar -xf helm-${HELM_VERSION}-linux-amd64.tar.gz && \
mv linux-amd64/helm /usr/local/bin && \
rm -rf helm-${HELM_VERSION}-linux-amd64.tar.gz linux-amd64 && \
helm version
# 清理缓存和不符合安全规范的命令
RUN apk del wget && \
rm -rf /var/cache/apk/* && \
rm -rf /sbin/apk /usr/bin/wget
# 初始化 bash 配置
RUN echo "source /etc/profile.d/bash_completion.sh" >> ~/.bashrc && \
echo "source <(kubectl completion bash)" >> ~/.bashrc && \
echo "export PS1='\u:\W\$ '" >> ~/.bashrc && \
echo "export TERM=xterm-256color" >> ~/.bashrc
# 启动一个常驻进程
CMD ["/bin/sh", "-c", "sleep infinity"]
安全审计
Web Console给用户进入容器提供了便利,用户可以执行任何操作,同时为了安全,记录下用户的操作也非常有必要。
目前实现是在 WebSocket Handler 层,全量拦截用户输入,返回的输出,添加操作上下文后放大数据队列中,定期上报的数据平台
效果如下图
最后
目前代码都已经开源到github,可以参考 Tencent/bk-bcs-saas项目
使用到的库
注:base64记得不要使用内置函数