前言
client-go是一个调用kubernetes集群资源对象API的客户端,即通过client-go实现对kubernetes集群中资源对象增删改查等操作。大部分对kubernetes进行前置API封装的二次开发都通过client-go这个第三方包来实现。
RESTClient
最基础的,封装了指定资源URL访问Kubernetes API的姿势,相当于的底层基础结构,可以直接通过 RESTClient 提供的RESTful方法如Get(),Put(),Post(),Delete()和k8s进行交互。
获取k8s version
type K8sVersionResponse struct {
GitVersion string
}
func (p *K8sProxy) getVersion(ctx context.Context) (string, error) {
getVersionUrl := p.restConfig.Host + "/version"
bytes, err := p.get(ctx, getVersionUrl)
if err != nil {
return "", err
}
k8sVersionResponse := K8sVersionResponse{}
if err = jsoniter.Unmarshal(bytes, &k8sVersionResponse); err != nil {
return "", errors.Wrap(err, "parse k8s version response json error")
}
return k8sVersionResponse.GitVersion, err
}
func (p *K8sProxy) get(ctx context.Context, url string) ([]byte, error) {
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, errors.Wrap(err, "create request error")
}
req = req.WithContext(ctx)
resp, err := p.RestClient.Client.Do(req)
if err != nil {
return nil, errors.Wrap(err, "get request error")
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrap(err, "copy response body error")
}
return data, nil
}
- 响应值是json,最好是定义一个结构体对应,方便后期维护。而不是直接解析json字符串。
- json对应的结构体不用定义json字符串里的全部字段,用到哪些就定义哪些。
Clientset
通过sdk里封装好的方法,对k8s里的一类资源进行操作。
ClientSet在RestClient的基础上封装了对Resouorce和Version的管理方法。
一个Resource可以理解为一个客户端,而ClientSet是多个客户端的集合
其操作资源对象时需要指定Group、指定Version,然后根据Resource获取,但是clientset不支持自定义crd(CustomResourceDefinition)。
更新configmap
configMap := v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "xxx",
},
Data: map[string]string{
"xxx.yaml": string(yaml),
},
}
_, err = clientset.CoreV1().ConfigMaps(xxx).Update(ctx, configMap, metav1.UpdateOptions{})
DynamicClient
DynamicClient是一种动态客户端它可以对任何资源进行restful操作包括crd自定义资源,不同于 clientset,dynamic client 返回的对象是一个 map[string]interface{}
利用DynamicClient更新自定义资源
resource := schema.GroupVersionResource{Group: "xxx", Version: "v1", Resource: "xxx"}
// 先查询,有的情况下就更新,没有就创建
xxx, err := k8sProxy.DynamicClient.Resource(resource).Get(ctx, xxx, metav1.GetOptions{})
if err == nil {
if err := unstructured.SetNestedField(xxx.Object, pop.Name, "spec", "pop"); err != nil {
return err
}
_, err = k8sProxy.DynamicClient.Resource(resource).Update(ctx, xxx, metav1.UpdateOptions{})
} else if k8sErrors.IsNotFound(err) {
xxx := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "xxx/v1",
"kind": "xxx",
"metadata": map[string]interface{}{
"name": xxx,
},
"spec": map[string]interface{}{
"pop": pop.Name,
},
},
}
_, err = k8sProxy.DynamicClient.Resource(resource).Create(ctx, xxx, metav1.CreateOptions{})
}
return err
-
这里的更新必须先把以前的资源查询出来,在在该基础上进行字段更新。不能直接使用下面创建时定义的那个xxx对象,会报错:resourceVersion有问题
-
kubectl api-resources
:查看resource
DiscoveryClient
DiscoveryClient是发现客户端,主要用于发现api server支持的资源组 资源版本 资源信息,k8s api server 支持很多资源组 资源版本,资源信息,此时可以通过DiscoveryClient来查看
kubectl的api-version和api-resource也是通过DiscoveryClient来实现的,还可以将信息缓存在本地cache,以减轻api的访问压力,默认在./kube/cache和./kube/http-cache下。