본문으로 바로가기

EOS 대응, OpenLDAP을 Linux2에서 LINUX2023으로 서버 이관 #2

category AWS 2026. 7. 14. 11:18
반응형

지난 포스팅에서 OpenLDAP 서버를 Linux2에서 Linux2023 Docker 컨테이너로 이관하는 과정을 정리했었는데요, 사실 이건 시작에 불과했습니다. LDAP 서버 하나만 옮긴다고 끝나는 게 아니라, 이 LDAP을 로그인에 사용하는 다른 서비스들도 전부 연결 정보를 갱신해줘야 했거든요.

사내에서 이 LDAP을 인증에 쓰고 있는 서비스가 GitLab, Rundeck, Redmine, Nexus, Grafana, 그리고 사내 Java 애플리케이션까지 있었는데, 재밌었던(?) 점은 서비스마다 LDAP 연결 정보를 관리하는 방식이 전부 달랐다는 겁니다. 어떤 건 설정 파일에 IP가 박혀있고, 어떤 건 DB에 저장되어 있고, 어떤 건 아예 ALB를 하나 거쳐서 타겟 그룹만 바꾸면 끝나는 구조였어요.

이번 포스팅에서는 각 서비스별로 어디를 확인하고 어디를 고쳐야 했는지 정리해봅니다.


큰 그림: 두 가지 연결 방식

작업하다 보니 서비스들이 크게 두 부류로 나뉘더라고요.

1. LDAP 서버 IP를 직접 설정에 박아두는 방식 → GitLab, Rundeck, Redmine, Nexus → 서버가 바뀔 때마다 각 서비스 설정을 일일이 찾아서 고쳐야 함

2. ALB를 앞에 두고 경유하는 방식 → Grafana, 사내 Java 애플리케이션 → 서비스 설정에는 ALB 주소만 있고, 실제 LDAP 서버는 ALB 타겟 그룹에 등록되어 있어서 타겟 그룹의 등록 대상만 바꾸면 애플리케이션 쪽은 손댈 필요가 없음

이걸 겪고 나니 확실히 후자(ALB 경유) 방식이 유지보수 관점에서 훨씬 편하다는 걸 체감했습니다. 애초에 인프라를 이렇게 설계해두면, 다음에 LDAP 서버를 또 옮기게 되더라도 애플리케이션 담당자들을 귀찮게 할 일이 없거든요. (다음에 인프라 설계할 기회가 있으면 꼭 이렇게 해야겠다고 다짐했습니다.)

그럼 서비스별로 하나씩 정리해보겠습니다.


GitLab — 설정 파일 (gitlab.rb)

GitLab은 /etc/gitlab/gitlab.rb에 LDAP 서버 정보가 YAML 블록으로 박혀있습니다.

sudo grep -A 20 "gitlab_rails\['ldap_servers'\]" /etc/gitlab/gitlab.rb
gitlab_rails['ldap_servers'] = YAML.load <<-'EOS'
  main:
    host: '기존서버IP'     # ← 여기를 신규 서버 IP로 변경
    port: 389
    bind_dn: '...'
    base: '...'
EOS

수정 후 반영은 gitlab-ctl reconfigure로 합니다. 여기서 처음엔 IP를 바꿨는데도 계속 옛날 IP로 접속을 시도하길래 한참 헤맸는데, 알고 보니 reconfigure를 안 하고 파일만 고친 상태였습니다. GitLab은 설정 파일을 고쳤다고 바로 반영되는 게 아니라 꼭 reconfigure 과정을 거쳐야 하더라고요.


Rundeck — jaas 설정 파일 (근데 여러 개 있어서 헷갈림)

Rundeck은 JAAS(Java Authentication and Authorization Service) 방식으로 LDAP 인증을 처리하는데, /etc/rundeck/ 밑을 보니 jaas-ldap.conf 말고도 _bak, _bak1 붙은 파일들에 jaas-multi-auth.conf까지 비슷한 파일이 여러 개 있었습니다. 인수인계가 여러 번 되면서 쌓인 흔적 같더라고요.

여기서 삽질했던 부분이, 실제로 IP를 고친 파일이 진짜 로드되는 파일이 아니었던 것입니다. 아무리 고쳐도 로그에는 계속 옛날 IP로 접속 시도하는 게 찍히길래 당황했었는데, 프로세스 실행 옵션을 직접 까보고서야 원인을 알았습니다.

ps -ef | grep rundeckd | tr ' ' '\n' | grep login.config

이 명령어로 실제 로드 중인 jaas 설정 파일 경로가 나옵니다. 이 파일을 찾아서 providerUrl 값을 고쳐야 진짜 반영이 됩니다.

providerUrl="ldap://기존서버IP:389"   ← 이 부분

수정 후 systemctl restart rundeckd로 반영.

교훈: 설정 파일이 여러 개 있을 때는 "고친 파일 = 실제 쓰이는 파일"이라고 섣불리 가정하면 안 되고, 프로세스가 실제로 뭘 로드하는지부터 확인하는 습관이 필요합니다.


