반응형

ec2를 pc에서 접속 시 public ip와 인증서(.pem)을 통해 ssh로 접속하는데, 접속이 안될 때가 있다.

(휴대폰 테더링을 통해 pc를 인터넷에 연결하면 그렇다.)

이 경우.. 아래와 같이 도메인으로 접속해보면 된다.

 

Before

ssh -i [인증서].pem -p [접속할 local port] ec2-user@[접속할 ec2의 public ip]

 

After

ssh -i [인증서].pem -p 20022 ec2-user@[접속할 ec2의 도메인 주소]

반응형
반응형

terraform을 설치할 때, 그냥 tfenv install 0.14.6 이렇게 설치하면 되지만,

m1에선 쉽게 되지 않는다.

test@HMH73K0H9Y ~ % tfenv install 0.14.6
Installing Terraform v0.14.6
Downloading release tarball from https://releases.hashicorp.com/terraform/0.14.6/terraform_0.14.6_darwin_arm64.zip
curl: (22) The requested URL returned error: 404                                                       
Tarball download failed

 

이유 및 해결 방법

저 경로에 arm64가 없고 amd64가 있기 때문인데, 그럼 amd64를 wget을 통해 가져와준다.

# wget https://releases.hashicorp.com/terraform/0.14.6/terraform_0.14.6_darwin_amd64.zip

test@HMH73K0H9Y bin % sudo wget https://releases.hashicorp.com/terraform/0.14.6/terraform_0.14.6_darwin_amd64.zip
Password:
--2022-05-24 07:42:30--  https://releases.hashicorp.com/terraform/0.14.6/terraform_0.14.6_darwin_amd64.zip
releases.hashicorp.com (releases.hashicorp.com) 해석 중... 2a04:4e42:7c::439, 146.75.49.183
다음으로 연결 중: releases.hashicorp.com (releases.hashicorp.com)|2a04:4e42:7c::439|:443... 연결했습니다.
HTTP 요청을 보냈습니다. 응답 기다리는 중... 200 OK
길이: 34590555 (33M) [application/zip]
저장 위치: `terraform_0.14.6_darwin_amd64.zip'


terraform_0.14.6_darwin_a 100%[=====================================>]  32.99M   897KB/s    /  33s     


2022-05-24 07:43:03 (1.01 MB/s) - `terraform_0.14.6_darwin_amd64.zip' 저장함 [34590555/34590555]


test@HMH73K0H9Y bin % sudo unzip terraform_0.14.6_darwin_amd64.zip 
Archive:  terraform_0.14.6_darwin_amd64.zip
  inflating: terraform               

jane@HMH73K0H9Y bin % terraform -version
cat: /opt/homebrew/Cellar/tfenv/2.2.3/version: No such file or directory
Version could not be resolved (set by /opt/homebrew/Cellar/tfenv/2.2.3/version or tfenv use <version>)

압축을 풀었고 terraform이 설치되었지만 여전히 버전 정보는 조회할 수 없다.

 

 

해결 방법

1) 위에서 요구하는 저 경로에( set by /opt/homebrew/Cellar/tfenv/2.2.3/version) vi version으로 0.14.6을 기입해주고,

test@HMH73K0H9Y 2.2.3 % ls

CHANGELOG.md LICENSE bin libexec version

INSTALL_RECEIPT.json README.md lib share versions

test@HMH73K0H9Y 2.2.3 % cat version

0.14.6

 

2) versions/ 뒤에 0.14.6 디렉토리를 만든 후,

test@HMH73K0H9Y bin % mkdir -p /opt/homebrew/Cellar/tfenv/2.2.3/versions/0.14.6/

 

3) 설치했었던 terraform 파일을 복사해준다.

test@HMH73K0H9Y bin % sudo mv ./terraform /opt/homebrew/Cellar/tfenv/2.2.3/versions/0.14.6/

 

 

해결 확인

test@HMH73K0H9Y 2.2.3 % tfenv use 0.14.6

Switching default version to v0.14.6

Switching completed

 

test@HMH73K0H9Y 2.2.3 % terraform --version

Terraform v0.14.6

 

Your version of Terraform is out of date! The latest version

is 1.2.0. You can update by downloading from https://www.terraform.io/downloads.html

 

 

반응형
반응형

- Hosting: 컨테이너(ECS, EKS)를 위한 컴퓨팅 리소스

  . EC2: 가상머신(VM) == 독립된 환경이 있고 운영체제를 갖고 있는 컴퓨팅 리소스

  . Fargate: EC2보다 더 추상화된 컴퓨팅 환경. 기본 인프라 관리할 필요 없는 EC2의 서버리스 버전. 앱별 자동으로 리소스 지정.

