515 lines
21 KiB
Markdown
515 lines
21 KiB
Markdown
|
|
# OpenSearch 3.1 클러스터 구축 가이드 (3-Node)
|
||
|
|
|
||
|
|
본 문서는 Ubuntu 24.04 환경에서 3대의 서버를 이용하여 OpenSearch 3.1 클러스터를 구축하고, 최종적으로 로드 밸런서(LB) 중심의 안정적인 프로덕션 아키텍처로 전환하는 전체 과정을 상세히 기술한다.
|
||
|
|
|
||
|
|
## 버전 히스토리
|
||
|
|
* **v1.0:** 개별 노드 직접 접속 방식의 초기 클러스터 구축
|
||
|
|
* **v2.0:** 로드 밸런서(LB)를 도입하여 고가용성 및 단일 접속점을 확보한 프로덕션 아키텍처로 전환
|
||
|
|
|
||
|
|
## 목차
|
||
|
|
1. [사전 정보](#1-사전-정보)
|
||
|
|
2. [**v1.0: 초기 클러스터 구축 (LB 미사용)**](#v10-초기-클러스터-구축-lb-미사용)
|
||
|
|
1. [1단계: 설치](#1단계-설치)
|
||
|
|
2. [2단계: 사전 준비](#2단계-사전-준비)
|
||
|
|
3. [3단계: OpenSearch 설정 (`opensearch.yml`)](#3단계-opensearch-설정-opensearchyml)
|
||
|
|
4. [4단계: JVM 및 시스템 설정](#4단계-jvm-및-시스템-설정)
|
||
|
|
5. [5단계: 보안 플러그인 설정](#5단계-보안-플러그인-설정)
|
||
|
|
6. [6단계: 클러스터 시작 및 적용](#6단계-클러스터-시작-및-적용)
|
||
|
|
7. [7단계: Dashboards 설정](#7단계-dashboards-설정)
|
||
|
|
8. [8단계: Dashboards 시작 및 확인](#8단계-dashboards-시작-및-확인)
|
||
|
|
9. [9단계: JWT 인증 테스트](#9단계-jwt-인증-테스트)
|
||
|
|
3. [**v2.0: LB 중심 아키텍처로 전환**](#v20-lb-중-심-아키텍처로-전환)
|
||
|
|
1. [10단계: 아키텍처 목표](#10단계-아키텍처-목표)
|
||
|
|
2. [11단계: LB 준비 및 Nginx 프록시 구축](#11단계-lb-준비-및-nginx-프록시-구축)
|
||
|
|
3. [12단계: OpenSearch 및 Dashboards 재구성](#12단계-opensearch-및-dashboards-재구성)
|
||
|
|
4. [13단계: 최종 전환 및 테스트](#13단계-최종-전환-및-테스트)
|
||
|
|
4. [**부록: 운영 및 관리**](#부록-운영-및-관리)
|
||
|
|
1. [주요 트러블슈팅 및 교훈](#주요-트러블슈팅-및-교훈)
|
||
|
|
2. [추가 권장 사항 및 팁](#추가-권장-사항-및-팁)
|
||
|
|
3. [사용자/역할 추가 (Dashboards UI)](#사용자역할-추가-dashboards-ui)
|
||
|
|
4. [인증서에서 정확한 DN 추출하기](#인증서에서-정확한-dn-추출하기)
|
||
|
|
5. [`-nameopt RFC2253` 옵션 상세 설명](#-nameopt-rfc2253-옵션-상세-설명)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 1. 사전 정보
|
||
|
|
|
||
|
|
### 서버 사양 (3대 공통)
|
||
|
|
* **CPU:** 8 vCPU
|
||
|
|
* **Memory:** 65 GB
|
||
|
|
* **Disk:** 2 TB SSD
|
||
|
|
* **OS:** Ubuntu 24.04
|
||
|
|
* **SSH Port:** 42894
|
||
|
|
|
||
|
|
### 노드 정보
|
||
|
|
| 항목 | Node1 | Node2 | Node3 |
|
||
|
|
| :--- | :--- | :--- | :--- |
|
||
|
|
| **호스트네임** | ds-opensearch001 | ds-opensearch002 | ds-opensearch003 |
|
||
|
|
| **외부 DNS (v1.0)** | ds-osearch001.oneunivrs.com | ds-osearch002.oneunivrs.com | ds-osearch003.oneunivrs.com |
|
||
|
|
| **내부 DNS** | ds-osnode001.oneunivrs.com | ds-osnode002.oneunivrs.com | ds-osnode003.oneunivrs.com |
|
||
|
|
| **Private IP** | 10.0.10.8 | 10.0.10.9 | 10.0.10.10 |
|
||
|
|
|
||
|
|
### SSL 인증서
|
||
|
|
* **종류:** 와일드카드 `*.oneunivrs.com`
|
||
|
|
* **초기 위치:** Node1의 `/data/cert/`
|
||
|
|
* **파일:** `oneunivrs.pem`, `root.pem`, `oneunivrs_key.pem`
|
||
|
|
* **DN:** `C=KR, ST=Seoul, O="ONEUNIVERSE Co.,Ltd.", CN=*.oneunivrs.com`
|
||
|
|
|
||
|
|
### JWT 인증
|
||
|
|
* **방식:** 대칭키 (HS256)
|
||
|
|
* **서명키:** `UGdiOTdLVjFBTWtndTRNRiZmVjdwMDdCRW1lSSUxTnA=`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## v1.0: 초기 클러스터 구축 (LB 미사용)
|
||
|
|
|
||
|
|
이 버전은 로드 밸런서 없이 각 노드에 직접 접속하는 방식의 기본 클러스터를 구축한다.
|
||
|
|
|
||
|
|
### 1단계: 설치
|
||
|
|
모든 작업은 `root` 계정으로 진행.
|
||
|
|
|
||
|
|
**[모든 노드]**
|
||
|
|
APT 저장소 설정 후 OpenSearch 설치. 초기 admin 비밀번호 지정.
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# APT 저장소 설정 (공식 문서 참조)
|
||
|
|
|
||
|
|
# OpenSearch 설치 (3.1.0)
|
||
|
|
env OPENSEARCH_INITIAL_ADMIN_PASSWORD='DHp5#r#GYQ9d' apt-get install opensearch=3.1.0
|
||
|
|
|
||
|
|
# Dashboards도 미리 설치
|
||
|
|
apt-get install opensearch-dashboards=3.1.0
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2단계: 사전 준비
|
||
|
|
**[모든 노드]**
|
||
|
|
#### 2.1. 데이터/로그 디렉토리 생성
|
||
|
|
```bash
|
||
|
|
mkdir -p /data/opensearch/{data,logs}
|
||
|
|
chown -R opensearch:opensearch /data/opensearch
|
||
|
|
```
|
||
|
|
#### 2.2. 인증서 복사 및 권한 설정
|
||
|
|
**[Node1]**
|
||
|
|
```bash
|
||
|
|
mkdir -p /etc/opensearch/certs
|
||
|
|
cp /data/cert/*.pem /etc/opensearch/certs/
|
||
|
|
|
||
|
|
# 다른 노드로 전송
|
||
|
|
scp -P 42894 /etc/opensearch/certs/*.pem root@ds-osnode002.oneunivrs.com:/etc/opensearch/certs/
|
||
|
|
scp -P 42894 /etc/opensearch/certs/*.pem root@ds-osnode003.oneunivrs.com:/etc/opensearch/certs/
|
||
|
|
```
|
||
|
|
|
||
|
|
**[모든 노드]**
|
||
|
|
```bash
|
||
|
|
chown -R opensearch:opensearch /etc/opensearch/certs
|
||
|
|
chmod 600 /etc/opensearch/certs/oneunivrs_key.pem # 개인키 권한 축소
|
||
|
|
chmod 644 /etc/opensearch/certs/oneunivrs.pem /etc/opensearch/certs/root.pem
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3단계: OpenSearch 설정 (`opensearch.yml`)
|
||
|
|
**[모든 노드]**
|
||
|
|
기존 파일 백업 후, 각 노드에 맞게 `/etc/opensearch/opensearch.yml` 작성.
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# 클러스터 이름
|
||
|
|
cluster.name: ds-cluster
|
||
|
|
|
||
|
|
# [중요] node.name은 내부 DNS와 일치시킬 것 (클러스터링 실패 방지)
|
||
|
|
# Node1: node.name: ds-osnode001.oneunivrs.com
|
||
|
|
# Node2: node.name: ds-osnode002.oneunivrs.com
|
||
|
|
# Node3: node.name: ds-osnode003.oneunivrs.com
|
||
|
|
node.name: ds-osnode001.oneunivrs.com # 각 노드에 맞게 수정
|
||
|
|
|
||
|
|
# 역할
|
||
|
|
node.roles: [ cluster_manager, data ]
|
||
|
|
|
||
|
|
# 경로
|
||
|
|
path.data: /data/opensearch/data
|
||
|
|
path.logs: /data/opensearch/logs
|
||
|
|
|
||
|
|
# 메모리 잠금
|
||
|
|
bootstrap.memory_lock: true
|
||
|
|
|
||
|
|
# 네트워크
|
||
|
|
network.host: 0.0.0.0
|
||
|
|
http.port: 9200
|
||
|
|
transport.port: 9300
|
||
|
|
|
||
|
|
# 클러스터링
|
||
|
|
discovery.seed_hosts:
|
||
|
|
- ds-osnode001.oneunivrs.com
|
||
|
|
- ds-osnode002.oneunivrs.com
|
||
|
|
- ds-osnode003.oneunivrs.com
|
||
|
|
|
||
|
|
# [중요] 최초 마스터 후보 목록. node.name과 일치해야 함.
|
||
|
|
cluster.initial_cluster_manager_nodes:
|
||
|
|
- ds-osnode001.oneunivrs.com
|
||
|
|
- ds-osnode002.oneunivrs.com
|
||
|
|
- ds-osnode003.oneunivrs.com
|
||
|
|
|
||
|
|
# 보안 플러그인
|
||
|
|
plugins.security.ssl.transport.enabled: true
|
||
|
|
plugins.security.ssl.transport.pemcert_filepath: certs/oneunivrs.pem
|
||
|
|
plugins.security.ssl.transport.pemkey_filepath: certs/oneunivrs_key.pem
|
||
|
|
plugins.security.ssl.transport.pemtrustedcas_filepath: certs/root.pem
|
||
|
|
plugins.security.ssl.transport.enforce_hostname_verification: false
|
||
|
|
|
||
|
|
plugins.security.ssl.http.enabled: true
|
||
|
|
plugins.security.ssl.http.pemcert_filepath: certs/oneunivrs.pem
|
||
|
|
plugins.security.ssl.http.pemkey_filepath: certs/oneunivrs_key.pem
|
||
|
|
plugins.security.ssl.http.pemtrustedcas_filepath: certs/root.pem
|
||
|
|
|
||
|
|
# [주의] DN의 쉼표(,)는 백슬래시 두 개(\\)로 이스케이프
|
||
|
|
plugins.security.nodes_dn:
|
||
|
|
- "CN=*.oneunivrs.com,O=ONEUNIVERSE Co.\\,Ltd.,ST=Seoul,C=KR"
|
||
|
|
plugins.security.authcz.admin_dn:
|
||
|
|
- "CN=*.oneunivrs.com,O=ONEUNIVERSE Co.\\,Ltd.,ST=Seoul,C=KR"
|
||
|
|
|
||
|
|
plugins.security.allow_default_init_securityindex: true
|
||
|
|
plugins.security.audit.type: internal_opensearch
|
||
|
|
plugins.security.restapi.roles_enabled: ["all_access", "security_rest_api_access"]
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4단계: JVM 및 시스템 설정
|
||
|
|
**[모든 노드]**
|
||
|
|
#### 4.1. JVM 힙 메모리
|
||
|
|
`/etc/opensearch/jvm.options` 파일 수정. 31GB로 설정.
|
||
|
|
```bash
|
||
|
|
sed -i 's/^-Xms1g/#-Xms1g/' /etc/opensearch/jvm.options
|
||
|
|
sed -i 's/^-Xmx1g/#-Xmx1g/' /etc/opensearch/jvm.options
|
||
|
|
echo -e "\n-Xms31g\n-Xmx31g" >> /etc/opensearch/jvm.options
|
||
|
|
```
|
||
|
|
#### 4.2. Systemd 오버라이드
|
||
|
|
메모리 잠금과 경로 권한 부여.
|
||
|
|
```bash
|
||
|
|
mkdir -p /etc/systemd/system/opensearch.service.d
|
||
|
|
cat <<EOF > /etc/systemd/system/opensearch.service.d/override.conf
|
||
|
|
[Service]
|
||
|
|
LimitMEMLOCK=infinity
|
||
|
|
ReadWritePaths=/data/opensearch/
|
||
|
|
EOF
|
||
|
|
|
||
|
|
systemctl daemon-reload
|
||
|
|
systemctl enable opensearch.service
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5단계: 보안 플러그인 설정
|
||
|
|
**[Node1에서 작업 후 다른 노드로 복사]**
|
||
|
|
#### 5.1. 인증 방식 설정 (`config.yml`)
|
||
|
|
`/etc/opensearch/opensearch-security/config.yml` 수정. JWT 우선, Basic 차선.
|
||
|
|
```yaml
|
||
|
|
---
|
||
|
|
_meta:
|
||
|
|
type: "config"
|
||
|
|
config_version: 2
|
||
|
|
config:
|
||
|
|
dynamic:
|
||
|
|
http:
|
||
|
|
anonymous_auth_enabled: false
|
||
|
|
authc:
|
||
|
|
# [중요] order: 0(JWT) -> order: 1(Basic)
|
||
|
|
jwt_auth_domain:
|
||
|
|
http_enabled: true
|
||
|
|
order: 0
|
||
|
|
http_authenticator:
|
||
|
|
type: jwt
|
||
|
|
challenge: false
|
||
|
|
config:
|
||
|
|
signing_key: "UGdiOTdLVjFBTWtndTRNRiZmVjdwMDdCRW1lSSUxTnA="
|
||
|
|
jwt_header: "Authorization" # "Bearer " 접두사는 자동 처리됨
|
||
|
|
subject_key: sub
|
||
|
|
roles_key: roles
|
||
|
|
authentication_backend:
|
||
|
|
type: noop
|
||
|
|
basic_internal_auth_domain:
|
||
|
|
http_enabled: true
|
||
|
|
order: 1
|
||
|
|
http_authenticator:
|
||
|
|
type: basic
|
||
|
|
challenge: true
|
||
|
|
authentication_backend:
|
||
|
|
type: internal
|
||
|
|
```
|
||
|
|
#### 5.2. 역할 매핑 (`roles_mapping.yml`)
|
||
|
|
`/etc/opensearch/opensearch-security/roles_mapping.yml` 수정.
|
||
|
|
```yaml
|
||
|
|
# ... (기존 내용 유지)
|
||
|
|
all_access:
|
||
|
|
reserved: false
|
||
|
|
users:
|
||
|
|
- "admin" # 내부 사용자
|
||
|
|
backend_roles:
|
||
|
|
- "admin" # JWT를 통해 온 사용자
|
||
|
|
# ... (기존 내용 유지)
|
||
|
|
```
|
||
|
|
#### 5.3. 파일 복사 및 권한 설정
|
||
|
|
**[Node1]**
|
||
|
|
```bash
|
||
|
|
scp -P 42894 /etc/opensearch/opensearch-security/config.yml root@ds-osnode002.oneunivrs.com:/etc/opensearch/opensearch-security/
|
||
|
|
scp -P 42894 /etc/opensearch/opensearch-security/roles_mapping.yml root@ds-osnode002.oneunivrs.com:/etc/opensearch/opensearch-security/
|
||
|
|
scp -P 42894 /etc/opensearch/opensearch-security/config.yml root@ds-osnode003.oneunivrs.com:/etc/opensearch/opensearch-security/
|
||
|
|
scp -P 42894 /etc/opensearch/opensearch-security/roles_mapping.yml root@ds-osnode003.oneunivrs.com:/etc/opensearch/opensearch-security/
|
||
|
|
```
|
||
|
|
**[모든 노드]**
|
||
|
|
```bash
|
||
|
|
chown -R opensearch:opensearch /etc/opensearch
|
||
|
|
find /etc/opensearch -type d -exec chmod 750 {} \;
|
||
|
|
find /etc/opensearch -type f -exec chmod 640 {} \;
|
||
|
|
chmod 600 /etc/opensearch/certs/oneunivrs_key.pem
|
||
|
|
chmod -R 600 /etc/opensearch/opensearch-security/*
|
||
|
|
```
|
||
|
|
|
||
|
|
### 6단계: 클러스터 시작 및 적용
|
||
|
|
#### 6.1. 클러스터 시작
|
||
|
|
마스터가 아닌 노드부터 순차적으로 시작.
|
||
|
|
```bash
|
||
|
|
systemctl start opensearch.service # Node3 -> Node2 -> Node1 순으로 실행
|
||
|
|
```
|
||
|
|
#### 6.2. 개인키 변환 (PKCS#8)
|
||
|
|
`securityadmin.sh`는 PKCS#8 형식을 요구함.
|
||
|
|
**[Node1]**
|
||
|
|
```bash
|
||
|
|
openssl pkcs8 -topk8 -inform PEM -outform PEM -in /etc/opensearch/certs/oneunivrs_key.pem -out /etc/opensearch/certs/oneunivrs_key.p8.pem -nocrypt
|
||
|
|
chown opensearch:opensearch /etc/opensearch/certs/oneunivrs_key.p8.pem
|
||
|
|
chmod 600 /etc/opensearch/certs/oneunivrs_key.p8.pem
|
||
|
|
```
|
||
|
|
#### 6.3. 보안 설정 적용
|
||
|
|
**[Node1]**
|
||
|
|
```bash
|
||
|
|
# [중요] 3.1 버전은 REST 포트(9200)와 변환된 키(.p8.pem) 사용
|
||
|
|
/usr/share/opensearch/plugins/opensearch-security/tools/securityadmin.sh \
|
||
|
|
-cd /etc/opensearch/opensearch-security/ \
|
||
|
|
-cacert /etc/opensearch/certs/root.pem \
|
||
|
|
-cert /etc/opensearch/certs/oneunivrs.pem \
|
||
|
|
-key /etc/opensearch/certs/oneunivrs_key.p8.pem \
|
||
|
|
-h ds-osnode001.oneunivrs.com \
|
||
|
|
-p 9200 \
|
||
|
|
-icl \
|
||
|
|
-nhnv
|
||
|
|
```
|
||
|
|
|
||
|
|
### 7단계: Dashboards 설정
|
||
|
|
**[Node1]**
|
||
|
|
#### 7.1. 대시보드용 인증서 복사
|
||
|
|
```bash
|
||
|
|
mkdir -p /etc/opensearch-dashboards/certs
|
||
|
|
cp /etc/opensearch/certs/*.pem /etc/opensearch-dashboards/certs/
|
||
|
|
chown -R opensearch-dashboards:opensearch-dashboards /etc/opensearch-dashboards/certs
|
||
|
|
```
|
||
|
|
#### 7.2. `opensearch_dashboards.yml` 설정
|
||
|
|
```yaml
|
||
|
|
server.port: 5601
|
||
|
|
server.host: "0.0.0.0"
|
||
|
|
server.name: "oneunivrs-opensearch-dashboards"
|
||
|
|
|
||
|
|
# 고가용성을 위해 클러스터 노드 모두 기재
|
||
|
|
opensearch.hosts:
|
||
|
|
- https://ds-osearch001.oneunivrs.com:9200
|
||
|
|
- https://ds-osearch002.oneunivrs.com:9200
|
||
|
|
- https://ds-osearch003.oneunivrs.com:9200
|
||
|
|
|
||
|
|
# [중요] 2.x 이후 버전의 설정 키 이름
|
||
|
|
opensearch.requestHeadersWhitelist: [ "securitytenant", "authorization" ]
|
||
|
|
|
||
|
|
# 대시보드 HTTPS
|
||
|
|
server.ssl.enabled: true
|
||
|
|
server.ssl.certificate: /etc/opensearch-dashboards/certs/oneunivrs.pem
|
||
|
|
server.ssl.key: /etc/opensearch-dashboards/certs/oneunivrs_key.pem
|
||
|
|
|
||
|
|
# [중요] 2.x 이후 버전의 설정 키 이름 (배열)
|
||
|
|
opensearch.ssl:
|
||
|
|
verificationMode: full
|
||
|
|
certificateAuthorities: [ "/etc/opensearch-dashboards/certs/root.pem" ]
|
||
|
|
|
||
|
|
# 서비스 계정
|
||
|
|
opensearch.username: "kibanaserver"
|
||
|
|
opensearch.password: "kibanaserver"
|
||
|
|
|
||
|
|
# 보안 연동
|
||
|
|
opensearch_security:
|
||
|
|
multitenancy.enabled: true
|
||
|
|
auth.anonymous_auth_enabled: false
|
||
|
|
cookie.password: "강력하고_랜덤한_문자열_사용"
|
||
|
|
```
|
||
|
|
|
||
|
|
### 8단계: Dashboards 시작 및 확인
|
||
|
|
**[Node1]**
|
||
|
|
```bash
|
||
|
|
systemctl start opensearch-dashboards.service
|
||
|
|
systemctl enable opensearch-dashboards.service
|
||
|
|
```
|
||
|
|
브라우저에서 `https://ds-osearch001.oneunivrs.com:5601` 접속. `admin` / `DHp5#r#GYQ9d` 로그인 확인.
|
||
|
|
|
||
|
|
### 9단계: JWT 인증 테스트
|
||
|
|
#### 9.1. 서버에서 직접 토큰 생성
|
||
|
|
외부 도구의 키 처리 방식 문제로 서버에서 직접 생성하는 것이 가장 확실.
|
||
|
|
**[Node1]**
|
||
|
|
```bash
|
||
|
|
pip install pyjwt
|
||
|
|
vi create_token.py
|
||
|
|
```
|
||
|
|
```python
|
||
|
|
# create_token.py
|
||
|
|
import jwt, time, base64
|
||
|
|
base64_secret = "UGdiOTdLVjFBTWtndTRNRiZmVjdwMDdCRW1lSSUxTnA="
|
||
|
|
# [핵심] Base64 디코딩
|
||
|
|
decoded_secret = base64.b64decode(base64_secret)
|
||
|
|
payload = { "sub": "admin", "roles": ["admin"], "exp": int(time.time()) + 3600 }
|
||
|
|
token = jwt.encode(payload, decoded_secret, algorithm="HS256")
|
||
|
|
print(token)
|
||
|
|
```
|
||
|
|
```bash
|
||
|
|
python3 create_token.py # 토큰 생성 후 복사
|
||
|
|
```
|
||
|
|
#### 9.2. `curl`로 API 호출
|
||
|
|
```bash
|
||
|
|
curl -k -H "Authorization: Bearer <방금_생성한_토큰>" "https://ds-osearch001.oneunivrs.com:9200"
|
||
|
|
```
|
||
|
|
성공 응답 확인.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## v2.0: LB 중심 아키텍처로 전환
|
||
|
|
|
||
|
|
초기 구축된 클러스터를 프로덕션 환경에 적합하도록 로드 밸런서(LB) 중심의 고가용성 아키텍처로 전환한다.
|
||
|
|
|
||
|
|
### 10단계: 아키텍처 목표
|
||
|
|
* **AS-IS:** 클라이언트가 개별 노드(`ds-osearch001` 등)에 직접 접속.
|
||
|
|
* **TO-BE:** 클라이언트는 LB의 단일 대표 주소(`ds-opensearch.oneunivrs.com`)에만 접속. 노드들은 내부망에 격리되어 보안 강화.
|
||
|
|
|
||
|
|
### 11단계: LB 준비 및 Nginx 프록시 구축
|
||
|
|
|
||
|
|
LB의 헬스 체크 제약(200 OK만 허용)을 우회하기 위해, 모든 OpenSearch 노드에 헬스 체크 전용 Nginx 프록시를 설치한다.
|
||
|
|
|
||
|
|
**[모든 노드 (Node1, Node2, Node3)에서 실행]**
|
||
|
|
```bash
|
||
|
|
# Nginx 설치
|
||
|
|
apt-get update && apt-get install nginx -y
|
||
|
|
|
||
|
|
# Nginx용 SSL 디렉토리 생성 및 인증서 복사
|
||
|
|
mkdir -p /etc/nginx/ssl
|
||
|
|
cp /etc/opensearch/certs/*.pem /etc/nginx/ssl/
|
||
|
|
|
||
|
|
# 기본 설정 비활성화
|
||
|
|
rm /etc/nginx/sites-enabled/default
|
||
|
|
|
||
|
|
# 헬스 체크용 설정 파일 생성
|
||
|
|
vi /etc/nginx/sites-available/opensearch-healthcheck
|
||
|
|
```
|
||
|
|
|
||
|
|
`opensearch-healthcheck` 파일에 아래 내용을 작성한다.
|
||
|
|
```nginx
|
||
|
|
server {
|
||
|
|
listen 9201 ssl;
|
||
|
|
# [주의] IPv6 비활성화 환경에서는 아래 라인 주석 처리
|
||
|
|
# listen [::]:9201 ssl;
|
||
|
|
|
||
|
|
# 각 노드의 내부 DNS 또는 IP로 설정
|
||
|
|
server_name ds-osnode001.oneunivrs.com; # Node2에서는 ds-osnode002...
|
||
|
|
|
||
|
|
ssl_certificate /etc/nginx/ssl/oneunivrs.pem;
|
||
|
|
ssl_certificate_key /etc/nginx/ssl/oneunivrs_key.pem;
|
||
|
|
|
||
|
|
location / {
|
||
|
|
# 헬스 체크 요청에 무조건 200 OK 응답
|
||
|
|
return 200 'Healthy';
|
||
|
|
add_header Content-Type text/plain;
|
||
|
|
add_header Content-Length 7;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 설정 활성화 및 재시작
|
||
|
|
ln -s /etc/nginx/sites-available/opensearch-healthcheck /etc/nginx/sites-enabled/
|
||
|
|
nginx -t
|
||
|
|
systemctl restart nginx
|
||
|
|
systemctl enable nginx
|
||
|
|
```
|
||
|
|
|
||
|
|
### 12단계: OpenSearch 및 Dashboards 재구성
|
||
|
|
|
||
|
|
**[로드 밸런서 설정]**
|
||
|
|
* **대표 DNS:** `ds-opensearch.oneunivrs.com`을 생성하여 LB의 Public IP에 연결.
|
||
|
|
* **리스너:** `HTTPS:9200` (API용), `HTTPS:5601` (Dashboards용) 생성.
|
||
|
|
* **SSL 인증서:** `oneunivrs.com` 인증서를 LB에 설치.
|
||
|
|
* **`opensearch-api` 타겟 그룹:**
|
||
|
|
* **대상:** `10.0.10.8:9200`, `10.0.10.9:9200`, `10.0.10.10:9200`
|
||
|
|
* **헬스 체크:** `HTTPS`, Port `9201`, Path `/`, Method `GET`
|
||
|
|
* **`opensearch-dashboard` 타겟 그룹:**
|
||
|
|
* **대상:** `10.0.10.8:5601`
|
||
|
|
* **헬스 체크:** `HTTPS`, Port `9201`, Path `/`, Method `GET` (API와 동일한 프록시 사용)
|
||
|
|
|
||
|
|
**[Node1의 Dashboards 설정 변경]**
|
||
|
|
`/etc/opensearch-dashboards/opensearch_dashboards.yml`을 수정하여 LB를 바라보게 한다.
|
||
|
|
```yaml
|
||
|
|
# opensearch.hosts를 새로운 LB 대표 DNS로 변경
|
||
|
|
opensearch.hosts: ["https://ds-opensearch.oneunivrs.com:9200"]
|
||
|
|
|
||
|
|
# [중요] LB <-> Dashboards 간 SNI 문제 해결을 위한 옵션 추가
|
||
|
|
opensearch.ssl:
|
||
|
|
alwaysPresentCertificate: true
|
||
|
|
verificationMode: full
|
||
|
|
certificateAuthorities: [ "/etc/opensearch-dashboards/certs/root.pem" ]
|
||
|
|
```
|
||
|
|
```bash
|
||
|
|
# Dashboards 서비스 재시작
|
||
|
|
systemctl restart opensearch-dashboards.service
|
||
|
|
```
|
||
|
|
|
||
|
|
### 13단계: 최종 전환 및 테스트
|
||
|
|
1. LB 콘솔에서 `opensearch-api`와 `opensearch-dashboard` 타겟 그룹의 상태가 모두 `healthy`로 바뀌는지 확인한다.
|
||
|
|
2. 모든 클라이언트의 접속 주소를 `https://ds-opensearch.oneunivrs.com`으로 변경한다.
|
||
|
|
3. API와 Dashboards 접속이 모두 정상적으로 이루어지는지 최종 확인한다.
|
||
|
|
```bash
|
||
|
|
curl -k -H "Authorization: Bearer <최종_토큰>" "https://ds-opensearch.oneunivrs.com:9200"
|
||
|
|
```
|
||
|
|
4. (선택 사항) 전환이 안정화되면, 개별 노드의 외부 IP를 제거하고 방화벽을 강화하여 보안 수준을 높인다.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 부록: 운영 및 관리
|
||
|
|
|
||
|
|
### 주요 트러블슈팅 및 교훈
|
||
|
|
1. **클러스터 형성 실패 (`cluster-manager not discovered`):** `opensearch.yml`의 `node.name`과 `cluster.initial_cluster_manager_nodes` 목록의 이름이 불일치. 클러스터링 관련 설정의 이름은 정확히 일치해야 함.
|
||
|
|
2. **`securityadmin.sh` 실행 실패:**
|
||
|
|
* **원인 1 (`InvalidKeySpecException`):** `securityadmin.sh`는 PKCS#8 형식의 개인키를 필요로 함. `openssl pkcs8` 명령으로 변환하여 해결.
|
||
|
|
* **원인 2 (포트 오류):** OpenSearch 2.12 이후 `securityadmin.sh`는 REST 포트(9200)를 사용.
|
||
|
|
3. **Dashboards 시작 실패:** 2.x 버전 이후 변경된 설정 키 이름 문제 (`requestHeadersWhitelist`, `ssl.ca`). 버전업 시 공식 문서의 Breaking Changes를 반드시 확인해야 함.
|
||
|
|
4. **JWT 인증 실패 (`Unauthorized`):**
|
||
|
|
* **근본 원인:** `signing_key`를 Base64 문자열 그대로 사용.
|
||
|
|
* **해결:** `signing_key`를 **Base64 디코딩**한 바이너리 값을 실제 비밀키로 사용하여 토큰을 생성해야 함.
|
||
|
|
5. **LB 헬스 체크 실패 (`503`, `401`, `405` 등):**
|
||
|
|
* **원인:** 사용하는 LB가 헬스 체크 성공 기준으로 `200 OK`만 허용하는데, 보안이 활성화된 OpenSearch/Dashboards는 인증되지 않은 요청에 `200 OK`를 반환하지 않음.
|
||
|
|
* **해결:** 모든 노드에 Nginx를 헬스 체크 전용 프록시로 설치. LB는 Nginx의 `9201` 포트로 헬스 체크를 요청하고, Nginx는 무조건 `200 OK`를 응답하여 문제를 우회함.
|
||
|
|
|
||
|
|
### 추가 권장 사항 및 팁
|
||
|
|
1. **롤링 리스타트 시 샤드 재배치 중단:** `/_cluster/settings` API를 통해 `cluster.routing.rebalance.enable`을 `none`으로 설정하면 재시작 속도를 높일 수 있음.
|
||
|
|
2. **인덱스 템플릿 및 ILM:** 데이터가 많아지기 전에 Dashboards의 `Index Management` 메뉴에서 인덱스 템플릿과 ILM(수명 주기 관리) 정책을 설정하여 운영을 자동화할 것.
|
||
|
|
3. **스냅샷 및 복구:** 데이터 유실 방지를 위해 Dashboards의 `Snapshots` 메뉴에서 외부 저장소(S3 등)로의 주기적인 백업을 반드시 설정할 것.
|
||
|
|
4. **방화벽 설정:** LB 전환 후 노드들의 외부 IP를 제거하고, OS 방화벽(UFW 등)을 사용해 신뢰할 수 있는 내부 IP 대역에서의 접속만 허용하여 보안을 강화할 것.
|
||
|
|
|
||
|
|
### 사용자/역할 추가 (Dashboards UI)
|
||
|
|
`admin` 계정으로 Dashboards에 로그인 후, `Security` 메뉴에서 YAML 파일 수정 없이 직관적으로 사용자, 역할, 역할 매핑을 관리할 수 있다. 일회성 작업은 UI를 사용하는 것이 편리하다.
|
||
|
|
* **역할 생성:** `Security > Roles > Create role`
|
||
|
|
* **사용자 생성:** `Security > Internal Users > Create internal user`
|
||
|
|
* **역할 매핑:** `Security > Roles > (역할 선택) > Mapped users > Manage mapping`
|
||
|
|
|
||
|
|
### 인증서에서 정확한 DN 추출하기
|
||
|
|
`opensearch.yml`의 `nodes_dn`, `admin_dn` 설정 시, `openssl` 명령어로 정확한 DN을 추출하여 사용하면 실수를 방지할 수 있다.
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# [권장] RFC2253 형식으로 출력
|
||
|
|
openssl x509 -in /data/cert/oneunivrs.pem -noout -subject -nameopt RFC2253
|
||
|
|
```
|
||
|
|
**출력 예시:** `CN=*.oneunivrs.com,O=ONEUNIVERSE Co.\,Ltd.,ST=Seoul,C=KR`
|
||
|
|
**`opensearch.yml` 적용 시:** YAML 문자열 내에서 백슬래시(`\`)는 이스케이프해야 하므로 `\\`로 변경해야 한다.
|
||
|
|
`"CN=*.oneunivrs.com,O=ONEUNIVERSE Co.\\,Ltd.,ST=Seoul,C=KR"`
|
||
|
|
|
||
|
|
### `-nameopt RFC2253` 옵션 상세 설명
|
||
|
|
이 옵션은 기계가 파싱하기 좋은 표준 형식으로 DN을 출력한다.
|
||
|
|
* `subject=` 같은 불필요한 접두사가 없다.
|
||
|
|
* 쉼표(`,`)로만 구분되며 불필요한 공백이 없다.
|
||
|
|
* **가장 중요:** DN 값 자체에 포함된 특수 문자(예: `Co.,Ltd.`의 쉼표)를 백슬래시(`\`)로 자동으로 이스케이프 처리해준다.
|
||
|
|
* OpenSearch 보안 플러그인은 이 형식을 가장 안정적으로 인식하므로, DN 설정 시 반드시 사용하는 것이 좋다.
|