2020年7月15日 星期三

AWS CloudWatch Synthetics

原本想用 DataDog 的 Sythetics API Test 做 e2e monitoring & alarm 但是遇到 multi-part form-data 沒辦法在 Request Body 使用 \r\n 的問題

curl -i -X  --trace-ascii - -F 'key=key1' -F 'key2=key2' https://whatever.totest.com/auth

你可以看到送出的 Content-Length 和 Request Body 是

Content-Length: YYY
Content-Type: multipart/form-data; boundary=xxxx
--xxxx
Content-Disposition: form-data; name="key1"
key1
--xxxx
Content-Disposition: form-data; name="key2"
key2
--xxxx--

但是使用 DataDog 送出去的話只會用 \n 和 curl 送出的一比較,就發現 Content-Length 比較小,但是 DataDog 似乎沒辦法改..

試了一下 AWS CloudWatch Synthetics Canary 發現他其實就是 deploy 一個 nodejs lambda layer 裡面執行 Puppeteer, Chromium 和 AWS SDK 但是又整合了 cloudwatch dashoboard, cloudwatch logs 和 cloudwatch alarm,所以不只可以跑 script 還可以透過 chromium 去抓網頁的 screenshot 彈性超大!

另外一個好處是可以編輯要送出去的 postData,一開始我看他預設也是送 \n 會造成 invalid request 但是只要改成 \r\n 就好囉!



2020年7月12日 星期日

Publish lambda layer to regions from s3 bucket?

boto3 有個 publish_layer_version API,你可以使用 S3 bucket + key or zipfile 來發布 lambda layer.

使用 zipfile 的話就是從命令執行端上傳,所以假設你的 lambda packet 是 20MB 然後你要發佈到 16 個 AWS region 的話,就看你命令執行端的網路上傳速度了。

使用 S3 bucket 來放要發佈的 zipfile 檔似乎比較合理,因為這樣子檔案的複製就是在 AWS 的網路內發生。

But... 很機車的是,如果你的 zipfile 是放在 us-west-1 的 S3 bucket 那麼你就只能發佈到 us-west-1 .... 當你要發佈到其他 region 會出現 error
botocore.errorfactory.InvalidParameterValueException: 
An error occurred (InvalidParameterValueException) when calling 
the PublishLayerVersion operation: Error occurred while GetObject. 
S3 Error Code: PermanentRedirect. 
S3 Error Message: The bucket is in this region: us-east-1. 
Please use this region to retry the request

S3 bucket name 是 global unique 但其實 bucket 位置是有 region 的...
目前還沒有看到什麼比較好的方式來發佈 lambda layer 到全部的 region.... replicate 所有的 zipfile 到所有的 region, 然後每個都有自己的 bucket name 似乎蠻蠢的?....

Application Load Balancer lambda endpoint healthy check will be charged

AWS 還是有蠻多坑的...

如果 ALB 的 TargetGroup 使用 lambda endpoint
那麼為了避免 code start issue 可能會使用 provisioned concurrency

另外 lambda endpoint 在 update stack 的時候會出現 Load Balancer not able to stabilizied 的問題。AWS support 目前給的work around就是開啟 ALB healthy check
預設是每 35 秒會做一次 healthy check 然後如果 ALB 跨3個 AZ 的話,healthy check count 就 x3 ....
然後每次的 lambda execution 都是照 lambda function usage 來收費

另外ALB的 healthy check 不會有完整的 request header
如果你的 framework 不預期有這種不正常的 header 沒有去 handle 的話 可能會一直狂噴500...
如果你還沒有把預設的 lambda error retry 關掉的話......
這樣子用 lambda endpoint 真的比較省嗎?....


2020年7月10日 星期五

Access private API gateway from another account

最近在做一個 PoC 驗證說怎麼在現有的架構下,把一些 public API 移到 VPC 裡面,只讓特定網路的人可以存取。

當然最直覺的想法就是,建一個新的 VPC ,加上 execute-api VPC endpoint 然後這個 VPC 再跟特定網路做 Peering,建一個 Private API Gateway 在新的 VPC 裡面。

這樣新的 VPC 可以透過 VPC endpoint 去存取 API Gateway,然後再加一個 ALB ,裡面的 target group 指向 VPC endpoint 的 IP和 443 port,ALB 設定好 Domain Listener,API Gateway 也加上相同的 Custom Domain Name,這樣子 ALB 就可以當成特定網路 access 的 entry point,一但 Peering 完成後,從特定網路來的 request 就可以經由 ALB -> API GW 跨 VPC 存取原本環境的 backend resource。

但我一直在想,Peering 是必要的嗎? 沒想到隔天就看到這個教學 How can I access an API Gateway private REST API in another account using an interface VPC endpoint? 裡面的做法突破了原本我直覺上的盲點! 就是即使是 Internal API Gateway 似乎只要設定好了 resource policy 就可以允許其他 account 的 VPC endpoint 跨帳號存取!

所以例子裡面的 private API Gateway 是建立在 B 帳號裡面,A 帳號的 VPC 只是啟用了 VPC endpoint,一但 B 帳號的 private API Gateway 在 resource policy 設定好允許 A 帳號的 VPC endpoint 存取,即使兩個帳號之間沒有 peering 也是可以互通的!

雖然說這樣子要帶 hostname header or api-gw-id 但是 原本架構上的 ALB 也是為了 VPC endpoint 可以知道要 forward request 給哪個 API Gateway 才加上的... 

但至少是一個不想要建 VPC Peering 的選項之一.... :p

Reference:


2020年7月2日 星期四

CloudFomration and serverless lambda deployment

幸運的有 AWS::Serverless::Function 可以使用,不然想到要用 Custom Resource 頭就痛。原生的 AWS::Lambda::Function 如果要使用 Provisioned Concurrency 就必須使用 Version/Alias,但是 Version 的 property 全部都是不能更新的!所以接下來 lambda function 的更新,都不會讓 Alias 指向新的 Version....
還好透過 Transform 的宣告後,啟用AutoPublishAlias: live 再加上小部分 property 的修改,CloudFormation 就可以自動地幫我們管理 Version 和 Alias 啦。

不過還踩到另外一個小雷是,預設 Application Load Balancer 的 Target Group 如果是指向 lambda 的話,healthy check 是關閉的。但是在這種情況下,你 update stack 就會遇到 "ElasticLoadBalancerV2 TargetGroup did not stabilize" ,很厲害的 AWS Support 就給了一個 workaround ,把 healthy check 打開就好了 .... lol

Ref: