무중단 서비스를 유지하면서 EKS nodegorup의 spec을 변경해야 하는 경우 적용

사전작업

  • 서비스 이중화 : 서비스의 replicas를 2 이상 설정하여 가용성울 보장한다.
  • request 값 확인 : 변경하려는 node의 spec이 서비스들의 request에 부족하지 않은지 확인한다.
  • topologySpreadConstraints 확인 : hostName으로 최대한 노드 이름 기준으로 POD가 분산 되어 뜰 수 있도록 확인한다.

Node Spec 변경

신규 노드그룹 추가

테라폼 코드를 활용하거나, EKS console에서 Add node group 메뉴를 통해 원하는 스펙의 노드그룹을 추가한다.

 

기존 노드 taint 설정

기존 노드에 taint(NoSchedule)을 설정하여 이동하려는 POD가 기존 노드 그룹에 뜨는걸 방지한다.
node_name_1은 ip-xx-xx-xx-xx.ap-northeast-2.compute.internal 과 같은 형태이다.

$ kubectl taint nodes node_name_1  key=value:NoSchedule
$ kubectl taint nodes node_name_2  key=value:NoSchedule

 

기존 노드 Drain 설정

1번 노드에 drain 설정하여 POD를 신규 노드 그룹으로 이동시킨다.

$  kubectl drain node_name_1 –ignore-daemonsets

위와 같이 local storage를 사용하는 POD를 삭제할 수 없다는 메시지가 나오는 경우 아래와 같은 옵션을 추가하여 POD를 이동시킨다.
이때 이동하는 POD의 data는 전부 삭제되기 때문에 주의해야 한다.

$  kubectl drain node_name_1 –ignore-daemonsets –delete-emptydir-data


1번 노드에서 이동한 POD들이 정상적으로 뜬걸 확인 후 2번 노드도 동일하게 작업한다.

$  kubectl drain node_name_2 –ignore-daemonsets

 

기존 노드 그룹 삭제 처리

POD 들이 완전히 이동한 걸 확인 후 기존 노드 그룹은 삭제처리한다.

EKS console 혹은 테라폼 코드를 활용한다.

참고

https://aws.amazon.com/ko/premiumsupport/knowledge-center/eks-worker-node-actions/

https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/migrate-stack.html

https://halfmoon95.tistory.com/entry/EKS-Pod-%EC%88%98-%EC%A0%9C%ED%95%9C

Ubuntu 기준

EC2에서 이중화한 서버의 경우 시간대는 KST나 UTC로 맞추었지만, date를 찍어보면 2~3분 정도 시간차이가 발생하는걸 확인할 수 있다.

이런 경우 발생한 로그를 추적하기에도 어려움이 있기 때문에 시간을 동일하게 맞추어 주는 작업이 필요하다.

Amazon Time Sync Service를 사용하면 손쉽게 적용 가능하다.

아래와 같은 명령어를 입력하여 서버에 적용하면 서버간 시간대가 초 단위까지 일치하는 것을 확인할 수 있다.

$ sudo apt update
$ sudo apt install chrony
$ sudo vi /etc/chrony/chrony.conf
 
#server나 pool 문 앞에 아래 내용 추가
server 169.254.169.123 prefer iburst minpoll 4 maxpoll 4
 
#chrony 서비스 재시작
$ sudo /etc/init.d/chrony restart
 
#동기화 확인
$ chronyc sources -v
 
#동기화 지표 확인
$ chronyc tracking



https://aws.amazon.com/ko/about-aws/whats-new/2017/11/introducing-the-amazon-time-sync-service/

https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/set-time.html

'AWS' 카테고리의 다른 글

EKS node group spec 변경  (0) 2023.01.03
postgreSQL RDS dump 뜨기(pg_dumpall)  (0) 2023.01.03
ALB + Tomcat 환경에서 client ip 로깅하기  (0) 2023.01.03
AWS Access key 종류  (0) 2023.01.03
EC2 EBS 볼륨 증설(ubuntu os)  (0) 2023.01.03

AWS에서 서비스하는 postgreSQL RDS의 경우 super user 권한을 가진 user가 없어서 pg_dumpall 를 수행할 수 없다고 공식 가이드 문서에서 확인할 수 있다.

https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/PostgreSQL.Procedural.Importing.html

하지만, 약간의 변형을 가하면, pg_dumpall 명령어를 사용할 수 있다.

기본 구성

  • postgreSQL (source DB) : dump를 뜨려는 원본 RDS
  • postgreSQL (target DB) : dump를 복원하려는 타겟 RDS
  • dump용 EC2 : postgreSQL client 버전 12 이상이 설치되어 있는 서버. source RDS와 target RDS에 접속가능해야 한다.

DUMP 수행

postgreSQL RDS는 rdsadmin 이 소유하고 있는 database가 있는데 이건 RDS 생성시 만들었던 master 계정이 권한이 없기 때문에 덤프를 뜨는게 불가능하다. postgreSQL 12버전 이상을 사용하면 특정 database를 제외하고 덤프를 뜰 수 있다.(–exclude-database 옵션)

덤프를 뜨기전, master 계정이 database에 권한을 가지고 있는지, tablespace 소유 여부를 확인한다.

# postgreSQL 접속
$ psql --host=(source RDS Endpoint) --port=(source RDS port) --username=(master 계정) --password

# db list 조회
> \l 

# 사용자 권한 조회
> \du

# table space 조회
> \db

# master 계정 소유로 table space 변경
> ALTER TABLESPACE (tablespace 명) OWNER TO (master 계정);

# master 계정에게 db 권한 부여
> GRANT (db명) TO (master 계정);

master계정에게 권한이 부여되었다면, 아래 명령어로 rdsadmin이 소유한 database는 제외하고 dump를 뜬다. –no-role-passwords 옵션을 사용하여 super_user 권한이 없는 계정으로 dump를 뜬다. 복원 후 사용자 비밀번호는 다시 지정한다.

$ pg_dumpall --no-role-passwords -f (파일명) --exclude-database=rdsadmin --exclude-database=template0 -v -h (source RDS endpoint) -U (master 계정) -p (source RDS port)

데이터 용량이 많아서 압축 덤프를 사용하는 경우의 명령어는 아래와 같다.(gzip 사용)

$ pg_dumpall --no-role-passwords --exclude-database=rdsadmin --exclude-database=template0 -v -h (source RDS endpoint) -U (master 계정) -p (source RDS port) | gzip > 파일명.gz

덤프 중 실제로 잘 덤프를 뜨고 있는지 여부에 대한 확인은 RDS의 모니터링 지표 중 connection 지표를 확인한다.

RESTORE 수행

덤프 작업이 완료 된 후 restore를 수행한다.

$ psql -h (target RDS endpoint) -U (master 계정) -p (target RDS port) < (백업 파일)

압축 덤프를 사용했던 경우에는 아래 명령어로 복원한다.

gunzip -c 파일명.gz | psql -h (target RDS endpoint) -U (master 계정) -p (target RDS port) 

복원 후 psql로 target RDS에 접속하여 사용자 비밀번호를 다시 입력한다.

# target RDS 연결
$ psql --host=(target RDS Endpoint) --port=(target RDS port) --username=(master 계정) --password

# 사용자 정보 변경
> ALTER ROLE (사용자명) WITH LOGIN;
> ALTER USER (사용자명) WITH PASSWORD '(비밀번호)';

40 GB 데이터 베이스 기준으로 dump 뜨는데 30분, restore하는데 20분이 수행되었다.

pg_dump의 경우 table space 및 사용자의 권한은 복사되지 않고, 데이터 베이스 별로 덤프를 떠서 복원해야 하기 때문에 RDS 전체 데이터를 백업해야 하는 경우에는 pg_dumpall 이 더 빠르고 정확하고 편하다.

'AWS' 카테고리의 다른 글

EKS node group spec 변경  (0) 2023.01.03
EC2 서버간 시간 동기화(Amazon Time Sync Service)  (0) 2023.01.03
ALB + Tomcat 환경에서 client ip 로깅하기  (0) 2023.01.03
AWS Access key 종류  (0) 2023.01.03
EC2 EBS 볼륨 증설(ubuntu os)  (0) 2023.01.03

tomcat 8.5.xx 버전을 사용하는 서버 환경에서 어플리케이션을 호출하는 ip를 로깅해야 할 경우가 생긴다. 기본 설정대로 하면 tomcat의 access log에 실제 클라이언트의 외부 IP가 아닌 ALB의 IP가 찍히게 된다.


