Skip to content

Date: October 01, 2022

pods

Dashboard app with Go AWS SDK

Motivation

  • EC2 -> ECS ์ด๊ด€ ๋ฐ ์ƒ์„ฑ ์ž‘์—…์— ํ•„์š”ํ•œ, ECS, TG, ALB ๋“ฑ ์ž์›์กฐํšŒ ๊ธฐ๋Šฅ ํ•„์š”
  • ์ž์› ์ƒ์„ฑ ์‹œ stage ๋ณ„ ๋ฐ์ดํ„ฐ ํ™•์ธ ํ•„์š”ํ•˜์—ฌ AWS Console ๋Œ€์‹ , SDK ํ™œ์šฉ
  • CLI (go cobra library) ํˆด ๋Œ€์‹ , ์›นํŽ˜์ด์ง€ url (ip:port)๋กœ ๊ฐ„ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” web ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑ
    • url: ํ”„๋ผ์ด๋น— ํด๋ผ์šฐ๋“œ ๋‚ด๋ถ€ vpn์œผ๋กœ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
  • AWS ์ž์›๊ฐ„ ์˜์กด์„ฑ์ด ์žˆ๋Š”๋ฐ, AWS๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋‹จ์ผ API๋กœ ์›ํ•˜๋Š” ์ž์›์ƒํƒœ ์กฐํšŒ๊ฐ€ ํž˜๋“ฆ
  • AWS API ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋“ค๋กœ object list ๋งŒ๋“ค์–ด, ์ •๋ ฌ ์ฒ˜๋ฆฌ (Override Len, Less, Swap functions)

Skills

Backend : Go, Go AWS SDK
Frontend : Javascript, HTML, CSS

How Application Works

It utilizes Go AWS SDK to render a organized view of AWS resources deployed in multiple environments: dev, stg, prd.

  • ALB > TargetGroup > Target Health > Container_Ip, Instance_Id
  • ECS Task์˜ Container, Image, IP ๋“ฑ
  • ECR tag, image uri -> ์ตœ์‹ ์ˆœ ์ •๋ ฌ

Progress

  • Web application (go, javascript, html, css) ์™„์„ฑ
  • ์ปจํ…Œ์ด๋„ˆํ™”
    • Dockerfile ๋นŒ๋“œ, Image ์ƒ์„ฑ, ์ปจํ…Œ์ด๋„ˆ Run
    • EC2 role based access๋กœ, aws credential ๊ด€๋ฆฌ -> ๋„์ปค ์ปจํ…Œ์ด๋„ˆ๋กœ credential propagation ํ…Œ์ŠคํŠธ ์ค‘
    • ๊ณ ๋ฃจํ‹ด ๋ฐ ์ฑ„๋„ ์ ์šฉ: API ํ˜ธ์ถœ์‹œ ๋‹ค์ˆ˜์˜ AWS api ํ†ต์‹ ํ•˜๋Š” ๊ฒฝ์šฐ
  • Cloudwatch ๋กœ๊ทธ, EC2, Task event ์กฐํšŒ(down, up) ์ถ”๊ฐ€ ์˜ˆ์ •

Test

  • Cloud์ ‘์† -> Vpn > http://{ip_addr}:port

go sdk app

Aws Profile Management

  • credential_source=Ec2InstanceMetadata

    • AWS CLI / SDK๊ฐ€ EC2 ์ธ์Šคํ„ด์Šค์— attach๋œ IAM Role ์‚ฌ์šฉํ•˜์—ฌ Source credential ๊ฐ€์ ธ์˜ด
  • EC2์ธ์Šคํ„ด์Šค์— IAM Role Attachํ•˜๊ธฐ

# IAM Role with permission policies :
#       Create role > Add Permissions

AmazonEC2FullAccess
    Provides full access to Amazon EC2 via the AWS Management Console.

IAMFullAccess
    Provides full access to IAM via the AWS Management Console.

AmazonEC2ContainerRegistryFullAccess
    Provides administrative access to Amazon ECR resources

