Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add helm charts for feast jobservice #1081

Merged
merged 7 commits into from
Oct 23, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ compile-protos-python: install-python-ci-dependencies
@$(foreach dir,$(PROTO_TYPE_SUBDIRS),cd ${ROOT_DIR}/protos; python -m grpc_tools.protoc -I. --python_out=../sdk/python/ --mypy_out=../sdk/python/ feast/$(dir)/*.proto;)
@$(foreach dir,$(PROTO_SERVICE_SUBDIRS),cd ${ROOT_DIR}/protos; python -m grpc_tools.protoc -I. --grpc_python_out=../sdk/python/ feast/$(dir)/*.proto;)
cd ${ROOT_DIR}/protos; python -m grpc_tools.protoc -I. --python_out=../sdk/python/ --mypy_out=../sdk/python/ tensorflow_metadata/proto/v0/*.proto
cd ${ROOT_DIR}/protos; python -m grpc_tools.protoc -I. --python_out=../sdk/python/ --grpc_python_out=../sdk/python/ --mypy_out=../sdk/python/ feast/third_party/grpc/health/v1/*.proto

install-python: compile-protos-python
cd sdk/python; python setup.py develop
Expand Down
4 changes: 4 additions & 0 deletions infra/charts/feast/charts/feast-jobservice/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
description: Feast Job Coontroller manage ingestion jobs.
name: feast-jobservice
version: 0.8-SNAPSHOT
71 changes: 71 additions & 0 deletions infra/charts/feast/charts/feast-jobservice/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
feast-jobcontroller
==========
Feast Job Controller manage ingestion jobs.

Current chart version is `0.8-SNAPSHOT`





## Chart Values

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| "application-generated.yaml".enabled | bool | `true` | Flag to include Helm generated configuration for http port, Feast database URL, Kafka bootstrap servers and jobs metrics host. This is useful for deployment that uses default configuration for Kafka, Postgres and StatsD exporter. Please set `application-override.yaml` to override this configuration. |
| "application-override.yaml" | object | `{"enabled":true}` | Configuration to override the default [application.yaml](https://github.com/feast-dev/feast/blob/master/job-controller/src/main/resources/application.yml). Will be created as a ConfigMap. `application-override.yaml` has a higher precedence than `application-secret.yaml` |
| "application-secret.yaml" | object | `{"enabled":true}` | Configuration to override the default [application.yaml](https://github.com/feast-dev/feast/blob/master/job-controller/src/main/resources/application.yml). Will be created as a Secret. `application-override.yaml` has a higher precedence than `application-secret.yaml`. It is recommended to either set `application-override.yaml` or `application-secret.yaml` only to simplify config management. |
| "application.yaml".enabled | bool | `true` | Flag to include the default [configuration](https://github.com/feast-dev/feast/blob/master/job-controller/src/main/resources/application.yml). Please set `application-override.yaml` to override this configuration. |
| envOverrides | object | `{}` | Extra environment variables to set |
| gcpProjectId | string | `""` | Project ID to use when using Google Cloud services such as BigQuery, Cloud Storage and Dataflow |
| gcpServiceAccount.enabled | bool | `false` | Flag to use [service account](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) JSON key |
| gcpServiceAccount.existingSecret.key | string | `"credentials.json"` | Key in the secret data (file name of the service account) |
| gcpServiceAccount.existingSecret.name | string | `"feast-gcp-service-account"` | Name of the existing secret containing the service account |
| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
| image.repository | string | `"gcr.io/kf-feast/feast-jobcontroller"` | Docker image repository |
| image.tag | string | `"develop"` | Image tag |
| ingress.grpc.annotations | object | `{}` | Extra annotations for the ingress |
| ingress.grpc.auth.enabled | bool | `false` | Flag to enable auth |
| ingress.grpc.class | string | `"nginx"` | Which ingress controller to use |
| ingress.grpc.enabled | bool | `false` | Flag to create an ingress resource for the service |
| ingress.grpc.hosts | list | `[]` | List of hostnames to match when routing requests |
| ingress.grpc.https.enabled | bool | `true` | Flag to enable HTTPS |
| ingress.grpc.https.secretNames | object | `{}` | Map of hostname to TLS secret name |
| ingress.grpc.whitelist | string | `""` | Allowed client IP source ranges |
| ingress.http.annotations | object | `{}` | Extra annotations for the ingress |
| ingress.http.auth.authUrl | string | `"http://auth-server.auth-ns.svc.cluster.local/auth"` | URL to an existing authentication service |
| ingress.http.auth.enabled | bool | `false` | Flag to enable auth |
| ingress.http.class | string | `"nginx"` | Which ingress controller to use |
| ingress.http.enabled | bool | `false` | Flag to create an ingress resource for the service |
| ingress.http.hosts | list | `[]` | List of hostnames to match when routing requests |
| ingress.http.https.enabled | bool | `true` | Flag to enable HTTPS |
| ingress.http.https.secretNames | object | `{}` | Map of hostname to TLS secret name |
| ingress.http.whitelist | string | `""` | Allowed client IP source ranges |
| javaOpts | string | `nil` | [JVM options](https://docs.oracle.com/cd/E22289_01/html/821-1274/configuring-the-default-jvm-and-java-arguments.html). For better performance, it is advised to set the min and max heap: <br> `-Xms2048m -Xmx2048m` |
| livenessProbe.enabled | bool | `false` | Flag to enabled the probe |
| livenessProbe.failureThreshold | int | `5` | Min consecutive failures for the probe to be considered failed |
| livenessProbe.initialDelaySeconds | int | `60` | Delay before the probe is initiated |
| livenessProbe.periodSeconds | int | `10` | How often to perform the probe |
| livenessProbe.successThreshold | int | `1` | Min consecutive success for the probe to be considered successful |
| livenessProbe.timeoutSeconds | int | `5` | When the probe times out |
| logLevel | string | `"WARN"` | Default log level, use either one of `DEBUG`, `INFO`, `WARN` or `ERROR` |
| logType | string | `"Console"` | Log format, either `JSON` or `Console` |
| nodeSelector | object | `{}` | Node labels for pod assignment |
| podLabels | object | `{}` | Labels to be added to Feast Job Controller pods |
| postgresql.existingSecret | string | `""` | Existing secret to use for authenticating to Postgres |
| prometheus.enabled | bool | `true` | Flag to enable scraping of Feast Job Controller metrics |
| readinessProbe.enabled | bool | `true` | Flag to enabled the probe |
| readinessProbe.failureThreshold | int | `5` | Min consecutive failures for the probe to be considered failed |
| readinessProbe.initialDelaySeconds | int | `20` | Delay before the probe is initiated |
| readinessProbe.periodSeconds | int | `10` | How often to perform the probe |
| readinessProbe.successThreshold | int | `1` | Min consecutive success for the probe to be considered successful |
| readinessProbe.timeoutSeconds | int | `10` | When the probe times out |
| replicaCount | int | `1` | Number of pods that will be created |
| resources | object | `{}` | CPU/memory [resource requests/limit](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container) |
| service.grpc.nodePort | string | `nil` | Port number that each cluster node will listen to |
| service.grpc.port | int | `6565` | Service port for GRPC requests |
| service.grpc.targetPort | int | `6565` | Container port serving GRPC requests |
| service.http.nodePort | string | `nil` | Port number that each cluster node will listen to |
| service.http.port | int | `80` | Service port for HTTP requests |
| service.http.targetPort | int | `8080` | Container port serving HTTP requests and Prometheus metrics |
| service.type | string | `"ClusterIP"` | Kubernetes service type |
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "feast-jobservice.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "feast-jobservice.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "feast-jobservice.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Common labels
*/}}
{{- define "feast-jobservice.labels" -}}
app.kubernetes.io/name: {{ include "feast-jobservice.name" . }}
helm.sh/chart: {{ include "feast-jobservice.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{{- /*
This takes an array of three values:
- the top context
- the feast component
- the service protocol
- the ingress context
*/ -}}
{{- define "feast.ingress" -}}
{{- $top := (index . 0) -}}
{{- $component := (index . 1) -}}
{{- $protocol := (index . 2) -}}
{{- $ingressValues := (index . 3) -}}
apiVersion: extensions/v1beta1
kind: Ingress
{{ include "feast.ingress.metadata" . }}
spec:
rules:
{{- range $host := $ingressValues.hosts }}
- host: {{ $host }}
http:
paths:
- path: /
backend:
serviceName: {{ include (printf "feast-%s.fullname" $component) $top }}
servicePort: {{ index $top.Values "service" $protocol "port" }}
{{- end }}
{{- if $ingressValues.https.enabled }}
tls:
{{- range $host := $ingressValues.hosts }}
- secretName: {{ index $ingressValues.https.secretNames $host | default (splitList "." $host | rest | join "-" | printf "%s-tls") }}
hosts:
- {{ $host }}
{{- end }}
{{- end -}}
{{- end -}}

