IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  Multicore acceleration | 오픈 소스 | 리눅스  >

셀/B.E. 컨테이너 가상화, Part 2: 구현

오픈 소스 소프트웨어 프로젝트인 OpenVZ를 사용해서 셀/B.E. 플랫폼에서 소프트웨어 기반 컨테이너 가상화 개념을 익히자

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

토론

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

Christian Kaiser, 리서치 인턴, IBM
Christian Rund, 연구 개발 엔지니어, IBM

옮긴이: 박재호 이해영 dwkorea@kr.ibm.com

2008 년 5 월 06 일

이 연재는 하드웨어 자원에 초점을 맞춘 컨테이너 가상화(또는 운영체제 가상화)로 알려진 소프트웨어 가상화 형태와 오픈 소스 프로젝트인 OpenVZ를 설명합니다. 이 연재물은 소프트웨어 방법론을 통해 셀/B.E. 프로세서 가상화에 필요한 모든 컴포넌트와 기법을 상세하게 개괄합니다. 두 번째 기사는 연재물 Part 1에서 설명한 전용 가상화 구현 방법과 파티셔닝에 대한 세부 사항을 다룹니다.

이 기사는 첫 번째 기사(Part 1, 그림 3)에서 예시한 전용 가상화(파티셔닝) 개념을 구현하는 방법을 소개한다. 이 기사는 (Part 1 그림 4에 나오는) 공유 디바이스 개념 개발은 설명하지 않는다.

시스템 구현을 보여주기 위해 이 기사는 다음 내용을 다룬다.

  • spufs 가상화: 각 마운트 지점에 다른 루트 아이노드를 사용
  • sysfs 조정: 실행 중에 반드시 변경해야 하는 항목
  • SPU 스케줄러 변경: 가상화 실행을 위한 단계 추가
  • OpenVZ 도구 변경: 새로운 기능 활용

spufs 가상화

기본적으로 spufs는 마운트할 때마다 매번 같은 root-inode를 사용한다. 예를 들어, chroot로 환경을 두 개 구축한다면(A와 B), 둘 다 /spu에 spufs를 마운트한다. 환경 A에서 SPE 스레드를 만들고 /spu 목록을 열거하면, 직전에 생성한 SPE 스레드가 보인다. 하지만 환경 B에서도 동일한 /spu 목록이 보인다. 환경 A와 똑같은 root-inode에 접근하기 때문이다.

이런 행동 양식을 변경해 양쪽 환경 모두 각자 생성한 SPE 스레드만 볼 수 있게 하려면, spufs가 항상 매번 마운트 지점에 대해 동일한 root-inode를 사용하지 않도록 변경해야 한다. spufs를 마운트할 때, 내부적으로 슈퍼 블록을 반환하는 커널 함수를 호출한다. 일반적으로 함수 get_sb_single()을 사용하는데, 항상 같은 슈퍼 블록을 반환한다. get_sb_nodev()는 항상 다른 슈퍼 블록을 반환하므로 이게 바로 우리가 바라는 동작 방식이다(그림 1은 가상화 직전과 직후에 spufs를 보여준다).


그림 1. 가상화 직전과 직후 spufs
가상화 직전과 직후 spufs

OpenVZ는 컨테이너 내부에 마운트 가능한 파일 시스템을 몇 종류만 허용한다. 파일 시스템마다 파일에 밀접한 특성을 정의하는 struct file_system_type 인스턴스를 구현한다. OpenVZ는 (다른 구조체 중에서도) 이 구조체를 확장해 파일 시스템이 마운트가 가능한지를 알려주는 멤버를 정의한다. 그래서 .fs_flags 멤버는 FS_VIRTUALIZED로 설정해야 한다.

컨테이너 내부에 생성되는 프로세스는 PID가 둘이다. (Part 1에서 각 컨테이너마다 커널이 제공하는 독자적인 자원 집합이 있다고 설명했다. 프로세스 트리는 자원 집합 중 하나다. 컨테이너는 자신이 만든 가상화된 PID가 달린 프로세스 집합만 볼 수 있다.) 컨테이너 내부에는 가상화된 PID가 있으며, 호스트 시스템에는 동일한 프로세스가 전역 PID라는 다른 PID로 나타난다. 언급한 바와 같이 spufs 디렉터리는 spethread-<PID>-<thread-ID> 형태로 이름을 붙이는데, <PID>는 SPE 스레드를 담은 프로세스 ID이며, <thread-ID>는 해당하는 스레드 ID다. 컨테이너 환경에서 가상화된 ID의 결과로 컨테이너 내부의 spufs 목록은 전역 PID가 아니라 가상화된 PID를 보여줘야만 한다. 다행스럽게 이런 기능은 이미 OpenVZ에 구현되어 있다.

