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

AWS ECR

Server/AWS 2018. 8. 15. 00:33

ECS 를 시작하기 전에 가장 먼저 어플리케이션을 이미지로 만들어 ECR(Elastic Container Registry) 에 등록을 해 보자. ECR 에 이미지를 등록하는 것은 ECS 와 연계되는 부분이 거의 없으므로 ECS 를 몰라도 상관없다. 이미지 등록에만 집중하자.

 

ECS 를 몰라도 상관없다고 말했지만, 꼭 집고 넘어가야 할게 있다. ㅜ ECS 를 사용할 때 사용자가 선택할 수 있는 두 가지 선택지가 있다. 하나는 인스턴스로서 EC2 를 사용할지 Fargate 를 사용할지이고 (이를 시작 유형이라고 함), 또 하나는 Docker Registry 를 공개용(public) 으로 구성할지 비공개용(private) 으로 구성할지 이다. Fargate 라는 것은 컨테이너를 위한 EC2 등의 인스턴스를 필요로 하지 않고 컨테이너 자체를 배포하는 아마존의 기술이다. 지금은 몰라도 된다. 하지만 알고 싶다면... EC2 에서 돌아가던 것이 EC2 없이도 어디선가 돌아간다 라고 생각하면 쉽다; 그만큼 EC2 등의 인스턴스를 관리하는 노력이 줄어드니까 더 좋다고도 볼 수 있다. EC2 를 컨트롤 하는 것 처럼 정밀한 제어는 힘들겠지만. 아무튼 좋아보이니 비싸기도 하다. EC2 시작 유형을 사용해보면 Fargate 설정은 훨씬 더 쉬우므로 EC2 시작 유형 기반으로 설명할 것이다. 아마도 대부분이 실전에서는 private 저장소를 사용하게 될텐데, 혹시라도 public 저장소를 사용하게 되면 EC2 인스턴스 유형을 사용할 수 없다. 즉 EC2 인스턴스 유형은 private 저장소만 지원한다. 이를 유념하도록 하고... ECS 에서 Docker Registry 는 ECR 말고도 아마 거의 다 지원할 것이다. Docker Hub, self-hosted registry 등...

 

여기서는 아마존 패밀리인 ECR 을 사용해 보도록 하겠다.

 

 

1. Docker 이미지 생성

 

docker 이미지를 생성하려면 Docker 를 설치하고 데몬을 실행시켜 docker cli 를 사용할 수 있어야 한다. (여기까지는 알아서 잘 해보자 ㅜ)

그리고 이미지 설정 파일인 dockerfile 을 만들어 필요에 맞게 구성한다.

나는 다음과 같이 tomcat 에서 구동하는 war 파일에 ssl 통신이 가능하도록 이미지화 하는 dockerfile 을 만들었다. (이것도 본인 필요에 맞게 알아서 잘 해보자;)

 

$ vi dockerfile
FROM tomcat:8.0-jre8-alpine
RUN ["rm""-rf""/usr/local/tomcat/webapps/ROOT"]
COPY ["./keystore""./server.xml""./web.xml""/usr/local/tomcat/conf/"]
COPY ./build/libs/WEB-0.0.1-SNAPSHOT.war /usr/local/tomcat/webapps/ROOT.war
cs

 

dockerfile 기반으로 hello-world 라는 이미지를 생성하고 확인한다.

 

$ docker build -t hello-world .
$ docker images --filter reference=hello-world
$ docker run -p 8080:8080 hello-world
cs

 

해당 포트의 반응이 없을 경우, 서버나 VirtualBox VM 에서 컨테이너 포트에 인바운드 트래픽이 허용되어 있는지 체크한다. 

 

 

2. ECR 에 저장소 생성

 

이미지가 정상적으로 생성되었다면, AWS Docker Registry 인 ECR 에 푸시를 해보자.

그 전에 ECR 에 이미지를 푸시하기 위해서는 AWS cli 가 반드시 필요하다. 로그인 및 푸시 명령이 AWS cli 으로만 가능하다. 알아서 cli 를 설치한다. ㅜ

먼저 콘솔이나 cli 로 ECR 에 특정 이름의 저장소를 생성한다.

cli 를 사용할 때는 root 계정을 사용하지 말고 ECS 용 IAM 계정을 새로 생성하고 profile 에 등록하는 편이 낫다. 해당 key 로 profile 에 자격증명 및 리전 등록하는 것은 생략.

 

