在 YAML 部署作业中部署后检查应用程序运行状况端点的最佳方法?

Vic*_*rra 1 azure-devops azure-pipelines

在你喊“门!”之前 请阅读。

我有本地 IIS 服务器群,我为每个(开发、测试、生产)创建了一个 VM 环境。在我所有的应用程序中,我都有一个 CD YAML,如下所示:

- stage: Deploy_Test
  jobs:
  - deployment: APIDeployTestIISFarm
    displayName: Deploy API to Test IIS
    environment:
      name: Test
      resourceType: VirtualMachine
    strategy:
      runOnce:
        deploy:
          steps:
Run Code Online (Sandbox Code Playgroud)

因为我有 20 个不同的应用程序,它们都针对相同的环境,所以我无法使用 Gates 功能。并非所有应用程序都具有完全相同的/health端点。

我目前正在制作一个 powershell 命令来简单地调用 /health 并且如果“不健康”可能会抛出结果。尽管与只会检查 200 的 HTTP 门相比,这对我来说听起来非常难看,但我敢打赌它也具有容错/弹性。毕竟,IIS 站点在部署后第一次点击时需要一秒钟的时间来启动。

对我尚未见过的其他想法或任务持开放态度。

Vic*_*rra 6

我的解决方案是创建一个容错 PowerShell 脚本来 ping 运行状况端点。我更进一步,将其包装在一个模板中,该模板可以插入到您的主 CI/CD 模板中。这样做可以让我使用我选择的 IDE (VSCode) 单独开发和测试 PS 脚本,并且由于模板,还可以将其作为标准任务重新使用,或者在 Azure Pipelines 之外使用它。

脚本

脚本注意事项:脚本最终通过Write-Error结合我们稍后将看到的failOnStderr: trueforPowerShell@2任务来决定任务是否失败。

## Base code borrowed from https://karask.com/retry-powershell-invoke-webrequest/
## Slightly modified to remove things like the file logging.

param (
    [string]$URI,
    [string]$Method = 'GET',
    [string]$SuccessTextContent = 'Healthy',
    [string]$Retries = 1,
    [string]$SecondsDelay = 2,
    [string]$TimeoutSec = 120
)

Write-Output "$Method ""$URI"" Retries: $Retries, SecondsDelay $SecondsDelay, TimeoutSec $TimeoutSec";

Function Req {
    Param(
        [Parameter(Mandatory=$True)]
        [hashtable]$Params,
        [int]$Retries = 1,
        [int]$SecondsDelay = 2
    )

    $Params.Add('UserAgent', 'azagent powershell task')

    $method = $Params['Method']
    $url = $Params['Uri']

    $cmd = { Write-Host "$method $url..." -NoNewline; Invoke-WebRequest @Params }

    $retryCount = 0
    $completed = $false
    $response = $null

    while (-not $completed) {
        try {
            $response = Invoke-Command $cmd -ArgumentList $Params
            if ($response.StatusCode -ne 200) {
                throw "Expecting reponse code 200, was: $($response.StatusCode)"
            }
            $completed = $true
        } catch {
            Write-Output "$(Get-Date -Format G): Request to $url failed. $_"
            if ($retrycount -ge $Retries) {
                Write-Error "Request to $url failed the maximum number of $retryCount times."
                throw
            } else {
                Write-Warning "Request to $url failed. Retrying in $SecondsDelay seconds."
                Start-Sleep $SecondsDelay
                $retrycount++
            }
        }
    }

    Write-Host "OK ($($response.StatusCode))"
    return $response
}

$res = Req -Retries $Retries -SecondsDelay $SecondsDelay -Params @{ 'Method'=$Method;'Uri'=$URI;'TimeoutSec'=$TimeoutSec;'UseBasicParsing'=$true }

if($res.Content -ne "$SuccessTextContent")
{
    Write-Error $response.Content
}
else
{
    Write-Host "Helath check validation success."
}
Run Code Online (Sandbox Code Playgroud)

模板

关于模板的说明:关于这个任务有一个很容易被忽略的微妙细节。- checkout: templates. 这实际上将检查在插入此模板的模板中定义的存储库资源。这似乎很明显,因为模板被插入,然后一旦完成它就好像它是一个 yaml 一样执行。

parameters:
  - name: URI
    type: string
  - name: Method
    type: string
    default: 'GET'
  - name: SuccessTextContent
    type: string
    default: 'Healthy'
  - name: Retries
    type: number
    default: 5
  - name: SecondsDelay
    type: number
    default: 2
  - name: TimeoutSec
    type: number
    default: 120

steps:
  - checkout: templates
  - task: PowerShell@2
    displayName: '${{ parameters.Method }} ${{ parameters.URI }}...'    
    inputs:
      failOnStderr: true
      targetType: 'filePath'
      filePath: $(System.DefaultWorkingDirectory)\InvokeRequestWithRetry.ps1
      arguments: > # Use this to avoid newline characters in multi-line string
        -URI "${{ parameters.URI }}"
        -Method "${{ parameters.Method }}"
        -SuccessTextContent "${{ parameters.SuccessTextContent }}"
        -Retries ${{ parameters.Retries }}
        -SecondsDelay ${{ parameters.SecondsDelay }}
        -TimeoutSec ${{ parameters.TimeoutSec }}
Run Code Online (Sandbox Code Playgroud)

父 CI/CD YAML

关于父 YAML 的注意事项:最后,我们有用法。我选择将此作为自己的专用部署作业,以便在一切都失败时我可以手动单击重试,而不必重新运行整个部署。此外,我希望 PS 在我的防火墙后面针对我的 VM 环境运行。

resources:
  repositories:
    - repository: templates
      type: git
      name: IAMM/azure-pipelines-templates
      ref: refs/tags/v0.4

## ...
## Removed for brevity
## ...

- deployment: MyAppHealthDevIIS
  dependsOn: MyAppDeployDevIIS
  displayName: 'Hit /health/views endpoint before proceeding'
  environment:
    name: Development
    resourceType: VirtualMachine
  strategy:
    runOnce:
      deploy:
        steps:
        - template: templates/health-check.yaml@templates
          parameters:
            URI: 'https://$(iisHostName)/$(iisTargetApplication)/health/views'
            SecondsDelay: 5
Run Code Online (Sandbox Code Playgroud)