{{- define "feast.ingress.metadata" -}}
{{- $commonMetadata := fromYaml (include "common.metadata" (first .)) }}
{{- $overrides := fromYaml (include "feast.ingress.metadata-overrides" .) -}}
{{- toYaml (merge $overrides $commonMetadata) -}}
{{- end -}}

{{- define "feast.ingress.metadata-overrides" -}}
{{- $top := (index . 0) -}}
{{- $component := (index . 1) -}}
{{- $protocol := (index . 2) -}}
{{- $ingressValues := (index . 3) -}}
{{- $commonFullname := include "common.fullname" $top }}
metadata:
name: {{ $commonFullname }}-{{ $component }}-{{ $protocol }}
annotations:
kubernetes.io/ingress.class: {{ $ingressValues.class | quote }}
{{- if (and (eq $ingressValues.class "nginx") $ingressValues.auth.enabled) }}
nginx.ingress.kubernetes.io/auth-url: {{ $ingressValues.auth.authUrl | quote }}
nginx.ingress.kubernetes.io/auth-response-headers: "x-auth-request-email, x-auth-request-user"
nginx.ingress.kubernetes.io/auth-signin: "https://{{ $ingressValues.auth.signinHost | default (splitList "." (index $ingressValues.hosts 0) | rest | join "." | printf "auth.%s")}}/oauth2/start?rd=/r/$host/$request_uri"
{{- end }}
{{- if (and (eq $ingressValues.class "nginx") $ingressValues.whitelist) }}
nginx.ingress.kubernetes.io/whitelist-source-range: {{ $ingressValues.whitelist | quote -}}
{{- end }}
{{- if (and (eq $ingressValues.class "nginx") (eq $protocol "grpc") ) }}
# TODO: Allow choice of GRPC/GRPCS
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
{{- end }}
{{- if $ingressValues.annotations -}}
{{ include "common.annote" $ingressValues.annotations | indent 4 }}
{{- end }}
{{- end -}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "feast-jobservice.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "feast-jobservice.name" . }}
component: jobservice
chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
data:
application-generated.yaml: |
{{- if index .Values "application-generated.yaml" "enabled" }}
feast:
core-host: {{ .Release.Name }}-feast-core
stream:
type: kafka
options:
bootstrapServers: {{ .Release.Name }}-kafka:9092
topic: feast
jobs:
metrics:
enabled: true
type: statsd
host: {{ .Release.Name }}-prometheus-statsd-exporter-udp
port: 9125

server:
port: {{ .Values.service.http.targetPort }}
{{- end }}

application-override.yaml: |
{{- if index .Values "application-override.yaml" "enabled" }}
{{- toYaml (index .Values "application-override.yaml") | nindent 4 }}
{{- end }}
156 changes: 156 additions & 0 deletions infra/charts/feast/charts/feast-jobservice/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "feast-jobservice.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "feast-jobservice.name" . }}
component: jobservice
chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "feast-jobservice.name" . }}
component: jobservice
release: {{ .Release.Name }}
template:
metadata:
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
{{- if .Values.prometheus.enabled }}
prometheus.io/path: /metrics
prometheus.io/port: "{{ .Values.service.http.targetPort }}"
prometheus.io/scrape: "true"
{{- end }}
labels:
app: {{ template "feast-jobservice.name" . }}
component: jobservice
release: {{ .Release.Name }}
{{- if .Values.podLabels }}
{{ toYaml .Values.podLabels | nindent 8 }}
{{- end }}
spec:
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}

