Getting "rpc error: code = Unavailable desc = error reading from server: EOF" when trying to create a new etcdv3 client
Getting "rpc error: code = Unavailable desc = error reading from server: EOF" when trying to create a new etcdv3 client
我正在尝试从 K8s 控制器访问我的 ETCD 数据库,但在尝试打开 ETCD 客户端时获取 rpc error/EOF。
我的设置:
- ETCD 服务部署在我的 K8s 集群中并包含在我的 Istio 服务网格中(其 DNS 记录:
my-etcd-cluster.my-etcd-namespace.svc.cluster.local
)
- 我有一个使用 Kubebuilder 框架开发的自定义 K8s 控制器,它部署在同一个集群、不同的命名空间中,但配置为同一个 Istio 服务网格的一部分
- 我正在尝试使用 ETCD 的 Go 客户端 SDK 库从控制器连接到 ETCD 数据库
这是我受影响的 Go 代码:
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"http://my-etcd-cluster.my-etcd-namespace.svc.cluster.local:2379"},
DialTimeout: 5 * time.Second,
Username: username,
Password: password,
})
if err != nil {
return nil, fmt.Errorf("opening ETCD client failed: %v", err)
}
这是我在执行 clientv3.New(...)
时遇到的错误:
{"level":"warn","ts":"2022-03-16T23:37:42.174Z","logger":"etcd-client","caller":"v3@v3.5.0/retry_interceptor.go:62","msg":"retrying of unary invoker failed",
"target":"etcd-endpoints://0xc00057f500/#initially=[http://my-etcd-cluster.my-etcd-namespace.svc.cluster.local:2379]","attempt":0,
"error":"rpc error: code = Unavailable desc = error reading from server: EOF"}
...
1.647473862175209e+09 INFO controller.etcdclient Finish reconcile loop for some-service/test-svc-client {"reconciler group": "my-controller.something.io", "reconciler kind": "ETCDClient", "name": "test-svc-client", "namespace": "some-service", "reconcile-etcd-client": "some-service/test-svc-client"}
1.6474738621752858e+09 ERROR controller.etcdclient Reconciler error {"reconciler group": "my-controller.something.io", "reconciler kind": "ETCDClient", "name": "test-svc-client", "namespace": "some-service", "error": "opening ETCD client failed: rpc error: code = Unavailable desc = error reading from server: EOF"}
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.11.0/pkg/internal/controller/controller.go:266
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2
/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.11.0/pkg/internal/controller/controller.go:227
当我传递一些虚拟的、无效的凭据时,也会发生同样的错误。
但是,当我尝试以 HTTP API 方式访问数据库时:
postBody, _ := json.Marshal(map[string]string{
"name": username,
"password": password,
})
responseBody := bytes.NewBuffer(postBody)
resp, err := http.Post("http://my-etcd-cluster.my-etcd-namespace.svc.cluster.local:2379/v3/auth/authenticate", "application/json", responseBody)
if err != nil {
return ctrl.Result{}, fmt.Errorf("an error occured %w", err)
}
l.Info(fmt.Sprintf("code: %d", resp.StatusCode))
defer resp.Body.Close()
...我得到了 200 OK 和一个正确的令牌(这是预期的),所以我相信我的 Istio 配置没问题,我的控制器应该能够看到 ETCD 数据库服务。我不知道为什么这在遵循客户端 SDK 方法时不起作用。
当我使用 ETCD 服务的端口转发并在本地访问它时,clientv3.New()
和其他客户端 SDK 方法非常有效。我错过了什么?如果有任何建议,我将不胜感激。
编辑:
我还添加了一个简单的 pod 来尝试通过 etcdctl 访问我的 etcd 数据库:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: my-controller-namespace
spec:
containers:
- name: etcdctl
image: bitnami/etcd
command:
- sleep
- infinity
当通过 kubectl exec
登录容器时,我能够访问我的数据库:
$ etcdctl --endpoints=my-etcd-cluster.my-etcd-namespace.svc.cluster.local:2379 --user="user" --password="password" put foo bob
OK
我想问题出在 SDK 的某个地方?
原来是版本不匹配 - 我的 ETCD 数据库是 v3.5.2,我使用的 clientv3 库是 v3.5.0。
如 ETCD 更新日志中所示 (https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.5.md):
我正在尝试从 K8s 控制器访问我的 ETCD 数据库,但在尝试打开 ETCD 客户端时获取 rpc error/EOF。
我的设置:
- ETCD 服务部署在我的 K8s 集群中并包含在我的 Istio 服务网格中(其 DNS 记录:
my-etcd-cluster.my-etcd-namespace.svc.cluster.local
) - 我有一个使用 Kubebuilder 框架开发的自定义 K8s 控制器,它部署在同一个集群、不同的命名空间中,但配置为同一个 Istio 服务网格的一部分
- 我正在尝试使用 ETCD 的 Go 客户端 SDK 库从控制器连接到 ETCD 数据库
这是我受影响的 Go 代码:
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"http://my-etcd-cluster.my-etcd-namespace.svc.cluster.local:2379"},
DialTimeout: 5 * time.Second,
Username: username,
Password: password,
})
if err != nil {
return nil, fmt.Errorf("opening ETCD client failed: %v", err)
}
这是我在执行 clientv3.New(...)
时遇到的错误:
{"level":"warn","ts":"2022-03-16T23:37:42.174Z","logger":"etcd-client","caller":"v3@v3.5.0/retry_interceptor.go:62","msg":"retrying of unary invoker failed",
"target":"etcd-endpoints://0xc00057f500/#initially=[http://my-etcd-cluster.my-etcd-namespace.svc.cluster.local:2379]","attempt":0,
"error":"rpc error: code = Unavailable desc = error reading from server: EOF"}
...
1.647473862175209e+09 INFO controller.etcdclient Finish reconcile loop for some-service/test-svc-client {"reconciler group": "my-controller.something.io", "reconciler kind": "ETCDClient", "name": "test-svc-client", "namespace": "some-service", "reconcile-etcd-client": "some-service/test-svc-client"}
1.6474738621752858e+09 ERROR controller.etcdclient Reconciler error {"reconciler group": "my-controller.something.io", "reconciler kind": "ETCDClient", "name": "test-svc-client", "namespace": "some-service", "error": "opening ETCD client failed: rpc error: code = Unavailable desc = error reading from server: EOF"}
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.11.0/pkg/internal/controller/controller.go:266
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2
/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.11.0/pkg/internal/controller/controller.go:227
当我传递一些虚拟的、无效的凭据时,也会发生同样的错误。
但是,当我尝试以 HTTP API 方式访问数据库时:
postBody, _ := json.Marshal(map[string]string{
"name": username,
"password": password,
})
responseBody := bytes.NewBuffer(postBody)
resp, err := http.Post("http://my-etcd-cluster.my-etcd-namespace.svc.cluster.local:2379/v3/auth/authenticate", "application/json", responseBody)
if err != nil {
return ctrl.Result{}, fmt.Errorf("an error occured %w", err)
}
l.Info(fmt.Sprintf("code: %d", resp.StatusCode))
defer resp.Body.Close()
...我得到了 200 OK 和一个正确的令牌(这是预期的),所以我相信我的 Istio 配置没问题,我的控制器应该能够看到 ETCD 数据库服务。我不知道为什么这在遵循客户端 SDK 方法时不起作用。
当我使用 ETCD 服务的端口转发并在本地访问它时,clientv3.New()
和其他客户端 SDK 方法非常有效。我错过了什么?如果有任何建议,我将不胜感激。
编辑: 我还添加了一个简单的 pod 来尝试通过 etcdctl 访问我的 etcd 数据库:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: my-controller-namespace
spec:
containers:
- name: etcdctl
image: bitnami/etcd
command:
- sleep
- infinity
当通过 kubectl exec
登录容器时,我能够访问我的数据库:
$ etcdctl --endpoints=my-etcd-cluster.my-etcd-namespace.svc.cluster.local:2379 --user="user" --password="password" put foo bob
OK
我想问题出在 SDK 的某个地方?
原来是版本不匹配 - 我的 ETCD 数据库是 v3.5.2,我使用的 clientv3 库是 v3.5.0。 如 ETCD 更新日志中所示 (https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.5.md):