背景是我们希望能在k8s中通过DNS方式,访问服务的FQDN来调用虚拟机注册到nacos的服务。
我们vm和k8s的网段配置了相关路由能相互访问
之前nacos有维护了一个同步去coredns的项目,但是年久失修,支持的nacos版本和coredns版本都不高。后面在官方文档找资料的时候,发现nacos是支持istio MCP协议的 Pilot MCP协议介绍 ,于是采取这个方案来完成目标。《Nacos 1.1.4发布,业界率先支持Istio MCP协议 》
环境:
istio: 1.10
nacos: 2.1.0
配置nacos开启MCP Server 进入nacos配置目录,执行以下命令,把 nacos.istio.mcp.server.enabled
值设置为 true。重启nacos server 让它运行MCP Server。
1 [root@dev_10.1.10.209 nacos]#sed -i 's/nacos.istio.mcp.server.enabled=false/nacos.istio.mcp.server.enabled=true/g' conf/application.properties
重启后nacos MCP server会监听 18848
端口
1 2 3 [root@dev_10.1.10.209 nacos]#lsof -i:18848 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME java 98108 root 171u IPv4 834348182 0t0 TCP *:18848 (LISTEN)
配置istio添加MCP server sources 我测试的nacos server所在的服务器IP10.1.10.209
nacos MCP server监听的端口 18848
编辑istio的configmap,添加以下配置
1 kubectl edit -n istio-system cm istio
1 2 configSources: - address: xds://10.1.10.209:18848
添加后的配置大概如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 apiVersion: v1 data: mesh: |- accessLogFile: /dev/stdout configSources: - address: xds://10.1.10.209:18848 defaultConfig: discoveryAddress: istiod.istio-system.svc:15012 proxyMetadata: {} tracing: zipkin: address: zipkin.istio-system:9411 enablePrometheusMerge: true rootNamespace: istio-system trustDomain: cluster.local meshNetworks: 'networks: {}'
重启下istiod 连接MCP server同步信息
1 kubectl rollout restart -n istio-system deployment istiod
服务访问 同步nacos服务信息到istio后,我们可以在服务的sidecar envoy看到同步下来的服务配置信息。
如以下是我 ops-apollo-probe
服务的pod ops-apollo-probe-7765fd445f-smstf
的envoy配置信息,搜索nacos后的结果。
1 2 3 4 5 6 7 ➜ ~ istioctl pc all -n develop ops-apollo-probe-7765fd445f-smstf|grep nacos msg-group.DEFAULT-GROUP.public.nacos 80 - outbound EDS nacos-test.develop.svc.cluster.local.DEFAULT-GROUP.public.nacos 80 - outbound EDS nacos-vm.DEFAULT-GROUP.public.nacos 7788 - outbound EDS 80 msg-group.DEFAULT-GROUP.public.nacos /* 80 nacos-test.develop.svc.cluster.local.DEFAULT-GROUP.public.nacos, nacos-test + 1 more... /* 7788 nacos-vm.DEFAULT-GROUP.public.nacos /*
带着 nacos结尾的域名就是nacos同步下来的,比如 nacos-vm.DEFAULT-GROUP.public.nacos
但是现在,在我ops-apollo-probe容器里面,依旧是无法通过nacos-vm.DEFAULT-GROUP.public.nacos
访问到我的 nacos-vm服务的。
因为现在大概的访问流程是这样的,详情见Understanding DNS - istio
因为coredns中并没有 nacos-vm.DEFAULT-GROUP.public.nacos
的解析,所以解析失败,报错退出。
以下为在ops-apollo-probe服务的容器内请求:
1 2 3 4 5 6 7 8 9 10 11 /app # curl -v nacos-vm.DEFAULT-GROUP.public.nacos:7788/healthz * Could not resolve host: nacos-vm.DEFAULT-GROUP.public.nacos * Closing connection 0 curl: (6) Could not resolve host: nacos-vm.DEFAULT-GROUP.public.nacos /app # nslookup nacos-vm.DEFAULT-GROUP.public.nacos Server: 10.17.0.10 Address: 10.17.0.10:53 ** server can't find nacos-vm.DEFAULT-GROUP.public.nacos: NXDOMAIN ** server can't find nacos-vm.DEFAULT-GROUP.public.nacos: NXDOMAIN
curl显示不能解析,nslookup没解析出IP,可以看到nameserver是coredns的IP(10.17.0.10)。
1 2 3 ➜ ~ kubectl get svc -n kube-system kube-dns NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.17.0.10 <none> 53/UDP,53/TCP 35d
所以要解决访问,还要能有个IP把包先发出去,到istio sidecar接管请求后就完事,因为envoy有服务的真正IP信息。
所以我们可以瞎指定一个IP,比如1.1.1.1。
hosts大法指定IP 域名解析,hosts文件的记录优先级高于nameserver的记录
1 2 # 添加hosts /app # echo '1.1.1.1 nacos-vm.DEFAULT-GROUP.public.nacos' >> /etc/hosts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /app # curl -v nacos-vm.DEFAULT-GROUP.public.nacos:7788/healthz * Trying 1.1.1.1:7788... * Connected to nacos-vm.DEFAULT-GROUP.public.nacos (1.1.1.1) port 7788 (#0) > GET /healthz HTTP/1.1 > Host: nacos-vm.DEFAULT-GROUP.public.nacos:7788 > User-Agent: curl/7.80.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < content-type: text/plain;charset=UTF-8 < content-length: 2 < date: Mon, 19 Sep 2022 11:57:22 GMT < x-envoy-upstream-service-time: 4 < server: envoy < * Connection #0 to host nacos-vm.DEFAULT-GROUP.public.nacos left intact OK
可以看到能正常请求到nacos-vm的健康检查接口
直接指定IP 可以直接指定连接IP,跳过域名解析环境,带上host头来用来匹配envoy的规则即可。
如curl实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /app # ping nacos-vm.DEFAULT-GROUP.public.nacos ping: bad address 'nacos-vm.DEFAULT-GROUP.public.nacos' /app # curl -v -H "Host: nacos-vm.DEFAULT-GROUP.public.nacos" 1.1.1.1:7788/healthz * Trying 1.1.1.1:7788... * Connected to 1.1.1.1 (1.1.1.1) port 7788 (#0) > GET /healthz HTTP/1.1 > Host: nacos-vm.DEFAULT-GROUP.public.nacos > User-Agent: curl/7.80.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < content-type: text/plain;charset=UTF-8 < content-length: 2 < date: Mon, 19 Sep 2022 12:03:59 GMT < x-envoy-upstream-service-time: 3 < server: envoy < * Connection #0 to host 1.1.1.1 left intact OK/app #
可以看到携带相关host头,直接请求1.1.1.1:7788/healthz 也是能访问到相关接口。
nacos官方给的例子其实就是这种做法。
1 2 3 4 5 6 7 Instance instance = new Instance ();instance.setIp("1.1.1.1" ); instance.setPort(80 ); instance.setEhpemeral(false ); instance.setMetadata(new HashMap <String, String>()); instance.getMetadata().put(PreservedMetadataKeys.INSTANCE_ID_GENERATOR, Constants.SNOWFLAKE_INSTANCE_ID_GENERATOR);
coredns增加nacos后缀解析为固定的IP 1 kubectl edit cm -n kube-system coredns
增加以下配置:
10.96.0.10
是我coredns的cluster IP
1 2 3 4 5 6 template IN ANY public.nacos { answer "{{ .Name }} 60 IN A 1.1.1.1" rcode NOERROR authority "public.nacos. 60 IN NS ns0.public.nacos." additional "ns0.public.nacos. 60 IN A 10.96.0.10" }
添加后效果如下:
ping和nslookup的结果符合预期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 /app # ping nacos-vm.DEFAULT-GROUP.public.nacos PING nacos-vm.DEFAULT-GROUP.public.nacos (1.1.1.1): 56 data bytes 64 bytes from 1.1.1.1: seq=0 ttl=53 time=158.908 ms ^C --- nacos-vm.DEFAULT-GROUP.public.nacos ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 158.908/158.908/158.908 ms /app # nslookup nacos-vm.DEFAULT-GROUP.public.nacos Server: 10.17.0.10 Address: 10.17.0.10:53 Name: nacos-vm.default-group.public.nacos Address: 1.1.1.1 Name: nacos-vm.default-group.public.nacos Address: 1.1.1.1
请求自然也是没问题。
istio DNS代理 istio sidecar提供dns解析DNS Proxying ,既可以减少coredns压力,又可以加快解析速度。它会从预留的IP段 240.240.0.0/16
中分配一个。
1 kubectl edit -n istio-system cm istio
增加如下配置:
1 2 3 4 5 6 defaultConfig: proxyMetadata: # Enable basic DNS proxying ISTIO_META_DNS_CAPTURE: "true" # Enable automatic address allocation, optional ISTIO_META_DNS_AUTO_ALLOCATE: "true"
加好的配置大概如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 apiVersion: v1 data: mesh: |- accessLogFile: /dev/stdout configSources: - address: xds://10.1.10.209:18848 defaultConfig: discoveryAddress: istiod.istio-system.svc:15012 proxyMetadata: ISTIO_META_DNS_CAPTURE: "true" ISTIO_META_DNS_AUTO_ALLOCATE: "true" tracing: zipkin: address: zipkin.istio-system:9411 enablePrometheusMerge: true extensionProviders: - envoyOtelAls: port: 4317 service: otel-collector.istio-system.svc.cluster.local name: otel rootNamespace: istio-system trustDomain: cluster.local meshNetworks: 'networks: {}'
我重启了相关服务
1 kubectl rollout restart -n develop deployment ops-apollo-probe
验证nslookup结果,
1 2 3 4 5 6 7 8 9 /app # nslookup nacos-vm.default-group.public.nacos Server: 10.17.0.10 Address: 10.17.0.10:53 Name: nacos-vm.default-group.public.nacos Address: 240.240.0.2 /app #
请求自然也是没问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /app # curl -v nacos-vm.default-group.public.nacos:7788/healthz * Trying 240.240.0.2:7788... * Connected to nacos-vm.default-group.public.nacos (240.240.0.2) port 7788 (#0) > GET /healthz HTTP/1.1 > Host: nacos-vm.default-group.public.nacos:7788 > User-Agent: curl/7.80.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < content-type: text/plain;charset=UTF-8 < content-length: 2 < date: Mon, 19 Sep 2022 16:04:51 GMT < x-envoy-upstream-service-time: 5 < server: envoy < * Connection #0 to host nacos-vm.default-group.public.nacos left intact OK