Kubernetes WebSSH终端窗口自适应Resize
追求完美不服输的我,一直在与各种问题斗争的路上痛并快乐着
上一篇文章Django实现WebSSH操作Kubernetes Pod最后留了个问题没有解决,那就是terminal内容窗口的大小没有办法调整,这会导致的一个问题就是浏览器上可显示内容的区域太小,当查看/编辑文件时非常不便,就像下边这样,红色可视区域并没有被用到


RESIZE_CHANNEL
前文说到kubectl exec有两个参数COLUMNS和LINES可以调整tty内容窗口的大小,命令如下:
kubectl exec -i -t $1 env COLUMNS=$COLUMNS LINES=$LINES bash
这实际上就是将COLUMNS和LINES两个环境变量传递到了容器内,由于Kubernetes stream底层也是通过kubernetes exec实现的,所以我们在启动容器时也将这两个变量传递进去就可以了,就像这样
exec_command = [
"/bin/sh",
"-c",
'export LINES=20; export COLUMNS=100; '
'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']
添加了export LINES=20; export COLUMNS=100;,可以实现改变tty的输出大小,但这有个问题就是只能在建立链接时指定一次,不能动态的更新,也就是在一次websocket会话的过程中,如果页面大小改变了,后端输出的LINES和COLUMNS是无法随着改变的
在解决问题的过程中发现官方源码中有个RESIZE_CHANNEL的配置,同样可以控制窗口的大小,使用方法如下:
cont_stream = stream(api_instance.connect_get_namespaced_pod_exec,
name=pod_name,
namespace=self.namespace,
container=container,
command=exec_command,
stderr=True, stdin=True,
stdout=True, tty=True,
_preload_content=False
)
cont_stream.write_channel(4, json.dumps({"Height": int(rows), "Width": int(cols)}))
这样我们就可以修改stream输出的窗口大小了
xterm.js fit
一顿操作后,打开页面,咦?怎么页面不行,原来窗口的调整不仅需要调整stream输出数据的窗口大小,前端页面也要跟着一并调整
这里用到了xterm.js的另一个组件fit,fit可以调整终端大小的cols和rows适配父级元素
首先调整terminal块的宽度和高度为整个页面可视区域的大小,要让整个可视区域为终端窗口
document.getElementById('terminal').style.height = window.innerHeight + 'px';
然后引入fit组件,在term初始化之后执行fit操作
<script src="/static/plugins/xterm/xterm.js"></script>
<script src="/static/plugins/xterm/addons/fit/fit.js"></script>
<script>
// 修改terminal的高度为body的高度
document.getElementById('terminal').style.height = window.innerHeight + 'px';
var term = new Terminal({cursorBlink: true});
term.open(document.getElementById('terminal'));
// xterm fullscreen config
Terminal.applyAddon(fit);
term.fit();
console.log(term.cols, term.rows);
</script>
fit之后就可以通过term.cols和term.rows取到xterm.js根据字体大小自动计算过的cols和rows的值了,然后把这两个值传递给kubernetes,kubernetes再根据这两个值输出窗口大小,这样前后端匹配就完美了
数据传递
xterm.js可以通过如下的方法动态的将cols和rows传递给后端
term.on('resize', size => {
socket.send('resize', [size.cols, size.rows]);
})
但当窗口由大变小时,之前输出的内容会有样式错乱,我为了方便直接在WebSocket连接建立时采用url传参的方式把cols和rows两个值传递给后端,kubernetes根据这两个值来设置输出内容的窗口大小,这样做的缺点是不会随着前端页面的变化动态的去调整后端stream输出窗口的大小,不过问题不大,如果页面调整大小,刷新下页面重新建立连接就可以啦,具体实现如下
首先需要修改的就是WebSocket的url地址
前端增加term.cols和term.rows两个参数的传递
var socket = new WebSocket(
'ws://' + window.location.host + '/pod/{{ name }}/'+term.cols+'/'+term.rows);
Routing增加两个参数的解析
re_path(r'^pod/(?P<name>\w+)/(?P<cols>\d+)/(?P<rows>\d+)$', SSHConsumer),
Consumer解析URL将对应参数传递给Kubernetes stream
class SSHConsumer(WebsocketConsumer):
def connect(self):
self.name = self.scope["url_route"]["kwargs"]["name"]
self.cols = self.scope["url_route"]["kwargs"]["cols"]
self.rows = self.scope["url_route"]["kwargs"]["rows"]
# kube exec
self.stream = KubeApi().pod_exec(self.name, cols=self.cols, rows=self.rows)
kub_stream = K8SStreamThread(self, self.stream)
kub_stream.start()
self.accept()
最后Kubernetes stream接收参数并修改窗口大小
def pod_exec(self, RAND, container="", rows=24, cols=80):
api_instance = client.CoreV1Api()
exec_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']
cont_stream = stream(api_instance.connect_get_namespaced_pod_exec,
name=pod_name,
namespace=self.namespace,
container=container,
command=exec_command,
stderr=True, stdin=True,
stdout=True, tty=True,
_preload_content=False
)
cont_stream.write_channel(4, json.dumps({"Height": int(rows), "Width": int(cols)}))
return cont_stream
至此,每次WebSocket连接建立,前后端就会有一样的输出窗口大小,问题解决~

