🦡
【MS Learn】Azure Kubernetes Service (AKS) でのアプリケーションの構成とシークレットの管理 をやった
はじめに
タイトルの文字数が足りない🙃
やってみたシリーズです。
今日はこちら
手を動かすところだけ記述していきます。
番号とかは飛び飛びになりますので、ご本家様と照らし合わせてみていただけると幸いです。
Azure Cloud Shellのbashで実行しています。
ユニット3: 演習 - シークレットでの変数の安全な格納
開始前の準備
- リソースグループを作成します。リージョンはjapaneastで。
Azure Cloud Shell
export RESOURCE_GROUP=rg-ship-manager
export CLUSTER_NAME=ship-manager-cluster
export LOCATION=japaneast
az group create --location $LOCATION --name $RESOURCE_GROUP
{
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rg-ship-manager",
"location": "japaneast",
"managedBy": null,
"name": "rg-ship-manager",
"properties": {
"provisioningState": "Succeeded"
},
"tags": null,
"type": "Microsoft.Resources/resourceGroups"
}
- AKS クラスターを作成します。
Azure Cloud Shell
$ az aks create \
-g $RESOURCE_GROUP \
-n $CLUSTER_NAME \
--location $LOCATION \
--node-count 1 \
--node-vm-size Standard_B2s \
--generate-ssh-keys \
--enable-addons http_application_routing
{
"aadProfile": null,
"addonProfiles": {
"httpApplicationRouting": {
"config": {
"HTTPApplicationRoutingZoneName": "c9fa5b63cf7744ff8c0a.japaneast.aksapp.io"
},
"enabled": true,
"identity": {
"clientId": "0e88e470-548c-4131-8b3a-6fc74c95ec06",
"objectId": "95d7273e-351f-4663-8a5d-76713c8a0eaa",
"resourceId": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/MC_rg-ship-manager_ship-manager-cluster_japaneast/providers/Microsoft.ManagedIdentity/userAssignedIdentities/httpapplicationrouting-ship-manager-cluster"
}
}
},
"agentPoolProfiles": [
{
"availabilityZones": null,
"count": 1,
"creationData": null,
"currentOrchestratorVersion": "1.26.6",
"enableAutoScaling": false,
"enableEncryptionAtHost": false,
"enableFips": false,
"enableNodePublicIp": false,
"enableUltraSsd": false,
"gpuInstanceProfile": null,
"hostGroupId": null,
"kubeletConfig": null,
"kubeletDiskType": "OS",
"linuxOsConfig": null,
"maxCount": null,
"maxPods": 110,
"minCount": null,
"mode": "System",
"name": "nodepool1",
"nodeImageVersion": "AKSUbuntu-2204gen2containerd-202309.06.0",
"nodeLabels": null,
"nodePublicIpPrefixId": null,
"nodeTaints": null,
"orchestratorVersion": "1.26.6",
"osDiskSizeGb": 128,
"osDiskType": "Managed",
"osSku": "Ubuntu",
"osType": "Linux",
"podSubnetId": null,
"powerState": {
"code": "Running"
},
"provisioningState": "Succeeded",
"proximityPlacementGroupId": null,
"scaleDownMode": null,
"scaleSetEvictionPolicy": null,
"scaleSetPriority": null,
"spotMaxPrice": null,
"tags": null,
"type": "VirtualMachineScaleSets",
"upgradeSettings": {
"drainTimeoutInMinutes": null,
"maxSurge": null
},
"vmSize": "Standard_B2s",
"vnetSubnetId": null,
"workloadRuntime": null
}
],
"apiServerAccessProfile": null,
"autoScalerProfile": null,
"autoUpgradeProfile": {
"nodeOsUpgradeChannel": "NodeImage",
"upgradeChannel": null
},
"azureMonitorProfile": null,
"azurePortalFqdn": "ship-manag-rg-ship-manager-a058ec-1j6bfb4y.portal.hcp.japaneast.azmk8s.io",
"currentKubernetesVersion": "1.26.6",
"disableLocalAccounts": false,
"diskEncryptionSetId": null,
"dnsPrefix": "ship-manag-rg-ship-manager-a058ec",
"enablePodSecurityPolicy": null,
"enableRbac": true,
"extendedLocation": null,
"fqdn": "ship-manag-rg-ship-manager-a058ec-1j6bfb4y.hcp.japaneast.azmk8s.io",
"fqdnSubdomain": null,
"httpProxyConfig": null,
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/rg-ship-manager/providers/Microsoft.ContainerService/managedClusters/ship-manager-cluster",
"identity": {
"delegatedResources": null,
"principalId": "92b7870a-a8db-4b03-9f99-2cc52c0ec8c8",
"tenantId": "cb9bb346-c037-4fb2-a3ff-dd23544753ea",
"type": "SystemAssigned",
"userAssignedIdentities": null
},
"identityProfile": {
"kubeletidentity": {
"clientId": "2796c780-7fc4-4f57-a7a2-00086535632f",
"objectId": "9082eb66-fc2f-48a1-8ef2-f244f341ac92",
"resourceId": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/MC_rg-ship-manager_ship-manager-cluster_japaneast/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ship-manager-cluster-agentpool"
}
},
"kubernetesVersion": "1.26.6",
"linuxProfile": {
"adminUsername": "azureuser",
"ssh": {
"publicKeys": [
{
"keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCtlQI5JNtID9FT9ei748fLS8yiwL94XmBPoXsxv9UGFe3ZilBzAtPUara5AXKVHDiHcPyLuXTq6iLbbC1tvVidf1BsH/lwFFSjz/z7aSAS2I84dAu5E/+AYg6azipYYtWzcCwIPfhaP0FqgtEOb0+Cvf1DgZ2tmUfOlg2qY0PdfrTU7Pf5cpCK46+zLhqQL7HpZNi/CHQrtU5TiSU6gU2gUy0/tOvlvUh4T+ipR+yH51Y2XF5v0Szy8c1brSOJ4VpO8sdxLycSw2QYOMbuv0Pxjg8YIv5yKbGxjKVOCn6Mp8QwOgYj1BeEdpUr4Lz2/ZuFlJoTNcPQSkxCjVI0VtRF"
}
]
}
},
"location": "japaneast",
"maxAgentPools": 100,
"name": "ship-manager-cluster",
"networkProfile": {
"dnsServiceIp": "10.0.0.10",
"ipFamilies": [
"IPv4"
],
"loadBalancerProfile": {
"allocatedOutboundPorts": null,
"effectiveOutboundIPs": [
{
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/MC_rg-ship-manager_ship-manager-cluster_japaneast/providers/Microsoft.Network/publicIPAddresses/4d702973-7ca5-464e-9163-7d4bc6d5ebec",
"resourceGroup": "MC_rg-ship-manager_ship-manager-cluster_japaneast"
}
],
"enableMultipleStandardLoadBalancers": null,
"idleTimeoutInMinutes": null,
"managedOutboundIPs": {
"count": 1,
"countIpv6": null
},
"outboundIPs": null,
"outboundIpPrefixes": null
},
"loadBalancerSku": "Standard",
"natGatewayProfile": null,
"networkDataplane": null,
"networkMode": null,
"networkPlugin": "kubenet",
"networkPluginMode": null,
"networkPolicy": null,
"outboundType": "loadBalancer",
"podCidr": "10.244.0.0/16",
"podCidrs": [
"10.244.0.0/16"
],
"serviceCidr": "10.0.0.0/16",
"serviceCidrs": [
"10.0.0.0/16"
]
},
"nodeResourceGroup": "MC_rg-ship-manager_ship-manager-cluster_japaneast",
"oidcIssuerProfile": {
"enabled": false,
"issuerUrl": null
},
"podIdentityProfile": null,
"powerState": {
"code": "Running"
},
"privateFqdn": null,
"privateLinkResources": null,
"provisioningState": "Succeeded",
"publicNetworkAccess": null,
"resourceGroup": "rg-ship-manager",
"securityProfile": {
"azureKeyVaultKms": null,
"defender": null,
"imageCleaner": null,
"workloadIdentity": null
},
"servicePrincipalProfile": {
"clientId": "msi",
"secret": null
},
"sku": {
"name": "Base",
"tier": "Free"
},
"storageProfile": {
"blobCsiDriver": null,
"diskCsiDriver": {
"enabled": true
},
"fileCsiDriver": {
"enabled": true
},
"snapshotController": {
"enabled": true
}
},
"supportPlan": "KubernetesOfficial",
"systemData": null,
"tags": null,
"type": "Microsoft.ContainerService/ManagedClusters",
"upgradeSettings": null,
"windowsProfile": null,
"workloadAutoScalerProfile": {
"keda": null,
"verticalPodAutoscaler": null
}
}
- コンテキストを取得します。
Azure Cloud Shell
$ az aks get-credentials -n $CLUSTER_NAME -g $RESOURCE_GROUP
シークレットの作成
- MongoDB データベースをデプロイします。
Azure Cloud Shell
$ export DATABASE_NAME=contoso-ship-manager-$RANDOM && \
az cosmosdb create \
-n $DATABASE_NAME \
-g $RESOURCE_GROUP \
--kind MongoDB
{
"analyticalStorageConfiguration": {
"schemaType": "FullFidelity"
},
"apiProperties": {
"serverVersion": "3.6"
},
"backupPolicy": {
"migrationState": null,
"periodicModeProperties": {
"backupIntervalInMinutes": 240,
"backupRetentionIntervalInHours": 8,
"backupStorageRedundancy": "Geo"
},
"type": "Periodic"
},
"capabilities": [
{
"name": "EnableMongo"
}
],
"capacity": null,
"connectorOffer": null,
"consistencyPolicy": {
"defaultConsistencyLevel": "Session",
"maxIntervalInSeconds": 5,
"maxStalenessPrefix": 100
},
"cors": [],
"createMode": null,
"databaseAccountOfferType": "Standard",
"defaultIdentity": "FirstPartyIdentity",
"disableKeyBasedMetadataWriteAccess": false,
"disableLocalAuth": false,
"documentEndpoint": "https://contoso-ship-manager-3289.documents.azure.com:443/",
"enableAnalyticalStorage": false,
"enableAutomaticFailover": false,
"enableCassandraConnector": null,
"enableFreeTier": false,
"enableMultipleWriteLocations": false,
"enablePartitionMerge": false,
"failoverPolicies": [
{
"failoverPriority": 0,
"id": "contoso-ship-manager-3289-japaneast",
"locationName": "Japan East"
}
],
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rg-ship-manager/providers/Microsoft.DocumentDB/databaseAccounts/contoso-ship-manager-3289",
"identity": {
"principalId": null,
"tenantId": null,
"type": "None",
"userAssignedIdentities": null
},
"instanceId": "16ff5e7c-989b-41d6-9758-8bbdf60b0c9c",
"ipRules": [],
"isVirtualNetworkFilterEnabled": false,
"keyVaultKeyUri": null,
"keysMetadata": {
"primaryMasterKey": {
"generationTime": "2023-10-12T01:45:12.889474+00:00"
},
"primaryReadonlyMasterKey": {
"generationTime": "2023-10-12T01:45:12.889474+00:00"
},
"secondaryMasterKey": {
"generationTime": "2023-10-12T01:45:12.889474+00:00"
},
"secondaryReadonlyMasterKey": {
"generationTime": "2023-10-12T01:45:12.889474+00:00"
}
},
"kind": "MongoDB",
"location": "Japan East",
"locations": [
{
"documentEndpoint": "https://contoso-ship-manager-3289-japaneast.documents.azure.com:443/",
"failoverPriority": 0,
"id": "contoso-ship-manager-3289-japaneast",
"isZoneRedundant": false,
"locationName": "Japan East",
"provisioningState": "Succeeded"
}
],
"minimalTlsVersion": "Tls12",
"name": "contoso-ship-manager-3289",
"networkAclBypass": "None",
"networkAclBypassResourceIds": [],
"privateEndpointConnections": null,
"provisioningState": "Succeeded",
"publicNetworkAccess": "Enabled",
"readLocations": [
{
"documentEndpoint": "https://contoso-ship-manager-3289-japaneast.documents.azure.com:443/",
"failoverPriority": 0,
"id": "contoso-ship-manager-3289-japaneast",
"isZoneRedundant": false,
"locationName": "Japan East",
"provisioningState": "Succeeded"
}
],
"resourceGroup": "rg-ship-manager",
"restoreParameters": null,
"systemData": {
"createdAt": "2023-10-12T01:45:12.889474+00:00",
"createdBy": null,
"createdByType": null,
"lastModifiedAt": null,
"lastModifiedBy": null,
"lastModifiedByType": null
},
"tags": {},
"type": "Microsoft.DocumentDB/databaseAccounts",
"virtualNetworkRules": [],
"writeLocations": [
{
"documentEndpoint": "https://contoso-ship-manager-3289-japaneast.documents.azure.com:443/",
"failoverPriority": 0,
"id": "contoso-ship-manager-3289-japaneast",
"isZoneRedundant": false,
"locationName": "Japan East",
"provisioningState": "Succeeded"
}
]
}
DBができたら接続文字列を取得します。
Azure Cloud Shell
$ az cosmosdb keys list \
--type connection-strings \
-g $RESOURCE_GROUP \
-n $DATABASE_NAME \
-o tsv \
--query "connectionStrings[0].connectionString"
mongodb://contoso-ship-manager-3289:znWHOSjseEgocRevi7wZhf79g8GdZv2gCSkILpTYI2Dpzk*********8RxrYAdtPCqRjQ9nyFACDbYa9aQA==@contoso-ship-manager-3289.mongo.cosmos.azure.com:10255/?ssl=true&replicaSet=globaldb&retrywrites=false&maxIdleTimeMS=120000&appName=@contoso-ship-manager-3289@
- backend-secret.yaml を作成します。
Azure Cloud Shell
$ touch backend-secret.yaml
- エディタで開きます。
Azure Cloud Shell
$ touch backend-secret.yaml
- シークレットの仕様を記述します。プレースホルダ文字列は先ほど取得した接続文字列に置き換えることを忘れずに。
backend-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: ship-manager-database
namespace: default
type: Opaque
stringData:
database_mongodb_uri: "<paste the connection string here>"
- ファイルを保存して閉じます。
- kubectl apply コマンドを実行してシークレットを適用します。
Azure Cloud Shell
$ kubectl apply -f backend-secret.yaml
secret/ship-manager-database created
- シークレットに対してクエリを実行し、作業の結果を確認します。
Azure Cloud Shell
$ kubectl get secret ship-manager-database
NAME TYPE DATA AGE
ship-manager-database Opaque 1 103s
アプリケーションを作成する
- HTTP アプリケーション ルーティング アドオンによって使用可能になった DNS ゾーンを取得します。
Azure Cloud Shell
$ az aks show \
-g $RESOURCE_GROUP \
-n $CLUSTER_NAME \
-o tsv \
--query addonProfiles.httpApplicationRouting.config.HTTPApplicationRoutingZoneName
c9fa5b63cf7744ff8c0a.japaneast.aksapp.io
- backend-application.yaml を作成して、エディタで開きます。
Azure Cloud Shell
$ touch backend-application.yaml
$ code backend-application.yaml
- 以下のコードを記述して、保存して閉じます。
backend-application.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ship-manager-backend
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: ship-manager-backend
template:
metadata:
labels:
app: ship-manager-backend
spec:
containers:
- image: mcr.microsoft.com/mslearn/samples/contoso-ship-manager:backend
name: ship-manager-backend
ports:
- containerPort: 3000
name: http
env:
- name: DATABASE_MONGODB_URI
valueFrom:
secretKeyRef:
key: database_mongodb_uri
name: ship-manager-database
- name: DATABASE_MONGODB_DBNAME
value: ship_manager
envのところがポイントらしいです。
- backend-application.yaml の末尾にサービスを追記します。
backend-application.yaml
---
apiVersion: v1
kind: Service
metadata:
name: ship-manager-backend
namespace: default
spec:
selector:
app: ship-manager-backend
ports:
- name: http
port: 80
targetPort: 3000
---
パイプ3つで区切れるんですね。
5-6. イングレスを追加します。backend-application.yaml の末尾に以下のコードを追加します。
backend-application.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ship-manager-backend
namespace: default
annotations:
kubernetes.io/ingress.class: addon-http-application-routing
spec:
rules:
- host: ship-manager-backend.c9fa5b63cf7744ff8c0a.japaneast.aksapp.io # ここを取得したDNSゾーンに変更する
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ship-manager-backend
port:
name: http
ファイル全体はこんな感じ
backend-application.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ship-manager-backend
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: ship-manager-backend
template:
metadata:
labels:
app: ship-manager-backend
spec:
containers:
- image: mcr.microsoft.com/mslearn/samples/contoso-ship-manager:backend
name: ship-manager-backend
ports:
- containerPort: 3000
name: http
env:
- name: DATABASE_MONGODB_URI
valueFrom:
secretKeyRef:
key: database_mongodb_uri
name: ship-manager-database
- name: DATABASE_MONGODB_DBNAME
value: ship_manager
---
apiVersion: v1
kind: Service
metadata:
name: ship-manager-backend
namespace: default
spec:
selector:
app: ship-manager-backend
ports:
- name: http
port: 80
targetPort: 3000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ship-manager-backend
namespace: default
annotations:
kubernetes.io/ingress.class: addon-http-application-routing
spec:
rules:
- host: ship-manager-backend.c9fa5b63cf7744ff8c0a.japaneast.aksapp.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ship-manager-backend
port:
name: http
- 変更を適用します。
Azure Cloud Shell
$ kubectl apply -f backend-application.yaml
deployment.apps/ship-manager-backend created
service/ship-manager-backend created
ingress.networking.k8s.io/ship-manager-backend created
変更が反映されるまでは少し時間がかかります。
※/shipsとかにアクセスすると空の配列が返ってきます。データ入れてないからかな。
ユニット5: 演習 - ConfigMap を使用したアプリケーションの強化
開始前の準備
は上記でやっているのでここでは割愛。
ConfigMap の作成
- HTTP アプリケーション ルーティング アドオンによって使用可能になった DNS ゾーンを取得します。ユニット3で取得しましたね。
Azure Cloud Shell
$ az aks show \
-g $RESOURCE_GROUP \
-n $CLUSTER_NAME \
-o tsv \
--query addonProfiles.httpApplicationRouting.config.HTTPApplicationRoutingZoneName
c9fa5b63cf7744ff8c0a.japaneast.aksapp.io
2-3. configmap.yaml を作成し、エディタで開きます。
Azure Cloud Shell
$ touch configmap.yaml
$ code configmap.yaml
- 以下のコードを貼り付けます。
configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ship-manager-config
namespace: default
data:
config.js: |
const config = (() => {
return {
'VUE_APP_BACKEND_BASE_URL': 'http://ship-manager-backend.c9fa5b63cf7744ff8c0a.japaneast.aksapp.io', # DNSゾーンを書き換える
}
})()
- ファイルを保存して閉じます。
- クラスターに変更を適用します。
Azure Cloud Shell
$ kubectl apply -f configmap.yaml
configmap/ship-manager-config created
- 作成した ConfigMap に対してクエリを実行し、作業内容を確認します。
Azure Cloud Shell
$ kubectl get configmap ship-manager-config
NAME DATA AGE
ship-manager-config 1 41s
アプリケーションを作成する
- frontend.yaml を作成します。
Azure Cloud Shell
$ touch frontend.yaml
$ code frontend.yaml
- 以下のコードを貼り付けます。
frontend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: contoso-ship-manager-frontend
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: contoso-ship-manager-frontend
template:
metadata:
labels:
app: contoso-ship-manager-frontend
spec:
containers:
- image: mcr.microsoft.com/mslearn/samples/contoso-ship-manager:frontend
name: contoso-ship-manager-frontend
ports:
- containerPort: 80
name: http
volumeMounts:
- name: config
mountPath: /usr/src/app/dist/config.js
subPath: config.js
volumes:
- name: config
configMap:
name: ship-manager-config
---
volumeMounts で ConfigMap をマウントしてます。
- 末尾に以下のサービスとイングレスのコードを追記します。
frontend.yaml
apiVersion: v1
kind: Service
metadata:
name: contoso-ship-manager-frontend
namespace: default
spec:
selector:
app: contoso-ship-manager-frontend
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: contoso-ship-manager-frontend
namespace: default
annotations:
kubernetes.io/ingress.class: addon-http-application-routing
spec:
rules:
- host: contoso-ship-manager.c9fa5b63cf7744ff8c0a.japaneast.aksapp.io # DNSゾーンは書き換える
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: contoso-ship-manager-frontend
port:
name: http
- ファイルを保存して閉じます。
ファイルの全体はこんな感じ
frontend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: contoso-ship-manager-frontend
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: contoso-ship-manager-frontend
template:
metadata:
labels:
app: contoso-ship-manager-frontend
spec:
containers:
- image: mcr.microsoft.com/mslearn/samples/contoso-ship-manager:frontend
name: contoso-ship-manager-frontend
ports:
- containerPort: 80
name: http
volumeMounts:
- name: config
mountPath: /usr/src/app/dist/config.js
subPath: config.js
volumes:
- name: config
configMap:
name: ship-manager-config
---
apiVersion: v1
kind: Service
metadata:
name: contoso-ship-manager-frontend
namespace: default
spec:
selector:
app: contoso-ship-manager-frontend
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: contoso-ship-manager-frontend
namespace: default
annotations:
kubernetes.io/ingress.class: addon-http-application-routing
spec:
rules:
- host: contoso-ship-manager.c9fa5b63cf7744ff8c0a.japaneast.aksapp.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: contoso-ship-manager-frontend
port:
name: http
- アプリケーションをデプロイします。
Azure Cloud Shell
$ kubectl apply -f frontend.yaml
deployment.apps/contoso-ship-manager-frontend created
service/contoso-ship-manager-frontend created
ingress.networking.k8s.io/contoso-ship-manager-frontend created
- Kubernetes API に対してクエリを実行し、作業内容を確認します。
Azure Cloud Shell
kubectl get deploy contoso-ship-manager-frontend
NAME READY UP-TO-DATE AVAILABLE AGE
contoso-ship-manager-frontend 1/1 1 1 2m59s
※ちなみに、このフロントエンドにアクセスしたら真っ白な画面が出ました。データ入れてないからかな。
起動したしいいか。おわりに
これの応用でKeyVaultにシークレットを保存して、configMapで読めるようにするとか感じなのかなぁと思ったり。また調べてやってみよう
Discussion