::: IT인터넷 :::

Docker로 MinIO 사용하기

곰탱이푸우 2022. 3. 3. 14:30
MinIO는 AWS S3와 같은 오브젝트(객체) 스토리지 서비스를 오픈소스로 제공하는 인프라이다.
AWS S3의 API와 호환되기 때문에 로컬에서 S3를 온프레미스 (On-premise) 형태로 사용하기 위해 구축하는 경우가 많다.
또는 AWS S3와 용어가 거의 동일하기 때문에, AWS S3를 사용하기 전에 숙달하는 목적으로 사용하기도 한다.

GitHub과 DockerHub 사이트는 다음과 같다.

 
원래 Apache V2 라이선스였는데, 2021년 5월 AGPL (Affero General Public License) v3.0 으로 변경되었다.
아래 사이트의 내용을 참고하면 AGPL 라이선스라 하더라도, 코드 변경 없이 단순 사용만 하는 경우는 공개 대상이 아닌 것을 알 수 있다.
배포시 의무사항 부분을 보면 다음과 같다.
수정 버전의 경우 네트워크를 통해 원격으로 대화하는 모든 사용자들에게
해당 소스를 받을 수 있는 기회를 제공해야 함
즉, 코드 수정을 하지 않으면 공개 의무가 발생하지 않으므로 편하게 사용하면 된다.

 

추가 참고 사항 (Updated. 2023.04.25)
위의 내용은 사내 폐쇄망 환경에서 코드 수정 없이 Docker 컨테이너로 띄워서 내부에서만 사용하는 경우에 해당한다.
- minio-py 파이썬 라이브러리를 이용하여 MinIO에 데이터 파일을 업로드/다운로드 하는 패키지를 제작했고,
- 해당 라이브러리를 이용한 로그인/업로드/다운로드는 소켓 통신에 해당되기 때문에 공개 의무는 발생하지 않으며,
  (결합 대상에 포함되지 않음)
- 공개 의무가 발생하더라도 사내 사용자를 대상으로만 소스코드를 공개하면 된다. (내부 형상관리시스템에 이미 공개...)
- 또한 Command Line을 통한 사용도 공개 대상이 아니다. (MinioClient를 사용하는 경우)
- 관련 글
https://www.oss.kr/oss_license_qna/show/7cbdf9cd-d158-4f1a-b138-3d94c385c116
https://www.oss.kr/oss_license_qna/show/89fc25c3-7f43-49c6-8cfa-d392a8139935
https://www.oss.kr/oss_license_qna/show/ad1c96f3-38d9-4a87-835d-5286c2311afb
https://www.oss.kr/oss_license_qna/show/5ef58eac-28c9-482e-b5e0-292244c2b198

단, 아래 경우에는 배포 또는 결합에 해당되므로 소스코드 공개 의무에 대한 전문가의 검토가 필요하다.
- 유료/무료 여부 상관 없이 MinIO 서비스를 인터넷에 공개하여 외부 사용자가 사용하는 경우 
- 자체 솔루션과 연동한 제품을 고객사에 납품하는 경우 (고객사 대상으로 공개 의무 발생)
   ex) 자체 솔루션에 iframe으로 MinIO 웹페이지를 출력
- 관련 글
https://min.io/compliance
https://www.gnu.org/licenses/agpl-3.0.en.html
https://www.oss.kr/oss_license_qna/show/ad1c96f3-38d9-4a87-835d-5286c2311afb
https://www.oss.kr/oss_license_qna/show/ebb310a4-b1d9-4652-a41e-b85778b37810
https://www.oss.kr/oss_license_qna/show/13a7e0bb-1f0b-444f-9251-56e4bd188f69
https://www.oss.kr/oss_license_qna/show/48cf50b6-ac43-4342-8772-82a5f9ee8b93

일부 표현의 모호성으로 인해 혼동이 있을 수 있으므로, 아래 글을 읽어볼 것을 권한다.
https://www.oss.kr/oss_license_qna/show/e078e03a-cde7-4b3b-abca-1f483f4f74b9

