Skip to content

Commit ad86471

Browse files
authored
Merge pull request #48 from ks6088ts-labs/feature/issue-47_support-bicep
add bicep codes for deployment
2 parents 075434c + 85eb321 commit ad86471

File tree

9 files changed

+674
-9
lines changed

9 files changed

+674
-9
lines changed

apps/8_streamlit_azure_openai_batch/main.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
)
1818
azure_openai_api_key = st.text_input(
1919
label="AZURE_OPENAI_API_KEY",
20-
# DEBUG
21-
value=getenv("AZURE_OPENAI_API_KEY"),
2220
key="AZURE_OPENAI_API_KEY",
2321
type="password",
2422
)

docs/README.dev.md

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# Developer Guide
2+
13
## Development instructions
24

35
### Local development
@@ -31,16 +33,22 @@ make docker-run
3133
make ci-test-docker
3234
```
3335

34-
To publish the docker image to Docker Hub, you need to set the following secrets in the repository settings.
36+
## Deployment
37+
38+
### Infrastructure
3539

3640
```shell
37-
gh secret set DOCKERHUB_USERNAME --body $DOCKERHUB_USERNAME
38-
gh secret set DOCKERHUB_TOKEN --body $DOCKERHUB_TOKEN
41+
cd infra
42+
az login
43+
44+
make deploy
3945
```
4046

41-
## Deployment
47+
- ref. [Azure-Samples/azure-ai-studio-secure-bicep](https://github.com/Azure-Samples/azure-ai-studio-secure-bicep)
48+
49+
### Application
4250

43-
### From Docker Hub
51+
#### From Docker Hub
4452

4553
You can run the docker image from Docker Hub.
4654

@@ -54,7 +62,7 @@ docker run -p 8501:8501 ks6088ts/workshop-azure-openai:latest \
5462
python -m streamlit run apps/99_streamlit_llm_examples/main.py
5563
```
5664

57-
### App Service
65+
#### App Service
5866

5967
For deploying the Streamlit application to Azure App Service, you need to set the following two configurations.
6068

@@ -66,8 +74,17 @@ Notes:
6674
- Update the startup command as needed. App Service listens on port 8000 by default, so `--server.port 8000` is required.
6775
- The default port of App Service is 8000, so `--server.port 8000` is required.
6876

69-
#### References
77+
##### References
7078