리눅스(Linux®) 커널에서 arch/powerpc/platforms/cell/spufs/inode.c 파일을 변경하자.




위로


sysfs 조정하기

sysfs는 이미 가상화되어 있기에 컨테이너 내부에서 사용할 수 있다. 호스트 시스템에 보이는 내용은 sysfs 복사본이 아니라 일부에 불과하다. sysfs의 목표는 실행하는 동안에 SPU를 할당하고 해제하는 데 있다. sysfs 항목은 실행하는 동안에 수정이 일어나야 함을 의미한다. 수정에 앞서 SPU 목록을 열거한 디렉터리를 생성한다.

이 디렉터리는 /sys/devices/system/spu다. 기본적으로 컨테이너 환경에 있는 sysfs에는 /sys/devices/system/spu도, /sys/devices/system도, /sys/devices도 존재하지 않는다. 이 세 항목은 컨테이너 초기화(시동 과정) 과정에서 생성되어야 한다. /sys/devices/system/spu의 하위 디렉터리는 spu0에서 <spu>이 될 수 있는데, 여기서 <N>은 시스템에 존재하는 사용 가능한 SPU 수에서 1을 뺀 값이다. 디렉터리는 SPU가 컨테이너에 할당될 때 생성되어야 하며, 컨테이너에서 할당이 해제될 때 삭제되어야 한다.

sysfs 목록에서 각 디렉터리는 커널 영역에서 대응하는 kobject 인스턴스를 포함한다. kobject는 디렉터리 이름과 어버이 kobject(다시 말해, 대응하는 어버이 디렉터리)를 정의하는 구조체다. 예를 들어, /sys/devices/system/spu/spu3 디렉터리에 보이는 kobject는 나중에 설정해야 하는 값을 두 개 포함한다.

  • spu3 이름
  • /sys/devices/system/spu를 표현하는 kobject를 가리키는 포인터

subsystem_register() 호출을 사용해 kobject를 sysfs에 등록하고 나면, 객체가 사용자 영역에 보인다. 반대는 sysfs에서 디렉터리를 삭제하는 작업이다. 이렇게 하려면 삭제 대상 kobject를 매개변수로 넘기며 subsystem_unregister() 함수를 호출하면 된다. 그림 2에 예제가 나온다.


그림 2. sysfs와 kobject
sysfs와 kobject

spu3이라는 이름의 kobject는 spu라는 이름의 어버이 kobject를 가리키는 포인터를 포함한다.

커널 파일인 kernel/ve/vecalls.c에 핵심 변경 내역을 적용한다. 이 파일은 OpenVZ에 밀접한 파일로, 컨테이너 초기화와 매개변수 설정 과정에서 호출되는 대다수 함수가 정의되어 있다.




위로


SPU 스케줄러 변경하기

시스템에 있는 각 물리 SPU는 커널 영역에서 spu 구조체 인스턴스로 표현된다. 이 구조체는 다음 내역을 포함하여 여러 가지 정보를 담고 있다.

  • SPU ID(숫자)
  • SPU가 속한 셀/B.E. 노드
  • SPU의 LS를 가리키는 포인터

새로운 멤버 변수는 컨테이너 ID 형태로 SPU 소유주를 저장한다. SPU 스케줄러는 SPU에서 수행하는 SPE 스레드를 실행하기 위해 자유로운 SPU를 찾는 spu_alloc() 함수를 구현한다. 따라서 이 함수는 시스템에서 사용 가능한 SPU 목록을 탐색한다(어떤 SPE 스레드도 명령 즉시 실행되지는 않는다).

일반적인 동작 방식에 따르면 목록에서 첫 번째 SPU를 찾은 다음 여기서 SPE 스레드를 수행한다. 가상화를 위해, 이 함수는 SPE 스레드와 자유로운 SPU가 포함하고 있는 컨테이너 ID가 같은지 점검해야 한다. 그림 3은 프로세스 변경 직전과 직후에 spu_alloc()이 동작하는 방식을 보여준다.


그림 3. 변경 직전과 직후의 spu_alloc()
변경 직전과 직후의 spu_alloc()