정리하면 다음과 같다.
- 개인적인 목적(학습, 테스트 등)으로 수정 없이 컨테이너만 실행해서 사용하는 경우에는 제약 없음
- 회사의 폐쇄망 환경에서 연구 및 자동화 목적으로 내부 구성원만 사용하는 경우에도 (사실상) 제약 없음
- 회사에서 고객 대상 제품(서비스)에 포함(연동)하려는 경우에는 제약 있음 (사내 변호사 또는 법무 담당과 검토 필요)

따라서 외부 고객에게 제공하기 위해 소속된 회사 제품과 연결하고자 한다면
GPL이 붙은 라이선스는 최대한 피하는 것을 권장한다.

 

MinIO는 단독 모드 (Stand-alone), 이레이저 코드 모드 (Erasure Code), 분산 모드 (Distributed)으로 설치 및 운영이 가능하다.
 
직접 설치해도 되지만, 독립 환경에서 실행하기 위해 Docker를 사용한다.

 

 

단독 모드 (Stand-alone)

단독 모드는 단일 노드에 단일 디스크를 사용한다.
 
주로 개발과 테스트 용도로 사용한다.
 

HTTP 모드

먼저 docker-compose.yml 파일을 작성한다.
$ vi docker-compose.yml

version: '3'
services:
  minio:
    # 저장소주소:포트 생략하면 dockerhub 사용
    # 버전 생략하면 latest 사용
    # 2022-01-20 현재 최신 버전은 RELEASE.2022-01-08T03-11-54Z
    image: 저장소주소:포트/minio/minio:버전
    command: server /data --console-address ":9001"
    container_name: minio    # 필요한 경우 수정
    environment:
      MINIO_ROOT_USER: minio    # 필요한 경우 수정
      MINIO_ROOT_PASSWORD: miniopass    # 필요한 경우 수정
    restart: always
    shm_size: '1gb'  # default는 64MB
    ports:
      - "9000:9000"    # minio 서비스 포트
      - "9001:9001"    # minio 콘솔 포트
    volumes:
      - /폴더경로/data:/data  # 현재 경로 하위인 경우 ./data:/data

 

아래 명령으로 컨테이너를 실행한다.
$ docker-compose up -d

# docker-compose가 설치 되어 있지 않다면 아래 명령어로 설치한다.
# sudo apt install docker-compose
 
네트워크 설정은 하지 않았으므로 컨테이너이름_default 이름의 Docker 네트워크가 생성된다.
 
컨테이너가 실행되었는지 확인한다.
 
http://localhost:9001 로 접속하면 아래와 같이 웹 화면을 확인할 수 있다.
 
 

HTTPS 모드

사설 인증서로 HTTPS 모드를 적용한다.
 
기존 자체 서명 인증서 만들기 내용은 아래 포스팅을 참고한다.
 

자체 서명 인증서 만들기

Docker로 테스트하거나 실서비스 운영을 하다보면 HTTPS 접근 방법에 대한 고민을 하게 된다. HTTPS를 사용하려면 공인 인증서 또는 사설 인증서를 적용해야 한다. 공인 인증서를 사용하는 방법은 크

www.bearpooh.com

 
위의 방법으로 생성한 자체 서명 인증서는 gitlab, jenkins, nexus에서 정상 사용이 가능하다.
 
그러나 기존에 생성한 자체 서명 인증서를 사용하면 로그인할떄 아래와 같은 오류 메시지가 출력된다.
 
MinIO에서는 IP SANs (Subject Alt Name) 항목에 해당 서버의 FQDN이나 IP 주소가 지정되어야 한다.
 
따라서 아래 방법으로 진행한다.

 

 

인증서 경로 생성
docker-compose를 사용하여 MinIO Docker를 실행할 것이다.
따라서 MinIO의 docker-compose.yml 파일이 위치한 경로로 이동하여 certs 폴더를 생성한다.
$ cd MinIO경로  # docker-compose.yml이 위치한 경로
$ mkdir certs
$ cd certs
 
루트 인증서 생성
자체 서명하는 사설 인증서에 사용할 루트 인증서를 생성한다.
# root ca 키생성 
$ openssl genrsa -aes256 -out rootca.key 2048