아래 설정을 참고하면 ALB가 아닌 외부에 호출하는 실체 client ip가 로깅된다.

server.xml 에서 Valve 설정을 아래와 같이 수정한다.

<Valve className="org.apache.catalina.valves.AccessLogValve"
  ....(중략)
  pattern="%{X-Forwarded-For}i %l %u %t &quot;%r&quot; %s %b %{User-Agent}i"
  ....(중략)
/>

<Valve className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
remoteIpHeader="x-forwarded-for"
proxiesHeader="x-forwarded-by"
protocolHeader="x-forwarded-proto" />


Remote Ip Valve 설정을 추가할때 모든 IP에 대해 추적하기 위해 정규식을 internalProxies 에 모든 숫자에 대해서 넣었지만, 특정 IP 대역에 대해 추적하려면 해당하는 IP 정규식을 넣으면 된다.


위와 같이 설정시 ALB IP가 아닌 Client IP가 access log에 찍히게 된다.

 

aws 에서 발급하는 access key는 여러가지 종류가 있다. 보통 가장 많이 사용하게 되는 IAM 의 Security credentials에서 발급하게 되는 access key 일 것이다. 하지만 발급을 해보면 AKIA 로 시작하는것을 확인 할 수 있다.

사실 aceess key에는 여러종류가 있어서 접두어로 그 종류를 구분할 수 있다.


IAM Role로 발행한 key의 경우 ASIA로 시작하는 액세스키를 갖게 된다. codecommit을 위한 SSH 퍼블릭 키를 발행받는다면 APKA로 시작하게 된다.

혹시 Access Key로 무언가를 추적해야 할때 유용하게 쓰일 수 있다.


참고 : https://aws.amazon.com/ko/blogs/korea/aws-api-call-2-s3-pre-signed-url/

EC2 사용 중 EBS 볼륨을 증설해야 하는 경우가 있다. ubuntu os(ext 4 파일 시스템)환경에서는 아래와 같이 처리하면 된다.



현재 용량 확인하기

EC2의 Storage 탭에서 Block device의 정보를 확인한다.

현재 10G로 설정되어 있다.

EC2에 접속하여 아래 명령어를 입력하여 실제 사용 중인 용량을 확인한다.

$ df -hT

위와 같이 사용량이 95%로 증설이 필요하다는걸 확인할 수 있다.


파티션의 상태를 확인한다.

$ lsblk

파티션을 하나 사용중이고(nvme0n1p1) 파티션의 용량도 10G로 현재의 EBS 용량과 동일하게 설정되어 있다. 참고로 /snap/과 관련된 부분은 AWS 쪽에서 관리하는 것으로 신경쓰지 않아도 된다.



EBS 용량 증설 하기

EC2 storage 탭의 Volume ID를 클릭하여 EBS 서비스의 화면으로 이동한다.

증설하려는 EBS를 선택 후 Action – Modify Volume을 클릭한다.

증설하려는 용량을 입력한 후 Modify를 클릭하여 증설한다. 이제 증설한 용량(15G)을 서버 파일시스템의 파티션에 추가 해주어야한다.

서버에 접속한 후 다시 아래 명령어를 입력하여 파티션의 상태를 확인한다. 아까와는 다르게 5G 가 차이나는걸 볼 수 있다.

$ lsblk

이제 5G를 파티션에 추가해주겠다.

$ sudo growpart /dev/nvme0n1 1

다시한번 파티션의 용량을 조회하면 제대로 15G가 반영되어 있는 것을 확인할 수 있다.

$ lsblk



참고 :

https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/recognize-expanded-volume-linux.html

https://aws.amazon.com/ko/premiumsupport/knowledge-center/ebs-volume-size-increase/

S3 서비스

S3 서비스의 전체 이름은 Amazon Simple Storage Service이다. S가 세 개라서 S3로 부른다. 오브젝트 스토리지 서비스로 높은 내구성과 높은 가용성을 저렴한 가격으로 제공해주기 때문에 AWS 인프라를 사용하게 되면 로그 저장용이나 정적인 컨텐츠 보관용으로 꼭 사용하게 된다. S3의 내구성을 좀더 살펴보자면, S3가 제공하는 내구성은 99.999999999% 이다. 9개 무려 11개로 사실 이정도면 거의 서비스 다운이 없다고 보면 된다. (AWS의 모든 리전은 최소 3개의 AZ를 가지고 있는데 S3는 무조건 3개의 AZ를 전부 사용하고 있고, 물리적 복사본을 각 AZ당 2개 이상 가지고 있다.)

