对单个Kubernetes API使用client-go来针对Kubernetes API直接在多个YAML文件中使用多种类型

我正在使用https://github.com/kubernetes/client-go,并且一切正常。

我有一个官方Kubernetes资讯主页的清单(YAML):https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta4/aio/deploy/recommended.yaml

我想使用client-go模仿Go代码中的kubectl apply这个清单。

我知道我需要对YAML字节进行一些(非)编组,以封装https://github.com/kubernetes/api

中定义的正确API类型。

我已经成功Create将单个API类型kind: List*添加到集群中,但是我如何对包含不同类型列表的清单执行此操作?是否有资源csplit支持这些不同类型?

我当前的解决方法是使用csplit /path/to/recommended.yaml /---/ '{*}' --prefix='dashboard.' --suffix-format='%03d.yaml' 以-作为分隔符来拆分YAML文件

kubectl apply -f -

接下来,我遍历已创建的新(14)部分,读取它们的字节,打开UniversalDeserializer的解码器返回的对象的类型,并使用我的k8s客户端集调用正确的API方法。

我想通过编程来对集群中仪表板的任何新版本进行更新。我还将需要对Metrics Server和许多其他资源执行此操作。另一种(可能更简单)的方法是将安装了kubectl的代码运送到容器映像中,然后直接调用kind;但这意味着我还需要将kube配置写入磁盘或内联传递它,以便kubectl可以使用它。

我发现此问题有帮助:https://github.com/kubernetes/client-go/issues/193 解码器位于此处:https://github.com/kubernetes/apimachinery/tree/master/pkg/runtime/serializer

它在客户端中公开:https://github.com/kubernetes/client-go/blob/master/kubernetes/scheme/register.go#L69

我还看了kubectl:https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/convert/convert.go#L139使用的RunConvert方法,并假设我可以提供自己的genericclioptions.IOStreams来获取输出?

It looks like RunConvert is on a deprecation path

我还查看了其他带有[client-go]标签的问题,但是大多数问题都使用旧示例或使用定义了单个Serviceaccount的YAML文件,并且此后API发生了变化。

编辑:因为我需要对多个群集执行此操作,并且正在以编程方式创建群集(AWS EKS API + CloudFormation / eksctl),所以我想将创建master的开销降至最低跨多个群集上下文,跨多个AWS账户。理想情况下,创建我的客户端集所涉及的唯一身份验证步骤是使用aws-iam-authenticator使用群集数据(名称,区域,CA cert等)获取令牌。一段时间没有发布aws-iam-authenticator,但是Serviceaccount的内容允许使用第三方角色交叉帐户角色和要传递的外部ID。 IMO,这比使用{{1}}(和IRSA)更干净,因为应用程序(用于创建附加组件并将附加组件应用到这些集群的后端API)还需要与其他AWS服务交互。 / p>

编辑:我最近发现了https://github.com/ericchiang/k8s。在高层上,它肯定比client-go更简单,但不支持此行为。

rongxiaoxiao 回答:对单个Kubernetes API使用client-go来针对Kubernetes API直接在多个YAML文件中使用多种类型

听起来您已经想出了如何将YAML文件反序列化为Kubernetes runtime.Object,但是问题是动态部署runtime.Object而没有为每种类型编写特殊代码。

kubectl通过直接与REST API进行交互来实现。具体来说,通过resource.Helper

在我的代码中,我有类似的东西:

import (
    meta "k8s.io/apimachinery/pkg/api/meta"
    "k8s.io/cli-runtime/pkg/resource"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/rest"
    "k8s.io/client-go/restmapper"
    "k8s.io/apimachinery/pkg/runtime"
)

func createObject(kubeClientset kubernetes.Interface,restConfig rest.Config,obj runtime.Object) error {
    // Create a REST mapper that tracks information about the available resources in the cluster.
    groupResources,err := restmapper.GetAPIGroupResources(kubeClientset.Discovery())
    if err != nil {
        return err
    }
    rm := restmapper.NewDiscoveryRESTMapper(groupResources)

    // Get some metadata needed to make the REST request.
    gvk := obj.GetObjectKind().GroupVersionKind()
    gk := schema.GroupKind{Group: gvk.Group,Kind: gvk.Kind}
    mapping,err := rm.RESTMapping(gk,gvk.Version)
    if err != nil {
        return err
    }

    name,err := meta.NewAccessor().Name(obj)
    if err != nil {
        return err
    }

    // Create a client specifically for creating the object.
    restClient,err := newRestClient(restConfig,mapping.GroupVersionKind.GroupVersion())
    if err != nil {
        return err
    }

    // Use the REST helper to create the object in the "default" namespace.
    restHelper := resource.NewHelper(restClient,mapping)
    return restHelper.Create("default",false,obj,&metav1.CreateOptions{})
}

func newRestClient(restConfig rest.Config,gv schema.GroupVersion) (rest.Interface,error) {
    restConfig.ContentConfig = resource.UnstructuredPlusDefaultContentConfig()
    restConfig.GroupVersion = &gv
    if len(gv.Group) == 0 {
        restConfig.APIPath = "/api"
    } else {
        restConfig.APIPath = "/apis"
    }

    return rest.RESTClientFor(&restConfig)
}

,

我能够在我的一个项目中实现这一点。我不得不使用 kubectl 的 apply 命令中的大部分源代码才能使其正常工作。

https://github.com/billiford/go-clouddriver/blob/master/pkg/kubernetes/client.go#L63

本文链接:https://www.f2er.com/3131112.html

大家都在问