Skip to content

Commit

Permalink
Merge pull request #13 from AustrianDataLAB/feature/ml-serving-service
Browse files Browse the repository at this point in the history
Feature/ml serving service
  • Loading branch information
mbrandstaetter authored May 31, 2024
2 parents 17b8ca9 + 708bac4 commit 65280f9
Show file tree
Hide file tree
Showing 27 changed files with 662 additions and 0 deletions.
88 changes: 88 additions & 0 deletions .github/workflows/build-serving.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: build-push-serving

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

on:
# schedule:
# - cron: '40 16 * * *'
push:
branches: [ "feature/ml-serving-service" ]
# Publish semver tags as releases.
#tags: [ 'v*.*.*' ]
pull_request:
branches: [ "dev","main" ]

env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}

jobs:
build-scan-push:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

-
name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

-
name: Extract Docker metadata
id: meta
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
-
name: Build and load
uses: docker/build-push-action@v4
with:
load: true
context: ./serving-service
file: ./serving-service/Dockerfile
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
-
name: Scan for vulnerabilities
id: scan
uses: crazy-max/ghaction-container-scan@v3
with:
image: ${{ steps.meta.outputs.tags }}
dockerfile: ./serving-service/Dockerfile

-
name: Upload SARIF file
if: ${{ steps.scan.outputs.sarif != '' }}
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ${{ steps.scan.outputs.sarif }}

-
name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
context: ./serving-service
file: ./serving-service/Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
34 changes: 34 additions & 0 deletions .github/workflows/test-serving.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Test serving-service with docker-compose
on:
push:
branches: [ "feature/ml-serving-service" ]
# Publish semver tags as releases.
#tags: [ 'v*.*.*' ]
pull_request:
branches: [ "dev","main" ]


jobs:
test-and-report:
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
-
name: checkout
uses: actions/checkout@v2
-
name: run test
working-directory: ./serving-service
run: make test

-
name: Publish Unit Test Results
uses: EnricoMi/publish-unit-test-result-action@v1
if: always()
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
files: ./serving-service/test/test-results/*.xml
-
name: TearDown
working-directory: ./serving-service
run: make down
2 changes: 2 additions & 0 deletions serving-service/.env_example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PERSISTENCE_SERVICE_URI=http://persistence-service.mlaas.svc.cluster.local:5000
TENANT=Auth_type <token>
12 changes: 12 additions & 0 deletions serving-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM cgr.dev/chainguard/python:latest-dev

WORKDIR /app

COPY requirements.txt .

RUN pip install -r requirements.txt --user

COPY __init__.py .
COPY ./main.py .

ENTRYPOINT ["python", "/app/main.py"]
16 changes: 16 additions & 0 deletions serving-service/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
IMAGE_NAME := mlaas-service-serving
CONTAINER_NAME := serving-container

.PHONY: build up down stop test

build:
docker build -t $(IMAGE_NAME) -f Dockerfile .

up:
docker-compose up --build -d

down:
docker-compose down --remove-orphans

test:
docker compose -f test/docker-compose-test.yaml up --build --abort-on-container-exit
19 changes: 19 additions & 0 deletions serving-service/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Serving Service

This service is used to serve trained models to do inference.

# Endpoints
- ``GET /``: check if the service is up, returns "Hello, World!"
- ``POST /infere``: user can infer a result by sending a request with a picture

# TODO

# Quickstart
## Requirements
- Docker
- Make

## Howto
- ``make build`` to build the service image
- ``make up/down`` if to run/cleanup the service+local backend in containers
- ``make test`` to run the tests
Empty file added serving-service/__init__.py
Empty file.
16 changes: 16 additions & 0 deletions serving-service/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: '3.5'

networks:
test_network:
driver: bridge

services:
serving-service:
build:
context: .
dockerfile: ./Dockerfile
image: mlaas-service-serving:latest
ports:
- "5001:5001"
networks:
- test_network
Binary file added serving-service/helm/serving-0.1.0.tgz
Binary file not shown.
23 changes: 23 additions & 0 deletions serving-service/helm/serving/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
21 changes: 21 additions & 0 deletions serving-service/helm/serving/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: v2
name: serving
description: A Helm chart for Kubernetes
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "0.1.0"
62 changes: 62 additions & 0 deletions serving-service/helm/serving/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "serving.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 "serving.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 "serving.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "serving.labels" -}}
helm.sh/chart: {{ include "serving.chart" . }}
{{ include "serving.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "serving.selectorLabels" -}}
app.kubernetes.io/name: {{ include "serving.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Create the name of the service account to use
*/}}
{{- define "serving.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "serving.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
43 changes: 43 additions & 0 deletions serving-service/helm/serving/templates/serving.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "serving.fullname" . }}-serving-service
labels:
{{- include "serving.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.servingService.replicas }}
selector:
matchLabels:
app: serving-service
{{- include "serving.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
app: serving-service
{{- include "serving.selectorLabels" . | nindent 8 }}
spec:
containers:
- env:
- name: KUBERNETES_CLUSTER_DOMAIN
value: {{ quote .Values.kubernetesClusterDomain }}
image: {{ .Values.servingService.servingService.image.repository }}:{{ .Values.servingService.servingService.image.tag
| default .Chart.AppVersion }}
imagePullPolicy: {{ .Values.servingService.servingService.imagePullPolicy }}
name: serving-service
ports:
- containerPort: 5001
resources: {}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "serving.fullname" . }}-serving-service
labels:
{{- include "serving.labels" . | nindent 4 }}
spec:
type: {{ .Values.servingService.type }}
selector:
app: serving-service
{{- include "serving.selectorLabels" . | nindent 4 }}
ports:
{{- .Values.servingService.ports | toYaml | nindent 2 }}
14 changes: 14 additions & 0 deletions serving-service/helm/serving/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
kubernetesClusterDomain: cluster.local
servingService:
ports:
- name: api
port: 5001
protocol: TCP
targetPort: 5001
replicas: 1
servingService:
image:
repository: ghcr.io/austriandatalab/ml-as-a-service
tag: feature-serving-service
imagePullPolicy: IfNotPresent
type: ClusterIP
Loading

0 comments on commit 65280f9

Please sign in to comment.