一、为什么要做Azure Functions的自动化CI/CD流水线

很多做后端开发的朋友应该都有过这样的经历:写好一段函数代码,先在本地测试,然后打包传到Azure上,改配置、重启服务,整个过程手忙脚乱不说,还容易出错——比如忘改生产环境的数据库连接串,或者更新的时候服务断了,用户访问直接报错。尤其是函数这种按次付费、随用随启的服务,本来是为了简化开发,结果部署环节反而成了麻烦。

Azure Functions本身是微软云的无服务器服务,不用管服务器、不用扩容,只要写代码就行,但如果部署环节还停留在手动阶段,就完全浪费了无服务器的优势。自动化CI/CD流水线就是解决这个问题的:只要你把代码提交到仓库,剩下的测试、打包、部署全由机器完成,而且能做到更新的时候用户没感知,也就是零停机。

1.1 核心概念先理清楚(怕你懵)

这里先给大家说两个容易混的概念,后面全程会用到:

  • CI(持续集成):就是你每次改代码提交后,自动跑测试、打包,保证新代码是能用的。比如你改了函数里的参数校验,提交后机器自动测一遍有没有bug,没问题再往下走。
  • CD(持续部署):就是把打包好的代码自动部署到目标环境(比如测试、生产),而且能控制部署的节奏,比如先部署到测试环境验证,没问题再推到生产。

零停机部署是CD的进阶功能,意思是更新服务的时候,旧版本的服务先不删,等新版本的服务完全跑起来、能正常处理请求了,再把旧版本关掉,这样用户的请求不会断。

二、准备工作:提前搭好的基础环境

做流水线之前,得先把几个基础东西准备好,就像盖房子先打地基。这里统一用的技术栈是:Git(代码仓库)、Azure DevOps(做流水线的工具)、Azure Functions(目标服务)。

2.1 具体要准备的东西

  1. 一个GitHub或者Azure DevOps的代码仓库,用来存你的函数代码。
  2. 一个Azure账号,能创建Azure Functions应用(后面叫Function App)。
  3. 一个Azure DevOps的项目,用来配置流水线。

先给大家看一个最简单的Azure Functions代码示例,后面流水线会用到。这个函数是用C#写的,功能很简单:接收一个GET请求,返回“Hello, 你的名字”。

技术栈:Git、Azure DevOps、Azure Functions(C#)

// 函数的入口类,Azure Functions会自动识别这个类的函数
public class HelloFunction
{
    // FunctionName属性指定函数名,Trigger是HTTP触发器,说明这个函数是被HTTP请求触发的
    [FunctionName("HelloFunction")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "hello/{name}")] HttpRequest req, // 路由是/hello/xxx,xxx是名字参数
        string name, // 从路由里拿的name参数
        ILogger log)
    {
        log.LogInformation($"收到请求,名字是:{name}"); // 打日志,方便排查问题

        // 简单的参数校验,如果名字为空,返回400错误
        if (string.IsNullOrEmpty(name))
        {
            return new BadRequestObjectResult("请在路由里传名字,比如/hello/张三");
        }

        // 返回200状态码和问候语
        return new OkObjectResult($"Hello, {name}!");
    }
}

这个代码很简单,把它提交到你的代码仓库里,仓库结构大概是这样的:

你的仓库名/
├── HelloFunction.cs  # 刚才的函数代码
├── host.json         # Azure Functions的配置文件,比如日志、超时时间
├── local.settings.json # 本地开发用的配置,比如连接串(生产环境会用Azure的配置)
└── 项目文件.csproj   # C#项目的依赖文件

三、搭建CI/CD流水线:一步步来

接下来是核心环节,用Azure DevOps搭流水线。Azure DevOps的流水线叫“管道”,你可以理解为一个自动化的流程链,每个环节是一个步骤。

3.1 第一步:创建Azure DevOps的服务连接

