前言
最近做的一個項目是要把公司在國外已經上線的一個物聯網的項目移植到AWS中國區來。
由於AWS屬於國外雲產商,在中國運營,必須符合國家的相關規定:
- 必須是合資公司 (AWS北京區由北京光環新網運營,寧夏區由西雲數據運營)
- 拿到ICP認證
- 服務器和數據必須在物理上中國境內
- 其他
AWS在Global區已有的服務,也是一點點在中國上線的,例如2020年上線了很多重要的服務,Route53、Certificate Manager等等, 可以在這里查看最新上線的服務
我曾經問過AWS中國的support人員,其他未上線的服務是否有時間表?support人員,一般標准回答都是:"沒有准確的時間表。"
AWS的中國區和AWS在Global的其他區之間是"不相通的";賬號是獨立分開的,中國區的賬號下,目前只有北京和寧夏兩個region
坑
從這段時間的工作經驗,總結出要把國外的AWS雲項目移植到中國需要注意的一些"坑", 其中很多問題,在中文社區很難找到相關文章,所以決定分享出來,避免大家再走彎路!
坑一:arn問題
問題描述
AWS的各個資源,都有一個arn,作為全局唯一的標識, 例如:arn:partition:service:region:account-id:resource-id
我們一般會在代碼中會直接這樣寫:arn:aws:apigateway:region:lambda, 這樣寫,在AWS Global基本上沒有問題,但是在中國區,AWS采取了不同的arn
上面的那個例子在中國區就變成了: arn:aws-cn:aipgateway:region:lambda
大部分公司都希望一套代碼在全球使用,不希望單獨為中國區准備一個版本。那怎么樣做到兼容呢?
解決方案
在cloudFormation內建腳本中有一個參數Partition, 有了這個參數,上面的arn的寫法就變成了: arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda
為了做到批量修改,我們可以使用一些輔助工具replace,它還支持正則表達式
以下是一段參考腳本,適用於在CloudFormation中存在arn hardcode的情況, 可以根據具體情況進行修改替代規則
npm install -g replace
replace '!Sub "arn:aws:' '!Sub "arn:${AWS::Partition}:' *.template.yaml
replace '"arn:aws:iot:",{ "Fn::Sub": "${AWS::Region}" }' '{ "Fn::Sub": "arn:${AWS::Partition}:iot:${AWS::Region}" }' *.template.yaml
坑二:網址域名后綴
問題描述
在Global區,在生成的APIGateway和S3地址都是:https://.amazonaws.com, 在中國區變成了https://.amazonaws.com.cn
解決方案
目前我采取的方案,有些ugly:
- 把所有hardcode的amazonaws.com用占位符替換掉
- 部署的時候,根據目標環境替換成對應的值
偽代碼
# preparation
replace '.\$\{AWS::Region\}.amazonaws.com' '.${AWS::Region}.#AMAZONAWS#' *.template.yaml
# deployment stage
if "target is China"
replace '#AMAZONAWS#' 'amazonaws.com.cn' *.template.yaml
else
replace '#AMAZONAWS#' 'amazonaws.com' *.template.yaml
坑三:可用區問題
問題描述
在Global區,大部分的region都有3個及以上可用區,所以在自動化創建VPC腳本里面,會默認使用3個可用區,however,在北京區(cn-north-1)目前只有兩個可用區
解決方案
為了兼容性,方案類似於坑二,就是在部署腳本中需要判斷目標區域的可用區數量,然后決定是用2個或3個可用區的腳本,建議VPC的部署腳本分成兩份,一份支持兩個可用區,另外一個支持三個可用區
坑四:APIGateway端口 80\443默認關閉問題
問題描述
曾經被這個問題耽誤了很長時間,明明一個很簡單的APIGateway+lambda應用,從本地postman怎么也發不通!后來發現每個賬號,默認80和443端口是不通的!
解決方案
需要從AWS Console錄一個support的case來開通。另外你的組織可能已經開始使用AWS Organization來管理多級賬號了,每個子賬號都需要用這種方式來開通端口
case參考模板:
坑四:計費單位
問題描述
有時候需要設置一些Alarm,當費用超預算時,自動郵件通知,設置計費單位的時候,需要注意,中國區目前只支持CNY
解決方案
不要hardcode,而是把計費單位作為參數傳進去
Parameters:
MoneyUnit:
Type: String
Default: USD
Resources:
DynamoDBBudget:
Type: "AWS::Budgets::Budget"
Properties:
Budget:
BudgetLimit:
Amount: !Ref DynamoDBBillingTreshold
Unit: !Ref MoneyUnit
TimeUnit: MONTHLY
不可用服務替代方案
之前提過,很多服務在中國區未上線,不可用,但很多全球項目又深度依賴這些服務。這個時候,就需要尋找替代方案。順便說一下,在做整體架構設計的時候,可能需要考慮我的現有代碼要從一個雲產商移植到另外一個雲產商需要付出的代價,這里就不展開講了。
AWS Cognito User Pool -> Keycloak
問題描述
我們的項目深度依賴Cognito user pool, Cognito user pool和APIGateway集成, 做用戶身份驗證和授權,遺憾的是這個服務在中國區不可用。
解決方案
我們找到一個非常強大的做用戶管理和身份驗證的開源項目:Keycloak
經過實踐,完美解決:用lambda寫一個customize authorizer和APIGateway進行集成
其他
一位一起工作的國外同事,在國外,經常碰到一些網絡連接的問題,開AWS China Console間歇性斷網,非常影響工作效率。
后來的臨時解決方案是先走公司內網,連到一台中國的服務器(jump server),再從這台服務器上連接AWS Console。
總覺得不是一個非常好的方案,建議能在國內有一名開發人員配合工作,提高效率!
寫在最后
說是“坑”,其實是調侃,畢竟世界發展太快,之前的開發人員可能也沒預料到科技受到各種ZZ因素的影響,導致無法理想化的大一統!
程序員就是這么一個職業,不斷的給別人挖坑,填別人的坑!哈哈
好了,分享使我快樂,有什么問題,請留言。