【问题标题】:Zookeeper: Hostname resolution failsZookeeper:主机名解析失败
【发布时间】:2018-03-18 06:10:06
【问题描述】:

我在 OpenShift/Kubernetes 环境中运行 Zookeeper。我已将 zookeeper 设置为StatefulSet,以便可靠地保存配置数据。

我在zoo.cfg 中按主机名配置了三台服务器,但在启动时,主机名解析失败。我验证了主机名确实可以在集群中使用 nslookup 解析。

动物园.cfg:

clientPort=2181
dataDir=/var/lib/zookeeper/data
dataLogDir=/var/lib/zookeeper/log
tickTime=2000
initLimit=10
syncLimit=2000
maxClientCnxns=60
minSessionTimeout= 4000
maxSessionTimeout= 40000
autopurge.snapRetainCount=3
autopurge.purgeInteval=0
server.1=zookeeper-0.zookeeper-headless:2888:3888
server.2=zookeeper-1.zookeeper-headless:2888:3888
server.3=zookeeper-2.zookeeper-headless:2888:3888

我的 OpenShift / Kubernetes 配置的相关部分:

  # StatefulSet
  - apiVersion: apps/v1beta1
    kind: StatefulSet
    metadata:
      labels:
        app: zookeeper
      name: zookeeper
    spec:
      serviceName: zookeeper-headless
      replicas: 3
      template:
        metadata:
          labels:
            app: zookeeper
        spec:
          containers:
            - image: 172.30.158.156:5000/os-cloud-platform/zookeeper:latest
              name: zookeeper
              ports:
                - containerPort: 2181
                  protocol: TCP
                  name: client
                - containerPort: 2888
                  protocol: TCP
                  name: server
                - containerPort: 3888
                  protocol: TCP
                  name: leader-election
          dnsPolicy: ClusterFirst
          schedulerName: default-scheduler

  # Service
  - apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: zookeeper
      name: zookeeper
    spec:
      ports:
        - name: client
          port: 2181
          protocol: TCP
          targetPort: 2181
      selector:
        app: zookeeper
      sessionAffinity: None
      type: ClusterIP

  - apiVersion: v1
    kind: Service
    metadata:
      name: zookeeper-headless
      labels:
        app: zookeeper
    spec:
      ports:
        - port: 2888
          name: server
        - port: 3888
          name: leader-election
      clusterIP: None
      selector:
        app: zookeeper

OpenShift 日志显示 UnknownHostExceptions,但:

2017-10-06 10:59:18,289 [myid:] - WARN  [main:QuorumPeer$QuorumServer@155] - Failed to resolve address: zookeeper-2.zookeeper-headless
java.net.UnknownHostException: zookeeper-2.zookeeper-headless: No address associated with hostname
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928)
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323)
    at java.net.InetAddress.getAllByName0(InetAddress.java:1276)
    at java.net.InetAddress.getAllByName(InetAddress.java:1192)
    at java.net.InetAddress.getAllByName(InetAddress.java:1126)
    at java.net.InetAddress.getByName(InetAddress.java:1076)
    at org.apache.zookeeper.server.quorum.QuorumPeer$QuorumServer.recreateSocketAddresses(QuorumPeer.java:148)
    at org.apache.zookeeper.server.quorum.QuorumPeer$QuorumServer.<init>(QuorumPeer.java:133)
    at org.apache.zookeeper.server.quorum.QuorumPeerConfig.parseProperties(QuorumPeerConfig.java:228)
    at org.apache.zookeeper.server.quorum.QuorumPeerConfig.parse(QuorumPeerConfig.java:140)
    at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:101)
at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:78)
...

可能是什么原因?我验证了主机名(例如zookeeper-2.zookeeper-headless)可通过nslookup从其他 pod 获得。

【问题讨论】:

标签: kubernetes openshift apache-zookeeper kube-dns


【解决方案1】:

我找到了解决此问题的有效解决方案。 ZooKeeper 在启动时读取 ensemble 中的服务器列表,并查找它的“自己的”条目。然后它使用这个条目来确定监听哪个端口和接口。

server.1=zookeeper-0.zookeeper-headless:2888:3888
server.2=zookeeper-1.zookeeper-headless:2888:3888
server.3=zookeeper-2.zookeeper-headless:2888:3888

由于提供的主机名将在这台机器上解析为 127.0.0.1,ZooKeeper 将侦听本地环回接口,因此不接受来自其他 ZooKeeper 服务器的连接。

server.1=0.0.0.0:2888:3888
server.2=zookeeper-1.zookeeper-headless:2888:3888
server.3=zookeeper-2.zookeeper-headless:2888:3888

为了使集群中的事情自动化,我编写了一个 bash 脚本,它将在容器启动时替换一个“自己的”条目。

编辑:正如 cmets 所要求的,这是我的 ENTRYPOINT 脚本,负责放置 myid 文件并为每个 zoo.cfg 设置适当的主机名:

#!/bin/bash
# This script extracts the number out of the pod's hostname and sets it as zookeepers id.

# Exact paths may vary according to your setup
MYID_FILE="/var/lib/zookeeper/data/myid"
ZOOCFG_FILE="/conf/zoo.cfg"

# Create myid-file
# Extract only numbers from hostname
id=$(hostname | tr -d -c 0-9)
echo $id > "${MYID_FILE}"

# change own hostname to 0.0.0.0
# otherwise, the own hostname will resolve to 127.0.0.1
# https://stackoverflow.com/a/40750900/5764665
fullHostname="$(hostname).zookeeper-headless"
sed -i -e "s/${fullHostname}/0.0.0.0/g" "${ZOOCFG_FILE}"

echo "Executing $@"
exec "$@"

【讨论】:

  • 嗨弗兰兹。我有同样的问题。我想问您如何更改 pod 的特定服务器以解析其 localhost。你也可以分享一下bash脚本吗?那真的很有帮助。非常感谢
  • 非常感谢您提供的脚本。你能告诉我在哪里运行这个脚本(initContainer 什么的?)。抱歉,我对 Kubernetes 真的很陌生
  • 这个脚本是你的 Docker 镜像的入口点。它将执行您在 Kubernetes 设置中传递的所有 args
  • 我使用configmap 挂载了一个卷,然后使用该挂载的卷在我的容器中运行脚本,就像command: ['/bin/bash', '/var/lib/zk-init.sh'] 一样。但我收到错误sed: /conf/zoo.cfg: No such file or directory。虽然当我成功运行容器时。它确实包含/conf/zoo.cfg。请告诉我我做错了什么?注意:/var/libmountPath
  • @FranzWimmer 只是想告诉你,这对 kubernetes/istio 上下文也有帮助。 zookeeper 在 kubernetes 中运行良好,但是一旦我使用 istio 侧卡部署 zk,zk-instances 就无法再相互通信了。在按照描述更改 serverconfig 后,它再次工作。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-31
  • 1970-01-01
  • 2014-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多