- Management(ECS, EKS): 

 . ECS(Elastic Container Service): 컨테이너 기반의 컴퓨팅 플랫폼. 단순함. AWS에서만 제공되는 Orchestration. AWS Only

 . EKS(Elastic Kubernetes Service): 컨테이너 기반의 k8s 환경 플랫폼. 보다 복잡함. K8s 환경이라 플랫폼간 이전 용이(범용)

 

  * 차이점

   1) LB(Load Balancing): ECS는 앞단 LB에서만 로드를 분산시키지만, EKS는 K8s 내부 proxy가 있어 pod간 노드 분산도 가능함.

 2) Networking(IP할당): ECS는 task별 ENI(Elastic Network I/F)를 할당받지만, EKS는 단일 pod마다 IP 할당받을 수 있음.

      ECS는 pod를 15개까지 만들 수 있는 반면, EKS는 750개 까지 만들 수 있음. 그래서 큰 서비스를 만들 거라면 EKS가 나음.

 3) Pricing(비용): 클러스터는 ECS는 무료지만 EKS는 시간당 0.20 USD(한달이면 144 USD).

      나머지는 사용하는 리소스에 따라 각기 부과됨. 

 

 

 

 

출처: 

https://timewizhan.tistory.com/entry/AWS-ECS-vs-EKS

https://ondemand.tistory.com/354

 

 

 

반응형
반응형

이전 포스팅에서, cloudwatch에서 알람이 발생할 때마다 SNS, 그리고 lambda를 trigger해서 slack으로 알람을 보냈다.

* 이전 포스팅:

https://countrymouse.tistory.com/entry/awscloudwatchslack

 

[AWS] cloudwatch, lambda를 통해 slack으로 알람 보내기 (Nodejs)

Cloudwatch에서 알람 조건을 만들어서, 해당 알람이 발생할 때 slack으로 notify하는 환경을 만들어보자. 1. AWS > CloudWatch > 경보 생성 1) 지표 선택 2) 지표에서 원하는 tracking값 및 임계치 선택 (알람..

countrymouse.tistory.com

 

그런데, alarm으로 받는 text의 포맷이 아래와 같이 가독성이 떨어진다. 그래서, 보다 가독성 있게 수정해보기로 한다.

 

위 가독성 없는 텍스트를 아래 포맷으로 수정한다.

 

코드는 아래 티스토리 블로거 향로님의 코드를 사용하였고 아래는 한줄한줄 해석을 달아보았다. 

(직접 하나씩 만들어보려고 했는데, 반나절의 삽질을 해도 원하는 대로 잘 안돼서 다른 분의 코드를 사용하기로 했다...)

https://jojoldu.tistory.com/586

 

CloudWatch 이상 지표를 슬랙 알람으로 받기 (feat. SNS, Lambda)

AWS 서비스를 이용하면 CloudWatch를 통해 서비스의 이상 지표를 손쉽게 확인할 수 있습니다. 이를테면 다음과 같은 경우인데요. 평소보다 로드밸런서로 들어오는 요청양이 2배이상 높다거나 RDS의 C

jojoldu.tistory.com

 

향로님 코드에 cause부분과 관련된 코드는 삭제하였고(나는 '원인'을 '설명'으로 대체했다), 일부분에 주석을 추가하였다.

// 구성 -> 환경변수로 webhook을 받도록 합니다.
const ENV = process.env
if (!ENV.webhook) throw new Error('Missing environment variable: webhook')

const webhook = ENV.webhook;
const https = require('https')

const statusColorsAndMessage = {
    ALARM: {"color": "danger", "message":"위험"},
    INSUFFICIENT_DATA: {"color": "warning", "message":"데이터 부족"},
    OK: {"color": "good", "message":"정상"}
}


// 1. 여기서부터 시작 
exports.handler = async (event) => {
    await exports.processEvent(event);
}


// 2. processEvent로 넘어간다.
exports.processEvent = async (event) => {
    console.log('Event:', JSON.stringify(event))
    const snsMessage = event.Records[0].Sns.Message;
    console.log('SNS Message:', snsMessage);
    const postData = exports.buildSlackMessage(JSON.parse(snsMessage))  // 3. buildSlackMessage
    await exports.postSlack(postData, webhook);
}

// snsMessage는 이전 포스팅 값들이 담겨 있는데, 참고해보자.


// 3. buildSlackMessage(위 jane_bot2에서 출력한 snsMessage를 받아와서 각각 처리한다.)
exports.buildSlackMessage = (data) => {
    const newState = statusColorsAndMessage[data.NewStateValue];  // 위 jane_bot2 기준 ALARM
    const oldState = statusColorsAndMessage[data.OldStateValue];     // 위 jane_bot2 기준 OK
    const executeTime = exports.toYyyymmddhhmmss(data.StateChangeTime); // 2022-05-23T03:16:02.297+0000
    const description = data.NewStateReason;  // 기존 코드엔 description, cause가 둘 다 있지만 나는 description에 대체했다.
    return {
        attachments: [
            {
                title: `[${data.AlarmName}]`,
                color: newState.color,
                fields: [
                    {
                        title: 'Timestamp',
                        value: executeTime
                    },
                    {
                        title: 'Alarm',
                        value: description
                    },
                    {
                        title: 'Previous Status',
                        value: oldState.message,
                        short: true
                    },
                    {
                        title: 'Current Status',
                        value: `*${newState.message}*`,
                        short: true
                    },
                    {
                        title: 'Link',
                        value: exports.createLink(data)
                    }
                ]
            }
        ]
    }
}

// CloudWatch 알람 바로 가기 링크
exports.createLink = (data) => {
    return `https://console.aws.amazon.com/cloudwatch/home?region=${exports.exportRegionCode(data.AlarmArn)}#alarm:alarmFilter=ANY;name=${encodeURIComponent(data.AlarmName)}`;
}

exports.exportRegionCode = (arn) => {
    return  arn.replace("arn:aws:cloudwatch:", "").split(":")[0];
}


// 타임존 UTC -> KST (2022-05-23T03:16:02.297+0000 --> 2022-05-23 13:14:48)
exports.toYyyymmddhhmmss = (timeString) => {

    if(!timeString){
        return '';
    }

    const kstDate = new Date(new Date(timeString).getTime() + 32400000);

    function pad2(n) { return n < 10 ? '0' + n : n }

    return kstDate.getFullYear().toString()
        + '-'+ pad2(kstDate.getMonth() + 1)
        + '-'+ pad2(kstDate.getDate())
        + ' '+ pad2(kstDate.getHours())
        + ':'+ pad2(kstDate.getMinutes())
        + ':'+ pad2(kstDate.getSeconds());
}  

exports.postSlack = async (message, slackUrl) => {
    return await request(exports.options(slackUrl), message);
}

exports.options = (slackUrl) => {
    const {host, pathname} = new URL(slackUrl);
    return {
        hostname: host,
        path: pathname,
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
    };
}

function request(options, data) {

    return new Promise((resolve, reject) => {
        const req = https.request(options, (res) => {
            res.setEncoding('utf8');
            let responseBody = '';

            res.on('data', (chunk) => {
                responseBody += chunk;
            });

            res.on('end', () => {
                resolve(responseBody);
            });
        });

        req.on('error', (err) => {
            console.error(err);
            reject(err);
        });

        req.write(JSON.stringify(data));
        req.end();
    });
}

 

완성!

반응형
반응형

Cloudwatch에서 알람 조건을 만들어서, 해당 알람이 발생할 때 slack으로 notify하는 환경을 만들어보자.

 

 

1. AWS > CloudWatch > 경보 생성

1) 지표 선택

 

2) 지표에서 원하는 tracking값 및 임계치 선택 (알람 발생을 위해 임계값은 1로 설정)

 

3) SNS 연동 (이전 포스팅에서 만든 jane-test-sns2)

 - 이전 포스팅: https://countrymouse.tistory.com/entry/awsslack

 

[AWS] Lambda와 slack 연동하기 (Nodejs)

1. slack에서 app을 생성한다.  1) slack에 접속하여 메뉴 중 앱 > 앱 디렉터리를 클릭하면 된다. https://api.slack.com/apps?new_app=1 2) 그럼 아래 창이 나오는데, 오른쪽 상단의 '구축'을 누르면 된다. 3)..

countrymouse.tistory.com

+ 여기서 알림을 추가하고, 정상 상태에서도 알람이 발생하도록 정상 알림도 추가한다.

 

 

4) 이름 설정 후 미리보기, 경보 생성

5) 경보가 생성되었음. 데이터가 5분 주기므로 기다려보기.

 

 

2. SNS 앱 확인

 : 아까 cloudwatch에서 연동해둔 SNS(jane-test-sns2)를 보니 lambda가 구독되어 있다.

그렇다면, cloudwatch에 알람이 발생하면, SNS를 통해, Lambda가 트리거 될 것이다.

 

3. lambda의 index.json 코드

cloudwatch를 통해 event를 받을 때 어떤 값들이 수신되는지 확인해봤다. // console.log(message)

exports.handler = async (event, context) => {
    //console.log('Received event:', JSON.stringify(event, null, 2));
    const message = event.Records[0].Sns.Message;
    console.log('From SNS:', message);
    return message;
};

 

4. Slack

 (jane_bot2 is testing은 무시하시길... 테스트 했던 console log다.)

그럼 예상했던 대로, cloudwatch에서 생성한 알람이 발생할 때마다 SNS를 호출시키고, 그게 lambda를 호출시켜서, slack으로 온다.

EC2 -> Cloudwatch -> SNS -> Lambda -> slack 구조다.

 

그럼 다음 포스팅에서는 이 text들을 예쁘게 만들어보기로 한다. (삽질 엄청했다....)

반응형
반응형

1. slack에서 app을 생성한다.

 1) slack에 접속하여 메뉴 중 앱 > 앱 디렉터리를 클릭하면 된다.

https://api.slack.com/apps?new_app=1

 

 

2) 그럼 아래 창이 나오는데, 오른쪽 상단의 '구축'을 누르면 된다.

 

 

3) Create an app을 클릭한다.

 

 

4) From scratch 후 이름 및 workspace 생성

 

5) 기능추가: Incoming Webhooks 클릭.

 

6) Activate Incoming Webhooks을 On 설정한 후, 아래에 있는 Webhook URI에 워크스페이스 추가를 클릭한다.

 

 

7) 이 app이 동작될 채널을 선택한다.

 

8) 그럼 이렇게 webhook URL이 생겼고, 이건 이따가 index.js에서 사용한다.

 

9) jane_bot2가 #clone-prision에 초대되었다.

 

 

2. 자 다음, AWS로 이동한다.

1) Amazon SNS > 주제 > 주제생성

설정에서는 표준선택 및 이름 외 별도 설정할 게 없고, lambda에서 설정한다.

 

 

2) blueprint로 sns를 검색해서 lambda를 생성한다.

 

3) 아까 생성한 sns를 여기서 선택해준다. (jane-test-sns2) 

그리고 함수 생성.

 

4) 함수를 생성하면 이와 같이 출력되는데, 코드는 로컬에서 작성 후 zip파일으로 압축 해 업로드 해준다. 

코드 수정 전

 

 

5) 로컬에서 생성한 코드를 zip으로 압축해 업로드 했다.

slack-node를 설치해야하기 때문에 node_modules까지 가져와야 한다.

webhookUri는 아까 1 -> 8)에 있었던 Webhook URI를 그대로 복붙해주면 된다.

 

6) Test를 클릭하면 아까 설정한 워크스페이스 > 채널로 jane_bot2가 동작한다 :)

반응형
반응형

1. Trigger를 S3로 설정한 lambda를 만든다.

   (S3는 미리 만들어놔야 함)

   

1) Lambda > 함수생성 > 블루프린트 사용(aws에서 제공하는 템플릿) > s3 검색 > nodejs의 경우 s3-get-object

 

 2) 구성 누른 후 나머지 설정은 기존 사용하던 값으로 설정,

     S3 트리거에서 버킷을 만들어놓은 버킷으로 설정 + 이벤트 유형: 모든 객체 생성 이벤트

     // 이렇게 하면, 모든 객체 생성 이벤트(생성삭제수정 등)가 일어날 때마다 lambda 함수가 호출된다.

 

3) 만들어진 람다

 

2. index.js 코드

const aws = require('aws-sdk');
const fs = require('fs');
var s3 = new aws.S3({ apiVersion: '2006-03-01' });

exports.handler = async(event, context,  callback) => {
    const bucket = event.Records[0].s3.bucket.name;
    const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
    const params = {
        Bucket: bucket,
        Key: key,
    };

// json 파일을 읽어와서 json 형태로 출력
    var theObject = await s3.getObject(params).promise();
    const data = JSON.parse(theObject.Body);
    console.log(data);
   // console.log(theObject.Body.toString('utf8'));  // 보기 예쁜 형태로
        

 

 // S3에서 이벤트가 발생할 때마다 로그에 찍어줄 값.

  try {
        const { ContentType } = await s3.getObject(params).promise();
        console.log('CONTENT TYPE:', ContentType);
        console.log('********** Event generated by S3 ************* ');
        return ContentType;
        
    } catch (err) {
        console.log(err);
        const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
        console.log(message);
        throw new Error(message);
    }
};

 

3. 람다의 테스트에서 awsRegion, bucket-name, arn, key를 바꾸어주어야 정상 테스팅됨.

람다 테스트

      "awsRegion": “ap-northeast-2",

      "s3": {

        "s3SchemaVersion": "1.0",

        "configurationId": "testConfigRule",

        "bucket": {

          "name": "jane-bkt”,

          "ownerIdentity": {

            "principalId": "EXAMPLE"

          },

          "arn": "arn:aws:s3:::jane-bkt"

        },

        "object": {

          "key": "s3test.json",

          "size": 1024,

          "eTag": "0123456789abcdef0123456789abcdef",

          "sequencer": "0A1B2C3D4E5F678901"

        }

 

 

4. 테스팅 결과

1) json 파일이 예쁘게 나온다.

2) S3의 해당 버킷에 새로운 파일을 업로드할 경우, 람다가 실행되어 Cloudwatch에서 로그를 확인할 수도 있다.

 

반응형

+ Recent posts