Trong quá trình làm việc, hay gặp vấn đề nên notes ra đây luôn tránh quên
Lambda function là gì
Lambda function là một service rất hay của AWS mới xuất hiện trong vài năm gần đây. Nó cho phép người dùng đưa chương trình của mình lên và chạy mà không cần phải cài đặt môi trường như EC2.
Tuy nhiên Lambda function không thể tự chạy một mình, nó cần có sự kiện kích hoạt, có thể là gọi thông qua API, hoặc thông qua dạng Jobs từ AWS CloudWatch.
Và nó không phải tất cả cho một hệ thống mà chỉ là một phần của hệ thống. Nó thường được với vai trò là business logic, nhận thông tin, lấy thông tin từ module khác, trả lại kết quả hoặc ghi dữ liệu vào Database (DynamoDB hay S3)
Một ưu điểm của Lambda function là cách tính chi phí, thay vì một chi phí cho server như E2, thì nó chỉ tính phí dựa trên thời gian function được gọi. Rât tiết kiệm phải không.
Tài liệu về Lambda function
API Gateway là gì
Đúng như nghĩa đen, API Gateway cung cấp phương thức để bên ngoài có thể giao tiếp với tài nguyên hệ thống, như api, hay s3. Với nhiều options setting, có thể giới hạn theo quyền được tạo sẵn, key hay giới hạn IP address
Tài liệu về API Gateway
SAM là gì
SAM là một dịch vụ của AWS giúp triển khai, cài đặt và câú hình tự động các dịch vụ, module của hệ thống lên môi trường AWS, thông qua file config là template.yaml.
Rất tiện lợi trong quá trình phát triển, test và deploy với sự thiết lập thông số khác nhau cho mỗi môi trường.
Tài liệu về AWS SAM
Cấu hình chung các dịch vụ này với nhau
Dưới đây là nội dung mẫu của file yaml điển hình.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | <span class="token key atrule">AWSTemplateFormatVersion</span><span class="token punctuation">:</span> <span class="token string">'2010-09-09'</span> <span class="token key atrule">Transform</span><span class="token punctuation">:</span> AWS<span class="token punctuation">:</span><span class="token punctuation">:</span>Serverless<span class="token punctuation">-</span><span class="token datetime number">2016-10-31</span> <span class="token key atrule">Description</span><span class="token punctuation">:</span> <span class="token punctuation">...</span> <span class="token comment"># tham số dùng để truyền khi chạy từ aws cli</span> <span class="token key atrule">Parameters</span><span class="token punctuation">:</span> <span class="token key atrule">Stage</span><span class="token punctuation">:</span> <span class="token key atrule">Type</span><span class="token punctuation">:</span> String <span class="token key atrule">AllowedValues</span><span class="token punctuation">:</span> <span class="token punctuation">-</span> staging <span class="token punctuation">-</span> production <span class="token comment"># Định nghĩa các tham số tuỳ thuộc vào môi trường(staging/production)</span> <span class="token key atrule">Mappings</span><span class="token punctuation">:</span> <span class="token key atrule">Configs</span><span class="token punctuation">:</span> <span class="token key atrule">staging</span><span class="token punctuation">:</span> <span class="token key atrule">tham_số</span><span class="token punctuation">:</span> Giá_trị <span class="token key atrule">SourceVpce</span><span class="token punctuation">:</span> <span class="token punctuation">-</span> vpce<span class="token punctuation">-</span>abc <span class="token comment">#VPC endpoint mà dùng để truy cập private api gateway</span> <span class="token key atrule">production</span><span class="token punctuation">:</span> <span class="token comment">#môi trường production</span> <span class="token key atrule">tham_số</span><span class="token punctuation">:</span> Giá_trị <span class="token key atrule">SourceVpce</span><span class="token punctuation">:</span> <span class="token punctuation">-</span> vpce<span class="token punctuation">-</span>def <span class="token comment"># Định nghĩa biến môi trường, sau này có thể truy cập trong chương trình lambda</span> <span class="token comment"># Ví dụ: process.env.XXXX</span> <span class="token key atrule">Globals</span><span class="token punctuation">:</span> <span class="token key atrule">Function</span><span class="token punctuation">:</span> <span class="token key atrule">Timeout</span><span class="token punctuation">:</span> <span class="token number">3</span> <span class="token key atrule">Environment</span><span class="token punctuation">:</span> <span class="token key atrule">Variables</span><span class="token punctuation">:</span> <span class="token key atrule">RELEASE_STAGE</span><span class="token punctuation">:</span> <span class="token tag">!Ref</span> Stage <span class="token key atrule">BIẾN_TOÀN_CỤC</span><span class="token punctuation">:</span> <span class="token tag">!FindInMap</span> <span class="token punctuation">[</span> Configs<span class="token punctuation">,</span> <span class="token tag">!Ref</span> Stage<span class="token punctuation">,</span> tham_số <span class="token punctuation">]</span> <span class="token comment"># Định nghĩa các service</span> <span class="token key atrule">Resources</span><span class="token punctuation">:</span> <span class="token key atrule">FooBarApi</span><span class="token punctuation">:</span> <span class="token key atrule">Type</span><span class="token punctuation">:</span> AWS<span class="token punctuation">:</span><span class="token punctuation">:</span>Serverless<span class="token punctuation">:</span><span class="token punctuation">:</span>Api <span class="token key atrule">Properties</span><span class="token punctuation">:</span> <span class="token key atrule">Name</span><span class="token punctuation">:</span> FooBarApi <span class="token key atrule">StageName</span><span class="token punctuation">:</span> Prod <span class="token key atrule">EndpointConfiguration</span><span class="token punctuation">:</span> PRIVATE <span class="token comment"># option cho private API gateway</span> <span class="token key atrule">Auth</span><span class="token punctuation">:</span> <span class="token key atrule">ResourcePolicy</span><span class="token punctuation">:</span> <span class="token comment"># giới hạn resource có thể truy cập api gateway</span> <span class="token key atrule">CustomStatements</span><span class="token punctuation">:</span> <span class="token key atrule">Effect</span><span class="token punctuation">:</span> Allow <span class="token key atrule">Action</span><span class="token punctuation">:</span> <span class="token string">'execute-api:Invoke'</span> <span class="token key atrule">Resource</span><span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token string">'execute-api:/*/*/*'</span> <span class="token key atrule">Principal</span><span class="token punctuation">:</span> <span class="token string">'*'</span> <span class="token key atrule">Condition</span><span class="token punctuation">:</span> <span class="token key atrule">ForAnyValue:StringEquals</span><span class="token punctuation">:</span> <span class="token comment"># Chỉ những vpce định nghĩa ở trên mới có thể truy cập đến private api gateway này</span> <span class="token key atrule">aws:sourceVpce</span><span class="token punctuation">:</span> <span class="token tag">!FindInMap</span> <span class="token punctuation">[</span> Configs<span class="token punctuation">,</span> <span class="token tag">!Ref</span> Stage<span class="token punctuation">,</span> SourceVpce <span class="token punctuation">]</span> |
Những điểm cần chú ý
Thiết lập API gateway là private
1 2 | <span class="token key atrule">EndpointConfiguration</span><span class="token punctuation">:</span> PRIVATE |
Giới hạn vpce
1 2 3 | <span class="token key atrule">ForAnyValue:StringEquals</span><span class="token punctuation">:</span> <span class="token key atrule">aws:sourceVpce</span><span class="token punctuation">:</span> <span class="token tag">!FindInMap</span> <span class="token punctuation">[</span> Configs<span class="token punctuation">,</span> <span class="token tag">!Ref</span> Stage<span class="token punctuation">,</span> SourceVpce <span class="token punctuation">]</span> |
Trỏ tới API này khi định nghĩa Lambda function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token key atrule">FooBarFunction</span><span class="token punctuation">:</span> <span class="token key atrule">Type</span><span class="token punctuation">:</span> <span class="token string">'AWS::Serverless::Function'</span> <span class="token key atrule">Properties</span><span class="token punctuation">:</span> <span class="token key atrule">CodeUri</span><span class="token punctuation">:</span> foor<span class="token punctuation">-</span>bar/ <span class="token key atrule">Handler</span><span class="token punctuation">:</span> lambda.handler <span class="token key atrule">Runtime</span><span class="token punctuation">:</span> nodejs10.x <span class="token key atrule">Timeout</span><span class="token punctuation">:</span> <span class="token number">10</span> <span class="token key atrule">Events</span><span class="token punctuation">:</span> <span class="token comment"># Định ngĩa sự kiện kích hoạt Lambda function</span> <span class="token key atrule">PutLogistics</span><span class="token punctuation">:</span> <span class="token key atrule">Type</span><span class="token punctuation">:</span> Api <span class="token key atrule">Properties</span><span class="token punctuation">:</span> <span class="token key atrule">RestApiId</span><span class="token punctuation">:</span> <span class="token key atrule">Ref</span><span class="token punctuation">:</span> FooBarApi <span class="token key atrule">Path</span><span class="token punctuation">:</span> /foo/bar <span class="token key atrule">Method</span><span class="token punctuation">:</span> put |
Với định nghĩa như trên, chúng ta đã định nghĩa được cùng lúc
- API gateway
- Lambda function
- … có thể cấu hình cả S3, DynamoDB …
Cách triển khai SAM lên môi trường AWS thông qua cli
Chú ý: các bạn cần cài đặt sẵn
- aws cli
- sam cli
- cấu hình profile bên trong 2 file ./aws/config và ./aws/credentials
1 2 3 4 5 6 7 8 | <span class="token punctuation">[</span>default<span class="token punctuation">]</span> output <span class="token operator">=</span> json region <span class="token operator">=</span> ap-northeast-1 <span class="token punctuation">[</span>xyz-staging<span class="token punctuation">]</span> output <span class="token operator">=</span> json region <span class="token operator">=</span> ap-northeast-1 |
1 2 3 4 5 6 7 8 | <span class="token punctuation">[</span>default<span class="token punctuation">]</span> aws_access_key_id <span class="token operator">=</span> <span class="token punctuation">..</span>. aws_secret_access_key <span class="token operator">=</span> <span class="token punctuation">..</span><span class="token punctuation">..</span> <span class="token punctuation">[</span>xyz-staging<span class="token punctuation">]</span> aws_access_key_id <span class="token operator">=</span> <span class="token punctuation">..</span>. aws_secret_access_key <span class="token operator">=</span> <span class="token punctuation">..</span>. |
Build và triển khai (deploy)
1 2 3 4 5 6 7 8 | sam build --profile xyz-staging sam package --profile xyz-staging --output-template packaged.yaml --s3-bucket xyz-sam-staging <span class="token comment"># xyz-sam-staging là S3 bucket dùng để lưu trữ data của cấu hình SAM này</span> sam deploy --profile xyz-staging --template-file packaged.yaml --region ap-northeast-1 --capabilities CAPABILITY_IAM --stack-name xyz-staging --parameter-overrides Stage<span class="token operator">=</span>staging <span class="token comment"># --stack-name xyz-staging: tên của stack khi triển khai lên aws, có thể vào AWS > Cloudformation để xem các stack, trạng thái của việc thực thi, thành công hay lỗi</span> |
Bàn về cách định nghĩa API trong template
Có hai cách để định nghĩa một api:
- Định nghĩa độc lập (như ví dụ trên)
- Định nghĩa bên trong thuộc tính events của Function
Trong trường hợp này, nếu muốn thiết lập API là private thì phải định nghĩa trong Global Section
(Vì khi này, thuộc tínhEndpointConfiguration
không được hỗ trợ)
Hãy tham khảo ví dụ dưới
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <span class="token key atrule">Globals</span><span class="token punctuation">:</span> <span class="token key atrule">Api</span><span class="token punctuation">:</span> <span class="token key atrule">EndpointConfiguration</span><span class="token punctuation">:</span> PRIVATE <span class="token punctuation">...</span> <span class="token key atrule">FooBarFunction</span><span class="token punctuation">:</span> <span class="token key atrule">Type</span><span class="token punctuation">:</span> <span class="token string">'AWS::Serverless::Function'</span> <span class="token key atrule">Properties</span><span class="token punctuation">:</span> <span class="token key atrule">CodeUri</span><span class="token punctuation">:</span> foo<span class="token punctuation">-</span>bar/ <span class="token key atrule">Handler</span><span class="token punctuation">:</span> lambda2.handler <span class="token key atrule">Runtime</span><span class="token punctuation">:</span> nodejs10.x <span class="token key atrule">Timeout</span><span class="token punctuation">:</span> <span class="token number">10</span> <span class="token key atrule">Events</span><span class="token punctuation">:</span> <span class="token key atrule">Foobar</span><span class="token punctuation">:</span> <span class="token key atrule">Type</span><span class="token punctuation">:</span> Api <span class="token key atrule">Properties</span><span class="token punctuation">:</span> <span class="token key atrule">Path</span><span class="token punctuation">:</span> /foo/bar <span class="token key atrule">Method</span><span class="token punctuation">:</span> put <span class="token key atrule">Auth</span><span class="token punctuation">:</span> <span class="token key atrule">ResourcePolicy</span><span class="token punctuation">:</span> <span class="token key atrule">CustomStatements</span><span class="token punctuation">:</span> <span class="token key atrule">Effect</span><span class="token punctuation">:</span> Allow <span class="token key atrule">Action</span><span class="token punctuation">:</span> <span class="token string">'execute-api:Invoke'</span> <span class="token key atrule">Resource</span><span class="token punctuation">:</span> <span class="token punctuation">-</span> <span class="token string">'execute-api:/*/*/*'</span> <span class="token key atrule">Principal</span><span class="token punctuation">:</span> <span class="token string">'*'</span> <span class="token key atrule">Condition</span><span class="token punctuation">:</span> <span class="token key atrule">ForAnyValue:StringEquals</span><span class="token punctuation">:</span> <span class="token key atrule">aws:sourceVpce</span><span class="token punctuation">:</span> <span class="token tag">!FindInMap</span> <span class="token punctuation">[</span> Configs<span class="token punctuation">,</span> <span class="token tag">!Ref</span> Stage<span class="token punctuation">,</span> SourceVpce <span class="token punctuation">]</span> <span class="token key atrule">Policies</span><span class="token punctuation">:</span> <span class="token punctuation">-</span> AWSLambdaVPCAccessExecutionRole <span class="token punctuation">-</span> SecretsManagerReadWrite <span class="token punctuation">-</span> <span class="token key atrule">S3ReadPolicy</span><span class="token punctuation">:</span> <span class="token key atrule">BucketName</span><span class="token punctuation">:</span> <span class="token tag">!FindInMap</span> <span class="token punctuation">[</span> Configs<span class="token punctuation">,</span> <span class="token tag">!Ref</span> Stage<span class="token punctuation">,</span> ShopInfoBucket <span class="token punctuation">]</span> |
Các bạn có thể thấy, thay vì dùng property: RestApiId:
để trỏ tới API được định nghĩa sẵn, chúng ta mô tả API này ngay trong Function. Cũng khá tiện nhỉ
Lời cuối
Vậy là bạn đã hoàn thành việc cấu hình và triển khai các dịch vụ có liên kết với nhau lên AWS rồi đấy.
Giờ là lúc xác nhận xem chúng có triển khai đúng không bằng các vào AWS Manage console, xem trong
CloudFormation, Lambda function, API Gateway.
Ở các bài viết sau, mình sẽ hướng dẫn cách gọi API Gateway này từ command line, từ chương trình, cũng như các test riêng biệt Lambda function, API Gateway trên chính AWS Manage Console nhé.
Thân ái!