Skip to content

Feast operator always deploys an online store, regardless of CR configuration #6586

Description

@dbbvitor

Expected Behavior

The Feast operator should deploy only the services declared in a FeatureStore CR. It should be possible to deploy a standalone registry or a standalone offline store, with no online store, by simply not specifying spec.services.onlineStore. This mirrors how registry and offlineStore already behave and is required by the documented federated / shared registry pattern.

Current Behavior

The operator always deploys an online store service (including a serving pod), even when the CR does not declare spec.services.onlineStore. Root cause is in ApplyDefaultsToStatus (internal/controller/services/util.go):

// default to onlineStore service deployment
if services.OnlineStore == nil {
    services.OnlineStore = &feastdevv1.OnlineStore{}
}
// ...
if services.OnlineStore.Server == nil {
    services.OnlineStore.Server = &feastdevv1.ServerConfigs{}   // forces a serving pod
}

Unlike registry (if services.Registry != nil) and offlineStore (if services.OfflineStore != nil), which are only defaulted when declared, and whose .Server is only defaulted when already present, the onlineStore block runs unconditionally and creates Server from nil.

Downstream:

  1. isOnlineStore() is always true → reconcileServices() always deploys the online store, and isOnlineServer() is always true. There's no opt-out, the OnlineStore CRD type has no disabled field. (This also makes the "at least one local server must be configured" guard in Deploy() unreachable.)
  2. The scaling admission validation is asymmetric (api/v1/featurestore_types.go): the offline rule allows the store to be absent (!has(self.services.offlineStore) || ...), but the online rule requires it to exist and be DB-backed. So scaling a registry-only/offline-only store fails admission with Scaling requires DB-backed persistence for the online store. Configure services.onlineStore.persistence.store when using replicas > 1 or autoscaling., forcing DB persistence for an online store the user never asked for.

Steps to reproduce

  1. Apply a CR declaring only a registry (or only an offline store), with no spec.services.onlineStore.
  2. kubectl get deploy -l feast.dev/name=<name> → an online/feature-server container is deployed alongside the registry (expected: registry only).
  3. Add spec.replicas: 2 (or services.scaling.autoscaling) to that registry-only CR → rejected at admission with the online-store DB-persistence error, despite no online store being declared.

Specifications

  • Version: 0.64.0
  • Platform: Kubernetes
  • Subsystem: feast-operator — internal/controller/services

Possible Solution

  1. Guard the online-store block in ApplyDefaultsToStatus with if services.OnlineStore != nil { ... } (and only default Server when already present), making it symmetric with registry/offline. Preferable to adding a new opt-out API field.
  2. Add an "online store absent" escape hatch to the online CEL rule (!has(self.services.onlineStore) || (...)), matching the offline rule.
  3. Keep noLocalCoreServerConfigured() enforcing that at least one core server is deployed.

Happy to open a PR! 😄

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions