open-feature / open-feature-operator

A Kubernetes feature flag operator
https://openfeature.dev
Apache License 2.0
198 stars 38 forks source link

[OFO/flagd] Research and document flagd client support #371

Closed toddbaert closed 5 months ago

toddbaert commented 1 year ago

With client spec changes and SDKs on the way, we need to decide what sort of support we want for the client/web in OFO (if any). We already have the required bulk-resolution functionality in flagd, as well as CORs options to support local development

@james-milligan already did some research here with a PoC deployment, I believe. That may feed into this discussion.

If we were to support this, we'd want enhancements to the operator that could facilitate the following:

Non functionally, we should consider:

skyerus commented 1 year ago

POC

I have put together a POC using kubernetes gateway API (KGA) as means to ingest external traffic (intended as successor to an ingress).

The deployment pattern this POC is catered to:

Assuming that the above is true (application is readily deployed and ready to receive external traffic), one can create a ClientSideConfiguration CR (naming TBD). The creation of a ClientSideConfiguration CR triggers its reconciliation loop which does the following:

The end result is two exposed applications: the client application and flagd. Both are exposed by the Gateway, which routes the request to the appropriate service based on the matching of the Host header (this is checked against the hostname defined in the Gateway's listeners). The following diagram depicts this.

ofo-flagd-client-support-architecture

Note: To get this to work locally I had to add hostnames to my hosts file to route them to localhost. Without this the browser doesn't send the appropriate Host header to the Gateway, preventing it from being able to route the request.

How to run the POC

Prerequisites:

# build OFO
IMG=ghcr.io/open-feature/open-feature-operator:local ARCH=arm64 make docker-build
# create kind cluster
kind create cluster --config ./test/e2e/kind-cluster.yml
# load OFO into cluster
kind load docker-image ghcr.io/open-feature/open-feature-operator:local
# pull ofo-client-app
docker pull ghcr.io/skyerus/ofo-client-app:latest
# load ofo-client-app into cluster 
kind load docker-image ghcr.io/skyerus/ofo-client-app:latest
# deploy OFO
IMG=ghcr.io/open-feature/open-feature-operator:local make deploy-operator
# install KGA CRDs
kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
  { kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.6.1" | kubectl apply -f -; }
# install istio gateway
istioctl install --set profile=minimal -y
# deploy resources
kubectl apply -f config/samples/dev.yaml
# add hostnames to hosts file (location of hosts file is macOS specific in this example)
sudo sh -c 'echo "127.0.0.1 ofoclientapp.com" >> /private/etc/hosts'
sudo sh -c 'echo "127.0.0.1 flagd.ofoclientapp.com" >> /private/etc/hosts'
# port forward 8080 to the gateway pod
kubectl port-forward $(kubectl get pods --selector=istio.io/gateway-name=clientsidegateway -o \
  jsonpath='{.items[*].metadata.name}') 8080:80

Go to http://ofoclientapp.com:8080/ in your browser and click the Update color button to verify that the traffic is routed to flagd correctly.

Questions/Concerns

Further Steps

AlexsJones commented 1 year ago

g that the above is true (application is readily deployed

Hi, it's me again, playing devil's advocate here.

What's the need to connect to the client side to flagd, what do we gain doing this over using the client side SDKs elsewhere?

If you think about the story behind this; someone is going to be using a browser-based experience but the flags are completely unexposed and only accessible through a custom resource; do you have a use case in mind for this? Are we thinking of also having a Web API accessible through the gateway to program flags?

skyerus commented 1 year ago

What's the need to connect to the client side to flagd, what do we gain doing this over using the client side SDKs elsewhere?

I'm not sure I'm following, are you suggesting that the client connects to flagd indirectly via some existing server?

someone is going to be using a browser-based experience but the flags are completely unexposed and only accessible through a custom resource

The flags are exposed in the demonstrated POC, or are you referring to the mutation of them being unexposed?

do you have a use case in mind for this?

It could enable user interfaces to react dynamically to user context based on flags by going straight to the flag source (flagd).

Are we thinking of also having a Web API accessible through the gateway to program flags?

To alter flagd's internal state you mean? Interesting idea but I'd argue it's out of scope for the topic at hand

AlexsJones commented 1 year ago

I am querying whether there is a desire to have flagD as a provider the client SDK's can connect to is the goal. I was curious whether there are people interested in this pattern.

For example, the in K8s pattern makes sense when its workloads a backend dev might be controlling or a website you're running from a pod. It gets a bit more complex when you're an iOS developer that hits a KGA endpoint for flagD as a provider. That's where I'm trying to really identify what we're talking about.

skyerus commented 1 year ago

Just so I'm clear, are you suggesting that there might not be enough value in exposing flagd for use by client side applications? For those use-cases, defer to a vendor built for this?

toddbaert commented 1 year ago

I am querying whether there is a desire to have flagD as a provider the client SDK's can connect to is the goal.

There's a definite interest internally at Dynatrace. Specifically usage in web applications (directly from the browser) is desired.

Anecdotally, in the vendor interviews I've been party to with @moredip, we typically heard that client use-cases represent about half of the usage most vendors see.

Some examples of this in partner vendors:

https://docs.flagsmith.com/clients/javascript https://help.split.io/hc/en-us/sections/12619122908557-Client-side-SDKs https://docs.cloudbees.com/docs/cloudbees-feature-management-api/latest/api-reference/javascript-browser-api https://docs.launchdarkly.com/sdk/client-side

I think as a reference implementation, we more or less need to support this important paradigm in flagd.

skyerus commented 1 year ago

See this OFEP comment for the current plan for flagd client support.

skyerus commented 1 year ago

I've created a new OFEP outlining an alternative solution avoiding the previously discussed concerns & limitations.

beeme1mr commented 5 months ago

Addressed by https://github.com/open-feature/open-feature-operator/pull/633