运行在kubernetes集群中的pod对于运维人员还是管理员进行日常查看还是很不方便,如果通过控制台的方式将日志输出或者通过控制台的方式进行容器中日志的查看,针对这样一个背景调研了一下kubernetes远程访问容器的技术,这里主要涉及两个主要的问题,一个是采用什么样的远程访问方式进行访问,一个是如何保证集群外以权限最小化的方式进行访问。
kubernetes实现的进入某个容器的功能,底层本质是Docker容器通过exec进入容器的扩展
docker exec -it containerID /bin/sh
通过上面的命令,就可以进入到容器内部,其本质是新建了一个与目标容器,共享namespace的新的shell进程,所以该shell进程看到的一切就是容器内部的世界了。
那么kubernetes要实现这一点就需要利用Docker的这个功能实现跨节点的长连接。
从kubectl命令行工具到容器内部,这里经过的网络路径其实是较长的,如下:

因为exec命令行是实时交互的。即输入和输出实时发生。 所以K8s选择了使用类似Websocket这种双向实时通信的协议,来传递输入/输出内容。 Kubectl <—(双向实时协议)—> Kube-Api-Server <—(双向实时协议)—>节点kubelet kubectl使用了一个加SPDY的协议去连接kubernetes的api-server,这里的SPDY协议是Google公司开发的一个双全工通信协议,类似websocket,经过调研kube-apiserver支持这里提到的SPDY协议和websocket协议。
这种场景,虽然看着最直接,但是适用的场景反而有限,因为权限的隔离问题,一般情况下前端是不可能拿到最大的kubernetes权限让其进入任意的容器中。

在前端和K8s的中间,增加一个自研的Server,可以很好的控制权限隔离,封装K8s到业务的转换。

那么对于自研Server来说,它就是一个类似Proxy的程序。其中,[Web<---->自研Server]这一段肯定是使用Websocket协议。但是[自研Server<---->K8s]这一段,则有2种实现:1种是直接使用Websocket协议。第2种是使用SPDY协议。
因为SPDY协议已经被淘汰了,所以直接使用WebSocket实现显得高大上,并且代码也更简洁,对于Python后端,Websocker实现也更加容易,因此这里我个人更推荐使用下一种实现方式。

针对Python后端的场景,这种方案实现更容易Websocket通信,充当这里的Server,快速实现远程访问容器日志的功能,并且使用该方案的优点主要有以下几点: 1. 结构简单,代码更简洁,访问链较短; 2. 对于Python实现Server更加容易;

