반응형

Airflow를 이용한 oracle batch job을 개발 중, cx_Oracle을 인식하지 못하는 현상이 발생하였다. 결론적으로는 매우 어이없는 실수지만, 동일한 이슈를 겪는 사람들이 분명 있을 것으로 생각하여 해결 과정을 정리하고자 한다. 

문제

  • 기존 postgresql 관련된 dag만 존재하던 airflow에 Oracle 관련 job을 추가하였다. 
  • Airflow 스케줄러에서 cx_Oracle을 호출하여, connection을 시도하니, 아래와 같은 오류가 발생하였다.
cx_oracle.databaseerror: dpi-1047: cannot locate a 64-bit oracle client library: "libclntsh.so: cannot open shared object file: no such file or directory". see https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html for help

 

  • 실제 instantclient에 들어가봤을 때, libclntsh.so 파일이 존재하였다. 

 

개발 환경

  • 문제가 발생한 상황은 centos 7버전에 conda 가상환경을 통해, airflow shcheduler를 수행하고 있었고, 모니터링의 편의를 위해 tmux로 shceduler와 webserber를 각각 다른 터미널로 수행 중이었다.

 

해결 시도

  • 해당 에러를 과거에도 경험해본 적이 있는데, 환경 변수 PATH에 instantclient의 경로가 인지되지 않아, 발생하는 문제이다. 
  • ~/. bashrc에 경로를 잡아주고, source ~/. bashrc를 통해 환경 변수를 적용해 준다. 
vim ~/.bashrc

######## .bashrc 마지막 줄 추가 #######
export ORACLE_HOME=”/home/user/{instatclient 위치}″
export LD_LIBRARY_PATH=”$ORACLE_HOME”
#######################################

source ~/.bashrc
  • python으로 connection을 실험해주니, 정상적으로 연결이 된다. 하지만, airflow scheduler 안에서는 계속 같은 이슈가 발생하였다. 

 

해결 방법

  • 너무나 당연한 내용이지만, source ~/.bashrc를 적용한 터미널과 상관없이, airflow의 scheduler와 webserver가 구동 중인 터미널에는 변경된 bashrc의 내용이 적용되지 않았다. 
  • . bashrc는 터미널이 시작될 때, 적용되는데,. bashrc 수정 전에 tmux로 생성한, airflow의 scheduler와 webserver 관련 터미널들은 변경된. bashrc를 적용하지 않았기 때문에, 당연히 instantclient의 경로를 인지하지 못하고, 경로를 못 찾는 이슈가 계속 발생한 것이다. 
  • scheduler와 webserver를 종료하고, 각 터미널에서 source ~/.bashrc를 적용해 준 후, scheduler와 webserver를 각각 재시작하니, 정상적으로 cx_Oracle을 통한 connection이 가능하였다. 
  • 지금 생각하니, 매우 당연한 내용이지만, 이유를 찾지 못해 한참을 고생했다. 아직 scheduler에 실시간성 스케줄링이 필요한 내용이 없어서 scheduler 종료 후, 시작이 가능하였지만, 운영 중인 환경에서는 어려울 것 같다. 이런 경우에는, cx_Oracle이 필요한 dag 안에서 cx_Oracle을 통한 connection 전에 시스템 환경 변수를 넣어주는 과정으로 해결 가능하다. 
import os

current_path = os.environ.get('PATH', '')
new_path = 'instantclient 경로'

if new_path not in current_path:
    updated_path = f"{current_path}:{new_path}"
    os.environ['PATH'] = updated_path

 

 

'Linux' 카테고리의 다른 글

[이슈 해결] SSH 접속이 갑자기 느려졌을 때 해결 방법  (50) 2023.11.20
반응형

회사에서 정상적으로 운영하던 서비스에 문제가 생겼다. 돌이켜보면 매우 간단한 이슈였지만, 해결과정이 재밌었고 비슷한 상황에 도움이 될 수 있을 것 같아서 기록으로 남기게 되었다.

 

문제

  • 며칠 전부터 서버 간의 SSH 연결이 매우 늦어지는 상황이 일어났다. 특히, 특정일 10:00:00을 기준으로 특정 대역대 서버가 모두 영향을 받게 되었다.
  • 특히, expect를 이용한 명령어 수행이 기본 1분 내외의 수행시간에서 30분이 지나도 해결되지 않는 문제가 발생하였다.
  • 당장 서비스 중인 서버이기 때문에, 해당 대역대가 아닌 다른 서버로 연결을 바꾸어, 해결했지만 특정 대역대의 서버 전체의 "SSH"가 느려져서, 빠른 해결이 필요하였다.

 

가설 & 시도

  • 처음으로 의심한 것은 서버 자체의 부하이다. 
  • 하지만, ps와 top으로 확인해 보았을 때, H/W 리소스는 충분하였고, 특히 특정 대역대의 서버 전체의 SSH가 다 늦어졌다는 점이 서버 자체의 부하의 가설이 아닌 것을 의미했다. 
  • 다음 의심한 점은 해당 대역대의 서버들을 물고 있는 Switch의 문제였다. 하지만, SSH 연결 외에 다른 연결을 정상적으로 수행된다는 점이 이상하였다.

 

로그 확인

  • SSH 연결에서는 verbose 옵션을 통해 SSH 연결 과정을 debugging 할 수 있다.
