My Note

自己理解のためのブログ

Serverless Framework GoでLambda-Functionをデプロイする

Macにnpmをインストールする

  • $ brew install nodebrew
  • $ mkdir -p ~/.nodebrew/src
  • $ nodebrew install-binary latest
  • $ nodebrew list
  • $ nodebrew use v11.4.0
  • $ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zshrc

MacにServerlessFrameworkをインストールする

  • $ npm install -g serverless
  • $ cd ${HOME}/go-serverlessFramework
  • myserviceというサービスで作成する
$ serverless create -u https://github.com/serverless/serverless-golang/ -p myservice
Serverless: Generating boilerplate...
Serverless: Downloading and installing "serverless-golang"...
Serverless: Successfully installed "myservice"
  • ディレクトリへ移動する
    • $ cd ${HOME}/go-serverlessFramework/myservice
  • GOPATHを設定する
    • $ export GOPATH=`pwd`
  • go getで必要なパッケージを取得する
    • $ go get github.com/aws/aws-lambda-go/lambda
  • ソースコードコンパイルする
    • $ GOOS=linux go build -o bin/main
  • serverless.ymlを修正する
    • regionを us-east-1 から ap-northeast-1 に変更する
  • ServelessFrameworkでデプロイする
    • aws-cliを実行できるようにMacのローカルにAPIを実行できるようにする必要がある
      • S3とCloudFormationとLambdaを作成できる権限が必要
    • $ serverless deploy
serverless deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (7.85 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
.........
Serverless: Stack update finished...
Service Information
service: myservice
stage: dev
region: ap-northeast-1
stack: myservice-dev
api keys:
  None
endpoints:
  None
functions:
  hello: myservice-dev-hello
layers:
  None

デプロイしたLambdaの一部抜粋

f:id:yhidetoshi:20190617215456p:plain f:id:yhidetoshi:20190617215513p:plain f:id:yhidetoshi:20190617215541p:plain

  • デプロイするGoコードは以下を使う(main.go)
    • AMI数と起動設定数をSlackにPostする
package main

import (
    "context"
    "fmt"
    "os"
    "strconv"

    "github.com/ashwanthkumar/slack-go-webhook"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/autoscaling"
    "github.com/aws/aws-sdk-go/service/ec2"
)

const (
    WEBHOOKURL = "https://hooks.slack.com/services/XXXXX"
    CHANNEL    = "dev"
    USERNAME   = "ResourceChecker"
)

var (
    config = aws.Config{Region: aws.String("ap-northeast-1")}
    svcEc2 = ec2.New(session.New(&config))
    svcAsg = autoscaling.New(session.New(&config))
)

type Get interface {
    GetAmiNums() int
    GetLCNums() int
    GetAccountAlias() string
}

type Nums struct {
    amiNumbers   int
    lcNumbers    int
    accountAlias string
}

func main() {
    lambda.Start(Handler)
}

func Handler(ctx context.Context) {
    n := &Nums{}
    PostSlack(n.GetAmiNums(), n.GetLCNums())

}

// return total registered AMIs
func (n *Nums) GetAmiNums() int {
    var owner, images []*string
    var _owner []string = []string{"self"}

    owner = aws.StringSlice(_owner)
    params := &ec2.DescribeImagesInput{
        ImageIds: images,
        Owners:   owner,
    }
    res, err := svcEc2.DescribeImages(params)
    if err != nil {
        fmt.Println(err.Error())
        os.Exit(1)
    }

    n.amiNumbers = len(res.Images)
    return n.amiNumbers

}

// Return total LaunchConfigurations
func (n *Nums) GetLCNums() int {
    pageNum := 0
    sumLcs := 0

    params := &autoscaling.DescribeLaunchConfigurationsInput{}
    err := svcAsg.DescribeLaunchConfigurationsPages(params,
        func(page *autoscaling.DescribeLaunchConfigurationsOutput, lastPage bool) bool {
            sumLcs += len(page.LaunchConfigurations)
            pageNum++

            return pageNum <= 4 // 50 * 4page = 200(Max)
        })
    if err != nil {
        fmt.Println(err.Error())
        os.Exit(1)
    }
    n.lcNumbers = sumLcs

    return n.lcNumbers

}


// Post Slack result
func PostSlack(amiNumbers, lcNumbers int) {
    field1 := slack.Field{Title: "Total AMIs", Value: strconv.Itoa(amiNumbers)}
    field2 := slack.Field{Title: "Total LaunchConfigurations", Value: strconv.Itoa(lcNumbers)}

    attachment := slack.Attachment{}
    attachment.AddField(field1).AddField(field2)
    color := "warning"
    attachment.Color = &color
    payload := slack.Payload{
        Username:    USERNAME,
        Channel:     CHANNEL,
        Attachments: []slack.Attachment{attachment},
    }
    err := slack.Send(WEBHOOKURL, "", payload)
    if len(err) > 0 {
        panic(err)
    }
}

実行結果

f:id:yhidetoshi:20190617215633p:plain

まとめ

npmのインストールからServerlessFrameworkを使い、GoのLambda関数をデプロイするところまでを実施しました。 Serverless Frameworkを使って、Lambda関数をGoで書いてデプロイしていきたいと思います。