k8s实践(11) --服务发现CoreDNS详解

栏目: IT技术 · 发布时间: 5年前

内容简介:参考:从Kubernetes 1.11开始,可使用CoreDNS作为Kubernetes的DNS插件进入GA状态,Kubernetes推荐使用CoreDNS作为集群内的DNS服务。 我们先看一下Kubernetes DNS服务的发展历程。Kubernetes 1.3之前的版本使用skyDNS作为DNS服务,这个有点久远了。Kubernetes的DNS服务由kube2sky、skyDNS、etcd组成。 kube2sky通过kube-apiserver监听集群中Service的变化,将生成的DNS记录信息更新

参考:

一.Kubernetes DNS服务发展史

从Kubernetes 1.11开始,可使用CoreDNS作为Kubernetes的DNS插件进入GA状态,Kubernetes推荐使用CoreDNS作为集群内的DNS服务。 我们先看一下Kubernetes DNS服务的发展历程。

1.1 Kubernetes 1.3之前的版本 – skyDNS

Kubernetes 1.3之前的版本使用skyDNS作为DNS服务,这个有点久远了。Kubernetes的DNS服务由kube2sky、skyDNS、etcd组成。 kube2sky通过kube-apiserver监听集群中Service的变化,将生成的DNS记录信息更新到etcd中,而skyDNS将从etcd中获取数据对外提供DNS的查询服务。

1.2 Kubernetes 1.3版本开始 – kubeDNS

Kubernetes 1.3开始使用kubeDNS和dnsmasq替换了原来的kube2sky和skyDNS,不再使用etcd,而是将DNS记录直接存放在内存中,通过dnsmasq的缓存功能提高DNS的查询效率。下图是描述了Kubernetes使用kubeDNS实现服务发现的整体架构:

k8s实践(11) --服务发现CoreDNS详解

1.3 Kubernetes 1.11版本开始 – CoreDNS进入GA

从Kubernetes 1.11开始,可使用CoreDNS作为Kubernetes的DNS插件进入GA状态,Kubernetes推荐使用CoreDNS作为集群内的DNS服务。 CoreDNS从2017年初就成为了CNCF的的孵化项目,CoreDNS的特点就是十分灵活和可扩展的插件机制,

各种插件实现:

k8s实践(11) --服务发现CoreDNS详解

不同的功能,如重定向、定制DNS记录、记录日志等等。下图描述了CoreDNS的整体架构:

k8s实践(11) --服务发现CoreDNS详解

二、CoreDNS简介

Kubernetes包括用于服务发现的DNS服务器Kube-DNS。 该DNS服务器利用SkyDNS的库来为Kubernetes pod和服务提供DNS请求。SkyDNS2的作者,Miek Gieben,创建了一个新的DNS服务器,CoreDNS,它采用更模块化,可扩展的框架构建。 Infoblox已经与Miek合作,将此DNS服务器作为Kube-DNS的替代品。

CoreDNS利用作为Web服务器Caddy的一部分而开发的服务器框架。该框架具有非常灵活,可扩展的模型,用于通过各种中间件组件传递请求。这些中间件组件根据请求提供不同的操作,例如记录,重定向,修改或维护 。虽然它一开始作为Web服务器,但是Caddy并不是专门针对HTTP协议的,而是构建了一个基于CoreDNS的理想框架。

在这种灵活的模型中添加对Kubernetes的支持,相当于创建了一个Kubernetes中间件。该中间件使用Kubernetes API来满足针对特定Kubernetes pod或服务的DNS请求。而且由于Kube-DNS作为Kubernetes的另一项服务,kubelet和Kube-DNS之间没有紧密的绑定。您只需要将DNS服务的IP地址和域名传递给kubelet,而Kubernetes并不关心谁在实际处理该IP请求。

1、CoreDNS支持行为