相关文章推荐阅读:
Kubernetes WebSSH终端窗口自适应Resize的更多相关文章
- Python Django撸个WebSSH操作Kubernetes Pod(下)- 终端窗口自适应Resize
追求完美不服输的我,一直在与各种问题斗争的路上痛并快乐着 上一篇文章Django实现WebSSH操作Kubernetes Pod最后留了个问题没有解决,那就是terminal内容窗口的大小没有办法调整 ...
- WPF 窗口自适应
窗口自适应就是说,当主窗口缩放的时候,内部的控件位置自动的调整,而不是隐藏掉.这主要依赖于Grid布局. 1.比如这个groupbox 本身是在一个Grid的Row中的.缩放之后,左边的button不 ...
- xshell 终端窗口目录显示为深蓝色的不易分辨问题
xshell更改终端窗口目录展示深蓝色的不易分辨 经常使用xshell远程连接服务器,使用ls命令,目录的颜色都是深蓝色, 如果终端窗口背景颜色是黑色的(对眼睛较好的黑色的背景色,大家一般都选择黑色背 ...
- 终端I/O之终端窗口的大小
大多数UNIX系统都提供了一种功能,可以对当前终端窗口的大小进行跟踪,在窗口大小发生变化时,使内核通知前台进程组.内核为每个终端和伪终端保存一个winsize结构: Struct winsize { ...
- 显示 Ubuntu 11.10 的 终端窗口
显示 Ubuntu 11.10 的 终端窗口 一.点击左上角的图标 -> 在search框里搜索termial . 二.快捷键:Ctrl+Alt+t.
- Ubuntu自定义终端窗口位置
方法一: 自定义终端启动快捷键 具体方法是自定义一个快速启动终端的快捷键,附带设置终端启动时的位置参数.首先获得需要放置窗口的目标位置信息,可以通过终端命令“ xwininfo ”来获得.步骤是首先打 ...
- VS Code 终端窗口无法输入命令的解决方案
问题 今天打开vs code,打开终端窗口,发现不能输入命令了 解决方法 邮件桌面 vscode的快捷键,打开“兼容性”标签,勾选"以管理员身份运行此程序" 结果 修改之后重启vs ...
- 使用MVVM DataTriggers在WPF XAML视图之间切换/Window窗口自适应内容大小并居中
原文 使用MVVM DataTriggers在WPF XAML视图之间切换 相关文章: http://www.technical-recipes.com/2016/switching-between- ...
- VMVare的窗口自适应
啊!好久没来博客园了.原因很简单,我把密码丢了. 最近才从系统申请重置了密码,这不,又能登录了.你可能好奇,是的,我也在疑惑:我是不是搞IT的啊?因为只要密码丢失,我就认为世界完蛋了,我完蛋了:) 这 ...
随机推荐
- Flink 从 0 到 1 学习 —— Flink 配置文件详解
前面文章我们已经知道 Flink 是什么东西了,安装好 Flink 后,我们再来看下安装路径下的配置文件吧. 安装目录下主要有 flink-conf.yaml 配置.日志的配置文件.zk 配置.Fli ...
- mysql 函数 存取过程
1.打开数据库 2.选择函数,点击新建函数,选择过程,点击完成 4.写入自己要添加的sql语句 5.点击CTAL + S 保存,如若报错则语法或函数错误
- Jenkins把GitHub项目做成Docker镜像
本文是<Jenkins流水线(pipeline)实战>系列的第三篇,前面已对Jenkins流水线有了基本认识,也试过从GitHub下载pipeline脚本并执行,今天的实战是编写一段pip ...
- SpringCloud-Hystrix Dashboard 之 Unable to connect to Command Metric Stream
实践hystrix dashboard仪表盘的时候,不管是按照书上的还是网上的,都提示Unable to connect to Command Metric Stream. 查了好久发现,如果使用sp ...
- netCDF4 not installed properly - DLL load failed (netCDF4安装问题)
环境描述:windows10 ,conda,python3.6 问题描述:netCDF4是python中用来处理地球气象数据的文件读取包,在安装完成后,from netCDF4 import Data ...
- 前台提交数据到node服务器(get方式)
.有两种办法,一种是表单提交,一种是ajax方式提交. 1.form提交 在前台模板文件上写: <form action="/reg" method="get&q ...
- 2019-2020学年:Java自学书单(定个小目标)
spring spring技术内幕(回顾+深入) mysql 高性能mysql innoDB (回顾+深入) redis redis实战 redis设计与实现(巩固) 算法 算法第四版 java实现 ...
- APP自動化測試腳本3
package com.lemon.day01; import java.net.MalformedURLException; import java.net.URL; import java.uti ...
- vue中关于滚动条的那点事
vue中关于滚动条的那点事 不知道你有没有遇到过这种情况,有时当页面切换时,滚动条不在页面的顶端.最近半路加入一个项目,就遇到这种情况.(若只是为了解决此问题,可直接翻到最下方)下面谈谈解决此问题的过 ...
- 详解http报文
摘要 作为一个web开发者,每天都在使用者Http协议,却总是一知半解.本文参看Http RFC7230规范,梳理了http报文部分. http 报文构成 start-line: 起始行,描述请求或响 ...