7179
- [Streamlit を Azure App Service で動かす!](https://qiita.com/takashiuesaka/items/491b21e9afb34bbb6e6d)
7280
- [WARNING: Could not find virtual environment directory /home/site/wwwroot/antenv](https://stackoverflow.com/a/61720957)
7381
- [How to deploy a streamlit application on Azure App Service (WebApp)](https://learn.microsoft.com/en-us/answers/questions/1470782/how-to-deploy-a-streamlit-application-on-azure-app)
82+
83+
### GitHub Actions
84+
85+
To publish the docker image to Docker Hub, you need to set the following secrets in the repository settings.
86+
87+
```shell
88+
gh secret set DOCKERHUB_USERNAME --body $DOCKERHUB_USERNAME
89+
gh secret set DOCKERHUB_TOKEN --body $DOCKERHUB_TOKEN
90+
```

infra/Makefile

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Parameters
2+
SOURCE_FILES ?= $(shell find . -type f -name '*.bicep' -print)
3+
OUT_DIR ?= ./artifacts
4+
BICEP_MAIN ?= ./main.bicep
5+
BICEP_PARAMETERS ?= ./main.bicepparam
6+
7+
# Git
8+
GIT_REVISION ?= $(shell git rev-parse --short HEAD)
9+
GIT_TAG ?= $(shell git describe --tags --abbrev=0 --always | sed -e s/v//g)
10+
11+
# Azure
12+
SUBSCRIPTION_ID ?= $(shell az account show --query id --output tsv)
13+
SUBSCRIPTION_NAME ?= $(shell az account show --query name --output tsv)
14+
TENANT_ID ?= $(shell az account show --query tenantId --output tsv)
15+
OBJECT_ID ?= $(shell az account show --query user.name --output tsv)
16+
USER_ID ?= $(shell az ad user show --id $(OBJECT_ID) --query id --output tsv)
17+
RESOURCE_GROUP_NAME ?= rg-workshop-azure-openai
18+
LOCATION ?= japaneast
19+
DEPLOYMENT_NAME ?= main
20+
21+
.PHONY: help
22+
help:
23+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
24+
.DEFAULT_GOAL := help
25+
26+
.PHONY: info
27+
info: ## show information
28+
@echo "GIT_REVISION: $(GIT_REVISION)"
29+
@echo "GIT_TAG: $(GIT_TAG)"
30+
@echo "SUBSCRIPTION_ID: $(SUBSCRIPTION_ID)"
31+
@echo "SUBSCRIPTION_NAME: $(SUBSCRIPTION_NAME)"
32+
@echo "TENANT_ID: $(TENANT_ID)"
33+
@echo "OBJECT_ID: $(OBJECT_ID)"
34+
@echo "USER_ID: $(USER_ID)"
35+
36+
.PHONY: install-deps-dev
37+
install-deps-dev: ## install dependencies for development
38+
@which az || echo "Please install Azure CLI: https://github.com/Azure/azure-cli#installation"
39+
@az bicep upgrade
40+
41+
.PHONY: format
42+
format: ## format codes
43+
@$(foreach file,$(SOURCE_FILES),az bicep format --file $(file) --insert-final-newline;)
44+
45+
.PHONY: lint
46+
lint: ## lint codes
47+
@echo "lint: Skip since not implemented yet"
48+
49+
.PHONY: build
50+
build: ## build a bicep file
51+
@mkdir -p $(OUT_DIR)
52+
@az bicep build \
53+
--file $(BICEP_MAIN) \
54+
--outfile $(OUT_DIR)/$(GIT_REVISION).json
55+
56+
.PHONY: test
57+
test: deployment-what-if ## test codes
58+
59+
.PHONY: ci-test
60+
ci-test: install-deps-dev lint build test ## ci test
61+
62+
.PHONY: create-resource-group
63+
create-resource-group: ## create resource group
64+
az group create \
65+
--name $(RESOURCE_GROUP_NAME) \
66+
--location $(LOCATION)
67+
68+
.PHONY: delete-resource-group
69+
delete-resource-group: ## delete resource group
70+
az group delete --name $(RESOURCE_GROUP_NAME) --yes --no-wait
71+
72+
.PHONY: deployment-what-if
73+
deployment-what-if: ## execute a deployment What-If operation at resource group scope
74+
az deployment group what-if \
75+
--resource-group $(RESOURCE_GROUP_NAME) \
76+
--template-file $(BICEP_MAIN) \
77+
--parameters $(BICEP_PARAMETERS)
78+
79+
.PHONY: deployment-create
80+
deployment-create: ## start a deployment at resource group
81+
az deployment group create \
82+
--resource-group $(RESOURCE_GROUP_NAME) \
83+
--template-file $(BICEP_MAIN) \
84+
--parameters $(BICEP_PARAMETERS)
85+
86+
.PHONY: deployment-output
87+
deployment-output: ## show deployment output
88+
az deployment group show \
89+
--resource-group $(RESOURCE_GROUP_NAME) \
90+
--name $(DEPLOYMENT_NAME) \
91+
--query properties.outputs.deploymentInfo.value
92+
93+
.PHONY: deploy
94+
deploy: create-resource-group deployment-what-if deployment-create ## deploy resources
95+
96+
.PHONY: destroy
97+
destroy: delete-resource-group ## destroy resources
98+
99+
# Generate deployment credentials: https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/deploy-github-actions?tabs=userlevel%2CCLI#generate-deployment-credentials
100+
.PHONY: create-for-rbac
101+
create-for-rbac: ## create service principal for RBAC
102+
az ad sp create-for-rbac \
103+
--name test-baseline-environment-on-azure-bicep \
104+
--role contributor \
105+
--scopes /subscriptions/$(SUBSCRIPTION_ID)/resourceGroups/$(RESOURCE_GROUP_NAME) \
106+
--sdk-auth > $(OUT_DIR)/azure-credentials.json
107+
108+
# Configure the GitHub secrets: https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/deploy-github-actions?tabs=userlevel%2CCLI#configure-the-github-secrets
109+
.PHONY: configure-github-secrets
110+
configure-github-secrets: ## configure GitHub secrets
111+
gh secret set AZURE_CREDENTIALS < $(OUT_DIR)/azure-credentials.json
112+
gh secret set AZURE_SUBSCRIPTION --body $(SUBSCRIPTION_ID)
113+
gh secret set AZURE_RG --body $(RESOURCE_GROUP_NAME)

infra/main.bicep

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Parameters
2+
@description('Specifies the name prefix for all the Azure resources.')
3+
@minLength(4)
4+
@maxLength(10)
5+
param prefix string = substring(uniqueString(resourceGroup().id, location), 0, 4)
6+
7+
@description('Specifies the location for all the Azure resources.')
8+
param location string = resourceGroup().location
9+
10+
@description('Specifies the name of the Azure Log Analytics resource.')
11+
param logAnalyticsName string = ''
12+
13+
@description('Specifies the service tier of the workspace: Free, Standalone, PerNode, Per-GB.')
14+
@allowed([
15+
'Free'
16+
'Standalone'
17+
'PerNode'
18+
'PerGB2018'
19+
])
20+
param logAnalyticsSku string = 'PerNode'
21+
22+
@description('Specifies the workspace data retention in days. -1 means Unlimited retention for the Unlimited Sku. 730 days is the maximum allowed for all other Skus.')
23+
param logAnalyticsRetentionInDays int = 60
24+
25+
@description('Specifies the name of the Azure AI Services resource.')
26+
param aiServicesName string = ''
27+
28+
@description('Specifies the resource model definition representing SKU.')
29+
param aiServicesSku object = {
30+
name: 'S0'
31+
}
32+
33+
@description('Specifies the identity of the Azure AI Services resource.')
34+
param aiServicesIdentity object = {
35+
type: 'SystemAssigned'
36+
}
37+
38+
@description('Specifies an optional subdomain name used for token-based authentication.')
39+
param aiServicesCustomSubDomainName string = ''
40+
41+
@description('Specifies whether disable the local authentication via API key.')
42+
param aiServicesDisableLocalAuth bool = false
43+
44+
@description('Specifies whether or not public endpoint access is allowed for this account..')
45+
@allowed([
46+
'Enabled'
47+
'Disabled'
48+
])
49+
param aiServicesPublicNetworkAccess string = 'Enabled'
50+
51+
@description('Specifies the OpenAI deployments to create.')
52+
param openAiDeployments array = []
53+
54+
@description('Specifies the resource tags for all the resoources.')
55+
param tags object = {}
56+
57+
@description('Specifies the object id of a Microsoft Entra ID user. In general, this the object id of the system administrator who deploys the Azure resources.')
58+
param userObjectId string = ''
59+
60+
@description('Specifies the name of the Azure AI Search resource.')
61+
param aiSearchName string = '${prefix}aisearch'
62+
63+
@description('Specifies the name of the Azure Cosmos DB resource.')
64+
param cosmosDbName string = '${prefix}cosmosdb'
65+
66+
// Resources
67+
module workspace 'modules/logAnalytics.bicep' = {
68+
name: 'workspace'
69+
params: {
70+
// properties
71+
name: empty(logAnalyticsName) ? toLower('${prefix}-log-analytics') : logAnalyticsName
72+
location: location
73+
tags: tags
74+
sku: logAnalyticsSku
75+
retentionInDays: logAnalyticsRetentionInDays
76+
}
77+
}
78+
79+
module aiServices 'modules/aiServices.bicep' = {
80+
name: 'aiServices'
81+
params: {
82+
// properties
83+
name: empty(aiServicesName) ? toLower('${prefix}-ai-services') : aiServicesName
84+
location: location
85+
tags: tags
86+
sku: aiServicesSku
87+
identity: aiServicesIdentity
88+
customSubDomainName: empty(aiServicesCustomSubDomainName)
89+
? toLower('${prefix}-ai-services')
90+
: aiServicesCustomSubDomainName
91+
disableLocalAuth: aiServicesDisableLocalAuth
92+
publicNetworkAccess: aiServicesPublicNetworkAccess
93+
deployments: openAiDeployments
94+
workspaceId: workspace.outputs.id
95+
96+
// role assignments
97+
userObjectId: userObjectId
98+
}
99+
}
100+
101+
module aiSearch './modules/aiSearch.bicep' = {
102+
name: 'aiSearch'
103+
params: {
104+
name: aiSearchName
105+
location: location
106+
tags: tags
107+
}
108+
}
109+
110+
module cosmosDb './modules/cosmosDb.bicep' = {
111+
name: 'cosmosDb'
112+
params: {
113+
name: cosmosDbName
114+
location: location
115+
tags: tags
116+
primaryRegion: location
117+
secondaryRegion: 'japanwest'
118+
}
119+
}
120+
121+
output deploymentInfo object = {
122+
subscriptionId: subscription().subscriptionId
123+
resourceGroupName: resourceGroup().name
124+
location: location
125+
aiServicesName: aiServices.outputs.name
126+
aiServicesEndpoint: aiServices.outputs.endpoint
127+
aiSearchName: aiSearch.outputs.name
128+
cosmosDbAccountName: cosmosDb.outputs.accountName
129+
cosmosDbAccountEndpoint: cosmosDb.outputs.accountEndpoint
130+
}

infra/main.bicepparam

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using './main.bicep'
2+
3+
// param prefix = 'secure'
4+
// param suffix = 'test'
5+
// param userObjectId = '<user-object-id>'
6+
// param logAnalyticsName = '${prefix}loganalytics'
7+
param openAiDeployments = [
8+
{
9+
model: {
10+
name: 'text-embedding-3-large'
11+
version: '1'
12+
}
13+
sku: {
14+
name: 'Standard'
15+
capacity: 10
16+
}
17+
}
18+
{
19+
model: {
20+
name: 'gpt-4o'
21+
version: '2024-05-13'
22+
}
23+
sku: {
24+
name: 'GlobalStandard'
25+
capacity: 10
26+
}
27+
}
28+
]
29+
param tags = {
30+
environment: 'development'
31+
iac: 'bicep'
32+
}

0 commit comments

Comments
 (0)