분산 구조라서 객체의 Create / Delete만 지원하고 Modify의 경우 overwrite(재생성)으로 진행된다. HTTP(S) 프로토콜을 사용하여 S3에 오브젝트 업로드/다운로드가 가능하다. 최종 일관성(Eventual Consistency)를 지원하기 때문에 Overwrite나 Delete의 경우 내부 복제가 완료되기까지 약간의 시간이 걸릴 수 있다.

 

 

 

 

버킷(Bucket)과 객체(Object)

S3 서비스에서 객체(Object)를 저장하기 위해서는 Bucket 이라는 걸 만들어야 한다. Bucket은 객체를 담는 바구니, 우리에게 익숙한 개념으로는 폴더라고 생각하면 된다. 다만 버킷은 Flat한 구조라서 버킷 내부적으로 하위구조(Hierachie)를 가질 수는 없지만, “/”를 구분자로 하여 논리적으로 하위구조를 가질 수 있게 해준다.(folder/object와 같은 형태)

버킷은 기본값이 private이다. public으로 열고 싶으면 S3 버킷 정책에 대해 살펴보아야 하는데 보안상 public으로 여는건 권고하지 않고 있다. 버킷명은 모든 AWS 계정, 모든 region에 걸쳐 전세계적으로 고유한 값이다. 버킷주소는 “버킷명.리전명.amazonaws.com”의 형태이다.

객체는 버킷에 저장되는 오브젝트로 최소 1Byte에서 최대 5TB까지 가능하다. 저장 가능한 객체의 갯수는 무제한이다. 역시 기본값은 private이고 객체의 주소는 고유한 형태로 버킷명+키값(오브젝트명)이다.

 

 

 

 

S3 접근 권한 없는 사용자가 private S3에 접근하기(pre-signed url 발행)

S3 버킷의 기본 정책은 private이다. public에서 접근해서 object를 다운받거나 업로드 해야 하는 경우 버킷 자체를 public으로 열기엔 부담스럽고, 그렇다고 pulblic에 있는 사용자에게 S3 접근권한을 일일히 부여하기도 번거롭다. 이럴 때 사용할 수 있는게 pre-signed url이다. S3 접근을 위한 임시 url로 일정 시간이 지나면 만료되어 public 접근이 불가능해진다.

1. S3 접근 권한이 없는 사용자가 S3 접근 권한을 가지고 있는 EC2에 HTTP(S)등의 API로 S3 접근 권한 URL을 요청한다.

2. EC2에서 S3로 pre-signed url 발행을 요청한다.

3. S3에서 pre-singed url 을 발행하여 EC2에 전달한다.

4. EC2는 url을 사용자에게 전달한다.

5. 사용자는 발행받은 url (pre-signed url)로 S3에 접근하여 업로드/다운로드를 수행한다.

 

 

 

 

실제로 어떻게 구현되는지 하나씩 살펴보겠다.

먼저 EC2에서 AWS Credential을 가지고 오는 부분은 전에 작성한 페이지로 대체한다. 요약하자면 EC2는 Role로 S3 접근권한을 가질 수 있다.

참고 링크 : https://ninano.techblogg.net/2021/07/29/ec2%ec%97%90%ec%84%9c-access-key-%ec%97%86%ec%9d%b4-role-%ed%99%9c%ec%9a%a9%ed%95%98%ec%97%ac-%ec%82%ac%ec%9a%a9%ed%95%98%ea%b8%b0java-aws-sdk-credential/

maven 기반 spring boot 소스로 구성하였다.

먼저 pom.xml 에 aws sdk를 추가한다.

...
		
		<dependency>
		    <groupId>com.amazonaws</groupId>
		    <artifactId>aws-java-sdk</artifactId>
		    <version>1.11.920</version>
		</dependency>
...

pre-singed url을 발행하는 소스는 아래와 같다. pre-signed url을 발행 할 때는 다음 네가지 설정을 해주어야한다.

  • Bucket name : S3 버킷 이름
  • Object key : 오브젝트 이름
  • Method : REST API 중 허용하려는 Method (GET, POST, PUT 등)
  • Expiration : 발행한 URL 유효시간(초단위)