流水线要操作你的Azure账号,得先给它权限。这个步骤只要做一次,以后所有流水线都能用。

  1. 登录Azure DevOps,进入你的项目,点左边的“项目设置”。
  2. 找到“服务连接”,点“新建服务连接”。
  3. 类型选“Azure Resource Manager”,下一步。
  4. 认证方式选“服务主体(自动)”,然后选你的Azure账号、订阅,给连接起个名字,比如“Azure生产环境连接”,保存。

3.2 第二步:编写流水线的YAML配置

Azure DevOps的流水线可以用YAML文件来定义,你可以把这个YAML文件也提交到代码仓库里,和代码一起管理。下面给大家一个完整的YAML示例,每一行都有注释,你可以直接改一改用。

技术栈:Git、Azure DevOps、Azure Functions(C#)

# 流水线的名称,随便起
name: Azure Functions 生产流水线

# 触发条件:只要你往main分支提交代码,就自动跑这个流水线
trigger:
  branches:
    include:
      - main

# 运行流水线的机器类型,这里选微软提供的Windows机器,因为我们的函数是C#写的,用Windows环境编译
pool:
  vmImage: 'windows-latest'

# 变量:这里定义几个常用的变量,后面步骤里直接用,不用重复写
variables:
  functionAppName: '你的函数应用名' # 替换成你在Azure上创建的Function App的名字
  azureSubscription: 'Azure生产环境连接' # 替换成你刚才创建的服务连接的名字
  buildConfiguration: 'Release' # 编译模式,Release是正式版,Debug是测试版

# 步骤:流水线的具体流程,按顺序执行
steps:
  # 第一步:安装.NET SDK,因为要编译C#代码
  - task: UseDotNet@2
    inputs:
      packageType: 'sdk'
      version: '6.x' # 替换成你函数用的.NET版本,比如.NET 7、.NET 8
      installationPath: $(Agent.ToolsDirectory)/dotnet

  # 第二步:编译函数代码,生成打包文件
  - task: DotNetCoreCLI@2
    inputs:
      command: 'publish' # publish命令是把代码编译成可部署的包
      publishWebProjects: false # 我们不是Web项目,所以设为false
      projects: '*.csproj' # 要编译的项目文件,这里是所有的csproj
      arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)' # 编译参数,输出到指定目录
      zipAfterPublish: true # 编译完自动打包成zip,方便部署

  # 第三步:把打包好的zip部署到Azure Functions,并且开启零停机更新
  - task: AzureFunctionApp@1
    inputs:
      azureSubscription: $(azureSubscription) # 用刚才的服务连接
      appType: 'functionApp' # 部署的类型是Function App
      appName: $(functionAppName) # 你的函数应用名
      package: '$(Build.ArtifactStagingDirectory)/*.zip' # 要部署的包的路径
      deploymentMethod: 'auto' # 部署方式设为auto,Azure会自动选最优的部署方式,这里就是零停机的方式
      # 补充:如果你要手动指定零停机,也可以设为'run-from-package',效果一样

把这个YAML文件保存为azure-pipelines.yml,提交到你的代码仓库的main分支里。

3.3 第三步:测试流水线

提交完YAML之后,Azure DevOps会自动识别到这个文件,并且跑一次流水线。你可以去Azure DevOps的“管道”里看运行状态:

  1. 点左边的“管道”,找到你刚创建的流水线,点进去。
  2. 你会看到流水线的运行记录,每个步骤的状态都能看到:安装.NET SDK、编译、部署。
  3. 如果部署成功,你可以去Azure上看你的Function App,点“函数”,找到你的HelloFunction,点“获取函数URL”,复制URL去浏览器访问,就能看到返回的结果了。

比如你的URL是https://你的函数名.azurewebsites.net/api/hello/张三,访问后会返回Hello, 张三!,说明流水线跑通了。

四、零停机部署的原理和验证

很多人可能会问,这个流水线怎么做到零停机的?其实原理很简单,Azure Functions的部署有两种方式:

  • 直接替换:把旧的代码删掉,再放新的代码,这个过程中服务会停。
  • 包部署(Run From Package):把新的代码打包成zip,上传到Azure,Azure会先把新的包解压、启动、验证没问题,再把旧的服务关掉,把流量切到新的服务上。这个过程中旧服务一直能处理请求,所以用户没感知。