$ aws ecr create-repository --repository-name hello-world-repo
{
    "repository": {
        "registryId": "aws_account_id",
        "repositoryName": "hello-world-repo",
        "repositoryArn": "arn:aws:ecr:us-east-1:aws_account_id:repository/hello-world-repo",
        "createdAt": 1505337806.0,
        "repositoryUri": "aws_account_id.dkr.ecr.us-east-1.amazonaws.com/hello-world-repo"
    }
}
cs

 

콘솔을 이용하던 cli 를 이용하던 저장소를 생성하고 나면 이미지를 푸시할 주소인 repositoryUri 를 확인할 수 있다.

repositoryUri 에는 12 자리 숫자의 aws_account_id, 리전, 저장소 이름이 포함되어 있다.

 

 

3. ECR 로 이미지 푸시

 

저장소를 생성했으면 이미지를 푸시하면 되는데, 그러기 위해서는 푸시할 이미지를 repositoryUri 값으로 태그 지정해야 한다.

 

$ docker tag hello-world aws_account_id.dkr.ecr.us-east-1.amazonaws.com/hello-world-repo
cs

 

태그 지정을 마쳤으면 푸시를 하기 전에 ECR 에 로그인 과정을 거쳐야 한다.(참 번거롭다.ㅜ)

 

$ aws ecr get-login --no-include-email

// aws cli v2+
$ aws ecr get-login-password --region xxxx (--profile xxx) | docker login --username AWS --password-stdin xxx(accountId).dkr.ecr.xxx(region).amazonaws.com
cs

 

위 명령을 입력하면 로그인에 필요한 명령어를 포함한 12시간 짜리 토큰이 발급된다.

 

docker login -u AWS -p ...base64 encoding token...very...long...  https://aws_account_id.dkr.ecr.us-east-1.amazonaws.com
cs

 

이와 같은 형태인데 이 부분을 그대로 복붙했다가는 프로세스 목록(ps) 에 토큰이 다 노출되게 되므로 패스워드 옵션(-p) 전까지만 입력하고 대화형 방식으로 토큰을 입력하던지 eval 명령을 사용한다.

 

$ eval $(aws ecr get-login --no-include-email)
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
cs

 

마지막으로 repositoryUri 태그가 달린 이미지를 푸시한다.

 

$ docker push aws_account_id.dkr.ecr.us-east-1.amazonaws.com/hello-world
cs

 

ECS - Repositories 에서 푸시된 이미지 확인.

 

 

나중에 어떤 식으로든 자동화를 해야겠지만 일단 이렇게 번거로운 과정을 거치면 비로소 ECR 에 이미지를 푸시할 수 있게 된다. 수정된 이미지를 다시 푸시할 경우에 토큰이 만료됐다면 위 로그인 과정을 다시 거쳐야 한다.

그럭저럭 쓸만함...

 

 


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

,

Amazon ECS

Server/AWS 2018. 8. 13. 19:50

Amazon Elastic Container Service(ECS) 는 클러스터에서 도커 컨테이너를 손쉽게 실행, 중지 및 관리할 수 있게 해주는 컨테이너 관리 서비스이다.

도커 이미지로 Auto scaling, LB, EC2 등과 통합하여 서비스 하고자 할 때 좋은 선택이 될 수 있으며, 무중단 배포가 간편하다는 가장 큰 장점이 있다.





위 그림은 ECS 의 전반적인 아키텍처를 나타낸 것이다.

요점은 배포할 어플리케이션을 이미지 저장소로부터 가져와서 원하는 수 만큼의 인스턴스(EC2 등) 에 배포한다는 것이다.

Docker 의 Cluster, Stack, Service, Task 등과 거의 같은 기능들을 하지만, 비슷하면서도 다르다... ㅡ.ㅡ;


다시 어플리케이션을 ECS 를 통화 배포하는 세분화된 단계를 보자면,


1. 배포할 어플리케이션을 docker 이미지로 생성한다.

2. 해당 이미지를 어디서든 가져올 수 있도록 docker 레지스트리(ECR, docker hub 등) 에 등록한다.


여기까지는 주로 docker 에 관련된 내용이다. docker 레지스트리는 docker 이미지를 버전관리 할 수 있으며, 버전관리 측면에서 github 와 비슷한 기능을 한다.


