AWS

AWS-FinOps-S3-incomplete-multipart-uploads-MPU

S3는 청크 단위로 파일을 잘라서 업로드 할수있는 기능을 제공한다.

이 기능의 정식명칭은 multipart upload 이다.

https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html

MPU라고 줄여서 부른다.

MPU는 업로드 속도를 빠르게 해줄수있는 아주 좋은 기능이지만, 업로드에 실패할 경우 완성되지 않은 청크단위의 파일들이 S3스토리지에 저장되게 된다. 업로드가 정상적으로 이루어진 경우 청크단위로 나뉜 파일을 하나의 파일로 합쳐서 객체로 보이게 되지만, 그렇지 않은 파일은 우리의 눈에 보이지 않지만 S3의 스토리지에 비용만 발생시키며, 하등 쓸모없는 상태로 저장만 되어있는다. 이런 경우를 "incomplete multipart uploads" 라 부른다.

불완전 멀티파트 업로드/완료되지 않은 멀티파트 업로드 는 Lifecycle 를 통해 삭제 할수있다. 간단한 정책을 만들어서 보여주고자 한다.

설정은 S3 버킷 에서 관리로 가면 수명주기 규칙으로 설정할수 있다.

이설정은 모든 버킷에서 통용적으로 사용할수 있는 규칙이므로 버킷을 생성할때 무조건 넣어도 좋다.

위와같이 "만료된 객체 삭제 마커 또는 완료되지 않은 멀티파트 업로드 삭제" 체크후 "불완전 멀티파트 업로드 삭제" 를 체크하면 된다. 일수는 1일이 최소값이다.

정상적으로 삭제가 동작하면 이런식으로 S3 dashboard에서 불완전한 멀티파트업로드 바이트 차트가 0B로 변경되는것을 확인할수 있다.

불완전 MPU는 대표적으로 이런경우 생성된다.

MPU 업로드 실패.
Athena 쿼리 실패
Redshift UNLOAD 실패등

AWS 서비스에서 S3로 저장하는 액션을 취하다 실패하는경우가 있다면 대부분 "불완전 MPU"가 생성될것이다.

AWS S3 대시보드를 확인하여 "불완전한 MPU" 를 확인하고 삭제해보자.

바닥에 흘리고 다니던 눈먼 동전 줍기가 될것이다.

읽어주셔서 감사하다!
앞으로도 FinOps 시리즈로 찾아 뵙겠다.

AWS-IAM-Identity-Center

가시다 님과 함께하는 CASS 스터디를 시작했다.

첫시간은 OU / IAM과 함께하는 즐거운 시간.
MSP에서 OU는 열심히 익힌터라 좀 자신이 있었다. 그래서 나는 IAM Center를 써봤다.

검증할것은 이것이다. 지금까지는 각 계정에 역할을 생성하고, STS를 통해서 계정에 접근했다면 IAM Center에선 통합계정을 생성하여 OU에 연결된 루트계정들에 접근할수 있도록한다.

먼저 OU에 계정을 연결한다.

3개의 계정이 연결된것을 확인할수있다.

linxuer 계정이 Root OU를 관리한다.

linuxer 계정에서 IAM Identity Center서비스 로 이동한다. 그리고 사용자를 생성한다.

사용자를 생성할때 권한세트를 참조한다. 나는 AdministratorAccess 권한을 미리 생성해서 넣어줬다.

IAM Identity Center 에서는 이계정으로 OU의 하위 모든 계정을 관리한다 이과정에서 IAM Role Change가 필요하지 않다. 테스트하면서 정말 놀랐다.

계정을 생성하면 아래와 같은 메일주소가 온다.

내 포탈이라는 페이지로 이동하면 계정의 패스워드와 MFA를 설정할수 있는 페이지로 이동한다. MFA 잊지말고 설정하자

이포탈의 역할은 딱하나다.

로그인-MFA-다른계정의 콘솔접근-억세스키생성
편리하지만 위험하다. 단순 1회발급되고 휘발성을 가지던 억세스키가 페이지 안에선 변경되지 않고 여러차례 확인이 가능하다

보안에 특별히 유의가 필요하다!!!!!!!!

이서비스는 다음과 같은 메뉴만 제공한다. 미리 OU에서 SCP로 Linuxer2 계정의 S3를 제한해 놨다. linuxer2 계정에서 S3로 이동해 볼거다.

IAM Identity Center 계정도 정상적으로 제어된다. 그럼 Trail 에는 어떻게 표시될까?

signin.amazonaws.com 을통해 로그인한 계정을 추적할수 있다.

앞으로 OU를 사용하는 사용자는 IAM Identity Center를 이용해 다량의 작업을 편하게 할수 있음을 알았고 불편하게 역할 전환을 하게되는 경우가 없이 IAM Identity Center Console을 사용할수 있음 을 알수있었다.

새로운 보안의 공백이 될 수 있음을 염두에 두도록 하자.

읽어 주셔서 감사하다!

AWS FinOps - Intro

이번엔 FinOps에 대한 이야기를 할거다.

먼저 본론으로 들어가기 전에 FinOps에 대한 정의부터 이야기할까 한다.

우리가 흔히 알고있는 DevOps는 Development 과 operations 의 합성어 이다.
FinOps는 이 DevOps 에 Finance를 더한것이다. ( Finance + Development + Operations )
IT infra 상에서 발생하는 비용을 제어하고 투자하는 방식을 말하는것이다.

'투자' 라고 말하면 의아 할수도 있는데 클라우드 상의 자원은 무한하지만 사용자에게 할당된 비용은 유한하다.
그렇기에 제한된 비용내에서 적절한곳에 맞는 리소스를 투입하는것이 FinOps 에서 투자인것이다.

FinOps의 목적은 절약이 아니다.
FinOps는 제한적인 예산에서 낭비되는 비용을 줄여 리소스가 필요한곳에 투입하는것이 FinOps 목적인 것이다.
절약에서 '만' 끝난다면 지속적으로 줄여야하는 비용의 압박에 씨달릴 것이다.

또한 비용관리는 반드시 필요하나, 이 비용관리가 비즈니스의 편의성을 해치고, 확장성과 탄력성에 영향을 준다면 당신을 FinOps를 잘못이해 하고있는것이다.

예를 들어 RI를 구매 후 워크로드가 변화에도 불구하고 RI때문에 유연한 리소스를 사용하지 못한다면 잘못된 방식의 비용관리를 하고 있는 것이다. RI 때문에 서버추가에 대한 고민이나 원하는 유형의 인스턴스를 사용하지 못한다는 것은 클라우드를 사용하는 방식도 아니며, 이런경우 차라리 On-Premises로 의 회귀가 더 저렴할것이며 사용패턴도 맞을것이다.

차후 포스팅 할 내용에서는 먼저 가장 간단히 보고 절약할 부분부터 새로운 아키텍처가 필요한 부분까지 작성할 것이다.

FinOps의 세계가 얼마나 짜릿하고 즐거운 분야인지 같이 느껴보면 좋겠다.

함께 돈을 버는 엔지니어의 세계로 가보자.


DOIK-Study

가시다님과 함께하는 스터디는 항상 즐겁다. 이번 스터디엔 라이브로 못해서..일단 바닐라쿠버 배포하고 시작했다.

Headless 서비스는 ClusterIP가 None으로 설정하며 kubeproxy를 통하지않고 pod의 endpoint가 svc에 연결된다.

나는 먼저 NFS 서버를 Headless 로 배포하기로 했다.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nfs-server-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
      
---

kind: Service
apiVersion: v1
metadata:
  name: nfs-service
spec:
  type: ClusterIP
  clusterIP: None
  selector:
    role: nfs
  ports:
    # Open the ports required by the NFS server
    # Port 2049 for TCP
    - name: tcp-2049
      port: 2049
      protocol: TCP

    # Port 111 for UDP
    - name: udp-111
      port: 111
      protocol: UDP
      
    # Port 20048 for TCP
    - name: tcp-20048
      port: 20048
      protocol: TCP
---

