'Server/AWS'에 해당하는 글 49건

CloudFront

Server/AWS 2019. 8. 20. 18:43



CloudFront 는 .html, .css, .js 및 이미지 파일과 같은 정적 및 동적 웹 콘텐츠를 사용자에게 더 빨리 배포하도록 지원하는 AWS 의 CDN 서비스이다. 전 세계 주요지역에 CloudFront POP(엣지 로케이션) 이 위치하고 있어 해당 캐시 서버에서 오리진(EC2 인스턴스나 ELB, S3 버킷 등) 의 파일을 받아 클라이언트에게 빠르게 응답하는 기능을 한다. 캐시 서버는 오리진(origin)으로부터 파일을 캐시하고 나면 해당 파일이 수정되기 전까지는 오리진에 연결하지 않고 빠르게 클라이언트에 응답할 수 있다. 


CloudFront 는 이미지나 동영상 등의 리소스가 보관된 S3 를 오리진으로 설정하는 것이 일반적이며, 운영시 꼭 필요한 서비스 중 하나이다.



CloudFront 의 설정/배포 방법


  1. CloudFront 에 캐시할 오리진(예제에서는 S3 사용) 의 주소(test.s3.amazonaws.com) 메모.
  2. 콘솔의 CloudFront 에서 [Create Distribution] 으로 배포 설정.
  3. Origin Domain Name 의 S3/ELB 목록에서 캐시할 오리진을 선택하고 Alternate Domain Names(CNAMEs) 에 원하는 CloudFront 도메인 설정.
  4. 나머지 설정은 버킷 접근 권한/정책, https, SSL 설정 정도... 이렇게 세팅하고 배포 생성하기를 시작하면 수분안에 각 캐시 서버에 오리진이 배포된다.


CloudFront 배포 도메인은 http://aabbccdd112233.cloudfront.net 형식이며 설정한 CNAME 으로 대체할 수 있다. 브라우저에서 해당 리소스의 헤더에서 X-Cache: Hit from cloudfront 가 확인되면 정상적으로 캐시되고 있는 것이다. 캐시 유지 시간이 지나서 CloudFront가 오리진에 접속하여 파일을 가져왔을 때에는 Miss from cloudfront 라고 표시된다.



캐시 삭제


캐시 파일은 기본적으로 24시간 동안 유효하며, 특정 파일을 즉시 갱신해야 할 경우 콘솔 등에서 무효화(Invalidation) 요청을 통해 캐시된 파일을 삭제시킬 수 있다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Amazon EKS

Server/AWS 2019. 5. 18. 00:56


Amazon EKS 는 AWS 에서 Kubernetes 를 손쉽게 실행하도록 하는 관리형 서비스이다. EKS 는 여러 가용 영역에서 Kubernetes 제어 플레인 인스턴스를 실행하고 관리하여 고가용성을 보장한다. 또한 오픈 소스 Kubernetes 소프트웨어의 최신 버전을 실행하므로 Kubernetes 의 모든 기존 플러그인과 도구를 사용할 수 있다. EKS 는 ECR, ELB, IAM, VPC 등의 AWS 서비스와도 통합되어 확장성과 보안을 제공한다. 아래는 EKS 를 사용하여 어플리케이션을 배포하는 일련의 플로우이다.


  1. 클러스터의 VPC / IAM / Security Groups 생성
  2. 로컬에 AWS CLI / kubectl / IAM Authenticator 설치
  3. EKS 클러스터 생성
  4. kubeconfig 파일 생성 / 설정
  5. Node 생성 및 클러스터에 등록
  6. kubectl 로 클러스터와 통신
  7. EKS 클러스터에 어플리케이션 배포 및 관리


우선 EKS 는 EC2 등으로 쿠버네티스 마스터 노드를 따로 띄우지 않고 AWS 에서 관리해 준다. 물론 유료지만 마스터 노드 설정이 따로 필요 없고 단지 클러스터만 생성하면 된다. 그럼에도 불구하고 추가로 해야할 일이 꽤나 많은 것처럼 보여진다. 하지만 살펴보면 기존 EC2 같은 컴퓨팅에도 사용했던 것들이니 혼란스러울 것은 없다. Hello EKS 를 만들어보기 전에 일단 EKS 가 어떻게 돌아가는지를 위 플로우와 함께 설명해 보려 한다.