# root ca 요청서 만들기 
$ openssl req -new -key rootca.key -out rootca.csr
You are about to be asked to enter information that will be incorporated 
into your certificate request. 
What you are about to enter is what is called a Distinguished Name or a DN. 
There are quite a few fields but you can leave some blank 
For some fields there will be a default value, 
If you enter '.', the field will be left blank. 
----- 
Country Name (2 letter code) [XX]:KR 
State or Province Name (full name) []:GG  # 경기도 
Locality Name (eg, city) [Default City]:SN  # 성남시 
Organization Name (eg, company) [Default Company Ltd]:test  # 조직/회사명 입력 
Organizational Unit Name (eg, section) []:unit  # 부서명 입력 
Common Name (eg, your name or your server's hostname) []:test  # 서버 이름 입력 
Email Address []:test@test.com    # 이메일 주소 
Please enter the following 'extra' attributes 
to be sent with your certificate request 
A challenge password []: testcerts  # 공개되도 상관 없는 암호 입력   
  An optional company name []:    # 비워놓고 엔터 (다른 이름 부여 가능)

# root ca 인증서 만들기
$ openssl x509 -req -days 3650 -set_serial 1 -in rootca.csr -signkey rootca.key \
    -out rootca.crt 
Signature ok 
subject=C = KR, ST = GG, L = SN, O = test, OU = unit, CN = test, 
emailAddress = test@test.com
Getting Private key
 
openssl.conf 작성
사설 인증서에 입력할 서버 정보를 입력한다.
$ vi openssl.conf

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]  # 위의 distinguished_name 항목에 전달 될 내용
C = KR    # 국가명
ST = GG    # 행정구역 (State)
L = SN    # 행정구역 (City)
O = test    # 회사 (단체) 이름
OU = unit    #  조직 (부서) 이름
CN = test    # 서버 이름 (또는 FQDN)

# 아래 부분이 가장 중요
[v3_req]    # 위의 x509_extensions에 전달 될 내용
subjectAltName = @alt_names    # 아래 alt_names 내용 사용

[alt_names]
IP.1 = 127.0.0.1    # IP 주소는 127.0.0.1 
DNS.1 = localhost    # 서버 주소는 localhost

# 서버에서 운영할 경우 IP.2 추가하고 해당 서버 IP 입력
# 서버에서 운영할 경우 DNS.2 추가하고 해당 서버 FQDN 입력
 
 
사설 인증서 생성
참고로 사설 인증서의 키 (KEY) 파일 이름은 private.key, 사설 인증서 (CRT)의 파일 이름은 public.crt로 되어야 한다.
 
아래 명령을 참고하여 사설 인증서에 사용할 private.key 파일을 생성한다.
앞서 생성한 openssl.conf 파일을 사용한다.
# 웹용 인증서 키 만들기
$ openssl genrsa -aes256 -out private.key 2048

# 키 암호 제거
$ openssl rsa -in private.key -out private.np.key

# 요청서 만들기
# -config 옵션의 경우 conf 파일이 없으면 입력하지 않음
$ openssl req -new -key private.np.key -out public.csr -config openssl.conf
 
아래 명령을 참고하여 사설 인증서인 public.crt 파일을 생성한다.
앞서 생성한 openssl.conf 파일을 사용한다.
# 인증서 만들기
openssl x509 -req -days 3650 -extensions v3_req -in public.csr \
  -CA rootca.crt -CAcreateserial -CAkey rootca.key \
  -out public.crt -extfile openssl.conf

# 확인
$ openssl x509 -text -in public.crt
 
아래와 같이 Subject Alternative Name (SANs) 항목에 주소가 표시되면 된다.
 
docker-compose 작성
MinIO Docker 컨테이너를 생성하기 위한 docker-compose.yml 파일을 생성한다.
$ vi docker-compose.yml

version: '3'
services:
  minio:
    # 저장소주소:포트 생략하면 dockerhub 사용
    # 버전 생략하면 lastest 사용
    # 2022-01-20 현재 최신 버전은 RELEASE.2022-01-08T03-11-54Z
    image: 저장소주소:포트/minio/minio:latest
    command: server /data --console-address ":9001"
    container_name: minio    # 필요한 경우 수정
    environment:
      MINIO_ROOT_USER: minio    # 필요한 경우 수정
      MINIO_ROOT_PASSWORD: miniopass    # 필요한 경우docke 수정
      MINIO_CERT_PASSWD: testcerts    # 인증서 암호 입력 (인증서 암호가 없으면 해당 옵션 삭제)
      MINIO_SERVER_URL: https://127.0.0.1:9000
      TZ: Asia/Seoul
    restart: always
    shm_size: '1gb'  # default는 64MB
    ports:
      - "9000:9000"    # minio 서비스 포트
      - "9001:9001"    # minio 콘솔 포트
    volumes:
      - ./data:/data  # 현재 경로 하위인 경우 ./data:/data
      - ./certs:/root/.minio/certs
 
 