Redmine — 설정 파일이 아니라 DB, 그리고 관리자 웹 UI

Redmine은 앞의 둘과 완전히 다른 방식이었습니다. LDAP 설정을 텍스트 파일이 아니라 DB(auth_sources 테이블)에 저장하고, 관리자 웹 UI에서 관리합니다.

관리(Administration) → LDAP 인증(LDAP authentication)

여기서 등록된 서버의 Host 값만 바꾸고 저장하면 끝입니다. 재시작도 필요 없고 즉시 반영돼서, 사실 넷 중에 이게 제일 편했습니다. 혹시 웹 UI 접근이 막혀있는 경우엔 DB에서 직접 조회/수정도 가능합니다.

SELECT id, name, host, port FROM auth_sources;
UPDATE auth_sources SET host = '신규서버IP' WHERE host = '기존서버IP';

Nexus — 웹 UI, 근데 비밀번호를 다시 넣어야 함

Nexus도 Redmine처럼 웹 UI(Administration → Security → LDAP)에서 관리합니다. Hostname 값만 바꾸면 될 줄 알았는데, 저장하려니 Password를 다시 입력하라고 뜨더라고요.

Nexus는 보안상 이유로 기존 비밀번호를 화면에 표시하지 않기 때문에, 수정할 때마다 Bind DN 계정의 비밀번호를 다시 입력해야 합니다. 문제는 이 비밀번호를 아무도 기억을 못 하고 있었다는 거... 결국 LDAP에 저장된 값을 까봤는데, 당연하지만 해시값이라 원래 비밀번호를 복원할 방법은 없었습니다.

docker exec ldap slapcat -b "dc=..." | grep -A 5 "uid=서비스계정"
# userPassword:: (해시값, 여기서 평문 복원 불가)

결국 이런 경우엔 두 가지 선택지뿐입니다.

  1. 사내 비밀번호 관리 도구나 인수인계 문서에서 찾기
  2. 진짜 없으면 LDAP에서 새 비밀번호로 재설정하고 Nexus 쪽에도 동일하게 입력 (단, 이 계정을 다른 서비스가 같이 쓰고 있지 않은지 먼저 확인 필수)

이 경험 이후로 서비스 계정 비밀번호는 어딘가에 안전하게 기록해둬야겠다는 생각이 강하게 들었습니다.


Grafana / Java 애플리케이션 — ALB라서 그냥 타겟 그룹만 바꿈

여기서부터는 좀 다른 이야기입니다. Grafana와 사내 Java 애플리케이션은 LDAP 서버에 직접 붙는 게 아니라 ALB를 하나 거쳐서 통신하고 있었습니다. 즉 설정 파일에는 ALB 주소만 있고, 실제 LDAP 서버가 어디인지는 ALB 타겟 그룹의 등록 대상으로 결정되는 구조였죠.

덕분에 이 두 서비스는 애플리케이션 설정을 전혀 건드릴 필요가 없었습니다.

EC2 콘솔 → 로드밸런싱 → 대상 그룹 → 해당 LDAP용 타겟 그룹
→ 기존 서버 등록 해제
→ 신규 서버를 동일 포트(389)로 등록

이거 하나로 끝. 대상 상태가 Healthy로 바뀌는 것만 확인하면 됩니다.

앞서 GitLab, Rundeck에서 설정 파일 찾아 헤매고, Nexus에서 비밀번호 때문에 고생했던 걸 생각하면, 이 두 서비스는 정말 순식간에 끝나서 허탈할 정도였습니다. 인프라를 이렇게 설계해두는 게 왜 중요한지 제대로 체감한 순간이었어요.


정리

서비스 연결 방식 확인/수정 위치

GitLab 설정 파일 /etc/gitlab/gitlab.rb, 수정 후 gitlab-ctl reconfigure 필수
Rundeck 설정 파일 (여러 개 존재 주의) 실행 프로세스에서 실제 로드 파일 확인 후 providerUrl 수정
Redmine DB / 웹 UI 관리자 페이지 → LDAP 인증, 즉시 반영
Nexus 웹 UI Administration → Security → LDAP, 비밀번호 재입력 필요
Grafana ALB 경유 타겟 그룹 대상 교체만으로 끝
Java 애플리케이션 ALB 경유 타겟 그룹 대상 교체만으로 끝

 

돌이켜보면 이번 이관 작업에서 가장 크게 배운 건 기술적인 디테일보다는, "연동된 서비스가 얼마나 되는지, 그리고 각각이 어떻게 연결되어 있는지 파악하는 것" 자체가 작업의 절반이었다는 점입니다.

서버 하나 옮기는 건 사실 몇 시간이면 끝나는데, 그 서버를 쓰는 서비스들을 하나하나 찾아다니면서 확인하는 데 훨씬 더 많은 시간이 들었거든요.

다음에 비슷한 이관 작업을 할 일이 있다면, 시작 전에 "이 서버에 붙어있는 서비스 목록"부터 먼저 정리하고 들어가야겠다는 다짐을 하며 이번 포스팅은 여기서 마칩니다.

반응형