먼저 클러스터를 생성할 때 지정해야 할 항목들로 VPC, SG(Security Group), IAM 이 있다. 그렇기 때문에 미리 생성해 놓아야 한다. VPC 와 SG 는 원하는 구성이 있다면 미리 생성하여 사용해도 좋고, aws 에서 샘플로 제공하는 기본 사양을 그대로 사용하거나 수정하여 사용할 수 있다. 일반적으로 EKS 의 VPC 구성은 public 서브넷에 마스터 노드, private 서브넷에 워커 노드를 배치하는 형태를 가진다. 또한 클러스터의 제어 플레인에 리소스 권한을 부여하기 위해 IAM role 을 미리 생성해 놓고 클러스터 생성시 지정해야 한다. 일단 이렇게 하면 클러스터 및 제어 플레인이 생성된다. 그리고 바로 제어 플레인 사용 과금이 시작된다.^^ 여기까지가 1,3번 과정.


이제 노드를 추가해보자. EKS 콘솔에 들어가보면 알겠지만 관련 메뉴가 [클러스터 리스트] 하나 달랑 있다. EKS 콘솔에서 할 수 있는건 클러스터 생성/설정까지만... EKS 에서 노드는 일반적으로 EC2를 가리킨다. 그렇다면 노드 생성은 일반적인 EC2 생성하듯 하면 될 것 같지만 그 외에도 설정해야 할게 상당히 많다. AutoScalingGroup 설정, 연결할 클러스터 세부 설정 등 꽤나 복잡하다. 하지만 AWS 에서는 CloudFormation 에서 미리 정의된 소스들을 사용하여 노드 생성/설정 및 클러스터 등록을 간편하게 할 수 있다. 클러스터 등록할 때 부터는 kubectl 을 사용하게 되는데 특정 클러스터와의 연결을 위해 IAM 인증이 필요하므로 둘다 로컬에 미리 설치해 놓도록 한다. 여기까지가 2,4,5,6번 과정.


7번 과정은 배포 방식에 따라 설정은 다르겠지만 기본적으로 어플리케이션을 컨테이너 이미지로 생성하여 업로드하고 yaml/json 파일로 deployment, service 등을 설정하여 배포할 수 있다. 그 뒤 유지보수는 대시보드 등으로...


하나마나인 설명 같기도 하고;; 다음엔 Hello EKS 를 직접 만들어보긔~




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

AWS VPC 시나리오

Server/AWS 2019. 5. 17. 11:54

AWS 에서 VPC 마법사로 생성할 수 있는 VPC 시나리오로 다음의 4가지를 제공한다.

public 서브넷만 있는 VPC

public 및 private 서브넷이 있는 VPC

public 및 private 서브넷이 있고 VPN 액세스를 제공하는 VPC

private 서브넷만 있고 VPN 액세스를 제공하는 VPC


이 4가지의 VPC 구성을 알고나면 어떤 커스텀 VPC 구성도 가능하다. 하나씩 살펴보자.



1. public 서브넷만 있는 VPC


위 그림에는 다음 정보가 포함된다.

vpc : 10.0.0.0/16

public subnet : 10.0.0.0/24

ec2 : 10.0.0.6 (EIP: 198.51.100.2)

router : 10.0.0.0/16(local), 0.0.0.0/0(igw-id)

internet gateway

