当尝试在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地址)。
答案 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' });