Kubernetes 聯邦集羣 kubefed v2的使用

1. 描述

跨羣集同步資源: 通過將多個集羣組成一個聯邦,可以在多個羣集中的保持資源同步。 例如,可以確保多個羣集中部署相同的程序。

跨羣集發現:聯邦提供了自動配置DNS服務器和負載均衡器與所有羣集後端的功能。

2. 概念統一

概念 描述
聯邦 一組Kubernetes集羣,提供一個集羣組成一個大資源的池子的接口,該接口可用於在這些集羣之間部署Kubernetes應用程序。
聯邦化 使用戶將k8s 集羣裏的資源,服務發現,和高可用應用在多集羣之上
主集羣 用於暴露KubeFed API 並且運行 KubeFed control plane.
成員集羣 通過KubeFed API 加入聯邦,且主集羣可以控制的集羣,主集羣也可以是成員集羣。

3. 聯邦集羣準備

  • 實現準備好2個k8s 集羣。

  • 部署helm,注意不想翻牆的話,就用alauda 自己的鏡像庫

    • wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.1-linux-amd64.tar.gz

    • tar -zxvf helm-v2.14.1-linux-amd64.tar.gz

    • mv linux-amd64/helm /usr/local/bin/helm

    • helm init --service-account tiller

    • deployment裏把tiller地址改成alauda地址index.alauda.cn/claas/tiller:v2.14.1

    • Rbac規則調整下

       cat << EOF | kubectl apply -f -
       apiVersion: v1
       kind: ServiceAccount
       metadata:
         name: tiller
         namespace: kube-system
       ---
       apiVersion: rbac.authorization.k8s.io/v1
       kind: ClusterRoleBinding
       metadata:
         name: tiller
       roleRef:
         apiGroup: rbac.authorization.k8s.io
         kind: ClusterRole
         name: cluster-admin
       subjects:
         - kind: ServiceAccount
           name: tiller
           namespace: kube-system
       EOF
      
  • 安裝kubefedctl 二進制

    VERSION=0.1.0-rc6
    OS=linux
    ARCH=amd64
    curl -LO https://github.com/kubernetes-sigs/kubefed/releases/download/v${VERSION}/kubefedctl-${VERSION}-${OS}-${ARCH}.tgz
    tar -zxvf kubefedctl-*.tgz
    chmod u+x kubefedctl
    sudo mv kubefedctl /usr/local/bin/
    
  • 準備兩個集羣,一個叫做global,一個叫做business。

  • 添加kubectl config 文件,類似這樣:export KUBECONFIG=/root/lmxia/cluster-config/config-cluster.yaml

    apiVersion: v1
    kind: Config
    preferences: {}
    
    clusters:
    - cluster:
        server: https://10.0.128.95:6443
        insecure-skip-tls-verify: true
      name: global
    - cluster:
        server: https://10.0.129.168:6443
        insecure-skip-tls-verify: true
      name: business
    
    users:
    - name: global-admin
      user:
        token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tNmw3NGIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImNkN2YxOTcxLTgxZTYtMTFlOS04MzFlLTUyNTQwMGNiNDMyZCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.GnEEx8yaYaik78Q1rQiFiP3Mhscxvn2nXKfSpEhSgfxytsT7V7I5ftuibq4zGxLYs1z8U0N_0tcQXq3DBL97-4kNfQdCMx42QOzV4yDvRNI_DFlM5oICjZeiVMRHSWCWUZEVyas9zb9G23MJ8uU4C3kesoOz9ycL61-fTYnx_99wNvycFlyEnb614cWMkCq6ji1gfa52Iei7u5y7CSyHxj0z09e5WS4JOjVjtGTGVBFevlsj1qZjeh4otqprLU8fVixonuFgT8X-CFBXz-1KjmugGq9tR7EIFqgbmwx-ZYNsAjGkP2iOUnPs9POCOtZh7Fj5lqyqUjeO7FqyU778IQ
    - name: business-admin
      user:
        token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjbHVzdGVycm9sZS1hZ2dyZWdhdGlvbi1jb250cm9sbGVyLXRva2VuLXA5ZDlmIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNsdXN0ZXJyb2xlLWFnZ3JlZ2F0aW9uLWNvbnRyb2xsZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJlYTE5YmJhMS04MWYyLTExZTktOTQ3Mi01MjU0MDA3YjFiMjIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06Y2x1c3RlcnJvbGUtYWdncmVnYXRpb24tY29udHJvbGxlciJ9.jI6M3ErK3mlAGk-cCtuhdS4H34-4Wl7yBGMWxOpqhaczHtlIi3H1dZHzDySNihTsy8kcpbJRhz-vkitYslKkqIKqbtkvUNTSAivXSxieSKbtb7jeCt1-6OUgoQTNRcYfpRK7Ur-2Y8XcRazcxr6i-tIODhljBmSd9mT32jLtyoDNsraE9o7-c4eEvA5DxkM6BlvpVHSh6cnBN4UhJ7qKo-M1g1ZSyAIGwN-Zd_0uQjcnAA5AqyzRUGQJ2AalXy5IGDescE2sL8mbOJqOHbB9PRNmI2vCcVzyhDtjmfR9o-EToPRvn8bUqqV3ulmznMGNM9SkLNUWUQCU1ZMkrP2ATg
    
    contexts:
    - context:
        cluster: business
        user: business-admin
      name: business
    - context:
        cluster: global
        user: global-admin
      name: global
    

    其中token 是一個比較高權的token,怎麼來的呢?

    kubectl describe secret -n kube-system $(kubectl get secret -n kube-system | awk '/clusterrole-aggregation-controller-token/ {print $1}') | awk '/^token:/{print $2}'
    

    接下來就可以做聯邦集羣相關的事兒了。

    4. 加入聯邦

    1. kubefedctl join business --cluster-context business --host-cluster-context global --v=2

      會發現,做了什麼呢?

      • 在business集羣中創建了一個namespace: kube-federation-system

      • 在business集羣裏, 創建了一個service account: business-global,當然還有secret,business-global-token-kr8dz,同步在global裏也會創建一個secret:business-66qpm,這個兩個secret 的內容完全一樣。

      • 在business集羣中創建了一個clusterrole 和 clusterrolebinding, 這個clusterrole 具有全部的resource 的全部權限

      • 最重要的,在global集羣裏: federated cluster resource。這個crd 的一個實例,描述了一個集羣的信息。

        kubectl get kubefedclusters -n kube-federation-system -o yaml

    2. kubefedctl join global --cluster-context global --host-cluster-context global --v=2

      類似上一步。

    重要概念:

    kubefedclusters.core.kubefed.io, KubeFedCluster configures KubeFed to be aware of a Kubernetes clusterand encapsulates the details necessary to communicate with the cluster.

