Skip to content

Commit 41affbb

Browse files
authored
Add Dockerfile for GCP CloudRun FeatureServer (feast-dev#1887)
* Add `gcp_cloudrun` Dockerfile and resources Signed-off-by: Judah Rand <[email protected]> * Remove unnecessary config Signed-off-by: Judah Rand <[email protected]> * Sync CloudRun `app.py` with AWS Lambda Signed-off-by: Judah Rand <[email protected]>
1 parent ea00d50 commit 41affbb

File tree

5 files changed

+74
-0
lines changed

5 files changed

+74
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
FROM python:3.9-slim
2+
3+
# Allow statements and log messages to immediately appear in the Knative logs
4+
ENV PYTHONUNBUFFERED True
5+
6+
# Copy local code to the container image.
7+
ENV APP_HOME /app
8+
WORKDIR $APP_HOME
9+
10+
# Copy app handler code
11+
COPY sdk/python/feast/infra/feature_servers/gcp_cloudrun/app.py ./app.py
12+
13+
# Copy necessary parts of the Feast codebase
14+
COPY sdk/python ./sdk/python
15+
COPY protos ./protos
16+
COPY README.md ./README.md
17+
18+
# Install production dependencies.
19+
RUN pip install --no-cache-dir \
20+
-e 'sdk/python[gcp,redis]' \
21+
-r ./sdk/python/feast/infra/feature_servers/gcp_cloudrun/requirements.txt
22+
23+
# Run the web service on container startup. Here we use the gunicorn
24+
# webserver, with one worker process and 8 threads.
25+
# For environments with multiple CPU cores, increase the number of workers
26+
# to be equal to the cores available.
27+
# Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling.
28+
CMD exec gunicorn -k uvicorn.workers.UvicornWorker --bind :$PORT --workers 1 --threads 8 --timeout 0 app:app
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import base64
2+
import os
3+
import tempfile
4+
from pathlib import Path
5+
6+
from feast import FeatureStore
7+
from feast.constants import FEATURE_STORE_YAML_ENV_NAME
8+
from feast.feature_server import get_app
9+
10+
# Load RepoConfig
11+
config_base64 = os.environ[FEATURE_STORE_YAML_ENV_NAME]
12+
config_bytes = base64.b64decode(config_base64)
13+
14+
# Create a new unique directory for writing feature_store.yaml
15+
repo_path = Path(tempfile.mkdtemp())
16+
17+
with open(repo_path / "feature_store.yaml", "wb") as f:
18+
f.write(config_bytes)
19+
20+
# Initialize the feature store
21+
store = FeatureStore(repo_path=str(repo_path.resolve()))
22+
23+
# Create the FastAPI app
24+
app = get_app(store)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from pydantic import StrictBool
2+
from pydantic.typing import Literal
3+
4+
from feast.repo_config import FeastConfigBaseModel
5+
6+
7+
class GcpCloudRunFeatureServerConfig(FeastConfigBaseModel):
8+
"""Feature server config for GCP CloudRun."""
9+
10+
type: Literal["gcp_cloudrun"] = "gcp_cloudrun"
11+
"""Feature server type selector."""
12+
13+
enabled: StrictBool = False
14+
"""Whether the feature server should be launched."""
15+
16+
public: StrictBool = True
17+
"""Whether the endpoint should be publicly accessible."""
18+
19+
auth: Literal["none", "api-key"] = "none"
20+
"""Authentication method for the endpoint."""
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
gunicorn

sdk/python/feast/repo_config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
FEATURE_SERVER_CONFIG_CLASS_FOR_TYPE = {
4343
"aws_lambda": "feast.infra.feature_servers.aws_lambda.config.AwsLambdaFeatureServerConfig",
44+
"gcp_cloudrun": "feast.infra.feature_servers.gcp_cloudrun.config.GcpCloudRunFeatureServerConfig",
4445
}
4546

4647

0 commit comments

Comments
 (0)