本篇将说明Kubernetes exec API的运作方式,并以简单范例进行开发在前后端上。虽然Kubernetes提供了不同资源的RESTful API来进行CRUD操作,但是部分API并非单纯的回传一个资料,有些是需要透过SPDY或WebSocket建立长连线串流,这种API以exec,attach为主,目标是对一个Pod执行指定指令,或者进入该Pod进行互动等等。

Exec API端点

首先了解一下Kubernetes exec API端点,由于Kubernetes官方文件并未提供相关资讯,因此这边透过kubectl指令来了解API的结构:

$ cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: ubuntu
spec:
containers:
- name: ubuntu
image: ubuntu:16.04
command: ['/bin/bash', '-c', 'while :; do echo Hello; sleep 1; done ']
EOF $ kubectl -v = 8 exec -ti ubuntu bash
...
I0625 10:39:33.716271 93099 round_trippers.go:383] POST https://xxx.xxx.xxx.xxx:8443/api/v1/namespaces/default/ pods / ubuntu / exec?command = bash&container = ubuntu&container = ubuntu&stdin = true&stdout = true&tty = true
...

从上述得知exec API结构大致如下图所示:

其中API中的查询又可细分以下资讯:

  • command:将被执行的指令。若指令为ping 8.8.8.8,则API为command=ping&command=8.8.8.8。类型为string值。
  • container:哪个容器将被执行指令。若Pod只有一个容器,一般会用API找出名称塞到该参数中,若多个则选择让人输入名称。类型为string值。
  • stdin:是否开启标准输入,通常由使用者决定是否开启。类型为bool值。
  • stdout:是否开启标准输出,通常是預設開啟。类型为bool值。
  • stderr:是否开启标准错误输出,通常是預設開啟。类型为bool值。
  • tty:是否分配一个终端设备(Pseudo TTY,PTY)。ㄒ为bool值。

协议

执行是利用SPDY与WebSocket协定进行串流沟通的API,其中SPDY在Kubernetes官方的client-go已经有实现(参考远程命令),而kubectl正是使用SPDY,但是是SPDY目前已经规划在未来将被移弃,因此建议选择使用WebSocket来作为串流沟通。但而无论是使用哪一个协定,都要注意请求的Header必须有Connection: UpgradeUpgrade: xxx等,不然API Server会拒绝存取请求。

HTTP标头

除了SPDY与WebSocket所需要的Headers(如升级等)外,使用者与开发者还必须提供两个Headers来确保能够正确授权并沟通:

  • 授权:该Header是用来提供给API Server做认证请求的资讯,通常会是以Authorization: Bearer <token>的形式。
  • 接受:指定客户端能够接收的内容类型,一般为Accept: application/json,若输入不支持的类型将会被API以406 Not Acceptable拒绝请求。

沟通协定

一旦符合上述所有资讯后,WebSocket(或SPDY)就能够建立连线,并且与API服务器进行沟通。而当写入WebSocket时,资料将被传送到标准输入(stdin),而WebSocket的接收将会是标准输出(stdout)与输出错误(stderr).Kubernetes API服务器简单定义了一个协定来复用stdout与stderr。因此可以理解当WebSocket建立连线后,传送资料时需要再缓冲的第一个字元定义为stdin(buf [0] = 0),而接收资料时要判断stdout(buf [0] = 1)与stderr(buf [0] = 2)。其资讯如下:

标准串流
0 标准输入
1 标准输出
2 标准错误

简单下面以发送ls指令为例:

#传送`ls`指令,必须buf [0]自行塞入0字元来表示stdin.buf
= [0 108 115 10] #接收
BUF = [1 108 115 13 10 27 91 48 109 27 91 ...]

最后需要注意Timeout问题,由于可能对WebSocket设置TCP Timeout,因此建议每一段时间发送一个stdin空讯息来保持连线。

透过WebSocket 实现Kubernetes Exec Terminal

