배치로 갤러리 만들기

KubernetesBeginner
지금 연습하기

소개

Field Notes에는 라이선스가 확보된 정원 사진 스무 장이 있으며, 직원이 다운로드할 수 있는 작은 갤러리가 필요합니다. 먼저 한 그룹을 시험한 다음 Kubernetes Job으로 네 그룹을 모두 실행합니다. 마지막 그룹에는 사진이 두 장뿐이지만, 이 그룹도 자체 완료 인덱스가 성공해야 합니다.

Pod, Deployment, Service, 레이블, 간단한 YAML, 기본 터미널 경로를 이미 알고 있어야 합니다. Job, 완료 인덱스, 이 공유 볼륨, 여기서 사용하는 편집 명령은 아래에서 소개합니다. 클러스터, 처리기 이미지, 원본 사진, 웹사이트, 스토리지는 준비되어 있습니다. Python을 작성하거나 이미지를 빌드하거나 클라우드 계정을 준비할 필요가 없습니다.

명령은 Workspace에서 실행하고 웹사이트는 Gallery에서 확인합니다. 두 진입점은 하나의 교육용 VM을 사용합니다. starter/와 inputs/ 아래의 제공된 파일, 원본 사진, 참조 예제, 처리기, 서비스, 스토리지는 변경하지 마세요. 45분은 읽기와 일반적인 실수에 필요한 시간을 포함한 저자의 예상 시간입니다.

먼저 한 그룹 시험하기

이 단계에서는 정상적으로 완성된 예제를 원본과 비교한 다음, 인덱스가 하나인 Job으로 별도의 샘플을 처리합니다.

Gallery를 여세요. 홈페이지의 큰 사진에는 Source collection · licensed garden photographs라는 레이블이 있습니다. 이는 입력 자료이며 여러분이 완성한 작업이 아닙니다. See the reference를 선택하세요. Thumbnail은 제공된 320 × 220 JPEG이며, Licensed source copy는 원래 비율을 유지합니다. 가장자리가 다른 이유는 잘라내기 때문입니다. 페이지 탐색 메뉴에서 Gallery를 선택하세요. 처음에는 0 of 20 images available로 표시됩니다.

Workspace로 전환하세요. 이 터미널은 /home/labex/project/photo-gallery에서 시작합니다. pwd는 이 작업 디렉터리를 출력합니다.

pwd

다른 위치로 이동했다면 cd /home/labex/project/photo-gallery로 돌아오세요. 아래의 모든 상대 파일 이름은 이 위치를 기준으로 합니다. 파일은 이 VM에 유지되지만, 다른 실습은 자체적인 독립 파일과 클러스터 리소스로 시작합니다.

Deployment는 서비스를 계속 실행합니다. 반면 Job은 정해진 작업이 완료될 때까지 Pod를 실행합니다. 제공된 워커는 사진 한 그룹을 처리하고 종료합니다. Indexed Job에서 Kubernetes는 필요한 각 완료 작업에 0부터 시작하는 번호를 부여합니다. 워커는 Kubernetes가 제공하는 JOB_COMPLETION_INDEX 값을 읽고 해당 그룹을 선택합니다. 여러분은 워커를 작성하는 대신 Job을 구성합니다.

제공된 샘플 매니페스트를 읽으세요. cat은 파일을 변경하지 않고 표시합니다.

cat starter/sample-job.yaml

중요한 필드는 completionMode: Indexed, completions: 1, parallelism: 1입니다. 이 필드들은 원하는 동시 워커 수를 하나로 하여 인덱스 0만 요청합니다. restartPolicy: Never는 실패한 컨테이너를 해당 Pod에서 실패 상태로 유지한다는 뜻입니다. 다른 Pod가 필요한지는 Job 정책이 결정합니다. backoffLimit: 0은 원본이 정상인 이 연습에서 재시도하지 않는다는 뜻이며, activeDeadlineSeconds: 180은 Job의 활성 수명을 제한합니다. 나머지 필드들은 준비된 이미지, 입력 계획, 출력 볼륨을 연결하므로 변경하지 마세요.

