Exposing leader node on Neo4j Causal Cluster on GKE

11/23/2019

Per the limitations noted in the user guide, some configuration is required to make bolt+routing accessible outside of the cluster. I created the following configuration to allow an application on the internal network to access the nodes inside the cluster:

apiVersion: v1
kind: Service
metadata:
  name: mygraph-neo4j-access
  labels:
    statefulset.kubernetes.io/pod-name: mygraph-neo4j-core-0
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  loadBalancerIP: 10.0.0.0
  ports:
    - name: http
      port: 7474
      targetPort: 7474
    - name: https
      port: 7473
      targetPort: 7473
    - name: bolt
      port: 7687
      targetPort: 7687
  selector:
    statefulset.kubernetes.io/pod-name: mygraph-neo4j-core-0

This seems to work without issue, except if the node crashes and another node is assigned as the leader node. In this case, the writes now point to a follower node and the write fails.

As a newcomer to GKE, I was wondering if there is a different label/selector that can be used to identify the leader node outside of the specific node name and if there isn't, what other methods could be used to identify the leader.

The documentation recommends assigning an externally valid DNS name to each node, but I'm unclear how to do this and/or if this would actually solve the issue of identifying the leader node.

-- Andy
kubernetes
neo4j

1 Answer

11/27/2019

Here is a step by step guide to configure ExternalDNS

1.Create a DNS zone which will contain the managed DNS records.

$ gcloud dns managed-zones create "external-dns-test-gcp-zalan-do" \
    --dns-name "external-dns-test.gcp.zalan.do." \
    --description "Automatically managed zone by kubernetes.io/external-dns"

2.Make a note of the nameservers that were assigned to your new zone

$ gcloud dns record-sets list \
    --zone "external-dns-test-gcp-zalan-do" \
    --name "external-dns-test.gcp.zalan.do." \
    --type NS
NAME                             TYPE  TTL    DATA
external-dns-test.gcp.zalan.do.  NS    21600  ns-cloud-e1.googledomains.com.,ns-cloud-e2.googledomains.com.,ns-cloud-e3.googledomains.com.,ns-cloud-e4.googledomains.com.

Tell the parent zone where to find the DNS records for this zone by adding the corresponding NS records there. Assuming the parent zone is "gcp-zalan-do" and the domain is "gcp.zalan.do" and that it's also hosted at Google we would do the following.

In this case it's ns-cloud-{e1-e4}.googledomains.com. but your's could slightly differ, e.g. {a1-a4}, {b1-b4} etc.

Tell the parent zone where to find the DNS records for this zone by adding the corresponding NS records there. Assuming the parent zone is "gcp-zalan-do" and the domain is "gcp.zalan.do" and that it's also hosted at Google we would do the following.

$ gcloud dns record-sets transaction start --zone "gcp-zalan-do"
$ gcloud dns record-sets transaction add ns-cloud-e{1..4}.googledomains.com. \
    --name "external-dns-test.gcp.zalan.do." --ttl 300 --type NS --zone "gcp-zalan-do"
$ gcloud dns record-sets transaction execute --zone "gcp-zalan-do"

3.Deploy ExternalDNS

Because of the way Container Engine checks permissions when you create a Role or ClusterRole, you must first create a RoleBinding that grants you all of the permissions included in the role you want to create.

kubectl create clusterrolebinding your-user-cluster-admin-binding --clusterrole=cluster-admin --user=your.google.cloud.email@example.org

Then apply one of the following manifests file to deploy ExternalDNS.

Manifest (for clusters without RBAC enabled)

Manifest (for clusters with RBAC enabled)

Use --dry-run if you want to be extra careful on the first run. Note, that you will not see any records created when you are running in dry-run mode. You can, however, inspect the logs and watch what would have been done.

You can verify if it works following these instructions

-- Ernesto U
Source: StackOverflow