1.0.0版本主要遵循Kube-DNS的当前行为。 CoreDNS的005及更高版本实现了完整的规范和更多功能。

  • A记录(正常的Service分配了一个名为my-svc.my-namespace.svc.cluster.local的DNS A记录。 这解决了服务的集群IP)
  • “headless”(没有集群IP)的Service也分配了一个名为my-svc.my-namespace.svc.cluster.local的DNS A记录。 与普通服务不同,这解决了Service选择了pods的一组IP。 客户预计将从这ip集合中消耗集合或使用标准循环选择。
  • 针对名为正常或无头服务的端口创建的SRV记录,对于每个命名的端口,SRV记录的格式为_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster.local。对于常规服务,这将解析为端口号和CNAME:my-svc.my-namespace.svc.cluster.local;对于无头服务,这解决了多个答案,一个用于支持服务的每个pod,并包含端口号还有格式为auto-generated-name.my-svc.my-namespace.svc.cluster.local 的pod的CNAME 。SRV记录包含它们中的“svc”段,对于省略“svc”段的旧式CNAME不支持。
  • 作为Service一部分的endpoints的A记录(比如“pets”的记录)
  • pod的Spec中描述的A记录
  • 还有就是用来发现正在使用的DNS模式版本的TXT记录

所有群集中不需要pod A记录支持,默认情况下禁用。 此外,CoreDNS对此用例的支持超出了在Kube-DNS中找到的标准行为。

在Kube-DNS中,这些记录不反映集群的状态,例如,对w-x-y-z.namespace.pod.cluster.local的任何查询将返回带有w.x.y.z(ip)的A记录,即使该IP不属于指定的命名空间,甚至不属于集群地址空间。最初的想法是启用对* .namespace.pod.cluster.local这样的域使用通配符SSL证书。

CoreDNS集成了提供pod验证的选项,验证返回的IP地址w.x.y.z实际上是指定命名空间中的pod的IP。他防止在命名空间中欺骗DNS名称。 然而,它确实会大大增加CoreDNS实例的内存占用,因为现在它需要观察所有的pod,而不仅仅是服务端点。

2、架构

整个 CoreDNS 服务都建立在一个使用 Go 编写的 HTTP/2 Web 服务器 Caddy · GitHub 上,CoreDNS 整个项目可以作为一个 Caddy 的教科书用法。

k8s实践(11) --服务发现CoreDNS详解

CoreDNS 的大多数功能都是由插件来实现的,插件和服务本身都使用了 Caddy 提供的一些功能,所以项目本身也不是特别的复杂。

3、插件

作为基于 Caddy 的 Web 服务器,CoreDNS 实现了一个插件链的架构,将很多 DNS 相关的逻辑都抽象成了一层一层的插件,包括 Kubernetes 等功能,每一个插件都是一个遵循如下协议的结构体:

type (
	Plugin func(Handler) Handler

	Handler interface {
		ServeDNS(context.Context, dns.ResponseWriter, *dns.Msg) (int, error)
		Name() string
	}
)

所以只需要为插件实现 ServeDNS 以及  Name 这两个接口并且写一些用于配置的代码就可以将插件集成到 CoreDNS 中。

4、Corefile

另一个 CoreDNS 的特点就是它能够通过简单易懂的 DSL 定义 DNS 服务,在 Corefile 中就可以组合多个插件对外提供服务:

coredns.io:5300 {
    file db.coredns.io
}

example.io:53 {
    log
    errors
    file db.example.io
}

example.net:53 {
    file db.example.net
}

.:53 {
    kubernetes
    proxy . 8.8.8.8
    log
    errors
    cache
}

对于以上的配置文件,CoreDNS 会根据每一个代码块前面的区和端点对外暴露两个端点提供服务:

k8s实践(11) --服务发现CoreDNS详解

该配置文件对外暴露了两个 DNS 服务,其中一个监听在 5300 端口,另一个在 53 端口,请求这两个服务时会根据不同的域名选择不同区中的插件进行处理。

原理

CoreDNS 可以通过四种方式对外直接提供 DNS 服务,分别是 UDP、gRPC、HTTPS 和 TLS:

k8s实践(11) --服务发现CoreDNS详解

但是无论哪种类型的 DNS 服务,最终队会调用以下的 ServeDNS 方法,为服务的调用者提供 DNS 服务:

