본문 바로가기
테크

MinIO로 S3 호환 가능한 파일 스토리지 플랫폼 구축하기

2022.11.25

안녕하세요. 와디즈에서 서비스플랫폼 개발을 담당하고 있는 정인철 프로입니다.

와디즈에서 펀딩을 진행하는 제품은 사전에 엄격한 심사를 거치게 되는데요. 이때 필요한 서류를 요청을 드리고 있어요. 심사 서류는 암호화하여 안전하게 보관, 관리하고 있습니다. 이번 글에서는 암호화된 파일의 안전한 보관을 위해 S3 호환 가능한 MinIO를 사용하여 사내 파일 스토리지 플랫폼을 구축한 과정을 소개하려 합니다.

 

요구 사항 및 시스템 개선

먼저, 파일 스토리지 플랫폼은 사업부의 요구 사항과 시스템 개선 두 마리 토끼를 잡는 목표를 설정했어요.

사업부 요구 사항

“와디즈에 업로드된 심사 서류 파일이 사내 보안 규정에 따라 N년이 지나면 자동으로 삭제되면 좋겠어요”

시스템 개선

이번 신규 파일 스토리지 플랫폼 구축 전에는 서비스마다 파일을 관리하고 있었어요. 즉, 암호화된 파일이 한 곳에서 관리되지 못하고 있었죠. 사내 보안 규정에 따라 업로드 후 N년 이상 지나면 자동으로 파일이 삭제되어야 하는데요. 이 또한 팀별로 관리를 하고 있었어요. 이러한 상황들 때문에 암호화된 파일 관리의 로직이 분산되면서, 관련 로직 변경 시 각 서비스를 수정, 배포해야 하는 이슈가 있었습니다. 개발 생산성 측면에서의 문제도 있었고요.

정리하면 아래와 같습니다.

MinIO 로 S3 호환 가능한 파일 스토리지 플랫폼 구축_요구사항과 사용 기술

이제 어떻게 파일 스토리지 플랫폼을 구성했는지 좀 더 자세히 알아보겠습니다.

 

Distributed MinIO 구성

암호화된 파일을 저장할 공간으로 Distributed MinIO를 구성했어요. 구성을 위해 4대의 서버를 할당 받았습니다. 각각의 서버에는 ‘/stg’라는 마운트 포인트에 외장 블록 스토리지를 연결하여 로컬 파일 시스템처럼 사용할 수 있게 했어요. 그 후 MinIO 도메인을 등록했고, nginx를 이용하여 MinIO 도메인으로 접근하면 minio01 ~ 04로 요청이 전달되도록 설정했습니다.

그리고, MinIO 의 공식 홈페이지에서 MinIO Quickstart Guide, Distributed MinIO Quickstart Guide, How to secure access to MinIO server with TLS를 참고하여 Distributed MinIO을 구성하였습니다.

아래는 구성 환경이에요. 실제 구성한 환경을 바탕으로 재구성 했습니다.

  • OS : RHEL/CentOS/Oracle Linux 7
  • MinIO : 2021-04-22T15:44:28Z 버전
  • IP : 1.2.3.4 ,1.2.3.5 ,1.2.3.6 , 1.2.3.7
  • Domain : minio01.foo.com, minio02.foo.com, minio03.foo.com, minio04.foo.com
  • 사용 포트 : 9000 (MinIO 기본 포트), 443 (TLS 사용)

그럼, 과정을 한 번 살펴볼게요.

1. MinIO Distributed를 구성하기 위해 /etc/hosts를 등록을 해줍니다.

# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
1.2.3.4 minio01.foo.com
1.2.3.5 minio02.foo.com
1.2.3.6 minio03.foo.com
1.2.3.7 minio04.foo.com

2. MinIO 및 TLS를 사용하기 위해 9000, 443 포트를 허용해 줍니다.

firewall-cmd --zone=public --add-port=9000/tcp --permanent
firewall-cmd --zone=public --add-port=443/tcp --permanent
firewall-cmd --reload

3. MinIO 설치

3-1. MinIO 파일 다운로드를 합니다.

[wadiz@minio01 ~]# wget https://dl.min.io/server/minio/release/linux-amd64/minio
[wadiz@minio01 ~]# cd /usr/local/bin
[wadiz@minio01 ~]# wget https://dl.min.io/server/minio/release/linux-amd64/minio
[wadiz@minio01 ~]# chmod +x minio

3-2. MinIO configuration을 작성합니다.

[wadiz@minio01 ~]# vi /etc/minio/minio.conf
MINIO_CLUSTER = --address :9000 https://minio0{1...4}.foo.com/stg/data/data{1...4}
MINIO_ACCESS_KEY = "MINIO_ACCEESS_KEY"
MINIO_SECRET_KEY = "MINIO_SECRET_KEY"

3-3. MinIO 관리를 위한 system daemon을 등록합니다.

[wadiz@minio01 ~]# vi /etc/systemd/system/minio.service

[Unit]
Description=Distributed Minio
Documentation=https://docs.minio.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio

[Service]
WorkingDirectory=/usr/local
User= username
Group= usergroup
PermissionsStartOnly=true
EnvironmentFile=-/etc/minio/minio.conf

ExecStart=/usr/local/bin/minio server $MINIO_CLUSTER
StandardOutput=journal
StandardError=inherit

# Let systemd restart this service always
Restart=always
# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=65536
# Disable timeout logic and wait until process is stopped
TimeoutStopSec=infinity
SendSIGKILL=no
[Install]
WantedBy=multi-user.target

4. TLS를 위해 minIO에 인증서를 적용합니다.

인증서는 ~/.minio/certs 디렉토리를 생성한 후 private.key 와 public.crt 을 넣어 줍니다.

[wadiz@minio01 ~]# systemctl daemon-reload

5. 4대의 서버에서 minio를 실행시켜 줍니다.

[root@minio01 ~]# systemctl start minio
[root@minio02 ~]# systemctl start minio
[root@minio03 ~]# systemctl start minio
[root@minio04 ~]# systemctl start minio

6. nginx 구성

nginx의 도메인( minio.foo.com )으로 접근하면 minio01 ~ 04로 요청이 전달되도록 하기 위해, upstream 설정을 nginx.conf를 수정 해줍니다.

# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
   worker_connections 1024;
}

http {
   log_format main '$remote_addr - $remote_user [$time_local] "$request" '
   '$status $body_bytes_sent "$http_referer" '
   '"$http_user_agent" "$http_x_forwarded_for"';

   access_log /var/log/nginx/access.log main;

   sendfile on;
   tcp_nopush on;
   tcp_nodelay on;
   keepalive_timeout 65;
   types_hash_max_size 2048;

   include /etc/nginx/mime.types;
   default_type application/octet-stream;

   # Load modular configuration files from the /etc/nginx/conf.d directory.
   # See http://nginx.org/en/docs/ngx_core_module.html#include
   # for more information.
   include /etc/nginx/conf.d/*.conf;

   # 01. minIO 서버 리스트 추가
   upstream minio_servers {
     server 1.2.3.4:9000;
     server 1.2.3.5:9000;
     server 1.2.3.6:9000;
     server 1.2.3.7:9000;
   }
   server {
     listen 80 default_server;
     listen [::]:80 default_server;
     server_name dev-minio.wadiz.kr 192.168.2.51;
     root /usr/share/nginx/html;
     return 301 https://$server_name$request_uri;

     # Load configuration files for the default server block.
     include /etc/nginx/default.d/*.conf;

     location / {
     }

     error_page 404 /404.html;
     location = /404.html {
     }

     error_page 500 502 503 504 /50x.html;
     location = /50x.html {
     }
  }

 # 02. nginx 443 적용
 server {
   listen 443 ssl;
   listen [::]:443;

   # 02-1. nginx domain 설정
   server_name minio.foo.com 1.2.3.8;
   ignore_invalid_headers off;
   proxy_buffering off;

   root /usr/share/nginx/html;

   # 02-2. 인증서 적용
   ssl_certificate "certification.crt 경로";
   ssl_certificate_key "certification.key 경로";

   ssl_session_cache shared:SSL:1m;
   ssl_session_timeout 60m;
   ssl_protocols TLSv1.2 TLSv1.3;
   ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS;
   ssl_prefer_server_ciphers on;

   location / {
     proxy_pass https://minio_servers;
     proxy_set_header Host $host;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header X-Client-DN $ssl_client_s_dn;
     proxy_set_header X-SSL-Subject $ssl_client_s_dn;
     proxy_set_header X-SSL-Issuer $ssl_client_i_dn;
     proxy_read_timeout 1800;
     proxy_connect_timeout 1800;
     proxy_http_version 1.1;
     proxy_set_header Connection "";
     chunked_transfer_encoding off;

     client_max_body_size 10M;

   }
   error_page 404 /404.html;
   location = /404.html {
   }

   error_page 500 502 503 504 /50x.html;
   location = /50x.html {
     root html;
   }
 }
}

nginx를 실행시켜 줍니다.

[root@nginx ~]# systemctl start nginx

마지막으로 해당 도메인 주소(minio.foo.com)로 접속해 사용할 Bucket을 만들어주는 것으로 설치를 마무리했습니다!

minio.foo.com

minio.foo.com

 

파일 스토리지 플랫폼 구성

파일 스토리지 플랫폼 구성

 

파일 암호화 업로드 및 다운로드

파일 서비스를 통해 SecretKey를 안전하게 저장하고, 암호화했어요. MinIO에 저장할 수 있도록 구성한 거죠.

파일 암호화 업로드 및 다운로드

 

백업 구성

파일 서비스를 백업해주는 ‘파일 백업 서비스’를 만들었어요. 백업을 위해 주기적으로 특정 시간에 실행하는 구조로 정했습니다. 암호화된 백업 데이터는 AWS S3에 저장하도록 구성했어요.

백업 구성

마치며

파일 스토리지 플랫폼을 구축한 후, 펀딩을 넘어 스토어, 멤버십 서비스에서도 이를 사용하고 있어요. 지금은 기본적인 기능들만 수행하고 있지만, 다음에는 각 서비스 버킷에 대한 요청 내역을 볼 수 있는 Access logging 기능과 사업부별 접근 권한 설정 기능 등을 추가해 더욱 견고한 파일 스토리지 플랫폼으로 가져갈 생각입니다.

설계부터 구축 그리고 운영 환경에 오픈하기까지 여러 동료에게 많은 도움을 받았어요. 제가 생각하지 못했던 부분에 대해 조언과 응원도 받았죠. 이곳은 새로운 것을 시도해보기 좋은 회사라 생각합니다. 앞으로도 많은 새로운 시도를 하면서 경험을 쌓고, 보람을 느끼는 진국이(와디즈인)가 되고 싶네요 😉

👇 태그를 클릭하면 같은 키워드의 글을 모아볼 수 있어요.

  • 좋아요