gray-fall-86820
02/09/2024, 3:33 PMimport pulumi
import pulumi_azure_native as azure_native
# Create an Azure Resource Group
resource_group = azure_native.resources.ResourceGroup('resource_group')
# Create an Azure Container Registry
container_registry = azure_native.containerregistry.Registry(
'container_registry',
resource_group_name=resource_group.name,
sku=azure_native.containerregistry.SkuArgs(
name='Basic', # Change to 'Standard' or 'Premium' for production workloads
),
admin_user_enabled=True,
)
# Create an App Service Plan with Linux
service_plan = azure_native.web.AppServicePlan(
'service_plan',
resource_group_name=resource_group.name,
kind='Linux',
reserved=True, # This is required for Linux plan creation
sku=azure_native.web.SkuDescriptionArgs(
name='B1', # Change as needed for scaling
tier='Basic', # Change as needed for scaling
),
)
# Create an App Service using an image from the Container Registry
app_service = azure_native.web.WebApp(
'app_service',
resource_group_name=resource_group.name,
server_farm_id=service_plan.id,
site_config=azure_native.web.SiteConfigArgs(
linux_fx_version=f'DOCKER|{container_registry.login_server}.<http://azurecr.io/mydockerimage:latest|azurecr.io/mydockerimage:latest>',
app_settings=[
azure_native.web.NameValuePairArgs(
name='DOCKER_REGISTRY_SERVER_URL',
value=f'https://{container_registry.login_server}.<http://azurecr.io|azurecr.io>'
),
azure_native.web.NameValuePairArgs(
name='DOCKER_REGISTRY_SERVER_USERNAME',
value=container_registry.admin_user_name,
),
azure_native.web.NameValuePairArgs(
name='DOCKER_REGISTRY_SERVER_PASSWORD',
value=container_registry.admin_user_enabled.apply(
lambda enabled: pulumi.secret(container_registry.admin_user_password) if enabled else pulumi.secret("")
),
),
],
),
)
# Export the Azure App Service endpoint
pulumi.export('app_service_endpoint', app_service.default_host_name.apply(lambda host: f'http://{host}'))
So essentially pretty basic setup with a container base app. So basically, create an "App Service Plan" and an "App" then a "Azure Container Registry".
This app is going to always use the latest Docker image.
Below is what I want to do;
1. Use this example to create the new resources - this is one time operation
2. Use the relevant github repository of a particular app and run the existing github workflow for the first time so that this new resource from the start includes the latest app updates
3. Generally, we have a simple pipeline from github where whenever a new PR is approved and merged with the main branch we execute the relevant workflow(s) to push the latest changes to the Azure Registry
Maybe I am not doing or thinking in the right way, so if someone can provide a better approach, will be really grateful.adventurous-butcher-54166
02/13/2024, 4:40 PMadmin_user_enabled=False
◦ Enable managed identity on the App Service: identity=web.ManagedServiceIdentityArgs(type=web.ManagedServiceIdentityType.SYSTEM_ASSIGNED),
◦ Assign the AcrPull role on the App Service. See this gist for how to do that in Pulumi/Python.
◦ Remove the docker login related ENV vars
◦ Set this option in site_config: acr_use_managed_identity_creds=True
• Use OIDC credentials in your workflow instead of client credentials. I used this bash script in the past before migrating the provisioning of this Pulumi (can't share that right now). It will automatically create the service principal and store the credential as an environment secret in your GitHub repo if gh
cli is present. Otherwise see GitHub and Azure docs.
• Don't use latest
tags for containers as it's an anti-pattern and can cause various problems and confusion
◦ Instead use the docker-metadata-action to automatically tag your images with branch name, github sha. Pull request builds will get a pr-number tag. Can even support semver tags if you implement that.
◦ This makes it much clearer what version of your container is actually deployed
• For App Service production workloads which need zero-downtime:
◦ Go with the Premium tier app services
◦ Create deployment slots
◦ Have your CI/CD workflow deploy release candidates to a staging slot and then swap that into production
◦ I've used az cli in a workflow for doing that like so:
◦ az webapp deployment slot swap -s slot_name -n app_name -g resource_group
gray-fall-86820
02/13/2024, 4:52 PMname: Build and deploy - Test
on:
push:
paths-ignore:
- '**/README.md'
- '**/.github/workflows/**.yml'
branches:
- develop
workflow_dispatch:
jobs:
lint:
runs-on: ubuntu-latest
environment: Testing
steps:
- uses: actions/checkout@v2
- uses: psf/black@stable
deploy:
runs-on: ubuntu-latest
environment: Testing
steps:
- uses: actions/checkout@v2
- uses: azure/docker-login@v1
with:
login-server: ${{ secrets.ACR_DEV_SERVER }}
username: ${{ secrets.ACR_DEV_USERNAME }}
password: ${{ secrets.ACR_DEV_PASSWORD }}
- run: |
docker build -t ${{ secrets.ACR_DEV_SERVER }}/repo-name:${{ github.sha }} .
docker push ${{ secrets.ACR_DEV_SERVER }}/repo-name:${{ github.sha }}
- uses: azure/webapps-deploy@v2
with:
app-name: 'App Name'
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
images: '${{ secrets.ACR_DEV_SERVER}}/repo-name:${{ github.sha }}'
gray-fall-86820
02/13/2024, 5:42 PMadventurous-butcher-54166
02/13/2024, 6:00 PMwork-dir
to where your Pulumi code lives
• command: up | preview
If you export outputs from the stack these can then be referenced in consecutive workflow steps - assuming your pulumi step has the id: pulumi
and you have a stack output named registry_endpoint
${{ steps.pulumi.outputs.registry_endpoint }}"
And if you install the Pulumi GitHub App you will get automatic comments on your pull requests with the results of a pulumi action.gray-fall-86820
02/13/2024, 8:56 PM