$ time ssh -v {ip주소}
  • 나의 경우에는 SSH 연결 대상 서버에서 msg를 응답받는 구간에서, 응답을 받는 데까지 매우 오랜 시간이 걸리는 것을 확인했다.
  • 따라서, SSH 대상 서버를 들어가서 로그를 확인하였다.
  • 별도의 SSH 모니터링 툴을 사용하지 않는다면 Linux 서버에서 SSH 관련 로그를 확인해 볼 방법은 2가지이다.
    • /var/log/audit : Linux 자체에서 audit에 관한 로그를 저장하는 곳이다. 시스템에서 발생하는 이벤트와 활동을 추적하기 때문에, SSH 연결등의 정보가 이곳에 기록된다.  
    • /var/log/secure : 보안 이벤트와 사용자 인증에 대한 로그가 기록된다. sshd(SSH 데몬)에 의한 로그인 시도, 계정 관련 이슈 등이 기록된다. SSH 연결을 위한 보안의 시간이 기록되기 때문에, 확인해야 한다.

<audit log 예시 - ChatGPT가 만들어줌>

type=USER_AUTH msg=audit(1603989582.198:304): pid=1234 uid=1000 auid=1000 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=login id=jsmith exe=/usr/sbin/sshd (hostname=?, addr=192.168.1.100, terminal=sshd res=success)'

 

<secure log 예시 - ChatGPT가 만들어줌>

Nov 20 10:15:30 server sshd[1234]: Accepted publickey for jsmith from 192.168.1.100 port 22 ssh2
Nov 20 10:15:30 server sshd[1234]: pam_unix(sshd:session): session opened for user jsmith by (uid=0)
Nov 20 10:15:30 server systemd-logind[567]: New session 1234 of user jsmith.

 

  • 로그를 확인해 보았을 때, audit log에 정상적으로 success가 찍혀있고, secure log를 확인해 보니, 연결 시도부터까지의 시간이 느린 것을 발견하였다. 

 

방법 발견

  • 최초에 SSH가 느려지는 상황을 구글링 하였을 때, 가장 많이 나오는 방법이 /etc/ssh/sshd_config 파일의 UseDNS 옵션을 "no"로 바꾸는 것이다.
  • 사실 이 방법이 효과적일 것으로 생각했지만, 회사의 엄격한 보안 정책과 운영 중인 시스템에서 변경점을 가하기 어려워(sshd restart가 필요하기 때문), 운영 중이지 않은 서비스로 실험을 해보았다. 
  • /etc/ssh/sshd_config에 아래 내용을 추가한다. (만약 UseDNS yes로 되어 있으면 no로 변환한다) 그러고 나서, sshd를 재시작해준다.
$ sudo vim /etc/ssh/sshd_config

---------------------------------

UseDNS no

---------------------------------
$ sudo systemctl restart ssh

 

  • 원리를 알아보니, server에서 SSH로 연결을 시도할 때, SSH 데몬에 DNS를 사용하도록 설정되어 있으면,  target 서버에서 /etc/resolv.conf 파일을 읽어서, 해당 파일에 명시된 DNS 서버에, hostname을 묻는 DNS query를 날리고, 이 결과를 통해, 현재 SSH 연결을 시도한 서버에 해당하는 서버가 있으면 해당 hostname으로 연결을 진행한다.
  • 이 과정을 reverse DNS lookup이라고 하는데, resolve.conf의 각 서버와 통신하여, hostname을 묻는 과정이 포함되기 때문에 conf 파일 내의 모든 서버와의 연결이 정상적이어야 한다.

  • UseDNS를 no로 변경하니, 이슈 전처럼 정상적인 속도로 SSH가 진행되었다. 하지만, 단순히 DNS connection 몇 개가 추가되었다고, 이렇게 오랜 속도가 걸리는 것은 많이 이상하였다.

 

이슈 해결

  • 결론부터 말하면, resolv.conf에 해당한 서버 중, 특정 서버가 IP를 변경하여 생긴 문제였다. 문제가 되는 대역대는 VM 서버를 사용하는 서버들이었고, 하나의 서버를 copy 하는 방식으로 서버를 setup 했기 때문에, 이 대역대의 모든 서버에 대해 동일 현상이 발생하였다.
  • resolv.conf에서 문제가 되는 IP들을 제거해 주니, UseDNS 옵션을 다 시켜도, 예전처럼 빠른 속도로 SSH를 붙을 수 있게 되었다.
  • 특히, 문제가 발생한 서비스의 경우, shell script 상에 expect 명령어를 이용하도록 되어 있는데, DNS와의 연결이 되지 않으니, Target Server에서 적절한 response를 주지 못하고, 이로 인해 Target 서버와의 연결이 안 되는 것처럼 느껴진 것이었다.
  • 돌이켜보니, 매우 간단하고, 황당한 이슈였지만, 원인을 찾는 과정에서 많은 것을 배운 것 같다.

 

교훈

  • 최근 SSH에서는 UseDNS의 default 설정이 no라고 한다. 다만, 예전 버전을 사용하는 경우에는 UseDNS의 기본 옵션은 yes이다. 만약 보안적 문제가 없다면, UseDNS를 끄는 것이 더 좋을 것 같다.
  • 하지만, 불가피하게 사용하는 경우에는 꼭 DNS 설정을 잘 관리해야 한다. 해당 DNS도 현재는 거의 사용하지 않지만, History 및 영향도 파악이 불가하여, 별도의 삭제를 하지 않다가 이슈를 맞이하게 된 상황이다. 
  • Linux 명령어를 단순 사용하기만 했는데, 동작 원리를 알아야겠다! 

'Linux' 카테고리의 다른 글

[이슈 해결] Airflow에서 cx_Oracle 관련 에러 (dpi-1047)  (24) 2024.02.19

+ Recent posts