apiVersion: v1
kind: ReplicationController
metadata:
  name: nfs-server
spec:
  replicas: 1
  selector:
    role: nfs-server
  template:
    metadata:
      labels:
        role: nfs-server
    spec:
      containers:
      - name: nfs-server
        image: gcr.io/google_containers/volume-nfs:0.8
        ports:
          - name: nfs
            containerPort: 2049
          - name: mountd
            containerPort: 20048
          - name: rpcbind
            containerPort: 111
        securityContext:
          privileged: true
        volumeMounts:
          - mountPath: /exports
            name: nfs-export
      volumes:
        - name: nfs-export-fast
          persistentVolumeClaim:
            claimName: nfs-server-pvc-fast
            

🐤

yaml을 deploy 하면 다음과같다.

이제 프로비저너 셋팅이 좀 필요하다. 가시다님께서는 친절하게 프로비저너 셋팅도 다해주셨지만 나는 내가만든 NFS 서버를 사용할거기 때문에 프로비저너를 다시 배포할거다.

#지우고
helm delete -n kube-system nfs-provisioner
#다시 설치하고
helm install nfs-provisioner -n kube-system nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --set nfs.server=nfs-service.default.svc.cluster.local --set nfs.path=/exports
NAME: nfs-provisioner
LAST DEPLOYED: Thu May 26 16:10:31 2022
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None

🐤

응 잘됬다.

(🐤 |DOIK-Lab:default) root@k8s-m:~# k get svc
NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)            AGE
kubernetes    ClusterIP   10.200.1.1   <none>        443/TCP            4h30m
nfs-service   ClusterIP   None         <none>        2049/TCP,111/UDP   6m29s

(🐤 |DOIK-Lab:default) root@k8s-m:~# k get ep
NAME          ENDPOINTS                            AGE
kubernetes    192.168.10.10:6443                   4h30m
nfs-service   172.16.158.2:2049,172.16.158.2:111   6m48s

(🐤 |DOIK-Lab:default) root@k8s-m:~# k get pod -o wide
NAME             READY   STATUS    RESTARTS   AGE    IP             NODE     NOMINATED NODE   READINESS GATES
nfs-server-pod   1/1     Running   0          7m1s   172.16.158.2   k8s-w1   <none>           <none>

🐤

정상적으로 NFS서버가 잘 배포된것을 확인할수 있다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-nfs-pv
  labels:
    type: mysql-nfs-pv
spec:
  storageClassName: nfs-client
  capacity:
    storage: 4Gi
  accessModes:
  - ReadWriteOnce          # ReadWriteOnce RWO (1:1 마운트, 읽기 쓰기)
  nfs:
    server: 172.16.184.9 # NFS-Server 의 IP
    path: /1       # NFS 저장소
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: wp-nfs-pv
  labels:
    type: wp-nfs-pv
spec:
  storageClassName: nfs-client
  capacity:
    storage: 4Gi
  accessModes:
  - ReadWriteOnce
  nfs:
    server: 172.16.184.9 # NFS-Server 의 IP
    path: /2      # NFS 저장소

🐤

nfs-service.svc.cluster.local domain을 이용하려 하였으나, PV 에서 domain으로 설정시 nfs-provisioner 정상적으로 마운트 되지 않았다.

headless NFS를 하려고 한것이나, 실패하였다.
지원하지 않는다.(결론)

다음과 같은 증상이었다. IP로 프로비저너 설치후엔 잘되었다.

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app: wordpress
  name: mysql-pv-claim
spec:
  storageClassName: nfs-client
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi
  selector:
    matchLabels:
      type: "mysql-nfs-pv"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app: wordpress
  name: wp-pv-claim
spec:
  storageClassName: nfs-client
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi
  selector:
    matchLabels:
      type: "wp-nfs-pv"

🐤

selector를 이용하여 PV를 사용하도록 설정해 주었다

Every 2.0s: kubectl get svc,pods,pv,pvc -o wide                                                                                                                                                                    k8s-m: Thu May 26 18:10:41 2022