ec2 가 인터넷에 오픈되어 있는 웹서비스 등에 알맞는 구성이다. 서브넷은 모두 private 형태이므로 외부와의 통신이 가능하려면 internet gateway 를 두어야 하며, 나가는 트래픽에 대하여 routing table 에 올바르게 설정해야 한다. 10.0.0.0/16(local) 은 해당 vpc 의 다른 서브넷으로의 통신을 가능하게 하며, 0.0.0.0/0(igw-id) 는 외부 모든 트래픽은 igw-id 로 보낸다는 설정이다. 외부에서 해당 서비스(EC2 등) 에 접근할 수 있도록 Public IP 주소도 연결해야 한다. Public IP 주소가 없다면 외부로부터 요청을 받을 수가 없을 것이고, router 에 igw 로의 설정이 없다면 외부로 응답이나 요청을 할 수 없을 것이다. 보안적인 측면에서 보안그룹(security group) 과 network acl 로도 ip/port 에 대하여 허용/거부를 설정할 수 있는데 network acl 은 보통 다 열어놓고 보안그룹만 이용한다. 모든 포트가 차단된 상태에서 웹서비스시 80, 443 포트로 들어오는 요청은 모두 열어주고, 22 포트는 개발자 ip 정도만 열어주는 형태를 추천한다. 이것이 일반적인 public 서브넷의 형태이다. 



2. public 및 private 서브넷이 있는 VPC


위 그림에는 다음 정보가 포함된다.

vpc : 10.0.0.0/16

public subnet : 10.0.0.0/24

private subnet : 10.0.1.0/24

ec2(web) : 10.0.0.5~7 (EIP: 198.51.100.1~3)

ec2(db) : 10.0.1.5~7

router1 : 10.0.0.0/16(local), 0.0.0.0/0(igw-id)

router2 : 10.0.0.0/16(local), 0.0.0.0/0(nat-gw-id)

internet gateway

nat gateway

프론트엔드와 백엔드로 나누어 일반적으로 웹서버만 public 서브넷에 두고 DB 는 private 서브넷에 두어, 외부에서는 웹서버와 접근 가능하게 하고 DB 는 웹서버에서만 접근 가능하게 하는 구성이다. 굳이 노출할 필요없는 백엔드를 외부와 차단시키는 것에 중점을 둔 구성이다. public/private 구분을 위해 igw(인터넷 게이트웨이) 로 향하지 않도록 router 를 하나 더 추가해야 한다. 옵션이지만 private 서브넷에서 일방적으로 외부와 통신을 해야 한다면 nat 게이트웨이를 생성하고 router 에 nat 게이트웨이로 트래픽을 보내도록 routing 을 추가한다. igw 가 public 서브넷과 외부와의 양방향 통신이 가능하게 한다면, nat 게이트웨이는 public 서브넷에 위치하면서 private 서브넷에 대하여 외부로 단방향 통신(요청/응답) 이 가능하게 하며 응답을 받을 수 있도록 public IP 할당이 필요하다. 외부에서는 여전히 nat 게이트웨이로 서브넷과 통신할 수 없다. (nat 게이트웨이는 유료) 웹서버의 보안그룹 설정은 시나리오1과 동일, DB 보안그룹 설정은 웹서버 보안그룹ID 로부터 오는 해당 DB 전용포트만 열어주면 된다. 예로 mysql 의 경우 3306 포트.



3. public 및 private 서브넷이 있고 VPN 액세스를 제공하는 VPC


위 그림에는 다음 정보가 포함된다.

vpc : 10.0.0.0/16

public subnet : 10.0.0.0/24

private subnet : 10.0.1.0/24

ec2(web) : 10.0.0.5~7 (EIP: 198.51.100.1~3)

ec2(db) : 10.0.1.5~7

router1 : 10.0.0.0/16(local), 0.0.0.0/0(igw-id)

router2 : 10.0.0.0/16(local), 0.0.0.0/0(vgw-id)

internet gateway

vpn (virtual private gateway, customer gateway)

시나리오2번과 비슷하지만 private subnet 을 외부는 여전히 차단하고 특정 네트워크(customer gateway)와만 통신할 수 있도록 하는 구성이다. vpn 이라고 하는 가상 비공개 네트워크를 구현하여 vpn 에 연결되어야만 private subnet 과의 통신이 가능하다. vpc 콘솔에서 private 서브넷과 연결할 네트워크(customer gateway) 를 ip 와 함께 지정하고 virtual private gateway 생성, 그리고 그 둘을 이어주는 Site-to-Site VPN 연결을 구성하면 된다. (vpn 도 역시 유료) 서브넷의 보안그룹 설정은 vpn 으로 연결되는 네트워크 ip 대역으로부터 필요한 포트만 열어주면 된다.



