在单个YAML文件中直接对多种类型的Kubernetes API使用client-go进行kubectl apply


10

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

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

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

我了解我需要将YAML字节进行一些(非)编组为程序包中定义的正确API类型:https : //github.com/kubernetes/api

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

我当前的解决方法是使用csplit-作为分隔符来拆分YAML文件

csplit /path/to/recommended.yaml /---/ '{*}' --prefix='dashboard.' --suffix-format='%03d.yaml'

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

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

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

它在此处的client-go中公开:https : //github.com/kubernetes/client-go/blob/master/kubernetes/scheme/register.go#L69

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

看起来RunConvert在弃用路径上

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

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

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


1
与其将kube config写入容器磁盘,不如
KFC_

1
您为什么不只阅读YAML文件的内容并^---$在代码中进行分割?
Shawyeok

@Shawyeok因为这仍然需要我知道文件中的类型。如果不对几种预期的类型(Kubernetes对象)进行测试,就无法动态获取类型,并且如果不存在预期的类型,则该对象将不会应用于集群(这会导致更多问题)。这也将导致不得不为单个组件编写大量代码,而这些代码无法为多个组件扩展。除了解码之外,还调用正确的API方法将对象应用于集群。
西蒙

Answers:


3

听起来您已经找到了如何将YAML文件反序列化为Kubernetes runtime.Object的方法,但是问题是如何动态部署a runtime.Object而不为每种Kind编写特殊代码。

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)
}

你好,凯文,谢谢你的回答!我还没有机会尝试这种方法,但是我没有意识到,package restmapper这看起来很有希望。暂时接受答案,但很快就会重新访问。
西蒙

1
希望这对你有用!
Kevin Lin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.