func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) {
	m, _ := edns.Version(r)

	ctx, _ := incrementDepthAndCheck(ctx)

	b := r.Question[0].Name
	var off int
	var end bool

	var dshandler *Config

	w = request.NewScrubWriter(r, w)

	for {
		if h, ok := s.zones[string(b[:l])]; ok {
			ctx = context.WithValue(ctx, plugin.ServerCtx{}, s.Addr)
			if r.Question[0].Qtype != dns.TypeDS {
				rcode, _ := h.pluginChain.ServeDNS(ctx, w, r)
 			dshandler = h
		}
		off, end = dns.NextLabel(q, off)
		if end {
			break
		}
	}

	if r.Question[0].Qtype == dns.TypeDS && dshandler != nil && dshandler.pluginChain != nil {
		rcode, _ := dshandler.pluginChain.ServeDNS(ctx, w, r)
		plugin.ClientWrite(rcode)
		return
	}

	if h, ok := s.zones["."]; ok && h.pluginChain != nil {
		ctx = context.WithValue(ctx, plugin.ServerCtx{}, s.Addr)

		rcode, _ := h.pluginChain.ServeDNS(ctx, w, r)
		plugin.ClientWrite(rcode)
		return
	}
}

在上述这个已经被简化的复杂函数中,最重要的就是调用了『插件链』的 ServeDNS 方法,将来源的请求交给一系列插件进行处理,如果我们使用以下的文件作为 Corefile:

example.org {
    file /usr/local/etc/coredns/example.org
    prometheus     # enable metrics
    errors         # show errors
    log            # enable query logs
}

那么在 CoreDNS 服务启动时,对于当前的 example.org 这个组,它会依次加载  filelogerrors 和  prometheus 几个插件,这里的顺序是由 zdirectives.go 文件定义的,启动的顺序是从下到上:

var Directives = []string{
  // ...
	"prometheus",
	"errors",
	"log",
  // ...
	"file",
  // ...
	"whoami",
	"on",
}

因为启动的时候会按照从下到上的顺序依次『包装』每一个插件,所以在真正调用时就是从上到下执行的,这就是因为 NewServer 方法中对插件进行了组合:

func NewServer(addr string, group []*Config) (*Server, error) {
	s := &Server{
		Addr:        addr,
		zones:       make(map[string]*Config),
		connTimeout: 5 * time.Second,
	}

	for _, site := range group {
		s.zones[site.Zone] = site
		if site.registry != nil {
			for name := range enableChaos {
				if _, ok := site.registry[name]; ok {
					s.classChaos = true
					break
				}
			}
		}
		var stack plugin.Handler
		for i := len(site.Plugin) - 1; i >= 0; i-- {
			stack = site.Plugin[i](stack)
			site.registerHandler(stack)
		}
		site.pluginChain = stack
	}

	return s, nil
}

对于 Corefile 里面的每一个配置组, NewServer 都会讲配置组中提及的插件按照一定的顺序组合起来,原理跟 Rack Middleware 的机制非常相似,插件  Plugin 其实就是一个出入参数都是  Handler 的函数:

type (
	Plugin func(Handler) Handler

	Handler interface {
		ServeDNS(context.Context, dns.ResponseWriter, *dns.Msg) (int, error)
		Name() string
	}
)

所以我们可以将它们叠成堆栈的方式对它们进行操作,这样在最后就会形成一个插件的调用链,在每个插件执行方法时都可以通过 NextOrFailure 函数调用下一个插件的  ServerDNS 方法:

func NextOrFailure(name string, next Handler, ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
	if next != nil {
		if span := ot.SpanFromContext(ctx); span != nil {
			child := span.Tracer().StartSpan(next.Name(), ot.ChildOf(span.Context()))
			defer child.Finish()
			ctx = ot.ContextWithSpan(ctx, child)
		}
		return next.ServeDNS(ctx, w, r)
	}

	return dns.RcodeServerFailure, Error(name, errors.New("no next plugin found"))
}

除了通过 ServeDNS 调用下一个插件之外,我们也可以调用  WriteMsg 方法并结束整个调用链。

k8s实践(11) --服务发现CoreDNS详解

从插件的堆叠到顺序调用以及错误处理,我们对 CoreDNS 的工作原理已经非常清楚了,接下来我们可以简单介绍几个插件的作用。

三、在kubernetes中部署coredns

1、下载coredns部署包并说明

https://github.com/coredns/deployment/tree/master/kubernetes

主要有几个文件:

k8s实践(11) --服务发现CoreDNS详解

deploy.sh是一个便捷的脚本,用于生成用于在当前运行标准kube-dns的集群上运行CoreDNS的清单。使用coredns.yaml.sed文件作为模板,它创建一个ConfigMap和一个CoreDNS  deployment,然后更新 Kube-DNS service selector以使用CoreDNS deployment。 通过重新使用现有服务,服务请求不会中断。

脚本不会删除kube-dns的deployment或replication controller - 您必须手动执行:

kubectl delete --namespace=kube-system deployment kube-dns

要使用它,只需将它们放在同一目录中,然后运行deploy.sh脚本 ,将其传递给您的服务CIDR(10.3.0.0/24) 。 这将生成具有必要Corefile的ConfigMap。 它还将查找现有的kube-dns服务的集群IP。 

[root@k8s-master conf.d]# etcdctl ls /k8s/network/subnets  /k8s/network/subnets/10.0.24.0-24  /k8s/network/subnets/10.0.86.0-24  /k8s/network/subnets/10.0.35.0-24

(注意:以上原始脚本只适用于当前kubernetes集群含有kube-dns的情况,如果没有需要修改下脚本

#!/bin/bash

# Deploys CoreDNS to a cluster currently running Kube-DNS.

SERVICE_CIDR=$1
CLUSTER_DOMAIN=${2:-cluster.local}
YAML_TEMPLATE=${3:-`pwd`/coredns.yaml.sed}
YAML=${4:-`pwd`/coredns.yaml}

if [[ -z $SERVICE_CIDR ]]; then
echo "Usage: $0 SERVICE-CIDR [ CLUSTER-DOMAIN ] [ YAML-TEMPLATE ] [ YAML ]"
exit 1
fi

#CLUSTER_DNS_IP=$(kubectl get service --namespace kube-system kube-dns -o jsonpath="{.spec.clusterIP}")
CLUSTER_DNS_IP=
10.0.24.200

默认情况下CLUSTER_DNS_IP是自动获取kube-dns的集群ip的,但是由于没有部署kube-dns所以只能手动指定一个集群ip了。

执行: ./deploy.sh 10.0.0.0/24 cluster.local 

以上脚本执行后可以看到预览的效果。

仔细观察上面的Corefile部分,这是一个在端口53上运行CoreDNS并为Kubernetes提供cluster.local域的示例

.:53 {
        errors
        log stdout
        health
        kubernetes cluster.local 10.3.0.0/24
        proxy . /etc/resolv.conf
        cache 30
    }

1)errors官方没有明确解释,后面研究

2)log stdout:日志中间件配置为将日志写入STDOUT

