's3'에 해당하는 글 4건

파일 mime-type 체크

Daily/Prog 2020. 5. 14. 18:26



얼마전 s3 에 업로드된 상당량의 이미지 mime-type 이 octet-stream 으로 올라가 있는 것을 확인했다. 또 그 파일들은 모두 확장자가 대문자인 것도 확인했다.


String mimeType = Files.probeContentType(path);


위 부분에서 대문자 확장자 파일들에 대한 처리가 정상적으로 되지 않아 null 을 반환한 것이 문제였다. 확장자로 mimeType 을 얻어오는 과정에서 발생할 예외들을 미리 예상하여 처리할 수도 있지만, 업로드시 파일에서 직접 mimeType 을 확인할 수도 있다. Apache 의  Tika 라이브러리를 사용해 봤다.


compile group: 'org.apache.tika', name: 'tika-core', version: '1.24'

...

String mimeType = new Tika().detect(inputStream);


tika-parsers 는 용량이 어마무시하다. parser 가 꼭 필요한게 아니라면 core 만 받자.


그리고 기존에 s3 에 octet-stream 타입으로 업로드된 이미지 파일들은 aws-cli 로 배치처리 하여 image/jpeg 으로 변경하였다.


> aws s3 cp \

 s3://bucket/path \

 s3://bucket/path \

 --exclude "*" \

 --include "*.JPG" \

 --acl public-read \

 --no-guess-mime-type \

 --content-type "image/jpeg" \

 --metadata-directive "REPLACE" \

 --recursive

 --profile myprofile


아쉽게도 include 에 지정한 패턴이 대소문자를 구분하지 못해서 시간이 꽤 걸렸음...




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

트랙백  0 , 댓글  0개가 달렸습니다.
secret

s3 업로드시 발생하는 로그.


Sep 30 03:29:32 ip-172-50-10-72 tomcat8: 2019-09-30 12:29:32.717  WARN 27104 --- [io-8443-exec-65] c.amazonaws.services.s3.AmazonS3Client   : No content length specified for stream data.  Stream contents will be buffered in memory and could result in out of memory errors.


s3 업로드시 setContentLength 를 지정하지 않거나 IOUtils.toByteArray(inputStream) 사용시 inputStream 이 소진되어 발생하는 경고이며 다음과 같이 수정이 필요하다.


byte[] bytes = IOUtils.toByteArray(inputStream);
objectMetadata.setContentLength(bytes.length);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
 
PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, byteArrayInputStream, objectMetadata);
client.putObject(putObjectRequest);
cs




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

트랙백  0 , 댓글  0개가 달렸습니다.
secret

간만에 AWS 유지보수 건이 떨어졌다.


AWS Signature Version 4 to replace AWS Signature Version 2 for signing S3 API requests

Amazon S3 will no longer support path-style API requests starting September 30th, 2020



AWS Signature Version 4 to replace AWS Signature Version 2 for signing S3 API requests


2019년 6월 24일 부터는 S3 API 요청시 Signature Version 2 방식(SigV2)의 서명으로는 통신사용이 불가능하다. 기존 코드가 SigV2 서명을 사용 중이었다면 보안이 강화된 SigV4 방식으로 코드를 수정해야 한다. 2014년 1월 이후에 런칭된 리전(서울리전 등...) 에서는 SigV4 만 지원하므로 수정할 필요가 없으나 그 전에 런칭된 리전(도쿄리전 등....) 에서는 SigV2, SigV4 모두 사용이 가능했으므로 어떤 버전의 서명을 사용중인지 체크해야 한다. 개발 프레임워크 로그에서 서명 버전을 확인할 수 있으면 좋겠지만 스프링에서는 확인할 수 없었다. 대신 AWS CloudTrail 로그나 Athena 쿼리로 조회할 수 있다.


SELECT * 

FROM s3_cloudtrail_events_db.cloudtrail_myawsexamplebucket_table

WHERE eventsource='s3.amazonaws.com'

AND json_extract_scalar(additionalEventData, '$.SignatureVersion')='SigV2'

LIMIT 5


SignatureVersion 이 SigV2 인 레코드가 있다면 SDK 를 최신버전으로 바꾸는 것으로 간단하게 해결된다.

사용 언어 확인 : https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/dev/UsingAWSSDK.html

참고로 나는 AWS SDK for JAVA 1.10 버전에서 1.11 로 변경하여 해결하였다. 람다 스무개를 다바꿨다... ㅡㅡ;;



Amazon S3 will no longer support path-style API requests starting September 30th, 2020


S3 주소 지정시에 두가지 형식을 사용할 수 있었다. 


  • //s3.amazonaws.com/<bucketname>/key (Path style)
  • //<bucketname>.s3.amazonaws.com/key) (Virtual-hosted style)


버킷 이름이 도메인 호스트 자리에 들어가느냐 경로(path) 안에 들어가느냐 인데, 경로 방식을 2020년 9월 30일부터 폐기하기로 했다. 경로 방식을 사용 중이라면 미리 준비해 놓는 것이 좋다.



미리 공지주는건 좋은데, 그래도 Deprecate 난 반댈세...





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

트랙백  0 , 댓글  0개가 달렸습니다.
secret

S3 Output Plugin

Tool/Fluentd 2017. 4. 13. 23:10

이제 flentd 의 워크플로우와 설정 파일을 수정하는 방법을 보았으니, 내가 하고자 하는 인프라를 구축하고 td-agent.conf 파일을 수정하면 된다.

input -> (filter) -> match 모델로 거의 모든 다양한 데이터 수집이 가능한데, 흔히 쓰이는 것들을 요약하자면...

웹서버 로그 / 시스템 로그 / Rest API 등을 입력받아, Mongo / Elasticsearch / S3 / Treasure Data 등으로 전달하는 일을 주로 한다.

인터넷을 뒤져보면 더 많은 예제도 찾을 수 있다.


내가 해야 하는 작업은 아래와 같다.


1. 웹 어플리케이션에서 fluent-logger 를 통해

2. fluentd 서버로 메시지 전달

3. 수집된 로그를 가공하여 S3 로 전달

4. AWS Athena 에서 S3 데이터 쿼리


이번 포스트에서는 fluentd 에 관련된 2번, 3번을 설정 파일을 수정하여 해결해 보겠다.



S3 플러그인 설치


td-agent-gem 툴을 이용해 S3 플러그인을 설치한다.


# td-agent-gem install fluent-plugin-s3
Fetching: fluent-plugin-s3-0.8.2.gem (100%)
Successfully installed fluent-plugin-s3-0.8.2
Parsing documentation for fluent-plugin-s3-0.8.2
Installing ri documentation for fluent-plugin-s3-0.8.2
Done installing documentation for fluent-plugin-s3 after 0 seconds
cs


혹시나 아래와 같은 오류가 발생한다면...


Fetching: strptime-0.1.9.gem (100%)
Building native extensions.  This could take a while...
ERROR:  Error installing fluent-plugin-s3:
        ERROR: Failed to build gem native extension.
 
    /opt/td-agent/embedded/bin/ruby -r ./siteconf20170405-3324-1dj4g72.rb extconf.rb
checking for rb_timespec_now()... *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.
cs


Development Tools 을 설치한다.


# yum groupinstall "Development Tools" "Legacy Software Development"
or
# apt-get install build-essential
cs



td-agent.conf 수정


설정 파일에는 fluent-logger 라이브러리를 통해 forward 타입으로 입력받을 것이고, fluentd 서버가 내부망에 있으므로 외부 접근은 걱정 없다.

forward 로부터 입력받은 이벤트 tag 별로, 별도의 디렉토리에 json 으로 메시지를 쌓고, 1시간에 1번씩 AWS S3 에 로그를 업로드 할 것이다.


# vi /etc/td-agent/td-agent.conf
 
<source>
    @type forward
</source>
 
<match fanbook.*>
    @type s3
 
    aws_key_id YOUR_AWS_KEY_ID
    aws_sec_key YOUR_AWS_SECRET_KEY
    s3_bucket YOUR_S3_BUCKET_NAME
    s3_region YOUR_S3_REGION
 
    path logs/${tag[1]}/%Y/%m/%d/
    s3_object_key_format %{path}%{time_slice}_%{index}.%{file_extension}
    store_as json
 
    <buffer tag,time>
        @type file
        path /var/log/td-agent/s3
        timekey 1h
        timekey_wait 10m
        timekey_use_utc true # use utc
    </buffer>
    <format>
        @type json
    </format>
</match>
cs



위 설정 파일을 간단하게 분석해 보자.

<match> 지시자에 out_s3 플러그인을 설정하였고, 그 아래에는 S3 키/버킷/리전 정보를 입력하였다.

path 파라미터에는 해당 버킷에 레코드가 저장될 경로를 입력한다.

태그/년/월/일을 뜻하는 ${tag}/%Y/%m/%d/ 문법은 v0.14 에서만 표시할 수 있다. v0.12 는 path / s3_object_key_format 에 이 문법을 지원하지 않는다.

오로지 이것 때문에 아직 안정화 되지 않은 v0.14 를 선택했다 ㅡ.ㅡ;

s3_object_key_format 은 업로드할 객체 키로 전체 경로를 입력한다.

store_as 는 어떤 파일로 S3 에 업로드 할 것인지를 결정한다. default 는 압축된 gzip 이지만, json 으로 설정했다. 이 값으로 %{file_extension} 가 결정된다.


output 을 담당하는 <match> 지시자 안에는, 이벤트를 버퍼링하도록 <buffer> 섹션을 넣을 수 있다.

버퍼링은 파일로 저장되도록 @type file 을 설정했다. @type 을 지정하지 않으면 defulat 인 memory 가 설정된다.

태그별로 파일을 만들고 시간 당 업로드를 실행할 계획이므로 <buffer tag,time> 라고 지정하였다.

path 는 버퍼링 파일이 저장될 경로이다.

timekey 는 파일을 생성하여 지정한 시간 동안 버퍼링을 받고 시간이 만료되면 새로운 파일로 버퍼링 처리를 반복한다.

timekey_wait 는 버퍼링 된 파일을 ouput 플러그인(s3) 에서 처리할 시기를 결정한다. 일반적으로 Fluentd 가 지연된 이벤트를 받을 수 있도록 대기시키는 시간이다.

timekey 가 1h 이고 timekey_wait 가 10m 라면, 1시간 10분에 업로드를 시작한다.


<format> 섹션은은 이벤트 형식이다. 기본적인 파일 타입은 out_file 로 예제에서 계속 보아왔던 time|tag|record(json) 이지만, time|tag 를 빼고 record 만 넣기 위해 json 으로 변경하였다.



테스트


input : 

echo '{"json":"message01"}' | /opt/td-agent/embedded/bin/fluent-cat test.hongs
echo '{"json":"message02"}' | /opt/td-agent/embedded/bin/fluent-cat test.hongs
cs


output :

S3/logs/hongs/2017/04/11/201704110320_0.json
 
{"json":"message01"}
{"json":"message02"}
cs




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

트랙백  0 , 댓글  0개가 달렸습니다.
secret