nats-io / nats-streaming-operator

NATS Streaming Operator
Apache License 2.0
174 stars 44 forks source link

Unable to publish events to the service #41

Closed BuddhiWathsala closed 5 years ago

BuddhiWathsala commented 5 years ago

I installed the nats-streaming-operator to my minikube cluster. It installed without any issue. Since nats service created by nats-operator is a ClusterIP one I unable to send data into that service externally. So I tried two approaches to send data.

Approach 1

Create a service like below of type LoadBalancer and try to send data.

apiVersion: v1
kind: Service
metadata:
  name: nats-streaming
  namespace: default
  labels:
    app: nats-streaming
    stan_cluster: siddhi-stan
spec:
  externalTrafficPolicy: Cluster
  ports:
  - name: natsservice
    port: 4222
    protocol: TCP
    targetPort: 4222
  - name: natsservice-proxy
    port: 8222
    protocol: TCP
    targetPort: 8222
  selector:
    app: nats-streaming
    stan_cluster: siddhi-stan
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer: {}

Approach 2

Create a different kubernetes deployment of https://github.com/nats-io/go-nats-streaming/tree/master/examples and use that deployment to send data.

I used the following command to send requests.

go run $GOPATH/src/github.com/nats-io/go-nats-streaming/examples/stan-pub/main.go --server nats://nats-streaming.default.svc.cluster.local:4222 <SUBJECT> "{\"name\":\"data\"}"

But from both approaches, I got an error as

Can't connect: stan: connect request timeout.
Make sure a NATS Streaming Server is running at: nats://nats-streaming:4222
exit status 1

So I want to know that how can I external send data to nats-streaming-server in the kubernetes cluster?

Specifications

wallyqs commented 5 years ago

You should try to connect to the NATS service to be able to publish messages to NATS Streaming. I recommend you to look at trying to connect to the service created by the NATS Operator first: https://github.com/nats-io/nats-operator/ If just want to try on minikube then can do a port-forward locally as well

BuddhiWathsala commented 5 years ago

I changed the type of service to LoadBalancer which created by the NATS operator. And I tried to connect to the NATS streaming server using this streaming example. But it gives an error as below.

Exception in thread "main" java.io.IOException: stan: connect request timeout
    at io.nats.streaming.StreamingConnectionImpl.connect(StreamingConnectionImpl.java:156)
    at io.nats.streaming.NatsStreaming.connect(NatsStreaming.java:90)
    at io.nats.streaming.examples.Subscriber.run(Subscriber.java:82)
    at io.nats.streaming.examples.Subscriber.main(Subscriber.java:273)

But I was able to connect to that service from this non-streaming example. Since that service created by NATS operator only contains the labels of NATS cluster, how that service would connect to the NATS streming cluster?

BuddhiWathsala commented 5 years ago

Here I created an ingress load balancer and resolve the problem.

Steps

  1. Create K8s ingress load balancer like this.
  2. Then enable TCP support to the load balancer referring this
  3. Then use minikube IP to send data to the nats streaming server.

Thanks, @wallyqs for the help.

Koshmaar commented 4 years ago

Hi @BuddhiWathsala , could you share more details and code from your solution? I'm facing similiar problem: I have minikube with nats-streaming, and want to create ingress for it, so that I can send message to it from golang script. Which minikube version are you using?

BuddhiWathsala commented 4 years ago

@Koshmaar, you can try the following steps. And here I've used minikube version: v1.4.0.

  1. First, you need to create an ingress using the following YAML (use kubectl apply -f).

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: my-ingress
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      rules:
      - http:
          paths:
          - path: /testpath
            backend:
              serviceName: test
              servicePort: 80
  2. After that I installed NATS operator and NATS streaming operator.

  3. Install a NATS cluster and a STAN cluster in Kuberentes using following YAMLs (use kubectl apply -f).

    apiVersion: nats.io/v1alpha2
    kind: NatsCluster
    metadata:
    name: nats-siddhi
    spec:
    size: 1
    
    ---
    
    apiVersion: streaming.nats.io/v1alpha1
    kind: NatsStreamingCluster
    metadata:
    name: stan-siddhi
    spec:
    size: 1
    natsSvc: nats-siddhi
  4. Then do the followings that describe in this comment

    1. Disable minikube ingress addons
      minikube addons disable ingress
    2. Deploy ingress controller manually
      kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
    3. Get the ingress controller YAML file
      kubectl get deploy nginx-ingress-controller -n ingress-nginx -o yaml>> nginx-ingress-controller.yaml
    4. Add the spec.template.spec.hostNetwork = true to the above ingress controller YAML and redeploy it.
  5. Expose NATS TCP endpoind as follows. For more details refer this doc.

    1. Get the existing TCP config file.
      kubectl get cm -n ingress-nginx -o yaml > tcp.yaml
    2. Update it as below. Note that here the important part is this configuration IS 4222: "default/nats-siddhi:4222". In this configuration first 4222 means the port that I need to expose NATS externally. The default is the namespace in which NATS installed. The nats-siddhi:4222 is the URL of the NATS server I installed previously.
      apiVersion: v1
      kind: ConfigMap
      metadata:
        annotations:
          kubectl.kubernetes.io/last-applied-configuration: |
            {"apiVersion":"v1","kind":"ConfigMap","metadata":{"annotations":{},"labels":{"app.kubernetes.io/name":"ingress-nginx","app.kubernetes.io/part-of":"ingress-nginx"},"name":"tcp-services","namespace":"ingress-nginx"}}
        labels:
          app.kubernetes.io/name: ingress-nginx
          app.kubernetes.io/part-of: ingress-nginx
        name: tcp-services
        namespace: ingress-nginx
        selfLink: /api/v1/namespaces/ingress-nginx/configmaps/tcp-services
      data:
        4222: "default/nats-siddhi:4222"
  6. Now you can access the NATS and STAN servers externally using your minikube IP and port 4222. You can check the availability using following command.

    $ netstat <MINIKUBE_IP>:4222
Koshmaar commented 4 years ago

@BuddhiWathsala Thank you very much :) It's detailed and helpful description.