• Helm-4: 让编排兼容不同版本K8S


    在使用Helm过程中, 经常会遇到编排需要兼容不同K8S版本的问题. 考虑如下场景:

    1. 以前编写的Deployment资源, 其apiVersion为 apps/v1beta1, 但后来新的版本中已经改为 apps/v1,希望能兼容

    2. 在K8S 1.11以前, 默认CRD既不支持subResources, 也不能够通过 UpdateStatus 更新状态, 必须使用 Update. 而在这之后, 必须使用 UpdateStatus 才能更新状态.

    Helm 内置了一系列内部对象,可以针对这些情况进行编排.

    Deployment兼容多版本K8S

    针对以上第一个问题, 我们可以直接在 _helpers.tpl 中加入以下内容:

    {{/*
    Define apiVersion for Deployment
    */}}
    {{- define "deployApiVersion" -}} 
    {{- if .Capabilities.APIVersions.Has "apps/v1beta1/Deployment" -}}
    apps/v1beta1
    {{- else -}}
    apps/v1
    {{- end -}}
    {{- end -}}
    

    这里判断这套K8S是否具备 apps/v1beta/Deployment , 如果有, 使用 apps/v1 ,否则就是旧版本的 apps/v1beta1

    然后, Deployment引用这一段即可:

    kind: Deployment
    apiVersion: {{ include "deployApiVersion" . }}
    

    检测配置 disableSubresources 是否开启

    经过查询文档, disableSubresources 默认开启是在 1.11 版本, 因此我们可以简单一点, 只判断小版本是否大于等于 "11", 当然这里没有判断大版本.

    disableSubresources: {{ if ge .Capabilities.KubeVersion.Minor "11" }}false{{ else }}true{{ end }}
    

    Capabilities 实现

    我们可能在某些场景下, 希望自己的程序能够直接去判断我们对接的K8S集群有哪些能力. 这部分实现我们可以参考 helm 源码. 在 pkg/action/action.go中揭示了其实现方式:

    // capabilities builds a Capabilities from discovery information.
    func (c *Configuration) getCapabilities() (*chartutil.Capabilities, error) {
            if c.Capabilities != nil {
                    return c.Capabilities, nil
            }
            dc, err := c.RESTClientGetter.ToDiscoveryClient()
            if err != nil {
                    return nil, errors.Wrap(err, "could not get Kubernetes discovery client")
            }
            // force a discovery cache invalidation to always fetch the latest server version/capabilities.
            dc.Invalidate()
            kubeVersion, err := dc.ServerVersion()
            if err != nil {
                    return nil, errors.Wrap(err, "could not get server version from Kubernetes")
            }
            // Issue #6361:
            // Client-Go emits an error when an API service is registered but unimplemented.
            // We trap that error here and print a warning. But since the discovery client continues
            // building the API object, it is correctly populated with all valid APIs.
            // See https://github.com/kubernetes/kubernetes/issues/72051#issuecomment-521157642
            apiVersions, err := GetVersionSet(dc)
            if err != nil {
                    if discovery.IsGroupDiscoveryFailedError(err) {
                            c.Log("WARNING: The Kubernetes server has an orphaned API service. Server reports: %s", err)
                            c.Log("WARNING: To fix this, kubectl delete apiservice <service-name>")
                    } else {
                            return nil, errors.Wrap(err, "could not get apiVersions from Kubernetes")
                    }
            }
    
            c.Capabilities = &chartutil.Capabilities{
                    APIVersions: apiVersions,
                    KubeVersion: chartutil.KubeVersion{
                            Version: kubeVersion.GitVersion,
                            Major:   kubeVersion.Major,
                            Minor:   kubeVersion.Minor,
                    },
            }
            return c.Capabilities, nil
    }
    

    dry-run 没问题的chart一定能够在集群上部署吗?

    在解决第一个问题时, 我事先通过 -dry-run 测试我写出的chart, 结果安装到集群却失败了. 其实, 在Helm Chart进行dryrun时, 是不会与集群进行交互的.

    在 helm 源码中, 它的解释是编排chart的作者的期望可能是连接到集群,但用户却不一定如此期望:

            // A `helm template` or `helm install --dry-run` should not talk to the remote cluster.
            // It will break in interesting and exotic ways because other data (e.g. discovery)
            // is mocked. It is not up to the template author to decide when the user wants to
            // connect to the cluster. So when the user says to dry run, respect the user's
            // wishes and do not connect to the cluster.
            if !dryRun && c.RESTClientGetter != nil {
                    rest, err := c.RESTClientGetter.ToRESTConfig()
                    if err != nil {
                            return hs, b, "", err
                    }
                    files, err2 = engine.RenderWithClient(ch, values, rest)
            } else {
                    files, err2 = engine.Render(ch, values)
            }
    
  • 相关阅读:
    fiddler应用之Composer(发送接口请求)
    fiddler应用之AutoResponder(fiddler的重定向页面功能)
    fiddler应用之设置断点(fiddler篡改request和response数据)
    fiddler应用之过滤器(用fiddler筛选特定网络请求)
    fiddler配置之对移动设备进行抓包证书安装
    fiddler配置之设置手机代理
    外部排序的基本概念
    80天考研核心短语
    地址访问冲突问题(四体交叉存取)
    制约函数法
  • 原文地址:https://www.cnblogs.com/qianyuming/p/12774062.html
Copyright © 2020-2023  润新知