环境配置
软件 | 版本 |
Go | 1.12+ |
Kubernetes | 1.13+ |
Telepresence | latest |
KubeSphere | v3.3.0 |
Go 环境在 windows 下配置十分麻烦,建议还是在 linux 下搭建开发环境
安装 Go
# 1.下载压缩包
wget -c https://dl.google.com/go/go1.20.2.linux-amd64.tar.gz -O go1.15.5.linux-amd64.tar.gz
# 2.执行tar解压到/usr/loacl目录下,得到go文件夹
tar -C /usr/local -zxvf go1.15.5.linux-amd64.tar.gz
# 3.添加/usr/loacl/go/bin目录到 PATH变量中。添加到/etc/profile 或$HOME/.profile都可以
vim /etc/profile
# go envrionment
export GOROOT=/usr/local/go # go 的安装目录
export GOPATH=$HOME/workspace/go # go 项目的存放目录
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
export GOPROXY=https://goproxy.io,direct # go 项目依赖下载的代理地址
安装 Goland
网上教程很多,这里就不说了。
本地环境有搭建
-
下载 kubesphere 代码
-
添加配置文件(内涵访问目标 kubernetes 的参数等信息)
-
在 kubesphere 项目的根目录下创建如下 kubesphere.yaml 文件
kubernetes: kubeconfig: "/root/.kube/config" master: https://x.x.x.x:port $qps: 1e+06 burst: 1000000 authentication: authenticateRateLimiterMaxTries: 10 authenticateRateLimiterDuration: 10m0s loginHistoryRetentionPeriod: 168h maximumClockSkew: 10s multipleLogin: True kubectlImage: kubesphere/kubectl:v1.21.0 jwtSecret: "d1yCqU4aiss6va1GetpObYDWBcI94a0K" oauthOptions: clients: - name: kubesphere secret: kubesphere redirectURIs: - '*' network: ippoolType: none multicluster: clusterRole: none monitoring: endpoint: http://prometheus-operated.kubesphere-monitoring-system.svc:9090 enableGPUMonitoring: false gpu: kinds: - resourceName: nvidia.com/gpu resourceType: GPU default: True notification: endpoint: http://notification-manager-svc.kubesphere-monitoring-system.svc:19093 terminal: image: alpine:3.14 timeout: 600 gateway: watchesPath: /var/helm-charts/watches.yaml repository: kubesphere/nginx-ingress-controller tag: v1.1.0 namespace: kubesphere-controls-system
-
拷贝目标集群的config文件至 kubesphere.yaml 文件中 kubeconfig 字段指定的目录
-
-
以 debug 模式启动 apiserver
当看到 Start listening on :9090 提示时,表示启动成功,本地 ks-apiserver 监听在 9090 端口
-
针对不同场景的调试方法
-
场景一:本地开发环境 ks-console 访问本地开发环境 ks-apiserver
参考前端本地环境搭建中的场景三
-
场景二:使用集群中的 ks-console 访问本地开发环境 ks-apiserver
参考如何使用Telepresence 拦截集群内流量到本地开发环境
# 开始拦截请求 telepresence intercept ks-apiserver --port 9090 --namespace kubesphere-system # 停止拦截请求 telepresence uninstall -n kubesphere-system -d ks-apiserver
-
编写自定义接口
-
进入项目根目录,创建新的文件夹如下:
cd kubesphere mkdir -p pkg/kapis/hellokubesphere/v1alpha1 cd pkg/kapis/hellokubesphere/v1alpha1
-
在目标目录下创建 handler.go,在本实验中,只返回一个带有“hello-kubesphere”的 http 响应,正常开发中可以添加其他逻辑
package hellokubesphere import "github.com/emicklei/go-restful" type handler struct {} func newHandler() handler{ return handler{} } func (h handler) HelloKubeSphere (req *restful.Request, resp *restful.Response) { resp.WriteAsJson(HelloResponse{ Message: "hello kubesphere", }) } type HelloResponse struct { Message string `json:"message"` }
-
一旦完成了逻辑部分,就需要用一个名为 register.go 的文件设计 api 路径和 http 方法。
package hellokubesphere import ( "net/http" "github.com/emicklei/go-restful" "k8s.io/apimachinery/pkg/runtime/schema" "kubesphere.io/kubesphere/pkg/api" "kubesphere.io/kubesphere/pkg/apiserver/runtime" ) const ( GroupName = "example.kubesphere.io" ) // 因为创建了一个名为v1alpha1的文件夹,所以需要将“版本”设置为“v1alpha1” var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} func AddToContainer(container *restful.Container) error { webservice := runtime.NewWebService(GroupVersion) handler := newHandler() webservice.Route(webservice.GET("/hello-kubesphere"). Reads(""). To(handler.HelloKubeSphere). Returns(http.StatusOK, api.StatusOK, HelloResponse{})). Doc("Api for hello-kubesphere") container.Add(webservice) return nil }
-
创建 handler.go 和 register.go 这两个文件之后,还需要将 api 注册为 go-restful。回到 kubesphere 根目录,编辑 pkg/apiserver/apiserver.go,在 installKubeSphereAPIs 函数的末尾添加下面这行代码
urlruntime.Must(hellokubesphere.AddToContainer(s.container))
5 运行 ks-apiserver 并测试
# 使用 curl 尝试访问前面的接口 curl -u admin:Cloud@9000 localhost:9090/kapis/example.kubesphere.io/v1alpha1/hello-kubesphere
请求调用逻辑
在 KubeSphere 中,/apis 对应 k8s 的请求,而在 /kapis 对应子组件的请求,由 ks-apiserver 自身或者转发目标组件来提供响应,ks-apiserver 通过创建处理链 buildHandlerChain 来进行分发。
首先从 ks-apisever 的启动来看,整个程序的启动入口在 cmd/ks-apiserver/apiserver.go
func main() {
cmd := app.NewAPIServerCommand()
if err := cmd.Execute(); err != nil {
log.Fatalln(err)
}
}
再根据 NewAPIServerCommand 方法找到 cmd/ks-apiserver/app/server.go,其中最重要的是 run 方法,其中 PrepareRun 方法是一些准备工作
func run(s *options.ServerRunOptions, ctx context.Context) error {
apiserver, err := s.NewAPIServer(ctx.Done())
if err != nil {
return err
}
err = apiserver.PrepareRun(ctx.Done())
if err != nil {
return err
}
err = apiserver.Run(ctx)
if err == http.ErrServerClosed {
return nil
}
return err
}