Go C#

Kubernetes Provider (.NET)

If Proto.Actor application is planned to be deployed inside Kubernetes cluster, then this cluster membership provider is the best choice.

Below is the example how to configure it. The full working code might be found in Realtime map example. The sample also contains a Helm chart.

Provider is available in Proto.Cluster.Kubernetes NuGet package.

(GrpcCoreRemoteConfig, IClusterProvider) ConfigureForKubernetes(IConfiguration config)
{
    var kubernetes = new Kubernetes(KubernetesClientConfiguration.InClusterConfig());
    var clusterProvider = new KubernetesProvider(kubernetes);

    var remoteConfig = GrpcNetRemoteConfig
        .BindToAllInterfaces(advertisedHost: config["ProtoActor:AdvertisedHost"])
        .WithProtoMessages(EmptyReflection.Descriptor)
        .WithProtoMessages(MessagesReflection.Descriptor)
        .WithLogLevelForDeserializationErrors(LogLevel.Critical)
        .WithRemoteDiagnostics(true);

    return (remoteConfig, clusterProvider);
}

Advertised Host

When running a Proto Cluster inside Kubernetes, there will be a local address on which the service is listening to, meaning the address inside the container, e.g. 0.0.0.0 in order to bind to all available network interfaces.

Your service will also have to expose an “Advertised Host”, this is the address which is exposed to the other cluster members, the address that points to the specific Pod of a cluster member.

This can be retrieved the following way in your service definition:

apiVersion: apps/v1
kind: Deployment
# ...
spec:
  # ...
  template:
    # ...
    spec:
      # ...
      containers:
        # ...
        - env:
          - name: "ProtoActor__AdvertisedHost"  # this is the host we expose to other cluster members
            valueFrom:
              fieldRef:
                fieldPath: status.podIP

Permissions

The application will also need some extra permissions inside Kubernetes in order to read and write metadata to its own Pods. The role will need the following permissions:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: proto-cluster
rules:
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - get
      - list
      - watch
      - patch

To bind the role to the deployment:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: proto-cluster
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: proto-cluster
subjects:
  - kind: ServiceAccount
    name: SomeServiceAccount # this is the service account that should have the role applied
apiVersion: apps/v1
kind: Deployment
# ...
spec:
  # ...
  template:
    # ...
    spec:
      # ...
      serviceAccountName: SomeServiceAccount

How it works?

Kubernetes provider registers a new member in a cluster by modifying labels on it’s own pod. It adds information about cluster name, pod port, member id and all actor kinds supported by the node. Additionally it spawns the actor responsible for cluster monitoring. Monitor uses Kubernetes API to receive updates about any pod change that runs in a namespace. Each such change is propagated by using gossip to all members.

Icon