3)health:健康检查,提供了指定端口(默认为8080)上的HTTP端点,如果实例是健康的,则返回“OK”。

4)cluster.local:CoreDNS为kubernetes提供的域,10.3.0.0/24这告诉Kubernetes中间件它负责为反向区域提供PTR请求0.0.3.10.in-addr.arpa ..换句话说,这是允许反向DNS解析服务(我们经常使用到得DNS服务器里面有两个区域,即“正向查找区域”和“反向查找区域”,正向查找区域就是我们通常所说的域名解析,反向查找区域即是这里所说的IP反向解析,它的作用就是通过查询IP地址的PTR记录来得到该IP地址指向的域名,当然,要成功得到域名就必需要有该IP地址的PTR记录。PTR记录是邮件交换记录的一种,邮件交换记录中有A记录和PTR记录,A记录解析名字到地址,而PTR记录解析地址到名字。地址是指一个客户端的IP地址,名字是指一个客户的完全合格域名。通过对PTR记录的查询,达到反查的目的。)

5)proxy:这可以配置多个upstream 域名服务器,也可以用于延迟查找 /etc/resolv.conf 中定义的域名服务器

6)cache:这允许缓存两个响应结果,一个是肯定结果(即,查询返回一个结果)和否定结果(查询返回“没有这样的域”),具有单独的高速缓存大小和TTLs。

