Skip to content

Commit

Permalink
fixup: add caching to provider, k8s stuff
Browse files Browse the repository at this point in the history
Signed-off-by: Todd Baert <[email protected]>
  • Loading branch information
toddbaert committed Sep 27, 2023
1 parent bb332ed commit 6f8eeba
Show file tree
Hide file tree
Showing 7 changed files with 370 additions and 3 deletions.
4 changes: 4 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ nav:
- 'Fractional Specification': 'reference/specifications/custom-operations/fractional-operation-spec.md'
- 'Semantic Version Specification': 'reference/specifications/custom-operations/semver-operation-spec.md'
- 'String Comparison Specification': 'reference/specifications/custom-operations/string-comparison-operation-spec.md'
- 'OpenFeature Operator':
- 'Installation': 'reference/openfeature-operator/installation.md'
- 'FeatureFlagConfiguration': 'reference/openfeature-operator/crds/featureflagconfiguration.md'
- 'FlagSourceConfiguration': 'reference/openfeature-operator/crds/flagsourceconfiguration.md'
- 'Naming': 'reference/naming.md'
- 'FAQ': 'faq.md'
- 'Troubleshooting': 'troubleshooting.md'
Expand Down
2 changes: 1 addition & 1 deletion web-docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ flagd was designed with cloud-native paradigms in mind.
You can run it as a sidecar, or as a central service in your cluster.
If you're interested in a full-featured solution for using flagd in Kubernetes, consider the [OpenFeature operator](https://github.com/open-feature/open-feature-operator).

<!-- for now, we are just linking out to the OFO README, but eventually we should consider fully documenting OFO here. -->
For more information, see [OpenFeature Operator](./reference/openfeature-operator/installation.md).

---

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Feature Flag Configuration

The `FeatureFlagConfiguration` version `v1alpha2` CRD defines a CR with the following example structure:

```yaml
apiVersion: core.openfeature.dev/v1alpha2
kind: FeatureFlagConfiguration
metadata:
name: featureflagconfiguration-sample
spec:
featureFlagSpec:
flags:
foo:
state: "ENABLED"
variants:
bar: "BAR"
baz: "BAZ"
defaultVariant: "bar"
```
In the example above, we have defined a `String` type feature flag named `foo` and it is in the `ENABLED` state.
It has variants of `bar` and `baz`, referring to respected values of `BAR` and `BAZ`.
The default variant is set to`bar`.

## featureFlagSpec