PersistentVolumeClaim, 줄여서 PVC는 영구 스토리지를 요청합니다. 준비된 gallery-output PVC는 워커가 종료된 후에도 파일을 유지합니다. 여기서는 ReadWriteOnce 볼륨을 같은 노드의 여러 Pod에서 마운트할 수 있습니다. 여러 노드에 걸친 공유 쓰기까지 보장하는 것은 아닙니다. 샘플은 별도의 sample 디렉터리에 기록하므로 최종 갤러리를 모르는 사이에 채울 수 없습니다.

샘플을 적용하세요. apply -f는 이름으로 지정한 YAML 파일을 읽습니다. -n은 이 프로젝트의 Kubernetes 리소스를 묶는 네임스페이스를 선택합니다.

kubectl apply -n photo-workshop -f starter/sample-job.yaml

Job 고유의 Complete 조건을 기다리세요. --timeout=180s는 이 명령이 기다리는 시간을 제한하며 Job의 기한을 변경하지는 않습니다.

kubectl wait -n photo-workshop --for=condition=Complete job/gallery-sample --timeout=180s

예상되는 마지막 출력은 job.batch/gallery-sample condition met입니다. 시간 초과만으로 실패가 입증되지는 않습니다. 변경할 내용을 결정하기 전에 3단계에서 배우는 명령으로 Job과 로그를 조사하세요. setup을 다시 실행하거나 제공된 리소스를 삭제하지 마세요.

Gallery로 전환하여 Sample을 선택하고 6 of 6 images available을 확인하세요. Windmill garden을 열어 썸네일과 원본을 비교한 다음 Back to sample을 선택하세요. 페이지 탐색 메뉴에서 Gallery를 선택하면 최종 모음은 여전히 비어 있습니다. 이 구분은 성공한 연습 실행을 전체 결과물로 오해하지 않도록 합니다.

모든 완료 인덱스 계획하기

이 단계에서는 입력 그룹 구성을 저장된 Job 매니페스트로 옮깁니다. 이 단계의 어떤 작업도 아직 최종 처리를 시작하지 않습니다.

/home/labex/project/photo-gallery에서 시작하는 Workspace로 전환하세요. 전체 입력 매핑을 읽으세요.

cat inputs/groups.txt

Index 0부터 Index 3까지 네 줄이 있습니다. 처음 세 줄은 각각 사진 여섯 장을 포함하고, 인덱스 3은 photo-19와 photo-20을 포함합니다. completions는 사진이 아닌 그룹 수를 셉니다. 이 결과물을 완성하려면 20개나 3개가 아니라 4개의 인덱스가 성공해야 합니다.

직원용 작업 지침을 읽으세요.

cat inputs/brief.txt

요청된 병렬도는 1부터 2까지 허용됩니다. 두 그룹이 함께 진행할 수 있도록 2를 요청하겠습니다. 리소스를 사용할 수 없으면 Kubernetes는 더 적은 Pod를 실행할 수 있습니다. 요청된 병렬도는 재시도나 종료 중의 모든 프로세스에 대한 절대적인 제한이 아닙니다. 이 프로젝트는 분산 처리 플랫폼 대신 준비된 작은 노드 하나를 사용합니다.

준비된 최종 Job 템플릿을 편집할 파일로 복사하세요. cp는 파일을 복사하며 starter/ 아래의 소스를 온전히 남겨 둡니다.

cp starter/gallery-job.yaml gallery-job.yaml

cp가 No such file or directory를 보고하면 pwd를 확인하고 위 디렉터리로 돌아온 뒤, 정확한 파일 이름으로 같은 복사를 반복하세요. 빈 대체 템플릿을 만들지 마세요.

sed로 복사한 파일의 두 필드 값을 문자 그대로 바꾸세요. -i는 해당 파일을 직접 편집합니다. 각 표현식은 s/old/new/ 형식이며, 이전 텍스트를 새 텍스트로 교체합니다. 작은따옴표는 셸이 표현식을 문자 그대로 전달하게 합니다. 제공된 이 템플릿에서 해당 필드들은 각각 한 번씩 나타납니다.

sed -i 's/completions: 1/completions: 4/' gallery-job.yaml
sed -i 's/parallelism: 1/parallelism: 2/' gallery-job.yaml