docker-compose 실행
아래 명령으로 컨테이너를 실행한다.
$ docker-compose up -d

# docker-compose가 설치 되어 있지 않다면 아래 명령어로 설치한다.
# sudo apt install docker-compose

# docker-compose의 yml 파일명이 docker-compose.yml이 아닌 경우 아래와 같이 실행한다.
# docker-compose -f yml파일명 up -d

# Docker 컨테이너 실행 로그 출력
# docker logs 컨테이너이름
 
MinIO 접속 및 로그인
MinIO 컨테이너가 정상적으로 실행되면 접속해본다.
 
아래와 같이 https로 접속해도 정상적으로 로그인이 되어야 한다.
 
 

이레이저 코드 모드 (Erasure Code)

MinIO에서는 손상 된 데이터를 복구할 수 있는 이레이저 코드 (Erasure Code) 모드를 제공한다.
 
일반적으로 서버에서는 데이터의 손상을 복구하기 위해 RAID를 사용한다.
4개의 디스크에 RAID 5의 경우 1개는 복구를 위한 정보를 저장하는 용도로 사용하기 때문에 실제 사용 가능한 디스크는 3개이다.
데이터가 손상 될 경우 복구 정보를 디스크의 정보를 활용해서 복구하게 된다.
 
이레이저 코드 모드는 이러한 RAID를 구성할 수 없는 경우에 사용할 수 있는 방법이다.
MinIO에 사용하는 디스크를 4개 이상 2의 배수 (4, 6, 8, 10, 12, 14, 16 등)로 구성하는 방법을 사용한다.
디스크에 나눠서 저장하고 데이터 손상이 발생할 경우 다른 디스크의 정보를 활용하여 복구한다.
 
자세한 내용은 아래 사이트를 참고한다.
Docker를 사용하는 경우 공유 볼륨을 4개 이상 적용하면 된다.
 
아래와 같이 docker-compose.yml 을 작성하고 컨테이너를 생성한다.
공유 볼륨을 보면 디스크가 4개인 것을 알 수 있다.
$ vi docker-compose.yml

version: '3'
services:
  minio:
    # 저장소주소:포트 생략하면 dockerhub 사용
    # 버전 생략하면 lastest 사용
    # 2022-01-20 현재 최신 버전은 RELEASE.2022-01-08T03-11-54Z
    image: 저장소주소:포트/minio/minio:latest
    command: server /data1 /data2 /data3 /data4 --console-address ":9001"
    container_name: minio
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: miniopass
    restart: always
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - ./data1:/data1
      - ./data2:/data2
      - ./data3:/data3
      - ./data4:/data4
 
HTTPS 모드를 적용하고자 한다면 단독 모드 (Stand-alone)의 HTTPS 모드를 참고한다.

 

 

분산 모드 (Distributed)

MinIO의 경우 다수의 서버에 분산해서 운영할 수 있는 분산 모드를 지원한다.
이레이저 코드 모드가 단일 서버에 다수의 디스크로 운영하는 방법이라면, 분산 모드는 다수 서버로 운영할 수 있는 방법이다.
물론 분산 모드에서도 이레이저 코드 모드를 적용해서 운영할 수 있다.
 
분산 모드의 경우 개인이나 소규모 조직보다, 빅데이터 같이 대용량 데이터를 사용해야 하거나 조직의 규모가 큰 경우 유용하다.
분산 모드인 만큼 데이터 보호, 고가용성을 제공하는 장점이 있다.
데이터 레플리카 (복제본) 생성과 버저닝 기능은 분산 모드에서만 제공한다.
 
자세한 내용은 아래 사이트를 참고한다.
Docker를 사용하는 경우 컨테이너를 4개 생성하고 동일 네트워크로 묶어주면 된다.
 

단독 모드 분산 구성

아래와 같이 docker-compose.yml 을 작성하고 컨테이너를 생성한다.
컨테이너가 4개 인 것을 알 수 있다.
$ vi docker-compose.yml

