某天,node
某魚說要吃瞄,git
因而......github
李國寶:邊緣計算k8s集羣SuperEdge初體驗
zhuanlan.zhihu.com
圖標docker
照着上一篇文章來講,我這邊邊緣計算集羣有一堆節點。shell
每一個節點都在不一樣的網絡環境下。api
他們的共同點都是能夠訪問內網,安全
部分是某雲學生主機,bash
部分是跑在家庭網絡環境下的虛擬機,服務器
甚至假設中還有一些是樹莓派之類的機器。網絡
因此他們另外一個共同點是,基本都沒有公網IP。
這樣一來,我要實現遠程登陸到某些節點搞事的時候,
只有內網穿透這一條路子了。
使用frp進行內網穿透 - 少數派
sspai.com
圖標
https://github.com/fatedier/frp
github.com
內網穿透倒沒什麼,在公司使用這貨長期跑了兩年垮大洋穿透也很穩定。
只是...
只是...
只是...
要一臺臺機器配置一次,要維護一個穩定的公網服務器做爲橋接。
就是...麻煩了點。
而後想了下。
當前的kube superedge邊緣計算集羣自己就實現了4層和7層的內網穿透,
理論上直接使用它的能力也能夠作到遠程登陸的。
因而開始研究了一下怎麼實如今只有kubectl環境的機器上,
直接登陸k8s容器集羣的node節點。
搜了一波以後首先發現的是這個項目。
A kubectl plugin to SSH into Kubernetes nodes using a SSH jump host Pod
github.com
看描述和需求來講,徹底符合個人要求。
$ kubectl krew install ssh-jump
照着教程配置好插件,裝好環境以後實踐了一下。
....
一切都好,就是連不上去。
蛋疼了...
接着又找了一波,發現了一個Redhat老哥的博客。
A consistent, provider-agnostic way to SSH into any Kubernetes node
完美。
我想要的就是這個。
看了下插件代碼。luksa/kubectl-plugins看了下插件代碼。
https://github.com/luksa/kubectl-plugins/blob/master/kubectl-ssh
github.com
#!/usr/bin/env bash set -e ssh_node() { node=$1 if [ "$node" = "" ]; then node=$(kubectl get node -o name | sed 's/node\///' | tr '\n' ' ') node=${node::-1} if [[ "$node" =~ " " ]]; then echo "Node name must be specified. Choose one of: [$node]" exit 1 else echo "Single-node cluster detected. Defaulting to node $node" fi fi pod=$( kubectl create -o name -f - <<EOF apiVersion: v1 kind: Pod metadata: generateName: ssh-node- labels: plugin: ssh-node spec: nodeName: $node containers: - name: ssh-node image: busybox imagePullPolicy: IfNotPresent command: ["chroot", "/host"] tty: true stdin: true stdinOnce: true securityContext: privileged: true volumeMounts: - name: host mountPath: /host volumes: - name: host hostPath: path: / hostNetwork: true hostIPC: true hostPID: true restartPolicy: Never EOF ) deletePod() { kubectl delete $pod --wait=false } trap deletePod EXIT echo "Created $pod" echo "Waiting for container to start..." kubectl wait --for=condition=Ready $pod >/dev/null kubectl attach -it $pod -c ssh-node } ssh_pod() { # TODO: improve this if [ "$1" == "" ]; then echo "Pod name must be specified." exit 1 fi kubectl exec -it "$@" bash || ( echo "Running bash in pod failed; trying with sh" kubectl exec -it "$@" sh ) } print_usage() { echo "Provider-agnostic way of opening a remote shell to a Kubernetes node." echo echo "Enables you to access a node even when it doesn't run an SSH server or" echo "when you don't have the required credentials. Also, the way you log in" echo "is always the same, regardless of what provides the Kubernetes cluster" echo "(e.g. Minikube, Kind, Docker Desktop, GKE, AKS, EKS, ...)" echo echo "You must have cluster-admin rights to use this plugin." echo echo "The primary focus of this plugin is to provide access to nodes, but it" echo "also provides a quick way of running a shell inside a pod." echo echo "Examples: " echo " # Open a shell to node of a single-node cluster (e.g. Docker Desktop)" echo " kubectl ssh node" echo echo " # Open a shell to node of a multi-node cluster (e.g. GKE)" echo " kubectl ssh node my-worker-node-1" echo echo " # Open a shell to a pod" echo " kubectl ssh pod my-pod" echo echo "Usage:" echo " kubectl ssh node [nodeName]" echo " kubectl ssh pod [podName] [-n namespace] [-c container]" exit 0 } if [ "$1" == "--help" ]; then print_usage fi if [[ "$1" == node/* ]]; then ssh_node ${1:5} elif [ "$1" == "node" ]; then ssh_node $2 elif [[ "$1" == pod/* ]]; then ssh_pod "$@" elif [ "$1" == "pod" ]; then shift ssh_pod "$@" else print_usage fi
認真看了一下這個腳本。
直呼人才啊。
果真是玩Linux的老哥啊。
牛逼啊。
太牛逼了。
太有趣了。
額。
講人話。
這個腳本使用busybox鏡像啓動了容器實例,
經過chroot到 /host + 把宿主機全部文件掛在到容器實例的方式,
實現了在容器實例直接對宿主機系統一對一「Copy」(可能表達不太準確),
進而實現直接在這個容器實例中操做宿主機的全部資源。
是的,全部資源。
是的,全部資源。
是的,全部資源。
着這裏直接能看到其餘程序的進程,
免密碼直接操做其餘用戶的數據。
所謂,
這就是容器逃逸。
而後....
咱們的目的確實也達到了。
經過這種方式確實能夠直接實現登陸任意一臺k8s node節點,
不再須要密碼和受權。
總結。
很好玩。
不明鏡像確實有風險。
這個世界一直都不太安全。
參考資料:
docker 容器逃逸漏洞(CVE-2020-15257)風險通告
容器逃逸技術概覽 - DockOne.io
rambo1412:容器逃逸技術概覽