3. ECS 의 최상위 리소스인 cluster 를 생성한다. 이 때 VPC 설정으로 네트워크의 영역을 정의하며, 사용할 인스턴스 타입/사양 등을 선택한다.

4. 가장 중요한 task 정의를 생성한다. 이 정의에는 사용할 이미지, 포트, 컨테이너 사양 등을 정의한다.

5. 특정 cluster 에서 task 를 효율적으로 관리할 service 를 생성한다. 이 service 구성에는 실행할 task 정의, 실행할 인스턴스 수, LB, Auto Scaling 등을 설정할 수 있다.


여기까지는 일반적으로 EC2 를 생성할 때 구성했었던 VPC, Subnet, Secure group, Key-pair, LB, Auto scaling 과 ECS 를 구성하는 Cluster, Service, Task 등을 설정했다. Cluster - Service - Task 의 상관 관계가 조금 복잡해 보일 수 있는데,


하나의 Cluster 에는 하나 이상의 Service 를 생성할 수 있으며, 생성된 Service 는 해당 Cluster 에서만 사용된다.

하나의 Service 에는 하나의 task 및 인스턴스 수를 관리할 수 있다.

생성된 Task 정의는 하나 이상의 Cluster 또는 하나 이상의 Service 에서 실행될 수 있다.


ECS 의 완성은 Cluster 에서 Task 정의를 실행하는 것이다. 이것이 곧 배포이다. task 정의는 Service 없이도 Cluster 에서 직접 실행 시킬 수 있지만, Service 를 생성하므로써 더 효율적으로 task 를 관리할 수 있다. LB, Auto scaling, 순차 배포 등. 많은 사용자들이 도커 이미지로 Auto scaling, LB, EC2 등과 통합하여 무중단 배포로 서비스 하기 위해 이 ECS 를 선택하게 될 것이다.




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

,

Jenkins vs ECS

Server/AWS 2018. 8. 12. 02:40



Jenkins 가 지속적 통합(CI), 즉 빌드/테스트 및 배포 자동화 도구라고 할 때, ECS 는 Docker 컨테이너를 실행 및 관리하는 AWS 서비스라고 할 수 있다. 이 설명만으로 볼 때 이 둘이 비교가 가능한건지... 비교할 수는 없겠지만 단지 배포 자동화를 중점으로 간략하게 비교해 보고자 한다. 전 세계에서 대부분의 개발자들이 필요로 하고 사용하는 전문적인 서비스들이지만, 나에겐 그저 자동화라는 가면을 쓴 골치아픈 녀석들 일 뿐.


Jenkins 는 배포가 빠르고 간편하다. 소스 저장소에 push 하거나, 목록에서 배포할 서버를 찾아 버튼을 클릭하는 것 만으로 배포를 완료할 수 있다. 사실 서버도 적고 Release 후에 유지보수가 거의 필요없다면 굳이 이런 CI 툴 등은 필요하지 않을 것이다. 공부하고 설치하고 세팅하고 테스트하고 관리비용 내고... 근데 정작 배포할 일은 거의 없고... 그렇다면 그냥 FTP 로 올리는게 여러가지로 맘이 편할지 모른다. 난 처음 Jenkins 를 설치하고 서버별로 각종 세팅을 하는데에 적지 않은 시간을 할애하면서, 이게 자동화인가... 라는 생각을 했다. 다 만들어놨을 때나 자동화지, 자동화를 위해 흘려야 할 피, 땀, 눈물이... 힘들었다. ㅋㅋ 하지만 이렇게 CI 툴을 하나 익혀놓으면 다른 비슷한 툴들도 쉽게 접근할 수 있다. 방식은 거의가 똑같다.


Jenkins 의 단점을 세가지 정도로 쥐어 짜봤다.


  • 하나는 오토 스케일링. 오토 스케일링이 필요하지 않는 서버라면 상관없겠지만... 늘어난 서버를 수대로, 또 수동으로 세팅해 줘야 한다는건 오토 스케일링이 필요한 사람들에게는 꽤나 번거로운 문제.
  • 또 하나는 복원. 나는 주로 태그로 복원하는 편인데, 롤백할 때마다 설정에 태그 붙였다 뗏다 하는 것도 번거로움. (쥐어짠 티가 남;)
  • 마지막으로 무중단 배포. 이건, 글쎄... 불가능 한건 아니지만 수동적인 무중단 배포(?) 라고 설명하면 되려나.


