Our team has set up an ansible-playbook to deploy Azure Function using this reference. We use a user assigned identity to pull the function app image from an ACR like the following:
- name: Force Login using identity
command: az login --identity
- name: Get subscriptionId
command: az account show --query id --output tsv
register: subscriptionId
- name: Get functionapp identity's clientId
command: az identity show --resource-group "{{ functionapp_resource_group }}" --name "{{ functionapp_user_identity }}" --query clientId --output tsv
register: identityId
- name: Use functionapp identity for acr pull
command:
az resource update
--ids /subscriptions/{{ subscriptionId.stdout }}/resourceGroups/{{ functionapp_resource_group }}/providers/Microsoft.Web/sites/{{ functionapp_name }}/config/web
--set properties.acrUseManagedIdentityCreds=True
--set properties.AcrUserManagedIdentityID={{ identityId.stdout }}
- name: Config the functionapp
command:
az functionapp config appsettings set --name "{{ functionapp_name }}"
--resource-group "{{ functionapp_resource_group }}"
--settings
"Key1={{ Value1 }}"
"Key2={{ Value2 }}"
- name: Deploy the functionapp
command:
az functionapp config container set --name "{{ functionapp_name }}"
--resource-group "{{ functionapp_resource_group }}"
--docker-custom-image-name "{{ docker_registry_host }}/{{ image_name }}:{{ image_tag }}"
--docker-registry-server-url "{{ docker_registry_host }}"
Usually, the script works fine. The successful deployment log should be like the following:
However, we encountered a strange failure today. When deploying the image, the Azure Portal shows an incomplete log:
Does anyone know why this failure occurred?
I finally figured out that it may imply there's no further docker log today.
Related
I am trying to get connection string using Powershell and pass this argument to another step in the actions, but I am getting this error:
Input required and not supplied: connection-string
But I am following a similar behaviour that I use before but I am not sure why it is not working, Here is part of my script:
- name: Secrets to Key Vault
uses: azure/powershell#v1
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
with:
inlineScript: |
$sqlConnectionString = (az keyvault secret show --vault-name <keyVaultName> --name <secret-name> --query [value] --output tsv)
echo ::set-output name=sqlConnectionString::$( $sqlConnectionString)
azPSVersion : '3.1.0'
- name: Deploy Core Module
uses: azure/sql-action#v1
id: sqlConnection
with:
server-name: <sqlServerName>
connection-string: ${{ steps.sqlConnection.outputs.sqlConnectionString}}
dacpac-package: './Database.dacpac'
I think problem is related to the output of the variable but I use similar syntax previously just in a simple run and it worked. Could it be related to the behaviour of the Powershell?
Plese add id to you first action:
- name: Secrets to Key Vault
uses: azure/powershell#v1
id: setSqlConnection
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
with:
inlineScript: |
$sqlConnectionString = (az keyvault secret show --vault-name <keyVaultName> --name <secret-name> --query [value] --output tsv)
echo ::set-output name=sqlConnectionString::$( $sqlConnectionString)
azPSVersion : '3.1.0'
- name: Deploy Core Module
uses: azure/sql-action#v1
id: sqlConnection
with:
server-name: <sqlServerName>
connection-string: ${{ steps.setSqlConnection.outputs.sqlConnectionString}}
dacpac-package: './Database.dacpac'
and then use it to access output ${{ steps.setSqlConnection.outputs.sqlConnectionString}}
I have an Azure storage account. When I allow all networks to it, my Github Actions can run and update my Azure static website.
When I disallow all but named networks (147.243.0.0/16 and my machine's IP) I get a 403 (request denied) error in Github Actions.
I assume I need to add GitHub to these IPs but when I run:
curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/meta
there are tons of IPs! Do I need to add them all?
I assume you want to allow the GitHub Actions runner access to your storage account? Then yes, since that is potentially a large fleet of VMs, there are ton of IPs you would need to whitelist.
The alternative is to use a few tasks inside your pipeline:
look up the IP of the runner, e.g. using https://api.ipify.org
Add this IP to the allow-list using AZ CLI
Do your actual work on storage
Remove the allow entry again through CLI
Example Code:
name: Deploy to Azure
on:
push:
branches:
- main
workflow_dispatch:
jobs:
publish:
environment: Production
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- uses: azure/login#v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Whitelist GitHub Runner IP
uses: azure/CLI#v1
with:
inlineScript: |
set -eu
agentIP=$(curl -s https://api.ipify.org/)
az storage account network-rule add \
--resource-group "${{ secrets.RESOURCE_GROUP }}" \
--account-name "${{ secrets.STORAGE_ACCOUNT_NAME }}" \
--ip-address $agentIP
sleep 300
- name: Upload to blob storage
uses: azure/CLI#v1
with:
inlineScript: |
set -eu
az storage blob upload-batch \
--account-name "${{ secrets.STORAGE_ACCOUNT_NAME }}" \
--source ./src/ \
--destination '$web' \
--overwrite true
- name: Purge CDN endpoint
uses: azure/CLI#v1
with:
inlineScript: |
set -eu
az cdn endpoint purge \
--content-paths "/*" \
--profile-name "${{ secrets.CDN_PROFILE_NAME }}" \
--name "${{ secrets.CDN_ENDPOINT }}" \
--resource-group "${{ secrets.RESOURCE_GROUP }}"
- name: Remove GitHub Runner IP from Whitelist
if: always()
uses: azure/CLI#v1
with:
inlineScript: |
set -eu
agentIP=$(curl -s https://api.ipify.org/)
az storage account network-rule remove \
--resource-group "${{ secrets.RESOURCE_GROUP }}" \
--account-name "${{ secrets.STORAGE_ACCOUNT_NAME }}" \
--ip-address $agentIP
- name: logout
if: always()
run: |
az logout
Now you can assign fixed IP address for your runners. This is in beta, but now doable
Fixed IP ranges
Setup a fixed IP range for your machines by simply ticking a check box, this provides an IP range that can be allow listed in internal systems and in GitHub’s allow list to keep using Actions while making your GitHub environment more secure.
I am unable to set encryption for the storage account once the storage account created successfully. I am creating the below playbooks for the storage account and encryption.
- name: storage_account_creation | deploy storage account
azure_rm_storageaccount:
state: present
cloud_environment: "AzureCloud"
subscription_id: "XXXX-XXXX-XXXX-XXX"
resource_group_name: "XXXX-XXXX-XXXX-XXXX"
client_id: "XXXX-XXXX-XXXX-XXXX"
secret: "XXXX-XXXX-XXXX-XXXX"
tenant: "XXXX-XXXX-XXXX-XXX"
location: "{{ azloc['stdout_lines'][0] }}"
kind: BlobStorage
access_tier: "Hot"
name: "storageaccount_001"
account_type: "Standard_LRS"
network_acls:
bypass: AzureServices
default_action: deny
encrypt.yml
- name: encrypt | Get keyvault name from id
set_fact:
keyvaultname: "XXXXXXXXXX"
- name: encrypt | Get object id of storage account
shell: az storage account show --subscription "{{ subscription_id }}" -n "{{ Storageaccount_name }}" --query "identity.principalId" --output tsv
register: azsaobjectid
- debug:
var: azsaobjectid
- name: encrypt | Create key vault access policy for new storage account
shell: az keyvault set-policy --subscription "{{ subscription_id }}" -n {{ keyvaultname }}" --key-permissions get wrapKey unwrapKey --object-id "{{ azsaobjectid.stdout_lines[0] }}"
When I execute the scripts I get the below error
fatal: [localhost]: FAILED! =>
msg: |-
The task includes an option with an undefined variable. The error was: list object has no element 0
The error appears to be in 'encrypt.yml': line 10, column 4, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: encrypt | Create key vault access policy for new storage account
^ here
The error details suggest that you are using a variable that hasn't been defined. I suspect this is from your register block in get object id of storage account.
However...
Consider re-writing these tasks to use official azure modules.
Shelling out should be a last resort, and from the look of it, you can accomplish your goal by using the azure_rm_storageaccount_info_module module to gather facts, and azure_rm_keyvault module to set your policy.
Using official modules ensures your playbook is idempotent, easier to read, and your error details will likely become clearer as well.
I have followed this documentation on providing ACR access to AKS : https://learn.microsoft.com/en-us/azure/container-registry/container-registry-auth-aks but still i'm getting the authentication failed error. Can someone help me with this?
env:
- name: no_cpu
valueFrom:
resourceFieldRef:
containerName: proxy
resource: requests.cpu
imagePullSecrets:
- name: acr-auth
Make sure you have the acrpull role assigned to the AKS SP on the ACR resource (from the portal, on the IAM tab, or using the script:
#!/bin/bash
AKS_RESOURCE_GROUP=myAKSResourceGroup
AKS_CLUSTER_NAME=myAKSCluster
ACR_RESOURCE_GROUP=myACRResourceGroup
ACR_NAME=myACRRegistry
# Get the id of the service principal configured for AKS
CLIENT_ID=$(az aks show --resource-group $AKS_RESOURCE_GROUP --name $AKS_CLUSTER_NAME --query "servicePrincipalProfile.clientId" --output tsv)
# Get the ACR registry resource id
ACR_ID=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query "id" --output tsv)
# Create role assignment
az role assignment create --assignee $CLIENT_ID --role acrpull --scope $ACR_ID
).
Then create pull secret via command line:
kubectl create secret docker-registry acr-auth --docker-server <acr-login-server> --docker-username <service-principal-ID> --docker-password <service-principal-password> --docker-email <email-address>
or
apiVersion: v1
kind: Secret
metadata:
name: acr-auth
type: docker-registry
data:
username: <base64encoded username>
password: <base64encoded password>
Both are equivalent.
you need to remove imagepullsecrets property from the pod\deployment definition. that way you will instruct kubernetes to use internal aks\acr auth
I'm trying to deploy a Kubernetes Pod in AKS (I'm new to Kubernetes, so at this stage, I just want to create a container, deploy to Kubernetes and connect to it).
My Yaml file is as follows:
apiVersion: v1
kind: Pod
spec:
containers:
- name: dockertest20190205080020
image: dockertest20190205080020.azurecr.io
ports:
- containerPort: 443
metadata:
name: my-test
I've created the image in Azure Container Registry and, according to the CLI, successfully deployed it to Kubernetes.
After deploying, I used the following command:
kubectl get service
And it tells me there is no External IP to connect to. I then tried:
kubectl describe pod my-test
Which gave the following errors:
Events:
Warning Failed 4m (x2221 over 8h) kubelet, aks-nodepool1-27401563-2 Error: ImagePullBackOff
Normal BackOff 0s (x2242 over 8h) kubelet, aks-nodepool1-27401563-2 Back-off pulling image "dockertest20190205080020.azurecr.io"
I then tried editing the deployment:
kubectl edit pods my-test
Which game me the error:
message: 'containers with unready status: [dockertest20190205080020]'
I'm not a little unsure what my next diagnostic step would be. I get the impression there's an issue with the container or the container registry, but I'm unsure how to determine what that may be.
What happens here (most likely) - your AKS doesnt have permissions to pull images frmo you ACR (that's the default behaviour). You need to grant those (link):
#!/bin/bash
AKS_RESOURCE_GROUP=myAKSResourceGroup
AKS_CLUSTER_NAME=myAKSCluster
ACR_RESOURCE_GROUP=myACRResourceGroup
ACR_NAME=myACRRegistry
# Get the id of the service principal configured for AKS
CLIENT_ID=$(az aks show --resource-group $AKS_RESOURCE_GROUP --name $AKS_CLUSTER_NAME --query "servicePrincipalProfile.clientId" --output tsv)
# Get the ACR registry resource id
ACR_ID=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query "id" --output tsv)
# Create role assignment
az role assignment create --assignee $CLIENT_ID --role acrpull --scope $ACR_ID
Alternative is to just use a docker login secret (that article mentions that as well).
Example image in ACR:
image name would be
clrtacr.azurecr.io/dns:tag (or without tag for latest)
I'm not sure if you know there is something wrong in your yaml file, or it just shows as you want for security. But I would show you here:
apiVersion: v1
kind: Pod
spec:
containers:
- name: dockertest20190205080020
image: dockertest20190205080020.azurecr.io/image_name_and_version
ports:
- containerPort: 443
metadata:
name: my-test
Also, as the error that you got shows, you don't have the permission to pull the image from your ACR.
On my side, I would be better to use a secret for pulling all the image from the ACR. You can create a service principal to achieve it. The steps would be like here:
#!/bin/bash
ACR_NAME=myacrinstance
SERVICE_PRINCIPAL_NAME=acr-service-principal
# Populate the ACR login server and resource id.
ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --query loginServer --output tsv)
ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query id --output tsv)
# Create acrpull role assignment with a scope of the ACR resource.
SP_PASSWD=$(az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME --role acrpull --scopes $ACR_REGISTRY_ID --query password --output tsv)
# Get the service principal client id.
CLIENT_ID=$(az ad sp show --id http://$SERVICE_PRINCIPAL_NAME --query appId --output tsv)
# Output used when creating Kubernetes secret.
echo "Service principal ID: $CLIENT_ID"
echo "Service principal password: $SP_PASSWD"
# Create the secret
kubectl create secret docker-registry acr-auth --docker-server <acr-login-server> --docker-username <service-principal-ID> --docker-password <service-principal-password>
Then you can change your yaml file like this:
apiVersion: v1
kind: Pod
spec:
containers:
- name: dockertest20190205080020
image: dockertest20190205080020.azurecr.io/image_name_and_version
ports:
- containerPort: 443
imagePullSecrets:
- name: acr-auth
metadata:
name: my-test