반응형
Github Action을 이용해서 CDN S3 업로드 POC 진행중..
너무 오래 걸리는데?? Action log를 살펴보는데..

 

 

 

upload : 오호 예상대로 업로드가 잘됐군
delete : 뭐지..?
delete : 이
delete : 거
delete : 어
delete : 떻
delete : 게
delete : 멈
delete : 추
delete : 지...
 

 

제가 멍청하게 Github 지정된 폴더와 S3 버킷을 동기화하는 코드를 넣어서 S3 객체를 날리고 있었습니다..
평정심을 찾고.. 아니 끝까지 못 찾았습니다..
부랴부랴 버킷에 들어가 봅니다!
 

 

 
버킷 버전 관리가 활성화되어 있으면 복구가 가능합니다!!
버전 관리가 활성화되어있는 상태에서는 객체를 삭제하면 삭제 마커 버전이 생성되는데요
삭제 마커 버전을 삭제하면 전 버전으로 복구 시킬 수 있습니다.
 
 
이렇게 aws console을 이용해서 복구 시킬 수도 있지만, 저같이 대량의 파일을 삭제했을 경우에는 코드로 복구 시킬 수 있는데요.
AWS SDK를 사용해서 여러 프로그래밍 언어로 코딩하는 방법도 있지만, 저는 급한 마음에 AWS CLI를 이용해서 S3 복구를 진행하였습니다.

 

1. AWS CLI를 설치

AWS CLI 이용하려면 CLI 설치를 먼저 진행해야 합니다.
Homebrew를 이용해서 설치를 진행하도록 하겠습니다.
aws cli 설치 : brew install awscli
설치 확인 : aws --version
aws cli를 이용하기 위해서는 aws configure 설정을 해줘야 합니다.
aws iam 서비스에서 관련된 권한만 부여된 사용자를 생성해서 설정하는게 보안에 더 좋습니다.
저는 s3 관련 권한만 부여된 사용자를 생성하였습니다.
 
 
위와 같이 사용자를 생성하면 AWS Access Key ID와 Secret Access Key가 생성되는데요,
중요한 정보이기에 외부 유출에 유의하셔야 합니다.
aws cli 설정 : aws configure
설정값에 key와 각종 정보를 등록하셨다면 이제 aws cli를 이용해서 S3 객체를 복원해 보도록 하겠습니다.
 
순서는 크게 두가지 입니다.
  1. 오늘 날짜로 삭제된 S3 객체 목록 추출
  2. 추출된 리스트를 이용해서 삭제 마커 버전 삭제

 

2. 삭제된 S3 객체 목록 추출

cli를 이용해서 aws api를 호출하면 아래와 같이 삭제 마커가 붙은 객체를 가져올 수 있습니다.
터미널에서 조회
aws s3api list-object-versions --bucket s3_bucket_name --output text | grep DELETEMARKERS

 

 
aws s3 api를 이용해서 오늘 날짜로 삭제된 객체 목록을 txt 파일로 가져올 수 있습니다.
s3_deleted_object_list.sh
#!/bin/bash
TODAY=$(date +"%Y-%m-%d")
aws s3api list-object-versions --bucket s3_bucket_name --output text | grep DELETEMARKERS | grep $TODAY > deleted_objects_today.txt

 

3. 추출된 리스트를 이용해서 삭제 마커 버전 삭제

위에서 추출한 목록에서 객체의 key 값과 version_id를 이용해서 해당 버전을 삭제시킬 수 있습니다.
s3_restore.sh
#!/bin/bash


while read -r line; do
key=$(echo $line | awk '{print $3}')
versionId=$(echo $line | awk '{print $5}')
aws s3api delete-object --bucket s3_bucket_name --key "$key" --version-id "$versionId"
done < deleted_objects_today.txt

 

 

 

 

728x90
반응형

'AWS' 카테고리의 다른 글

AWS SAA-CO3 Certification 취득  (0) 2024.12.08
AWS ECS 이용한 서비스 배포  (0) 2024.04.28
AWS를 이용한 SSL 적용하기  (0) 2023.01.08
반응형

토이 프로젝트로 혼자서 클라우드 서비스를 이용하여 웹 개발부터 배포까지 온 과정을 경험해 보았습니다.

이 과정을 단계별로 나누어서 정리해 보려고 합니다.!

많은 피드백은 감사합니다!

 

목차 

STEP 01) NCP 서버 

STEP 02) AWS RDS, S3

STEP 03) Web Application 개발

STEP 04) Jenkins pipeline 배포

STEP 05) Domain 등록

 

 


 

* Web Application 개발은 앞에서 살펴보았던 AWS 서비스를 사용하는 방법만 소개하도록 하겠습니다.

 

개발 환경

 - SpringBoot 2.6.6

 - Mariadb 2.7.5

 - Gradle 7.4.1

 

1. RDS 연결(yml 설정)

  - 이전 RDS 설정 확인

spring:
  datasource:
    url: jdbc:mariadb://rds end point 주소 + prot + schema name
      예) jdbc:mariadb://rds.amazonaws.com:3306/rdstest
    driver-class-name: org.mariadb.jdbc.Driver
    username: admin
    password: 패스워드

 

2. S3 연결

  - 이전 S3 설정 확인

1.  spring cloud starter 의존성 추가

  - build.gradlew

implementation 'io.awspring.cloud:spring-cloud-starter-aws:2.3.1'

 

2. yml 설정

cloud:
  aws:
    credentials:
      access-key: access key
      secret-key: secret key
    s3:
      region: ap-northeast-2
      endpoint: s3-bucket

 

  - access key, secrey key 새 액세스 키 만들기로 생성

 

 

- region, endpoint 작성

  endpoint는 :::뒤에 복/붙

 

AwsS3Config.java

 

package com.bumblebee.dailyspecial.domain.aws;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author bumblebee
 */
@Configuration
public class AwsS3Config {

    @Value("${cloud.aws.credentials.access-key}")
    private String accessKey;

    @Value("${cloud.aws.credentials.secret-key}")
    private String secretKey;

    @Value("${cloud.aws.s3.region}")
    private String region;

    @Bean
    public AmazonS3Client amazonS3Client() {
        BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey);
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                .build();
    }

}

 

AwsS3Service.java

 

package com.bumblebee.dailyspecial.domain.aws;

import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.bumblebee.dailyspecial.domain.comutils.CommonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author bumblebee
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class AwsS3Service {

    private final AmazonS3Client amazonS3Client;

    @Value("${cloud.aws.s3.endpoint}")
    private String bucketName;

    public String uploadFileV1(String category, MultipartFile multipartFile) {
        validateFileExists(multipartFile);

        String fileName = CommonUtils.buildFileName(category, multipartFile.getOriginalFilename());

        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType(multipartFile.getContentType());

        try (InputStream inputStream = multipartFile.getInputStream()) {
            amazonS3Client.putObject(new PutObjectRequest(bucketName, fileName, inputStream, objectMetadata)
                    .withCannedAcl(CannedAccessControlList.PublicRead));
        } catch (IOException e) {
//            throw new FileUploadFailedException();
        }

        return amazonS3Client.getUrl(bucketName, fileName).toString();
    }

    private void validateFileExists(MultipartFile multipartFile) {
        if (multipartFile.isEmpty()) {
//            throw new EmptyFileException();
        }
    }

}

 

AwsS3Config class에 amazonS3Client 메소드를 @Bean으로 등록합니다.

파일을 업로드가 필요한 로직에 AwsS3Service class에서 uploadFIleV1 메소드를 이용해서 S3에 업로드 합니다.

예)

awsS3Service.uploadFileV1("Img", multipartFile);

 

그 외 다운로드 및 다중 업로드 기능도 제공하고 있습니다.

 

참조

  - Springboot로 S3 파일 업로드하기

728x90
반응형
반응형

토이 프로젝트로 혼자서 클라우드 서비스를 이용하여 웹 개발부터 배포까지 온 과정을 경험해 보았습니다.

이 과정을 단계별로 나누어서 정리해 보려고 합니다.!

많은 피드백은 감사합니다!

 

목차 

STEP 1) NCP 서버 

STEP 2) AWS RDS, S3

STEP 3) Web Application 개발

STEP 04) Jenkins pipeline 배포

STEP 05) Domain 등록


AWS(Amazon Web Services)

  - 아마존 클라우드 서비스

  - 현재 클라우드 컴퓨팅 분야에서 세계 1위

  - 다양한 클라우드 자원을 1년간 무료로 경험해 볼 수 있다.

  - 많은 국내 IT 기업에서도 사용 중이다.

 

* 이번 장에서는 Web Application를 만드는데 필요한 객체 스토리지 서비스(S3)를 AWS에서 사용하는 방법을 알아보겠습니다. 

S3

S3는 AWS(Amazon Web Service)에서 제공하는 인터넷 스토리지 서비스입니다.
S3(Simple Storage Service) 를 뜻합니다.

 

장점

  • 높은 내구도를 자랑하며 정보를 안전하게 저장 할 수 있습니다.
  • 저렴한 비용으로 사용이 가능합니다(ec2에 이미지, 영상등을 저장하며 비용이 만만치 않습니다.)
  • 보안성이 뛰어납니다 ( SSL을 통하여 데이터 전송과 암호화를 하므로 해킹 걱정이 적습니다.)
  • 속도가 빠릅니다 (각 지역에 맞게 선택하며, 업/다운로드 시 지역시간 최소화를 위한 멀티 파트 업로드를 지원합니다.)

 

1. Amazon S3에서 버킷 만들기를 선택합니다.

 

 

2. S3 버킷 만들기

  - 버킷 이름과 AWS 리전을 선택합니다.

 

3. ACL 활성화됨을 선택합니다.

  - 비활성화를 하게 되면 개발 당시 파일 업로드할 때 400 에러가 발생된 경험이 있습니다.

 

4. 퍼블릭 액세스 차단은 맨 마지막 임의의 퍼블릭 버킷 또는 엑세스 지점 정책을 ... 제외하고 체크 하도록 하겠습니다.

  - 모든 퍼블릭 액세스 차단을 권장하고 있습니다.

 

5.  버킷 버전 관리 및 기본 암호화 운영할 때는 활성화를 하는 게 유지 보수 측면에서나 보안상 좋습니다.

 

6. 생성된 버킷에 이미지를 업로드해 보겠습니다.

 

7. 파일 추가 후 업로드 클릭

 

 

8. 객체 URL 복사 후 접근!

 

 

AccessDenied 에러 발생..

 

9. 버킷 > 권한 탭 > 버킷 정책 설정

  9.1 ) 퍼블릭 액세스 차단 모두 해체 후 저장

 

  9.2 ) 버킷 정책 편집 > 정책 생성기

 

 

  - Select Type of Policy : S3 Bucket Policy 

  - Principal : *

  - Actions : GetObject

  - Amazon Resource Name(ARN) : 버킷 > 속성 탭 > Amazon 리소스 이름(ARN) /* (이름 뒤에 /* 붙여줍니다.)

  9.3 ) Generate Policy 후 JSON 복사 > 버킷 정책에 붙여넣기 후 저장

 

10. 객체 URL 접근 이미지 출력!

 

728x90
반응형

+ Recent posts