4. private 서브넷만 있고 VPN 액세스를 제공하는 VPC


위 그림에는 다음 정보가 포함된다.

vpc : 10.0.0.0/16

private subnet : 10.0.0.0/24

ec2(web) : 10.0.0.5~7 (EIP: 198.51.100.1~3)

router : 10.0.0.0/16(local), 0.0.0.0/0(vgw-id)

vpn (virtual private gateway, customer gateway)

시나리오3번에서 public 서브넷만 제외한 구성이다. public 서브넷이 없으므로 igw 도 없다. vpn 과 연결된 특정 네트워크에서만 private 서브넷과 통신이 가능하며, 외부가 차단된 구성이다보니 서비스보다는 사내 인트라넷이나 개발 서버 등이 필요할 때 사용 가능한 구성이다.


이 중에 그나마 유용하게 쓸 수 있는 것이 2번이나 3번 시나리오 이다. 내가 선호하는 구성은 소규모 웹서비스의 경우 2번과 흡사하게. 더 큰규모의 웹서비스는 3번 시나리오에서 public subnet 에는 elb 만 두고 모든 자원을 private 서브넷으로, private 서브넷은 vpn 연결로 관리하는 것이 즐겨 사용하는 시나리오 이다. ^^


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

CodeStar

Server/AWS 2018. 9. 17. 21:31

특정 프로그래밍 언어로 개발/빌드/배포 환경을 미리 구성된 템플릿을 사용하여 빠르게 구축해 주는 서비스이다. 예를 들어, Laravel 로 PHP 개발을 하려 한다면, EC2 / Git / CodeBuild / CodeDeploy / CodePipeline 등을 미리 구성해 주며 git 에 push 만 하면 자동 배포되어 결과를 확인할 수 있다. 그리고 제공되는 대시보드에서 프로젝트의 개발/빌드/배포 등의 이벤트 현황을 즉시 확인할 수 있다. 아무래도 미리 준비된 템플릿으로 빠르게 구성되는 장점은 있지만, 언어나 프레임워크의 버전, 서버종류 등의 선택이 제한적인 단점 때문에 사용할 일이 있을지는 모르겠다.





CodeStar 는...


CodeStar 는 AWS 를 기반으로 애플리케이션을 빠르게 개발, 빌드, 배포할 수 있는 클라우드 기반 서비스이다. CodeStar 프로젝트를 생성하면 이미 만들어진 CloudFormation 템플릿 중 원하는 환경의 어플리케이션을 선택할 수 있다. 사용되는 Service 들이 모두 리전 별 서비스이므로 CodeStar 역시 리전 별로 서비스한다. CodeStar 자체는 무료이므로 함께 사용하는 리소스의 요금만 발생된다.



CloudFormation 템플릿 선택사항


  • Application : Web application / Web service / Static Website / AWS Config Rule
  • Service : Elastic Beanstalk / EC2 / AWS Lambda
  • Language : Python / PHP / C# / Node.js / Ruby / Java / Go / HTML


Web application 와 Web service 의 차이라면 Web application 은 UI 나 웹페이지 기능이 많고, Web service 는 RESTful 같은 API 기능에 특화되어 있는 것 같다. 그 외에도 빌드가 트리거 될 AWS CodeCommit 나 GitHub 중 하나의 저장소를 선택해야 하고, 리소스 구성 세부 정보에서 배포될 EC2 와 VPC, Subnet 등을 설정할 수 있다.