적용하기 전에 저장된 결과를 읽으세요.

cat gallery-job.yaml

metadata.name: gallery-batch, completionMode: Indexed, completions: 4, parallelism: 2를 확인하세요. 준비된 처리기 이미지, 명령, 환경, 마운트, 리소스 설정, 재시도하지 않는 정책, 180초 기한을 유지하세요. 동등한 YAML 서식이나 다른 새로운 최종 Job 이름도 허용됩니다. 저장된 파일은 실제로 실행하는 Job을 설명해야 합니다.

잘못 입력한 치환은 일치하는 내용이 없어도 성공적으로 종료할 수 있으므로 결과를 읽는 것이 중요합니다. 아직 파일을 적용하지 않았다면 원래 템플릿을 다시 복사하고 두 편집을 반복하여 복구하세요. Job을 적용한 뒤에는 충돌하는 이름으로 다시 복사하지 마세요. Job 작업 템플릿은 일반적으로 변경할 수 없으므로, 다른 시도를 위해 새 Job 이름을 준비하세요.

전체 배치 실행하기

이 단계에서는 저장된 Job을 적용하고 Kubernetes 고유의 완료 증거를 실제 워커 Pod와 연결합니다.

Workspace의 /home/labex/project/photo-gallery에서 저장된 파일을 적용하세요.

kubectl apply -n photo-workshop -f gallery-job.yaml

필요한 모든 인덱스가 완료될 때까지 기다리세요.

kubectl wait -n photo-workshop --for=condition=Complete job/gallery-batch --timeout=180s

Kubernetes 고유의 Job 요약을 읽으세요.

kubectl get job gallery-batch -n photo-workshop

완료된 Job은 완료 수를 4/4로 표시해야 합니다. describe는 세부 정보와 이벤트를 추가합니다.

kubectl describe job gallery-batch -n photo-workshop

Completion Mode: Indexed와 Completed Indexes: 0-3을 찾으세요. 범위에는 양 끝이 포함되므로, 사진이 적은 마지막 그룹까지 네 그룹을 모두 포함합니다. 완료 증거만으로 이미지 내용이 올바르다고 볼 수는 없습니다. 다음 단계에서 이를 확인하고 다운로드합니다.

이 Job에 속하는 Pod만 나열하세요. -l은 레이블로 선택합니다. -L은 다른 레이블을 보여 주는 열을 추가하며, 여기서는 완료 인덱스를 표시합니다.

kubectl get pods -n photo-workshop -l batch.kubernetes.io/job-name=gallery-batch -L batch.kubernetes.io/job-completion-index

인덱스 0, 1, 2, 3의 완료된 Pod가 있어야 합니다. 이 표의 Completed는 Pod의 성공 단계를 나타냅니다. 실제 워커 출력을 읽으세요. --all-pods=true는 Job의 Pod를 포함하고, --prefix=true는 각 줄을 출력한 Pod를 식별합니다.

kubectl logs -n photo-workshop job/gallery-batch --all-pods=true --prefix=true

각 워커는 할당된 사진 이름을 표시하고 320 x 220 출력을 보고합니다. 인덱스 3은 사진 두 장을 완료해야 합니다. 이 로그는 발생한 일을 설명하는 데 도움이 됩니다. 실제 파일, 원본과의 관계, Job 소유의 성공한 Pod도 검사합니다.

대기 시간이 초과되면 describe와 같은 Pod/로그 명령을 사용하여 미완료 워크로드와 실패한 워크로드를 구분하세요. 알 수 없는 Job 이름은 보통 파일이 적용되지 않았거나 이름이 다르다는 뜻입니다. gallery-job.yaml을 읽고 실제 이름을 사용하세요. 완료된 Pod나 샘플을 지우지 마세요. 다음 안내형 실습에서는 의도적으로 발생시킨 일시적 원본 장애에서 복구하는 방법을 배웁니다.

실제 이미지 전달하기

이 단계에서는 완성된 웹사이트를 확인하고 사용할 수 있는 전달 파일 두 개를 저장합니다.

