IT/기초 지식

[Docker] NVIDIA Container Toolkit(NVIDIA Docker)의 동작원리

개발자 두더지 2022. 2. 18. 01:30
728x90

일본 포스팅을 번역한 자료입니다. 오역및 의역이 있을 수 있으며, 틀린 내용이 있는 경우 지적해주시면 정정하겠습니다.
Docker에서 NIVIDA GPU를 사용하는 경우 NVIDIA Container Toolkit(NVIDIA Docker)이 필요하다. 이번 포스팅에서는 왜 NVIDIA Container Toolkit이 필요한지, 어떻게 동작하고 있는지에 대해 설명할 것이다. 참고로 2021년 4월 시점 내용이니 현재는 바꼈을지도 모르니 어디까지나 참고로 하길 바란다.

왜 NVIDIA Container Toolkit(NVIDIA Docker)이 필요할까?


NVIDIA GPU는 호스트의 디바이스 파일 (/dev/nvidia0등)으로써 등록되어 있다. 또한, CUDA 라이브러리(libcuda.so등)는 호스트에 설치된 버전과 일치할 필요가 있다. 그러므로 컨테이너로부터 GPU를 이용하는 경우, 이러한 것들을 모두 호스트로부터 마운트할 필요가 있다.
그러나 디바이스명이나 라이브러리의 버전은 계속해서 변하므로 설정이 번거롭다. 마운트한 라이브러리의 사용 전에 ldconfig를 실행하여 공유 라이브러리의 갱신을 하는 등의 전처리도 필요하다.
NVIDIA Container Toolkit(NVIDIA Docker)은 컨테이너에서 NVIDIA GPU를 사용할 수 있도록, 마운트 등의 준비를 자동으로 해주는 것이다.

호스트 쪽의 NVIDIA 디바이스나 라이브러리를 마운트하기 위해, 호스트 쪽에 NVIDIA 드라이브가 설치되어 있을 필요가 있다. NVIDIA 라이브러리의 설치하는 몇 가지 방법이 있지만, cuda-drivers 패키지로 설치하는 방법이 간단하다.

마운트 내용 확인하기

Docker의 --gpus 옵션의 유무로 마운트와의 차이를 비교하면, NVIDIA Container Toolkit에 의해 어떠한 점이 바뀌는지 확인할 수 있다. 마운트된 것들은 지정된 GPU 옵션에 의해 차이가 있다. 마운트 이외에도 공유 라이브러리의 갱신을 실시하는 ldconfig의 실행 등도 자동으로 행해지고 있다.

# 마운트의 차이를 확인하는 커맨드의 예 diff -U 0 \ <(sudo docker run --runtime=runc --entrypoint /bin/mount nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2) \ <(sudo docker run --runtime=runc --gpus=all --entrypoint /bin/mount nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2)
# 마운트 차이의 예 --- /dev/fd/63 2021-04-08 08:18:42.567678185 +0000 +++ /dev/fd/62 2021-04-08 08:18:42.567678185 +0000 @@ -1 +1 @@ -overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/2V65PYVZQEQEQUKYGYKL7HR5FR:/var/lib/docker/overlay2/l/7AIBFJWODCJRWMDLILRWOHB4Q7:/var/lib/docker/overlay2/l/V4OWAINIOOG5CUMPSAKM3VJZ5Q:/var/lib/docker/overlay2/l/LKGX4OMPAYSA47UDWAQDI2X5T3:/var/lib/docker/overlay2/l/NMVYKU22UFTYCR746XX4YXYZAJ:/var/lib/docker/overlay2/l/KH33H3HWPX7J54CSBPGEHVODCH:/var/lib/docker/overlay2/l/NPFWWK26TM64CQQJK3GUYF7RPO:/var/lib/docker/overlay2/l/A76FTIXHIEOSZVT427WCLXYTVP:/var/lib/docker/overlay2/l/SZJWHW7O4WNEYUYJ6S2DZ7M22K,upperdir=/var/lib/docker/overlay2/4e868bfba66474c89e5afe795f9cba4e8c30f03b33e8270bceda5f8f718f1b72/diff,workdir=/var/lib/docker/overlay2/4e868bfba66474c89e5afe795f9cba4e8c30f03b33e8270bceda5f8f718f1b72/work,xino=off) +overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/GPNKN2XS3ZRFTOLF67IUBLPJOG:/var/lib/docker/overlay2/l/7AIBFJWODCJRWMDLILRWOHB4Q7:/var/lib/docker/overlay2/l/V4OWAINIOOG5CUMPSAKM3VJZ5Q:/var/lib/docker/overlay2/l/LKGX4OMPAYSA47UDWAQDI2X5T3:/var/lib/docker/overlay2/l/NMVYKU22UFTYCR746XX4YXYZAJ:/var/lib/docker/overlay2/l/KH33H3HWPX7J54CSBPGEHVODCH:/var/lib/docker/overlay2/l/NPFWWK26TM64CQQJK3GUYF7RPO:/var/lib/docker/overlay2/l/A76FTIXHIEOSZVT427WCLXYTVP:/var/lib/docker/overlay2/l/SZJWHW7O4WNEYUYJ6S2DZ7M22K,upperdir=/var/lib/docker/overlay2/a4aaa0c474a91c9856d083d06618161c34516d4a3a361032c08f34c44bbab08f/diff,workdir=/var/lib/docker/overlay2/a4aaa0c474a91c9856d083d06618161c34516d4a3a361032c08f34c44bbab08f/work,xino=off) @@ -23,0 +24,22 @@ +tmpfs on /proc/driver/nvidia type tmpfs (rw,nosuid,nodev,noexec,relatime,mode=555) +/dev/vda1 on /usr/bin/nvidia-smi type ext4 (ro,nosuid,nodev,relatime) +/dev/vda1 on /usr/bin/nvidia-debugdump type ext4 (ro,nosuid,nodev,relatime) +/dev/vda1 on /usr/bin/nvidia-persistenced type ext4 (ro,nosuid,nodev,relatime) +/dev/vda1 on /usr/bin/nvidia-cuda-mps-control type ext4 (ro,nosuid,nodev,relatime) +/dev/vda1 on /usr/bin/nvidia-cuda-mps-server type ext4 (ro,nosuid,nodev,relatime) +/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.460.32.03 type ext4 (ro,nosuid,nodev,relatime) +/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-cfg.so.460.32.03 type ext4 (ro,nosuid,nodev,relatime) +/dev/vda1 on /usr/lib/x86_64-linux-gnu/libcuda.so.460.32.03 type ext4 (ro,nosuid,nodev,relatime) +/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-opencl.so.460.32.03 type ext4 (ro,nosuid,nodev,relatime) +/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-ptxjitcompiler.so.460.32.03 type ext4 (ro,nosuid,nodev,relatime) +/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-allocator.so.460.32.03 type ext4 (ro,nosuid,nodev,relatime) +/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-compiler.so.460.32.03 type ext4 (ro,nosuid,nodev,relatime) +overlay on /usr/lib/x86_64-linux-gnu/libcuda.so.440.118.02 type overlay (ro,nosuid,nodev,relatime,lowerdir=/var/lib/docker/overlay2/l/GPNKN2XS3ZRFTOLF67IUBLPJOG:/var/lib/docker/overlay2/l/7AIBFJWODCJRWMDLILRWOHB4Q7:/var/lib/docker/overlay2/l/V4OWAINIOOG5CUMPSAKM3VJZ5Q:/var/lib/docker/overlay2/l/LKGX4OMPAYSA47UDWAQDI2X5T3:/var/lib/docker/overlay2/l/NMVYKU22UFTYCR746XX4YXYZAJ:/var/lib/docker/overlay2/l/KH33H3HWPX7J54CSBPGEHVODCH:/var/lib/docker/overlay2/l/NPFWWK26TM64CQQJK3GUYF7RPO:/var/lib/docker/overlay2/l/A76FTIXHIEOSZVT427WCLXYTVP:/var/lib/docker/overlay2/l/SZJWHW7O4WNEYUYJ6S2DZ7M22K,upperdir=/var/lib/docker/overlay2/a4aaa0c474a91c9856d083d06618161c34516d4a3a361032c08f34c44bbab08f/diff,workdir=/var/lib/docker/overlay2/a4aaa0c474a91c9856d083d06618161c34516d4a3a361032c08f34c44bbab08f/work,xino=off) +overlay on /usr/lib/x86_64-linux-gnu/libnvidia-fatbinaryloader.so.440.118.02 type overlay (ro,nosuid,nodev,relatime,lowerdir=/var/lib/docker/overlay2/l/GPNKN2XS3ZRFTOLF67IUBLPJOG:/var/lib/docker/overlay2/l/7AIBFJWODCJRWMDLILRWOHB4Q7:/var/lib/docker/overlay2/l/V4OWAINIOOG5CUMPSAKM3VJZ5Q:/var/lib/docker/overlay2/l/LKGX4OMPAYSA47UDWAQDI2X5T3:/var/lib/docker/overlay2/l/NMVYKU22UFTYCR746XX4YXYZAJ:/var/lib/docker/overlay2/l/KH33H3HWPX7J54CSBPGEHVODCH:/var/lib/docker/overlay2/l/NPFWWK26TM64CQQJK3GUYF7RPO:/var/lib/docker/overlay2/l/A76FTIXHIEOSZVT427WCLXYTVP:/var/lib/docker/overlay2/l/SZJWHW7O4WNEYUYJ6S2DZ7M22K,upperdir=/var/lib/docker/overlay2/a4aaa0c474a91c9856d083d06618161c34516d4a3a361032c08f34c44bbab08f/diff,workdir=/var/lib/docker/overlay2/a4aaa0c474a91c9856d083d06618161c34516d4a3a361032c08f34c44bbab08f/work,xino=off) +overlay on /usr/lib/x86_64-linux-gnu/libnvidia-ptxjitcompiler.so.440.118.02 type overlay (ro,nosuid,nodev,relatime,lowerdir=/var/lib/docker/overlay2/l/GPNKN2XS3ZRFTOLF67IUBLPJOG:/var/lib/docker/overlay2/l/7AIBFJWODCJRWMDLILRWOHB4Q7:/var/lib/docker/overlay2/l/V4OWAINIOOG5CUMPSAKM3VJZ5Q:/var/lib/docker/overlay2/l/LKGX4OMPAYSA47UDWAQDI2X5T3:/var/lib/docker/overlay2/l/NMVYKU22UFTYCR746XX4YXYZAJ:/var/lib/docker/overlay2/l/KH33H3HWPX7J54CSBPGEHVODCH:/var/lib/docker/overlay2/l/NPFWWK26TM64CQQJK3GUYF7RPO:/var/lib/docker/overlay2/l/A76FTIXHIEOSZVT427WCLXYTVP:/var/lib/docker/overlay2/l/SZJWHW7O4WNEYUYJ6S2DZ7M22K,upperdir=/var/lib/docker/overlay2/a4aaa0c474a91c9856d083d06618161c34516d4a3a361032c08f34c44bbab08f/diff,workdir=/var/lib/docker/overlay2/a4aaa0c474a91c9856d083d06618161c34516d4a3a361032c08f34c44bbab08f/work,xino=off) +tmpfs on /run/nvidia-persistenced/socket type tmpfs (rw,nosuid,nodev,noexec,relatime,size=11344316k,mode=755) +udev on /dev/nvidiactl type devtmpfs (ro,nosuid,noexec,relatime,size=56704416k,nr_inodes=14176104,mode=755) +udev on /dev/nvidia-uvm type devtmpfs (ro,nosuid,noexec,relatime,size=56704416k,nr_inodes=14176104,mode=755) +udev on /dev/nvidia-uvm-tools type devtmpfs (ro,nosuid,noexec,relatime,size=56704416k,nr_inodes=14176104,mode=755) +udev on /dev/nvidia0 type devtmpfs (ro,nosuid,noexec,relatime,size=56704416k,nr_inodes=14176104,mode=755) +proc on /proc/driver/nvidia/gpus/0000:00:05.0 type proc (ro,nosuid,nodev,noexec,relatime)


