查看原文
其他

使用Go语言操作Istio和其他Kubernetes CRD

Dave Kerr 几米宋 2022-09-06

作者:Dave Kerr 译者:王帅俭 原文地址:https://dwmkerr.com/manipulating-istio-and-other-custom-kubernetes-resources-in-golang

在本文中,我将演示如何使用Golang来操作Kubernetes Custom Resources,以Istio为例。 不需要您了解Istio,我只是用它来展示概念!

Istio是一个非常受欢迎的服务网格平台,它允许工程师快速地为基于服务的应用程序添加遥测技术、先进的流量管理等功能。

Istio工作原理的一个有趣的地方是,当部署到Kubernetes集群中时,许多关键配置对象被作为自定义资源处理。自定义资源是一个非常强大的Kubernetes特性,它允许您创建自己的”一等“资源(就像pod、副本、部署等),然后使用 kubectl或Kubernetes API与它们进行交互。

在本文中,我将展示如何使用Golang Kubernetes client与这些自定义资源交互。

CRD:快速概述

在为集群设置Istio时,您可能要做的一件常见的事情是指定如何路由通信。这可能相当复杂,如下所示:

图1:来自istio.io的Istio流量管理示例

对于这样的系统,有一种配置方法就是使用一个ConfigMap,其中包含如何路由服务的定义。

然而,Istio实际上注册了新的资源类型(自定义资源定义),来表示网关或服务之类的对象。我们可以创建/更新/删除/操作这些资源类型,就像任何其他Kubernetes对象一样。

例如,我可以为上面的示例创建一个虚拟服务,如下所示:

  1. cat << EOF | kubectl create -f -

  1. apiVersion: networking.istio.io/v1alpha3

  2. kind: VirtualService

  3. metadata:

  4.  name: service2

  5. spec:

  6.  hosts:

  7.  - "*"

  8.  gateways:

  9.  - demo1-gateway

  10.  http:

  11.  - route:

  12.    - destination:

  13.        host: service2

  14.        subset: v1

  15.      weight: 95

  16.    - destination:

  17.        host: service2

  18.        subset: v2

  19.      weight: 5

  20. EOF

同样,重要的不是这个资源的具体内容,而是我可以像对待其他Kubernetes对象一样对待Istio资源:

  1. $ kubectl get virtualservices.networking.istio.io

  2. NAME       AGE

  3. service2   93s

或者:

  1. $ kubectl delete virtualservices.networking.istio.io/service2

甚至还可以使用 editdescribe、注册生命周期事件、监视更改等等操作。

使用go语言操作CRD

使用Golang Kubernetes Client可以创建强定义的类型,然后就可以使用这些类型与CRD交互。红帽博客文章Kubernetes Deep Dive: Code Generation for Custom Resources就是一个例子。

这是一种非常好的方法,但是如果您想快速访问一些数据,而又不想生成大量代码,那么这种方法会让您感到非常吃力。

还有一种替代方法,即使用 DynamicClient。首选的方法似乎是第一种方法,它涉及到代码生成,因此第二种方法的文档很少。然而,第二种方法其实很简单。

下面这个例子介绍如何列出所有Istio VirtualService资源,而无需生成任何代码:

  1. import (

  2.    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

  3.    "k8s.io/client-go/dynamic"

  4. )

  5. //  Create a Dynamic Client to interface with CRDs.

  6. dynamicClient, _ := dynamic.NewForConfig(config)

  7. //  Create a GVR which represents an Istio Virtual Service.

  8. virtualServiceGVR := schema.GroupVersionResource{

  9.    Group:    "networking.istio.io",

  10.    Version:  "v1alpha3",

  11.    Resource: "virtualservices",

  12. }

  13. //  List all of the Virtual Services.

  14. virtualServices, _ := dynamicClient.Resource(virtualServiceGVR).Namespace("default").List(metav1.ListOptions{})

  15. for _, virtualService := range virtualServices.Items {

  16.    fmt.Printf("VirtualService: %s\n", virtualService.GetName())

  17. }

为了清晰起见,这段代码省略了设置和错误处理,完整的示例在k8s-list-virtualservices.go。

