1. 排查流程

Failed to instantiate [org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier]: Factory method 'discoveryClientServi ceInstanceListSupplier' threw exception with message: Error creating bean with name 'nacosProperties': Unsatisfied dependency expressed through field 'inetIPv6Utils': Error creating bean with name ' inetUtilsProperties': Could not bind properties to 'InetUtilsProperties' : prefix=spring.cloud.inetutils, ignoreInvalidFields=false, ignoreUnknownFields=true

最近在协助子公司进行系统升级时,我们遇到了一个看似诡异的问题,新构建的镜像在本地测试环境一切正常,但部署到对方环境后,Nacos 竟然连接不上!奇怪的是,他们的旧系统却能正常注册到同一个 Nacos 服务端。

首先确认了Nacos连接配置无误,包括注册地址、账号密码以及针对bx命名空间的读写权限都已正确配置。

spring.cloud.nacos.discovery.server-addr = http://app-nacos1.bx.tanqidi.com:8848,http://app-nacos2.bx.tanqidi.com:8848,http://app-nacos3.bx.tanqidi.com:8848
spring.cloud.nacos.username = nacosbx
spring.cloud.nacos.password = 123456
spring.cloud.nacos.discovery.username = nacosbx
spring.cloud.nacos.discovery.password = 123456
spring.cloud.nacos.discovery.group = bx
spring.cloud.nacos.discovery.namespace = bx

为了快速验证是不是环境的问题,在对方的 KubeSphere 部署环境中进行了测试,结果一次通过且配置与我方环境完全一致,排除了配置不一致的问题。

随后在对方环境中,使用 host 网络单机启动了一个 Nacos 实例,运行正常,同样一次通过。由此开始怀疑其原有的 Nacos 集群可能存在问题。查阅官网部署文档后发现,官方建议开启 8848、9848、9849 三个端口。于是继续对其集群进行 telnet 测试,仅有一个端口可连通,而单独启动的实例因使用 host 网络,三个端口均可正常连接。

目标很接近了,是端口的问题,来到他们的中间件服务器使用脚本看看部署的时候是不是使用host或者bridge模式有没有正确映射端口。

执行脚本看从提取出来的信息来看,对方所部署的nacos集群确实是使用host网络模式的,那么非bridge模式的端口映射问题就排查了,所幸是host模式但是端口不通,那么最终就是防火墙的问题了,让对方开启允许访问9848,9849端口,重启一下java程序,完全正确!问题结束。