Gallery로 전환하여 페이지 탐색 메뉴의 Gallery를 선택하고 새로고침하세요. 20 of 20 images available을 확인하세요. 사진이 적은 마지막 그룹의 Blue and yellow flowers (photo-20)를 여세요. 썸네일을 해당 사진의 원본과 비교하세요. 다른 꽃 사진을 반복해서 복사한 것이어서는 안 됩니다. Download thumbnail을 선택한 뒤 Back to gallery를 선택하세요.

완성된 Field Notes 갤러리

최종 갤러리에는 사진이 적은 마지막 그룹의 두 이미지를 포함하여 서로 다른 준비된 사진 스무 장이 있습니다. 다운로드 동작은 모음 아래에 있습니다.

Take the collection with you에서 Download source index CSV와 Download gallery ZIP을 선택하세요. CSV는 각 출력을 원본 해시, 썸네일 해시, 제작자, 원본 페이지와 연결합니다. ZIP에는 index.csv와 photos/ 아래의 실제 JPEG가 들어 있습니다. 페이지는 실제로 사용할 수 있는 파일을 보고하며, 누락된 작업을 원본에서 다시 생성하지 않습니다. 불완전한 모음도 다운로드할 수 있으므로 전달 전에 완전한 결과를 검증하세요.

페이지 탐색 메뉴에서 Reference를 선택하고 원래 제공된 예제가 계속 작동하는지 확인하세요. Credits를 선택하여 제작자와 Wikimedia Commons 원본 링크를 보세요. 사진은 CC0 라이선스의 실습 자료이며 LabEx가 촬영한 사진이 아닙니다.

Workspace의 /home/labex/project/photo-gallery로 전환하세요. 같은 실제 다운로드를 여기에 저장합니다. curl은 URL을 요청합니다. --fail은 HTTP 실패 시 오류를 반환하고, --silent --show-error는 오류는 유지하면서 진행률 표시를 숨기며, -o는 출력 파일 이름을 지정합니다. 포트 8091은 이 VM에서 준비된 갤러리 Service에 연결합니다.

curl --fail --silent --show-error http://127.0.0.1:8091/download/index.csv -o gallery-index.csv
curl --fail --silent --show-error http://127.0.0.1:8091/download/gallery.zip -o gallery.zip

브라우저 다운로드는 브라우저가 저장합니다. 이 두 명령은 VM 작업 공간에 필요한 복사본을 저장합니다. 요청이 실패하면 웹사이트를 조사하고 문제를 해결한 뒤 요청을 반복하세요. 누락된 이미지를 감추려고 수신한 인덱스를 편집하지 마세요.

헤더와 처음 두 행을 표시하세요. head -n 3은 처음 세 줄을 읽습니다.

head -n 3 gallery-index.csv

헤더는 id,title,source_file,thumbnail,width,height로 시작합니다. 각 행은 사진 하나를 해당 사진의 photos/photo-NN.jpg와 연결하며, 크기는 320,220이고 실제 원본 출처 정보가 포함됩니다.

압축을 풀지 않고 아카이브 목록을 확인하세요. python3 -m zipfile은 Python 표준 ZIP 유틸리티를 실행하며, -l은 멤버 목록을 표시합니다.

python3 -m zipfile -l gallery.zip

index.csv와 photos/photo-20.jpg를 포함한 JPEG 경로 스무 개를 모두 찾으세요. 이름이나 개수만으로 이미지의 정확성을 입증할 수는 없으므로, 기능 검사에서는 실제 JPEG도 디코딩하고 각 사진을 해당 원본에서 생성한 결과와 비교합니다. gallery-job.yaml, 다운로드 두 개, 샘플, 완료된 Pod, 원본 파일, 참조 예제, 준비된 서비스를 계속 사용할 수 있도록 남겨 두세요.

요약

Indexed Job으로 실제 사진 갤러리를 전달했습니다. 사진을 완료 인덱스에 매핑하고, 요청된 병렬도를 제한하며, Kubernetes 고유의 Pod와 Job 증거를 확인하고, 원본 인덱스와 함께 실제 이미지를 전달했습니다. 샘플과 참조 예제는 최종 작업과 분리된 상태로 유지되었습니다.