5. 聯邦接口準備

默認會創建10種常見的透傳資源,如果crd 的話,必須每一個成員集羣都要安裝,看到默認的,如果是core api 就把group 名字給省略了。

[root@ake-master1 cluster-config]# kubectl get FederatedTypeConfig -n kube-federation-system
NAME                                     AGE
clusterroles.rbac.authorization.k8s.io   2h
configmaps                               2h
deployments.apps                         6s
ingresses.extensions                     2h
jobs.batch                               2h
namespaces                               2h
replicasets.apps                         2h
secrets                                  2h
serviceaccounts                          2h
services                                 2h

如果需要使能新的接口:

[root@ake-master1 cluster-config]# kubefedctl enable --host-cluster-context global deployments.apps
customresourcedefinition.apiextensions.k8s.io/federateddeployments.types.kubefed.io updated
federatedtypeconfig.core.kubefed.io/deployments.apps created in namespace kube-federation-system

會發現這個命令

  1. 會在主集羣創建一個CRD, for the federated type 叫 FederatedDeployments,group默認: types.kubefed.io
  2. 同時創建一個FederatedTypeConfig crd 實例出來,其中他的target type 指向了 deployments.apps。
  • 重點來了:

    FederatedTypeConfig將federated type CRD與目標kubernetes類型相關聯,從而可以將給定類型的聯合資源透傳到成員集羣。

以deployments.apps 爲例,如圖:

[root@ake-master1 cluster-config]# kubectl get FederatedTypeConfig  -n kube-federation-system deployments.apps -o yaml
apiVersion: core.kubefed.io/v1beta1
kind: FederatedTypeConfig
metadata:
  creationTimestamp: "2019-10-10T08:33:05Z"
  finalizers:
  - core.kubefed.io/federated-type-config
  generation: 1
  name: deployments.apps
  namespace: kube-federation-system
  resourceVersion: "68639766"
  selfLink: /apis/core.kubefed.io/v1beta1/namespaces/kube-federation-system/federatedtypeconfigs/deployments.apps
  uid: 94724cf9-eb38-11e9-b9d9-525400e36779