NAME                      TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE     SELECTOR
service/kubernetes        ClusterIP   10.200.1.1    <none>        443/TCP                      7h56m   <none>
service/nfs-service       ClusterIP   None          <none>        2049/TCP,111/UDP,20048/TCP   71m     role=nfs
service/wordpress         NodePort    10.200.1.33   <none>        80:30387/TCP                 3m25s   app=wordpress,tier=frontend
service/wordpress-mysql   ClusterIP   None          <none>        3306/TCP                     3m25s   app=wordpress,tier=mysql

NAME                                   READY   STATUS    RESTARTS   AGE     IP              NODE     NOMINATED NODE   READINESS GATES
pod/nfs-server-rxvf7                   1/1     Running   0          71m     172.16.184.9    k8s-w2   <none>           <none>
pod/wordpress-859f989bbb-msppd         1/1     Running   0          3m25s   172.16.158.21   k8s-w1   <none>           <none>
pod/wordpress-mysql-66fb7cfb68-z9vj5   1/1     Running   0          3m25s   172.16.158.20   k8s-w1   <none>           <none>

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                         STORAGECLASS   REASON   AGE     VOLUMEMODE
persistentvolume/mysql-nfs-pv                               4Gi        RWO            Retain           Bound    default/mysql-pv-claim        nfs-client              3m32s   Filesystem
persistentvolume/pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01   10Gi       RWO            Delete           Bound    default/nfs-server-pvc-fast   local-path              71m     Filesystem
persistentvolume/wp-nfs-pv                                  4Gi        RWO            Retain           Bound    default/wp-pv-claim           nfs-client              3m32s   Filesystem

NAME                                        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE     VOLUMEMODE
persistentvolumeclaim/mysql-pv-claim        Bound    mysql-nfs-pv                               4Gi        RWO            nfs-client     3m25s   Filesystem
persistentvolumeclaim/nfs-server-pvc-fast   Bound    pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01   10Gi       RWO            local-path     71m     Filesystem
persistentvolumeclaim/wp-pv-claim           Bound    wp-nfs-pv                                  4Gi        RWO            nfs-client     3m25s   Filesystem

🐤

서비스가 잘 작동하는것을 확인하였다.

(🐤 |DOIK-Lab:default) root@k8s-m:~/yaml/yaml# k exec nfs-server-rxvf7 -it -- /bin/bash
[root@nfs-server-rxvf7 /]# cd /exports/
[root@nfs-server-rxvf7 exports]# ll
total 32
drwxr-xr-x 5 systemd-bus-proxy root 4096 May 26 09:07 1
drwxr-xr-x 5                33   33 4096 May 26 09:07 2
-rw-r--r-- 1 root              root   16 May 26 07:59 index.html
[root@nfs-server-rxvf7 exports]# cd 1
[root@nfs-server-rxvf7 1]# ll
total 110608
-rw-rw---- 1 systemd-bus-proxy input       56 May 26 09:07 auto.cnf
-rw-rw---- 1 systemd-bus-proxy input 50331648 May 26 09:07 ib_logfile0
-rw-rw---- 1 systemd-bus-proxy input 50331648 May 26 09:07 ib_logfile1
-rw-rw---- 1 systemd-bus-proxy input 12582912 May 26 09:07 ibdata1
drwx------ 2 systemd-bus-proxy input     4096 May 26 09:07 mysql
drwx------ 2 systemd-bus-proxy input     4096 May 26 09:07 performance_schema
drwx------ 2 systemd-bus-proxy input     4096 May 26 09:07 wordpress
[root@nfs-server-rxvf7 1]# cd ..
[root@nfs-server-rxvf7 exports]# cd 2
[root@nfs-server-rxvf7 2]# ll
total 192
-rw-r--r--  1 33 33   418 Sep 25  2013 index.php
-rw-r--r--  1 33 33 19935 Jan  2  2017 license.txt
-rw-r--r--  1 33 33  7413 Dec 12  2016 readme.html
-rw-r--r--  1 33 33  5447 Sep 27  2016 wp-activate.php
drwxr-xr-x  9 33 33  4096 Oct 31  2017 wp-admin
-rw-r--r--  1 33 33   364 Dec 19  2015 wp-blog-header.php
-rw-r--r--  1 33 33  1627 Aug 29  2016 wp-comments-post.php
-rw-r--r--  1 33 33  2764 May 26 09:07 wp-config-sample.php
-rw-r--r--  1 33 33  3154 May 26 09:07 wp-config.php
drwxr-xr-x  4 33 33  4096 Oct 31  2017 wp-content
-rw-r--r--  1 33 33  3286 May 24  2015 wp-cron.php
drwxr-xr-x 18 33 33 12288 Oct 31  2017 wp-includes
-rw-r--r--  1 33 33  2422 Nov 21  2016 wp-links-opml.php
-rw-r--r--  1 33 33  3301 Oct 25  2016 wp-load.php
-rw-r--r--  1 33 33 34327 May 12  2017 wp-login.php
-rw-r--r--  1 33 33  8048 Jan 11  2017 wp-mail.php
-rw-r--r--  1 33 33 16200 Apr  6  2017 wp-settings.php
-rw-r--r--  1 33 33 29924 Jan 24  2017 wp-signup.php
-rw-r--r--  1 33 33  4513 Oct 14  2016 wp-trackback.php
-rw-r--r--  1 33 33  3065 Aug 31  2016 xmlrpc.php