2、现在安装coredns到kubernetes中

#    ./deploy.sh -r 10.0.0.0/16 -i 192.168.10.90  -d cluster.local -t coredns.yaml.sed -s  > coredns.yaml

#   .kubectl apply -f coredns.yaml

或者直接执行:

# ./deploy.sh -r 10.0.0.0/16 -i 192.168.10.90  -d cluster.local -t coredns.yaml.sed -s  | kubectl apply -f -

查看service

[root@k8s-master coredns]# kubectl get service -l k8s-app=kube-dns --namespace=kube-system  NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE  kube-dns   ClusterIP   192.168.10.90   <none>        53/UDP,53/TCP,9153/TCP   15d

查看coredns的Pod,确认所有Pod都处于Running状态:

kubectl get pods -n kube-system -l k8s-app=kube-dns
查看日志:# kubectl logs -f coredns-6cc7bf59f4-4rfq8 --namespace=kube-system

3、修改cluster-dns

修改master节点和所有node节点--cluster-dns配置,修改内容如红色所注,与上面的Corefile中的值对应。

k8s实践(11) --服务发现CoreDNS详解

4、测试CoreDNS

现在我们来创建一个wepapp的pod和service,测试一下coredns是否起作用

[root@k8s-master conf.d]# kubectl get pods  -o wide

NAME           READY     STATUS    RESTARTS   AGE       IP          NODE

webapp-nrz4t   1/1       Running   0          1d        10.0.35.3   192.168.10.39

webapp-zp69q   1/1       Running   0          1d        10.0.24.4   192.168.10.50

[root@k8s-master ~]# kubectl get svc

NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE

kubernetes   ClusterIP   192.168.0.1      <none>        443/TCP    28d

webapp       ClusterIP   192.168.14.242   <none>        9081/TCP   17d

webapp2      ClusterIP   192.168.22.2     <none>        9082/TCP   17d

[root@k8s-master ~]# curl 192.168.22.2:9082

Hello world

k8s实践(11) --服务发现CoreDNS详解

1、检查集群的pod /etc/resolv.conf是否生效:

首先进入这个集群内的另一个pod

kubectl exec -it webapp-nrz4t /bin/sh 或者 docker exec -it 0d0874df9e15 /bin/sh

$ cat /etc/resolv.conf

sh-4.2#  cat /etc/resolv.conf

nameserver 192.168.10.90

search default.svc.cluster.local svc.cluster.local cluster.local

options ndots:5

2、curl测试服务:

curl webapp.default.svc.cluster.local:9081

3、在master的主机上修改 /etc/resolv.conf,增加一行:nameserver 192.168.10.90后执行

curl webapp.default.svc.cluster.local:9081

k8s实践(11) --服务发现CoreDNS详解

通过域名访问成功!

问题排查技巧

如果执行 nslookup 命令失败,检查如下内容:

1、先检查本地 DNS 配置

查看配置文件 resolv.conf。

k8s实践(11) --服务发现CoreDNS详解

按照如下方法(注意搜索路径可能会因为云提供商不同而变化)验证搜索路径和 Name Server 的建立:

nameserver 192.168.10.90

search default.svc.cluster.local svc.cluster.local cluster.local

options ndots:5

2、快速诊断

出现类似如下指示的错误,说明 kube-dns 插件或相关 Service 存在问题:

k8s实践(11) --服务发现CoreDNS详解

检查service是否正常运行:

kubectl get svc --namespace=kube-system

k8s实践(11) --服务发现CoreDNS详解

或者检查是否 DNS Pod 正在运行

使用 kubectl get pods 命令验证 DNS Pod 正在运行:

