externalexposure.adoc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. [#externalexposure]
  2. # External Exposure of Neo4j Clusters
  3. [abstract]
  4. This chapter describes how to route traffic from the outside world or Internet to a Neo4j cluster on version 4.3.0 or above running in Kubernetes.
  5. If you are running a version of Neo4j earlier than 4.3.0 these instructions do not apply. Look at xref::externalexposure42.adoc[external exposure instructions for client routing]
  6. ## Overview
  7. By default when you install Neo4j using Neo4j Labs Helm chart none of the services that are created are accessible from outside the Kubernetes cluster.
  8. To access Neo4j from outside the Kubernetes cluster we will need an externally valid DNS name or IP address that clients can connect to. That external address needs to direct queries to a Kubernetes LoadBalancer service that is balanced over Neo4j cores.
  9. [NOTE]
  10. A Service with `type: LoadBalancer` is the only suitable option for Neo4j. Ingress cannot be used because Neo4j's driver protocol communicates at the TCP level and most Ingress only support HTTP communication. Node Port services cannot be associated with a static IP address which makes setting up DNS and SSL very difficult. Using NodePort can additionally create configuration challenges for some Neo4j applications that expect to use port 7687 specifically for communication with Neo4j. Because of that we recommend only using LoadBalancer services.
  11. ### Create Static IP addresses for inbound cluster traffic
  12. I'm using GCP, so it is done like this. Important notes here, on GCP the region must match your GKE
  13. region, and the network tier must be premium. On other clouds, the conceptual step here is the same,
  14. but the details will differ: you only need to allocate 1 static IP address for your entire Neo4j cluster.
  15. ```shell
  16. # Customize these next 2 for the region of your GKE cluster,
  17. # and your GCP project ID
  18. REGION=us-central1
  19. PROJECT=my-gcp-project-id
  20. gcloud compute addresses create \
  21. neo4j-static-ip --project=$PROJECT \
  22. --network-tier=PREMIUM --region=$REGION
  23. echo "IP:"
  24. gcloud compute addresses describe neo4j-static-ip \
  25. --region=$REGION --project=$PROJECT --format=json | jq -r '.address'
  26. ```
  27. **If you are doing this with Azure** please note that the static IP address must be in the same
  28. resource group as your Kubernetes cluster, and can be created with
  29. link:https://docs.microsoft.com/en-us/cli/azure/network/public-ip?view=azure-cli-latest#az-network-public-ip-create[az network public-ip create] like this (just one single sample):
  30. `az network public-ip create -g resource_group_name -n core01 --sku standard --dns-name neo4jcluster --allocation-method Static`. The Azure SKU used must be standard, and the resource group you need can be found in the Kubernetes Load Balancer that [following the Azure Tutorial](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough) sets up for you.
  31. For the remainder of this tutorial, let's assume that the core IP address I've allocated is
  32. as follows:
  33. ```shell
  34. export IP=35.202.123.82
  35. ```
  36. ### Installing the Helm Chart
  37. From the root of this repo, navigate to stable/neo4j and issue this command to install the helm chart
  38. with a deployment name of "graph".
  39. ```shell
  40. export DEPLOYMENT=graph
  41. helm install $DEPLOYMENT . \
  42. --set core.numberOfServers=3 \
  43. --set acceptLicenseAgreement=yes \
  44. --set neo4jPassword=mySecretPassword
  45. ```
  46. ## External Exposure
  47. After a few minutes you'll have a fully-formed cluster whose pods show ready, and which you can connect
  48. to from inside Kubernetes, *but* it will not yet be accessible from outside the Kubernetes cluster. So
  49. what we need to do next is to create a load balancer and set the `loadBalancerIP` to be the static IP address we
  50. reserved in the earlier step.
  51. A `load-balancer.yaml` file has been provided as a template, here's how to make one for given static
  52. IP address:
  53. ```shell
  54. export DEPLOYMENT=graph
  55. # Reuse IP from the earlier step here.
  56. # These *must be IP addresses* and not hostnames, because we're
  57. # assigning load balancer IP addresses to bind to.
  58. echo $DEPLOYMENT with IP $IP ;
  59. cat tools/external-exposure/load-balancer.yaml | envsubst | kubectl apply -f -
  60. ```
  61. Inside of these services, we use `externalTrafficPolicy: Local`. To avoid adding extra latency from additional network hops inside Kubernetes. link:https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/[Refer to the kubernetes docs] for more information on this topic.
  62. There are other options, such as the link:https://kubernetes.github.io/ingress-nginx/[nginx-ingress controller] which can be configured to support TCP connections but in this guide we're shooting for something as simple as possible that you can do with standard Kubernetes resource types.
  63. [NOTE]
  64. **Potential Trip-up point**: On GKE, the only thing needed to associate the static IP to the
  65. load balancer is this `loadBalancerIP` field in the YAML. On other clouds, there may be additional steps
  66. to allocate the static IP to the Kubernetes cluster. Consult your local cloud documentation.
  67. ## Putting it All Together
  68. We can verify our service is running nicely like this:
  69. ```
  70. $ kubectl get service | grep neo4j-external
  71. zeke-neo4j-external LoadBalancer 10.0.5.183 35.202.123.82 7687:30529/TCP,74.3.140843/TCP,7473:30325/TCP 115s
  72. ```
  73. After all of these steps, you should end up with a cluster properly exposed. We can recover our password
  74. like so, and connect to the static IP.
  75. ```shell
  76. export NEO4J_PASSWORD=$(kubectl get secrets graph-neo4j-secrets -o yaml | grep password | sed 's/.*: //' | base64 -d)
  77. cypher-shell -a neo4j://34.66.183.174:7687 -u neo4j -p "$NEO4J_PASSWORD"
  78. ```
  79. Additionally, since we exposed port 7474, you can go to any of the static IPs on port 7474 and end up with
  80. Neo4j browser and be able to connect.
  81. [NOTE]
  82. **Security**: These methods send your Neo4j credentials without encryption. To secure communication with Neo4j you must also set up SSL.
  83. ## Where to Go Next
  84. * If you have static IPs, you can of course associate DNS with them
  85. * Once you have DNS set up you can obtain signed SSL certificates. SSL certificates can be used with Neo4j directly (see the
  86. https://neo4j.com/docs/operations-manual/current/security/ssl-framework/[SSL Framework] section of the Neo4j Operations manual).
  87. Or, in many situations, SSL certificates can be registered with the Load Balancer instead.
  88. * This in turn will let you use https and neo4j+s protocols to communicate with Neo4j.