spec:
  federatedType:
    group: types.kubefed.io
    kind: FederatedDeployment
    pluralName: federateddeployments
    scope: Namespaced
    version: v1beta1
  propagation: Enabled
  targetType:
    group: apps
    kind: Deployment
    pluralName: deployments
    scope: Namespaced
    version: v1
status:
  observedGeneration: 1
  propagationController: Running
  statusController: NotRunning

這裏有兩個關鍵的字段:**federatedType **和 targetType,其中federatedType指的是我們enabled 過的 資源。上文提到enable 的話,會創建一個相關資源的federated,和一個FederatedTypeConfig(本質上就是個映射)。

使用聯邦資源以前需要檢查下是不是所有資源類型在成員集羣內都具備:

CLUSTER_CONTEXTS="global business"
for c in ${CLUSTER_CONTEXTS}; do echo ----- ${c} -----; kubectl --context=${c} api-resources --api-group=aiops.alauda.io; done

我們看到aiops 這個組,business 集羣就沒有,所以我們不能創建該類資源的聯邦資源時就可能會出錯。

6. 聯邦一個k8s 資源

kubefedctl federate 這個命令會從k8s 資源創造出一個聯邦資源,它會抽象該資源到對應的federatedType,默認會保存到和k8s 資源同一個ns裏,比如這裏,我們先創建一個secret:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

kubectl apply -f mysecret.yaml -n test, 然後

[root@ake-master1 lmxia]# kubefedctl federate secrets mysecret -n lmxia --host-cluster-context global
W1010 18:15:30.554209   31227 federate.go:410] Annotations defined for Secret "test/mysecret" will not appear in the template of the federated resource: map[kubectl.kubernetes.io/last-applied-configuration:{"apiVersion":"v1","data":{"password":"MWYyZDFlMmU2N2Rm","username":"YWRtaW4="},"kind":"Secret","metadata":{"annotations":{},"name":"mysecret","namespace":"test"},"type":"Opaque"}
]
I1010 18:15:34.601079   31227 federate.go:503] Successfully created FederatedSecret "test/mysecret" from Secret

開心的去看下聯邦的效果時,也許會失望,並沒有在business 集羣中創建出來。查原因:

[root@ake-master1 lmxia]# kubectl get FederatedSecret -n lmixa mysecret -o yaml
apiVersion: types.kubefed.io/v1beta1
kind: FederatedSecret
metadata:
  creationTimestamp: "2019-10-10T10:15:34Z"
  finalizers:
  - kubefed.io/sync-controller
  generation: 1
  name: mysecret
  namespace: test
  resourceVersion: "68695902"
  selfLink: /apis/types.kubefed.io/v1beta1/namespaces/test/federatedsecrets/mysecret
  uid: e5b86821-eb46-11e9-a4fa-525400ec6688
spec:
  placement:
    clusterSelector:
      matchLabels: {}
  template:
    data:
      password: MWYyZDFlMmU2N2Rm
      username: YWRtaW4=
    type: Opaque
status:
  conditions:
  - lastTransitionTime: "2019-10-10T10:15:34Z"
    lastUpdateTime: "2019-10-10T10:15:34Z"
    reason: NamespaceNotFederated
    status: "False"
    type: Propagation

NamespaceNotFederated, 所以事先我們需要先把ns 給聯邦管理起來。

kubefedctl federate namespace lmxia --host-cluster-context global

這時候會發現成功了:

[root@ake-master1 lmxia]# kubectl get FederatedSecret mysecret -n lmxia -o yaml
apiVersion: types.kubefed.io/v1beta1
kind: FederatedSecret
metadata:
  creationTimestamp: "2019-10-10T11:27:13Z"
  finalizers:
  - kubefed.io/sync-controller
  generation: 1
  name: mysecret
  namespace: lmxia
  resourceVersion: "68732031"
  selfLink: /apis/types.kubefed.io/v1beta1/namespaces/lmxia/federatedsecrets/mysecret
  uid: e7ef75e9-eb50-11e9-b9d9-525400e36779
spec:
  placement:
    clusterSelector:
      matchLabels: {}
  template:
    data:
      password: MWYyZDFlMmU2N2Rm
      username: YWRtaW4=
    type: Opaque
