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. 加入聯邦
-
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
-
-
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
會發現這個命令
- 會在主集羣創建一個CRD, for the federated type 叫
FederatedDeployments
,group默認: types.kubefed.io - 同時創建一個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,暫時不做了。