Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I den här artikeln utför du olika test- och valideringssteg i en PostgreSQL-databas som distribueras på AKS. Detta omfattar att verifiera distributionen, ansluta till databasen och testa redundansscenarier.
- Om du inte redan har distribuerat PostgreSQL följer du stegen i Distribuera en PostgreSQL-databas med hög tillgänglighet i AKS med Azure CLI för att konfigurera och sedan kan du återgå till den här artikeln.
Viktigt!
Programvara med öppen källkod nämns i AKS-dokumentationen och exempel. Programvara som du distribuerar undantas från AKS-serviceavtal, begränsad garanti och Azure Support. När du använder teknik med öppen källkod tillsammans med AKS kan du läsa supportalternativen som är tillgängliga från respektive community och projektunderhållare för att utveckla en plan.
Till exempel beskriver Ray GitHub-lagringsplatsen flera plattformar som varierar i svarstid, syfte och supportnivå.
Microsoft tar ansvar för att skapa de paket med öppen källkod som vi distribuerar på AKS. Det ansvaret omfattar att ha fullständigt ägarskap för bygg-, genomsöknings-, signerings-, validerings- och snabbkorrigeringsprocessen, tillsammans med kontroll över binärfilerna i containeravbildningar. Mer information finns i Sårbarhetshantering för AKS - och AKS-stödtäckning.
Granska det distribuerade PostgreSQL-klustret
Kontrollera att PostgreSQL är utspritt i flera tillgänglighetszoner genom att hämta AKS-nodinformationen kubectl get med hjälp av kommandot .
kubectl get nodes \
--context $AKS_PRIMARY_CLUSTER_NAME \
--namespace $PG_NAMESPACE \
--output json | jq '.items[] | {node: .metadata.name, zone: .metadata.labels."failure-domain.beta.kubernetes.io/zone"}'
Dina utdata bör likna följande exempelutdata med tillgänglighetszonen som visas för varje nod:
{
"node": "aks-postgres-15810965-vmss000000",
"zone": "westus3-1"
}
{
"node": "aks-postgres-15810965-vmss000001",
"zone": "westus3-2"
}
{
"node": "aks-postgres-15810965-vmss000002",
"zone": "westus3-3"
}
{
"node": "aks-systempool-26112968-vmss000000",
"zone": "westus3-1"
}
{
"node": "aks-systempool-26112968-vmss000001",
"zone": "westus3-2"
}
Anslut till PostgreSQL och skapa en exempeldatauppsättning
I det här avsnittet skapar du en tabell och infogar data i appdatabasen som skapades i CNPG-kluster-CRD som du distribuerade tidigare. Du använder dessa data för att verifiera säkerhetskopierings- och återställningsåtgärderna för PostgreSQL-klustret.
Skapa en tabell och infoga data i appdatabasen med hjälp av följande kommandon:
kubectl cnpg psql $PG_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE-- Create a small dataset CREATE TABLE datasample (id INTEGER, name VARCHAR(255)); INSERT INTO datasample (id, name) VALUES (1, 'John'); INSERT INTO datasample (id, name) VALUES (2, 'Jane'); INSERT INTO datasample (id, name) VALUES (3, 'Alice'); SELECT COUNT(*) FROM datasample;Skriv
\qför att avsluta psql när du är klar.Dina utdata bör likna följande exempelutdata:
CREATE TABLE INSERT 0 1 INSERT 0 1 INSERT 0 1 count ------- 3 (1 row)
Ansluta till skrivskyddade PostgreSQL-repliker
Anslut till PostgreSQL-skrivskyddade repliker och verifiera exempeldatauppsättningen med hjälp av följande kommandon:
kubectl cnpg psql --replica $PG_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACESELECT pg_is_in_recovery();Exempel på utdata
pg_is_in_recovery ------------------- t (1 row)SELECT COUNT(*) FROM datasample;Exempel på utdata
count ------- 3 (1 row)
Konfigurera postgreSQL-säkerhetskopieringar på begäran och schemalagda med Barman
Kontrollera att PostgreSQL-klustret kan komma åt Azure-lagringskontot som anges i CNPG-kluster-CRD och att det rapporteras som
Working WAL archivingOKmed hjälp av följande kommando:kubectl cnpg status $PG_PRIMARY_CLUSTER_NAME 1 \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACEExempel på utdata
Continuous Backup status First Point of Recoverability: Not Available Working WAL archiving: OK WALs waiting to be archived: 0 Last Archived WAL: 00000001000000000000000A @ 2024-07-09T17:18:13.982859Z Last Failed WAL: -Distribuera en säkerhetskopiering på begäran till Azure Storage, som använder identitetsintegrering för AKS-arbetsbelastning med hjälp av YAML-filen med
kubectl applykommandot .export BACKUP_ONDEMAND_NAME="on-demand-backup-1" cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -v 9 -f - apiVersion: postgresql.cnpg.io/v1 kind: Backup metadata: name: $BACKUP_ONDEMAND_NAME spec: method: barmanObjectStore cluster: name: $PG_PRIMARY_CLUSTER_NAME EOFVerifiera statusen för säkerhetskopieringen på begäran med hjälp av
kubectl describekommandot .kubectl describe backup $BACKUP_ONDEMAND_NAME \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACEExempel på utdata
Type Reason Age From Message ---- ------ ---- ---- ------- Normal Starting 6s cloudnative-pg-backup Starting backup for cluster pg-primary-cnpg-r8c7unrw Normal Starting 5s instance-manager Backup started Normal Completed 1s instance-manager Backup completedKontrollera att klustret har en första återställningspunkt med hjälp av följande kommando:
kubectl cnpg status $PG_PRIMARY_CLUSTER_NAME 1 \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACEExempel på utdata
Continuous Backup status First Point of Recoverability: 2024-06-05T13:47:18Z Working WAL archiving: OKKonfigurera en schemalagd säkerhetskopiering för varje timme vid 15 minuter efter timmen med hjälp av YAML-filen med
kubectl applykommandot .export BACKUP_SCHEDULED_NAME="scheduled-backup-1" cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -v 9 -f - apiVersion: postgresql.cnpg.io/v1 kind: ScheduledBackup metadata: name: $BACKUP_SCHEDULED_NAME spec: # Backup once per hour schedule: "0 15 * ? * *" backupOwnerReference: self cluster: name: $PG_PRIMARY_CLUSTER_NAME EOFVerifiera statusen för den schemalagda säkerhetskopieringen
kubectl describemed kommandot .kubectl describe scheduledbackup $BACKUP_SCHEDULED_NAME \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACEVisa säkerhetskopieringsfilerna som lagras i Azure Blob Storage för det primära klustret med hjälp av
az storage blob listkommandot .az storage blob list \ --account-name $PG_PRIMARY_STORAGE_ACCOUNT_NAME \ --container-name backups \ --query "[*].name" \ --only-show-errorsDina utdata bör likna följande exempelutdata och verifieringen av säkerhetskopian lyckades:
[ "pg-primary-cnpg-r8c7unrw/base/20240605T134715/backup.info", "pg-primary-cnpg-r8c7unrw/base/20240605T134715/data.tar", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000001", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000002", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000003", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000003.00000028.backup", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000004", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000005", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000005.00000028.backup", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000006", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000007", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000008", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000009" ]
Återställa säkerhetskopieringen på begäran till ett nytt PostgreSQL-kluster
I det här avsnittet återställer du säkerhetskopieringen på begäran som du skapade tidigare med CNPG-operatorn till en ny instans med hjälp av bootstrap-kluster-CRD. Ett kluster med en enda instans används för enkelhetens skull. Kom ihåg att AKS-arbetsbelastningsidentiteten (via CNPG inheritFromAzureAD) har åtkomst till säkerhetskopieringsfilerna och att återställningsklustrets namn används för att generera ett nytt Kubernetes-tjänstkonto särskilt för återställningsklustret.
Du kan också skapa en andra federerad autentiseringsuppgift för att mappa det nya tjänstkontot för återställningskluster till den befintliga UAMI som har åtkomsten "Storage Blob Data Contributor" till säkerhetskopieringsfilerna i Blob Storage.
Skapa en andra federerad identitetsautentiseringsuppgift med kommandot
az identity federated-credential create.export PG_PRIMARY_CLUSTER_NAME_RECOVERED="$PG_PRIMARY_CLUSTER_NAME-recovered-db" az identity federated-credential create \ --name $PG_PRIMARY_CLUSTER_NAME_RECOVERED \ --identity-name $AKS_UAMI_CLUSTER_IDENTITY_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --issuer "${AKS_PRIMARY_CLUSTER_OIDC_ISSUER}" \ --subject system:serviceaccount:"${PG_NAMESPACE}":"${PG_PRIMARY_CLUSTER_NAME_RECOVERED}" \ --audience api://AzureADTokenExchangeÅterställ säkerhetskopieringen på begäran med hjälp av kluster-CRD med
kubectl applykommandot .cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -v 9 -f - apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: $PG_PRIMARY_CLUSTER_NAME_RECOVERED spec: inheritedMetadata: annotations: service.beta.kubernetes.io/azure-dns-label-name: $AKS_PRIMARY_CLUSTER_PG_DNSPREFIX labels: azure.workload.identity/use: "true" instances: 1 affinity: nodeSelector: workload: postgres # Point to cluster backup created earlier and stored on Azure Blob Storage bootstrap: recovery: source: clusterBackup storage: size: 2Gi pvcTemplate: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi storageClassName: managed-csi-premium volumeMode: Filesystem walStorage: size: 2Gi pvcTemplate: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi storageClassName: managed-csi-premium volumeMode: Filesystem serviceAccountTemplate: metadata: annotations: azure.workload.identity/client-id: "$AKS_UAMI_WORKLOAD_CLIENTID" labels: azure.workload.identity/use: "true" externalClusters: - name: clusterBackup barmanObjectStore: destinationPath: https://${PG_PRIMARY_STORAGE_ACCOUNT_NAME}.blob.core.windows.net/backups serverName: $PG_PRIMARY_CLUSTER_NAME azureCredentials: inheritFromAzureAD: true wal: maxParallel: 8 EOFAnslut till den återställda instansen och kontrollera sedan att den datauppsättning som skapades i det ursprungliga klustret där den fullständiga säkerhetskopieringen gjordes finns med följande kommando:
kubectl cnpg psql $PG_PRIMARY_CLUSTER_NAME_RECOVERED --namespace $PG_NAMESPACESELECT COUNT(*) FROM datasample;Exempel på utdata
count ------- 3 (1 row) Type \q to exit psqlTa bort det återställda klustret med följande kommando:
kubectl cnpg destroy $PG_PRIMARY_CLUSTER_NAME_RECOVERED 1 \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACETa bort den federerade identitetsautentiseringsuppgiften
az identity federated-credential deletemed kommandot .az identity federated-credential delete \ --name $PG_PRIMARY_CLUSTER_NAME_RECOVERED \ --identity-name $AKS_UAMI_CLUSTER_IDENTITY_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --yes
Exponera PostgreSQL-klustret med hjälp av en offentlig lastbalanserare
I det här avsnittet konfigurerar du nödvändig infrastruktur för att offentligt exponera PostgreSQL-slutpunkterna för skrivande och skrivskyddad trafik med IP-källbegränsningar till den offentliga IP-adressen för din klientarbetsstation.
Du kan också hämta följande slutpunkter från kluster-IP-tjänsten:
-
En primär läs- och skrivslutpunkt som slutar med
*-rw. -
Noll till N (beroende på antalet repliker) skrivskyddade slutpunkter som slutar med
*-ro. -
En replikeringsslutpunkt som slutar med
*-r.
Hämta information om kluster-IP-tjänsten med hjälp av
kubectl getkommandot .kubectl get services \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACE \ -l cnpg.io/cluster=$PG_PRIMARY_CLUSTER_NAMEExempel på utdata
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE pg-primary-cnpg-sryti1qf-r ClusterIP 10.0.193.27 <none> 5432/TCP 3h57m pg-primary-cnpg-sryti1qf-ro ClusterIP 10.0.237.19 <none> 5432/TCP 3h57m pg-primary-cnpg-sryti1qf-rw ClusterIP 10.0.244.125 <none> 5432/TCP 3h57mAnmärkning
Det finns tre tjänster:
namespace/cluster-name-romappade till port 5433 ochnamespace/cluster-name-rwnamespace/cluster-name-rmappade till port 5433. Det är viktigt att undvika att använda samma port som läs-/skrivnoden i PostgreSQL-databasklustret. Om du bara vill att program ska få åtkomst till den skrivskyddade repliken av PostgreSQL-databasklustret dirigerar du dem till port 5433. Den slutliga tjänsten används vanligtvis för datasäkerhetskopior men kan också fungera som en skrivskyddad nod.Hämta tjänstinformationen med hjälp av
kubectl getkommandot .export PG_PRIMARY_CLUSTER_RW_SERVICE=$(kubectl get services \ --namespace $PG_NAMESPACE \ --context $AKS_PRIMARY_CLUSTER_NAME \ -l "cnpg.io/cluster" \ --output json | jq -r '.items[] | select(.metadata.name | endswith("-rw")) | .metadata.name') echo $PG_PRIMARY_CLUSTER_RW_SERVICE export PG_PRIMARY_CLUSTER_RO_SERVICE=$(kubectl get services \ --namespace $PG_NAMESPACE \ --context $AKS_PRIMARY_CLUSTER_NAME \ -l "cnpg.io/cluster" \ --output json | jq -r '.items[] | select(.metadata.name | endswith("-ro")) | .metadata.name') echo $PG_PRIMARY_CLUSTER_RO_SERVICEKonfigurera lastbalanserarens tjänst med följande YAML-filer med hjälp av
kubectl applykommandot .cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME -f - apiVersion: v1 kind: Service metadata: annotations: service.beta.kubernetes.io/azure-load-balancer-resource-group: $AKS_PRIMARY_CLUSTER_NODERG_NAME service.beta.kubernetes.io/azure-pip-name: $AKS_PRIMARY_CLUSTER_PUBLICIP_NAME service.beta.kubernetes.io/azure-dns-label-name: $AKS_PRIMARY_CLUSTER_PG_DNSPREFIX name: cnpg-cluster-load-balancer-rw namespace: "${PG_NAMESPACE}" spec: type: LoadBalancer ports: - protocol: TCP port: 5432 targetPort: 5432 selector: cnpg.io/instanceRole: primary cnpg.io/podRole: instance loadBalancerSourceRanges: - "$MY_PUBLIC_CLIENT_IP/32" EOF cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME -f - apiVersion: v1 kind: Service metadata: annotations: service.beta.kubernetes.io/azure-load-balancer-resource-group: $AKS_PRIMARY_CLUSTER_NODERG_NAME service.beta.kubernetes.io/azure-pip-name: $AKS_PRIMARY_CLUSTER_PUBLICIP_NAME service.beta.kubernetes.io/azure-dns-label-name: $AKS_PRIMARY_CLUSTER_PG_DNSPREFIX name: cnpg-cluster-load-balancer-ro namespace: "${PG_NAMESPACE}" spec: type: LoadBalancer ports: - protocol: TCP port: 5433 targetPort: 5432 selector: cnpg.io/instanceRole: replica cnpg.io/podRole: instance loadBalancerSourceRanges: - "$MY_PUBLIC_CLIENT_IP/32" EOFHämta tjänstinformationen med hjälp av
kubectl describekommandot .kubectl describe service cnpg-cluster-load-balancer-rw \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACE kubectl describe service cnpg-cluster-load-balancer-ro \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACE export AKS_PRIMARY_CLUSTER_ALB_DNSNAME="$(az network public-ip show \ --resource-group $AKS_PRIMARY_CLUSTER_NODERG_NAME \ --name $AKS_PRIMARY_CLUSTER_PUBLICIP_NAME \ --query "dnsSettings.fqdn" --output tsv)" echo $AKS_PRIMARY_CLUSTER_ALB_DNSNAME
Verifiera offentliga PostgreSQL-slutpunkter
I det här avsnittet kontrollerar du att Azure Load Balancer har konfigurerats korrekt med den statiska IP-adress som du skapade tidigare och dirigerar anslutningar till de primära skriv-läs- och skrivskyddade replikerna, och använder psql CLI för att ansluta till båda.
Kom ihåg att den primära läs- och skrivslutpunkten mappar till TCP-port 5432 och de skrivskyddade replikslutpunkterna mappar till port 5433 så att samma PostgreSQL DNS-namn kan användas för läsare och skrivare.
Anmärkning
Du behöver värdet för appanvändarlösenordet för grundläggande PostgreSQL-autentisering som genererades tidigare och lagrades i $PG_DATABASE_APPUSER_SECRET miljövariabeln.
Verifiera de offentliga PostgreSQL-slutpunkterna med hjälp av följande
psqlkommandon:echo "Public endpoint for PostgreSQL cluster: $AKS_PRIMARY_CLUSTER_ALB_DNSNAME" # Query the primary, pg_is_in_recovery = false psql -h $AKS_PRIMARY_CLUSTER_ALB_DNSNAME \ -p 5432 -U app -d appdb -W -c "SELECT pg_is_in_recovery();"Exempel på utdata
pg_is_in_recovery ------------------- f (1 row)echo "Query a replica, pg_is_in_recovery = true" psql -h $AKS_PRIMARY_CLUSTER_ALB_DNSNAME \ -p 5433 -U app -d appdb -W -c "SELECT pg_is_in_recovery();"Exempel på utdata
# Example output pg_is_in_recovery ------------------- t (1 row)När den är ansluten till den primära skriv-läs-slutpunkten returnerar PostgreSQL-funktionen
fför false, vilket innebär att den nuvarande anslutningen är skrivbar.När den är ansluten till en replik returnerar funktionen
tför true, vilket indikerar att databasen är under återhämtning och skrivskyddat.
Simulera en oplanerad överlämning
I det här avsnittet utlöser du ett plötsligt fel genom att ta bort podden som kör den primära, vilket simulerar en plötslig krasch eller förlust av nätverksanslutning till noden som är värd för PostgreSQL-primärt.
Kontrollera statusen för de poddinstanser som körs med hjälp av följande kommando:
kubectl cnpg status $PG_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACEExempel på utdata
Name Current LSN Rep role Status Node --------------------------- ----------- -------- ------- ----------- pg-primary-cnpg-sryti1qf-1 0/9000060 Primary OK aks-postgres-32388626-vmss000000 pg-primary-cnpg-sryti1qf-2 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000001 pg-primary-cnpg-sryti1qf-3 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000002Ta bort den primära podden med kommandot
kubectl delete.PRIMARY_POD=$(kubectl get pod \ --namespace $PG_NAMESPACE \ --no-headers \ -o custom-columns=":metadata.name" \ -l role=primary) kubectl delete pod $PRIMARY_POD --grace-period=1 --namespace $PG_NAMESPACEKontrollera att poddinstansen
pg-primary-cnpg-sryti1qf-2nu är den primära med hjälp av följande kommando:kubectl cnpg status $PG_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACEExempel på utdata
pg-primary-cnpg-sryti1qf-2 0/9000060 Primary OK aks-postgres-32388626-vmss000001 pg-primary-cnpg-sryti1qf-1 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000000 pg-primary-cnpg-sryti1qf-3 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000002pg-primary-cnpg-sryti1qf-1Återställ poddinstansen som primär med hjälp av följande kommando:kubectl cnpg promote $PG_PRIMARY_CLUSTER_NAME 1 --namespace $PG_NAMESPACEKontrollera att poddinstanserna har återgåt till sitt ursprungliga tillstånd före det oplanerade redundanstestet med hjälp av följande kommando:
kubectl cnpg status $PG_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACEExempel på utdata
Name Current LSN Rep role Status Node --------------------------- ----------- -------- ------- ----------- pg-primary-cnpg-sryti1qf-1 0/9000060 Primary OK aks-postgres-32388626-vmss000000 pg-primary-cnpg-sryti1qf-2 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000001 pg-primary-cnpg-sryti1qf-3 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000002
Rensa resurser
När du har granskat distributionen tar du bort alla resurser som du skapade i den här guiden med hjälp av
az group deletekommandot .az group delete --resource-group $RESOURCE_GROUP_NAME --no-wait --yes
Nästa steg
I den här guiden har du lärt dig att:
- Använd Azure CLI för att skapa ett AKS-kluster med flera zoner.
- Distribuera ett PostgreSQL-kluster och en databas med hög tillgänglighet med hjälp av CNPG-operatorn.
- Konfigurera övervakning för PostgreSQL med Prometheus och Grafana.
- Distribuera en exempeldatauppsättning till PostgreSQL-databasen.
- Simulera ett klusteravbrott och PostgreSQL-replikredundans.
- Utför en säkerhetskopia och återställning av PostgreSQL-databasen.
Mer information om hur du kan använda AKS för dina arbetsbelastningar finns i Vad är Azure Kubernetes Service (AKS)? Mer information om Azure Database for PostgreSQL finns i Vad är Azure Database for PostgreSQL?
Bidragsgivare
Microsoft ansvarar för denna artikel. Följande deltagare skrev den ursprungligen:
- Ken Kilty | Huvudansvarig TPM
- Russell de Pina | Huvudansvarig för TPM
- Adrian Joian | Senior kundtekniker
- Jenny Hayes | Senior innehållsutvecklare
- Carol Smith | Senior innehållsutvecklare
- Erin Schaffer | Innehållsutvecklare 2
- Adam Sharif | Kundtekniker 2
Azure Kubernetes Service