CodeStar 에는 프로젝트, 도구 체인 및 중요 이벤트를 전체적으로 보여주는 대시보드를 제공한다. 최신 프로젝트 활동 모니터링, 코드 변경, 빌드 결과 및 배포 상태 추적 같은 작업을 타일에 추가/제거하여 대시보드를 구성할 수 있다. 프로젝트를 생성하면 팀의 소유자로 추가되며, 다른 사용자를 더 추가하고 역할을 부여하여 함께 운용할 수 있다. GitHub 리포지토리나 Atlassian JIRA 같은 AWS 외부의 리소스를 사용하는 경우, 사용자 이름 및 이메일 주소를 가진 별도의 사용자 프로필을 사용할 수 있다. 코드를 변경하고 저장소에 푸시하면, Continuous deployment 타일에 진행 중인 작업이 표시되며, CodePipeline 에서 저장소의 변경 사항으로 빌드 및 배포되어 엔드포인트에서 결과를 확인할 수 있다.


프로젝트를 삭제하면 관련 내부 리소스는 자동으로 모두 삭제된다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

ECS with gradle

Server/AWS 2018. 8. 28. 23:51

개발 중에는 Java + Gradle 프로젝트에서 결과물을 확인하기 위해, ssh 플러그인을 사용해 개발 서버에 배포하고 있다. 실서버 ECS 배포를 위해 이미지를 만들고 ECR 에 푸시하고 Task 를 배포하는 플러그인이 있나 열심히 검색해 보았으나, 음... 생각만큼 지원이 덜 되어 있는거 같아 그냥 AWS Cli 명령으로 도배했다. 난 포기했지만 생각 있으면 써보시길...


'com.bmuschko.docker-remote-api'

'com.patdouble.awsecr'


build.gradle 로 처리하려는 것들을 나열해 봤다.


  1. 인스턴스 수량 증가
  2. Docker 이미지 빌드
  3. 기존 ECR latest 이미지 태그 변경 -> backup
  4. 이미지 ECR 로 푸시
  5. 서비스 업데이트 (배포)
  6. 인스턴스 수량 감소


이 모든걸 원클릭으로 끝내버리고 싶었는데, 배포 완료 시점을 알아야 했고 그로 인한 서브 작업들이 꼴도 보기 싫어서 그만 두었다. (꽤 지긋지긋해졌다) 저 얼마되지도 않는 작업을 실행하는데 필요한 오라질 도구가 참 많다. Docker, AWS Cli, ECS-Cli, PowerShell, ... 물론 Linux 환경이라면 PowerShell 하나 정도는 줄일 수 있겠지만 그러자고 Linux 환경을 하나 더 구축하는 것 역시 오라질이다. 그리고 ECR 이미지 태그를 변경하는 것 역시 포기했다. PowerShell 에서 AWSPowerShell 을 설치해야 되는데 에러 투성이다. 포기하고 backup 은 push 를 두 번 하는 방향으로; AWS Cli 로 통합하지 못하고 AWS Cli, ECS-Cli, PowerShell 을 다 깔 수 밖에 없게끔 만들어 놓은 이유가 참으로 궁금하다. docker 가 PowerShell 을 사용한 원죄가 있긴 하지만... 그렇게 따지면 윈도우를 만든... ㅡ.ㅡ;


아무튼 내가 구축하려는 구성은 기본 인스턴스 2 대, 배포시 4 대, 배포후 다시 2 대.

Cluster, Service, Task, ECR 등은 이미 콘솔에 생성되어 있다. (구성 내용 생략)


그리하여 실행할 gradle Task 는 3 개 정도 되겠다.

1,2,3,4 번을 묶어 backup 이 어찌될지 모르니 푸시까지 하나 (createImageNpushToECR), 5 번 배포 하나(ECSDeploy), 6 번 인스턴스 감소 하나(ECSInstanceDown).


* build.gradle


ext {
    clusterName = 'clusterName'
    serviceName = 'serviceName'
    taskName = 'taskName'
    stackName = 'EC2ContainerService-now-web'
    accountId = '8707500123456'
    region = 'ap-northeast-1'
    tagName = '870750012345.dkr.ecr.ap-northeast-1.amazonaws.com/web:latest'
    instanceMinCnt = 2
    instanceMaxCnt = 4
    getInstanceCnt = 0
}
 