Docker에서의 사용법


Docker에서 NVIDIA GPU를 사용하기 위해 사용하는 2가지 방법이 있다.
1. Docker의 --gpus 옵션을 사용한다.
2. Docker의 runtime에 nvidia를 사용한다.
어느 방법도 결국에는 Docker에 사용되고 있는 컨테이너 런타임 runc의 실행전에, NVIDIA Container Toolkit의 preStart Hook으로 실행되는 훅인 nvidia-container-runtime-hook에 의해 GPU가 설정된다.

Docker의 --gpus 옵션 사용하기

Docker 19.03부터 --gpus 옵션을 사용할 수 있으며, Docker 단체에서는 --gpus 옵션을 사용하는 것을 추천한다. 다음 커맨드는 Docker에서 --gpus 옵션을 사용하는 예이다.

docker run --gpus=all nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2

Docker의 runtime에 nvidia 사용하기

Kubernetes는 v1.21기준으로 Docker의 --gpus 옵션에 대응하지 않는다. 그러므로 Kubernetes로 NVIDIA GPU를 사용하는 경우는 nvidia runtime을 디폴트 런타임으로 설정할 필요가 있다.
다음의 커맨드는 Docker에서 nvidia 런타임을 지정하는 예이다. 또한, 디폴트 런타임을 nvidia를 지정해둔 경우 --runtime으로 지정할 필요가 없다.