刚才的YAML里的deploymentMethod: 'auto'就是自动选包部署,实现零停机。

4.1 怎么验证是不是真的零停机?

你可以做个简单的测试:

  1. 先在本地写一个循环访问函数的脚本,一直发请求,看会不会断。 技术栈:PowerShell
# 循环访问函数,每0.5秒一次,连续访问100次
for ($i = 1; $i -le 100; $i++) {
    $url = "https://你的函数名.azurewebsites.net/api/hello/测试"
    $response = Invoke-WebRequest -Uri $url -UseBasicParsing
    Write-Host "第$i次请求,状态码:$($response.StatusCode),结果:$($response.Content)"
    Start-Sleep -Milliseconds 500
}
  1. 运行这个脚本,同时去Azure DevOps里重新跑一次流水线(或者改一点代码提交)。
  2. 看脚本的输出,所有请求的状态码都是200,没有出现错误,说明部署过程中服务没断,就是零停机。

五、实际应用场景和优缺点分析

5.1 适合的应用场景

这个流水线适合很多场景,举几个例子:

  • 企业内部的工具函数:比如给员工发通知、统计数据的函数,更新的时候不能断,不然员工用不了。
  • 面向用户的API函数:比如电商的订单查询、用户信息获取的函数,更新的时候断了会影响用户体验,甚至造成损失。
  • 高频更新的函数:比如做活动的时候,经常要改函数的逻辑,手动部署太麻烦,自动化流水线能节省很多时间。

5.2 技术的优点

  • 节省时间:原来手动部署要十几分钟,现在只要几分钟,而且不用人盯着。
  • 减少错误:手动改配置容易错,流水线是固定的步骤,不会错。
  • 零停机:更新的时候用户没感知,提升体验。
  • 可追溯:每一次部署都有记录,能知道谁、什么时候、改了什么代码,出问题了能快速回滚。

5.3 技术的缺点

  • 学习成本:刚开始搭流水线的时候,要学Azure DevOps的配置、YAML的写法,对新手来说有点难。
  • 依赖工具:如果Azure DevOps或者Azure的服务出问题,流水线就跑不了。
  • 配置复杂:如果你的函数有很多依赖,比如数据库、消息队列,要在流水线里加很多步骤,配置会变复杂。

六、注意事项和常见问题

6.1 注意事项

  • 分支管理:一定要把流水线的触发条件设为main分支,不要让所有分支都触发部署,不然测试分支的代码也会部署到生产环境。
  • 配置管理:生产环境的配置(比如数据库连接串、密钥)不要写在代码里,要存在Azure的应用配置里,流水线部署的时候会自动用生产环境的配置。
  • 测试:流水线里一定要加测试步骤,不然有bug的代码也会部署到生产环境。比如刚才的流水线,你可以在编译之后加一个测试步骤,跑你的单元测试。
  • 权限控制:Azure DevOps的服务连接权限不要开太大,只要能操作你的Function App就行,避免安全问题。

6.2 常见问题

  • 部署失败:最常见的原因是YAML里的变量写错了,比如函数应用名、服务连接名不对,或者.NET版本不对。
  • 零停机没生效:可能是你部署的时候选了直接替换的方式,检查YAML里的deploymentMethod是不是设为auto或者run-from-package。
  • 配置不生效:生产环境的配置没改,检查Azure的Function App的配置是不是对的,有没有把代码里的配置覆盖掉。

七、文章总结

搭建Azure Functions的自动化CI/CD流水线,本质上是把原来手动做的部署工作,变成机器自动做的标准化流程,既节省时间又减少错误,还能实现零停机更新,提升用户体验。整个过程虽然刚开始配置有点麻烦,但只要搭好一次,以后用起来就很方便。

对新手来说,不要怕难,一步步来,先把基础环境准备好,再改改现成的YAML示例,跑通之后再慢慢优化,比如加测试步骤、加回滚功能。这个流水线不仅适合Azure Functions,很多其他的服务也能用类似的思路来搭,学会了以后做其他项目也能用。