task createImageNpushToECR() {
    group = 'docker'
    dependsOn war
    doFirst {
        exec { commandLine 'cmd''/c''aws ecr get-login --no-include-email --profile profileName > temp.cmd' }
        exec { commandLine 'cmd''/c''call temp.cmd' }
        exec { commandLine 'cmd''/c''del temp.cmd' }
    }
    doLast {
        exec { commandLine 'cmd''/c''docker build -t '+tags+' .' }
        exec { commandLine 'docker''push', tags }
    }
}
 
task ECSDeploy {
    group = 'docker'
    doLast {
        exec { commandLine 'cmd''/c''aws ecs update-service --force-new-deployment --profile profileName --cluster ' + clusterName + '  --service ' + serviceName + ' --task-definition ' + taskName }
    }
}
 
task ECSInstanceCnt {
    group = 'docker'
    doLast {
        new ByteArrayOutputStream().withStream { cnt ->
            exec {
                commandLine 'cmd''/c''aws ecs list-container-instances --cluster ' + clusterName + ' | findstr /R /C:"[' + accountId + ']" | find /c /v ""'
                standardOutput = cnt
            }
            getInstanceCnt = cnt.toString().toInteger()
        }
        println '# Current Web Instance Cnt : ' + getInstanceCnt
    }
}
 
task ECSInstanceUp {
    group = 'docker'
    dependsOn ECSInstanceCnt
    doLast {
        if (instanceMaxCnt > getInstanceCnt) {
            exec { commandLine 'cmd''/c''aws ecs update-service --cluster ' + clusterName + '  --service ' + serviceName + ' --deployment-configuration minimumHealthyPercent=50,maximumPercent=200' }
            exec { commandLine 'cmd''/c''ecs-cli configure --cluster ' + clusterName + ' --default-launch-type EC2 --region ' + region + ' --cfn-stack-name ' + stackName + ' --config-name ' + clusterName }
            exec { commandLine 'cmd''/c''ecs-cli scale --capability-iam --size ' + instanceMaxCnt + ' --cluster ' + clusterName + ' --aws-profile profileName' }
        }
    }
}
 
task ECSInstanceDown {
    group = 'docker'
    dependsOn ECSInstanceCnt
    doLast {
        if (instanceMinCnt < getInstanceCnt) {
            exec { commandLine 'cmd''/c''aws ecs update-service --cluster ' + clusterName + '  --service ' + serviceName + ' --deployment-configuration minimumHealthyPercent=100,maximumPercent=200' }
            exec { commandLine 'cmd''/c''ecs-cli configure --cluster ' + clusterName + ' --default-launch-type EC2 --region ' + region + ' --cfn-stack-name ' +  stackName + ' --config-name ' + clusterName }
            exec { commandLine 'cmd''/c''ecs-cli scale --capability-iam --size ' + instanceMinCnt + ' --cluster ' + clusterName + ' --aws-profile profileName' }
        }
    }
}
cs


대충 이렇다. 지금 딱 필요한 만큼만 꾸역꾸역 만들어 놓긴 했는데... 맘엔 안들지만 그래도 그냥 쓸란다.

간단하게 설명하자면...

  • createImageNpushToECR : war 파일 만들고 ECR 에 로그인 후 Docker 이미지 만들고 푸시.
  • ECSDeploy : Service 업데이트로 최신 이미지(latest) 배포
  • ECSInstanceCnt : 현재 Cluster 의 인스턴스 수량 (2개 설정)
  • ECSInstanceUp : 인스턴스 증가시킬 수량인 4 개 보다 작으면 4 개로 증설
  • ECSInstanceDown : 인스턴스 감소시킬 수량인 2 개 보다 크면 2 개로 감소


ECR 로그인은 gradle 소스에 있고 ECS-Cli 자격 증명 역시 aws profile 로 통합했다. AWS Cli 를 위한 자격 증명은 잘 등록해 보자... aws configure...


명령어도 윈도우 명령어로 바꿔 넣느라 삽질 좀 했다. 후...

개발에만 집중할 수 있게 해준다더니, 빡이쳐서 개발을 할 수가 없다. 아오...




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,