🐤

목적이었던 NFS도 정상적으로 작동한다.

(🐤 |DOIK-Lab:default) root@k8s-m:~/yaml# k scale deployment wordpress --replicas=3

(🐤 |DOIK-Lab:default) root@k8s-m:~/yaml# k get pod
NAME                               READY   STATUS    RESTARTS   AGE
nfs-server-rxvf7                   1/1     Running   0          77m
wordpress-859f989bbb-8r5zh         1/1     Running   0          47s
wordpress-859f989bbb-msppd         1/1     Running   0          8m38s
wordpress-859f989bbb-xhbs9         1/1     Running   0          47s
wordpress-mysql-66fb7cfb68-z9vj5   1/1     Running   0          8m38s

(🐤 |DOIK-Lab:default) root@k8s-m:~/yaml# k get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                         STORAGECLASS   REASON   AGE
mysql-nfs-pv                               4Gi        RWO            Retain           Bound    default/mysql-pv-claim        nfs-client              9m6s
pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01   10Gi       RWO            Delete           Bound    default/nfs-server-pvc-fast   local-path              77m
wp-nfs-pv                                  4Gi        RWO            Retain           Bound    default/wp-pv-claim           nfs-client              9m6s
(🐤 |DOIK-Lab:default) root@k8s-m:~/yaml# k get pvc
NAME                  STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-pv-claim        Bound    mysql-nfs-pv                               4Gi        RWO            nfs-client     9m2s
nfs-server-pvc-fast   Bound    pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01   10Gi       RWO            local-path     77m
wp-pv-claim           Bound    wp-nfs-pv                                  4Gi        RWO            nfs-client     9m2s

🐤

볼륨도 잘공유하여 프로비저닝 된것을 확인할수 있다. ㅜㅜ

클라우드를 시작하는 사람을 위한 안내서

시작하는 사람을 위한 안내서를 작성하고 싶었는데, 좀 늦었다.

매번 하는 말이지만 내 게으름 때문이다.
꼭 누군가에게 도움이 되는 글을 작성하고 싶었는데 그게 바로 오늘인 듯 하다.

클라우드를 하려면 먼저 계정을 생성하여야 한다.

계정을 생성 하였는가? 축하한다. 드디어 클라우드에 입문한 셈이다.

Twitter 上的 DRX|KNEE:"일리단님의 말이 떠오르는 어제 하루였다 아직 준비가 안됐다  https://t.co/QjLPBqUo64" / Twitter

클라우드는 보통 웹 콘솔로 처음 접하게 된다.
CSP 에서 제공하는 웹사이트에 가입을 했다면 뭘 해야 할지 고민이 될 것이다.

모든 설명은 AWS를 기준으로 작성된다.

걱정 마라.

