Skip to content

Commit

Permalink
Add Dockerfile for GCP CloudRun FeatureServer (#1887)
Browse files Browse the repository at this point in the history
* Add `gcp_cloudrun` Dockerfile and resources

Signed-off-by: Judah Rand <17158624+judahrand@users.noreply.github.com>

* Remove unnecessary config

Signed-off-by: Judah Rand <17158624+judahrand@users.noreply.github.com>

* Sync CloudRun `app.py` with AWS Lambda

Signed-off-by: Judah Rand <17158624+judahrand@users.noreply.github.com>
  • Loading branch information
judahrand authored Oct 20, 2021
1 parent ea00d50 commit 41affbb
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 0 deletions.
28 changes: 28 additions & 0 deletions sdk/python/feast/infra/feature_servers/gcp_cloudrun/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
FROM python:3.9-slim

# Allow statements and log messages to immediately appear in the Knative logs
ENV PYTHONUNBUFFERED True

# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME

# Copy app handler code
COPY sdk/python/feast/infra/feature_servers/gcp_cloudrun/app.py ./app.py

# Copy necessary parts of the Feast codebase
COPY sdk/python ./sdk/python
COPY protos ./protos
COPY README.md ./README.md

# Install production dependencies.
RUN pip install --no-cache-dir \
-e 'sdk/python[gcp,redis]' \
-r ./sdk/python/feast/infra/feature_servers/gcp_cloudrun/requirements.txt

# Run the web service on container startup. Here we use the gunicorn
# webserver, with one worker process and 8 threads.
# For environments with multiple CPU cores, increase the number of workers
# to be equal to the cores available.
# Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling.
CMD exec gunicorn -k uvicorn.workers.UvicornWorker --bind :$PORT --workers 1 --threads 8 --timeout 0 app:app
24 changes: 24 additions & 0 deletions sdk/python/feast/infra/feature_servers/gcp_cloudrun/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import base64
import os
import tempfile
from pathlib import Path

from feast import FeatureStore
from feast.constants import FEATURE_STORE_YAML_ENV_NAME
from feast.feature_server import get_app

# Load RepoConfig
config_base64 = os.environ[FEATURE_STORE_YAML_ENV_NAME]
config_bytes = base64.b64decode(config_base64)

# Create a new unique directory for writing feature_store.yaml
repo_path = Path(tempfile.mkdtemp())

with open(repo_path / "feature_store.yaml", "wb") as f:
f.write(config_bytes)

# Initialize the feature store
store = FeatureStore(repo_path=str(repo_path.resolve()))

# Create the FastAPI app
app = get_app(store)
20 changes: 20 additions & 0 deletions sdk/python/feast/infra/feature_servers/gcp_cloudrun/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from pydantic import StrictBool
from pydantic.typing import Literal

from feast.repo_config import FeastConfigBaseModel


class GcpCloudRunFeatureServerConfig(FeastConfigBaseModel):
"""Feature server config for GCP CloudRun."""

type: Literal["gcp_cloudrun"] = "gcp_cloudrun"
"""Feature server type selector."""

enabled: StrictBool = False
"""Whether the feature server should be launched."""

public: StrictBool = True
"""Whether the endpoint should be publicly accessible."""

auth: Literal["none", "api-key"] = "none"
"""Authentication method for the endpoint."""
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gunicorn
1 change: 1 addition & 0 deletions sdk/python/feast/repo_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

FEATURE_SERVER_CONFIG_CLASS_FOR_TYPE = {
"aws_lambda": "feast.infra.feature_servers.aws_lambda.config.AwsLambdaFeatureServerConfig",
"gcp_cloudrun": "feast.infra.feature_servers.gcp_cloudrun.config.GcpCloudRunFeatureServerConfig",
}


Expand Down

0 comments on commit 41affbb

Please sign in to comment.