docker run --runtime=nvidia nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2

참고로 디폴트 런타임으로 지정하기 위해서는 /etc/docker/daemon.json파일을 텍스트 에디터로 연 뒤, "default-runtime": "nvidia"를 추가해주면 된다.

{ "default-runtime": "nvidia", # 다른 설정 부분은 생략 }

GPU 디바이스와 옵션의 지정

--gpus 옵션과 nvidia 런타임에서는 NVIDIA GPU 옵션을 지정하는 방법이 각각 다르다. 이러한 지정을 하지 않은 경우, GPU 디바이스 등은 마운트되지 않는다. 지정 방법의 상세는 공식 사이트에서 확인가능하다.

사용 방법 지정 방법
--gpus 옵션 --gpus 옵션의 인수
nvidia 런타임 NVIDIA_VISIBLE_DEVICES 등의 환경변수로 지정

또한, --gpus 옵션 지정시에도 내부적으로는 환경 변수가 설정된다.
지정가능한 옵션은 다음과 같다. 사용할 GPU의 열거만 필수 이다. 베이스 이미지에 NVIDIA CUDA를 지정하고 있는 등의 경우는 베이스 이미지쪽에 환경 변수 NVIDIA_VISIBLE_DEVICES=all를 지정하고 있으므로, 의식하지 않았지만 지정되어 있는 경우가 있다.

  • 사용할 GPU의 열거

- 어떤 GPU 디바이스를 이용할 것인지를 지정
- all의 경우 전부, 0, 1, 2의 인덱스나 UUID로도 지정할 수 있다.

  • 드라이버 Capabilities

- 마운트할 드라이버의 종류를 지정한다 (예) compute, utility

  • CUDA 버전등의 제한

- 환경변수에서의 설정만 가능 (--gpus 옵션에서는 대응하지 않는다)
또한, Kubernetes에서 이용하는 경우 GPU 열거의 지정은 리소스 리퀘스트의 nvidia.com/gpu 지정에 따라 NVIDA device plugin쪽에서 설정된다.

구조(아키텍처)


NVIDIA Container Toolkit의 구조에 대해 알아보자. Docker의 경우 NVIDIA Container Toolkit은 주로 다음의 구성요소로 구성되어 있다. 구성 요소는 위에서 부터 아래의 순서대로 의존하는 형태로 되어 있다. 이용 방법에 따라 의존하는 구성 요소가 변한다. 그러나 공식 문서의 Which package should I use then?에서는 심플함과 과거 버전과의 호환성을 위해, 모두를 포함하고 있는 nvidia-docker2를 톱 레벨 패키지로써 이용하는 것을 추천한다.

nvidia-docker2

GitHub - NVIDIA/nvidia-docker: Build and run Docker containers leveraging NVIDIA GPUs

Build and run Docker containers leveraging NVIDIA GPUs - GitHub - NVIDIA/nvidia-docker: Build and run Docker containers leveraging NVIDIA GPUs

github.com

Docker용의 톱 레벨 패키지이다. 이 패키지를 넣으면, 아래의 컴포넌트는 의존 패키지로써 자동적으로 설치된다. NVIDIA 드라이버(예를 들어, cuda-drivers)는 별도의 설치가 필요하다.
이 패키지에는 nvida-container-runtime의 런타임 nvidia를 Docker에 추가하는 아래의 설정(/etc/docker/daemon.json)가 포함되어 있다. 이미 daemon.json 설정파일이 존재하고 있는 경우, 수동으로 설정해야할 필요가 있으므로 주의하자(dpkg의 경우는 conffiles 지정으로 되어 있다).

{ "runtimes": { "nvidia": { "path": "nvidia-container-runtime", "runtimeArgs": [] } } }

nvidia-container-runtime

GitHub - NVIDIA/nvidia-container-runtime: NVIDIA container runtime

NVIDIA container runtime. Contribute to NVIDIA/nvidia-container-runtime development by creating an account on GitHub.

github.com

runc를 랩한 OCI 런타임 준거의 nvidia 런타임이 포함되어 있다. Docker에 --runtime=nvidia를 붙인 경우, 이 런타임이 호출된다.
이 nvidia 런타임은 NVIDIA의 설정 처리를 실행하는 훅 nvidia-container-runtime-hook을 preStart Hook에 설정하여, runc를 실행만 하는 형태된다. 소스 코드로 200행 정도의 main.go만으로 심플하다.
nvidia-container-runtime-hook은 다음 항목의 컴포넌트 nvidia-container-toolkit이 포함된 바이너리이다. symlink가 되어 있어, 실체는 nvidia-container-toolkit이라는 바이너리이다.

$ ls -l /usr/bin/nvidia-container-runtime-hook lrwxrwxrwx 1 root root 33 Apr 13 09:12 /usr/bin/nvidia-container-runtime-hook -> /usr/bin/nvidia-container-toolkit

nvidia-container-toolkit

GitHub - NVIDIA/libnvidia-container: NVIDIA container runtime library

NVIDIA container runtime library. Contribute to NVIDIA/libnvidia-container development by creating an account on GitHub.

github.com

runc가 호출한 OCI의 preStart Hook이다. 이 훅은 실제의 NVIDIA 설정 처리를 실행하는 nvidia-container-cli를 호출한다. Docker의 --gpus 옵션을 사용하는 경우, 실제 의존하고 있는 것은 nvidia-container-toolkit 아래의 컴포넌트뿐이 된다. GPU의 설정은 환경 변수 경우로 이뤄진다.
OCI의 preStart Hook으로써 구현되고 있으므로 runc에 한정되지 않고, OCI Runtime의 사양에 따른 컨테이너 런타임이면 이용가능한 구조로 되어 있다.

libnvidia-container

GitHub - NVIDIA/libnvidia-container: NVIDIA container runtime library

NVIDIA container runtime library. Contribute to NVIDIA/libnvidia-container development by creating an account on GitHub.

github.com

Linux 컨테이너에 대응해 NVIDIA GPU에 필요한 설정을 실제로 실행하는 nvidia-container-cli가 포함되어 있다. Ubuntu 등의 패키지는 libnvidia-container1(라이브러리)와 libnvidia-container-tools(CLI)가 분리되어 있다. C에서 적혀있듯, namespace 등 Linux컨테이너의 기능을 직접 이용하고 있으므로, Linux 컨테이너의 구현하지 않는 구조로 되어 있다. GPU 디바이스나 라이브러리의 마운트뿐만 아니라, ldconfig의 실행이나 커넬 모듈의 로드 기능도 포함되어 있다.
아래는 Docker에서의 nvidia-container-cli의 호출되는 인수에 대한 예이다.

nvidia-container-cli \ --load-kmods \ # NVIDIA의 커넬 모듈을 로드 configure \ # 컨테이너를 설정하는 서브 커맨드 --ldconfig=@/sbin/ldconfig.real \ # ldconfig바이너리의 지정 --device=all \ # 사용GPU디바이스의 지정 --utility \ # utility드라이버의 유효화 --compute \ # compute드라이버의 유효와 --pid=57316 \ # 컨테이너의 PID를 지정 /var/lib/docker/overlay2/6a683460c03ce2c1017d7b3efdb274c6c281e039da4de6e079b268e71832f21e/merged # ↑rootfs의 지정

또한, list이라는 서브 커맨드를 사용하면, GPU 서포트에 필요한 파일의 목록을 확인할 수 있다.

$ nvidia-container-cli list /dev/nvidiactl /dev/nvidia-uvm /dev/nvidia-uvm-tools /dev/nvidia-modeset /dev/nvidia0 /usr/bin/nvidia-smi /usr/bin/nvidia-debugdump /usr/bin/nvidia-persistenced /usr/bin/nvidia-cuda-mps-control /usr/bin/nvidia-cuda-mps-server /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-cfg.so.460.56 /usr/lib/x86_64-linux-gnu/libcuda.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-opencl.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-ptxjitcompiler.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-allocator.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-compiler.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-ngx.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-encode.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-opticalflow.so.460.56 /usr/lib/x86_64-linux-gnu/libnvcuvid.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-eglcore.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-glcore.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-tls.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-glsi.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-fbc.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-ifr.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-rtcore.so.460.56 /usr/lib/x86_64-linux-gnu/libnvoptix.so.460.56 /usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.460.56 /usr/lib/x86_64-linux-gnu/libEGL_nvidia.so.460.56 /usr/lib/x86_64-linux-gnu/libGLESv2_nvidia.so.460.56 /usr/lib/x86_64-linux-gnu/libGLESv1_CM_nvidia.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-glvkspirv.so.460.56 /usr/lib/x86_64-linux-gnu/libnvidia-cbl.so.460.56 /run/nvidia-persistenced/socket


NVIDIA Container Toolkit 의 처리 흐름


Docker의 --gpus 옵션을 사용했을 경우와 런타임에서 nvidia를 사용한 경우 처리의 흐름이 달라지지만, 어떤 방법이든 결국에는 nvidia-container-toolkit이 runc의 preStart Hook으로 설정되어 실제 설정을 실행하는 nvidia-container-cli가 호출된다.
docker run으로 컨테이너를 실행했을 경우, 주로 다음과 같은 컴포넌트가 호출된다. 최종적으로는 컨테이너를 실행하는 런타임이 runc이다. (shim은 생략하고 있다)

컴포넌트 개요 리포지터리
docker CLI Docker의 CLI docker/cli
dockerd Docker Engine moby/moby
containerd 실제 컨테이너나 이미지 관리를 실행 containerd/containerd
runc OCI Runtime Spec 준거의 컨테이너 런타임 opencontainers/runc

참고자료
https://qiita.com/tkusumi/items/f275f0737fb5b261a868

728x90