(3)r.request方法首先检查是否设置 httpclient,如果没有,则使用 net/http默认的DefaultClient、r.URL.String方法根据配置的请求参数生成请求的 RESTfulURL,示例中生成的请求 URL 应该为 https://xxx/api/v1/namespaces/default/pods?limit=100。之后用 net/http标准库构建 req请求并发送该请求,最终fn函数变量对 APIServer的返回值进行解析(见代码清单2-14)。
func(r*Request)request(ctxcontext.Context,fnfunc(*http.Request,*http.Response))error{
//...
client:=r.c.Clientifclient==nil{
client=http.DefaultClient
}
//...for{
url:=r.URL().String()
req,err:=http.NewRequest(r.verb,url,r.body)
//...
resp,err:=client.Do(req)
//...
done:=func()bool{
//...
}()
//...
}
}
fn(req,resp)returntrue
总结:KubernetesAPIServer 有很多操作资源的接口,而RESTClient就是对访问这些 API 的封装。
1. ClientSet
虽然 RESTClient可以访问 Kubernetes 的任意资源对象,但在使用时需要配置的参数过于烦琐,为了更为优雅地处理,需要进一步封装。ClientSet继承自 RESTClient,使用预生成的 API对象与 APIServer进行交互,方便开发者二次开发。
ClientSet 是一组资源客户端的集合,比如操作Pods、Services、Secrets资源的CoreV1Client,操作 Deployments、ReplicaSets、DaemonSets资源的ExtensionsV1beta1Client等,如图2-5所示,直接通过这些客户端提供的操作方法即可对Kubernetes内置的原生资源进行 Create、Update、Get、List、Delete等多种操作。
图 2—5CientSet 交互图
ClientSet的使用方式在前面已有讲解,这里不再赘述。下面分析核心代码clientset.
CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})的执行流程。
ClientSet包含众多资源客户端,CoreV1方法负责返回 CoreV1Client(见代码清单2-15)。
typeClientsetstruct{
*discovery.DiscoveryClient
//...
coreV1 *corev1.CoreV1Client
//...
}
//...
//CoreV1retrievestheCoreV1Client
func(c*Clientset)CoreV1()corev1.CoreV1Interface{returnc.coreV1
}
Pods方法的参数用于设定 Namespace, 内部调用 newPods函数, 该函数返回实现PodInterface的对象(见代码清单2-16)。
func(c*CoreV1Client)Pods(namespacestring)PodInterface{returnnewPods(c,namespace)
}
可以看到 PodInterface 包含了操作 Pods 资源的全部方法,newPods 函数构造的 Pods对象内部包含 RESTClient,在 Pods对象的List 方法中,我们看到了熟悉的 RESTClient操作资源的调用流程(见代码清单2-17)。
typePodInterfaceinterface{
Create(ctxcontext.Context,pod*v1.Pod,optsmetav1.CreateOptions)(*v1.Pod,error)
Update(ctxcontext.Context,pod*v1.Pod,optsmetav1.UpdateOptions)(*v1.Pod,error)
UpdateStatus(ctxcontext.Context,pod*v1.Pod,optsmetav1.
UpdateOptions)(*v1.Pod,error)
Delete(ctxcontext.Context,namestring,optsmetav1.DeleteOptions)
error
DeleteCollection(ctxcontext.Context,optsmetav1.DeleteOptions,
listOptsmetav1.ListOptions)error
Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Pod, error)List(ctxcontext.Context,optsmetav1.ListOptions)(*v1.PodList,error)
//...
}
funcnewPods(c*CoreV1Client,namespacestring)*pods{return&pods{
client:c.RESTClient(),ns:namespace,
}
}
//...
func(c*pods)List(ctxcontext.Context,optsmetav1.ListOptions)(result
*v1.PodList,errerror){
//...
result=&v1.PodList{}err=c.client.Get().
Namespace(c.ns).
Resource("pods").
VersionedParams(&opts,scheme.ParameterCodec).Timeout(timeout).
Do(ctx).
Into(result)
return
}