volumes:
- name: {{ template "feast-jobservice.fullname" . }}-config
configMap:
name: {{ template "feast-jobservice.fullname" . }}
- name: {{ template "feast-jobservice.fullname" . }}-secret
secret:
secretName: {{ template "feast-jobservice.fullname" . }}
{{- if .Values.gcpServiceAccount.enabled }}
- name: {{ template "feast-jobservice.fullname" . }}-gcp-service-account
secret:
secretName: {{ .Values.gcpServiceAccount.existingSecret.name }}
{{- end }}

containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
imagePullPolicy: {{ .Values.image.pullPolicy }}

volumeMounts:
- name: {{ template "feast-jobservice.fullname" . }}-config
mountPath: /etc/feast
- name: {{ template "feast-jobservice.fullname" . }}-secret
mountPath: /etc/secrets/feast
readOnly: true
{{- if .Values.gcpServiceAccount.enabled }}
- name: {{ template "feast-jobservice.fullname" . }}-gcp-service-account
mountPath: /etc/secrets/google
readOnly: true
{{- end }}

env:
- name: LOG_TYPE
value: {{ .Values.logType | quote }}
- name: LOG_LEVEL
value: {{ .Values.logLevel | quote }}

{{- if .Values.postgresql.existingSecret }}
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.postgresql.existingSecret }}
key: postgresql-password
{{- end }}