一般情况下我们在集群外部访问集群内部的资源都是把master节点的/root/.kube/目录下得config配置文件拷贝过来直接使用,但是该文件的权限很大,对于集群外部访问集群内部资源存在很大的安全风险,因此在上述方案的基础上还需要设计一套权限控制的方案。 这里使用证书+RBAC的方案实现该目标。
基于命名空间(ysr)的用户权限配置步骤:
openssl genrsa -out ysr.key 2048
openssl req -new -key ysr.key -out ysr.csr -subj "/CN=ysr"
如果执行报错则执行:
cd /root && openssl rand -writerand .rnd
然后重新执行上面的命令
openssl x509 -req -in ysr.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out ysr.crt -days 365
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --server=https://192.168.0.128:6443 --kubeconfig=ysr-kubeconfig
kubectl config set-credentials ysr --client-certificate=ysr.crt --client-key=ysr.key --embed-certs=true --kubeconfig=ysr-kubeconfig
kubectl config set-context ysr --cluster=kubernetes --user=ysr --kubeconfig=ysr-kubeconfig
kubectl config use-context ysr --kubeconfig=ysr-kubeconfig
ysr-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ysr-role
namespace: ysr
rules:
- apiGroups: [""]
resources: ["pods/exec", "pods/logs"]
verbs: ["get"]
应用ysr-role.yaml
kubectl apply -f ysr-role.yaml
例如我们的命名空间名称为:ysr ,首先通过kubernetes集群的CA签发一个属于ysr的证书个私钥文件,这里的证书有效期可以作为一个配置项来控制证书的有效周期。 然后创建一个名称为ysr-config的配置文件,将上述创建的证书、用户(ysr)和CA证书设置到ysr-config文件中。 接着创建一个属于ysr命名空间的角色ysr-role,该用户的权限通过该角色配置。 最后将该角色绑定到用户ysr上,此时使用ysr-config文件进行访问集群就可以将权限控制到最小,并且到达证书设置的周期后该文件就失效了。
ysr-config:
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1EVXhNakEwTlRFeE5Gb1hEVE15TURVd09UQTBOVEV4TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTk1mCk1ySGpocmZ6dHd6RVI3eGZCMEw5aTUzVFNWY282a3QvSE01OUNEWHh4RFhFUXIzaW5xRkxNWHZpK3hMMjRuekEKcmJmTHIvRE93VG5XK2s4c2UzcFgwaUdwZGpzT2FnTmt0U2crRytlQ1c1THBEa3pBWmc0eVQzMkZ3TTNtNEFkNAp0eDB6MGNtQzJOZ295T2ZXUVRnazZGMlBhSTZya2UyKzExTGdPZEV3UXJtSXUvMzcycG8wQXQ0N3Y4Wm9JeG1FCnVxa1d3cmNDVHUrczNoUnU3TEJjNlNheStEUG1wdnpldUpvMGFVSmtiSlRTZjR2WUUvU3lUYW9pU3J5cklnVXYKN2VGV0ZINzd5RmJQQXdCaDhYUllTdGdBbXNVNkpQZWZSRExjTlFrWkQwRFIwR2c4RGJOVUpzdVdteUdwVTNwbQpEZ2xkcmk5NkJweEpta3MrT3dNQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFKZWZyZE5oY2E0R1l4emV3NW9UTkgvQVpqYkkKbXRmTDYvdXR0ZWhCTG5hRXRiemNKYk1seVUvVHhiNkcvSG5Jbm9wQUUrWXpPRm9vWjFGQ0toYm1DQnk1cTU0SwpjTUc2SEVwcUVaQWFtaTZESUVDdkRtVXJRaXNjRnQ3VUdjV2NDdy92V3AxL3ZzVnpzQ3FlQ3JmTWV2TFZWeTNoClJ2TERFRmxpdDBlVWhTRFp6cDA5cVd0MWlPbkpJaGJuckxlbUJkMUxJZlU4S1JmbGdHTHBqS21HeXd1ZVBJNGwKcmc5bXF4SXBqeGMyVk9Md0xTUTFWWWF1L0hHUHlxQzhIU3VxWkk0RU54TDEvMXNPQ2dzdzV1VmRNQXl3aFpSZwpJcnp1a0lyNWZtS1ZjRUVCOWxIOTNicVFjTjZNRDZqTWNjMWZpTGRPa2pROVd2VUR1b01xUUxBbi9UND0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
server: https://192.168.0.128:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: ysr
name: ysr
current-context: ysr
kind: Config
preferences: {}
users:
- name: ysr
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNuekNDQVljQ0NRQ2JGd0w0SXg3YnVqQU5CZ2txaGtpRzl3MEJBUXNGQURBVk1STXdFUVlEVlFRREV3cHIKZFdKbGNtNWxkR1Z6TUI0WERUSXlNRGt3TkRBNE16ZzBORm9YRFRJek1Ea3dOREE0TXpnME5Gb3dEakVNTUFvRwpBMVVFQXd3RGVYTnlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTFBdlVIT3JkClZhWWxuaWZtRzV0ZEtSOFVmcEtRSDV2SzVSY3Z4RmFqanF2SzlKUTY4MmNDZFBQNUNRRjBoTEhtTXFETldZQ04KcmRMVFFQTzJSU1RqS0cydXVMWUF3SnJteHc4ZUdGZm44VVRZYVAzZnZiRGtQK0xIeDRyZG1GK1VQR0d2aXVBSQpYZmFUZ1p3alBpMHRRbDRXcHcwSnN5WWsvMTdOL1ovTC9uSTd6ZSthSHh0Z1RCSjVZL05PS0g5bmhPMDhMZEpHCi9ubHFscURxeXhnWnBFYjRJMDNNcTRlL0dIU1RVWC9kaEtEUG9yeGo2S2VUY283TUtqSVdXNEp4aXdOcDVVOEQKRzgxNnZsajFYNnV3clRlVVhCNkJmZkg4NE5Kc0FFeEZMSHU3MldFb05HOCtmUjBzSWtxRkhxYXNzSGxjVU5GOQovYVc3eG5RU3JNQzJ5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ0FvY3NHaWJCWlQ2MTVCM3dDCkhaNGYyOW5rS1N6d2U1TVhXeW1CaloydmVnZ28wNElmZDVicHEwRjBvYzNISFRQRXYvUG5RSm9BNElZSStpVEkKVjBjSkMrcWV3bnZJU0ZUZmJsc0R0TG9NVXlNK2tTaVRNTzlJR3ZZME5tVXovNnFRbXNKOTd2WjN0WW5sbVFEVQp6REdrR3hURS8wQzBGRFlTTXVNcEwwZHZZaUx2Wkh2aFd4MWltdmtMczM1bjBuSlRVQmk5K1JKQTRnalhEbmFFCjlYdWJnalZxeUNFWlhqWmcvY2ZMRjlPUzgvM1BhQ2tuQlZNcm5IWkJLWGZ6UmZOQTNNQ3J3eWlGaG5FVW5LalkKMUhkdEhJQmZHeERyYWVZS0huYzFtbmEwS3oyYThsK2UrOFAwTXZDcTkwZFNPMTArTlJvdXp4cDR6YUE5ODd4OAp5VnlaCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBMUF2VUhPcmRWYVlsbmlmbUc1dGRLUjhVZnBLUUg1dks1UmN2eEZhampxdks5SlE2CjgyY0NkUFA1Q1FGMGhMSG1NcUROV1lDTnJkTFRRUE8yUlNUaktHMnV1TFlBd0pybXh3OGVHRmZuOFVUWWFQM2YKdmJEa1ArTEh4NHJkbUYrVVBHR3ZpdUFJWGZhVGdad2pQaTB0UWw0V3B3MEpzeVlrLzE3Ti9aL0wvbkk3emUrYQpIeHRnVEJKNVkvTk9LSDluaE8wOExkSkcvbmxxbHFEcXl4Z1pwRWI0STAzTXE0ZS9HSFNUVVgvZGhLRFBvcnhqCjZLZVRjbzdNS2pJV1c0Snhpd05wNVU4REc4MTZ2bGoxWDZ1d3JUZVVYQjZCZmZIODROSnNBRXhGTEh1NzJXRW8KTkc4K2ZSMHNJa3FGSHFhc3NIbGNVTkY5L2FXN3huUVNyTUMyeXdJREFRQUJBb0lCQURjM3BWS3FibHloV1dabgo2V29DK1MxK0pHNFphR0p5eFZFR3lxK01DQ2RjNFFyemxxNVBncnBGMWZIY2FTVXMxazhVeEtTcjd6ajJqNEI0CmRseG5FS2cwZDYwdDUrQS85aHliK1RCSm8rS1dGT3l5UDVNNy94UUwwQTVNUVF3dXg0RTV4dWFaRkZTem94RzcKUVFvdDVYMUUxdzFGUGVOaTZYdCtpcEdqRFJJQzMzbXhGOEJYSW4ySm51dER2eVc2cW9QeFYwaW0zTzY0MFovYQpGMnFvNGh6eGJXY0ZIR0Y5NUdJa1hWZTAzRDl1S1dLcUJ4K2pXT0M5bytORStTOEc3aUVtVzdnMyt4YkkvODhuCnNHUWEyNC8vK1RYTGc5aEs2S3h3ZWg0UFRESXlOUjZwd0pIem4rNko5UUhQT25sOENWeG45N2toYTY1Q3ZHNWwKdWFSYTU1RUNnWUVBL2RremRXWTNSMHg3S1o3bERDbTlkMGxYendpVDBWOHhkVFRFTmQrZmhzMmEyd2FYZGYrMQphRmdTN0lpaVQ0eFJQNjNxdjFmOGw3UG9zcVRMVmF0UVNlamJXVFd6MXlwUXFESDFzYTNpYTJ6V040TExxYVhqCmtiQ3ExVm5zeVVkc24xSUlyd0wwc25JQk9YNkdXT1IwcjRvZzgyaERQY0J5Z1V2ZjhOQkdwQWNDZ1lFQTFkZnMKMzZzRVpYM0dPZ0Z3SlR0YzNGempIR21Wbm4xeGlQS3VteHVIUXpmU3NLYTF2MTNCSm10SmNzTHp3WkZQaFNTOQpWZEVwMGhKZjA5aEFielIvMXl0STErcERUd0RSSGVpMWVYV3MxWnF3MlA5TFVYaTdOZ0Y4VGEzU2NkSnNHR2ZOCklTVHZidkNXL1VzclY3QTJVNHZvemJJbGVZUWQyM0szU3dXS1RoMENnWUFENUluS2VoZk02eHBVYUJCaElGNjgKYm81L0tVV0RCMit0dVhKczFSSVFNaVQyeU9JWHVDVWpCWDY4eTllWldyQ0FSbjE4RTdCVzd6WlpUdmVqUjY1QwpnK1NoT0phYWJSYXhqWnFUNy9PeDdBaFk3NU9KOVhaSTdLbWgvZkFJb2lURFNMSERaVXMxVlZRNWVudzY3cjN2ClZ6SHNLYVFtVlVZc1AycWV1Y0xyandLQmdIdit2VUlnVnVkR205ZHNtQXR1dFhTdGc1OG85ZkcxaVV6QWMxQkwKRVE1LzR2STlhR3R6UUprM1lwcGh3cGU5MjE4M28zV01WL1NRWlBKZ2xWUW1HKzYzRVlEcFBHZ2w4QnVvb1BteApxeXNjakdqMjkwUmhmaVJkamljNG9Dc1J1VTRaZWs4NnJIOG1rRmFFN0xmbTNFbHJlZTB6M0JqdTY2VWdpbm04CjE2cGRBb0dBY3VDZ05Yd05ENnNTZmt4dktTMW9hLzVOck5hUnROS09OelVHZEFQdTVUTUMzemlmWjhGTlIwZTcKdkxRWGZIZ1RSZTlWZ2FLWWF5Wkhram05ODN2RGJabXVRbVdCSGMzWVo1ZmpKNlVuZHdOWURPc0xlYTg2b25KTQpjQ1phSTZGZ2FtZGlVNG52UEJwVkpMQ0szSWtOUk42R2REc05oV1ZIQW0wNGMzaDFqSkU9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
通过页面访问集群中nginx容器的shell窗口(这里截图不符,只是为了方便使用的是default命名空间,不影响理解)

通过页面访问集群中nginx容器的日志

ysr-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ysr-role
namespace: ysr
rules:
- apiGroups: [""]
resources: ["pods/exec", "pods/logs"]
verbs: ["create"]
通过页面访问容器nginx的shell窗口和logs

可以看出,只要配置该用户的不通权限即可控制该用户的行为和操作范围。
源码路径(后端):https://github.com/yuanleyou/kubeshell-backend
源码路径(前端):https://github.com/yuanleyou/kubeshell-frontend
参考:https://bbs.huaweicloud.com/blogs/281515