You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 3a4abf5
Browse filesBrowse the repository at this point in the historyBrowse files
feat: Add packaged feature repository support to Feast Operator
Add spec.feastProjectDir.packaged for repositories distributed in feature server images, including staged and direct-use lifecycle modes, canonical path validation, generated CRD artifacts, documentation, and tests.
Integrate the init image override introduced by feast-dev#6598 with this precedence: services.initImage, packaged.image, RELATED_IMAGE_FEATURE_SERVER, then DefaultImage.
Signed-off-by: Shumin <shumin.zheng@outlook.com>
The repository can be added to a Feast feature-server image with a Dockerfile such as:
175
+
176
+
```dockerfile
177
+
FROM quay.io/feastdev/feature-server:latest
178
+
COPY feature_repo/ /opt/feast/feature_repo/
179
+
```
180
+
181
+
`featureRepoPath` must be a canonical absolute, non-root path: do not use `.`, `..`,
182
+
repeated separators, or a trailing separator. Put it outside operator-mounted locations
183
+
such as `/feast-data`; a volume mounted there would hide files baked into the image. When
184
+
init containers are enabled, the packaged path also must not equal, contain, or be
185
+
contained by the staged repository path.
186
+
187
+
With init containers enabled (the default), each Pod starts in this order:
188
+
189
+
1. `feast-init` replaces the operator-managed staged repository with a fresh copy of the
190
+
repository from `packaged.featureRepoPath`. With the default storage configuration,
191
+
for example, it copies `/opt/feast/feature_repo` from the image to
192
+
`/feast-data/<feastProject>/feature_repo`.
193
+
2. In the staged copy only, `feast-init` replaces `feature_store.yaml` (if exists in the
194
+
baked image) with the configuration generated from the FeatureStore resource. The file
195
+
baked into the image is not modified. The Python feature definitions come from the
196
+
packaged repository, while the FeatureStore resource remains authoritative for runtime
197
+
configuration.
198
+
3. When `services.runFeastApplyOnInit` is omitted or `true` (the default), `feast-apply`
199
+
runs `feast apply` from the staged repository using the packaged image. Setting it to
200
+
`false`skips only this step; repository staging still occurs.
201
+
4. The Feast service containers start with the staged repository as their working
202
+
directory.
203
+
204
+
The repository baked into the image is therefore the source artifact, while the staged
205
+
repository is the runtime copy used by `feast apply` and the Feast services.
206
+
207
+
For a baked repository whose own `feature_store.yaml` must remain authoritative, disable
208
+
init containers:
209
+
210
+
```yaml
211
+
services:
212
+
disableInitContainers: true
213
+
```
214
+
215
+
In that mode, Feast service containers use `featureRepoPath` directly and neither staging
216
+
nor `feast apply` runs during pod initialization. The Operator does not update the registry,
217
+
so `feast apply` must be handled separately—for example, by CI/CD or a separately managed
218
+
Kubernetes Job or CronJob—whenever the packaged feature definitions change.
219
+
220
+
The packaged `image` is optional. When set, it is the default for repository initialization,
221
+
`feast apply`, and Feast services. `services.initImage` takes precedence for the
222
+
`feast-init`and `feast-apply` init containers, while an explicit image on an individual
223
+
service takes precedence for that service. When the packaged image is omitted, the operator
224
+
uses `RELATED_IMAGE_FEATURE_SERVER` or its built-in feature-server image fallback.
225
+
226
+
### Full `packaged` field reference
227
+
228
+
| Field | Type | Required | Description |
229
+
|-------|------|----------|-------------|
230
+
| `featureRepoPath` | string | yes | Canonical absolute, non-root path to the feature repository in the image; it must not overlap the staged repository path |
231
+
| `image` | string | no | Image containing the repository; defaults to the operator feature-server image |
232
+
233
+
---
234
+
154
235
## `feast apply` on startup
155
236
156
-
By default, when the init container completes (git clone or `feast init`), the operator runs
237
+
By default, when repository initialization completes (git clone, `feast init`, or packaged
238
+
repository staging), the operator runs
157
239
`feast apply`before starting the servers. This registers all feature definitions with the
158
240
registry.
159
241
@@ -175,9 +257,8 @@ services:
175
257
176
258
## When `feastProjectDir` is omitted
177
259
178
-
If neither `git` nor `init` is set, the operator mounts an empty directory. In this case
179
-
you must supply a `feature_store.yaml` through another mechanism (e.g. a ConfigMap volume
180
-
mount via `services.volumes` + `volumeMounts`).
260
+
If `feastProjectDir` is not set, the operator defaults to `feastProjectDir.init: {}` and
261
+
creates a local template repository.
181
262
182
263
---
183
264
@@ -188,3 +269,4 @@ mount via `services.volumes` + `volumeMounts`).
188
269
- [Sample: private git repo with token](https://github.com/feast-dev/feast/blob/stable/infra/feast-operator/config/samples/v1_featurestore_git_token.yaml)
189
270
- [Sample: monorepo with featureRepoPath](https://github.com/feast-dev/feast/blob/stable/infra/feast-operator/config/samples/v1_featurestore_git_repopath.yaml)
Copy file name to clipboardExpand all lines: docs/how-to-guides/production-deployment-topologies.md
+19-9Lines changed: 19 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1066,12 +1066,15 @@ Production environments in regulated industries (finance, government, defense) o
1066
1066
1067
1067
### Default init container behavior
1068
1068
1069
-
When `feastProjectDir` is set on the FeatureStore CR, the operator creates up to two init containers:
1069
+
When `feastProjectDir` is set on the FeatureStore CR, the operator creates up to two init containers unless `services.disableInitContainers` is `true`:
1070
1070
1071
-
1. **`feast-init`** — bootstraps the feature repository by running either `git clone` (if `feastProjectDir.git` is set) or `feast init` (if `feastProjectDir.init` is set), then writes the generated `feature_store.yaml` into the repo directory.
1071
+
1. **`feast-init`** — bootstraps the feature repository by running `git clone`, `feast init`, or copying a repository from `feastProjectDir.packaged.featureRepoPath`. It then writes the operator-generated `feature_store.yaml` into the initialized repository.
1072
1072
2. **`feast-apply`** — runs `feast apply` to register feature definitions in the registry. Controlled by `runFeastApplyOnInit` (defaults to `true`). Skipped when `disableInitContainers` is `true`.
1073
1073
1074
-
In air-gapped environments, `git clone` will fail because the cluster cannot reach external Git repositories. The solution is to **pre-bake** the feature repository into a custom container image and disable the init containers entirely.
1074
+
In air-gapped environments, use `feastProjectDir.packaged` to identify a feature repository baked into an image. The operator supports two lifecycle modes:
1075
+
1076
+
* Keep init containers enabled to refresh shared storage from the image, generate configuration from the FeatureStore CR, and optionally run `feast apply`.
1077
+
* Set `services.disableInitContainers: true` to run directly from the baked path and treat its `feature_store.yaml` as authoritative.
1. **Build a custom container image** that bundles the feature repository and all Python dependencies into the Feast base image.
1107
1110
2. **Push** the image to your internal container registry.
1108
-
3. **Set `services.disableInitContainers: true`** on the FeatureStore CR to skip `git clone` / `feast init` and `feast apply`.
1109
-
4. **Override the image** on each service using the per-service `image` field.
1111
+
3. **Configure `feastProjectDir.packaged`** with the image and the canonical absolute path to the bundled repository. Do not use `.`, `..`, repeated separators, or a trailing separator, and keep the path outside operator-mounted locations such as `/feast-data` so it cannot overlap the staged repository.
1112
+
4. **Choose the lifecycle:** leave init containers enabled for operator-managed configuration and `feast apply`, or set `services.disableInitContainers: true` to use the baked repository and configuration directly.
1110
1113
5. **Set `imagePullPolicy: IfNotPresent`** (or `Never` if images are pre-loaded on nodes).
1111
1114
6. **Configure `imagePullSecrets`** on the namespace's ServiceAccount — the FeatureStore CRD does not expose an `imagePullSecrets` field, so use the standard Kubernetes approach of attaching secrets to the ServiceAccount that the pods run under.
Copy file name to clipboardExpand all lines: infra/feast-operator/README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ This is a K8s Operator that can be used to deploy and manage **Feast**, an open
7
7
8
8
| Guide | Topic |
9
9
|-------|-------|
10
-
|[1 — Project Provisioning](https://docs.feast.dev/how-to-guides/feast-operator/01-project-provisioning)|`feastProjectDir`: git clone vs `feast init` templates|
10
+
|[1 — Project Provisioning](https://docs.feast.dev/how-to-guides/feast-operator/01-project-provisioning)|`feastProjectDir`: git clone, `feast init`, or a repository packaged in an image|
11
11
|[2 — Persistence](https://docs.feast.dev/how-to-guides/feast-operator/02-persistence)| File (path + PVC) vs DB store for offline/online/registry; Secret format |
0 commit comments