使用go语言修改CRD

您可能已经注意到,代码 .Resource().Namespace().List()与Kubernetes Clientset进行API调用时使用的结构非常相似。实际上,本质上是一样的。看看接口,你可以看到所有你想要的操作:

  • Create

  • Update

  • Delete

  • Get

等等。这很好,因为您可以像我的文章'Patching Kubernetes Resources in Golang'中那样使用相同的技巧来操作这些实体,而无需创建表示它们的结构。

下面是另一个简短的例子,这次展示了如何将服务的路由的权重调整到50%/50%:

  1. import (

  2.    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

  3.    "k8s.io/client-go/dynamic"

  4. )

  5. //  Create a GVR which represents an Istio Virtual Service.

  6. virtualServiceGVR := schema.GroupVersionResource{

  7.    Group:    "networking.istio.io",

  8.    Version:  "v1alpha3",

  9.    Resource: "virtualservices",

  10. }

  11. //  Weight the two routes - 50/50.

  12. patchPayload := make([]PatchUInt32Value, 2)

  13. patchPayload[0].Op = "replace"

  14. patchPayload[0].Path = "/spec/http/0/route/0/weight"

  15. patchPayload[0].Value = 50

  16. patchPayload[1].Op = "replace"

  17. patchPayload[1].Path = "/spec/http/0/route/1/weight"

  18. patchPayload[1].Value = 50

  19. patchBytes, _ := json.Marshal(patchPayload)

  20. //  Apply the patch to the 'service2' service.

  21. _, err := dynamicClient.Resource(virtualServiceGVR).Namespace("default").Patch("service2", types.JSONPatchType, patchBytes)

请参阅 k8s-patch-virtualservice.go中的完整示例。

运行示例后,您可以使用Kubernetes CLI来验证更改:

  1. $ kubectl get virtualservices.networking.istio.io/service2 -o yaml

  1. apiVersion: networking.istio.io/v1alpha3

  2. kind: VirtualService

  3. metadata:

  4.  clusterName: ""

  5.  creationTimestamp: 2018-10-08T09:53:16Z

  6.  generation: 0

  7.  name: service2

  8.  namespace: default

  9.  resourceVersion: "487435"

  10.  selfLink: /apis/networking.istio.io/v1alpha3/namespaces/default/virtualservices/service2

  11.  uid: fac5930c-cadf-11e8-90a2-42010a94005b

  12. spec:

  13.  gateways:

  14.  - demo1-gateway

  15.  hosts:

  16.  - '*'

  17.  http:

  18.  - route:

  19.    - destination:

  20.        host: service2

  21.        subset: v1

  22.      weight: 50

  23.    - destination:

  24.        host: service2

  25.        subset: v2

  26.      weight: 50

保持简单!

就是这样!这个技巧使我正在做的事情变得简单了很多,但是需要做一些实验才能得到正确的结果。我希望你觉得这个方法有用,请在评论中分享你的想法与问题。

进一步阅读

在采用这种方法时使用了以下几篇文章:

  • Red Hat: Deep Dive: Code Generation for Custom Resources

  • Kubernetes Docs: Custom Resources

点击【阅读原文】跳转到ServiceMesher网站上浏览可以查看文中的链接。

相关阅读

  • SOFAMesh(https://github.com/alipay/sofa-mesh)基于Istio的大规模服务网格解决方案

  • SOFAMosn(https://github.com/alipay/sofa-mosn使用Go语言开发的高性能Sidecar代理

合作社区


参与社区

以下是参与ServiceMesher社区的方式,最简单的方式是联系我!

  • 加入微信交流群:关注本微信公众号后访问主页右下角有获取联系方式按钮,添加好友时请注明姓名-公司

  • 社区网址:http://www.servicemesher.com

  • Slack:https://servicemesher.slack.com (需要邀请才能加入)

  • GitHub:https://github.com/servicemesher

  • Istio中文文档进度追踪:https://github.com/servicemesher/istio-official-translation

  • Twitter: https://twitter.com/servicemesher

  • 提供文章线索与投稿:https://github.com/servicemesher/trans


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存