status:
  clusters:
  - name: business
  - name: global
  conditions:
  - lastTransitionTime: "2019-10-10T11:27:17Z"
    lastUpdateTime: "2019-10-10T11:27:17Z"
    status: "True"
    type: Propagation

直接從聯邦資源創建:

apiVersion: types.kubefed.io/v1beta1
kind: FederatedSecret
metadata:
  finalizers:
  - kubefed.io/sync-controller
  name: mysecret
  namespace: lmxia
spec:
  placement:
    clusterSelector:
      matchLabels: {}
  template:
    data:
      password: MWYyZDFlMmU2N2Rm
      username: YWRtaW4=
    type: Opaque

會發現會直接在所有集羣內,創建出來這個secret。

這裏有3個重要字段:

  • Templates 所以集羣都按這個配置

  • Placement 指定哪些集羣需部署該資源

  • Overrides 覆蓋template 中的配置,針對特定集羣做不同的設置

7. 刪除策略

刪除聯邦資源有一個,Pre-deletion cleanup,刪除前的clean up,它會把所有成員集羣的該k8s資源全部刪掉。

kubectl delete FederatedSecrets mysecret --host-cluster-context global -n lmxia

但是有沒有辦法幹掉聯邦資源的時候,保存k8s資源呢,可以修改刪除策略。

保留孤兒:

kubefedctl orphaning-deletion enable  FederatedSecrets mysecret -n lmxia --host-cluster-context global

再次刪除的時候:

kubectl delete FederatedSecrets mysecret -n lmxia

發現成員集羣的資源都保存着。

8. 嘗試針對不同的集羣做不同的配置

一個更加通用的使用方式是,不同的集羣,不同的鏡像倉庫,不同的集羣不同的副本數量,不同的secret 設置(或者說數據庫設置)我們通過部署一個deployment和一個secret 來展示:

apiVersion: types.kubefed.io/v1beta1
kind: FederatedDeployment
metadata:
  finalizers:
  - kubefed.io/sync-controller
  name: test-deployment
  namespace: fed-ns-1
spec:
  overrides:
  - clusterName: feder2
    clusterOverrides:
    - path: /spec/replicas
      value: 3
    - path: /spec/template/spec/containers/0/image
      value: nginx:1.17.0-alpine
  placement:
    clusters:
    - name: feder1
    - name: feder2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - image: index.alauda.cn/alauda/hello-world:latest
            name: hello
            volumeMounts:
            - mountPath: /etc/foo
              name: foo
              readOnly: true
          volumes:
          - name: foo
            secret:
              secretName: mysecret
status:
  clusters:
  - name: feder1
  - name: feder2
apiVersion: types.kubefed.io/v1beta1
kind: FederatedSecret
metadata:
  finalizers:
  - kubefed.io/sync-controller
  name: mysecret
  namespace: fed-ns-1
spec:
  overrides:
  - clusterName: feder2
    clusterOverrides:
    - path: /data/password
      value: MTIxMzI4dTI5NDczMjQ3
  placement:
    clusterSelector:
      matchLabels: {}
  template:
    data:
      password: MWYyZDFlMmU2N2Rm
      username: YWRtaW4=
    type: Opaque
status:
  clusters:
  - name: feder1
  - name: feder2

上述deployment 的yaml 中,override 字段裏feder2 集羣,要求部署3個實例,且鏡像倉庫爲docker hub的nginx:1.17.0-alpine,默認模版是index.alauda.cn/alauda/hello-world:latest,且副本是2。這個deployment 掛載了 secret,secret其中保存了deployment 的數據庫地址配置,也會是一個聯邦資源,這樣部署後,會發現ferder2 集羣3個實例,且鏡像爲nginx,掛載到容器裏的密碼和 feder1 是不同的。

8. 訪問

創建svc

apiVersion: types.kubefed.io/v1beta1
kind: FederatedService
metadata:
  finalizers:
  - kubefed.io/sync-controller
  name: test-service
  namespace: fed-ns-1
spec:
  placement:
    clusterSelector:
      matchLabels: {}
  template:
    metadata:
      labels:
        app: nginx
    spec:
      externalTrafficPolicy: Cluster
      ports:
      - name: nginx
        port: 80
        protocol: TCP
        targetPort: 80
      selector:
        app: nginx
      sessionAffinity: None
      type: NodePort
status:
  clusters:
  - name: feder2
  - name: feder1

發現無法產生loadballance 類型的svc,暫時不做了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章