大行至简 上行若水
目录
Rancher API的调用
与rancher的交互
rancher对请求的处理
rancher-k8s交互图
rancher-k8s交互核心类图
rancher-k8s交互架构图
1,构建rancher client
import rancher "pro/pkg/client-rancher/management/v3"
//token为ranchertoken
func newRancherManagementClient(token string) (*rancher.Client, error) {
opts := clientbase.ClientOpts{
URL: "服务对应rancher api地址,如https://192.168.10.19/v3",
TokenKey: token,
Insecure: "是否跳过验证TLS链接证书验证,值为True或False",
// TODO-xmh add Timeout
}
cli, err := rancher.NewClient(&opts)
if err != nil {
return nil, err
}
return cli, nil
}
2,资源操作,如创建密文
func CreateSecretV3(secret *client.NamespacedSecret, token string) error {
//传两个参数,第一个为要创建在哪个project下的projectID,第二个是连接rancher的token
cli, err := client.newRancherManagementClient(secret.ProjectId, token)
if err != nil {
return err
}
_, err = cli.NamespacedSecret.Create(secret)
return err
}
看看Create方法的实现
type NamespacedSecretOperations interface {
List(opts *types.ListOpts) (*NamespacedSecretCollection, error)
Create(opts *NamespacedSecret) (*NamespacedSecret, error)
Update(existing *NamespacedSecret, updates interface{}) (*NamespacedSecret, error)
Replace(existing *NamespacedSecret) (*NamespacedSecret, error)
ByID(id string) (*NamespacedSecret, error)
Delete(container *NamespacedSecret) error
}
func (c *NamespacedSecretClient) Create(container *NamespacedSecret) (*NamespacedSecret, error) {
resp := &NamespacedSecret{}
err := c.apiClient.Ops.DoCreate(NamespacedSecretType, container, resp)
return resp, err
}
DoCreate方法中层层调用,里面创建了request,在Client.Do(req)内部使用了http的send方法发送了request。执行c.apiClient.Ops.DoCreate(...)后rancher api server将收到这个http请求,我们知道,rancher是对k8s的封装,他内部必定使用了k8s的东西来进行了对资源的操作,那么rancher是怎么将资源交给k8s的?接下来我们进入rancher的源码中
rancher的设计基于类似控制器-xxxclient-xxxInterface这种,接口设计比较灵活。每个模块的sync方法就是处理请求的地方。
源码路径\github.com\rancher\rancher\pkg\controllers下就是对用户请求的处理,分为management和user两种,密文资源在user下面。
我们看看密文的创建方法,Create方法的定义在SecretInterface接口,其创建调用如下:
n *NamespaceController
n.clusterSecretsClient.Create(namespacedSecret)
func (s *secretClient) Create(o *v1.Secret) (*v1.Secret, error) {
obj, err := s.objectClient.Create(o)
return obj.(*v1.Secret), err
}
func (p *ObjectClient) Create(o runtime.Object) (runtime.Object, error) {
...
err := p.restClient.Post().
Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version).
NamespaceIfScoped(ns, p.resource.Namespaced).
Resource(p.resource.Name).
Body(o).
Do().
Into(result)
return result, err
}
其中restClient是ObjectClient结构体中一个属性,类型为rest.Interface接口,这个接口就是k8s对外提供的REST API(client-go),执行.Do()方法后请求将发往k8s 的api server,api server实际是由go的net.http包启动的http server(启动过程源码位于github.com\rancher\rancher\vendor\k8s.io\kubernetes\cmd\kube-apiserver\app\server.go)。
其中api server处理请求的逻辑也很复杂,此处不赘述,最后与etcd client以接口调用交互,etcd client与db的交互是基于grpc请求的方式进行(与etcd的交互部分详细内容很快会补上)。
以下是综合rancher与k8s及其源码分析所作的架构图