公众号:《尹安灿》 欢迎交流

背景是我们希望能在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。

[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 端口

[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,添加以下配置

kubectl edit -n istio-system cm istio
    configSources:
    - address: xds://10.1.10.209:18848

添加后的配置大概如下:

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同步信息

kubectl rollout restart -n istio-system deployment istiod

服务访问

同步nacos服务信息到istio后,我们可以在服务的sidecar envoy看到同步下来的服务配置信息。

如以下是我 ops-apollo-probe 服务的pod ops-apollo-probe-7765fd445f-smstf 的envoy配置信息,搜索nacos后的结果。

➜  ~ 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

image-20220919194215557

因为coredns中并没有 nacos-vm.DEFAULT-GROUP.public.nacos 的解析,所以解析失败,报错退出。

以下为在ops-apollo-probe服务的容器内请求:

/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)。

➜  ~ 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的记录

# 添加hosts
/app # echo '1.1.1.1 nacos-vm.DEFAULT-GROUP.public.nacos' >> /etc/hosts
/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实现如下:

/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官方给的例子其实就是这种做法。

Instance instance = new Instance();
instance.setIp("1.1.1.1");
instance.setPort(80);
// 必须设置ephemeral=false,来保证服务端使用的是严格的一致性协议,否则可能会导致生成的instance id冲突:
instance.setEhpemeral(false);
instance.setMetadata(new HashMap<String, String>());
instance.getMetadata().put(PreservedMetadataKeys.INSTANCE_ID_GENERATOR, Constants.SNOWFLAKE_INSTANCE_ID_GENERATOR);

coredns增加nacos后缀解析为固定的IP

kubectl edit cm -n kube-system coredns

增加以下配置:

10.96.0.10 是我coredns的cluster IP

       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的结果符合预期

/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 中分配一个。

kubectl edit -n istio-system cm istio

增加如下配置:

    defaultConfig:
      proxyMetadata:
        # Enable basic DNS proxying
        ISTIO_META_DNS_CAPTURE: "true"
        # Enable automatic address allocation, optional
        ISTIO_META_DNS_AUTO_ALLOCATE: "true"

加好的配置大概如下:

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: {}'

我重启了相关服务

kubectl rollout restart -n develop deployment ops-apollo-probe

验证nslookup结果,

/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 # 

请求自然也是没问题

/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
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