iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 24
0
DevOps

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

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

  • 分享至 

  • xImage
  •  

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

我們會在 AWS 上建立一個無伺服器架構的 API,會使用到 AWS Lambda 跟 Amazon 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_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

執行 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 佐 AWS 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言