这是一个来自于Azure的实验,实验资料:Azure Kubernetes 服务部署管道和 GitHub Actions
CICD
持续集成 (CI)
CI 要求团队经常在代码中实现和集成最小更改。 实现此方法意味需要不断测试、编译、部署,然后在生产环境中再次测试。
最重要的 CI 原则之一是尽可能频繁地将所有最新更改合并回主分支。 不断合并更改有助于避免出现“集成地狱”和合并日,当许多开发人员在一天内一次性合并其更改时,常常会发生这种情况。
CI 旨在避免因代码更改而引起的生产问题,即在问题对研发人员或客户造成实际损害之前检测到这些问题。
CI 管道
CI 管道是我们为检测到新的代码更改时所运行的进程赋予的统称。 每当代码更改触发 CI 运行时,将执行所有管道步骤。 如果其中一个步骤出现错误,则管道将停止执行。
事件会触发管道。 软件开发过程中会触发大量事件。 CI 提供程序需要支持所有相关事件。 触发事件时,将触发此特定事件的所有侦听器。 进程的第一个阶段将启动。
在大多数情况下,该过程从克隆或下载源代码开始。 然后,触发下一步,依此类推。
工作流可以包含逻辑跳转,以便在满足某些条件时不执行阶段,但管道会继续执行。
持续交付 (CD)
CD 从 CI 结束的地方开始。 CD 会自动执行到所选基础结构环境的交付过程。 可以使用 CD 快速、持续地向客户发布新更改。
使用 CD 时,可以提前决定是每天、每周、每月还是视业务需要择日来部署更改。
本实验CICD管道设计
本实验假设应用Contoso ,其会生成一个应用网站。
- CI阶段会生成两个工作管道,分别会生成带有latest和版本(如v.0.0.1)标签的镜像,并将两种镜像存储在镜像注册表中。
- CD阶段,在成功向主分支进行带标签的推送后,会在 AKS 中发布一个网站。 此设计可以检查投入生产环境的每个部署的版本。 将容器镜像部署好后,可以使用标签进行路由。
- 在每次成功推送到主分支(无论推送是否带标签)时在过渡环境中测试网站。
现在来设计此管道。
CI管道设计
Github Actions
Github Actions是本实验在Ci阶段使用的主要工具。GitHub Actions 通过自动化工作流无缝集成 GitHub 中的所有托管代码,工作流可以执行多个任务,并将代码集成到多个环境中(本实验环境为Azure镜像注册表)。
- GitHub Actions 支持所有 GitHub 事件。 每个步骤都定义为一个操作,该操作可以是 JavaScript 代码,也可以是 Docker 容器。
- Actions 是管道的最重要部分。 即阶段性的构建基块,且易于创建。
设计要点
- 原始环境MicrosoftDocs/mslearn-aks-deployment-pipeline-github-actions,fork到github个人账户。使用Azure CLI或Cloud Shell克隆。
- ACR和AKS的初始化使用克隆文件夹下init.sh实现
- 使用Github Actions创建两个工作流。一个为lasted版本,一个为v*版本触发。两个工作流生成的镜像Push到ACR镜像库。
本阶段设计的管道流程图:
如上图所示:两个不同的事件会触发管道
- 向主分支进行带标签的推送
- 向主分支进行不带标签的推送
CD管道设计
对于部署步骤,是将网站部署到正确位置。
设计要点
- 如果带标签的提交触发了管道,将网站部署到 AKS 群集的 production 命名空间中的生产环境
- 如果带标记的提交没有触发管道,将其推送到同一群集的 staging 命名空间
- 使用Helm为生成应用工具
本阶段设计的管道流程图:
LAB
初始化环境
- Fork原始内容
- 克隆文件夹到本地,使用Cloud shell或Azure CLI
[root@Alma ~]# git clone <https://github.com/etaon/mslearn-aks-deployment-pipeline-github-actions>
Cloning into 'mslearn-aks-deployment-pipeline-github-actions'...
remote: Enumerating objects: 146, done.
remote: Total 146 (delta 0), reused 0 (delta 0), pack-reused 146
Receiving objects: 100% (146/146), 225.46 KiB | 965.00 KiB/s, done.
Resolving deltas: 100% (59/59), done.
查看内容:
[root@Alma ~]# cd mslearn-aks-deployment-pipeline-github-actions/
[root@Alma mslearn-aks-deployment-pipeline-github-actions]# ll
total 48
-rw-r--r--. 1 root root 444 Jan 17 10:39 CODE_OF_CONDUCT.md
-rw-r--r--. 1 root root 574 Jan 17 10:39 Dockerfile
-rwxr-xr-x. 1 root root 1687 Jan 17 10:39 init.sh
drwxr-xr-x. 2 root root 69 Jan 17 10:39 kubernetes
-rw-r--r--. 1 root root 18653 Jan 17 10:39 LICENSE
-rw-r--r--. 1 root root 1141 Jan 17 10:39 LICENSE-CODE
-rw-r--r--. 1 root root 7686 Jan 17 10:39 README.md
-rw-r--r--. 1 root root 2780 Jan 17 10:39 SECURITY.md
drwxr-xr-x. 7 root root 101 Jan 17 10:39 src
- 使用init.sh生成环境,其内容如下
#!/bin/bash
echo "Defining variables..."
export RESOURCE_GROUP_NAME=mslearn-gh-pipelines-$RANDOM
export AKS_NAME=contoso-video
export ACR_NAME=ContosoContainerRegistry$RANDOM
echo "Searching for resource group..."
az group create -n $RESOURCE_GROUP_NAME -l eastus
echo "Creating cluster..."
az aks create \\
--resource-group $RESOURCE_GROUP_NAME \\
--name $AKS_NAME \\
--node-count 1 \\
--enable-addons http_application_routing \\
--dns-name-prefix $AKS_NAME \\
--enable-managed-identity \\
--generate-ssh-keys \\
--node-vm-size Standard_B2s
echo "Obtaining credentials..."
az aks get-credentials -n $AKS_NAME -g $RESOURCE_GROUP_NAME
echo "Creating ACR..."
az acr create -n $ACR_NAME -g $RESOURCE_GROUP_NAME --sku basic
az acr update -n $ACR_NAME --admin-enabled true
export ACR_USERNAME=$(az acr credential show -n $ACR_NAME --query "username" -o tsv)
export ACR_PASSWORD=$(az acr credential show -n $ACR_NAME --query "passwords[0].value" -o tsv)
az aks update \\
--name $AKS_NAME \\
--resource-group $RESOURCE_GROUP_NAME \\
--attach-acr $ACR_NAME
export DNS_NAME=$(az network dns zone list -o json --query "[?contains(resourceGroup,'$RESOURCE_GROUP_NAME')].name" -o tsv)
sed -i '' 's+!IMAGE!+'"$ACR_NAME"'/contoso-website+g' kubernetes/deployment.yaml
sed -i '' 's+!DNS!+'"$DNS_NAME"'+g' kubernetes/ingress.yaml
echo "Installation concluded, copy these values and store them, you'll use them later in this exercise:"
echo "-> Resource Group Name: $RESOURCE_GROUP_NAME"
echo "-> ACR Name: $ACR_NAME"
echo "-> ACR Login Username: $ACR_USERNAME"
echo "-> ACR Password: $ACR_PASSWORD"
echo "-> AKS Cluster Name: $ACR_NAME"
echo "-> AKS DNS Zone Name: $DNS_NAME"
可以看出本脚本主要生成一个AKS Cluster和一个ACR仓库。
[root@Alma mslearn-aks-deployment-pipeline-github-actions]# ./init.sh
Defining variables...
Searching for resource group...
{
"id": "/subscriptions/14adb214-7b29-422a-ac8a-df2af1e51201/resourceGroups/mslearn-gh-pipelines-6498",
"location": "eastus",
"managedBy": null,
"name": "mslearn-gh-pipelines-6498",
"properties": {
"provisioningState": "Succeeded"
},
"tags": null,
"type": "Microsoft.Resources/resourceGroups"
}
Creating cluster...
{
"aadProfile": null,
"addonProfiles": {
"httpApplicationRouting": {
"config": {
"HTTPApplicationRoutingZoneName": "9c4fe3790bba4b1eadd1.eastus.aksapp.io"
},
"enabled": true,
"identity": {
"clientId": "78b08f9a-00dd-4111-8d5f-56ba045ac2d8",
"objectId": "a5b7f775-f724-4c94-aead-28595e5e821b",
"resourceId": "/subscriptions/14adb214-7b29-422a-ac8a-df2af1e51201/resourcegroups/MC_mslearn-gh-pipelines-6498_contoso-video_eastus/providers/Microsoft.ManagedIdentity/userAssignedIdentities/httpapplicationrouting-contoso-video"
}
}
},
"agentPoolProfiles": [
{
"availabilityZones": null,
"count": 1,
"enableAutoScaling": false,
"enableEncryptionAtHost": false,
"enableFips": false,
"enableNodePublicIp": false,
"enableUltraSsd": false,
"gpuInstanceProfile": null,
"kubeletConfig": null,
"kubeletDiskType": "OS",
"linuxOsConfig": null,
"maxCount": null,
"maxPods": 110,
"minCount": null,
"mode": "System",
"name": "nodepool1",
"nodeImageVersion": "AKSUbuntu-1804gen2containerd-2022.01.07",
"nodeLabels": null,
"nodePublicIpPrefixId": null,
"nodeTaints": null,
"orchestratorVersion": "1.21.7",
"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": null,
"vmSize": "Standard_B2s",
"vnetSubnetId": null
}
],
"apiServerAccessProfile": null,
"autoScalerProfile": null,
"autoUpgradeProfile": null,
"azurePortalFqdn": "contoso-video-b9c207fb.portal.hcp.eastus.azmk8s.io",
"disableLocalAccounts": false,
"diskEncryptionSetId": null,
"dnsPrefix": "contoso-video",
"enablePodSecurityPolicy": null,
"enableRbac": true,
"extendedLocation": null,
"fqdn": "contoso-video-b9c207fb.hcp.eastus.azmk8s.io",
"fqdnSubdomain": null,
"httpProxyConfig": null,
"id": "/subscriptions/14adb214-7b29-422a-ac8a-df2af1e51201/resourcegroups/mslearn-gh-pipelines-6498/providers/Microsoft.ContainerService/managedClusters/contoso-video",
"identity": {
"principalId": "2d7d6a16-0029-4650-a940-e06444a45528",
"tenantId": "7446b7c5-bb59-4186-a8df-513c195bc49f",
"type": "SystemAssigned",
"userAssignedIdentities": null
},
"identityProfile": {
"kubeletidentity": {
"clientId": "bce75f9f-3c0a-47a4-b286-817aa71606c7",
"objectId": "9e9f8eac-2e13-4124-8471-3ae4aa22c0e6",
"resourceId": "/subscriptions/14adb214-7b29-422a-ac8a-df2af1e51201/resourcegroups/MC_mslearn-gh-pipelines-6498_contoso-video_eastus/providers/Microsoft.ManagedIdentity/userAssignedIdentities/contoso-video-agentpool"
}
},
"kubernetesVersion": "1.21.7",
"linuxProfile": {
"adminUsername": "azureuser",
"ssh": {
"publicKeys": [
{
"keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTn5WASHIgIKuIeEgGSdkaxZ8DntqG+zUkjMPiZMxtRH2/dZaL230SbRG+FZ3FrsvnQp40d7TSCGdADIufsS9hkNkR0egzIsPGqzhcjyeYOAOSBD8atImbAxb6aFntk1uS1hVpn2C2p5DE0//FsWdp+KDTVAcdHgkrYMPECTfQh/lmURlddaLf3ZNju6xUc/sOFDAPZmVXr17pkuAYRjAr7MGchh6Rpbkg665ZOdY4lAJWDZONJ1u1DsyGQO18qdLDU7ZreOSgHe0pgLbVtKnUTAhGicjQqRGvwfKUQdyV223PjBqo57o/iNpPej2NR2Euhbcst25BE8KjzZ6l9y8n"
}
]
}
},
"location": "eastus",
"maxAgentPools": 100,
"name": "contoso-video",
"networkProfile": {
"dnsServiceIp": "10.0.0.10",
"dockerBridgeCidr": "172.17.0.1/16",
"loadBalancerProfile": {
"allocatedOutboundPorts": null,
"effectiveOutboundIPs": [
{
"id": "/subscriptions/14adb214-7b29-422a-ac8a-df2af1e51201/resourceGroups/MC_mslearn-gh-pipelines-6498_contoso-video_eastus/providers/Microsoft.Network/publicIPAddresses/8b24dcb0-2bac-46c7-bcb6-27908632326c",
"resourceGroup": "MC_mslearn-gh-pipelines-6498_contoso-video_eastus"
}
],
"idleTimeoutInMinutes": null,
"managedOutboundIPs": {
"count": 1
},
"outboundIPs": null,
"outboundIpPrefixes": null
},
"loadBalancerSku": "Standard",
"natGatewayProfile": null,
"networkMode": null,
"networkPlugin": "kubenet",
"networkPolicy": null,
"outboundType": "loadBalancer",
"podCidr": "10.244.0.0/16",
"serviceCidr": "10.0.0.0/16"
},
"nodeResourceGroup": "MC_mslearn-gh-pipelines-6498_contoso-video_eastus",
"podIdentityProfile": null,
"powerState": {
"code": "Running"
},
"privateFqdn": null,
"privateLinkResources": null,
"provisioningState": "Succeeded",
"resourceGroup": "mslearn-gh-pipelines-6498",
"securityProfile": null,
"servicePrincipalProfile": {
"clientId": "msi",
"secret": null
},
"sku": {
"name": "Basic",
"tier": "Free"
},
"tags": null,
"type": "Microsoft.ContainerService/ManagedClusters",
"windowsProfile": null
}
Obtaining credentials...
Merged "contoso-video" as current context in /root/.kube/config
Creating ACR...
{
"adminUserEnabled": false,
"anonymousPullEnabled": false,
"creationDate": "2022-01-17T03:12:55.182289+00:00",
"dataEndpointEnabled": false,
"dataEndpointHostNames": [],
"encryption": {
"keyVaultProperties": null,
"status": "disabled"
},
"id": "/subscriptions/14adb214-7b29-422a-ac8a-df2af1e51201/resourceGroups/mslearn-gh-pipelines-6498/providers/Microsoft.ContainerRegistry/registries/ContosoContainerRegistry5380",
"identity": null,
"location": "eastus",
"loginServer": "contosocontainerregistry5380.azurecr.io",
"name": "ContosoContainerRegistry5380",
"networkRuleBypassOptions": "AzureServices",
"networkRuleSet": null,
"policies": {
"exportPolicy": {
"status": "enabled"
},
"quarantinePolicy": {
"status": "disabled"
},
"retentionPolicy": {
"days": 7,
"lastUpdatedTime": "2022-01-17T03:12:56.840110+00:00",
"status": "disabled"
},
"trustPolicy": {
"status": "disabled",
"type": "Notary"
}
},
"privateEndpointConnections": [],
"provisioningState": "Succeeded",
"publicNetworkAccess": "Enabled",
"resourceGroup": "mslearn-gh-pipelines-6498",
"sku": {
"name": "Basic",
"tier": "Basic"
},
"status": null,
"systemData": {
"createdAt": "2022-01-17T03:12:55.182289+00:00",
"createdBy": "izhao.yiyi@hotmail.com",
"createdByType": "User",
"lastModifiedAt": "2022-01-17T03:12:55.182289+00:00",
"lastModifiedBy": "izhao.yiyi@hotmail.com",
"lastModifiedByType": "User"
},
"tags": {},
"type": "Microsoft.ContainerRegistry/registries",
"zoneRedundancy": "Disabled"
}
{
"adminUserEnabled": true,
"anonymousPullEnabled": false,
"creationDate": "2022-01-17T03:12:55.182289+00:00",
"dataEndpointEnabled": false,
"dataEndpointHostNames": [],
"encryption": {
"keyVaultProperties": null,
"status": "disabled"
},
"id": "/subscriptions/14adb214-7b29-422a-ac8a-df2af1e51201/resourceGroups/mslearn-gh-pipelines-6498/providers/Microsoft.ContainerRegistry/registries/ContosoContainerRegistry5380",
"identity": null,
"location": "eastus",
"loginServer": "contosocontainerregistry5380.azurecr.io",
"name": "ContosoContainerRegistry5380",
"networkRuleBypassOptions": "AzureServices",
"networkRuleSet": null,
"policies": {
"exportPolicy": {
"status": "enabled"
},
"quarantinePolicy": {
"status": "disabled"
},
"retentionPolicy": {
"days": 7,
"lastUpdatedTime": "2022-01-17T03:12:56.840110+00:00",
"status": "disabled"
},
"trustPolicy": {
"status": "disabled",
"type": "Notary"
}
},
"privateEndpointConnections": [],
"provisioningState": "Succeeded",
"publicNetworkAccess": "Enabled",
"resourceGroup": "mslearn-gh-pipelines-6498",
"sku": {
"name": "Basic",
"tier": "Basic"
},
"status": null,
"systemData": {
"createdAt": "2022-01-17T03:12:55.182289+00:00",
"createdBy": "izhao.yiyi@hotmail.com",
"createdByType": "User",
"lastModifiedAt": "2022-01-17T03:13:13.400167+00:00",
"lastModifiedBy": "izhao.yiyi@hotmail.com",
"lastModifiedByType": "User"
},
"tags": {},
"type": "Microsoft.ContainerRegistry/registries",
"zoneRedundancy": "Disabled"
}
AAD role propagation done[############################################] 100.0000%{
"aadProfile": null,
"addonProfiles": {
"httpApplicationRouting": {
"config": {
"HTTPApplicationRoutingZoneName": "9c4fe3790bba4b1eadd1.eastus.aksapp.io"
},
"enabled": true,
"identity": {
"clientId": "78b08f9a-00dd-4111-8d5f-56ba045ac2d8",
"objectId": "a5b7f775-f724-4c94-aead-28595e5e821b",
"resourceId": "/subscriptions/14adb214-7b29-422a-ac8a-df2af1e51201/resourcegroups/MC_mslearn-gh-pipelines-6498_contoso-video_eastus/providers/Microsoft.ManagedIdentity/userAssignedIdentities/httpapplicationrouting-contoso-video"
}
}
},
"agentPoolProfiles": [
{
"availabilityZones": null,
"count": 1,
"enableAutoScaling": false,
"enableEncryptionAtHost": false,
"enableFips": false,
"enableNodePublicIp": false,
"enableUltraSsd": false,
"gpuInstanceProfile": null,
"kubeletConfig": null,
"kubeletDiskType": "OS",
"linuxOsConfig": null,
"maxCount": null,
"maxPods": 110,
"minCount": null,
"mode": "System",
"name": "nodepool1",
"nodeImageVersion": "AKSUbuntu-1804gen2containerd-2022.01.07",
"nodeLabels": null,
"nodePublicIpPrefixId": null,
"nodeTaints": null,
"orchestratorVersion": "1.21.7",
"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": null,
"vmSize": "Standard_B2s",
"vnetSubnetId": null
}
],
"apiServerAccessProfile": null,
"autoScalerProfile": null,
"autoUpgradeProfile": null,
"azurePortalFqdn": "contoso-video-b9c207fb.portal.hcp.eastus.azmk8s.io",
"disableLocalAccounts": false,
"diskEncryptionSetId": null,
"dnsPrefix": "contoso-video",
"enablePodSecurityPolicy": null,
"enableRbac": true,
"extendedLocation": null,
"fqdn": "contoso-video-b9c207fb.hcp.eastus.azmk8s.io",
"fqdnSubdomain": null,
"httpProxyConfig": null,
"id": "/subscriptions/14adb214-7b29-422a-ac8a-df2af1e51201/resourcegroups/mslearn-gh-pipelines-6498/providers/Microsoft.ContainerService/managedClusters/contoso-video",
"identity": {
"principalId": "2d7d6a16-0029-4650-a940-e06444a45528",
"tenantId": "7446b7c5-bb59-4186-a8df-513c195bc49f",
"type": "SystemAssigned",
"userAssignedIdentities": null
},
"identityProfile": {
"kubeletidentity": {
"clientId": "bce75f9f-3c0a-47a4-b286-817aa71606c7",
"objectId": "9e9f8eac-2e13-4124-8471-3ae4aa22c0e6",
"resourceId": "/subscriptions/14adb214-7b29-422a-ac8a-df2af1e51201/resourcegroups/MC_mslearn-gh-pipelines-6498_contoso-video_eastus/providers/Microsoft.ManagedIdentity/userAssignedIdentities/contoso-video-agentpool"
}
},
"kubernetesVersion": "1.21.7",
"linuxProfile": {
"adminUsername": "azureuser",
"ssh": {
"publicKeys": [
{
"keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTn5WASHIgIKuIeEgGSdkaxZ8DntqG+zUkjMPiZMxtRH2/dZaL230SbRG+FZ3FrsvnQp40d7TSCGdADIufsS9hkNkR0egzIsPGqzhcjyeYOAOSBD8atImbAxb6aFntk1uS1hVpn2C2p5DE0//FsWdp+KDTVAcdHgkrYMPECTfQh/lmURlddaLf3ZNju6xUc/sOFDAPZmVXr17pkuAYRjAr7MGchh6Rpbkg665ZOdY4lAJWDZONJ1u1DsyGQO18qdLDU7ZreOSgHe0pgLbVtKnUTAhGicjQqRGvwfKUQdyV223PjBqo57o/iNpPej2NR2Euhbcst25BE8KjzZ6l9y8n"
}
]
}
},
"location": "eastus",
"maxAgentPools": 100,
"name": "contoso-video",
"networkProfile": {
"dnsServiceIp": "10.0.0.10",
"dockerBridgeCidr": "172.17.0.1/16",
"loadBalancerProfile": {
"allocatedOutboundPorts": null,
"effectiveOutboundIPs": [
{
"id": "/subscriptions/14adb214-7b29-422a-ac8a-df2af1e51201/resourceGroups/MC_mslearn-gh-pipelines-6498_contoso-video_eastus/providers/Microsoft.Network/publicIPAddresses/8b24dcb0-2bac-46c7-bcb6-27908632326c",
"resourceGroup": "MC_mslearn-gh-pipelines-6498_contoso-video_eastus"
}
],
"idleTimeoutInMinutes": null,
"managedOutboundIPs": {
"count": 1
},
"outboundIPs": null,
"outboundIpPrefixes": null
},
"loadBalancerSku": "Standard",
"natGatewayProfile": null,
"networkMode": null,
"networkPlugin": "kubenet",
"networkPolicy": null,
"outboundType": "loadBalancer",
"podCidr": "10.244.0.0/16",
"serviceCidr": "10.0.0.0/16"
},
"nodeResourceGroup": "MC_mslearn-gh-pipelines-6498_contoso-video_eastus",
"podIdentityProfile": null,
"powerState": {
"code": "Running"
},
"privateFqdn": null,
"privateLinkResources": null,
"provisioningState": "Succeeded",
"resourceGroup": "mslearn-gh-pipelines-6498",
"securityProfile": null,
"servicePrincipalProfile": {
"clientId": "msi",
"secret": null
},
"sku": {
"name": "Basic",
"tier": "Free"
},
"tags": null,
"type": "Microsoft.ContainerService/ManagedClusters",
"windowsProfile": null
}
sed: can't read s+!IMAGE!+ContosoContainerRegistry5380/contoso-website+g: No such file or directory
sed: can't read s+!DNS!+9c4fe3790bba4b1eadd1.eastus.aksapp.io+g: No such file or directory
Installation concluded, copy these values and store them, you'll use them later in this exercise:
-> Resource Group Name: mslearn-gh-pipelines-6498
-> ACR Name: ContosoContainerRegistry5380
-> ACR Login Username: ContosoContainerRegistry5380
-> ACR Password: Kuyj6H3dvx3h90nj5P851onpoM7aMMX+
-> AKS Cluster Name: ContosoContainerRegistry5380
-> AKS DNS Zone Name: 9c4fe3790bba4b1eadd1.eastus.aksapp.io
最后生成的ASK、ACR等的参数:
-> Resource Group Name: mslearn-gh-pipelines-6498
-> ACR Name: ContosoContainerRegistry5380
-> ACR Login Username: ContosoContainerRegistry5380
-> ACR Password: Kuyj6H3dvx3h90nj5P851onpoM7aMMX+
-> AKS Cluster Name: ContosoContainerRegistry5380
-> AKS DNS Zone Name: 9c4fe3790bba4b1eadd1.eastus.aksapp.io
从控制台也可以看到:
CI:生成管道(latest)
步骤为:
- 生成操作工作流
- 创建触发器
- 生成并推送映像
- 设置secret
- 推送映像
生成操作工作流
选择Actions下的set up a workflow yourself
管道是存储库中的 .github/workflows 目录中的一个文件。 GitHub 提供了生成大多数管道所需的预生成组件。
默认会生成一个main.yml模板来定义管道,如以下示例所示:
# This is a basic workflow to help you get started with Actions
name: CI
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ main ]
pull_request:
branches: [ main ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Runs a single command using the runners shell
- name: Run a one-line script
run: echo Hello, world!
# Runs a set of commands using the runners shell
- name: Run a multi-line script
run: |
echo Add other actions to build,
echo test, and deploy your project.
配置文件分为三部分:
- 名字
# This is a basic workflow to help you get started with Actions
name: CI
- 触发器,以’on’标准
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ main ]
pull_request:
branches: [ main ]
- 工作流的具体行动
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Runs a single command using the runners shell
- name: Run a one-line script
run: echo Hello, world!
# Runs a set of commands using the runners shell
- name: Run a multi-line script
run: |
echo Add other actions to build,
echo test, and deploy your project.
创建触发器
修改yml名称并更改默认触发器
- “main.yml”重命名为“build-staging.yml”
- 该名称:Build and push the latest build to staging
- 修改触发器
name: Build and push the latest build to staging
on:
push:
branches: [ main ]
生成并推送映像
- 将 build 项重命名为 build_push_image。
- 将该版本修复为 ubuntu-20.04
- 在steps首先确保已具有一个使用 checkout 操作的步骤。 此操作会将存储库克隆到作业环境中(默认已存在)
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- 为了登录镜像存储卡,在右侧Marketplace输入Docker login,选择Docker Login并复制配置:
- name: Docker Login
# You may pin to the exact commit or the version.
# uses: docker/login-action@42d299face0c5c43a0487c477f595ac9cf22f1a7
uses: docker/login-action@v1.12.0
with:
# Server address of Docker registry. If not set then will default to Docker Hub
registry: # optional
# Username used to log against the Docker registry
username: # optional
# Password or personal access token used to log against the Docker registry
password: # optional
# Specifies whether the given registry is ECR (auto, true or false)
ecr: # optional, default is auto
# Log out from the Docker registry at the end of a job
logout: # optional, default is true
注意缩进:name 项应与上一个 uses 项对齐。
使用的参数用到了前面环境准备时的参数项:
项名称 | 用于操作 | 值 |
---|---|---|
username | docker/login | ${{ secrets.ACR_LOGIN }} |
password | docker/login | ${{ secrets.ACR_PASSWORD }} |
注册表 | docker/login | ${{ secrets.ACR_NAME }} |
repository | docker/build-and-push | contoso-website |
标记 | docker/build-and-push | latst |
上下文 | docker/build-and-push | . |
push | docker/build-and-push | true |
有关详细信息,请参阅 GitHub 生成-推送-操作文档 | ||
2. 生成并推送镜像 | ||
在上面提到的操作文档中可以查到Build and push的示例: |
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: user/app:latest
dockerfile文件放在操作的‘.’目录下:
FROM nginx:1.18
RUN curl -sL <https://deb.nodesource.com/setup_14.x> | bash - && apt-get update -y && apt-get install -y git curl nodejs && curl -sL <https://github.com/gohugoio/hugo/releases/download/v0.72.0/hugo_extended_0.72.0_Linux-64bit.tar.gz> | tar -xz hugo && mv hugo /usr/bin && npm i -g postcss-cli autoprefixer postcss
RUN git clone <https://github.com/MicrosoftDocs/mslearn-aks-deployment-pipeline-github-actions> /contoso-website
WORKDIR /contoso-website/src
RUN git submodule update --init themes/introduction
RUN hugo && mv public/* /usr/share/nginx/html
EXPOSE 80
- 还将在签出操作和登录操作之间添加另一个操作,以设置生成引擎供 Docker 使用。 此操作称为 docker/setup-buildx-action,使用 v1。
- name: Set up Buildx
uses: docker/setup-buildx-action@v1
最后的yml文件:
name: Build and push the latest build to staging
on:
push:
branches: [ main ]
jobs:
build_push_image:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Set up Buildx
uses: docker/setup-buildx-action@v1
- name: Docker Login
uses: docker/login-action@v1.12.0
with:
registry: ${{ secrets.ACR_NAME }}
username: ${{ secrets.ACR_LOGIN }}
password: ${{ secrets.ACR_PASSWORD }}
- name: Build and push staging images
uses: docker/build-push-action@v2
with:
context: .
tags: ${{secrets.ACR_NAME}}/contoso-website:latest
push: true
Commit new file:
可以看到在.github/workflow中已经生产了文件
而在Actions里面发现工作流失败:
这是因为在工作流中定义的参数还没有,这需要采用secret的方式导入。
设置secret
setting–>Secret–>New repository secret
名称:
registry: ${{ secrets.ACR_NAME }}
username: ${{ secrets.ACR_LOGIN }}
password: ${{ secrets.ACR_PASSWORD }}
值:
-> ACR Name: `ContosoContainerRegistry5380`#注意完整的ACR:contosocontainerregistry5380.azurecr.io
-> ACR Login Username: `ContosoContainerRegistry5380`
-> ACR Password: `Kuyj6H3dvx3h90nj5P851onpoM7aMMX+`
生产结果:
推送镜像
到Actions中再次提交
成功! 从Azure控制台也可以看到:
CI:生成管道(v*)
再生成使用带标签的工作流,建立新的yml文件:build-production.yml,并将name改成 name: Build and push the tagged build to production
触发器
name: Build and push the tagged build to production
on:
push:
tags:
- 'v*'
生成并推送映像
- 创建将收集必要版本信息的新步骤。 为此,将使用 ::set-output 内部命令。 在签出操作下面添加以下行:
- name: Fetch latest version
id: fetch_version
run: echo ::set-output name=TAG::${GITHUB_REF#refs/tags/}
- 修改push的label
- name: Build and push production images
uses: docker/build-push-action@v2
with:
context: .
tags: ${{secrets.ACR_NAME}}/contoso-website:latest,${{secrets.ACR_NAME}}/contoso-website:${{ steps.fetch_version.outputs.TAG }}
push: true
整体的yml:
name: Build and push the latest build to production
on:
push:
tags:
- 'v*'
jobs:
build_push_image:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Fetch latest version
id: fetch_version
run: echo ::set-output name=TAG::${GITHUB_REF#refs/tags/}
- name: Docker Login
uses: docker/login-action@v1.12.0
with:
registry: ${{ secrets.ACR_NAME }}
username: ${{ secrets.ACR_LOGIN }}
password: ${{ secrets.ACR_PASSWORD }}
- name: Build and push production images
uses: docker/build-push-action@v2
with:
context: .
tags: ${{secrets.ACR_NAME}}/contoso-website:latest,${{secrets.ACR_NAME}}/contoso-website:${{ steps.fetch_version.outputs.TAG }}
push: true
执行成功以后,由于没有push新的v*的label,并不会生成新的images:
- 在azure shell中提交tag(pull的文件夹更新到最新):
izhao_yiyi@Azure:~/mslearn-aks-deployment-pipeline-github-actions$ git tag -a v0.0.1 -m'First tag'
izhao_yiyi@Azure:~/mslearn-aks-deployment-pipeline-github-actions$ git push --tags
Username for '<https://github.com>': etaon
Password for '<https://etaon@github.com>':
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 170 bytes | 170.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To <https://github.com/etaon/mslearn-aks-deployment-pipeline-github-actions>
* [new tag] v0.0.1 -> v0.0.1
完成以后:
ACR中可以看到两个版本