kubectl get pods --namespace=kube-system -l k8s-app=kube-dns

应该能够看到类似如下信息:

k8s实践(11) --服务发现CoreDNS详解

如果看到没有 Pod 运行,或 Pod 失败/结束,DNS 插件不能默认部署到当前的环境,必须手动部署。

或者查看service的Endpoint是否正常:

kubectl get ep kube-dns --namespace=kube-system

k8s实践(11) --服务发现CoreDNS详解

如果没有看到 Endpoint,查看 调试 Service 文档 中的 Endpoint 段内容。

3、检查 DNS Pod 中的错误信息

使用 kubectl logs  命令查看 DNS 后台进程的日志:

kubectl logs coredns-6cc7bf59f4-vj7cc -n kube-system

看到错误信息:

eflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Namespace: Get https://192.168.0.1:443/api/v1/namespace

2.168.0.1:443/api/v1/endpoints?limit=500&resourceVersion=0: x509: certificate is valid for 192.168.10.50, 10.0.0.1, not 192.168.0.1
E0710 16:00:58.986103       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Namespace: Get https://192.168.0.1:443/api/v1/namespaces?limit=500&resourceVersion=0: x509: certificate is valid for 192.168.10.50, 10.0.0.1, not 192.168.0.1
E0710 16:00:58.989633       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Service: Get https://192.168.0.1:443/api/v1/services?limit=500&resourceVersion=0: x509: certificate is valid for 192.168.10.50, 10.0.0.1, not 192.168.0.1
E0710 16:00:58.991655       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Endpoints: Get https://192.168.0.1:443/api/v1/endpoints?limit=500&resourceVersion=0: x509: certificate is valid for 192.168.10.50, 10.0.0.1, not 192.168.0.1
E0710 16:00:59.990732       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+inco

原因:192.168.0.1不在证书里面

解决:需要重新设置:apiserver证书

masterssl.cnf文件的示例如下:IP.3 = 192.168.0.1

[req]  req_extensions = v3_req  distinguished_name = req_distinguished_name  [req_distinguished_name]  [ v3_req ]  basicConstraints = CA:FALSE  keyUsage = nonRepudiation, digitalSignature, keyEncipherment  subjectAltName = @alt_names  [alt_names]  DNS.1 = kubernetes  DNS.2 = kubernetes.default  DNS.3 = kubernetes.default.svc  DNS.4 = kubernetes.default.svc.cluster.local  IP.1 = ${K8S_SERVICE_IP}  IP.2 = ${MASTER_IPV4}
IP.3 = 192.168.0.1

错误信息:

E0712 02:25:45.326123       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Service: Unauthorized

E0712 02:25:45.327038       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Endpoints: Unauthorized

E0712 02:25:45.328029       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Namespace: Unauthorized

E0712 02:25:46.327153       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Service: Unauthorized

E0712 02:25:46.328210       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Endpoints: Unauthorized

E0712 02:25:46.329160       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Namespace: Unauthorized

E0712 02:25:47.328243       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Service: Unauthorized

E0712 02:25:47.329143       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Endpoints: Unauthorized

E0712 02:25:47.330086       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Namespace: Unauthorized

原因:service account 的token认知不通过,是因为重新生成证书后,需要删除旧的token。

解决:

kubectl get secret -n kube-system

NAME                  TYPE                                  DATA      AGE

coredns-token-cdn9x   kubernetes.io/service-account-token   3         3d

default-token-lht2v   kubernetes.io/service-account-token   3         3d

kubectl delete secret coredns-token-cdn9x  -n kube-system

secret "coredns-token-cdn9x" deleted


以上所述就是小编给大家介绍的《k8s实践(11) --服务发现CoreDNS详解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Beginning Google Maps API 3

Beginning Google Maps API 3

Gabriel Svennerberg / Apress / 2010-07-27 / $39.99

This book is about the next generation of the Google Maps API. It will provide the reader with the skills and knowledge necessary to incorporate Google Maps v3 on web pages in both desktop and mobile ......一起来看看 《Beginning Google Maps API 3》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具