version: '3'
services:
  minio1:
    # 2022-01-20 현재 최신 버전은 RELEASE.2022-01-08T03-11-54Z
    image: 저장소주소:포트/minio/minio:latest
    command: server http://minio{1...4}:9000/data --console-address ":9001"
    container_name: minio1
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: miniopass
    restart: always
    ports:
      - "9101:9000"
      - "9001:9001"  # 웹콘솔은 minio1에서 운영
    volumes:
      - ./minio1:/data
  minio2:
    # 2022-01-20 현재 최신 버전은 RELEASE.2022-01-08T03-11-54Z
    image: 저장소주소:포트/minio/minio:latest
    command: server http://minio{1...4}:9000/data --console-address ":9001"
    container_name: minio2
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: miniopass
    restart: always
    ports:
      - "9102:9000"
    volumes:
      - ./minio2:/data
  minio3:
    # 2022-01-20 현재 최신 버전은 RELEASE.2022-01-08T03-11-54Z
    image: 저장소주소:포트/minio/minio:latest
    command: server http://minio{1...4}:9000/data --console-address ":9001"
    container_name: minio3
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: miniopass
    restart: always
    ports:
      - "9103:9000"
    volumes:
      - ./minio3:/data
  minio4:
    # 2022-01-20 현재 최신 버전은 RELEASE.2022-01-08T03-11-54Z
    image: 저장소주소:포트/minio/minio:latest
    command: server http://minio{1...4}:9000/data --console-address ":9001"
    container_name: minio4
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: miniopass
    restart: always
    ports:
      - "9104:9000"
    volumes:
      - ./minio4:/data
 

 

이레이저 코드 모드 분산 구성

아래 코드를 참고하여 docker-compose.yml 을 작성하고 컨테이너를 생성한다.
컨테이너가 4개이고, 공유 볼륨이 2개씩 구성 된 것을 알 수 있다.
https://raw.githubusercontent.com/minio/minio/master/docs/orchestration/docker-compose/docker-compose.yaml

 

$ vi docker-compose.yml

version: '3.7'
# starts 4 docker containers running minio server instances. Each
# minio server's web interface will be accessible on the host at port
# 9001 through 9004.
services:
  minio1:
    # 2022-01-20 현재 최신 버전은 RELEASE.2022-01-08T03-11-54Z
    image: 저장소주소:포트/minio/minio:latest
    volumes:
      - data1-1:/data1
      - data1-2:/data2
    ports:
      - "9001:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3
  minio2:
    # 2022-01-20 현재 최신 버전은 RELEASE.2022-01-08T03-11-54Z
    image: 저장소주소:포트/minio/minio:latest
    volumes:
      - data2-1:/data1
      - data2-2:/data2
    ports:
      - "9002:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3
  minio3:
    # 2022-01-20 현재 최신 버전은 RELEASE.2022-01-08T03-11-54Z
    image: 저장소주소:포트/minio/minio:latest
    volumes:
      - data3-1:/data1
      - data3-2:/data2
    ports:
      - "9003:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3
  minio4:
    # 2022-01-20 현재 최신 버전은 RELEASE.2022-01-08T03-11-54Z
    image: 저장소주소:포트/minio/minio:latest
    volumes:
      - data4-1:/data1
      - data4-2:/data2
    ports:
      - "9004:9000"
    environment:
      MINIO_ACCESS_KEY: minio
      MINIO_SECRET_KEY: minio123
    command: server http://minio{1...4}/data{1...2}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3
## By default this config uses default local driver,
## For custom volumes replace with volume driver configuration.
volumes:
  data1-1:
  data1-2:
  data2-1:
  data2-2:
  data3-1:
  data3-2:
  data4-1:
  data4-2:
 
 

결론

일단 서버에 RAID가 구성되어 있어서 이레이저 모드는 고려하지 않는다.
또한 데이터가 크거나 많지 않고, 분산 환경으로 운영할 필요가 없어 당분간 단일 모드로 운영한다.
 
분산 환경은 쿠버네티스 환경이 구축 된 이후에 고려해볼만 한 것 같다.
 
향후 분산 환경이 필요한 경우 위의 내용을 참고해서 검토해본다.
 
아래 포스팅을 참고하여 정리했다.