그렇다면 ECS 가 Jenkins 의 이러한 단점들을 극복해 줄 수 있을까. ECS 는 결론만 말하자면 가능하다. 간단하게 오토 스케일링 및 관리가 가능하고, 이전 버전으로의 복구는 가능은 하지만 그닥 편하다고는 볼 수 없다. 그리고 무중단 배포도 가능하다. 서버 수를 원하는대로 늘였다 줄였다 무중단 연속 배포하는... 이 정도면 배포에 있어서는 거의 완벽하다고 볼 수 있다. 


하지만 안타깝게도 ECS 도 단점이 있다. 기능상의 단점이 아닌 사용자의 능력에 따른 자동화라고 해야 하나. ECS 배포 자동화를 위해 알아야 할 것들이 꽤 많은 편이다. 어느 정도 AWS 나 배포 바닥(?) 을 모르는 초보자라면 이것 저것 시간을 꽤 할애해야 한다. Jenkins 는 사실 Jenkins 만 설치하고 약간의 메뉴얼만 보면 쉽게 따라할 수 있다. ECS 는 Docker 기반이다보니 최소 배포할 이미지는 만들 줄 알아야 한다. 또 이미지 저장소인 ECR 에 이미지를 올리기 위해서는 AWS-Cli 를 사용해야만 한다. 그리고 ECS 를 공부해야 한다. cluster-service-task 를 숙지하고 업데이트/복구 배포 전략을 세워야 한다. 쓰고 보니 크게 공부를 하지 않아도 될 거 같은...; Jenkins 는 구성을 크게 달리할 여지가 별로 없고 인터넷만 조금 뒤져보면 원하는 답을 금방 얻을 수 있지만, ECS 는 운용에 있어 아직 사례들이 부족한 편이라 사용자들이 각자의 환경에 맞게 충분히 헤딩을 해보면서 준비해야 한다. 예를 들자면 이미지 업로드를 어떻게 자동화 할 것인지, 이미지가 업데이트 되었을 때 배포는 어떻게 자동화 시킬 것인지 등이다.



정리하자면 이렇다.


무중단배포, 오토 스케일링이 필요 없다면 그냥 알아서... 해당 사항 없음.

서버 수가 변동될 일이 별로 없고, 업데이트가 잦고, 무중단배포(수동) 가 필요하면 Jenkisn.

지금의 Jenkins 운용에 만족한다면 그냥 Jenkins.

서버 수가 급변하고, 업데이트가 잦고, 무중단배포(자동) 이 필요하다면 ECS.

AWS 에 친숙하고 자동 배포의 끝판왕을 만들고 싶다면 ECS. (얼마나 완벽한 자동화를 만드느냐는 사용자의 몫...)




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

,

Tomcat 80 to 443 port

Server/AWS 2018. 8. 8. 12:42

미션. http://mydomain.com -> https://mydomain.com


간만에 톰캣 단독 서버를 만들면서 포트 포워딩에 대한 노가다를 해보았다.

톰캣은 기본적으로 8080 포트와 8443(SSL) 포트를 사용하기 때문에 대부분의 경우 80 포트나 443 포트로 변경하기를 원할 것이다.

도커 등의 각종 컨테이너 서비스를 사용하면 포트 걱정할 일은 없지만, 포트 포워딩이 아닌 포트 변경이 가능한 방법을 찾아봤다.


> server.xml 


<Connector port="8080" protocol="HTTP/1.1" ... redirectPort="8443" ...
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" ...
cs


톰캣이 실행중일 때 netstat 로 listen 중인 포트를 확인해 보면 8080, 8443 포트가 열려 있는 것을 확인할 수 있다.

server.xml 파일에 설정되어 있는 포트 때문인데, 이 포트들을 원하는 포트로 변경한다고 해서 모두 동작하지는 않는다.

1024 이하의 TCP/UDP 포트(well-known) 로 변경하려 할 경우 root 권한을 필요로 하기 때문에 기본 세팅으로는 well-known 포트로 변경 할 수 없다.

(이를 가능하게 하는 것이 authbind 이다.)


이러한 이유로 우리는 tomcat 유저로 톰캣을 실행시킬 경우 포트를 80 이나 443 등으로 바꾸려는 무모한 짓으로 시간을 낭비하지 말아야 한다.

이를 확인하려면 tomcat8.conf 파일의 TOMCAT_USER 를 root 로 설정하면 server.xml 에 설정한 대로 포트가 변경되는 것을 확인할 수 있다.