AmazonS3FullAccess
    Provides full access to all buckets via the AWS Management Console.

ReadOnlyAccess
    Provides read-only access to AWS services and resources.

AmazonSESFullAccess
    Provides full access to Amazon SES via the AWS Management Console.

AmazonAPIGatewayAdministrator
    Provides full access to create/edit/delete APIs in Amazon API Gateway via the AWS Management Console.

AmazonECS_FullAccess
    Provides administrative access to Amazon ECS resources and enables ECS features through access to other AWS service resources, including VPCs, Auto Scaling groups, and CloudFormation stacks.

AWSCloudFormationFullAccess
    Provides full access to AWS CloudFormation.

AWSLambda_FullAccess
    Grants full access to AWS Lambda service, AWS

Credential: go aws sdk

import "github.com/aws/aws-sdk-go/aws/session"

// AWS ํ”„๋กœํŒŒ์ผ ๋ช… (~/.aws/config)
type AwsProfile struct{
    dev string
    stg string
    prd string
}
var awsProfile AwsProfile

// ์„ธ์…˜๊ฐ์ฒด ์ดˆ๊ธฐํ™”
func InitSession(profile string) *session.Session {
    if profile == "dev" {
        profile = awsProfile.dev
    } else if profile == "stg" {
        profile = awsProfile.stg
    } else if profile == "prd" {
        profile = awsProfile.prd
    }
    sess, err := session.NewSessionWithOptions(session.Options{
        // Specify profile to load for the session's config
        Profile: profile,
        SharedConfigState: session.SharedConfigEnable,
    })
    if err != nil {
        panic(err)
    }
    return sess
}

Repo custom interface

  • func (repo *Repo) getAWSTargetGroups()
  • func (repo *Repo) getAWSTargetHealths(tgarn string)
  • func (repo *Repo) getAWSEcsClusterDetails(clusterArn string)
  • func (repo *Repo) getAWSEcsSvcList(clusterArns []*string)
  • func (repo *Repo) getAWSListClusters()
  • func (repo *Repo) getAWSEcsClusters(clusters []*string)
  • func (repo *Repo) getAWSEcsDescribeTaskDefinition(services []*ecs.Service)
  • func (repo *Repo) getAWSEcsListAndDescribeTasks(clusterName, serviceName string)
  • func (repo *Repo) getAWSEcsDescribeService(clusterName, serviceName string)
  • func (repo *Repo) getAWSEcrRepos(repoName string)
  • func (repo *Repo) getAWSEcrDescribeImages(repoUri, repoName string)
// ์„ธ์…˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ
type Repo struct {
    sess *session.Session
}

// ์„ธ์…˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค
func RepoInterface(param *session.Session) *Repo {
    return &Repo{sess: param}
}

/**
 * ์„ธ์…˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ Repo ๊ตฌํ˜„์ฒด
 */

// TG ์กฐํšŒ -> tgMap ์ €์žฅ
func (repo *Repo) getAWSTargetGroups() {

    // ๋ฐ์ดํ„ฐ ์ดˆ๊ธฐํ™”
    tgMap = make(map[string]*elbv2.TargetGroup)

    // ELBV2 ์„œ๋น„์Šค ์ƒ์„ฑ
    svc := elbv2.New(repo.sess)
    input := &elbv2.DescribeTargetGroupsInput{ // ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ
        Names: []*string {
            // aws.String("awsdc-tg-erp-dev-tdms-7080"),
        },
    }
    // ELBV2 ์„œ๋น„์Šค api DescribeTargetGroups ํ˜ธ์ถœ
    pageNum := 0
    // result, err := svc.DescribeTargetGroups(input)
    err := svc.DescribeTargetGroupsPages(input, func(page *elbv2.DescribeTargetGroupsOutput, lastPage bool) bool {
            pageNum++
            log.Println("PAGE result data size: ", len(page.TargetGroups))
            for _, tg := range page.TargetGroups {
                tgMap[*tg.TargetGroupName] = tg
            }
            return !lastPage
    })
    if err != nil {
        handleError(err)
        return
    }
}