처음 가입하면 뭘해야 할지 바로 알려주겠다.

  1. MFA
  2. Budget
  3. Root 계정 봉인

3가지의 조치가 왜필요한지 이야기해 보겠다.

먼저 MFA를 하지 않아 털리게된다면 공격자는 AWS Console을 편하게 이용할 수 있다. 걸리기 전까지 컴퓨팅을 마음껏 쓸수 있는것이다. 이렇게 털린 계정은 전적으로 사용자 과실이다.

길바닥에 떨어진 지갑은 일반적인 사회라면 경찰서에 가져다주고 주인을 찾아 주겠지만, 그렇지 않은 경우도 많다. 그 길바닥에 떨어진 지갑이 바로 당신의 클라우드 계정이다. 작게는 수백 크게는 수억원까지 비용이 발생할수 있다. 이러한 대 참사를 막기위한 조치이다.

루트계정의 MFA를 설정하여 접근을 막고, 예산을 설정하여 비용이 초과되면 알럿을 받고, 루트계정을 사용하지 않는 방법과 역할 전환을 이용하여 계정의 보안을 강화하는 방법이 가장 적절한 방법인것이다. 여기에 리소스가 생성되면 알림을 받는것도 좋고, 사용하지 않는 태그를 기반으로 리소스가 생성되면 자동으로 삭제하는 방식도 좋다. 이런 여러가지 방식들이 있지만 가장 기본적인 방법이 위에서 제시한 세가지의 방법이다. 그럼 바로 시작하겠다.

MFA

라온클님 역작

MFA를 생성하기 전에 먼저 물어볼것이 있다. 혹시 메일주소가 다른 계정이나, 패스워드가 겹치진 않는가?
이건 굉장히 중요한 문제다. 계정이 다른 아이디 나 패스워드가 겹친다면 삭제하고 처음부터 다시 만들자. 자주사용하는 아이디와 패스워드는 유출될 확률이 높다. 물론 MFA를 사용하면 안전하다. 하지만 언제나 방심하는 순간 문제가 발생한다. 그러니, 콘솔용 메일주소는 별도로 사용하는것이 좋다.

이제 그럼 MFA를 걸어보자.

IAM 서비스로 이동한다 Root 계정의 MFA도 IAM에서 설정할수 있다.

MFA는 사용하지 않으면 IAM 대시보드에 바로 경고가 떠있다. MFA 를 생성하자.

가상 MFA 디바이스를 선택한다.

MFA는 여러 어플이 있는데 나는 MS에서 만든 어플을 선호한다. 온라인백업 기능을 지원한다. QR코드 표시 누르고 그이미지를 백업해두어도 나중에 MFA를 다시추가 가능하다. 하지만 보안이 매우 좋지않음으로 추천하지 않는 방법이다. 보관하려면 압축후 비밀번호를 걸어서 보관하라.

연속된 MFA를 입력하라는건 6자리를 두번 입력해야한다.

두번 입력하면 MFA 설정이 완료된다.

이 쉬운 과정이 일단 그대의 콘솔이 털리는걸 막아주는거다. 로그인이 불편하더라도 꼭 사용하길 바란다.

Budget

Budget 설정은 결제 대시보드에 있다.

예산은 설정하면 알럿이 온다. 예산을 작성하도록 하자.

예산 관련 옵션 들은 FinOps를 위한 여러가지 기능을 제공하는데 우리는 그냥 비용 예산을 작성하면 된다.

일별로 변경후 5$를 설정한다 프리티어에서 하루 5$를 넘으면 대참사다. 한번 만들고 알럿이 귀찮으면 서서히 조정하자.

이메일 수신자에 받고싶은 이메일을 넣어도 되고 SNS 에 주제와, 구독을 생성하여 SMS등으로 받을수도 있으며, Chatbot Alerts를 이용하여 슬랙등 여러 Bot으로 알럿을 받을수 있다. 이메일은 무료고 뒤의 두가지는 비용이 발생할수 있으므로 메일로 받고 관리해야하는 서비스라면 봇이나 SNS를 이용하길 바란다.