一般我们在操作K8S (Kubernetes) 都是透过kubectl 命令,其实kubectl 所有操作都是呼叫K8S 提供的标准WebService API,然而有时候需要进Container Debug 的时候就需要透过exec 功能。有用过K8S Dashboard 应该也知道,管理者可以任意进入某一个Container Terminal,其实就是透过exec sh command 来实现。我一直很好奇K8S Dashboard 要如何在Web 实现这样的功能,查一下果然不出所料有一个WebSocket API 可以使用,于是开始研究如何自己实现像是Dashboard Terminal 这样的功能。

K8S Exec Command API WebSocket 串接

我今天的目的是要在Web做出跟K8S Dashboard Terminal一样的功能,其中必须透过WebSocker API进行串接。这一个Exec API官方说明相当少,其实有一个Kubernetes Project,叫做container-terminal  已经有实做一样的功能,但是我实际测试的时候并不work,因为K8S API呼叫的Token必须透过HTTP Header传递,然而标准的HTML5并没有夹带自订Header的方法,container-terminal所使用在Query String夹带access_token并不是标准作法。

我按下F12 光明正大偷看了K8S Dashboard 的作法,发现是透过Cookie 自行验证WebSocket 权限,看来要透过HTML5 标准来呼叫API 就要自己实做Server 了。

开始以前,我们先看看只有一条IO特性的WebSocket如何处理exec呢?其实exec就是命令呼叫,所有的程式在Linux执行一个程序都是一样的,程序启动时会分配三个档案描述子(File Descriptor),分别是StdIn (标准输入), Std Out (标准输出), Std Error Out (标准错误输出),当我们的WebSocket成功Upgrade为TCP/IP之后,K8S API必须提供一个协定来处理这三种标准描述子的收发工作。区分方法就是在资料最前端加入一个Byte,如下:

Byte 0 : 标准输入

Byte 1 : 标准输出

Byte 2 : 标准错误输出

有了这些资讯我们就可以开始实做了WebSocket 串接了。

透过WebSocket 串接K8S Exec API 实现Terminal

由于刚刚提到HTML5 WebSocket标准并不提供自订的HTTP Header,因此我的想法是在Server端透过NodeJS夹带Token来连线K8S Exec WebSocket API,因为不在Browser的NodeJS就可以自订Request Header好通过K8S的验证机制。然后另外启动一个WebSocket Server提供浏览器进行连线,当然这里的认证机制要自己实做了,可以用Cookie/Session控制即可,这样一来也不需要暴露API Token。总而言之就是一个左手接右手传的机制,这里的终端机介面移植container-terminal用了xterm.js  套件,跑起来的画面如下:

这样一来就可以在浏览器操作你的Container,由于是命令模式并非VM 那种传整个画面的终端机,所以用起来貌似飞快,速度就跟平常使用SSH 差不多速度,满酷炫的。

范例程式码在GitHub 有兴趣请自己玩看看啰。

https://github.com/samejack/web-k8s-exec

此外,上述提到的K8S API WebSocket 协定,其实用在Log API 也是一样的,就可以在Web 做出logs 画面的即时输出,也是很方便。闪电分享结束.......下台一鞠躬~

