当试图在macos上的本地kubernetes集群中设置cassandra数据库时(通过minikube),我遇到了连接问题。似乎node.js无法正确解析dns设置,但通过命令行解析确实有效。
设置如下(简化):cassandra服务
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/hosts
minikube ip地址
192.xxx.xx.xxx dev.acme.com
到现在为止,一直都还不错。
打电话的时候 dev.acme.com/app1
通过postman,node.js应用程序本身被正确调用(可以在日志中看到),但是,该应用程序无法连接到cassandra并超时,出现以下错误:
“所有尝试查询的主机都失败。尝试了第一个主机,92.242.140.2:9042:驱动器错误:连接超时。请参阅“内部错误”
知识产权 92.242.140.2
似乎只是一个公共ip,是有关我的isp,我相信,因为该应用程序是无法解决的服务名称。
我创建了一个简单的node.js脚本来测试dns: var dns = require('dns') dns.resolve6('cassandra', (err, res) => console.log('ERR:', err, 'RES:', res))
答案是
错误:{错误:queryreqwrap.onresolve[as oncomplete](dns.js:197:19)处的queryaaa enotfound cassandra错误号:'enotfound',代码:'enotfound',系统调用:'queryaaa',主机名:'cassandra'}res:未定义
然而,这正是让人困惑的地方——当我ssh到pod(app1)中时,我能够使用以下方式连接到cassandra服务: cqlsh cassandra 9042 --cqlversion=3.4.4
因此,pod似乎“意识到”了服务名称,但node.js运行时却没有。
知道是什么导致node.js无法解析服务名/dns设置吗?
更新
在重新安装整个集群,包括重新安装docker、kubectl和minikube之后,我得到了同样的问题。
跑步时 ping cassandra
通过ssh从app1容器中,我得到以下内容
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:驱动器错误:连接超时。请参阅“内部错误”
这些就是服务
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条答案
按热度按时间qv7cva1a1#
node.js的cassandra驱动程序使用
resolve4
/resolve6
做它的dns查找,它绕过你的resolv.conf
文件。像ping这样的程序使用resolv.conf将“cassandra”解析为“cassandra.default.svc.cluster.local”,这是分配给您的cassandra服务的实际dns名称。有关node.js中名称解析的更详细说明,请参见此处。解决方法很简单,只需将完整的服务名称传递给您的客户端: