Skip to content

Commit

Permalink
Merge pull request #55 from gdsc-ssu/mj/week16
Browse files Browse the repository at this point in the history
[week16] S3
  • Loading branch information
thinkjin99 authored Sep 21, 2024
2 parents f5b10ea + 82d6bbc commit 801e37c
Show file tree
Hide file tree
Showing 2 changed files with 227 additions and 0 deletions.
215 changes: 215 additions & 0 deletions AWS/S3/S3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
### 출처
* [S3 최종 일관성](https://inpa.tistory.com/entry/AWS-%F0%9F%93%9A-S3-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9D%BC%EA%B4%80%EC%84%B1-%EB%AA%A8%EB%8D%B8-%EC%9B%90%EB%A6%AC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0)
* [S3는 플랫하다](https://stackoverflow.com/questions/7116450/what-are-valid-s3-key-names-that-can-be-accessed-via-the-s3-rest-api)
* [S3 암호화](https://inpa.tistory.com/entry/AWS-%F0%9F%93%9A-S3-%EA%B0%9D%EC%B2%B4-%EC%95%94%ED%98%B8%ED%99%94-%EA%B8%B0%EB%8A%A5-%EC%A2%85%EB%A5%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0#%EA%B8%B0%EC%A1%B4_%EA%B0%9D%EC%B2%B4_%EC%95%94%ED%98%B8%ED%99%94)
___
### 개요
* [[#S3란?]]
* [[#S3 구성요소 이해하기]]
* [[#S3의 최종 일관성]]
* [[#평평한 S3]]
* [[#S3 스토리지 유형]]
* [[#S3 접근 권한]]
* [[#S3 암호화]]
* [[#실습]]
___
### S3란?

S3는 Simple-Storage-Service의 약자로 안전하고 가변적인 저장 공간을 제공한다. S3에는 다음과 같은 특징이 존재한다.

* 저장 공간에 제약이 없다
* 자동으로 업 스케일링과 로드 밸런싱 등을 처리한다.
* 데이터의 복원이 가능하다
* 인증 조건을 추가해 파일을 보호할 수 있다

<b><u>S3를 활용하면 대용량의 비정형 데이터를 쉽게 관리할 수 있기 때문에 RDS나 캐시 등에 저장 하기엔 너무 크거나 자주 접속하지 않는 데이터 들을 여기에 저장한다.</u></b>

S3는 보통 이미지, 로그, 영상과 같은 것들을 저장할때 주로 활용한다. 이전에 AWS Cloud-Trail을 생각해보자. AWS 접속 로그가 전부 S3에 저장돼 이를 Athena를 활용해 관리했던 것이 기억날 것이다.

> [!S3와 트래픽]
> **S3는 파일 서버인 만큼 트래픽 분배가 주요하지만, 개발자는 이를 신경쓸 필요 없다. AWS에서 자체적으로 이러한 처리를 전부 핸들링해준다.**
___
### S3 구성요소 이해하기

* **버킷**
**버킷은 최상위 폴더로 S3를 활용하는 모든 객체는 어떠한 버킷 내부에 존재하게 된다.** 버킷은 리전 단위로 존재하며 버킷 단위로 보안을 설정할 수 도 있다. 버킷 이름은 리젼별로 유일해야 하기 때문에 신중히 작성할 필요가 있다.

* **객체**
**객체는 S3에서 업로드, 다운로드 되는 파일을 의미한다. 객체는 Key-Value의 방식으로 구별된다.**

* **버전 ID**
버전 아이디는 버킷에 이미 업로드된 파일의 버전을 말한다. 새로운 객체를 업로드 할 경우 버전을 다르게 해 하나의 객체를 여러 개의 버전으로 관리할 수 있다.

____
### S3의 최종 일관성

**S3 버킷에 오브젝트를 재 업로드 하거나 변경할 경우 짧은 지연이 발생하며 이로 인해 dity-read와 비슷한 현상이 발생**할 수 있다. 버킷의 값을 변경 하는 업데이트를 진행할 경우 여러 리전에서 순차적으로 수행되기 때문에 변경되지 않은 값을 가져오는 문제가 발생할 수 있다는 것이다.

<span class="red red-bg">이는 S3가 최종 일관성을 지키기 때문인데 최종 일관성은 곧장 데이터의 일관성을 보장하지 않고 결과적으로 보장하는 성질을 의미한다. </span> 이와 반대로 데이터 일관성은 요청이 처리되는 즉시 데이터의 일관성을 유지하는 성질을 의미한다.

S3에선 PUT 요청이 데이터 일관성을 가지므로 이를 통해 명확히 학습해보자. S3에 PUT을 통해 데이터를 전송할 경우 요청이 마무리 된 직후 곧장 업로드한 객체를 조회하는 것이 가능해진다. 즉 **PUT 요청은 수신되는 즉시 처리가 진행되고 응답이 돌아오는 시점에 작업이 완료됐음을 보증한다.**

하지만 UPDATE를 요청할 경우 수정 사항이 전부 반영되지 않았음에도 응답을 돌려준다. 따라서 업데이트가 언제 완료될 지 확인하기 위해선 클라이언트 입장에서는 busy-waiting 하는 것 외에는 파악할 방법이 없다. **시간이 지나 업데이트가 완료되면 결과적으로는 데이터의 일관성이 유지되긴 하지만, 요청 즉시 일관성이 유지 되진 않는다.** (딜레이가 엄청 나진 않다)

> [!최종 일관성은 왜 쓸까?]
> **데이터 일관성**과 **최종 일관성**은 데이터베이스에서 자주 등장하는 용어이다. RDB(관계형 데이터베이스)는 동시성이라고 해서 같은 시간에 조회하는 데이터는 항상 동일한 데이터임을 보증하는걸 기본으로 한다.
>
> 그런데 NoSQL이 쓰이게 되면서 동시성을 더 이상 보장하기가 힘들어졌다. NoSQL은 분산 노드를 이용하여 그냥 무조건 빠른 데이터 처리가 주목적이기 때문이다. 이처럼 데이터 변경이 발생했을 때, 시간이 지남에 따라 여러 노드에 전파되면서 당장은 아니지만 최종적으로 일관성이 유지되는 **최종 일관성(Eventual Consistency)** 이라한다.
정리하자면 S3는 동시성을 제공하지 않고 결과적 일관성을 갖는다. 그러므로 UPDATE 및 DELETE에 대한 <span class="red red-bg">최종 일관성을 가지는 S3는 객체를 처음 PUT을 진행할 경우에는 일관성 있는 데이터를 제공하나, 삭제 후 가져올 시에는 일관성 없는 결과를 리턴할 수 있다는 특징을 가진다.</span>

![500](https://obs3dian.s3.ap-northeast-2.amazonaws.com/S3%20/%20Pasted%20image%2020240614163248.png)

> [!동기 비동기랑 묘하게 비슷한..?]
> 동기 비동기와 묘하게 흡사한 기분이 든다. PUT은 동기적으로 처리 되고 UPDATE, DELETE는 비동기적으로 처리 된다는 이미지로 생각해도 될까?
___
### 평평한 S3

<span class="red red-bg">S3를 사용할 때 가장 많이 하는 착각중 하나가 S3가 계층적인 구조를 띈다고 생각하는 것이다. 사실 S3는 평평한 형태로 구성돼 있다. 모든 객체는 동일한 레벨에 위치하며 S3는 이를 전부 키값을 활용해 구분한다.</span>

우리가 폴더를 생성하면 만들어지는 그림들은 전부 논리적인 계층에 불과하고 실제 S3의 계층 구조에 영향을 주진 못한다.

> **Note that the Amazon S3 data model is a flat structure**: you create a bucket, and the bucket stores objects. There is no hierarchy of subbuckets or subfolders; however, you can infer logical hierarchy using keyname prefixes and delimiters as the Amazon S3 console does.
하지만 수 많은 파일을 어떠한 계층 구조 없이 관리하는 것은 힘든 일이므로 명시적으로 키값을 통해 논리적 계층 구조를 생성해 파일을 저장한다. 예를 들어 특정 일의 실행 로그를 저장한다고 하면 키 값을 `log/2024/05/30/server.log`와 같이 설정해 논리적으로 계층 구조를 표기한다.

___
### S3 스토리지 유형

* **일반 버킷**: 가장 대중적으로 사용되는 버킷

* **드문 접근 버킷 (Infrequent Bucket)**: 오브젝트에 자주 접근하지 않지만, 접근할 경우 빠른 탐색이 필요할 때 활용

* **단일 존 버킷 (One Zone)**: 하나의 존에만 위치한 버킷으로 만약 특정 리젼에 문제가 발생할 경우 영영 버킷을 복원하지 못할 수도 있음

* **글래시어**: 정~말 가끔 사용하는 데이터들을 저장할 때 사용하는 버킷으로 데이터 접근을 위해 약 4~5시간이 소요된다.

* **지능적 티어링 버킷 (Intelligent Tiering)**: AWS가 자체적으로 버킷의 접근이나 사용 패턴을 파악한 후에 적절한 스토리지 클래스로 설정해주는 버킷이다.
___
### S3 접근 권한

**S3 버킷을 디폴트로 생성하면 초기에는 프라이빗하게 생성되며 외부의 어떠한 인원도 버킷에 접근하거나 버킷을 활용하는 것이 불가해진다.**

하지만 어떤 버킷의 경우 다른 유저가 사용할 수 있도록 공개할 필요가 있는데, 이러한 권한들을 다른 서비스와 마찬가지로 정책을 통해 조절할 수 있다.

버킷의 경우 정책 뿐만아니라 ACL(Access Control List) 을 활용 해서도 접근 권한을 설정할 수 있는데, **ACL을 활용할 경우 디렉토리나 버킷 내부의 객체에 대한 접근 권한을 설정하는 것도 가능하다.**

> **A majority of modern use cases in Amazon S3 no longer require the use of ACLs**. We recommend that you keep ACLs disabled, except in unusual circumstances where you need to control access for each object individually. With ACLs disabled, you can use policies to control access to all objects in your bucket, regardless of who uploaded the objects to your bucket
근래에 들어서는 별도의 권한을 설정할 객체가 존재하지 않는 이상 ACL 설정을 무조건 비활성화 하는 것을 AWS는 권장하고 있다. (비활성화 하더라도 정책을 통해 권한 설정이 가능하다.)

<del>만약 ACL을 활성화하면 버킷 내부의 객체를 다른 AWS 계정이 소유하는 것
이 가능해지는데 이 부분에서의 이슈가 존재해서 그런것 같다.</del>
___
### S3 암호화

#### SSE-S3
Server Side Encrypt는 디폴트로 AWS에서 관리되는 방식으로 AWS 내부에서 관리되는 키를 통해 객체를 암호화하는 방식이다. 객체는 AWS 내부에 존재하는 키를 활용해 AES 암호화를 진행한다. AWS 공식 문서에는 다음과 같이 설명 돼있다.

> **모든 Amazon S3 버킷에는 기본적으로 암호화가 구성되어 있으며 S3 버킷에 업로드되는 신규 객체는 모두 저장 시 자동으로 암호화됩니다.** Amazon S3 관리형 키(SSE-S3)를 사용한 서버 측 암호화가 Amazon S3 내 모든 버킷의 기본 암호화 구성입니다. 다른 유형의 암호화를 사용하려면 S3 `PUT` 요청에 사용할 서버 측 암호화 유형을 지정하거나 대상 버킷에 기본 암호화 구성을 설정할 수 있습니다.
![](https://obs3dian.s3.ap-northeast-2.amazonaws.com/S3%20/%20Pasted%20image%2020240614204548.png)

#### SSE-KMS
KMS는 조금 더 사용자의 권한이 많은 암호화 방식이라고 이해하면 쉽다. **KMS를 활용하면 사용자는 암호화 방식을 지정할 수 있고 누가 언제 어떤 오브젝트에 해당 암호를 사용해 접근했는지 확인 할 수 있다.**

KMS는 별도의 비용이 요청되며 이에 따라 관리를 확실히 해야하는 데이터를 저장할때 주로 활용한다.

![](https://obs3dian.s3.ap-northeast-2.amazonaws.com/S3%20/%20Pasted%20image%2020240614205218.png)

#### SSE-C
**SSE-C는 개발자가 직접 생성한 암호를 활용하는 방식**이다. 개발자는 암호화를 위해 사용할 키를 오브젝트를 업로드 하거나 다운로드 할 때마다 서버에 같이 넘겨줘야 한다. 서버는 해당 키를 저장하지 않고 암호화를 수행한 후 바로 폐기한다.

암호화를 진행하기 위해선 AWS에 요청을 전송할 때 헤더 정보에 암호화를 위한 데이터를 명시 해줘야 한다. 예제는 아래와 같다. `x-amz-server-side-encryption` 헤더를 확인해보면 어떻게 암호화 방법을 지정하는지 확인할 수 있다.

```HTTP hl:9
PUT /simon-image.jpg HTTP/1.1
Host: SimonBucket.s3.<Region>.amazonaws.com
Date: Thu, 12, Feb 2022 16:50:00 CST
Authorization: authorization string
Content-Type: text/plain
Content-Length: 82612
x-amz-meta-author: Simon
Expect: 100-continue
x-amz-server-side-encryption: AES-256 [82612 bytes of object data]
```

___
### 실습

**특정 유저들만 접속 가능한 버킷을 만드는 작업을 수행해보자. 일부 유저만 해당 버킷에 접근해 파일을 읽을 수 있다.**

우선 버킷을 만들자. 버킷은 콘솔에서 손쉽게 만들 수 있다. 이때 외부 접근을 차단해야 하므로 프라이빗 버킷으로 생성해주자.

![](https://obs3dian.s3.ap-northeast-2.amazonaws.com/S3%20/%20%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202024-06-14%20%EC%98%A4%ED%9B%84%209.23.44.png)

![500](https://obs3dian.s3.ap-northeast-2.amazonaws.com/S3%20/%20%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202024-06-14%20%EC%98%A4%ED%9B%84%209.25.28.png)

이제 버킷에 데이터를 넣어주자. 버킷에 올라가는 데이터는 아래와 같다. 메타데이터 설정에서 컨텐츠 타입을 `image/jpeg` 으로 설정해주자.
![](https://obs3dian.s3.ap-northeast-2.amazonaws.com/S3%20/%20god.jpg)
![500](https://obs3dian.s3.ap-northeast-2.amazonaws.com/S3%20/%20%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202024-06-14%20%EC%98%A4%ED%9B%84%209.55.11.png)

이제 버킷 데이터를 읽기만 가능한 사용자를 만들어주자. iam 콘솔에서 사용자를 추가해주고 정책을 연결해주면 된다. iam 유저에게는 ReadOnly 권한을 부여해주면 된다.

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*",
"s3:Describe*",
"s3-object-lambda:Get*",
"s3-object-lambda:List*"
],
"Resource": "*"
}
]
}
```

여기까지 완료 됐다면 이제 파일이 읽힐 것이다. 번거로운 작업을 하나만 더 수행해주자. iam 메뉴로 이동해 CLI용 엑세스 키를 발급 받고 AWS CLI에 신규 프로필로 등록해야 한다. `aws configure --profile test` 와 같이 입력하면 손쉽게 AWS CLI 용 프로필을 생성할 수 있다.

이제 파일을 읽어보자!
**성공할 것 같았지만, 권한 문제로 인해 요청이 거절되는 것을 확인할 수 있다. ReadOnly 권한을 부여했음에도 이러한 문제가 발생하는 까닭은 버킷 정책을 수정하지 않았기 때문이다.**

```bash
aws s3api get-object --bucket mjtests3 --key god.jpg god.jpg --profile test

>>> An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
```

버킷으로 이동해 해당 유저의 접근을 허용해주자. 아래와 같이 정책을 수정한다.

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<account_id>:user/<user_name>"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<bucket_name>/*"
}
]
}
```

이제 파일을 조회 해보자! `aws s3api get-object --bucket mjtests3 --key god.jpg god.jpg --profile test` 를 입력하면 파일이 조회되고 해당 폴더에 카리나 사진이 다운된 것을 확인할 수 있다.

```json
{
"AcceptRanges": "bytes",
"LastModified": "2024-06-14T12:37:39+00:00",
"ContentLength": 130019,
"ETag": "\"99b5169ece682996d01e7f23646b9dd5\"",
"ContentType": "image/jpeg",
"ServerSideEncryption": "AES256",
"Metadata": {}
}
```
12 changes: 12 additions & 0 deletions review/week16/정명진.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
### S3
s3의 전반적인 개념과 속성을 다뤘다.

S3는 아마존에서 제공하는 데이터 저장을 위한 서비스로 사용이 간편하고 비용이 RDB에 비해 저렴한다. S3는 주로 대용량의 접근 속도가 조금 느려도 되는 데이터들을 저장하는 용도로 자주 활용한다.

S3는 평평한 자료구조를 가지며 키를 통해 값을 접근하는 방식으로 동작한다.
S3에는 한가지 재미있는 특성이 존재하는데 바로 최종 일관성이라는 속성이다.

S3는 궁극적으로 일관성을 보장하는 방식으로 동작하며, 특히 업데이트나 삭제 등의 작업이 발생했을 때 해당 작업이 완료 됐다는 응답이 돌아온 후에도 값의 수정과 삭제가 반영되지 않은 경우들이 존재하는데. 이는 S3가 이를 즉시 처리하는 것이 아니라 언젠가 처리하는 방식으로 동작하기 때문이다.



0 comments on commit 801e37c

Please sign in to comment.