개발 공부 기록하기/03. AWS & Infra

ulimit에 대해 알아보자

lannstark 2020. 10. 5. 12:03

안녕하세요 여러분! 공부하는 개발자입니다 😉

오늘은 linux에서 사용하는 ulimit 명령어에 대해 알아보려고 합니다!

  • 사용 OS : Amazon Linux 2 (RHEL)
  • 사용 머신 : t2.medium

1. ulimit이란?

ulimit 명령어의 man 페이지를 보면 다음과 같이 나와 있습니다.

Provides control over the resources available to the shell and to processes started by it, on systems that allow such control.

해석을 해보자면, "우리가 접속하는 shell이나 실행시키는 프로세스가 사용할 수 있는 머신의 자원의 조절을 제공한다"라는 뜻입니다. 예를 들어, 우리가 실행시키고 있는 프로세스에서 동시에 사용하는 파일 수 등을 조절할 수 있습니다.

계속 읽어보죠!

The -H and -S options specify that the hard or soft limit is set for the given resource. A hard limit cannot be increased by a non-root user once it is set; a soft limit may be incresed up to the value of the hard limit.

머신의 자원 제한에는 hard limit과 soft limit이 있다고 합니다. hard limit은 한 번 설정되면 root 권한이 아닌 유저에 의해 값이 증가할 수 없고요, soft limit은 hard limit까지 조절될 수 있다고 합니다. -H 옵션과 -S 옵션을 이용해 hard / soft limit을 구분할 수 있습니다.

If neither -H nor -S is specified, both the soft and hard limits are set. The value of limit can be a number in the unit specified for the resource or one of the special values hard, soft, or unlimited, which stand for the current hard limit, the current soft limit, and no limit, respectively

만약 -H 또는 -S 옵션을 명시하지 않으면, soft limit과 hard limit이 동시에 설정됩니다. 설정하는 값은 자원에 명시된 단위 숫자 또는 특별한 값(현재 hard limit, 현재 soft limit, no limit)일 수 있습니다.

If limit is omitted, the current value of the soft limit of the resource is specified, the limit name and unit are printed before the value.

만약 값이 설정되지 않으면, 자원에 대한 현재 soft limit 값이 특정됩니다.

ulimit 명령어의 옵션은 다음과 같습니다! (옵션이 더 많은데요, 다른 옵션이 궁금하시면 man ulimit 강력 추천 드립니다 ㅎㅎ)

  • -a : 모든 limit 값 출력
  • -b : 최대 socket buffer size
  • -c : 최대 코어 파일 사이즈
  • -d : 프로세스 data segment의 최대 크기
  • -f : shell에 만들어질 수 있는 파일의 최대 크기
  • -s : 최대 stack size
  • -n : open file descriptor의 최대 수
  • -u : 한 유저가 실행할 수 있는 최대 process 수
  • -x : 파일 락의 최대값
  • -T : thread 수의 최대값 (OS 버전에 따라 옵션이 작동하지 않는 경우도 있습니다)

2. open files & max user processes

자 그러면 우선 ulimit -a 를 확인해서 머신의 제한 값들을 살펴보겠습니다. (soft limit 입니다!)

이 중 open files 값과 max user processes 값에 대해서 조금 더 알아보겠습니다.

두 설정에 대해서는 명-글에서 결론을 내어주고 있습니다.

  • Java에서 동시에 생성 가능한 thread 수는 max user processes를 따라간다
  • Java에서 소켓 통신(HTTP API, JDBC 커넥션 등)은 open file 옵션을 따라간다
    • 단, JDK 내부 코드 상에서 hard limit값이 soft limit에 update 된다.

soft limit은 hard limit까지 모든 유저가 임의로 설정할 수 있다고 했는데, JDK가 그렇게 해주고 있는 것을 확인할 수 있네요 ㅎㅎㅎ

 

하지만 위와 같은 결론에 한 가지 의문이 있습니다. Java에서 동시에 생성 가능한 thread 수는 정말 max user processes를 따라 갈까요? (위 우아한형제들 기술 블로그 댓글창에 관련 질문이 있더라고요!)

해당 글에 첨부된 stackoverflow 댓글 아래를 보면, 다음과 같은 이야기를 하고 있습니다.

리눅스에서 process와 thread를 구분하지 않는 것은 틀린 발언이라는 뜻인데요, 확실히 하기 위해 저도 테스트를 한 번 해보았습니다.

다음과 같이 GET API를 한 번 받으면 thread를 100개 만들도록 했으며,

max process 개수는 256개로 변경했습니다.

169번째 thread 생성이 실패한 것으로 보이네요

이제 stack size를 8mb → 256kb로 변경해보겠습니다. 만약 max user processes가 thread 수를 제어하고 있다면, 168번째 thread 근처에서 생성이 실패해야 할 것입니다.

적절하게 설정을 변경해 주었고요!

이번에도 동일하게 169번째 thread 생성이 실패했습니다..

여기까지 하고 보니 한 가지 의아한게 있네요! 저기 있는 stacksize 1024k가 Thread를 만드는데 적용된 stack size 같은데요..?

-Xss 옵션을 주어 stack size 변경을 256k로 해보겠습니다.

그래도 여전히 동일하게 169번째 thread 생성이 실패했습니다.

possibly out of memory or process/resource limits reached 가 말해주는 것처럼, Thread가 실제 사용하는 stack size에 의한 JVM 메모리가 초과하거나 process/resource 한계에 도달했을 때 thread 생성이 실패하는 것처럼 보입니다.

결론적으로, Java Thread는 리눅스 시스템에서 프로세스 개수에 포함된다 라고 할 수 있겠네요! 역시 명-글...

조금 더 자료를 찾아보니 public personal wiki에서도 Java Thread는 리눅스 시스템에서 프로세스 개수에 포함되는 내용이 있네요 ㅎㅎ

 

3. ulimit 값 설정하기

ulimit -알파벳 값 으로 자원 제한을 설정할 수 있습니다.

예를 들어 위에서 stack size를 256으로 바꾸고 싶었다면, ulimit -s 256 이라고 할 수 있죠

하지만 이때 ssh 연결을 끊은 다음 다시 들어가게 되면 원상 복귀 되어 있습니다.

영구적으로 ulimit 값을 변경하기 위해서는 /etc/security/limits.conf 를 설정해 주어야 합니다.

제일 왼쪽에는 특정 유저를 지칭할 수도 있고 wild card (*)로 유저를 구분하지 않을 수도 있습니다.

그 후에는 soft / hard 여부와 item, value를 적절하게 설정해주면 됩니다.

참 쉽죠 ^^?

이상으로 ulimit을 알아보았습니다! 새로운 machine을 받으면 기본적으로 설정해주는게 좋겠네요 ㅎㅎ