Add API deployment instructions and artifacts. (#7)
This commit is contained in:
Родитель
2da72244f1
Коммит
7dcdab4311
|
@ -1,7 +0,0 @@
|
|||
apiVersion: azure.com/v1alpha2
|
||||
kind: CustomMetric
|
||||
metadata:
|
||||
name: camera-trap-detection-sync-appinsights-metric-detect
|
||||
spec:
|
||||
metric:
|
||||
metricName: customMetrics//CURRENT_REQUESTS/v1/camera-trap/detection-sync/detect
|
|
@ -0,0 +1,7 @@
|
|||
apiVersion: azure.com/v1alpha2
|
||||
kind: CustomMetric
|
||||
metadata:
|
||||
name: service-name-appinsights-metric-endpointname
|
||||
spec:
|
||||
metric:
|
||||
metricName: customMetrics//CURRENT_REQUESTS/service-name/endpointname
|
|
@ -0,0 +1,12 @@
|
|||
apiVersion: v1
|
||||
description: My description.
|
||||
name: service-name
|
||||
version: 1.0.0
|
||||
keywords:
|
||||
- sync
|
||||
home: "https://www.microsoft.com/en-us/aiforearth"
|
||||
sources:
|
||||
- "https://github.com/microsoft/AIforEarth-API-Platform"
|
||||
maintainers:
|
||||
- name: AI for Earth Engineering
|
||||
- email: aiforearthteam@microsoft.com
|
|
@ -0,0 +1,21 @@
|
|||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: service-name-autoscaler
|
||||
namespace: default
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
name: service-name
|
||||
minReplicas: 1
|
||||
maxReplicas: 10
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: 100
|
||||
- type: Pods
|
||||
pods:
|
||||
metricName: appinsights-metric-connector-name
|
||||
targetAverageValue: 1
|
|
@ -0,0 +1,42 @@
|
|||
global:
|
||||
registry_location: "off-cluster"
|
||||
replicaCount: 1
|
||||
image:
|
||||
repository: acrrepo.azurecr.io/image-name
|
||||
name: image-name
|
||||
tag: 1
|
||||
version: v1
|
||||
pullPolicy: Always
|
||||
secret: registrysecretname
|
||||
service:
|
||||
internalPort: 8021
|
||||
type: ClusterIP
|
||||
resources:
|
||||
limits:
|
||||
cpu: 2000m
|
||||
memory: 2Gi
|
||||
requests:
|
||||
cpu: 1001m
|
||||
memory: 500m
|
||||
env:
|
||||
CACHE_CONNECTOR_GET_URI: ""
|
||||
CACHE_CONNECTOR_UPSERT_URI: ""
|
||||
APPINSIGHTS_INSTRUMENTATIONKEY: ""
|
||||
DISABLE_CURRENT_REQUEST_METRIC: "False"
|
||||
SERVICE_CLUSTER: ""
|
||||
SERVICE_MODEL_NAME: ""
|
||||
SERVICE_MODEL_FRAMEWORK: ""
|
||||
SERVICE_MODEL_FRAMEOWRK_VERSION: ""
|
||||
SERVICE_MODEL_VERSION: "1.0"
|
||||
SERVICE_NAME: ""
|
||||
SERVICE_VERSION: "1.0"
|
||||
SERVICE_CONTAINER_VERSION: ""
|
||||
SERVICE_CONTAINER_NAME: ""
|
||||
DEBUG: "FALSE"
|
||||
volumeMounts:
|
||||
- name: nvidia
|
||||
mountPath: /usr/local/nvidia
|
||||
volumes:
|
||||
- name: nvidia
|
||||
hostPath:
|
||||
path: /usr/local/nvidia
|
|
@ -0,0 +1,34 @@
|
|||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "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).
|
||||
*/}}
|
||||
{{- define "fullname" -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- printf "%s-%s" .Release.Name $name | 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).
|
||||
*/}}
|
||||
{{- define "mdsd.fullname" -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- printf "mdsd-%s-%s" .Release.Name $name | 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).
|
||||
*/}}
|
||||
{{- define "privatekey.fullname" -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- printf "privatekey-%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
|
@ -0,0 +1,55 @@
|
|||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Values.image.name }}
|
||||
labels:
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ .Values.image.name }}
|
||||
spec:
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
command: ["/startup.sh"]
|
||||
ports:
|
||||
- containerPort: {{ .Values.service.internalPort }}
|
||||
name: http
|
||||
resources:
|
||||
{{ toYaml .Values.resources | indent 10 }}
|
||||
env:
|
||||
- name: CACHE_CONNECTOR_UPSERT_URI
|
||||
value: {{ .Values.env.CACHE_CONNECTOR_UPSERT_URI | quote }}
|
||||
- name: CACHE_CONNECTOR_GET_URI
|
||||
value: {{ .Values.env.CACHE_CONNECTOR_GET_URI | quote }}
|
||||
- name: APPINSIGHTS_INSTRUMENTATIONKEY
|
||||
value: {{ .Values.env.APPINSIGHTS_INSTRUMENTATIONKEY | quote }}
|
||||
- name: SERVICE_MODEL_NAME
|
||||
value: {{ .Values.env.SERVICE_MODEL_NAME | quote }}
|
||||
- name: SERVICE_MODEL_FRAMEOWRK_VERSION
|
||||
value: {{ .Values.env.SERVICE_MODEL_FRAMEOWRK_VERSION | quote }}
|
||||
- name: SERVICE_MODEL_VERSION
|
||||
value: {{ .Values.env.SERVICE_MODEL_VERSION | quote }}
|
||||
- name: SERVICE_NAME
|
||||
value: {{ .Values.env.SERVICE_NAME | quote }}
|
||||
- name: SERVICE_VERSION
|
||||
value: {{ .Values.env.SERVICE_VERSION | quote }}
|
||||
- name: SERVICE_CONTAINER_VERSION
|
||||
value: {{ .Values.env.SERVICE_CONTAINER_VERSION | quote }}
|
||||
- name: SERVICE_CONTAINER_NAME
|
||||
value: {{ .Values.env.SERVICE_CONTAINER_NAME | quote }}
|
||||
- name: SERVICE_CLUSTER
|
||||
value: {{ .Values.env.SERVICE_CLUSTER | quote }}
|
||||
- name: APPINSIGHTS_INSTRUMENTATIONKEY
|
||||
value: {{ .Values.env.APPINSIGHTS_INSTRUMENTATIONKEY | quote }}
|
||||
- name: NEXT_API_NAME_IN_PIPELINE
|
||||
value: {{ .Values.env.NEXT_API_NAME_IN_PIPELINE | quote }}
|
||||
volumeMounts:
|
||||
{{ toYaml .Values.volumeMounts | indent 10 }}
|
||||
volumes:
|
||||
{{ toYaml .Values.volumes | indent 8 }}
|
||||
imagePullSecrets:
|
||||
- name: {{ .Values.image.secret }}
|
|
@ -0,0 +1,17 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .Values.image.name }}
|
||||
labels:
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
app: {{ .Values.image.name }}
|
||||
version: {{ .Values.image.version }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.internalPort }}
|
||||
targetPort: {{ .Values.service.targetPort }}
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: {{ .Values.image.name }}
|
|
@ -0,0 +1,28 @@
|
|||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: service-name
|
||||
spec:
|
||||
hosts:
|
||||
- "*"
|
||||
gateways:
|
||||
- istio-gateway-name
|
||||
http:
|
||||
- match:
|
||||
- uri:
|
||||
prefix: ""
|
||||
route:
|
||||
- destination:
|
||||
host: service-name.default.svc.cluster.local
|
||||
port:
|
||||
number: 8021
|
||||
---
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: DestinationRule
|
||||
metadata:
|
||||
name: dr-service-name
|
||||
spec:
|
||||
host: service-name.default.svc.cluster.local
|
||||
trafficPolicy:
|
||||
loadBalancer:
|
||||
simple: ROUND_ROBIN
|
|
@ -0,0 +1,12 @@
|
|||
apiVersion: v1
|
||||
description: My description.
|
||||
name: service-name
|
||||
version: 1.0.0
|
||||
keywords:
|
||||
- sync
|
||||
home: "https://www.microsoft.com/en-us/aiforearth"
|
||||
sources:
|
||||
- "https://github.com/microsoft/AIforEarth-API-Platform"
|
||||
maintainers:
|
||||
- name: AI for Earth Engineering
|
||||
- email: aiforearthteam@microsoft.com
|
|
@ -0,0 +1,21 @@
|
|||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: service-name-autoscaler
|
||||
namespace: default
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
name: service-name
|
||||
minReplicas: 1
|
||||
maxReplicas: 10
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: 100
|
||||
- type: Pods
|
||||
pods:
|
||||
metricName: appinsights-metric-connector-name
|
||||
targetAverageValue: 1
|
|
@ -0,0 +1,32 @@
|
|||
global:
|
||||
registry_location: "off-cluster"
|
||||
replicaCount: 1
|
||||
image:
|
||||
repository: acrrepo.azurecr.io/image-name
|
||||
name: image-name
|
||||
tag: 1
|
||||
version: v1
|
||||
pullPolicy: Always
|
||||
secret: registrysecretname
|
||||
service:
|
||||
internalPort: 8021
|
||||
type: ClusterIP
|
||||
resources:
|
||||
limits:
|
||||
cpu: 2000m
|
||||
memory: 2Gi
|
||||
requests:
|
||||
cpu: 1001m
|
||||
memory: 500m
|
||||
env:
|
||||
APPINSIGHTS_INSTRUMENTATIONKEY: ""
|
||||
SERVICE_CLUSTER: "my-aks-cluster"
|
||||
SERVICE_MODEL_NAME: ""
|
||||
SERVICE_MODEL_FRAMEWORK: ""
|
||||
SERVICE_MODEL_FRAMEOWRK_VERSION: ""
|
||||
SERVICE_MODEL_VERSION: "1.0"
|
||||
SERVICE_NAME: ""
|
||||
SERVICE_VERSION: "1.0"
|
||||
SERVICE_CONTAINER_VERSION: ""
|
||||
SERVICE_CONTAINER_NAME: ""
|
||||
DEBUG: "FALSE"
|
|
@ -0,0 +1,34 @@
|
|||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "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).
|
||||
*/}}
|
||||
{{- define "fullname" -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- printf "%s-%s" .Release.Name $name | 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).
|
||||
*/}}
|
||||
{{- define "mdsd.fullname" -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- printf "mdsd-%s-%s" .Release.Name $name | 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).
|
||||
*/}}
|
||||
{{- define "privatekey.fullname" -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- printf "privatekey-%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
|
@ -0,0 +1,55 @@
|
|||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Values.image.name }}
|
||||
labels:
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ .Values.image.name }}
|
||||
spec:
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
command: ["/startup.sh"]
|
||||
ports:
|
||||
- containerPort: {{ .Values.service.internalPort }}
|
||||
name: http
|
||||
resources:
|
||||
{{ toYaml .Values.resources | indent 10 }}
|
||||
env:
|
||||
- name: CACHE_CONNECTOR_UPSERT_URI
|
||||
value: {{ .Values.env.CACHE_CONNECTOR_UPSERT_URI | quote }}
|
||||
- name: CACHE_CONNECTOR_GET_URI
|
||||
value: {{ .Values.env.CACHE_CONNECTOR_GET_URI | quote }}
|
||||
- name: APPINSIGHTS_INSTRUMENTATIONKEY
|
||||
value: {{ .Values.env.APPINSIGHTS_INSTRUMENTATIONKEY | quote }}
|
||||
- name: SERVICE_MODEL_NAME
|
||||
value: {{ .Values.env.SERVICE_MODEL_NAME | quote }}
|
||||
- name: SERVICE_MODEL_FRAMEOWRK_VERSION
|
||||
value: {{ .Values.env.SERVICE_MODEL_FRAMEOWRK_VERSION | quote }}
|
||||
- name: SERVICE_MODEL_VERSION
|
||||
value: {{ .Values.env.SERVICE_MODEL_VERSION | quote }}
|
||||
- name: SERVICE_NAME
|
||||
value: {{ .Values.env.SERVICE_NAME | quote }}
|
||||
- name: SERVICE_VERSION
|
||||
value: {{ .Values.env.SERVICE_VERSION | quote }}
|
||||
- name: SERVICE_CONTAINER_VERSION
|
||||
value: {{ .Values.env.SERVICE_CONTAINER_VERSION | quote }}
|
||||
- name: SERVICE_CONTAINER_NAME
|
||||
value: {{ .Values.env.SERVICE_CONTAINER_NAME | quote }}
|
||||
- name: SERVICE_CLUSTER
|
||||
value: {{ .Values.env.SERVICE_CLUSTER | quote }}
|
||||
- name: APPINSIGHTS_INSTRUMENTATIONKEY
|
||||
value: {{ .Values.env.APPINSIGHTS_INSTRUMENTATIONKEY | quote }}
|
||||
- name: NEXT_API_NAME_IN_PIPELINE
|
||||
value: {{ .Values.env.NEXT_API_NAME_IN_PIPELINE | quote }}
|
||||
volumeMounts:
|
||||
{{ toYaml .Values.volumeMounts | indent 10 }}
|
||||
volumes:
|
||||
{{ toYaml .Values.volumes | indent 8 }}
|
||||
imagePullSecrets:
|
||||
- name: {{ .Values.image.secret }}
|
|
@ -0,0 +1,17 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .Values.image.name }}
|
||||
labels:
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
app: {{ .Values.image.name }}
|
||||
version: {{ .Values.image.version }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.internalPort }}
|
||||
targetPort: {{ .Values.service.targetPort }}
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: {{ .Values.image.name }}
|
|
@ -22,26 +22,14 @@ To publish a container to the AI for Earth API Platform, the API must be built u
|
|||
|
||||
## Production Preparation
|
||||
### Create a production AI for Earth dockerfile for your API
|
||||
For all of the following steps, please reference the camera-trap example, located in the [camera-trap directory](Projects/camera-trap/detection-sync.dockerfile).
|
||||
1. In the [APIs/Projects](./Projects/) folder, you will notice separate folders for each project. Create a new folder for your project.
|
||||
2. Create a new <api_name>.dockerfile and place it in your folder (pay close attention to the tech stack - Python or R; be sure to use the correct one).
|
||||
3. Modify the FROM clause to point to your registry and <project_moniker> (where you pushed your image in the "Push to ACR" step). The version and tag arguments are required.
|
||||
|
||||
### Create a Helm chart, etc. for your API
|
||||
For all of the following steps, please reference the camera-trap example, located in the [camera-trap directory](APIs/Charts/camera-trap/detection-sync).
|
||||
1. In the charts/ folder, create a new folder for your project.
|
||||
2. Copy and existing chart project/api folder and place it under your project folder.
|
||||
3. Modify the [Chart.yaml](./Charts/camera-trap/detection-sync/Chart.yaml) by changing the description, name, and keywords fields. The name should be of the format <project_moniker>-<api_name>.
|
||||
4. Modify the [autoscaler.yaml](./Charts/camera-trap/detection-sync/autoscaler.yaml) by changing both name fields. The name should be of the format <project_moniker>-<api_name>-autoscaler and <project_moniker>-<api_name>, respectfully. Modify the maxReplicas to the maximum number of instances of your service that should be run and modify the targetCPUUtilizationPercentage to indicate when a new instance should be created. The API Platform supports [auto-scaling on custom Application Insights metrics](https://github.com/Azure/azure-k8s-metrics-adapter). The camera-trap example uses one such metric that tracks the number of requests that are being processed.
|
||||
5. Modify the [prod-values.yaml](./Charts/camera-trap/detection-sync/prod-values.yaml) by changing the image.repository to <your_registry>/<project_moniker>/<major_version>-ai4e-api-<api_name>, the name to <project_moniker>-<api_name>, a port that is not taken by ANY other chart by ANY other project API, the resources, and the env variables.
|
||||
6. Modify the [routing.yml](./Charts/camera-trap/detection-sync/routing.yml). The VirtualService name should be of the format <project_moniker>-<api_name>. Modify the uri.prefix to indicate the incoming path to match, modify the destination.host to a name that reflects <project_moniker>-<api_name>.default.svc.cluster.local, destination.port to reflect the port that is to be used, and destination.subset to the version of the release. Change the DestinationRule to a unique name for your API, modify the host to the destination.host value from above, and esure that the name and label version match the path version of the release. To read more about Istio routing, please see the [docs](https://istio.io/docs/tasks/traffic-management/request-routing/).
|
||||
|
||||
## Building and Deploying a Production API
|
||||
|
||||
### Build Distributed-capable Image
|
||||
The distributed image must be built from this (APIs) directory. The following illustrates how to build the camera-trap example.
|
||||
The distributed image must be built from this (APIs) directory. The following illustrates how to build the species example.
|
||||
```bash
|
||||
docker build . -f Projects/camera-trap/detection-sync.dockerfile -t ai4eapibackendv2gpu3registry.azurecr.io/camera-trap/1.0-ai4e-api-detection-sync:4
|
||||
docker build . -f Projects/species/species-sync.dockerfile -t registry_name.azurecr.io/species/1.0-ai4e-species-sync:1
|
||||
```
|
||||
|
||||
Once complete, push the new image to your container registry:
|
||||
|
@ -50,16 +38,24 @@ Once complete, push the new image to your container registry:
|
|||
az acr login -n <acr_name>
|
||||
|
||||
# Push your image to your ACR.
|
||||
docker push ai4eapibackendv2gpu3registry.azurecr.io/camera-trap/1.0-ai4e-api-detection-sync:4
|
||||
docker push registry_name.azurecr.io/species/1.0-ai4e-species-sync:1
|
||||
```
|
||||
|
||||
You now have a distributed-capable image stored in your container registry that is ready to be hosted on the API Platform.
|
||||
|
||||
### Create a Helm chart, etc. for your API
|
||||
For all of the following steps, please reference the camera-trap example, located in the [camera-trap directory](APIs/Charts/camera-trap/detection-sync).
|
||||
1. In the charts/ folder, create a new folder for your project.
|
||||
2. Copy a template chart from the [Charts/templates](./Charts/templates) folder and place it under your project folder.
|
||||
3. Modify the [Chart.yaml](./Charts/templates/async-gpu/Chart.yaml) by changing the description, name, and keywords fields. The name should be of the format <project_moniker>-<api_name>.
|
||||
4. Modify the [autoscaler.yaml](./Charts/templates/async-gpu/autoscaler.yaml) by changing both name fields. The name should be of the format <project_moniker>-<api_name>-autoscaler and <project_moniker>-<api_name>, respectfully. Modify the maxReplicas to the maximum number of instances of your service that should be run and modify the targetCPUUtilizationPercentage to indicate when a new instance should be created. The API Platform supports [auto-scaling on custom Application Insights metrics](https://github.com/Azure/azure-k8s-metrics-adapter).
|
||||
5. Modify the [prod-values.yaml](./Charts/templates/async-gpu/prod-values.yaml) by changing the image.repository to <your_registry>/<project_moniker>/<major_version>-ai4e-api-<api_name>, the name to <project_moniker>-<api_name>, a port that is not taken by ANY other chart by ANY other project API, the resources, and the env variables.
|
||||
6. Modify the [routing.yml](./Charts/templates/routing.yml). The VirtualService name should be of the format <project_moniker>-<api_name>. Modify the uri.prefix to indicate the incoming path to match, modify the destination.host to a name that reflects <project_moniker>-<api_name>.default.svc.cluster.local, destination.port to reflect the port that is to be used, and destination.subset to the version of the release. Change the DestinationRule to a unique name for your API, modify the host to the destination.host value from above, and esure that the name and label version match the path version of the release. To read more about Istio routing, please see the [docs](https://istio.io/docs/tasks/traffic-management/request-routing/).
|
||||
|
||||
|
||||
## Deploying a Production API
|
||||
|
||||
### Configure API Variables
|
||||
Before deploying to the cluster, edit the chart's prod-values.yaml file. This contains all configuration values to be used by your service. The Azure Function URLs can be retrieved by issuing the following command:
|
||||
```bash
|
||||
func azure functionapp list-functions $FUNCTION_APP_NAME --show-keys
|
||||
```
|
||||
Before deploying to the cluster, edit the chart's prod-values.yaml file. This contains all configuration values to be used by your service. The Azure Function URLs can be retrieved by using the [async_retrieve_cache_connector_urls helper function](async_retrieve_cache_connector_urls.sh).
|
||||
|
||||
Azure Function URLs are mapped to variables according to the following table:
|
||||
|
||||
|
@ -69,17 +65,23 @@ Azure Function URLs are mapped to variables according to the following table:
|
|||
| CACHE_CONNECTOR_GET_URI | cache-connector-get |
|
||||
| CURRENT_PROCESSING_UPSERT_URI | CurrentProcessingUpsert |
|
||||
|
||||
### Deploy the API to Production
|
||||
### Deploy the API Service to Production
|
||||
```bash
|
||||
# Deploy instance.
|
||||
helm install --values ./Charts/camera-trap/detection-sync/prod-values.yaml --name camera-trap-detection-sync ./Charts/camera-trap/detection-sync
|
||||
helm install --values ./Charts/service-name/prod-values.yaml --name service-name ./Charts/service-name
|
||||
|
||||
# Apply auto-scaling.
|
||||
kubectl apply -f ./Charts/camera-trap/detection-sync/autoscaler.yaml
|
||||
kubectl apply -f ./Charts/service-name/autoscaler.yaml
|
||||
|
||||
# Apply service routing.
|
||||
kubectl apply -f ./Charts/camera-trap/detection-sync/routing.yaml
|
||||
kubectl apply -f ./Charts/service-name//routing.yaml
|
||||
|
||||
# Apply optional Application Insights custom scaling metric.
|
||||
kubectl apply -f ./Charts/camera-trap/detection-sync/appinsights-metric.yaml
|
||||
kubectl apply -f ./Charts/service-name/appinsights-metric.yaml
|
||||
```
|
||||
|
||||
### Add the API to API Management
|
||||
The [create_sync_api_management_api.sh](./create_sync_api_management_api.sh) is used as an example of how to add sync APIs to your API Management instance, whereas the [create_async_api_management_api.sh](./create_async_api_management_api.sh) is used as an example of how to add async APIs. Copy the create_sync_api_management_api.sh file and use it as a template. To deploy to Azure, run the following:
|
||||
```bash
|
||||
bash ../APIManagement/create_sync_api_management_api.sh
|
||||
```
|
|
@ -0,0 +1,78 @@
|
|||
#!/bin/bash
|
||||
|
||||
AZURE_SUBSCRIPTION_ID=""
|
||||
INFRASTRUCTURE_RESOURCE_GROUP_NAME="" # Azure Resource Group
|
||||
|
||||
API_MANAGEMENT_NAME=""
|
||||
|
||||
API_PATH="landcover"
|
||||
API_DISPLAY_NAME="AI for Earth Land Cover Mapping API"
|
||||
API_DESCRIPTION="API for retrieving pre-computed classifications of aerial image pixels into natural and human-made terrain types."
|
||||
|
||||
|
||||
if test -z "$INFRASTRUCTURE_RESOURCE_GROUP_NAME"
|
||||
then
|
||||
echo "setupenv.sh must be completed first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
az account set --subscription $AZURE_SUBSCRIPTION_ID
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Could not set subscription $AZURE_SUBSCRIPTION_ID."
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Deploy API Management
|
||||
upsert_key=$(az rest --method post --uri "https://management.azure.com/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$INFRASTRUCTURE_RESOURCE_GROUP_NAME/providers/Microsoft.Web/sites/$FUNCTION_APP_NAME/functions/CacheConnectorUpsert/listKeys?api-version=2018-11-01")
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Could not get the CacheConnectorUpsert Azure Functions key."
|
||||
exit $?
|
||||
fi
|
||||
|
||||
upsert_key=$(echo $upsert_key | jq '.default' | sed -e 's/^"//' -e 's/"$//')
|
||||
upsert_fun_url="https://$CACHE_MANAGER_FUNCTION_APP_NAME.azurewebsites.net/api/CacheConnectorUpsert?code=$upsert_key"
|
||||
|
||||
ingress_ip=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Could not get the istio-ingressgateway ip."
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Create the API
|
||||
api_body="{\"properties\": {\"displayName\": \"$API_DISPLAY_NAME\",\"path\": \"$API_PATH\",\"protocols\": [\"https\"]}}"
|
||||
az rest --method put --uri "https://management.azure.com/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$INFRASTRUCTURE_RESOURCE_GROUP_NAME/providers/Microsoft.ApiManagement/service/$API_MANAGEMENT_NAME/apis/$API_PATH?api-version=2019-01-01" --body $api_body
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Could not create the $API_DISPLAY_NAME API."
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Create the API policy
|
||||
python3 -c "import APIManagement.api_management_customizer as customizer; customizer.customize_api_policy('$upsert_fun_url')"
|
||||
az rest --method put --uri "https://management.azure.com/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$INFRASTRUCTURE_RESOURCE_GROUP_NAME/providers/Microsoft.ApiManagement/service/$API_MANAGEMENT_NAME/apis/$API_PATH/policies/policy?api-version=2019-01-01" --body @customized_api_policy.json
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Could not create the $API_DISPLAY_NAME API POST operation's policy."
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Create the API POST operation
|
||||
api_operation_body="{\"properties\": {\"displayName\": \"$API_OPERATION_DISPLAY_NAME\",\"method\": \"POST\",\"urlTemplate\": \"$API_OPERATION_URL\"}}"
|
||||
az rest --method put --uri "https://management.azure.com/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$INFRASTRUCTURE_RESOURCE_GROUP_NAME/providers/Microsoft.ApiManagement/service/$API_MANAGEMENT_NAME/apis/$API_PATH/operations/$API_OPERATION_URL?api-version=2019-01-01" --body $api_operation_body
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Could not create the $API_DISPLAY_NAME API operation."
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Create the API operation's policy
|
||||
api_backend_policy="<policies><inbound><set-backend-service base-url=https://\"$ingress_ip\" /><rewrite-uri template=\"$BACKEND_API_URL\" /><base /></inbound><backend><base /></backend><outbound><base /></outbound><on-error><base /></on-error></policies>"
|
||||
az rest --method put --uri "https://management.azure.com/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$INFRASTRUCTURE_RESOURCE_GROUP_NAME/providers/Microsoft.ApiManagement/service/$API_MANAGEMENT_NAME/apis/$API_PATH/operations/$API_OPERATION_URL/policies/policy?api-version=2019-01-01" --body $api_backend_policy
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Could not create the $API_DISPLAY_NAME API POST operation's policy."
|
||||
exit $?
|
||||
fi
|
|
@ -0,0 +1,5 @@
|
|||
## assign_storage_auth_to_aks.sh
|
||||
Grants "Storage Blob Data Contributor" access to AKS via AAD. This gives services in the AKS cluster access to the provided storage account through Azure Active Directory.
|
||||
|
||||
## async_retrieve_cache_connector_urls.sh
|
||||
For async APIs that use the task management system, Cache Connector URLs must be provided. This script retrieves those URLs.
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
|
||||
AZURE_SUBSCRIPTION_ID=""
|
||||
STORAGE_ACCOUNT_RESOURCE_GROUP="-supporting-services-rg"
|
||||
STORAGE_ACCOUNT_NAME=""
|
||||
AKS_AAD_APPLICATION_ID="" # AAD application id for AKS
|
||||
|
||||
# Get storage account resource id
|
||||
resource_id=$(az storage account show --resource-group $STORAGE_ACCOUNT_RESOURCE_GROUP --name $STORAGE_ACCOUNT_NAME --subscription $AZURE_SUBSCRIPTION_ID --query "id" --output tsv)
|
||||
|
||||
az role assignment create --assignee $AKS_AAD_APPLICATION_ID --role "Storage Blob Data Contributor" --scope $resource_id
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Could not create an ACR role in the AKS cluster."
|
||||
echo "customize_aks.sh failed"
|
||||
exit $?
|
||||
fi
|
|
@ -0,0 +1,28 @@
|
|||
#!/bin/bash
|
||||
|
||||
AZURE_SUBSCRIPTION_ID=""
|
||||
INFRASTRUCTURE_RESOURCE_GROUP_NAME="-api-backend-rg"
|
||||
FUNCTION_APP_NAME="-api-backend-cache-app"
|
||||
CACHE_MANAGER_FUNCTION_APP_NAME="-api-backend-cache-app"
|
||||
|
||||
get_key=$(az rest --method post --uri "https://management.azure.com/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$INFRASTRUCTURE_RESOURCE_GROUP_NAME/providers/Microsoft.Web/sites/$FUNCTION_APP_NAME/functions/CacheConnectorGet/listKeys?api-version=2018-11-01")
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Could not get the CacheConnectorGet Azure Functions key."
|
||||
exit $?
|
||||
fi
|
||||
|
||||
get_key=$(echo $get_key | jq '.default' | sed -e 's/^"//' -e 's/"$//')
|
||||
get_fun_url="https://$CACHE_MANAGER_FUNCTION_APP_NAME.azurewebsites.net/api/CacheConnectorGet?code=$get_key"
|
||||
echo "CACHE_CONNECTOR_GET_URI: \"$get_fun_url\""
|
||||
|
||||
upsert_key=$(az rest --method post --uri "https://management.azure.com/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$INFRASTRUCTURE_RESOURCE_GROUP_NAME/providers/Microsoft.Web/sites/$FUNCTION_APP_NAME/functions/CacheConnectorUpsert/listKeys?api-version=2018-11-01")
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Could not get the CacheConnectorUpsert Azure Functions key."
|
||||
exit $?
|
||||
fi
|
||||
|
||||
upsert_key=$(echo $upsert_key | jq '.default' | sed -e 's/^"//' -e 's/"$//')
|
||||
upsert_fun_url="https://$CACHE_MANAGER_FUNCTION_APP_NAME.azurewebsites.net/api/CacheConnectorUpsert?code=$upsert_key"
|
||||
echo "CACHE_CONNECTOR_UPSERT_URI: \"$upsert_fun_url\""
|
|
@ -11,7 +11,62 @@ There are three types of files required for deployment:
|
|||
- Master script that runs each deployment script in sequence.
|
||||
- Individual component/feature deployment scripts.
|
||||
|
||||
### Component/feature deployment scripts
|
||||
## Contents
|
||||
1. [Installation Process](#Installation-Process)
|
||||
2. [Component/feature deployment scripts](#Component/feature-deployment-scripts)
|
||||
|
||||
## Installation Process
|
||||
To quickly get up and running, follow these steps.
|
||||
|
||||
1. Edit the [setup_env.sh](setup_env.sh) file. This is where you configure the deployment.
|
||||
2. From the top-level directory, run the following script. Note that connection issues and service creation latencies may result in errors. The scripts are designed such that you can rerun and services will not be recreated. There are some commented out resolutions in the scripts that may be of value.
|
||||
```bash
|
||||
bash InfrastructureDeployment/deploy_infrastructure.sh
|
||||
```
|
||||
3. [Secure the Istio Gateway](https://istio.io/docs/tasks/traffic-management/ingress/secure-ingress-mount/#configure-a-tls-ingress-gateway-with-a-file-mount-based-approach). This is optional, but should be completed for production instances. All of these steps are documented at the above link, but are listed here for brevity. To secure the gateway, please follow these steps:
|
||||
1. Get the ingress IP and ports of the Istio gateway:
|
||||
```bash
|
||||
kubectl get svc istio-ingressgateway -n istio-system
|
||||
```
|
||||
2. Generate server certificate and private key:
|
||||
```bash
|
||||
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt
|
||||
```
|
||||
3. Create a certificate and a private key (replace httpbin.example.com and organization):
|
||||
```bash
|
||||
openssl req -out httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
|
||||
openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in httpbin.example.com.csr -out httpbin.example.com.crt
|
||||
```
|
||||
4. Create a Kubernetes secret to hold the server’s certificate and private key (the secret must be named istio-ingressgateway-certs in the istio-system namespace):
|
||||
```bash
|
||||
kubectl create -n istio-system secret tls istio-ingressgateway-certs --key httpbin.example.com.key --cert httpbin.example.com.crt
|
||||
```
|
||||
5. Modify the default Istio gateway to use the HTTPS protocol (replace httpbin.example.com):
|
||||
```bash
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: ai4e-gateway
|
||||
spec:
|
||||
selector:
|
||||
istio: ingressgateway # use istio default ingress gateway
|
||||
servers:
|
||||
- port:
|
||||
number: 443
|
||||
name: https
|
||||
protocol: HTTPS
|
||||
tls:
|
||||
mode: SIMPLE
|
||||
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
|
||||
privateKey: /etc/istio/ingressgateway-certs/tls.key
|
||||
hosts:
|
||||
- "httpbin.example.com"
|
||||
EOF
|
||||
```
|
||||
|
||||
|
||||
## Component/feature deployment scripts
|
||||
Provided that prerequisites have been deployed, component deployment scripts may be run outside of the [deploy_infrastructure.sh](./deploy_infrastructure.sh) script. The scripts are typically executed in the following order.
|
||||
|
||||
### [deploy_prerequisites.sh](./deploy_prerequisites.sh)
|
||||
|
|
|
@ -6,6 +6,7 @@ echo "Creating the Azure Function Apps."
|
|||
if "$DEPLOY_CACHE_MANAGER_FUNCTION_APP" = "true"
|
||||
then
|
||||
echo "Creating the cache manager Azure Function App."
|
||||
echo "az functionapp create --name $CACHE_MANAGER_FUNCTION_APP_NAME --storage-account $FUNCTION_STORAGE_NAME --resource-group $INFRASTRUCTURE_RESOURCE_GROUP_NAME --plan $FUNCTION_APP_NAME-plan --deployment-container-image-name $CACHE_MANAGER_IMAGE --app-insights $APP_INSIGHTS_RESOURCE_NAME --docker-registry-server-user $FUNCTION_IMAGE_DOCKER_USER_NAME --docker-registry-server-password $FUNCTION_IMAGE_DOCKER_USER_PASSWORD"
|
||||
az functionapp create --name $CACHE_MANAGER_FUNCTION_APP_NAME --storage-account $FUNCTION_STORAGE_NAME --resource-group $INFRASTRUCTURE_RESOURCE_GROUP_NAME --plan $FUNCTION_APP_NAME-plan --deployment-container-image-name $CACHE_MANAGER_IMAGE --app-insights $APP_INSIGHTS_RESOURCE_NAME --docker-registry-server-user $FUNCTION_IMAGE_DOCKER_USER_NAME --docker-registry-server-password $FUNCTION_IMAGE_DOCKER_USER_PASSWORD
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
|
|
|
@ -1,67 +1,64 @@
|
|||
#!/bin/bash
|
||||
|
||||
AZURE_SUBSCRIPTION_ID=""
|
||||
INFRASTRUCTURE_RESOURCE_GROUP_NAME="-api-backend-rg"
|
||||
FUNCTION_APP_NAME="-api-backend-cache-app"
|
||||
CACHE_MANAGER_FUNCTION_APP_NAME="-api-backend-cache-app"
|
||||
FUNCTION_IMAGE_DOCKER_USER_NAME=""
|
||||
FUNCTION_IMAGE_DOCKER_USER_PASSWORD=""
|
||||
|
||||
AZURE_SUBSCRIPTION_ID=""
|
||||
DEPLOYMENT_PREFIX="ai4e-api-backend-master-test-2"
|
||||
# Storage account names must be fewer than 24 characters.
|
||||
FUNCTION_STORAGE_NAME="" # Azure Function Storage
|
||||
CONTAINER_REGISTRY_NAME="" # ACR name
|
||||
CONTAINER_REGISTRY_RESOURCE_GROUP=""
|
||||
|
||||
# Container registry that contains images to be used as services in Kubernetes
|
||||
SERVICE_CONTAINER_REGISTRY_NAME="containerregistry"
|
||||
SERVICE_CONTAINER_REGISTRY_RESOURCE_GROUP="-supporting-services-rg"
|
||||
|
||||
INSTALL_ISTIO="true"
|
||||
INSTALL_CUSTOM_METRICS_ADAPTER="false"
|
||||
|
||||
INFRASTRUCTURE_RESOURCE_GROUP_NAME="$DEPLOYMENT_PREFIX-rg" # Azure Resource Group
|
||||
INFRASTRUCTURE_LOCATION="eastus"
|
||||
|
||||
APP_INSIGHTS_RESOURCE_NAME="-api-backend-app-insights" # Application Services name
|
||||
APP_INSIGHTS_RESOURCE_NAME="$DEPLOYMENT_PREFIX-app-insights" # Application Services name
|
||||
CREATE_CONTAINER_REGISTRY="false"
|
||||
|
||||
# Container registry required for Azure Functions
|
||||
CREATE_CONTAINER_REGISTRY="true"
|
||||
CONTAINER_REGISTRY_NAME="testregistry" # ACR name
|
||||
CONTAINER_REGISTRY_RESOURCE_GROUP="-registry-rg"
|
||||
AKS_RESOURCE_GROUP_NAME="$DEPLOYMENT_PREFIX-aks-rg" # Azure Resource Group Name
|
||||
AKS_CLUSTER_NAME="$DEPLOYMENT_PREFIX" # AKS Cluster Name
|
||||
KUBERNETES_VERSION="1.15.10" # Kubernetes version to deploy
|
||||
DNS_NAME_PREFIX="$DEPLOYMENT_PREFIX" # Custom DNS prefix for your cluster
|
||||
|
||||
AKS_RESOURCE_GROUP_NAME="-api-backend-aks-rg" # Azure Resource Group Name
|
||||
AKS_CLUSTER_NAME="-api-backend" # AKS Cluster Name
|
||||
KUBERNETES_VERSION="1.14.8" # Kubernetes version to deploy
|
||||
DNS_NAME_PREFIX="-api-backend" # Custom DNS prefix for your cluster
|
||||
|
||||
CLUSTER_GPU_NODE_COUNT=1 # Number of GPU nodes to be used for API hosting
|
||||
CLUSTER_GPU_NODE_COUNT=2 # Number of GPU nodes to be used for API hosting
|
||||
CLUSTER_GPU_NODE_VM_SKU="Standard_NC6" # Azure GPU SKU representing the type of VM to use for the nodes
|
||||
GPU_SCALE_MIN_NODE_COUNT=1 # The minimum number of GPU nodes to keep available
|
||||
GPU_SCALE_MAX_NODE_COUNT=3 # The most number of GPU nodes to auto-scale
|
||||
GPU_SCALE_MIN_NODE_COUNT=2 # The minimum number of GPU nodes to keep available
|
||||
GPU_SCALE_MAX_NODE_COUNT=2 # The most number of GPU nodes to auto-scale
|
||||
CLUSTER_CPU_NODE_COUNT=2 # Number of CPU nodes to be used for API hosting
|
||||
CLUSTER_CPU_NODE_VM_SKU="Standard_DS2_v2" # Azure CPU SKU representing the type of VM to use for the nodes
|
||||
CPU_SCALE_MIN_NODE_COUNT=1 # The minimum number of CPU nodes to keep available
|
||||
CPU_SCALE_MAX_NODE_COUNT=3 # The most number of CPU nodes to auto-scale
|
||||
CPU_SCALE_MIN_NODE_COUNT=2 # The minimum number of CPU nodes to keep available
|
||||
CPU_SCALE_MAX_NODE_COUNT=2 # The most number of CPU nodes to auto-scale
|
||||
|
||||
ISTIO_VERSION="1.4.5" # The version of Istio to install
|
||||
AZURE_CACHE_NAME="-api-backend-cache" # Azure Cache Name
|
||||
AZURE_CACHE_NAME="$DEPLOYMENT_PREFIX-cache" # Azure Cache Name
|
||||
|
||||
FUNCTION_STORAGE_NAME="testfuncstorage" # Azure Function Storage
|
||||
FUNCTION_APP_NAME="$DEPLOYMENT_PREFIX-cache-app" # Azure Function App Name
|
||||
DEPLOY_CACHE_MANAGER_FUNCTION_APP="true"
|
||||
DEPLOY_BACKEND_WEBHOOK_FUNCTION_APP="true"
|
||||
DEPLOY_REQUEST_REPORTER_FUNCTION_APP="true"
|
||||
DEPLOY_TASK_PROCESS_LOGGER_FUNCTION_APP="true"
|
||||
BACKEND_WEBHOOK_FUNCTION_APP_NAME="-api-backend-webhook-app"
|
||||
REQUEST_REPORTER_FUNCTION_APP_NAME="-api-backend-requests-app"
|
||||
TASK_PROCESS_LOGGER_FUNCTION_APP_NAME="-api-backend-processes-app"
|
||||
CACHE_MANAGER_FUNCTION_APP_NAME="$DEPLOYMENT_PREFIX-cache-app"
|
||||
BACKEND_WEBHOOK_FUNCTION_APP_NAME="$DEPLOYMENT_PREFIX-webhook-app"
|
||||
REQUEST_REPORTER_FUNCTION_APP_NAME="$DEPLOYMENT_PREFIX-requests-app"
|
||||
TASK_PROCESS_LOGGER_FUNCTION_APP_NAME="$DEPLOYMENT_PREFIX-processes-app"
|
||||
|
||||
# DO NOT CHANGE
|
||||
CACHE_MANAGER_IMAGE="containerregistry.azurecr.io/func-cache-manager:1.0"
|
||||
BACKEND_WEBHOOK_IMAGE="containerregistry.azurecr.io/func-backend-webhook:1.0"
|
||||
REQUEST_REPORTER_IMAGE="containerregistry.azurecr.io/func-request-reporter:1.0"
|
||||
TASK_PROCESS_LOGGER_IMAGE="containerregistry.azurecr.io/func-task-process-logger:1.0"
|
||||
FUNCTION_IMAGE_DOCKER_USER_NAME="containerregistry"
|
||||
FUNCTION_IMAGE_DOCKER_USER_PASSWORD="Dv/v0gPrnqIwNkEU5JSwZKPZu9lqgrwV"
|
||||
CACHE_MANAGER_IMAGE="mcr.microsoft.com/aiforearth/func-cache-manager:1.0"
|
||||
BACKEND_WEBHOOK_IMAGE="mcr.microsoft.com/aiforearth/func-backend-webhook:1.0"
|
||||
REQUEST_REPORTER_IMAGE="mcr.microsoft.com/aiforearth/func-request-reporter:1.0"
|
||||
TASK_PROCESS_LOGGER_IMAGE="mcr.microsoft.com/aiforearth/func-task-process-logger:1.0"
|
||||
|
||||
EVENT_GRID_TOPIC_NAME="-api-backend-grid-topic" # Event Grid topic name
|
||||
EVENT_GRID_TOPIC_NAME="$DEPLOYMENT_PREFIX-grid-topic" # Event Grid topic name
|
||||
|
||||
SERVICE_PRINCIPAL_METRIC_ADAPTER_NAME="-metric-adapter-sp"
|
||||
SERVICE_PRINCIPAL_METRIC_ADAPTER_NAME="$DEPLOYMENT_PREFIX-metric-adapter-sp"
|
||||
|
||||
API_MANAGEMENT_NAME="-api-backend-api-mgmt"
|
||||
API_MANAGEMENT_ORGANIZATION_NAME=""
|
||||
API_MANAGEMENT_ADMIN_EMAIL=""
|
||||
API_MANAGEMENT_NAME="$DEPLOYMENT_PREFIX-api-mgmt"
|
||||
API_MANAGEMENT_ORGANIZATION_NAME="AI for Earth"
|
||||
API_MANAGEMENT_ADMIN_EMAIL="test@microsoft.com"
|
||||
API_MANAGEMENT_REGION="East US"
|
||||
API_MANAGEMENT_SKU="Consumption"
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ After developing an algorithm or machine learning model, researchers face the pr
|
|||
2. [AI for Earth API Platform](#AI-for-Earth-API-Platform) - Overview and features.
|
||||
3. [Platform Elements and Costs](#Platform-Elements-and-Costs)
|
||||
4. [Platform Deployment](#Platform-Deployment)
|
||||
5. [API Deployment](#API-Deployment)
|
||||
6. [Platform Alternatives](#Alternatives)
|
||||
7. [Contributions](#Contributing)
|
||||
|
||||
|
@ -136,6 +137,9 @@ API Management can be [configured with a consumption plan or a dedicated plan](h
|
|||
## Platform Deployment
|
||||
The platform may be deployed using scripts provided in the [InfrastructureDeployment](./InfrastructureDeployment) directory. Please follow the [instructions](./InfrastructureDeployment/README.md) in that directory to deploy the API Platform to Azure.
|
||||
|
||||
## API Deployment
|
||||
Your API can be deployed to the API Platform by following the [API instructions](./APIs/README.md).
|
||||
|
||||
## Alternatives
|
||||
Development on the AI for Earth API Platform began in the Spring of 2018. Recently, there have been a number of improvements to the [Azure Machine Learning Service](https://docs.microsoft.com/en-us/azure/machine-learning/service/how-to-deploy-azure-kubernetes-service) and [MLOps](https://docs.microsoft.com/en-us/azure/machine-learning/service/concept-model-management-and-deployment) that have greatly bridged the inference service gaps that we had initially identified.
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче