BCS 做容器的 WebConsole 也算很久了,这个目前使用频率还是很高的,但是 vim 这类操作一直不支持,最近更新了一个版本,可以完美支持 vi/vim 等操作

容器 WebConsole 技术小结

BCS 做容器的 WebConsole 也算很久了,这个目前使用频率还是很高的,但是 vim 这类操作一直不支持,最近更新了一个版本,可以完美支持 vi/vim 等操作

核心技术

数据交互流程

这里是通过 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记得不要使用内置函数