하지만 운용시 생성되는 모든 파일, 배포 디렉토리 및 log 파일까지 모두 root 로 설정되기 때문에 일반 유저로는 접근할 수 없어 좋은 방법이 될 수 없다.

그 어떤 서비스도 해당 그룹과 권한을 설정하여 사용하지, root 로 실행하라고 권하는 서비스는 없다.


결국 깔끔한 방법은 포트 포워딩이다.



80->8080, 443->8443 포트 포워딩


$ sudo vi /etc/init.d/iptables 
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8443
 
$ sudo /etc/init.d/iptables restart
cs


이렇게 iptables 로 포트 포워딩을 하면 80 과 443 을 사용할 수 있다.


http://mydomain.com (80)   -> http://mydomain.com (8080)

https://mydomain.com (443) -> https://mydomain.com (8443)


iptables 대신 firewalld 를 사용할 수도 있다.


$ sudo firewall-cmd --zone=public --add-forward-port=port=80:proto=tcp:toport=8080 --permanent
$ sudo firewall-cmd --zone=public --add-forward-port=port=443:proto=tcp:toport=8443 --permanent $ sudo firewall-cmd --reload
cs



80->443 포트 포워딩


이 상태에서 80 포트으로 접속했을 때 무조건 443 포트로 포워딩하려면 web.xml 파일을 수정한다.


$ sudo /etc/tomcat8/web.xml
      ...
      <security-constraint>
            <web-resource-collection>
                  <web-resource-name>Automatic SSL Forward</web-resource-name>
                  <url-pattern>/*</url-pattern>
            </web-resource-collection>
            <user-data-constraint>
                  <transport-guarantee>
                        CONFIDENTIAL
                  </transport-guarantee>
            </user-data-constraint>
      </security-constraint>
 
</web-app>
cs



http://mydomain.com -> https://mydomain.com:8443


여기서 server.xml 파일의 redirectPort 를 443 으로 바꿔주면,


http://mydomain.com -> https://mydomain.com


firewalld 를 사용할 때는 http 접속시 https 로 자동변경 되지 않아 server.xml 파일에 추가 설정이 필요했다.


<Connector port="8080" redirectPort="443" ... />
<Connector port="8443" proxyPort="443" ... />
cs



8443 포트 막기


마지막으로 https://mydomain.com:8443 같은 식의 8443 포트로 직접 접근을 막기 위해 iptables 를 한번 더 수정한다.


$ sudo vi /etc/init.d/iptables 
iptables -A PREROUTING -t mangle -p tcp --dport 8443 -j DROP
 
$ sudo /etc/init.d/iptables restart
cs




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

,

Multiple credentials

Server/AWS 2018. 7. 27. 00:11

IAM 에서 사용자에게 모든 role 을 부여하지 않고 필요에 맞게 사용자를 추가하여 role 을 부여했다면, cli 사용시 여러 사용자의 자격 증명을 로컬 파일에 저장하고 서비스에 맞게 자격 증명을 선택하여 사용할 수도 있다. 여러 자격 증명의 구분을 프로필 이름으로 할 수 있도록 프로필 이름을 명시한다.



Named profiles


~/.aws/credentials
 
[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
 
[user2]
aws_access_key_id=AKIAI44QH8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
 
~/.aws/config
 
[default]
region=us-west-2
output=json
 
[profile user2]
region=us-east-1
output=text
cs


보다시피 credentials 파일과 config 파일의 [profile name] 형식이 다름에 유의 한다.

이렇게 수동으로 작성해도 되고, aws configure 명령을 사용하여 profile 을 추가해도 된다.


$ aws configure --profile user2
AWS Access Key ID [None]: AKIAI44QH8DHBEXAMPLE
AWS Secret Access Key [None]: je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
Default region name [None]: us-east-1
Default output format [None]: text
cs


이렇게 여러 자격 증명이 등록되었다면 실제 명령에 --profile user2 라고 추가하면 되고,

계속해서 해당 프로필을 사용한다면 아래처럼 환경 변수로 등록할 수 있다.


$ export AWS_PROFILE=user2
cs


현재 자격 증명 확인


$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                    user2           manual    --profile
access_key     ****************MPLE shared-credentials-file
secret_key     ****************EKEY shared-credentials-file
    region                us-east-1      config-file    ~/.aws/config
cs




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

,