node.js - 在 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/hosts
minikube 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:9042
为10.96.239.137:9042
(10.69.239.137 是通过 cli 从 ping cassandra 收到的 IP 地址)时它确实有效。
解决方案
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' });
推荐阅读
- javascript - 如何使用 Jquery 设置 Html 元素中的变量值?
- python - Python烧瓶服务器需要很长时间才能启动
- tfs - TFS 和 Mantis 的集成
- elasticsearch - 我们可以将一个查询的结果用作弹性搜索中另一个查询的输入吗?
- swift - Swift:addSubview 放在前一个视图上
- forms - 来自 Laravel 作曲家的评论表
- power-automate - 流 - 在 SharePoint(电子表格)中创建文件时,获取行并将它们粘贴到主电子表格中
- powershell - VSTS CI 将镜像推送到 Linux 远程服务器
- javascript - 静音自动播放视频显示错误:play() 失败,因为用户没有先与文档交互。
- wyam - Wyam - 我如何在管道中订购内容?