如何通过抓包来查看Kubernetes|如何通过抓包来查看Kubernetes API流量
当我们通过kubectl来查看、修改Kubernetes资源时,有没有想过后面的接口到底是怎样的?有没有办法探查这些交互数据呢?
Kuberenetes客户端和服务端交互的接口,是基于http协议的。所以只需要能够捕捉并解析https流量,我们就能看到kubernetes的API流量。
但是由于kubenetes使用了客户端私钥来实现对客户端的认证,所以抓包配置要复杂一点。具体是如下的结构:
文章图片
如果想了解更多Kubernetes证书的知识,可以看下这篇Kubernetes证书解析的文章
从kubeconfig中提取出客户端证书和私钥
kubeconfig中包含了客户端的证书和私钥,我们首先要把它们提取出来:
# 提取出客户端证书
grep client-certificate-data ~/.kube/config | \
awk '{ print $2 }' | \
base64 --decode > client-cert.pem
# 提取出客户端私钥
grep client-key-data ~/.kube/config | \
awk '{ print $2 }' | \
base64 --decode > client-key.pem
# 提取出服务端CA证书
grep certificate-authority-data ~/.kube/config | \
awk '{ print $2 }' | \
base64 --decode > cluster-ca-cert.pem
参考自Reddit
配置Charles代理软件 从第一张图可以看出,代理软件的作用有两个:一是接收https流量并转发,二是转发到kubernetes apiserver的时候,使用指定的客户端私钥。
首先配置Charles,让他拦截所有的https流量:
文章图片
然后配置客户端私钥,即对于发送到apiserver的请求,统一使用指定的客户端私钥进行认证:
文章图片
配置kubectl 需要抓包kubectl的流量,需要两个条件:1. kubectl使用Charles作为代理,2. kubectl需要信任Charles的证书。
# Charles的代理端口是8888,设置https_proxy环境变量,让kubectl使用Charles代理
$ export https_proxy=http://127.0.0.1:8888/
# insecure-skip-tls-verify表示不校验服务端证书
$ kubectl --insecure-skip-tls-verify get pod
NAMEREADYSTATUSRESTARTSAGE
sc-b-7f5dfb694b-xtfrz2/2Running02d20h
我们就可以看到
get pod
的网络请求了:文章图片
可以看到,get pod的endpoint是
GET /api/v1/namespaces//pods
。让我们再尝试下创建pod的请求:
$ cat <pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-robberphex
spec:
containers:
- name: nginx
image: nginx:1.14.2
EOF
$ kubectl --insecure-skip-tls-verify apply -f pod.yaml
pod/nginx-robberphex created
也同样可以抓到包:
【如何通过抓包来查看Kubernetes|如何通过抓包来查看Kubernetes API流量】
文章图片
创建pod的endpoint是
POST /api/v1/namespaces//pods
配置kubenetes client 我们先从写一个用kubernetes go client来获取pod的例子(注意,代码中已经信任所有的证书,所以可以抓到包):
package main/*
require (
k8s.io/api v0.18.19
k8s.io/apimachinery v0.18.19
k8s.io/client-go v0.18.19
)
*/
import (
"context"
"flag"
"fmt"
"path/filepath"apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
)func main() {
ctx := context.Background()
var kubeconfig *string
if home := homedir.HomeDir();
home != "" {
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
} else {
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
}
flag.Parse()config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
panic(err)
}
// 让clientset信任所有证书
config.TLSClientConfig.CAData = https://www.it610.com/article/nil
config.TLSClientConfig.Insecure = true
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err)
}
podClient := clientset.CoreV1().Pods(apiv1.NamespaceDefault)
podList, err := podClient.List(ctx, metav1.ListOptions{})
if err != nil {
panic(err)
}for _, pod := range podList.Items {
fmt.Printf("podName: %s\n", pod.Name)
}fmt.Println("done!")
}
然后编译执行:
$ go build -o kube-client
$ export https_proxy=http://127.0.0.1:8888/
$ ./kube-client
podName: nginx-robberphex
podName: sc-b-7f5dfb694b-xtfrz
done!
这时也可以抓到同样的结果:
文章图片
基于此,我们就可以分析一个Kubernetes到底干了什么,也是我们分析Kubernetes?实现的入口。
推荐阅读
- 考研英语阅读终极解决方案——阅读理解如何巧拿高分
- 如何寻找情感问答App的分析切入点
- mybatisplus如何在xml的连表查询中使用queryWrapper
- MybatisPlus使用queryWrapper如何实现复杂查询
- gitlab|gitlab 通过备份还原 admin/runner 500 Internal Server Error
- 如何在Mac中的文件选择框中打开系统隐藏文件夹
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- java中如何实现重建二叉树
- Linux下面如何查看tomcat已经使用多少线程
- thinkphp|thinkphp 3.2 如何调用第三方类库