Kubernetes exec API串接分析的更多相关文章

  1. kubernetes核心原理之API Server原理分析

    kubernetes API Server的核心功能是提供了Kubernetes各类资源对象(Pod,RC,Service等)的增删改查及Watch等HTTP Rest接口,成为集群内各个功能模块之间 ...

  2. Kubernetes client-go DeltaFIFO 源码分析

    概述Queue 接口DeltaFIFO元素增删改 - queueActionLocked()Pop()Replace() 概述 源码版本信息 Project: kubernetes Branch: m ...

  3. 微服务、SOA 和 API对比与分析

    摘要: 对比微服务架构和面向服务的架构(SOA)是一个敏感的话题,常常引起激烈的争论.本文将介绍这些争论的起源,并分析如何以最佳方式解决它们.然后进一步查看这些概念如何与 API 管理概念结合使用,实 ...

  4. 深入了解Kubernetes REST API的工作方式

    关于Kubernetes REST API的工作方式: 在哪里以及如何定义从REST路径到处理REST调用的函数的映射? 与etcd的交互发生在哪里? 从客户端发出请求到保存在etcd中对象的端到端路 ...

  5. 如何用 Python 和 API 收集与分析网络数据?

    摘自 https://www.jianshu.com/p/d52020f0c247 本文以一款阿里云市场历史天气查询产品为例,为你逐步介绍如何用 Python 调用 API 收集.分析与可视化数据.希 ...

  6. kubernetes 的API 介绍

    在API conventions doc中描述了API的全部协议. 在API Reference文档中描述了API的端点.资源类型和示例. 在Controlling API Access doc中讨论 ...

  7. 记一次 .NET 某纺织工厂 MES系统 API 挂死分析

    一:背景 1. 讲故事 这个月中旬,有位朋友加我wx求助他的程序线程占有率很高,寻求如何解决,截图如下: 说实话,和不同行业的程序员聊天还是蛮有意思的,广交朋友,也能扩大自己的圈子,朋友说他因为这个b ...

  8. Qt 事件系统浅析 (用 Windows API 描述,分析了QCoreApplication::exec()和QEventLoop::exec的源码)(比起新号槽,事件机制是更高级的抽象,拥有更多特性,比如 accept/ignore,filter,还是实现状态机等高级 API 的基础)

    事件系统在 Qt 中扮演了十分重要的角色,不仅 GUI 的方方面面需要使用到事件系统,Signals/Slots 技术也离不开事件系统(多线程间).我们本文中暂且不描述 GUI 中的一些特殊情况,来说 ...

  9. Docker系列(十四):Kubernetes API和源码分析

    Kubernetes API入门 Ku8 eye开源项目

随机推荐

  1. gevent.queue

    目录 Gevent gevent基础之阻塞,非阻塞 同步,异步概念 同步异步与阻塞,非阻塞区别 Queue python内置Queue介绍 Gevent gevent基础之阻塞,非阻塞 1.geven ...

  2. MVVM架构方式

    一.概念 ①常见的架构方式或者开发思想还有MVC.MVP和MVVM,参考文章:MVC,MVP 和 MVVM 的图示 ②MVC:视图(View),指用户界面:控制器(Controller),指业务逻辑: ...

  3. 鸿蒙OS与微内核

    目前主流面向个人端操作系统都不是像鸿蒙一样采用微内核的,或许在这些操作系统上诞生时面对的需求场景用微内核是行不通的.但在当前场景下是不是能走通要实际验证才知道.面对当前操作系统已成熟的市场生态.专利技 ...

  4. Kafka的基本概念

    Kafka的前身是由LinkedIn开源的一款产品,2011年初开始开源,加入了 Apache 基金会,2012年从 Apache Incubator 毕业变成了 Apache 顶级开源项目. Top ...

  5. SQL进阶-索引设置&sql优化

    一.索引设置 1.索引的设置原则 经常出现在WHERE条件.关联条件中的字段作为索引字段: 在满足查询需求的前提下,应尽可能少的创建索引:(对于一个组合索引,可以满足以组合索引左边的一部分字段的查询需 ...

  6. uni-app 获取网络状态

    uni.getNetworkType(OBJECT) 获取网络类型. OBJECT 参数说明 参数名 类型 必填 说明 success Function 是 接口调用成功,返回网络类型 network ...

  7. Ubuntu使用小结(主要为后面部署K8s集群做基础铺垫)

    包管理 dpkg -L libxml2 #查看libxml2安装了些什么文件 dpkg -s /usr/bin/ls      #查看ls是那个包提供的 dpkg -c abc.deb #查看abc. ...

  8. 将图片文件转成BASE64格式

    html5Reader (file, item) { const reader = new FileReader() reader.onload = (e) => { this.$set(ite ...

  9. Nexus OSS私服仓库的备份与迁移

    背景 在上一篇博客 [Maven学习]Nexus OSS私服仓库的安装和配置 中,我们已经在机房搭建好了新的Nexus OSS私服仓库.下面是两个版本的Nexus OSS私服仓库的对比图. 老的Nex ...

  10. 如何在ProXmoX VE 下虚拟机安装 黑群晖 DSM 6.1.6

    ProXmoX 官方下载地址: https://www.proxmox.com/en/downloads Proxmox是一个非常优秀的开源虚拟化环境,集诸多优点于一身:开源免费,稳定可靠,架构简洁, ...