《使用 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 可使用 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 是一个二进制程序,能够在 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>
复制代码
其中 可使用如下的描述:
好比咱们须要把 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
类型的必需字段,好比:placement
、overrides
等。
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
复制代码
不过有两点要注意:
clusters
字段被指定,clusterSelector
将会被忽略若是须要在多个集群间进行区别调度的话就须要引入 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
复制代码
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
复制代码