前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 Kubernetes 联邦(Kubefed)进行多集群管理

使用 Kubernetes 联邦(Kubefed)进行多集群管理

作者头像
CS实验室
发布2021-03-22 12:41:13
3.5K0
发布2021-03-22 12:41:13
举报
文章被收录于专栏:CS实验室

前一篇文章 《Kubernetes 多集群管理:Kubefed(Federation v2)》对 Federation v2 的基本概念和工作原理简单介绍,本文着重介绍 Kubefed 的使用。

本文的实验环境采用 v0.1.0-rc6 进行。

代码语言:javascript
复制
$ kubefedctl version
kubefedctl version: version.Info{Version:"v0.1.0-rc6", GitCommit:"7586b42f4f477f1912caf28287fa2e0a7f68f407", GitTreeState:"clean", BuildDate:"2019-08-17T03:55:05Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"linux/amd64"}

安装

Federation v2 的安装分两个部分,一是 Controller Plan 和 kubefedctl。

Controller Plan

Controller Plan 可以使用 Helm 部署(目前 Helm 还是使用 v2 版本),参考官方安装文档:https://github.com/kubernetes-sigs/kubefed/blob/master/charts/kubefed/README.md

添加 helm repo:

代码语言:javascript
复制
$ helm repo add kubefed-charts https://raw.githubusercontent.com/kubernetes-sigs/kubefed/master/charts

$ helm repo list
NAME            URL
kubefed-charts   https://raw.githubusercontent.com/kubernetes-sigs/kubefed/master/charts

找到目前的版本:

代码语言:javascript
复制
$ helm search kubefed
NAME                            CHART VERSION   APP VERSION DESCRIPTION
kubefed-charts/kubefed          0.1.0-rc6                   KubeFed helm chart
kubefed-charts/federation-v2    0.0.10                      Kubernetes Federation V2 helm chart

然后使用 helm 直接安装最新版本即可:

代码语言:javascript
复制
$ helm install kubefed-charts/kubefed --name kubefed --version=0.1.0-rc6 --namespace kube-federation-system

kubefedctl

kubefedctl 是一个二进制程序,可以在 Github 的 Release 页面找到最新版本的下载地址:https://github.com/kubernetes-sigs/kubefed/releases

代码语言:javascript
复制
$ wget https://github.com/kubernetes-sigs/kubefed/releases/download/v0.1.0-rc6/kubefedctl-0.1.0-rc6-linux-amd64.tgz

$ tar -zxvf kubefedctl-0.1.0-rc6-linux-amd64.tgz

$ mv kubefedctl /usr/local/bin/

kubefedctl 提供了很多便捷操作,比如集群注册、资源注册等。

多集群管理

可以使用 kubefedctl join 命令接入新集群,在接入之前,需要先将多个集群信息配置在本地的 kubeconfig 中。

基本使用方式为:

代码语言:javascript
复制
kubefedctl join <集群名称> --cluster-context <要接入集群的 context 名称> --host-cluster-context <HOST 集群的 context>

比如:

代码语言:javascript
复制
kubefedctl join cluster1 --cluster-context cluster1 \
    --host-cluster-context cluster1 --v=2
kubefedctl join cluster2 --cluster-context cluster2 \
    --host-cluster-context cluster1 --v=2

Kubefed 是利用 CR 来存储自己所需要的数据,因此当使用 kubefedctl join 后,可以在 host cluster 查看到集群信息:

代码语言:javascript
复制
$ kubectl -n kube-federation-system get kubefedclusters
NAME       READY   AGE
cluster1   True    3d22h
cluster2   True    3d22h
cluster3   True    3d22h

kubefedctl join 命令只是将 Kubeconfig 里的配置转化为 KubeFedCluster 自定义资源存储到 kube-federation-system 命名空间中:

代码语言:javascript
复制
$ kubectl -n kube-federation-system get kubefedclusters cluster1 -o yaml
apiVersion: core.kubefed.io/v1beta1
kind: KubeFedCluster
metadata:
  creationTimestamp: "2019-10-24T08:05:38Z"
  generation: 1
  name: cluster1
  namespace: kube-federation-system
  resourceVersion: "647452"
  selfLink: /apis/core.kubefed.io/v1beta1/namespaces/kube-federation-system/kubefedclusters/cluster1
  uid: 4c5eb57f-5ed4-4cec-89f3-cfc062492ae0
spec:
  apiEndpoint: https://172.16.200.1:6443
  caBundle: LS....Qo=
  secretRef:
    name: cluster1-shb2x
status:
  conditions:
  - lastProbeTime: "2019-10-28T06:25:58Z"
    lastTransitionTime: "2019-10-28T05:13:47Z"
    message: /healthz responded with ok
    reason: ClusterReady
    status: "True"
    type: Ready
  region: ""

资源

Federation v1 的淘汰的原因之一便是对资源拓展比较死板(需要拓展 API Server)而且没有预料的 CRD 的大规模应用,因此 Federation v2 在资源管理上面做的非常灵活。

对于 KubeFed 来说,资源管理分两类,一是资源的类型管理,另一个是被联邦(federated)的资源管理。

对于资源类型,kubefedctl 提供了 enable 来使新的资源可以被联邦管理:

代码语言:javascript
复制
kubefedctl enable <target kubernetes API type>

其中可以使用以下的描述:

  • 类型,即 Kind (比如 Deployment)
  • 复数名词 (比如 deployments)
  • 带 api group 的复数资源名词 (比如 deployment.apps)
  • 缩写 (比如 deploy)

比如我们需要把 istio 中的 VirtualService 资源交给联邦管理,可以使用:

代码语言:javascript
复制
kubefedctl enable VirtualService

因为 Kubefed 是通过 CRD 管理资源,因此,当 enable 执行之后可以看到 Host Cluster 中新增了一种名为 federatedvirtualservices 的 CRD:

代码语言:javascript
复制
$ kubectl get crd | grep virtualservice
federatedvirtualservices.types.kubefed.io            2019-10-24T13:12:46Z
virtualservices.networking.istio.io                  2019-10-24T08:06:01Z

该 CRD 里面描述了 federatedvirtualservices 类型的必需字段,比如:placementoverrides 等。

kubefedctl enable 完成了资源类型的管理,对于需要被联邦的资源管理编辑基于新创建的 CRD 展开的。不过要部署资源之前,需要先创建 federatednamespaces ,多集群的资源只会部署到被 kubefed 管理的 namespace 中:

代码语言:javascript
复制
$ kubectl get federatednamespaces
NAME      AGE
default   3d21h

这里尝试创建一个 federatedvirtualservices 类型的资源:

代码语言:javascript
复制
$ kubectl get federatedvirtualservices
NAME            AGE
service-route   3d4h

完整 yaml:

代码语言:javascript
复制
apiVersion: types.kubefed.io/v1beta1
kind: FederatedVirtualService
metadata:
  name: service-route
  namespace: default
spec:
  placement:
    clusters:
    - name: cluster1
    - name: cluster2
    - name: cluster3
  template:
    metadata:
      name: service-route
    spec:
      gateways:
      - service-gateway
      hosts:
      - '*'
      http:
      - match:
        - uri:
            prefix: /
        route:
        - destination:
            host: service-a-1
            port:
              number: 3000

这时,Kubefed 会根据 template 里的描述为目标集群创建对应的 virtualservice 资源。

代码语言:javascript
复制
$ kubectl get virtualservices
NAME            GATEWAYS            HOSTS   AGE
service-route   [service-gateway]   [*]     3d4h

调度

Kubefed 目前只能做到一些简单的集群间调度,即手工指定。

对于手工指定的调度方式主要分为两部分,一是直接在资源中制定目的地,二是通过 ReplicaSchedulingPreference 进行比例分配。

对于每个被联邦的资源来说,都有一个 placement 字段用来描述将要部署在哪个集群,可以从 CRD 的描述中了解其定义思路:

代码语言:javascript
复制
placement:
  properties:
    clusterSelector:
      properties:
        matchExpressions:
          items:
            properties:
              key:
                type: string
              operator:
                type: string
              values:
                items:
                  type: string
                type: array
            required:
            - key
            - operator
            type: object
          type: array
        matchLabels:
          additionalProperties:
            type: string
          type: object
      type: object
    clusters:
      items:
        properties:
          name:
            type: string
        required:
        - name
        type: object
      type: array
  type: object

使用示例如下,可以通过 clusters 指定一个 cluster 列表,或者通过 clusterSelector 来根据集群标签选择集群:

代码语言:javascript
复制
spec:
  placement:
    clusters:
      - name: cluster2
      - name: cluster1
    clusterSelector:
      matchLabels:
        foo: bar

不过有两点要注意:

  1. 如果 clusters 字段被指定, clusterSelector 将会被忽略
  2. 被选择的集群是平等的,该资源会在每个被选中的集群中部署一个无差别副本

如果需要在多个集群间进行区别调度的话就需要引入 ReplicaSchedulingPreference 进行按比例的调度了。

ReplicaSchedulingPreference 定义了包括多个和调度相关的字段来描述调度策略:

代码语言:javascript
复制
apiVersion: scheduling.kubefed.io/v1alpha1
kind: ReplicaSchedulingPreference
metadata:
  name: test-deployment
  namespace: test-ns
spec:
  targetKind: FederatedDeployment
  totalReplicas: 9
  clusters:
    A:
      minReplicas: 4
      maxReplicas: 6
      weight: 1
    B:
      minReplicas: 4
      maxReplicas: 8
      weight: 2
  • totalReplicas 定义了总副本数
  • clusters 描述不同集群的 最大\最小 副本以及权重

Kubefed 会根据调度策略的定义来进行维护不同集群的副本数,具体细节可以参考文档:( https://github.com/kubernetes-sigs/kubefed/blob/master/docs/userguide.md#replicaschedulingpreference )。

网络

Kubefed 还有一个亮点功能是跨集群间的网络访问。Kubefed 通过引入外部 DNS,将 Ingress Controller 和 metallb 等外部 LB 结合起来,使跨集群的流量可配置。

以 Ingress 举例,用户可以创建 IngressDNSRecord 类型的资源,并指定域名,Kubefed 将会根据 IngressDNSRecord 配置相关的 DNS 策略,并应用到外部服务器中。

创建 IngressDNSRecord 类型的资源:

代码语言:javascript
复制
apiVersion: multiclusterdns.kubefed.io/v1alpha1
kind: IngressDNSRecord
metadata:
  name: test-ingress
  namespace: test-namespace
spec:
  hosts:
  - ingress.example.com
  recordTTL: 300

DNS Endpoint controller 会生成相关的 DNSEndpoint

代码语言:javascript
复制
$ kubectl -n test-namespace get dnsendpoints -o yaml
apiVersion: v1
items:
- apiVersion: multiclusterdns.kubefed.io/v1alpha1
  kind: DNSEndpoint
  metadata:
    creationTimestamp: 2018-10-10T20:37:38Z
    generation: 1
    name: ingress-test-ingress
    namespace: test-namespace
    resourceVersion: "251874"
    selfLink: /apis/multiclusterdns.kubefed.io/v1alpha1/namespaces/test-namespace/dnsendpoints/ingress-test-ingress
    uid: 538d1063-cccc-11e8-bebb-42010a8a00b8
  spec:
    endpoints:
    - dnsName: ingress.example.com
      recordTTL: 300
      recordType: A
      targets:
      - $CLUSTER1_INGRESS_IP
      - $CLUSTER2_INGRESS_IP
  status: {}
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

ExternalDNS controller 会监听 DNSEndpoint 资源,收到事件后会将该记录应用到 DNS 服务器上,如果成员集群的内部 DNS 服务器使用该外部 DNS 服务器作为上游服务器,那么成员集群可以直接访问对于域名就可以实现跨集群访问。

部署

官方仓库中有完整的实例以供实验,可以参考:https://github.com/kubernetes-sigs/kubefed/tree/master/example

除了调度之外,Kubefed 通过 overrides 字段实现不同集群间的差异化部署:

代码语言:javascript
复制
apiVersion: types.kubefed.io/v1beta1
kind: FederatedDeployment
metadata:
  name: test-deployment
  namespace: test-namespace
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - image: nginx
            name: nginx
  placement:
    clusters:
    - name: cluster2
    - name: cluster1
  overrides:
  - clusterName: cluster2
    clusterOverrides:
    - path: "/spec/replicas"
      value: 5
    - path: "/spec/template/spec/containers/0/image"
      value: "nginx:1.17.0-alpine"
    - path: "/metadata/annotations"
      op: "add"
      value:
        foo: bar
    - path: "/metadata/annotations/foo"
      op: "remove"

对该 Deployment 部署之后,可以通过 kubectl describe 查看部署状态:

代码语言:javascript
复制
$ kubectl describe federateddeployment.types.kubefed.io/test-deployment
Name:         test-deployment
Namespace:    default
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"types.kubefed.io/v1beta1","kind":"FederatedDeployment","metadata":{"annotations":{},"name":"test-deployment","namespace":"d...
API Version:  types.kubefed.io/v1beta1
Kind:         FederatedDeployment
Metadata:
  Creation Timestamp:  2019-10-28T07:55:34Z
  Finalizers:
    kubefed.io/sync-controller
  Generation:        1
  Resource Version:  657714
  Self Link:         /apis/types.kubefed.io/v1beta1/namespaces/default/federateddeployments/test-deployment
  UID:               6016a3eb-7e7f-4756-ba40-b655581f06ad
Spec:
  Overrides:
    Cluster Name:  cluster2
    Cluster Overrides:
      Path:   /spec/replicas
      Value:  5
      Path:   /spec/template/spec/containers/0/image
      Value:  nginx:1.17.0-alpine
      Op:     add
      Path:   /metadata/annotations
      Value:
        Foo:  bar
      Op:     remove
      Path:   /metadata/annotations/foo
  Placement:
    Clusters:
      Name:  cluster2
      Name:  cluster1
  Template:
    Metadata:
      Labels:
        App:  nginx
    Spec:
      Replicas:  3
      Selector:
        Match Labels:
          App:  nginx
      Template:
        Metadata:
          Labels:
            App:  nginx
        Spec:
          Containers:
            Image:  nginx
            Name:   nginx
Status:
  Clusters:
    Name:  cluster1
    Name:  cluster2
  Conditions:
    Last Transition Time:  2019-10-28T07:55:35Z
    Last Update Time:      2019-10-28T07:55:49Z
    Status:                True
    Type:                  Propagation
Events:
  Type    Reason           Age                From                            Message
  ----    ------           ----               ----                            -------
  Normal  CreateInCluster  14s                federateddeployment-controller  Creating Deployment "default/test-deployment" in cluster "cluster2"
  Normal  CreateInCluster  14s                federateddeployment-controller  Creating Deployment "default/test-deployment" in cluster "cluster1"
  Normal  UpdateInCluster  0s (x10 over 12s)  federateddeployment-controller  Updating Deployment "default/test-deployment" in cluster "cluster2"

以及可以看到,在不同集群间的差异:

代码语言:javascript
复制
$ kubectl --context=cluster1 get deploy | grep test
test-deployment   3/3     3            3           98s

$ kubectl --context=cluster2 get deploy | grep test
test-deployment   5/5     5            5           105s
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CS实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前一篇文章 《Kubernetes 多集群管理:Kubefed(Federation v2)》对 Federation v2 的基本概念和工作原理简单介绍,本文着重介绍 Kubefed 的使用。
    • 安装
      • Controller Plan
      • kubefedctl
    • 多集群管理
      • 资源
      • 调度
      • 网络
    • 部署
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档