使用 Kubernetes 聯邦(Kubefed)進行多集羣管理

《使用 Kubernetes 聯邦(Kubefed)進行多集羣管理》最先發布在 blog.ihypo.net/15718231244…html

前一篇文章 《Kubernetes 多集羣管理:Kubefed(Federation v2)》對 Federation v2 的基本概念和工做原理簡單介紹,本文着重介紹 Kubefed 的使用。linux

本文的實驗環境採用 v0.1.0-rc6 進行。nginx

$ 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。git

Controller Plan

Controller Plan 可使用 Helm 部署(目前 Helm 仍是使用 v2 版本),參考官方安裝文檔:github.com/kubernetes-…github

添加 helm repo:api

$ 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
複製代碼

找到目前的版本:bash

$ 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 直接安裝最新版本便可:服務器

$ helm install kubefed-charts/kubefed --name kubefed --version=0.1.0-rc6 --namespace kube-federation-system
複製代碼

kubefedctl

kubefedctl 是一個二進制程序,能夠在 Github 的 Release 頁面找到最新版本的下載地址:github.com/kubernetes-…網絡

$ 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 提供了不少便捷操做,好比集羣註冊、資源註冊等。app

多集羣管理

可使用 kubefedctl join 命令接入新集羣,在接入以前,須要先將多個集羣信息配置在本地的 kubeconfig 中。

基本使用方式爲:

kubefedctl join <集羣名稱> --cluster-context <要接入集羣的 context 名稱> --host-cluster-context <HOST 集羣的 context>
複製代碼

好比:

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 查看到集羣信息:

$ 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 命名空間中:

$ 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 來使新的資源能夠被聯邦管理:

kubefedctl enable <target kubernetes API type>
複製代碼

其中 可使用如下的描述:

  • 類型,即 Kind (好比 Deployment)
  • 複數名詞 (好比 deployments)
  • 帶 api group 的複數資源名詞 (好比 deployment.apps)
  • 縮寫 (好比 deploy)

好比咱們須要把 istio 中的 VirtualService 資源交給聯邦管理,可使用:

kubefedctl enable VirtualService
複製代碼

由於 Kubefed 是經過 CRD 管理資源,所以,當 enable 執行以後能夠看到 Host Cluster 中新增了一種名爲 federatedvirtualservices 的 CRD:

$ 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 中:

$ kubectl get federatednamespaces
NAME      AGE
default   3d21h
複製代碼

這裏嘗試建立一個 federatedvirtualservices 類型的資源:

$ kubectl get federatedvirtualservices
NAME            AGE
service-route   3d4h
複製代碼

完整 yaml:

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 資源。

$ kubectl get virtualservices
NAME            GATEWAYS            HOSTS   AGE
service-route   [service-gateway]   [*]     3d4h
複製代碼

調度

Kubefed 目前只能作到一些簡單的集羣間調度,即手工指定。

對於手工指定的調度方式主要分爲兩部分,一是直接在資源中制定目的地,二是經過 ReplicaSchedulingPreference 進行比例分配。

對於每一個被聯邦的資源來講,都有一個 placement 字段用來描述將要部署在哪一個集羣,能夠從 CRD 的描述中瞭解其定義思路:

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 來根據集羣標籤選擇集羣:

spec:
  placement:
    clusters:
      - name: cluster2
      - name: cluster1
    clusterSelector:
      matchLabels:
        foo: bar
複製代碼

不過有兩點要注意:

  1. 若是 clusters 字段被指定,clusterSelector 將會被忽略
  2. 被選擇的集羣是平等的,該資源會在每一個被選中的集羣中部署一個無差異副本

若是須要在多個集羣間進行區別調度的話就須要引入 ReplicaSchedulingPreference 進行按比例的調度了。

ReplicaSchedulingPreference 定義了包括多個和調度相關的字段來描述調度策略:

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 會根據調度策略的定義來進行維護不一樣集羣的副本數,具體細節能夠參考文檔:( github.com/kubernetes-… )。

網絡

Kubefed 還有一個亮點功能是跨集羣間的網絡訪問。Kubefed 經過引入外部 DNS,將 Ingress Controller 和 metallb 等外部 LB 結合起來,使跨集羣的流量可配置。

以 Ingress 舉例,用戶能夠建立 IngressDNSRecord 類型的資源,並指定域名,Kubefed 將會根據 IngressDNSRecord 自定配置相關的 DNS 策略,並應用到外部服務器中。

建立 IngressDNSRecord 類型的資源:

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

$ 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 服務器做爲上游服務器,那麼成員集羣能夠直接訪問對於域名就能夠實現跨集羣訪問。

部署

官方倉庫中有完整的實例以供實驗,能夠參考:github.com/kubernetes-…

除了調度以外,Kubefed 經過 overrides 字段實現不一樣集羣間的差別化部署:

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 查看部署狀態:

$ 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" 複製代碼

以及能夠看到,在不一樣集羣間的差別:

$ 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
複製代碼

相關文章
相關標籤/搜索