K8s问题(通过Node.js)连接到Mac OS上的Cassandra

时间:2019-03-15 10:09:06

标签: node.js cassandra kubernetes minikube

当尝试在Mac OS上的本地Kubernetes群集中(通过Minikube)设置Cassandra数据库时,出现连接问题。 看来Node.js不能正确解析DNS设置,但是可以通过命令行进行解析。

设置如下(简化): 卡桑德拉服务

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

然后将minikube ip地址添加到/etc/hosts

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

到目前为止很好。

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

  

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

该IP 92.242.140.2似乎只是与我的ISP相关的公共IP,我相信由于该应用无法解析服务名称。

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

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

响应是

  

ERR:{错误:queryAaaa ENOTFOUND cassandra       在QueryReqWrap.onresolve上(作为完成时)(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的64个字节   (10.96.239.137):icmp_seq = 1 ttl = 61时间= 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:9042替换为10.96.239.137:9042时,它确实起作用(10.69.239.137是通过cli ping cassandra收到的ip地址)。

1 个答案:

答案 0 :(得分:3)

The Cassandra driver for Node.js uses resolve4/resolve6 to do its dns lookup, which bypasses your resolv.conf file. A program like ping uses resolv.conf to resolve 'cassandra' to 'cassandra.default.svc.cluster.local', the actual dns name assigned to your Cassandra service. For a more detailed explanation of name resolution in node.js see here.

The fix is simple, just pass in the full service name to your client:

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