import java.io.IOException;
import java.net.URL;
import java.util.Date;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.amazonaws.HttpMethod;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;

@RestController
public class PreSignedUrlController  {
	private static final long ONE_HOUR = 1000 * 60 * 60; // 1시간;

	@GetMapping(path="/s3url-upload")
	public String GetS3UrlUpload(@RequestParam("objKey") String objectKey) {
		AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
				.withRegion(S3BucketConstant.CLIENT_REGION)
				.build();	

	    // Generate the pre-signed URL.
	    GeneratePresignedUrlRequest generatePresignedUrlRequest = 
	    		new GeneratePresignedUrlRequest(S3BucketConstant.BUCKET_NAME, objectKey)
						.withMethod(HttpMethod.PUT)
						.withExpiration(this.getExpiration(ONE_HOUR));


	    URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
	    
	    return url.toString();
	}
	
	@GetMapping(path="/s3url-download")
	public String GetS3UrlDownload(@RequestParam("objKey") String objectKey)  throws IOException {
		AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
				.withRegion(S3BucketConstant.CLIENT_REGION)
				.build();	

	 	// Generate the presigned URL.
        GeneratePresignedUrlRequest generatePresignedUrlRequest =
                new GeneratePresignedUrlRequest(S3BucketConstant.BUCKET_NAME, objectKey)
                        .withMethod(HttpMethod.GET)
                        .withExpiration(this.getExpiration(ONE_HOUR));

        URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);

        return url.toString();
	}

	private Date getExpiration(long expirationAsMilliseconds) {
		// Set the pre-signed URL to expire after milliseconds
		Date expiration = new Date();
		long expTimeMillis = expiration.getTime();
		expTimeMillis += expirationAsMilliseconds;
		expiration.setTime(expTimeMillis);
		return expiration;
	}

}

 

 

 

이렇게 발행한 pre-singed url은 아래와 같은 정보를 포함하게 된다. 내가 구성한 정보와 맞지 않는 형태로 접근하는 경우 signature가 맞지 않는 다는 오류가 발생하게 된다.

매개변수 설명
X-Amz-Algorithm 서명 버전과 알고리즘을 식별하고, 서명을 계산하는데 사용. 서명 버전 4를 위해서 “AWS4-HMAC-SHA256” 로 설정
X-Amz-Credential 액세스 키 ID와 범위 정보(요청 날짜, 사용하는 리전, 서비스 명). 리전 명은 리전 및 엔드포인트에서 확인 가능
X-Amz-Date 날짜는 ISO 8601형식. 예: 20160115T000000Z
X-Amz-Expires 미리 선언된 URL이 유효한 시간 주기. 초단위. 정수 값. 최소 1에서 최대 604800 (7일) 예: 86400 (24시간)
X-Amz-SignedHeaders 서명을 계산하기 위해 사용되어지는 헤더 목록. HTTP host 헤더가 요구됨
X-Amz-Signature 요청을 인증하기 위한 서명

 

 

 

공식 AWS 가이드 링크

https://aws.amazon.com/ko/blogs/korea/aws-api-call-2-s3-pre-signed-url/

https://aws.amazon.com/ko/premiumsupport/knowledge-center/presigned-url-s3-bucket-expiration/

Access key와 Secret key 를 사용하면 매우 편하지만 동시에 보안적으로 매우 위험하기도 하다. 저 두개만 알고 있으면 곧 계정에 대한 권한을 전부다 사용할 수 있기 때문이다.

따라서 아래 그림과 같이 로컬 환경에서는 access key와 secret key를 로컬 파일 시스템에 두고 사용할 수 있지만, 서버 환경(EC2)에서는 그렇게 하지 않고 Role을 기반으로 서비스를 사용하는 것이 좋다.

JAVA AWS SDK 기준으로 AWS가 credential을 어떻게 가져가는지 살펴보겠다.

credential 가이드 : https://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/credentials.html

위의 링크를 살펴보면 명시적으로 크레덴셜 provider를 설정하지 않으면, aws sdk가 credential을 가져가는 순서는 다음과 같다.