{{- if .Values.gcpServiceAccount.enabled }}
- name: GOOGLE_APPLICATION_CREDENTIALS
value: /etc/secrets/google/{{ .Values.gcpServiceAccount.existingSecret.key }}
{{- end }}

{{- if .Values.gcpProjectId }}
- name: GOOGLE_CLOUD_PROJECT
value: {{ .Values.gcpProjectId | quote }}
{{- end }}

{{- if .Values.javaOpts }}
- name: JAVA_TOOL_OPTIONS
value: {{ .Values.javaOpts }}
{{- end }}

{{- range $key, $value := .Values.envOverrides }}
- name: {{ printf "%s" $key | replace "." "_" | upper | quote }}
{{- if eq (kindOf $value) "map" }}
valueFrom:
{{- toYaml $value | nindent 12 }}
{{- else }}
value: {{ $value | quote }}
{{- end }}
{{- end }}

command:
- feast
- server
# - --spring.config.location=
# {{- if index .Values "application.yaml" "enabled" -}}
# classpath:/application.yml
# {{- end }}
# {{- if index .Values "application-generated.yaml" "enabled" -}}
# ,file:/etc/feast/application-generated.yaml
# {{- end }}
# {{- if index .Values "application-secret.yaml" "enabled" -}}
# ,file:/etc/secrets/feast/application-secret.yaml
# {{- end }}
# {{- if index .Values "application-override.yaml" "enabled" -}}
# ,file:/etc/feast/application-override.yaml
# {{- end }}
ports:
- name: http
containerPort: {{ .Values.service.http.targetPort }}
- name: grpc
containerPort: {{ .Values.service.grpc.targetPort }}

{{- if .Values.livenessProbe.enabled }}
livenessProbe:
exec:
command: ["/usr/bin/grpc-health-probe", "-addr=:{{ .Values.service.grpc.targetPort }}"]
initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
successThreshold: {{ .Values.livenessProbe.successThreshold }}
timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
{{- end }}

{{- if .Values.readinessProbe.enabled }}
readinessProbe:
exec:
command: ["/usr/bin/grpc-health-probe", "-addr=:{{ .Values.service.grpc.targetPort }}"]
initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
successThreshold: {{ .Values.readinessProbe.successThreshold }}
timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
{{- end }}

resources:
{{- toYaml .Values.resources | nindent 10 }}
Loading