Title here
Summary here
本文详细介绍 API Server 的调试方法,包括请求处理、认证授权、准入控制和存储操作等关键链路的调试技巧。
API Server 使用分层的 Handler 链处理请求:
# Handler 链入口
(dlv) b staging/src/k8s.io/apiserver/pkg/server/handler.go:ServeHTTP
# 请求信息解析
(dlv) b staging/src/k8s.io/apiserver/pkg/endpoints/filters/requestinfo.go:WithRequestInfo
# Director 路由
(dlv) b staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go:installAPIResources# 1. 启动调试
dlv exec ./_output/bin/kube-apiserver -- \
--etcd-servers=http://127.0.0.1:2379 \
--v=4
# 2. 设置断点
(dlv) b staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go:CreateResource
# 3. 继续执行
(dlv) c
# 4. 在另一个终端创建 Pod
kubectl run nginx --image=nginx
# 5. 断点触发后检查
(dlv) args
(dlv) p scope.Name
(dlv) p r.URL.Path# 查看注册的 API 路由
(dlv) b staging/src/k8s.io/apiserver/pkg/endpoints/installer.go:registerResourceHandlers
# 查看路由表
(dlv) p a.Actions
# 检查特定资源的路由
(dlv) cond 1 resource == "pods"# 认证主入口
(dlv) b staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go:withAuthentication
# 联合认证器
(dlv) b staging/src/k8s.io/apiserver/pkg/authentication/request/union/union.go:AuthenticateRequest
# X509 证书认证
(dlv) b staging/src/k8s.io/apiserver/pkg/authentication/request/x509/x509.go:AuthenticateRequest
# Bearer Token 认证
(dlv) b staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken.go:AuthenticateRequest
# ServiceAccount Token 认证
(dlv) b staging/src/k8s.io/apiserver/pkg/authentication/serviceaccount/lookup.go:AuthenticateToken# 1. 设置断点
(dlv) b staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken.go:AuthenticateRequest
# 2. 继续执行
(dlv) c
# 3. 使用 Token 发起请求
TOKEN=$(kubectl create token default)
curl -k -H "Authorization: Bearer $TOKEN" https://localhost:6443/api/v1/namespaces
# 4. 检查 Token 内容
(dlv) p token[:50] # 打印前50个字符
# 5. 检查认证结果
(dlv) n # 单步执行
(dlv) p resp
(dlv) p resp.User# 获取认证后的用户信息
(dlv) b staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go:56
# 断点触发后
(dlv) p req.Context().Value(request.userKey)
(dlv) p user.GetName()
(dlv) p user.GetGroups()# 授权主入口
(dlv) b staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go:withAuthorization
# 联合授权器
(dlv) b staging/src/k8s.io/apiserver/pkg/authorization/union/union.go:Authorize
# RBAC 授权
(dlv) b plugin/pkg/auth/authorizer/rbac/rbac.go:Authorize
(dlv) b staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/rbac.go:Authorize
# 规则匹配
(dlv) b staging/src/k8s.io/apiserver/pkg/authorization/authorizer/interfaces.go# 1. 设置 RBAC 授权断点
(dlv) b plugin/pkg/auth/authorizer/rbac/rbac.go:Authorize
# 2. 继续执行
(dlv) c
# 3. 发起请求
kubectl get pods -n kube-system
# 4. 检查授权属性
(dlv) p a.GetUser().GetName()
(dlv) p a.GetVerb()
(dlv) p a.GetResource()
(dlv) p a.GetNamespace()
# 5. 检查规则匹配
(dlv) b staging/src/k8s.io/apiserver/pkg/authorization/authorizer/rbac.go:visitRules
(dlv) c
(dlv) p rules# 授权缓存
(dlv) b staging/src/k8s.io/apiserver/pkg/authorization/union/union.go:Authorize
# 检查缓存命中
(dlv) p r.cachedAuthorizer# 准入控制主入口
(dlv) b staging/src/k8s.io/apiserver/pkg/admission/handler.go:Admit
(dlv) b staging/src/k8s.io/apiserver/pkg/admission/handler.go:Validate
# Mutating 准入
(dlv) b plugin/pkg/admission/namespace/lifecycle/admission.go:Admit
(dlv) b plugin/pkg/admission/serviceaccount/admission.go:Admit
# Validating 准入
(dlv) b plugin/pkg/admission/resourcequota/admission.go:Validate
(dlv) b plugin/pkg/admission/limitranger/admission.go:Validate
# Webhook 准入
(dlv) b staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/webhook.go:Dispatch# 1. 创建 ResourceQuota
kubectl create quota test-quota --hard=pods=2 -n default
# 2. 设置断点
(dlv) b plugin/pkg/admission/resourcequota/admission.go:Validate
# 3. 继续执行
(dlv) c
# 4. 创建 Pod 触发验证
kubectl run nginx1 --image=nginx
kubectl run nginx2 --image=nginx
kubectl run nginx3 --image=nginx # 这个应该被拒绝
# 5. 检查配额检查
(dlv) p a.GetResource()
(dlv) p quota# Webhook 调用
(dlv) b staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/generic/webhook.go:callHook
# 断点触发后
(dlv) p hook.GetName()
(dlv) p hook.GetURL()
# 查看 Webhook 响应
(dlv) n
(dlv) p result# REST Storage 接口
(dlv) b staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go:Create
(dlv) b staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go:Update
(dlv) b staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go:Delete
(dlv) b staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go:Get
# etcd3 存储
(dlv) b staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go:Create
(dlv) b staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go:Update
(dlv) b staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go:Delete
(dlv) b staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go:Get# 1. 设置断点
(dlv) b staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go:Create
# 2. 继续执行
(dlv) c
# 3. 创建 Pod
kubectl run nginx --image=nginx
# 4. 检查存储键
(dlv) p key
# 输出类似: "/registry/pods/default/nginx"
# 5. 检查存储值
(dlv) p out# Watch 建立
(dlv) b staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher.go:Watch
# 事件处理
(dlv) b staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher.go:processEvent
# Watch 缓存
(dlv) b staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher.go:Watch# 乐观锁更新
(dlv) b staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go:GuaranteedUpdate
# 断点触发后
(dlv) p key
(dlv) p preconditions
(dlv) p origState.Meta.ResourceVersion# 启动时设置高日志级别
./_output/bin/kube-apiserver \
--v=6 \
--vmodule=handlers=8,storage=7 \
...
# 动态调整日志级别 (需要启用 profiling)
curl -X PUT localhost:6443/debug/pprof/profile?seconds=30# 审计策略配置
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
verbs: ["create", "update", "patch", "delete"]
resources:
- group: ""
resources: ["pods"]# 启用审计
./_output/bin/kube-apiserver \
--audit-policy-file=audit-policy.yaml \
--audit-log-path=/var/log/kubernetes/audit.log \
...# 使用 kubectl 查看详细请求
kubectl get pods -v=9
# 使用 curl 发送请求并查看响应头
curl -k -v https://localhost:6443/api/v1/pods
# 查看 X-Kubernetes-Pf-* 头部
# 这些头部包含请求处理的性能信息# CPU 分析
go tool pprof http://localhost:6443/debug/pprof/profile?seconds=30
# 内存分析
go tool pprof http://localhost:6443/debug/pprof/heap
# Goroutine 分析
go tool pprof http://localhost:6443/debug/pprof/goroutine
# 在 pprof 中查看
(pprof) top 10
(pprof) list functionName
(pprof) web# 检查认证配置
(dlv) b staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go:withAuthentication
# 检查 Token 验证
(dlv) b staging/src/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken.go:AuthenticateRequest
# 查看认证结果
(dlv) p ok
(dlv) p err# 检查授权决策
(dlv) b plugin/pkg/auth/authorizer/rbac/rbac.go:Authorize
# 查看授权属性
(dlv) p a.GetVerb()
(dlv) p a.GetResource()
(dlv) p a.GetNamespace()
# 查看决策结果
(dlv) p decision
(dlv) p reason# 检查版本冲突
(dlv) b staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go:GuaranteedUpdate
# 检查 ResourceVersion
(dlv) p preconditions.ResourceVersion
(dlv) p origState.Meta.ResourceVersion# 检查 etcd 连接
(dlv) b staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go:newStore
# 查看连接配置
(dlv) p cfg
# 检查连接错误
(dlv) b go.etcd.io/etcd/client/v3.(*Client).Dial本文详细介绍了 API Server 各关键链路的调试方法:
掌握这些调试技巧可以帮助深入理解 API Server 的工作原理,快速定位和解决问题。