ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Streamlit] 설치 단계에서 발생한 이슈와 해결방법 정리
    [IT] 공부하는 개발자/Data engineering 2023. 4. 16. 02:11

     

    Streamlit 이란?

    데이터 시각화를 지원하는 웹 애플리케이션 개발을 위한 파이썬 기반 오픈소스 라이브러리
     


     

    왜 Streamlit을 써야 할까?

    1. 쉬움
    Data scientist 들이 가장 편하게 느끼는 파이썬 언어로 작성되어 있어서 러닝 커브가 적다.
     
    2. 시각화 지원
    시각화를 지원하는 프론트엔드 라이브러리가 많지 않은데, Streamlit 은 다양하고 많은 시각화 라이브러리를 지원해서 차트, 그래프를 높은 자유도로 만들 수 있다.
     
    3. 반응형 웹
    반응형 웹을 내부적으로 구현해 주므로 개발 비용을 절약할 수 있다.
     
    4. 비교군 중 가장 인기가 많은 시각화 오픈소스
    Github contribution 을 기준으로 비교해 보면 비슷한 오픈소스인 Panel 보다 7배 이상 contribution 이 많다. 인기가 많다면 제품 지원이 앞으로도 계속될 가능성이 높고, 트러블 슈팅이 보다 용이하다.


     

    설계

    쉬운 버전 관리, 확장성 등을 고려하여 Docker + Kubernetes로 배포한다.
     

     
    Streamlit 포트를 외부에 바로 노출하고 싶지 않기 때문에, 요청은 80 포트로 받고, 그 요청을 Streamlit 포트로 reverse proxy 해줄 컨테이너가 하나 더 필요해서 Nginx를 사이드카로 달 것이다.
     


    Trouble shooting

    1. streamlit pid not found 에러 로그와 함께 실행되지 않음
    nginx.pid 파일은 nginx 프로세스의 PID를 저장하는 파일인데 이 파일이 없으면 nginx 가 정상적으로 실행될 수 없다.
    따라서, 이 문제를 해결하기 위해서는 nginx 컨테이너에서 nginx.pid 파일이 생성되도록 설정해야 한다.

    1. nginx 설정 오류
    nginx 설정 파일에서 pid 파일의 경로가 정확하지 않을 경우 발생할 수 있습니다. nginx 설정 파일에서 pid 파일의 경로를 수정해보세요.

    2. 폴더 권한 설정 오류
    nginx 프로세스가 pid 파일을 생성할 폴더의 권한이 없는 경우에도 발생할 수 있습니다. 폴더의 권한을 수정하여 nginx 프로세스가 pid 파일을 생성할 수 있도록 해보세요.

    3. 폴더가 없는 경우
    폴더가 없는 경우에도 발생할 수 있습니다. 폴더가 없으면 nginx 프로세스가 pid 파일을 생성할 수 없습니다. 폴더를 만들어서 권한을 설정해 보세요.

     
    나는 1+3의 문제였다.
    nginx 설정 파일에 지정한 경로가 없는 경로였고, 그래서 경로 생성 명령어를 Dockerfile에 작성하여 빌드단계에서 생성하려고 의도했지만 실제로는 생성되지 않았다. pid 파일이 저장되는 path 가 mount disk였기 때문이다. 그래서 도커파일 빌드 단계가 아닌, 컨테이너 실행 단계에서 폴더를 만들어 주도록 변경하고 나니 문제가 해결되었다.
     


     
    2. Please wait... 메시지 무한 로딩
    Nginx 포트로 들어가면 Streamlit 안내는 뜨지만 Please wait...이라는 메시지만 보였다.
    이것은 CORS 문제 때문에 발생한다. 그러니까, 웹브라우저는 80번 포트로 request를 보냈는데 실제 받는 건 8501 포트일 때, Streamlit 은 보안 에러 (CORS Protectrion)를 발생시킨다.
    CORS 문제가 원인이 맞는지 확인하는 방법은 CORS 보호를 해제해 보는 것이다. 아래 문서 참고
     
    https://docs.streamlit.io/knowledge-base/deploy/remote-start

    Streamlit Docs

    Join the community Streamlit is more than just a way to make data apps, it's also a community of creators that share their apps and ideas and help each other make their work better. Please come join us on the community forum. We love to hear your questions

    docs.streamlit.io

    보호를 해제하여 잘 작동한다면, browser.serverAddress 와 browser.serverPort를 config에 추가한 후 다시 보호를 활성화하면 된다. 
    이것만으로는 해결이 안 될 수도 있다... 그럼 Nginx config 파일에 아래 설정을 넣어주자
     

      location / {
      ..
      ..
      
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 86400;
            proxy_@@@_timeout 86400;
      ..
      
      }

     
    나는 이걸로 해결되었다. Nginx에 proxy_@@@_timeout 시간이 모두 잡혀있었는데 다 늘려줬더니...
    그때부터 접속이 정상적으로 되었다. 

     


     
    3. Streamlit Config 파일 위치
    streamlit 실행 옵션을 실행할 때 --server.port 8080 이런 식으로 파라미터로 주입할 수도 있지만...
    나는 실행 옵션들을 config 파일로 관리해서, 코드 가시성을 개선시키고 싶었다.
    streamlit의 실행 옵션은 config.toml 에 작성하여 ~/. streamlit/config.toml 에 배치해 두면 Streamlit 이 실행될 때 그 파일을 자동으로 읽어서 반영한다.
    로컬에서 실행해 보니 잘 되길래 도커파일에도 config를 배치하는 명령어를 넣었다.
     

    WORKDIR /app/hello-world
    
    COPY config.toml /root/.streamlit/config.toml

     
    실패했다.ㅠ 이유는.. WORKDIR 때문이다.
    도커 이미지에서 최상위 폴더가 /app/hello-world 이기 때문에, config 파일이 들어갈 위치도 맞게 바뀌어야 했다.
    다음은 WORKDIR를 참고하여 맞게 작성한 코드이다.
     

    WORKDIR /app/hello-world
    
    COPY config.toml /app/hello-world/.streamlit/config.toml

     
    이렇게 config 파일을 배치해 줬더니 잘 작동하기 시작했다.
     


     
    4. 파일 업로드 실패: streamlit axioserror request failed with status code 400
     

    스크린샷은 403 으로 되어 있는데 내 쪽에서 발생하는 실패코드는 400 이었다

    로컬 환경이나, pod 1개로 구성한 develop 환경에서는 이런 문제가 없었는데 여러개 pod 으로 production 환경을 구성하자 파일 업로드가 pod 개수에 비례하여 실패하기 시작했다. config.toml 에서 CORS and XSRF 를 false 로 두는 것으로는 이 문제를 해결할 수 없었다.
    구글링해보니 File upload 모듈 내부의 문제라는데... 고정세션을 사용하여 file upload request 가 처음에 연결된 웹서버로 가도록 해주면 이러한 이슈가 사라진다고 한다.
    이 이슈를 마주친 순간부터 Streamlit 이 production에서 운영하기에는 그닥 좋지 않은 툴이라는 생각이 들기 시작했다. 

    다른 대안이 없어서 Load balancer 에 고정 세션 (Sticky session) 을 적용하여 이 문제를 해결하기는 했지만, 고정 세션을 사용하는 순간부터 장애에 대한 대응 능력이 낮아지는 것을 피할 수 없어진다. 그러니 고정 세션 시간 (Duration) 을 너무 길게 가져 가지 않아야 한다.
     
     

    댓글

Copyright in 2020 (And Beyond)