docker inspect --format 'docker run \
  --name {{printf "%q" .Name}} \
    {{- with .HostConfig}}
        {{- if .Privileged}}
  --privileged \
        {{- end}}
        {{- if .AutoRemove}}
  --rm \
        {{- end}}
        {{- if .Runtime}}
  --runtime {{printf "%q" .Runtime}} \
        {{- end}}
        {{- range $b := .Binds}}
  --volume {{printf "%q" $b}} \
        {{- end}}
        {{- range $v := .VolumesFrom}}
  --volumes-from {{printf "%q" $v}} \
        {{- end}}
        {{- range $l := .Links}}
  --link {{printf "%q" $l}} \
        {{- end}}
        {{- if index . "Mounts"}}
            {{- range $m := .Mounts}}
  --mount type={{.Type}}
                {{- if $s := index $m "Source"}},source={{$s}}{{- end}}
                {{- if $t := index $m "Target"}},destination={{$t}}{{- end}}
                {{- if index $m "ReadOnly"}},readonly{{- end}}
                {{- if $vo := index $m "VolumeOptions"}}
                    {{- range $i, $v := $vo.Labels}}
                        {{- printf ",volume-label=%s=%s" $i $v}}
                    {{- end}}
                    {{- if $dc := index $vo "DriverConfig" }}
                        {{- if $n := index $dc "Name" }}
                            {{- printf ",volume-driver=%s" $n}}
                        {{- end}}
                        {{- range $i, $v := $dc.Options}}
                            {{- printf ",volume-opt=%s=%s" $i $v}}
                        {{- end}}
                    {{- end}}
                {{- end}}
                {{- if $bo := index $m "BindOptions"}}
                    {{- if $p := index $bo "Propagation" }}
                        {{- printf ",bind-propagation=%s" $p}}
                    {{- end}}
                {{- end}} \
            {{- end}}
        {{- end}}
        {{- if .PublishAllPorts}}
  --publish-all \
        {{- end}}
        {{- if .UTSMode}}
  --uts {{printf "%q" .UTSMode}} \
        {{- end}}
        {{- with .LogConfig}}
  --log-driver {{printf "%q" .Type}} \
            {{- range $o, $v := .Config}}
  --log-opt {{$o}}={{printf "%q" $v}} \
            {{- end}}
        {{- end}}
        {{- with .RestartPolicy}}
  --restart "{{.Name -}}
            {{- if eq .Name "on-failure"}}:{{.MaximumRetryCount}}
            {{- end}}" \
        {{- end}}
        {{- range $e := .ExtraHosts}}
  --add-host {{printf "%q" $e}} \
        {{- end}}
        {{- range $v := .CapAdd}}
  --cap-add {{printf "%q" $v}} \
        {{- end}}
        {{- range $v := .CapDrop}}
  --cap-drop {{printf "%q" $v}} \
        {{- end}}
        {{- range $d := .Devices}}
  --device {{printf "%q" (index $d).PathOnHost}}:{{printf "%q" (index $d).PathInContainer}}:{{(index $d).CgroupPermissions}} \
        {{- end}}
    {{- end}}
    {{- with .NetworkSettings -}}
        {{- range $p, $conf := .Ports}}
            {{- with $conf}}
  --publish "
                {{- if $h := (index $conf 0).HostIp}}{{$h}}:
                {{- end}}
                {{- (index $conf 0).HostPort}}:{{$p}}" \
            {{- end}}
        {{- end}}
        {{- range $n, $conf := .Networks}}
            {{- with $conf}}
  --network {{printf "%q" $n}} \
                {{- range $a := $conf.Aliases}}
  --network-alias {{printf "%q" $a}} \
                {{- end}}
            {{- end}}
        {{- end}}
    {{- end}}
    {{- with .Config}}
        {{- if .Hostname}}
  --hostname {{printf "%q" .Hostname}} \
        {{- end}}
        {{- if .Domainname}}
  --domainname {{printf "%q" .Domainname}} \
        {{- end}}
        {{- if index . "ExposedPorts"}}
        {{- range $p, $conf := .ExposedPorts}}
  --expose {{printf "%q" $p}} \
        {{- end}}
        {{- end}}
        {{- if .User}}
  --user {{printf "%q" .User}} \
        {{- end}}
        {{- range $e := .Env}}
  --env {{printf "%q" $e}} \
        {{- end}}
        {{- range $l, $v := .Labels}}
  --label {{printf "%q" $l}}={{printf "%q" $v}} \
        {{- end}}
    {{- if not (or .AttachStdin  (or .AttachStdout .AttachStderr))}}
  --detach \
    {{- end}}
    {{- if .AttachStdin}}
  --attach stdin \
    {{- end}}
    {{- if .AttachStdout}}
  --attach stdout \
    {{- end}}
    {{- if .AttachStderr}}
  --attach stderr \
    {{- end}}
    {{- if .Tty}}
  --tty \
    {{- end}}
    {{- if .OpenStdin}}
  --interactive \
    {{- end}}
    {{- if .Entrypoint}}
{{- /* Since the entry point cannot be overridden from the command line with an array of size over 1,
       we are fine assuming the default value in such a case. */ -}}
        {{- if eq (len .Entrypoint) 1 }}
  --entrypoint "
            {{- range $i, $v := .Entrypoint}}
                {{- if $i}} {{end}}
                {{- $v}}
            {{- end}}" \
        {{- end}}
    {{- end}}
  {{printf "%q" .Image}} \
  {{range .Cmd}}{{printf "%q " .}}{{- end}}
{{- end}}' \
你的容器名
docker run \
  --name "/nacos1" \
  --runtime "runc" \
  --volume "/data/nacos1:/data" \
  --volume "/log/nacos1:/log" \
  --log-driver "json-file" \
  --restart "always" \
  --network "host" \
  --hostname "HYDOKVSRA123" \
  --expose "8848/tcp" \
  --env "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/app/jdk/bin:/app/jdk/jre/bin" \
  --env "TZ=Asia/Shanghai" \
  --env "JAVA_HOME=/app/jdk" \
  --env "JRE_HOME=/app/jdk/jre" \
  --env "CLASSPATH=.:/app/jdk/lib/dt.jar:/app/jdk/lib/tools.jar:/app/jdk/jre/lib" \
  --env "MODE=cluster" \
  --label "build-date"="20200705" \
  --label "license"="GPLv2" \
  --label "maintainer"="tanqidi Digital Platform Project Team Maintainers <crph_dp_zy@tanqidi.com>" \
  --label "name"="CentOS Base Image" \
  --label "vendor"="CentOS" \
  --detach \
  --entrypoint "bin/docker-entrypoint.sh" \
  "harbor.bx.tanqidi.com/bx/nacos:dev_latest" \
https://nacos.io/en/blog/faq/nacos-user-question-history8449/?spm=5238cd80.425a2867.0.0.776645229fy7XR&source=wuyi#_top

img_v3_02ld_1afaca03-2aa9-49a4-8175-faf67e3167cp.jpg

2. 操作总结

Nacos 部署挺关键的,要是出了问题,不妨先看看部署的时候有没有按官方说的那样,把 8848、9848、9849 这三个端口都开放了,有时候就是因为端口没开全导致各种莫名其妙的问题。接着也可以看看防火墙是不是把这些端口给拦了。再不行,就去 GitHub 上翻翻别人提过的问题,说不定正好有人遇到过类似的情况,还顺手把解决办法写出来了。