iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 24
0
DevOps

今晚我想來點 Terraform 佐 AWS系列 第 24

今晚我想來點 Terraform 搭 Golang 風味無伺服器架構

  • 分享至 

  • xImage
  •  

今天我們來試試在雲端服務很熱門的一種架構:無伺服器架構 (Serverless)

我們會在 AWS 上建立一個無伺服器架構的 API,會使用到 AWS LambdaAmazon API Gateway 兩種服務。

首先要來建立 Lambda 函數。

AWS Lambda

AWS Lambda 是一種無伺服器架構的服務,只要把你寫好的程式放上去,接下來 Lambda 會依照使用量自動擴增資源。費用會依照使用量計算。

Lambda 支援很多程式語言,今天我們會使用 golang 來測試。

準備 go 程式碼

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 編譯執行檔

建立 Lambda 函數

建立檔案 lamda.tf

  • 使用 archive_file 打包編譯好的執行檔
  • 使用 aws_iam_policy_documentaws_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

執行 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 在網路上使用。


上一篇
今晚我想來點優雅的 Terraform 風格指南
下一篇
今晚我想來點 Terraform 搭 Golang 風味無伺服器架構拌 API 閘道
系列文
今晚我想來點 Terraform 佐 AWS30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言