联邦DNS原理

在多集群中,一个FederatedDeploymentPod会存在多个集群中,那么我们如何提供一个固定的访问地址呢?

ServiceDNS

在单集群中,我们可以为每个Deployment创建一个同名的Service,然后就可以通过<service>.<namespace>.svc.cluster.local的方式来访问这个服务。

同理在联邦中,我们可以为每个FederatedDeployment创建一个同名的FederatedService,然后希望可以通过<federatedservice>.<namespace>.svc.example.com的方式来访问这个服务。接下来,我们来看看ServiceDNS是如达到这个效果的。

首先,我们要求每个工作集群使用LoadBalancer的方式对外暴露服务,也就是说FederatedService的类型要为LoadBalancer。此时,对于这个服务,每个工作集群都会有一个ExternalIP。然后,域名<federatedservice>.<namespace>.svc.example.com会被解析为这N个ExternalIP。

然后,上面的example.com从哪里来?很简单,我们创建一个Domain对象(需要注意它的namespace要与federation-controller-manager的一致)

接着,我们就可以为FederatedService(假设名字为test-service,命名空间为test-namespace)创建一条DNS记录,通过创建如下资源

然后DNSEndpoint Controller就会在自动创建一个如下的DNSEndpoint

然后ExternalDNS-Controller监听到这个DNSEndpoint后,就会往etcd写如下两条数据(以/skydns开头):

$ export ETCDCTL_API=3
$ etcdctl get /skydns --prefix 
/skydns/com/example/svc/test-domain/test-namespace/test-service
{"host":"<Cluster1-ExternalIP>","ttl":300,"targetstrip":1}
/skydns/com/example/svc/test-domain/test-namespace/test-service
{"host":"<Cluster2-ExternalIP>","ttl":300,"targetstrip":1}

然后,CoreDNS就会从etcd中读取以/skydns开头的数据,从后往前组成两条A记录:

<Cluster1-ExternalIP> test-service.test-namespace.test-domain.svc.example.com 
<Cluster2-ExternalIP> test-service.test-namespace.test-domain.svc.example.com

总结来说,ServiceDNS的核心如下:

  • 工作集群以LoadBalancer的方式暴露服务,即工作集群上的服务可以通过<exteranalIP>:<containerPort>的方式来访问

  • 抽象一个域名<federatedservice>.<namespace>.domain.svc.example.com,它可以解析到成N个ExternalIP中的一个,然后对外可以统一通过<federatedservice>.<namespace>.domain.svc.example.com:<containerPort>来访问

IngressDNS

上面ServiceDNS是用于四层负载;在此的基础上,我们可以这样子设计七层负载:

  • 每个工作集群以Ingress的方式暴露服务,即工作集群上的服务可以通过http://<ingress-controller-ip>、请求头携带"Host":"<containerPort>.<service>.<namespace>.example.com"来访问。

  • 抽象一个域名<containerPort>.<federatedservice>.<namespace>.example.com作为统一的对外访问方式,<containerPort>.<federatedservice>.<namespace>.example.com会被解析到三个ingress-controller-ip中的一个

example.com如何配置?

当创建了一个新的FederatedService时,同时还需要在相同的命名空间下创建一个ServiceDNSRecord,表示这个FederatedService的域名

当发布一个FederatedService时,CoreDNS如何找到每个工作节点上该服务的对外IP?

当创建了一个新的FederatedService时,federation-controller-manager会创建一个Endpoint,包含了每个工作集群该服务的IP(使用命令kubectl get dnsendpoint -n <namespace>查看)。CoreDNS也会监听FederatedService的创建,然后找到对应的DNSEndpoint

排错步骤

  • 手动往etcd中添加一条记录,看coredns能否解析;参考https://www.cnblogs.com/boshen-hzb/p/7541901.html

    A:经实验只要是/skydns/com/example/开头的,可以正常解析。

  • 手动往dnsendpoint中添加A记录,看externaldns能否正常地往etcd写数据;参考https://github.com/kubernetes-sigs/kubefed/blob/v0.0.10/docs/servicedns-with-externaldns.md

    A:可以正常写。只是不知道为什么会写很多条,而且后面还会多了一个随机数

  • 查找dnsendpoint没能成功添加serviceIP的原因

    A:猜测应该是dnsendpoint-controller有问题,这个controller应该是在federation-controller-manager里面吧?

Reference

Last updated

Was this helpful?