1. Java system properties
– Java System에서 정의한 property (aws.accessKeyId, aws.secretKey)
– SystemPropertyCredentialsProvider
2. Environment variables (환경변수)
– 시스템에서 정의한 환경변수(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
– EnvironmentVariableCredentialsProvider
3. Web identity token from AWS STS
– AWS STS 에서 제공하는 웹 토큰
– WebIdentityTokenFileCredentialsProvider
4. The shared credentials and config files
– 로컬 파일에 저장된 credentials 과 config 파일
– ProfileCredentialsProvider
5. Amazon ECS container credentials
– AWS_CONTAINER_CREDENTIALS_RELATIVE_URI system environment variable
– ContainerCredentialsProvider
6. Amazon EC2 instance profile credentials
– load credentials from the Amazon EC2 metadata service
– InstanceProfileCredentialsProvider

로컬에서는 4번을 사용하고 EC2에서는 6번의 credential을 사용하도록 하겠다.

 

 

 

Access Key 및 Secret Key 발급하기

IAM – 계정- 보안 자격 증명탭의 액세스 키 만들기 버튼을 클릭하여 access key 및 sercret key를 발급받는다. secret key의 경우 발급한 팝업에서만 확인이 가능하므로 잘 보관해두도록 한다.

 

 

 

Local에 credential 저장하기

User/.aws/credentials 파일을 만들고 아래 내용으로 작성한다.

[default]
aws_access_key_id = 발급받은 access key
aws_secret_access_key = 발급받은 secret key

User/.aws/config 파일을 만들고 아래 내용으로 작성한다.

[default]
region = 원하는 기본 리전(ap-northeast-2)
output = :

 

 

 

EC2에 Role 지정하기

사용하려는 서비스의 권한을 Policy로 만들어서 Role에 저장한다. 저장한 Role을 EC2에 할당한다.

 

 

 

JAVA aws sdk 에서 credential 가져오기

S3 를 사용하기 위해 credential을 가져오는 경우 아래와 같이 credential을 가지고 온다. 명시적으로 withCredential 을 사용하지 않았기 때문에 위에서 지정한 순서대로 크레덴셜을 가지고 온다.

AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withRegion(clientRegion)
                    .build();

S3 서비스 외에 다른 서비스를 사용하는 경우 아래 가이드 문서를 참고한다.

가이드 문서 : https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2

Local에서는 aceess key와 secret key로 크레덴셜을 가지고 오고 EC2에서는 Role로 가지고 오게 된다.

EC2를 사용하다 보면 SSH Key 파일이 없는데 급하게 서버에 붙어야 하는 상황이 생기게 된다. AWS에서는 session manager 라는 기능을 제공하여 key 파일 없이 AWS console에서 EC2에 접속할 수 있도록 한다.

session manager란 : https://docs.aws.amazon.com/ko_kr/systems-manager/latest/userguide/session-manager.html

EC2의 우측 상단에 있는 연결 버튼을 클릭하여 인스턴스에 연결 화면으로 이동한다. Session Manager 탭을 클릭하면 연결 버튼이 활성화 되어 있는 경우 바로 연결 하면 되지만, 대부분의 경우 아래와 같이 비활성화가 되어있다.

Session Manager(SSM) 사전 조건

session manager 를 사용하기 위해서는 아래 조건을 만족해야 한다.

– EC2 Role에 session manager 를 사용할 수 있는 권한이 포함되어야 한다.

– EC2에 session manager agent 가 설치되어야 한다. (AMI 사용시 session manage agent가 포함된 경우도 있지만, 아닌경우 수동으로 설치해야 한다.)

– EC2의 outbound에 443 포트가 any로 오픈 되어 있어야 한다. SSM은 443으로 EC2와 통신하기 때문에 443을 any로 열어주어야 접속 가능하다.

EC2 Role에 Session Manager 권한(정책) 추가하기

인스턴스 선택 후 작업 – 보안 – IAM 역할 수정을 선택한다.

아래 정책(AmazonEC2RoleforSSM)을 포함한 IAM 역할을 생성하여 인스턴스에 붙인다. AmazonEC2RoleforSSM 정책은 SSM을 사용하기 위해 AWS에서 관리하는 관리형 정책이다.

EC2 에 SSM Agent 설치하기

아래 가이드 문서를 참고하여 각자의 OS에 맞는 명령어를 수행한다.

https://docs.aws.amazon.com/ko_kr/systems-manager/latest/userguide/sysman-manual-agent-install.html

debian server 10 기준으로 설치 과정을 설명한다.

임시 디렉토리로 변경하여 해당되는 리전(ap-northeast-2)의 SSM agent를 설치한다.

mkdir /tmp/ssm
cd /tmp/ssm
wget https://s3.ap-northeast-2.amazonaws.com/amazon-ssm-ap-northeast-2/latest/debian_amd64/amazon-ssm-agent.deb
sudo dpkg -i amazon-ssm-agent.deb

아래 명령어를 수행하여 ssm agent가 실행중인지 확인한다.

sudo systemctl status amazon-ssm-agent

상태가 active가 아닌 stoppted, inactive, disabled로 나오는 경우 아래 명령어를 실행하여 서비스를 시작한다.

sudo systemctl enable amazon-ssm-agent

로그는 아래 경로에서 확인할 수 있다.

sudo cat /var/log/amazon/ssm/amazon-ssm-agent.log

EC2의 outbound rule에 443 추가하기

EC2의 security group에 443 any Rule을 추가한다.

SSM을 활용하여 EC2에 연결하기

위의 조건을 전부 만족하면 연결 버튼이 활성화 된다. 연결 버튼을 클릭하여 인스턴스에 접속한다.

Role을 먼저 추가한 후 agent를 설치해야 agent 서비스가 실행되면서 role 의 정책을 확인한다. 위의 과정을 다 수행했는데도 제대로 연결이 되지 않는 경우 agnet를 재실행한다.

sudo systemctl restart amazon-ssm-agent

key 파일 없이도 EC2에 연결이 가능해졌다.

아래 명령어를 수행하여 SSH 접속과 동일하게 원하는 사용자로 변경하여 사용가능하다.

sudo su - {user명}

이렇게 연결되는 세션은 AWS의 System Manager 서비스에서 조회 및 관리가 가능하다.

기본적으로 AWS 의 Cloud watch의 지표 중 memory 사용량은 모니터링 되지 않는다. 추가적으로 cloud watch agent를 설치하여 메모리 및 디스크 사용량을 모니터링 할 수 있다.

ubuntu 18.04 를 기준으로 cloud watch Agent를 EC2에 설치하고 cloud watch에서 모니터링 가능하도록 설정해보겠다.

EC2 Role 수정

사전작업으로 EC2의 Role 권한 중 CloudWatchAgentServerPolicy 가 추가되어 있어야 cloud wacth agent가 정상적으로 동작할 수가 있다.

IAM 서비스에서 Role 생성 – EC2 선택 – 아래 policy를 추가 – 생성한다.(role 이름 : ec2_cloudwatch_ssm)

AmazonSSMManagedInstanceCore

CloudWatchAgentServerPolicy

EC2 Action – Security – Modify IAM role 을 선택하여 위에서 생성한 role(ec2_cloudwatch_ssm) 로 변경한다.



Cloud Watch Agent 설정

아래 코드를 실행하여 cloud watch agent를 설치한다.

wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
sudo dpkg -i -E ./amazon-cloudwatch-agent.deb

wizard를 통해 지표, 모니터링 주기 등에 대한 설정을 진행한다. 대부분 기본값으로 진행하면 큰 문제 없고 마지막에 log 모니터링을 할건지, config를 parameter store에 저장할건지 확인 하는 부분만 선택하면 된다.

sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard

설치된 경로로 이동하여 agent를 실행한다.

cd /opt/aws/amazon-cloudwatch-agent/bin
sudo ./amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 file://opt/aws/amazon-cloudwatch-agent/bin/config.json -s
sudo ./amazon-cloudwatch-agent-ctl -m ec2 -a start

실행된 agent의 상태를 확인한다.

sudo ./amazon-cloudwatch-agent-ctl -m ec2 -a status
ps -ef | grep amazon-cloudwatch-agent

agent의 로그를 확인한다.

cd /opt/aws/amazon-cloudwatch-agent/logs
more amazon-cloudwatch-agent.log



Cloud Watch에서 memory 지표 확인

Cloud Watch 서비스 – Metrics – ALL metircs – mem_used_percent 지표 검색

약 1분 정도 이후부터 정상적으로 memory 지표를 확인할 수 있다.

참고 : https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/download-cloudwatch-agent-commandline.html

https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/create-iam-roles-for-cloudwatch-agent.html