The `featureFlagSpec` is an object representing the flag configurations themselves.
The documentation for this object can be found [here](https://github.com/open-feature/flagd/blob/main/docs/configuration/flag_configuration.md).
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
# FlagSourceConfigurations

`FlagSourceConfiguration` support multiple flag sources. Sources are configured as a list and given below are supported sources and their configurations,

## kubernetes aka `FeatureFlagConfiguration`

This is `FeatureFlagConfiguration` custom resource backed flagd feature flag definition.
Read more on the custom resource at the dedicated documentation of [FeatureFlagConfiguration](https://github.com/open-feature/open-feature-operator/blob/main/docs/feature_flag_configuration.md)

To refer this custom resource in `FlagSourceConfiguration`, provider type `kubernetes` is used as below example,

```yaml
sources:
- source: flags/sample-flags # FeatureFlagConfiguration - namespace/custom_resource_name
provider: kubernetes # kubernetes flag source backed by FeatureFlagConfiguration custom resource
```
## flagd-proxy
`flagd-proxy` is an alternative to direct resource access on `FeatureFlagConfiguration` custom resources.
This source type is useful when there is a need for restricting workload permissions and/or to reduce k8s API load.

Read more about proxy approach to access kubernetes resources: [flagd-proxy](https://github.com/open-feature/open-feature-operator/blob/main/docs/flagd_proxy.md)

## filepath

Injected sidecar can use volume mounted files as flag sources.
For this, provider type `filepath` is used as below example,

```yaml
sources:
- source: /etc/flagd/config.json
provider: filepath
```

## http

Feature flags can be sources from a http endpoint using provider type `http`,

```yaml
sources:
- source: http://my-flag-source.json
provider: http
httpSyncBearerToken: token # optional bearer token for the http connection
```

## grpc

Given below is an example configuration with provider type `grpc` and supported options,

```yaml
sources:
- source: my-flag-source:8080
provider: grpc
certPath: /certs/ca.cert # certificate for tls connectivity
tls: true # enforce tls connectivity
providerID: flagd-weatherapp-sidecar # identifier for this connection
selector: 'source=database,app=weatherapp' # flag filtering options
```

## Sidecar configurations

`FlagSourceConfiguration` further allows to provide configurations to the injected flagd sidecar.
Table given below is non-exhaustive list of overriding options,

| Configuration | Explanation | Default |
|---------------|-------------------------------|----------------------------|
| port | Flag evaluation endpoint port | 8013 |
| metricsPort | Metrics port | 8014 |
| evaluator | Evaluator to use | json |
| image | flagD image | ghcr.io/open-feature/flagd |
| tag | flagD image tag | Latest tag |
| probesEnabled | Enable/Disable health probes | true |

## Merging of configurations

The annotation value is a comma separated list of values following one of two patterns: `{NAME}` or `{NAMESPACE}/{NAME}`.
If no namespace is provided, it is assumed that the CR is within the same namespace as the deployed pod, for example:

```yaml
metadata:
namespace: test-ns
annotations:
openfeature.dev/enabled: "true"
openfeature.dev/flagsourceconfiguration: "config-A, test-ns-2/config-B"
```

In this example, 2 CRs are being used to configure the injected container (by default the operator uses the `flagd:main` image), `config-A` (which is assumed to be in the namespace `test-ns`) and `config-B` from the `test-ns-2` namespace, with `config-B` taking precedence in the configuration merge.

The `FlagSourceConfiguration` version `v1alpha3` CRD defines a CR with the following example structure, the documentation for this CRD can be found [here](https://github.com/open-feature/open-feature-operator/blob/main/docs/crds.md#flagsourceconfiguration):

```yaml
apiVersion: core.openfeature.dev/v1alpha3
kind: FlagSourceConfiguration
metadata:
name: flag-source-sample
spec:
metricsPort: 8080
Port: 80
evaluator: json
image: my-custom-sidecar-image
defaultSyncProvider: filepath
tag: main
sources:
- source: namespace/name
provider: kubernetes
- source: namespace/name2
- source: not-a-real-host.com
provider: http
envVars:
- name: MY_ENV_VAR
value: my-env-value
probesEnabled: true
debugLogging: false
```

The relevant `FlagSourceConfigurations` are passed to the operator by setting the `openfeature.dev/flagsourceconfiguration` annotation, and is responsible for providing the full configuration of the injected sidecar.

## Configuration Merging

When multiple `FlagSourceConfigurations` are provided, the configurations are merged. The last `CR` takes precedence over the first, with any configuration from the deprecated `FlagDSpec` field of the `FeatureFlagConfiguration` CRD taking the lowest priority.

```mermaid
flowchart LR
FlagSourceConfiguration-values -->|highest priority| environment-variables -->|lowest priority| defaults
```

An example of this behavior:

```yaml
metadata:
annotations:
openfeature.dev/enabled: "true"
openfeature.dev/flagsourceconfiguration:"config-A, config-B"
```

Config-A:

```yaml
apiVersion: core.openfeature.dev/v1alpha2
kind: FlagSourceConfiguration
metadata:
name: config-A
spec:
metricsPort: 8080
tag: latest
```

Config-B:

```yaml
apiVersion: core.openfeature.dev/v1alpha2
kind: FlagSourceConfiguration
metadata:
name: config-B
spec:
port: 8000
tag: main
```

Results in the following configuration:

```yaml
spec:
metricsPort: 8080
port: 8000
tag: main
```
132 changes: 132 additions & 0 deletions web-docs/reference/openfeature-operator/installation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Installing the OpenFeature Operator

Use the [OpenFeature Operator](https://github.com/open-feature/open-feature-operator) to install and run flagd on a Kubernetes cluster.

The operator includes flagd (no need to install flagd seperately).

## Installation

1. Install [cert-manager](https://cert-manager.io/docs/installation/) if you don't already have it on the cluster
1. Install the OpenFeature Operator (see below)
1. Define CRDs which describe the feature flag source (flagd) and the feature flags themselves
1. Annotate your deployment to enable flagd feature flagging for that pod

## Install OpenFeature operator

```bash
helm repo add openfeature https://open-feature.github.io/open-feature-operator/
helm repo update
helm upgrade --install openfeature openfeature/open-feature-operator
```

## Define feature flags

Create a namespace to house your flags:

```bash
kubectl create namespace flags
```

Next define your feature flag(s) using the [FeatureFlagConfiguration](./crds/featureflagconfiguration.md) CRD.

This example specifies one flag called `foo` which has two variants `bar` and `baz`. The `defaultVariant` is `bar`.

If this doesn't make sense, review the [concepts](../concepts/index.md) section.

```bash
kubectl apply -n flags -f - <<EOF
apiVersion: core.openfeature.dev/v1alpha2
kind: FeatureFlagConfiguration
metadata:
name: sample-flags
spec:
featureFlagSpec:
flags:
foo:
state: "ENABLED"
variants:
"bar": "BAR"
"baz": "BAZ"
defaultVariant: "bar"
targeting: {}
EOF
```

Next, tell the OpenFeature operator where to find flags.

Do so by creating a [FlagSourceConfiguration](./crds//flagsourceconfiguration.md) CRD.

This example specifies that the CRD called `sample-flags` (created above) can be found in the `flags` namespace and that the provider is `kubernetes`.

The `port` parameter defines the port on which the flagd API will be made available via the sidecar (more on this below).

```bash
kubectl apply -n flags -f - <<EOF
apiVersion: core.openfeature.dev/v1alpha3
kind: FlagSourceConfiguration
metadata:
name: flag-source-configuration
spec:
sources:
- source: flags/sample-flags
provider: kubernetes
port: 8080
EOF
```

## Enable your deployment for feature flags

The operator looks for `Deployment` objects annotated with particular annotations.

- `openfeature.dev/enabled: "true"` enables this deployment for flagd
- `openfeature.dev/flagsourceconfiguration: "flags/flag-source-configuration"` makes the given feature flag sources available to this deployment

When these two annotation are added, the OpenFeature operator will inject a sidecar into your workload.

flagd will then be available via `http://localhost` the port specified in the `FlagSourceConfiguration` (eg. `8080`)

Your Deployment YAML might look like this:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: busybox-curl
spec:
replicas: 1
selector:
matchLabels:
app: my-busybox-curl-app
template:
metadata:
labels:
app: my-busybox-curl-app
annotations:
# here are the annotations for OpenFeature Operator
openfeature.dev/enabled: "true"
openfeature.dev/flagsourceconfiguration: "flags/flag-source-configuration"
spec:
containers:
- name: busybox
image: yauritux/busybox-curl:latest
ports:
- containerPort: 80
args:
- sleep
- "30000"
```
## Pseudo-code of an application interacting with flagd sidecar
```bash
// From within the pod
curl --location 'http://localhost:8080/schema.v1.Service/ResolveString' --header 'Content-Type: application/json' --data '{ "flagKey":"foo"}'
```
In a real application, rather than `curl`, you would probably use the OpenFeature SDK with the `flagd` provider. // TODO link to a good example here.

## What does the operator do?

The operator will look for the annotations above and, when found, inject a sidecar into the relevant pods.

flagd reads the feature flag CRD(s) and makes an API endpoint available so your application can interact with flagd.
2 changes: 2 additions & 0 deletions web-docs/reference/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ For more information about Openfeature providers, see the [OpenFeature documenta
Providers for flagd come in two flavors: those that are built to communicate with a flagd instance (over HTTP or gRPC) and those that embed flagd's evaluation engine directly (note that some providers are capable of operating in either mode). For more information on how to deploy and use flagd, see [architecture](../architecture.md) and [deployment](../deployment.md).

For a catalog of available flagd providers, check out the [OpenFeature ecosystem](https://openfeature.dev/ecosystem?instant_search%5Bquery%5D=flagd&instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider) page.

For information on implementing a flagd provider, see the specifications for [RPC](./specifications/rpc-providers.md) and [in-process](./specifications/in-process-providers.md) providers.
Loading

0 comments on commit 6f8eeba

Please sign in to comment.