6

I'm developing an open-sourced cloud event gateway in .NET 5.0, backed by an EventStore channel, and am facing problems to connect the ProjectionsManager service.

I deployed an EventStore service in its own namespace, and can successfully connect to it, and subscribe to streams. However, when I try to connect the ProjectionsManager, I get the following exception:

Connection refused (eventstore.eventstore.svc.cluster.local:2113)

The fully qualified name of the service, 'eventstore.eventstore.svc.cluster.local', is correct and is used successfully by the IEventStoreConnection. The port, 2113, is correct too, for I am able to access the Admin UI by port-forwarding with Kubectl to my pod on that port.

What's going on? On all my local and docker-compose based tests, all works as expected. Only in Kubernetes do I face this problem.

Here's the content of my EventStore yaml file:

apiVersion: v1
kind: Namespace
metadata:
  name: eventstore
  labels:
    name: eventstore

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: eventstore
  namespace: eventstore
  labels:
    app: eventstore
spec:
  serviceName: eventstore
  replicas: 1
  selector:
    matchLabels:
      app: eventstore
  template:
    metadata:
      labels:
        app: eventstore
    spec:
      containers:
        - name: eventstore
          image: eventstore/eventstore:release-5.0.1
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 1112
              name: tcp-int
            - containerPort: 1113
              name: tcp-ext
            - containerPort: 2112
              name: http-int  
            - containerPort: 2113
              name: http-ext  
          volumeMounts:
            - name: data
              mountPath: /var/lib/eventstore
          env:
            - name: EVENTSTORE_EXT_HTTP_PORT
              value: "2113"
            - name: EVENTSTORE_EXT_TCP_PORT
              value: "1113"
            - name: EVENTSTORE_INT_HTTP_PREFIXES
              value: http://*:2112/
            - name: EVENTSTORE_EXT_HTTP_PREFIXES
              value: http://*:2113/
            - name: EVENTSTORE_RUN_PROJECTIONS
              value: All
            - name: EVENTSTORE_START_STANDARD_PROJECTIONS
              value: "true"
            - name: EVENTSTORE_EXT_IP
              value: "0.0.0.0"
            - name: EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP
              value: "true"
            - name: EVENTSTORE_ENABLE_EXTERNAL_TCP
              value: "true"
      volumes:
        - name: data
          emptyDir: {}

---

apiVersion: v1
kind: Service
metadata:
  name: eventstore
  namespace: eventstore
  labels:
    app: eventstore
spec:
  ports:
    - port: 1112
      name: tcp-int
    - port: 1113
      name: tcp-ext
    - port: 2112
      name: http-int  
    - port: 2113
      name: http-ext  
  selector:
    app: eventstore

Here is the C# snippet used to instantiate the ProjectionsManager:

new ProjectionsManager(new ConsoleLogger(), new DnsEndPoint("eventstore.eventstore.svc.cluster.local", 2113), TimeSpan.FromMilliseconds(3000), httpSchema: "http");

By the way, the service that is trying to connect the ProjectionsManager is coupled with an Istio sidecar, if that matters at all.

Thanks in advance for your precious help ;)

EDIT

It seems that Istio sidecar injection is the cause of the issue. Disabling it makes it work as expected. Any idea on why this is happening and on how to solve it with injection enabled?

  • 1.What is your istio version? 2.Could you check if it's gonna work if you disable istio sidecar? If you have [strict mtls](https://istio.io/latest/docs/tasks/security/authentication/mtls-migration/#lock-down-to-mutual-tls-by-namespace) enabled then pods with injected istio sidecar won't be able to communicate with pods without istio sidecar. – Jakub Nov 26 '20 at 08:14
  • 1. My version of Istio is 1.7.3. Kubernetes is 1.19.3. 2. If I disable sidecar injection, everything works as expected. 3. Strict MTLS is not enabled, everything is in permissive mode. Any idea on how to make it work with sidecar injection enabled? – Charles d'Avernas Nov 26 '20 at 10:35
  • Could you try to add [destination rule](https://istio.io/latest/docs/reference/config/networking/destination-rule/) for it which will disable mtls for this specific host/namespace? There is an [example](https://itnext.io/istio-adventures-disabling-mtls-for-one-namespace-62f37b99855c). – Jakub Nov 26 '20 at 10:43
  • I have created two DestinationRules, one in the eventstore namespace, and one in my eventing namespace, to be sure it is applied in both namespaces. It however still does not work. Here's the pastebin: https://pastebin.pl/view/6f6219b5 – Charles d'Avernas Nov 26 '20 at 11:06
  • 1
    Btw, without those destination rules, I see in Kiali that MTLS is not being enforced anyways. Don't you think my issue is rather related to EventStore not accepting a request forwarded by my sidecar? – Charles d'Avernas Nov 26 '20 at 11:13
  • I agree, if it still can't connect with mtls disabled, specially when the mtls is in permissive then I would say this issue is rather related to eventstore. I'm curious if you've tried to inject event store with a sidecar and check if it works then? – Jakub Nov 26 '20 at 12:01
  • I enabled sidecar injection for EventStore, but still does'nt work... :( – Charles d'Avernas Nov 26 '20 at 12:22
  • Connection refused is generally, firewall/port issue due to some handshake problem. i would check logs to see if anything there. – Jag Dec 07 '20 at 10:34
  • Have you tried to set `EVENTSTORE_EXT_IP` to use `valueFrom: fieldRef: fieldPath: status.podIP`? Using `EVENTSTORE_ENABLE_EXTERNAL_TCP` is also confusing as it's for v20, this option doesn't exist in v5. I've also heard about issues with Istio pass-through, are you able to connect directly? – Alexey Zimarev Apr 28 '21 at 07:30

1 Answers1

1

We encountered the same issue running EventStoreDB on a Kubernetes cluster with Istio sidecar injection enabled.

According to Istio's documentation on protocol selection, Istio will look at the name of the port you defined on your Service, and this will decide which protocol Istio is trying to intercept. If the format is not respected, Istio will try to guess the protocol (works for HTTP, HTTPS and gRPC).

In your case, your ports' name started with http- (http-int and http-ext). Therefore, Istio will not try to detect the protocol used, but instead will assume that the protocol is http (HTTP/1.1).

However, EventStoreDB's API is a gRPC endpoint. Therefore, you have two options:

  • Rename the port to start with grpc-. In that case any Istio proxy will know that this port is exposing gRPC
  • Name the port somethig else directly (like api or eventstoredb for example), to let Istio detect the protocol used.

Note that EventStoreDB exposes a admin web interface on the same port, which is HTTP. If you are accessing it through port-forwarding, then you have no Istio sidecar in the way, so the port's name will not influence the traffic. But if you try to expose the admin interface through an Istio Ingress Gateway (which I wouldn't recommend since you would be exposing your database to the Internet), then you might have issues accessing the admin interface. In that case, the second solution to let Istio detect the traffic is probably a more flexible solution.

A last option would be to expose 2 ports on the Service, one for http and the other for grpc, and have them both redirect to the same port on the Pod, but I'm actually not sure if this is allowed by Kubernetes.

Thibault Henry
  • 381
  • 3
  • 12