happyr / bref-hook-handler
处理 Bref Lambda 钩子的简单方法
Requires
- php: >=7.3
- ext-json: *
- async-aws/code-deploy: ^1.0
- async-aws/lambda: ^1.0
- bref/bref: ^0.5.20 || ^1.0
Requires (Dev)
- symfony/framework-bundle: ^4.4 || ^5.0
- symfony/phpunit-bridge: ^4.4 || ^5.0
README
这个小型库可以帮助你确保在将流量引入之前,你的 lambda 应用程序的新版本确实可以工作。它使运行“预流量钩子”变得简单。
安装
composer require happyr/bref-hook-handler
我们还需要来自 davidgf 的 serverless-plugin-canary-deployments
npm i --save-dev serverless-plugin-canary-deployments
配置
想法是创建一个新的 lambda 函数,可以验证一切是否正常工作。当我们确信一切正常时,我们将向 CodeDeploy 发出信号,允许真实流量。
示例 serverless.yml
service: canary-example frameworkVersion: ">=1.69.0 <2.0.0" # Bref and canary plugins plugins: - ./vendor/bref/bref - serverless-plugin-canary-deployments provider: name: aws region: eu-north-1 runtime: provided memorySize: 1792 environment: # Optional add the name of our main lambda function as env var HOOK_VERIFY_FUNCTION_NAME: ${self:service}-${opt:stage, "dev"}-website # Add IAM roles to use CodeDeploy and to be able to invoke our lambda function. iamRoleStatements: - Effect: Allow Action: - codedeploy:* Resource: - "*" - Effect: Allow Action: - lambda:InvokeFunction Resource: - arn:aws:lambda:${self:provider.region}:99999999:function:${self:service}-${opt:stage, "dev"}-website functions: website: handler: public/index.php description: '' timeout: 8 layers: - ${bref:layer.php-74-fpm} events: - http: 'ANY /' - http: 'ANY /{proxy+}' # Add deployment settings. This says: Deploy all at once if "preHook" says it is okey deploymentSettings: type: AllAtOnce alias: Live preTrafficHook: preHook # Define a PHP script to run to verify deployment. preHook: handler: prehook.php description: 'To verify deployment before allowing traffic' timeout: 10 layers: - ${bref:layer.php-74}
示例 prehook.php
预钩子脚本是你启动应用程序内核、测试写入数据库、在队列上分发消息等的地方。如果你使用 HookHandler
,它将自动与 CodeDeploy 进行通信。
当然,可以添加所需的多或少逻辑。
<?php require dirname(__DIR__).'/vendor/autoload.php'; use Happyr\BrefHookHandler\ApiGatewayFaker; use Happyr\BrefHookHandler\HookHandler; return new class extends HookHandler { protected function validateDeployment(): bool { $apiGateway = new ApiGatewayFaker(\getenv('HOOK_VERIFY_FUNCTION_NAME')); $response = $apiGateway->request('GET', '/'); $response->assertStatusCode(200); $response->assertBodyContains('Welcome to our site'); $kernel = new \App\Kernel('prod', false); $kernel->boot(); $kernel->getContainer()->get(CacheAccessChecker::class)->verify(); // If no exceptions were thrown and we return true, then we will // signal CodeDeploy to allow traffic return true; } };
发送 HTTP 请求
在上面的例子中,我们向我们的主页发送 HTTP 请求。我们不能使用 API Gateway,因为它不会将流量路由到新的 Lambda 版本。因此,我们直接使用看起来像来自 ApiGateway 的参数调用 lambda 版本。 ApiGatewayFaker
帮助我们做到这一点。
这就是为什么我们需要在 IAM 角色中配置 lambda:InvokeFunction
的唯一原因。
注意
如果 prehook.php 没有向 CodeDeploy 发出请求,则部署将卡在“检查堆栈更新进度”状态。这是一个好事。这确保了预钩子脚本总是报告“成功”。
如果发生这种情况,请检查 CloudWatch 日志。
太好了,让我们进行金丝雀部署!
可能会很诱人将 deploymentSettings.type
改为“全部同时”以外的其他值,以便首先将新版本暴露给 10% 的请求... 但这可能不是最佳选择。在更改之前,请先阅读这篇文章: https://lumigo.io/blog/canary-deployment-for-aws-lambda/