이후 예산을 작성하면 이제 일정이상 비용이 넘으면 알럿이 발생한다.

벌써 두가지의 조치를 했다. 남은 두가지만 하면된다.

Root 계정 봉인

Root 계정은 많은 참사를 불러 온다. 이 대 참사를 막기위한 방법이 있다. Root 계정에 MFA를 걸어서 안전하다고 생각할지 모르나, 문제는 언제 어디서 발생할지 모른다. 그렇기에, Root 계정을 봉인하는것을 추천한다.

Root 계정을 사용하지 않고 어떻게 AWS를 안전하게 사용하는지 알려주겠다.

이 방법에는 두가지가 필요하다.

  1. IAM User
  2. IAM Role

먼저 로그인 통로가 될 User를 생성한다. IAM에서 사용자를 추가하면 된다.

IAM 서비스로 이동하고 사용자탭으로 이동해서 사용자 추가를 누른다.

액세스키 방식이 아닌 AWS 관리 콘솔 액세스를 선택한다.

이 계정엔 아무 권한도 주지 않을 것이다.

이렇게 나와야한다. 계정을 생성 완료 했다면 계정의 요약에서 보안 자격 증명을 눌러보자.

콘솔 로그인 링크로 로그인하기 전에 먼저해야할 것이 있다.

MFA다.(궁서체다 매우진지하므로 추가해라.)

MFA는 최대한 활용한다.

이상태가 되면된다. 이제 요약에서 보여주는 콘솔링크로 AWS를 이용한다. 한번 로그인해보시라.

이 아무 권한도 없는 계정은 이제 방파제가 되어 로그인을 제어해줄것이다. 권한이 없는 계정으로 뭘하는지 궁금할것이다. 이때 필요한것이 역할 전환이다. 그럼 IAM Role을 생성하자.

IAM에서 역할탭으로 이동한다. 역할 만들기를 누르자.

다음과 같이 체크해준다.

권한은 여기서 최대 권한을 주지만, 사용자에 맞게 권한을 주는것이 더 적절하다.

역할을 생성하고 이 역할을 사용할수 있도록 수정을 해야한다.

여기서 "arn:aws:iam::00000000000:root" 를 수정해야한다. 수정할 값은 아까만든 계정의 ARN이다. 사용자탭으로 이동해서 계정을 눌러보면

다음과 같이 ARN을 확인할수 있다. 하지만 ARN은 규칙이 있어서 보지않고 그냥 수정해도 된다. 다시 역할로 돌아와서

신뢰관계를 수정하면 이제 생성했던 계정이 이 역할을 사용할수있다. 덤으로 MFA가 활성화 되어야지 만 이 역할을 사용할수 있다.

그럼이제 이 역할을 사용하는 방법은 바로전에 생성한 계정으로 로그인하고, 생성한 역할의 요약 탭에서 보여주는 역할전환 링크를 통해 역할을 전환한다.

다음메뉴에서 역할의 세션지속기간을 설정할수 있다. 역할전환 링크로 이동하면

다음과 같은 화면을 마주하게 되고, 역할 전환을 누르면 이제 IAM 사용자가 역할전환을 이용하여 AdministratorAccess 권한을 승계받은거다. 이제 해커는 MFA를 획득 하더라도 역할전환을 하지 못하면 어떠한 행위도 할 수 없다.

일반적으로 이 방식은 타 계정에서 어카운트를 생성하지 않고 로그인할때 사용하는 방식이다. 혹시 관리계정이 있다면 그관리계정에서 역할전환을 하는것이 더욱 권장되는 방식이다.

이외에도

https://aws.amazon.com/ko/premiumsupport/knowledge-center/config-email-resource-created/

AWS Config 서비스를 이용한 리소스 생성시 추적기능이 있다. 이 부분은 나중에 자세하게 다루어 볼까한다.

SNS EventBridge Config 등의 서비스를 사용하기때문이다.

이 글을 적게된 이유는 최근 여러 커뮤니티를 달군 3억 과금 때문이다. 해킹을 막기 위해선 불편함을 감수해야한다.

편하려다 피눈물 날테니 조심하자.