12.k8s之kube-dns

转载:
https://hansedong.github.io/2018/11/20/9/
https://hansedong.github.io/2018/11/22/10/

文章目录

kube-dns

作用:主要监听了两个资源

  • Service资源
  • Endpoints资源

为什么需要监控 Endpoints 资源?

// 开启一个 KubeDNS 处理实例
func NewKubeDNS(client clientset.Interface, clusterDomain string, timeout time.Duration, configSync config.Sync) *KubeDNS {
    kd := &KubeDNS{
        kubeClient:          client,
        domain:              clusterDomain,
        cache:               treecache.NewTreeCache(),
        cacheLock:           sync.RWMutex{},
        nodesStore:          kcache.NewStore(kcache.MetaNamespaceKeyFunc),
        reverseRecordMap:    make(map[string]*skymsg.Service),
        clusterIPServiceMap: make(map[string]*v1.Service),
        domainPath:          util.ReverseArray(strings.Split(strings.TrimRight(clusterDomain, "."), ".")),
        initialSyncTimeout:  timeout,

        configLock: sync.RWMutex{},
        configSync: configSync,
    }

  // 监听并处理 Endpoints 资源
    kd.setEndpointsStore()
    // 监听并处理 Services 资源
    kd.setServicesStore()

    return kd
}
// setServicesStore 负责处理 Service 资源
func (kd *KubeDNS) setServicesStore() {
    // Returns a cache.ListWatch that gets all changes to services.
    kd.servicesStore, kd.serviceController = kcache.NewInformer(
        kcache.NewListWatchFromClient(
            kd.kubeClient.Core().RESTClient(),
            "services",
            v1.NamespaceAll,
            fields.Everything()),
        &v1.Service{},
        resyncPeriod,
        // 这里也可以看出来,它其实主要针对 Service 的 增删改做 handle 处理
        kcache.ResourceEventHandlerFuncs{
            AddFunc:    kd.newService,
            DeleteFunc: kd.removeService,
            UpdateFunc: kd.updateService,
        },
    )
}

// 同上
func (kd *KubeDNS) setEndpointsStore() {
    // Returns a cache.ListWatch that gets all changes to endpoints.
    kd.endpointsStore, kd.endpointsController = kcache.NewInformer(
        kcache.NewListWatchFromClient(
            kd.kubeClient.Core().RESTClient(),
            "endpoints",
            v1.NamespaceAll,
            fields.Everything()),
        &v1.Endpoints{},
        resyncPeriod,
        kcache.ResourceEventHandlerFuncs{
            AddFunc:    kd.handleEndpointAdd,
            UpdateFunc: kd.handleEndpointUpdate,
            // If Service is named headless need to remove the reverse dns entries.
            DeleteFunc: kd.handleEndpointDelete,
        },
    )
}

我们看一下,如果 K8S 有 Service 资源创建出来,kube-dns 容器都做些什么

// 针对 K8S 中 Service 资源的创建,做处理
func (kd *KubeDNS) newService(obj interface{}) {
    if service, ok := assertIsService(obj); ok {
        glog.V(3).Infof("New service: %v", service.Name)
        glog.V(4).Infof("Service details: %v", service)

    // 1、如果 Service 是 ExternaName 类型,则创建 cname 记录
    // 稍微提一下,K8S 中的 Service,有几种类型:ClusterIP、NodePort、LoadBalancer、ExternaName
    
        // ExternalName services are a special kind that return CNAME records
        if service.Spec.Type == v1.ServiceTypeExternalName {
            kd.newExternalNameService(service)
            return
        }
    
        // 2、如果是无头服务,则处理无头服务方式的DNS记录(A记录),无头服务的域名记录有些不同,所以这里是单独进行处理的
        // 需要说明的是,我们刚刚提到的 Endpoints 资源,其实主要就是用在无头服务上的。
        
        // if ClusterIP is not set, a DNS entry should not be created
        if !v1.IsServiceIPSet(service) {
            if err := kd.newHeadlessService(service); err != nil {
                glog.Errorf("Could not create new headless service %v: %v", service.Name, err)
            }
            return
        }
        if len(service.Spec.Ports) == 0 {
            glog.Warningf("Service with no ports, this should not have happened: %v",
                service)
        }
        
        // 3、创建正常的 Service DNS 记录
        kd.newPortalService(service)
    }
}

上面提到,Service 的创建操作,会涉及到 newHeadlessService 无头服务域名记录的操作,具体如下:

// 创建无头服务Service的域名记录

// Generates skydns records for a headless service.
func (kd *KubeDNS) newHeadlessService(service *v1.Service) error {
    // Create an A record for every pod in the service.
    // This record must be periodically updated.
    // Format is as follows:
    // For a service x, with pods a and b create DNS records,
    // a.x.ns.domain. and, b.x.ns.domain.
    key, err := kcache.MetaNamespaceKeyFunc(service)
    if err != nil {
        return err
    }
    
    // 根据 Service 名称获取key,在根据 Key,获取这个 Service 下的 Endpoints,用来生成特殊的无头服务的域名记录
    e, exists, err := kd.endpointsStore.GetByKey(key)
    if err != nil {
        return fmt.Errorf("failed to get endpoints object from endpoints store - %v", err)
    }
    // 如果这个 Service 下没有 Endpoints,将不生成域名记录,一旦有endpoints之后,就会生成。
    if !exists {
        glog.V(1).Infof("Could not find endpoints for service %q in namespace %q. DNS records will be created once endpoints show up.",
            service.Name, service.Namespace)
        return nil
    }
    if e, ok := e.(*v1.Endpoints); ok {
        return kd.generateRecordsForHeadlessService(e, service)
    }
    return nil
}

如果 Service 下没有Endpoints,不处理,一旦有 Endpoints 产生,立即生成域名记录:

// 根据 Endpoints,创建无头服务记录
func (kd *KubeDNS) addDNSUsingEndpoints(e *v1.Endpoints) error {
  // 先根据 Endpoints 超出其属于哪个 Service
    svc, err := kd.getServiceFromEndpoints(e)
    if err != nil {
        return err
    }
    // 判断这个 Service 是不是无头服务的 Service,如果不是,直接返回
    if svc == nil || v1.IsServiceIPSet(svc) || svc.Spec.Type == v1.ServiceTypeExternalName {
        // No headless service found corresponding to endpoints object.
        return nil
    }
    // 如果是无头服务的 Service,生成域名记录
    return kd.generateRecordsForHeadlessService(e, svc)
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值