추가적인 점검 결과가 참이 아니면, 함수는 자유 SPU 목록에서 다음 SPU를 점검한다. SPE 스레드를 수행한 컨테이너에 유효한 자유 SPU가 없다면, SPU 스케줄러는 목록이 비어있는 듯이 행동하며, 자유 SPU가 나타날 때까지 기다린다.

spu_alloc() 함수는 리눅스 커널 원시 파일인 arch/powerpc/platforms/cell/spu_base.c에 구현되어 있다.




위로


OpenVZ 도구 변경하기

필요한 함수는 이미 대부분 존재하지만, 새로운 기능을 활용하려면 OpenVZ 도구를 수정해야만 한다. vzctl 도구는 실행 중에 SPU 할당을 관리한다. vzctl은 OpenVZ에서 컨테이너 매개변수를 설정하는 핵심 도구다. 컨테이너에 할당할 SPU 숫자를 설정하는 새로운 매개변수는 --spus <nr_spus>이다.

<nr_spus> 값은 컨테이너에 할당된 SPU 개수를 나타낸다. 절대값이므로, 이 값을 6으로 설정한 SPU 여덟 개를 컨테이너에 할당하면, SPU를 6개 더 추가하는 대신 컨테이너에서 SPU 두 개를 풀어버린다(8 - 6 = 2).

예를 들어, 여기에 ID가 101인 컨테이너에 SPU 여덟 개를 할당하는 명령행 결과가 있다.

[root@c02b12-0 ~]# vzctl set 101 --spus 8
Setting SPUs: 8
Configure meminfo: 1024000
WARNING: Settings were not saved and will be reset to original
 values on next start (use --save flag)
[root@c02b12-0 ~]#

이렇게 동작하려면, vzctl 도구는 사용자 영역 경계를 가로질러 몇 가지 관리 작업을 수행해야 한다. 이 도구는 다른 컨테이너가 아직 사용하지 않는 SPU를 찾아야만 한다. vzctl 도구는 사용 가능한 SPU 목록을 뒤져 spu 구조체에 있는 새로 구현한 컨테이너 ID 값을 점검한다(SPU 스케줄러를 변경하는 절에서 설명했다). 이 값이 0인 경우에 SPU는 요청 중인 컨테이너에 할당될 수 있다. 이 값을 0으로 사용한 이유는 컨테이너 ID 값은 0보다 커야 하기 때문에 값을 0으로 두면 SPU가 어떤 컨테이너에도 할당되어 있지 않음을 암시하기 때문이다. 이 함수가 요청을 처리하는 과정에서 충분한 자유 SPU를 발견하지 못할 경우, 절차가 종료되며 SPU를 하나도 컨테이너에 할당하지 않는다. 이미 컨테이너에 할당된 SPU 숫자가 요청받은 SPU 숫자보다 클 경우 그 차이만큼 할당을 해제한다.

사용자 영역과 커널 영역 경계를 가로지르기 위해 조금 다른 구현 모델을 활용할 수 있다(구현 모델에 대한 세부 사항은 참고자료 절에 소개하는 Arnd Bergmann이 쓴 "How to not invent kernel interfaces"를 살펴보기 바란다). 가장 손쉬운 방법은 새로운 시스템 호출을 구현해 매개변수 <containerID><nr_spus>를 시스템 호출을 위한 매개변수로 사상하면 된다.

컨테이너의 SPU 매개변수 설정을 다루는 함수는 커널 모듈로 만들어지도록 커널의 일부로 구현해야 한다. 하지만 이렇게 하면 심각한 문제가 생긴다. 커널 모듈이 메모리에 올라오지 않으면, 커널 영역에 있는 시스템 호출 처리 함수가 아무 일도 하지 않아야 한다. 하지만 모듈이 메모리에 올라오면, 모듈 내부에 구현된 함수를 호출할 수 있어야 한다. 이는 단순한 작업이 아닌데, (시스템 호출 처리 함수를 가리키는 함수 포인터가 들어있는) 시스템 호출 테이블은 정적 커널 빌드의 일부이기 때문이다.

모듈은 정적 함수의 일부가 아니며, 정적으로 붙박이된 시스템 호출 함수가 모듈의 일부인 함수를 호출하지 못하는 이유가 바로 여기에 있다. 해법으로 모듈에 있는 함수 포인터를 정적이면서 붙박이 시스템 호출 함수로 복사하는 함수 감싸게를 구현해 정적으로 붙박이 시스템 호출 처리기가 모듈 내부 함수를 호출하도록 만든다. 함수 감싸게는 모듈 초기화 과정과 해제 과정에서 호출된다. 그림 4에서 실선 화살표는 함수 감싸게 메서드를 보여준다.


