首页 > 解决方案 > 在 Mac OS 上连接到 Cassandra 的 K8s 问题(通过 Node.js)

问题描述

在尝试在 Mac OS 上的本地 Kubernetes 集群中设置 Cassandra 数据库时(通过 Minikube),我遇到了连接问题。似乎 Node.js 无法正确解析 DNS 设置,但通过命令行解析确实有效。

设置如下(简化): Cassandra Service

apiVersion: v1
kind: Service
metadata:
  labels:
    app: cassandra
  name: cassandra
spec:
  type: NodePort
  ports:
    - port: 9042
      targetPort: 9042
      protocol: TCP
      name: http
  selector:
    app: cassandra

此外,还有一个 PersistentVolume 和一个 StatefulSet。

应用程序本身非常基础

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app1
  labels:
    app: app1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app1
  template:
    metadata:
      labels:
        app: app1
    spec:
      containers:
      - name: app1
        image: xxxx.dkr.ecr.us-west-2.amazonaws.com/acme/app1
        imagePullPolicy: "Always"
        ports:
        - containerPort: 3003

和服务

apiVersion: v1
kind: Service
metadata:
  name: app1
  namespace: default
spec:
  selector:
    app: app1
  type: NodePort
  ports:
    - port: 3003
      targetPort: 3003
      protocol: TCP
      name: http

还有一个简单的入口设置

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: dev.acme.com
    http:
      paths:
      - path: /app1
        backend:
          serviceName: app1
          servicePort: 3003

并添加到/etc/hostsminikube ip地址

192.xxx.xx.xxx dev.acme.com

到目前为止,一切都很好。

尝试dev.acme.com/app1通过 Postman 调用时,node.js 应用程序本身被正确调用(可以在日志中看到),但是,该应用程序无法连接到 Cassandra 并超时并出现以下错误:

“尝试查询的所有主机都失败。第一个主机尝试,92.242.140.2:9042:DriverError:连接超时。请参阅 innerErrors。”

该 IP92.242.140.2似乎只是与我的 ISP 相关的公共 IP,我相信因为该应用程序无法解析服务名称。

我创建了一个简单的 node.js 脚本来测试 dns:

var dns = require('dns') dns.resolve6('cassandra', (err, res) => console.log('ERR:', err, 'RES:', res))

响应是

ERR:{错误:QueryReqWrap.onresolve 处的 queryAaaa ENOTFOUND cassandra [as oncomplete] (dns.js:197:19) errno:'ENOTFOUND',代码:'ENOTFOUND',系统调用:'queryAaaa',主机名:'cassandra'} RES : 不明确的

但是,这就是令人困惑的地方 - 当我 ssh 进入 pod (app1) 时,我可以使用以下方法连接到 cassandra 服务:

cqlsh cassandra 9042 --cqlversion=3.4.4

所以看起来 pod 是“知道”服务名称的,但 node.js 运行时不是。

知道什么可能导致 node.js 无法解析服务名称/dns 设置吗?

更新

重新安装整个集群后,包括重新安装 docker、kubectl 和 minikube,我遇到了同样的问题。

通过 ssh 从 app1 容器运行ping cassandra时,我得到以下信息

PING cassandra.default.svc.cluster.local (10.96.239.137) 56(84) 字节数据。来自 cassandra.default.svc.cluster.local (10.96.239.137) 的 64 个字节:icmp_seq=1 ttl=61 time=27.0 ms

2个包发送,2个接收,0%丢包,时间1001ms

这似乎很好。但是,从 Node.js 运行时运行时,我仍然遇到相同的错误 -

“尝试查询的所有主机都失败。第一个主机尝试,92.242.140.2:9042:DriverError:连接超时。请参阅 innerErrors。”

这些是服务

NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
app1        ClusterIP   None            <none>        3003/TCP         11m
cassandra    NodePort    10.96.239.137   <none>        9042:32564/TCP   38h
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          38h

这些是 pod(所有命名空间)

NAMESPACE     NAME                                        READY   STATUS    RESTARTS   AGE
default       app1-85d889db5-m977z                       1/1     Running   0          2m1s
default       cassandra-0                                 1/1     Running   0          38h
kube-system   calico-etcd-ccvs8                           1/1     Running   0          38h
kube-system   calico-node-thzwx                           2/2     Running   0          38h
kube-system   calico-policy-controller-5bb4fc6cdc-cnhrt   1/1     Running   0          38h
kube-system   coredns-86c58d9df4-z8pr4                    1/1     Running   0          38h
kube-system   coredns-86c58d9df4-zcn6p                    1/1     Running   0          38h
kube-system   default-http-backend-5ff9d456ff-84zb5       1/1     Running   0          38h
kube-system   etcd-minikube                               1/1     Running   0          38h
kube-system   kube-addon-manager-minikube                 1/1     Running   0          38h
kube-system   kube-apiserver-minikube                     1/1     Running   0          38h
kube-system   kube-controller-manager-minikube            1/1     Running   0          38h
kube-system   kube-proxy-jj7c4                            1/1     Running   0          38h
kube-system   kube-scheduler-minikube                     1/1     Running   0          38h
kube-system   kubernetes-dashboard-ccc79bfc9-6jtgq        1/1     Running   4          38h
kube-system   nginx-ingress-controller-7c66d668b-rvxpc    1/1     Running   0          38h
kube-system   registry-creds-x5bhl                        1/1     Running   0          38h
kube-system   storage-provisioner                         1/1     Running   0          38h

更新 2

从 Node.js 连接到 Cassandra 的代码:

const cassandra = require('cassandra-driver');
const client = new cassandra.Client({ contactPoints: ['cassandra:9042'], localDataCenter: 'datacenter1', keyspace: 'auth_server' });

const query = 'SELECT * FROM user';
client.execute(query, [])
  .then(result => console.log('User with email %s', result.rows[0].email));

替换cassandra:904210.96.239.137:9042(10.69.239.137 是通过 cli 从 ping cassandra 收到的 IP 地址)时它确实有效。

标签: node.jscassandrakubernetesminikube

解决方案


Node.js 的 Cassandra 驱动程序使用resolve4/resolve6进行 dns 查找,这会绕过您的resolv.conf文件。像 ping 这样的程序使用 resolv.conf 将“cassandra”解析为“cassandra.default.svc.cluster.local”,即分配给 Cassandra 服务的实际 dns 名称。有关 node.js 中名称解析的更详细说明,请参见此处

修复很简单,只需将完整的服务名称传递给您的客户端:

const client = new cassandra.Client({ contactPoints: ['cassandra.default.svc.cluster.local:9042'], localDataCenter: 'datacenter1', keyspace: 'auth_server' });

推荐阅读