Joyent의 Triton: /native는 우리 친구 이에요!
(Here’s the English version, easier to understand)
우리는 Docker 컨테이너를 Triton로 배포했고 다 잘 됐어요. 근데…갑자기 오늘 우리 앱가 먼제 있어요. 우리 앱은 느려요 아니면 작동하지 않아요. 그리고 컨테이너 안에 디버그 도구가 없어요. 그럼 우리는 뭐 할 거예요?
Triton의 컨테이너를 조금 탐에사하세요!
저는 다시 nginx 컨테이너를 트리톤에서 시작했어요.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Switch to Triton | |
eval $(triton env) | |
# Start nginx on triton | |
docker run -d --name test -p 80 nginx |
이 컨테이너를 시작 했을 떼 컨테이너 안에 `docker exec`로 shell을 사작해고 파일 시스템를 조금 보세요. 뭘 발견했어요?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
roman@minty ~ $ docker exec -ti test /bin/bash | |
root@ae35cee7759b:/# ls -l |
/native 뭐예요? 조금 더 보세요. 아마 유명한 Unix 프로그램을 잦아보세요? 아하! `awk`부터 `zcat`까지 다 있구나요! 그래서 /native가 다른 Unix예요? 맞아! /native는 Triton의 토박이 (native) 운영체제 이에요! 그리고 유용한 도구가 있어요!
/native를 사용하자!
이제는 /native기 있는걸 알아서 사용할 수 있어요. 먼저 나쁜 컨테이너 배포해요. 저는 ‘나쁜 컨테이너’ 예를 준비했어요. 소스 코드가 여기에 있어요. 이 ‘gamlerhart/waste-io’ 컨테이너를 시작하세요:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
docker run -d --name waste-io-example gamlerhart/waste-io |
이 컨테이너 문제 있잖아요. 무슨 문제 있는 것 잦아보세요. 우리는 다시 `docker exec`로 컨테이너가 연락해요. 그럼 `iostat’ 사용 해보면 `iostat’ 없다고요. 근데 우리는 /native 사용할 수 있어요. /native의 PATH에 더하고 `iostat’ 사용 할 수 있어요:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
roman@minty ~ $ docker exec -ti waste-io-example /bin/bash | |
root@3bd53e4a7fe4:/# | |
root@3bd53e4a7fe4:/# iostat -M 1 | |
bash: iostat: command not found | |
#Oh...damn...iostat would tell us if our IO is sane. | |
#Ah.../native to the rescue | |
root@3bd53e4a7fe4:/# iostat -M 1 | |
tty ramdisk1 sd0 sd1 sd2 cpu | |
tin tout Mps tps serv Mps tps serv Mps tps serv Mps tps serv us sy dt id | |
0 236 0 0 0 0 0 0 2 148 0 2 42 1 4 8 0 89 | |
0 1214 0 0 0 0 0 0 7 3583 0 0 0 0 9 14 0 77 | |
0 2100 0 0 0 0 0 0 7 3531 0 5 157 0 7 17 0 77 | |
0 941 0 0 0 0 0 0 7 3640 0 0 0 0 7 14 0 79 |
아하!! 우리 컨테이너가 IO 많이 하고 있어요. 근데 우리는 더 알고 싶어요. 흠~~~….’tracing’ 하고 싶어요. ‘dtrace’ 하자요!. 맞아! dtrace가 /native에 있어요. 저는 dtrace프로 아니에요. 근데 인터넷 안내 많아요 (dtrace.org, guide, 예가).
우리는 ‘lx-sycall’-프로브 (LinuX-syscall) 사용할 거에요. `-ln lx-syscall:::`가 lx-syscall 프로브를 명단해요. -n `syscall::: { @num[execname,pid,probefunc] = count() }`는 프로브 시작하고 프로그램과 프로세스 아이디와 sycall 이름 그룹 해요. 프로브를 Cntl+C 그만하세요.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#linux-syscalls aka lx-syscalls | |
root@3bd53e4a7fe4:/# dtrace -ln 'lx-syscall:::' | |
ID PROVIDER MODULE FUNCTION NAME | |
1549 lx-syscall sys32 inotify_init1 return | |
1550 lx-syscall sys32 preadv entry | |
1551 lx-syscall sys32 preadv return | |
1552 lx-syscall sys32 pwritev entry | |
# Start tracing the syscalls. Grouped by execname, pid and syscallname (probefunc) | |
root@3bd53e4a7fe4:/# dtrace -n 'syscall::: { @num[execname,pid,probefunc] = count() }' | |
dtrace: description 'lx-syscall::: ' matched 1352 probes | |
^C | |
node 23210 fsync 11368 | |
node 23210 ioctl 11368 | |
node 23210 open 11368 | |
node 23210 pwrite64 11368 | |
node 23210 close 11370 | |
node 23210 unlink 11370 | |
node 23210 epoll_wait 30332 | |
node 23210 read 30332 | |
node 23210 write 30332 | |
node 23210 futex 180019 | |
우리는 node-프로세스의 파일 시스템 write, read, open unlink하고 futex 많이 봐서 이 node 프로세스 나빠졌어요. 근데 이 프로세스가 뭐 하고 있어요? 무슨 파일 사용하고 있어요? 우리는 더 dtrace 프로브 하자! `x-syscall::open:entry` open-syscall만 보고 `execname==”node”`로 node-프로그램만 봐요. 고리고 `@num[copyinstr(arg0)] = count()`로 파일 그룹 해요:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
root@3bd53e4a7fe4:/# dtrace -n 'lx-syscall::open:entry/execname=="node"/ { @num[copyinstr(arg0)] = count() }' | |
dtrace: description 'lx-syscall::open:entry' matched 2 probes | |
^C | |
/tmp/io-file-0.00023033588805110305 1 | |
/tmp/io-file-0.00029973264092197915 1 | |
/tmp/io-file-0.001082331117725488 1 | |
/tmp/io-file-0.0017028727466004145 1 | |
/tmp/io-file-0.00224423432995402 1 | |
/tmp/io-file-0.002446706340221372 1 | |
/tmp/io-file-0.002880551536430742 1 |
아…임시의 파일을 많아요. 흠…node-프로그램 안에 어디에 이 임시의 파일 만들어요? Dtrace의 ‘jstack/ustack’ 우리는 스택 추적를 받을 수 있어요:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
root@3bd53e4a7fe4:/# dtrace -n 'lx-syscall::open:entry/execname=="node"/ { @num[jstack()] = count() }' | |
dtrace: description 'lx-syscall::open:entry' matched 2 probes | |
^C | |
libc.so.6`open+0x10 | |
libc.so.6`sysconf+0x54c | |
node`_ZN2v88internal20MarkCompactCollector31NumberOfParallelCompactionTasksEil+0x46 | |
node`_ZN2v88internal20MarkCompactCollector23EvacuatePagesInParallelEv+0xea | |
node`_ZN2v88internal20MarkCompactCollector29EvacuateNewSpaceAndCandidatesEv+0x67 | |
node`_ZN2v88internal20MarkCompactCollector14CollectGarbageEv+0x29 | |
node`_ZN2v88internal4Heap11MarkCompactEv+0x6d | |
node`_ZN2v88internal4Heap24PerformGarbageCollectionENS0_16GarbageCollectorENS_15GCCallbackFlagsE+0x4b0 | |
node`_ZN2v88internal4Heap14CollectGarbageENS0_16GarbageCollectorEPKcS4_NS_15GCCallbackFlagsE+0x142 | |
node`_ZN2v88internal4Heap15HandleGCRequestEv+0x84 | |
node`_ZN2v88internal10StackGuard16HandleInterruptsEv+0x31c | |
node`_ZN2v88internal18Runtime_StackGuardEiPPNS0_6ObjectEPNS0_7IsolateE+0x45 | |
0x2bd84b30961b | |
0x2bd84b44e1f9 | |
0x2bd84b4490eb | |
0x2bd84b44281b | |
0x2bd84b30d157 | |
0x2bd84b442615 | |
0x2bd84b337f84 | |
0x2bd84b322922 | |
node`_ZN2v88internal12_GLOBAL__N_16InvokeEPNS0_7IsolateEbNS0_6HandleINS0_6ObjectEEES6_iPS6_S6_+0xb3 | |
node`_ZN2v88internal9Execution4CallEPNS0_7IsolateENS0_6HandleINS0_6ObjectEEES6_iPS6_+0x61 | |
node`_ZN2v88Function4CallENS_5LocalINS_7ContextEEENS1_INS_5ValueEEEiPS5_+0x139 | |
node`_ZN2v88Function4CallENS_5LocalINS_5ValueEEEiPS3_+0x41 | |
node`_ZN4node9AsyncWrap12MakeCallbackEN2v85LocalINS1_8FunctionEEEiPNS2_INS1_5ValueEEE+0x149 | |
node`_ZN4nodeL5AfterEP7uv_fs_s+0x146 | |
node`uv__work_done+0xa5 | |
node`uv__async_event+0xab | |
node`uv__async_io+0xa3 | |
node`uv__io_poll+0x3a0 | |
node`uv_run+0x156 | |
node`_ZN4node5StartEiPPc+0x468 | |
libc.so.6`__libc_start_main+0xf5 | |
2 | |
libpthread.so.0`open+0x2d | |
node`worker+0xa1 | |
node`uv__thread_start+0x19 | |
libpthread.so.0`start_thread+0xc4 | |
62043 |
아…운이 없어요. open-syscall가 node의 이벤트 프로브에 나와요 (node를 dtrace로 알아보기 다른 주제이에요) . 근데 우리는 node를 프로그램가 `tmp/io-file-` 파일 마들기 알아고 이제 아마 프로그램 버그 문제를 풀 수 있어요.
dtrace 잘 아세요?
dtrace 잘 알면 많는 프로브 못 잦아요? 그럼 Triton 컨테이너 안에 컨테이너만 볼 수 있어서 dtrace 프로보 덜 많아요. 그리고 우리는 Joyent의 클라우드 스비스 ‘global-zone’ 들어가면 못 해요. 개인 Triton가 있으면 할 수 있어요. 근데 이 글 끝냈어요. ^.^끝
- Hey Mr Postman, be on Every Windows Machine.
- Joyent’s Triton : /native, our friend!