Python Django撸个WebSSH操作Kubernetes Pod(下)- 终端窗口自适应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连接建立,前后端就会有一样的输出窗口大小,问题解决~

相关文章推荐阅读:
Python Django撸个WebSSH操作Kubernetes Pod(下)- 终端窗口自适应Resize的更多相关文章
- Python Django撸个WebSSH操作Kubernetes Pod
优秀的系统都是根据反馈逐渐完善出来的 上篇文章介绍了我们为了应对安全和多分支频繁测试的问题而开发了一套Alodi系统,Alodi可以通过一个按钮快速构建一套测试环境,生成一个临时访问地址,详细信息可以 ...
- Kubernetes WebSSH终端窗口自适应Resize
追求完美不服输的我,一直在与各种问题斗争的路上痛并快乐着 上一篇文章Django实现WebSSH操作Kubernetes Pod最后留了个问题没有解决,那就是terminal内容窗口的大小没有办法调整 ...
- Django实现WebSSH操作Kubernetes Pod
优秀的系统都是根据反馈逐渐完善出来的 上篇文章介绍了我们为了应对安全和多分支频繁测试的问题而开发了一套Alodi系统,Alodi可以通过一个按钮快速构建一套测试环境,生成一个临时访问地址,详细信息可以 ...
- Python/Django(CBV/FBV/ORM操作)
Python/Django(CBV/FBV/ORM操作) CBV:url对应的类(模式) ##====================================CBV操作============ ...
- [python][django学习篇][6]操作数据库
查询(取)数据 >>> Category.objects.all() <QuerySet [<Category: Category object>]> > ...
- Python - Django - ORM 多对多操作
models.py: from django.db import models # 出版社 class Publisher(models.Model): id = models.AutoField(p ...
- Python - Django - ORM 外键操作
models.py: from django.db import models # 出版社 class Publisher(models.Model): id = models.AutoField(p ...
- Django实现WebSSH操作物理机或虚拟机
我想用它替换掉xshell.crt之类的工具 WebSSH操作物理机或虚拟机 Django实现WebSSH操作Kubernetes Pod文章发布后,有小伙伴说咖啡哥,我们现在还没有用上Kuberne ...
- 基于Python+Django的Kubernetes集群管理平台
➠更多技术干货请戳:听云博客 时至今日,接触kubernetes也有一段时间了,而我们的大部分业务也已经稳定地运行在不同规模的kubernetes集群上,不得不说,无论是从应用部署.迭代,还是从资源调 ...
随机推荐
- 引入 JPEGCodec;JPEGImageEncoder; 图片处理;MyEclipse编译时报错处理
在Eclipse中处理图片,需要引入两个包: import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JP ...
- 递归遍历磁盘下的某一文件夹中所有文件,并copy文件生成文件和带文件夹的文件
package com.hudong.test; import java.io.File; import java.io.IOException; import java.util.ArrayList ...
- 根据现有的数据库自动生成Django model
Django引入外部数据库还是比较方便的,首先在setting里面设置你要连接的数据库类型和连接名称,地址之类,和创建新项目的时候一致 运行下面代码可以自动生成models模型文件 python ma ...
- ubuntu 18.04用apt安装mysql-server
mysql5.7安装完成后普通用户不能进mysql 原因:root的plugin被修改成了auth_socket,用密码登陆的plugin应该是mysql_native_password,直接用roo ...
- 虚拟机+server03系统+sql的安装
教程: 首先安装虚拟机 然后安装server系统 最后完成sql的安装 https://download.pchome.net/system/sysenhance/detail-4673.html 虚 ...
- 【算法记事本#NLP-1】最大匹配算法分词
本文地址:https://www.cnblogs.com/oberon-zjt0806/p/12409536.html #NLP-1 最大匹配算法(MM) 最大匹配算法(Maximum Matchin ...
- MySQL集群MGR架构for多主模式
本文转载自: https://www.93bok.com MGR简介 MySQL Group Replication(简称MGR)是MySQL官方于2016年12月推出的一个全新的高可用与高扩展的解决 ...
- 下载cv2时下载失败或下载成功却无法使用怎么办
最近我也在安装cv2的时候遇到了奇怪的问题,导致在安装cv2的时候无法使用.我在网上查了各种资料,虽然都对的,但都不太全面.本文就把安装cv2时可能遇到的各种奇怪的问题的解决方案做一个总结,供大家参考 ...
- JDK 1.8 新特性之Date-Time API
来源:请点击查看 1.8之前的日期类: 线程不安全:java.util.Date 这个类线程不安全,而且所有日期类都是可变的. 时间处理麻烦:默认的开始日期从1900年,不支持国际化,不提供时区支持, ...
- Python 第一天学习记录