그림 4. 시스템 호출과 모듈 함수
시스템 호출과 모듈 함수

모듈 내부에 구현된 함수 포인터를 정적이면서 붙박이 커널 영역으로 복사하는 방법을 살펴보았다. 점선 화살표는 사용자 영역 응용 프로그램이 정적이면서 붙박이 시스템 호출 처리 함수를 전달해 모듈 내부에 있는 함수를 호출하는 모습을 보여준다.

변경이 필요한 커널 원시 코드 파일은 다음과 같다.

  • include/asm-powerpc/systbl.h
  • include/asm-powerpc/unistd.h
  • include/linux/syscalls.h
  • kernel/sys.c
  • kernel/sys_ni.c
  • kernel/ve/vecalls.c

또한 OpenVZ vzctl에서 변경이 필요한 파일은 다음과 같다.

  • include/res.h
  • include/vzctl_param.h
  • include/vzsyscalls.h
  • src/lib/config.c
  • src/lib/res.c
  • src/vzctl.c

OpenVZ 빌드 시스템에서 파일 두 개를 추가로 수정해야 한다.

  • include/spu.h
  • src/lib/spu.c



위로


Part 3를 위한 준비

Part 3는 의사 가상화나 완전 가상화 같은 다른 소프트웨어 가상화와 비교해 컨테이너 가상화 성능을 분석하고 시스템을 활용하고 테스트하는 방법을 설명한다.



참고자료

교육

제품 및 기술 얻기

토론
  • 포럼에 참여하기.

  • 프로세서에 대한 기술 질문 대답을 얻기 위해 셀/B.E. 아키텍처 포럼을 살펴본다. 포럼에서 유용한 문제와 대답이 주기적으로 올라오며, 중요 질문과 대답은 "포럼 감시" 블로그 연재물에서 다시 한번 강조될 것이다.

  • 파워 아키텍처 블로그를 살펴 새소식, 내려받기, 도움이 되는 자원, 셀/B.E.와 다른 파워 아키텍처 관련 기술을 위한 이벤트 정보를 얻자. 인기있는 "포럼 감시" 블로그 연재(Q&A 정리), "FixIT" 기술 갱신, Infobomb 기술 요약 정리를 찾을 수 있을 것이다.


필자소개

Christian Kaiser는 독일 아헨에 있는 RWTH 대학교에서 컴퓨터 공학을 공부했다. 2007년에 Kaiser는 독일 뵈블링엔에 위치한 IBM 독일 연구소에서 인턴으로 근무했다. IBM에서 인턴으로 근무하는 동안 셀/B.E. 프로세서에서 시각화 방법을 연구했다. 인턴을 마치고 Kaiser는 RWTH 아헨에서 운영체제 관련 논문을 마치러 돌아갔다. 논문 제목은 "Analysis of asynchronous collective communication in memory-coupled high-speed networks"다.


Christian Rund는 독일 뵈블링엔에 있는 IBM 개발 연구소에서 근무하고 있다. Rund는 슈튜트가르트 대학교에서 컴퓨터 과학을 공부했으며, 스웨덴 웁살라 대학교를 1997년에 졸업했다. 학창 시절에 Rund는 독일 헤른베르크에 있는 IBM에서 실습생으로 일했다. 1988년 Rund는 슈투트가르트에 있는 란데스쩬트랄방크(도이체 분데스방크)의 시스템 개발 부서에 합류했다. 2001년에 Rund는 IBM에 합류해 zSeries FCP 채널을 위한 개발 팀에서 연구 개발 엔지니어로 일했다. 2006년 중반 셀/B.E. 기반 서버를 위한 호스트 펌웨어 개발 연구 엔지니어로 근무하고 있다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



 


 


12345
 


이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us





위로


IBM is a trademark of IBM Corporation in the United States, other countries, or both. UNIX is a registered trademark of The Open Group in the United States and other countries. Linux is a registered trademark of Linus Torvalds in the United States, other countries, or both. Other company, product, or service names may be trademarks or service marks of others. 기타 회사, 제품, 및 서비스명은 다른 상표나 서비스 마크일 수 있습니다.

developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의