今天我們來試試在雲端服務很熱門的一種架構:無伺服器架構 (Serverless)
我們會在 AWS 上建立一個無伺服器架構的 API,會使用到 AWS Lambda 跟 Amazon API Gateway 兩種服務。
首先要來建立 Lambda 函數。
AWS Lambda 是一種無伺服器架構的服務,只要把你寫好的程式放上去,接下來 Lambda 會依照使用量自動擴增資源。費用會依照使用量計算。
Lambda 支援很多程式語言,今天我們會使用 golang 來測試。
AWS 官方提供給 go 的開發者使用的函式庫放在 github 上: https://github.com/aws/aws-lambda-go
這次的 Hello world 範例會使用到兩種函式庫:
github.com/aws/aws-lambda-go/lambda
github.com/aws/aws-lambda-go/events
我們建立 main.go 檔案,當程式接到請求時,會回應一組字串,以下是完整內容:
package main
import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)
// Response of API
type Response struct {
	Message string `json:"message"`
	At      string `json:"at"`
}
func handleRequest(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	resp := Response{
		Message: "Hello World!",
		At:      time.Now().Format(time.RFC3339),
	}
	name, ok := req.QueryStringParameters["name"]
	if ok {
		resp.Message = fmt.Sprintf("Hello, %s!\n", name)
	}
	body, _ := json.Marshal(resp)
	res := events.APIGatewayProxyResponse{
		StatusCode: http.StatusOK,
		Headers:    map[string]string{"Content-Type": "text/json; charset=utf-8"},
		Body:       string(body),
	}
	return res, nil
}
func main() {
	lambda.Start(handleRequest)
}
建立 Makefile 放入 go build 指令
build:
	GOOS=linux go build -ldflags="-s -w" -o bin/main main.go
執行指令 make build 編譯執行檔
建立檔案 lamda.tf
archive_file 打包編譯好的執行檔aws_iam_policy_document 跟 aws_iam_role 建立 IAM 角色aws_lambda_function 建立 Lambda 函數完整內容:
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}
provider "aws" {
  profile = "default"
  region  = "ap-northeast-1"
}
provider "archive" {}
data "archive_file" "zip" {
  type        = "zip"
  source_file = "bin/main"
  output_path = "hello_lambda.zip"
}
data "aws_iam_policy_document" "policy" {
  statement {
    sid    = ""
    effect = "Allow"
    principals {
      identifiers = ["lambda.amazonaws.com"]
      type        = "Service"
    }
    actions = ["sts:AssumeRole"]
  }
}
resource "aws_iam_role" "lambda_exec" {
  name               = "lambda_exec"
  assume_role_policy = data.aws_iam_policy_document.policy.json
}
resource "aws_lambda_function" "hello" {
  function_name    = "hello_lambda"
  filename         = data.archive_file.zip.output_path
  source_code_hash = data.archive_file.zip.output_base64sha256
  role    = aws_iam_role.lambda_exec.arn
  handler = "main"
  runtime = "go1.x"
}
執行 terraform init 初始化 Terraform,下載供應商外掛
$ terraform init
Initializing the backend...
...
* hashicorp/archive: version = "~> 1.3.0"
* hashicorp/aws: version = "~> 3.8.0"
Terraform has been successfully initialized!
執行 terraform apply 建立 Lambda 函數
$ terraform apply
...
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
我們成功建立一個 Lambda 函數了,接著要來做一點測試
使用 AWS 指令測試函數:
$ aws lambda invoke --region=ap-northeast-1 --function-name=hello_lambda  output.json
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
檢查輸出的資料:
cat output.json
{"statusCode":200,"headers":{"Content-Type":"text/json; charset=utf-8"},"multiValueHeaders":null,"body":"{\"message\":\"Hello World!\",\"at\":\"2020-09-26T09:35:12Z\"}"}%
現在我們有了 Lamda 函數,下一步要跟 API Gateway 組合,讓這個函數可以介由 HTTP 在網路上使用。