소개
Juniper Café가 가을 메뉴를 선보일 준비를 마쳤습니다. 웹사이트는 작동하지만 아직 일상 메뉴를 보여 주고 있습니다. Kubernetes를 통해 새 메뉴를 게시하고, 이전 구성을 보존하며, 카운터 직원에게 전달할 실제 메뉴를 다운로드합니다.
Pod, Deployment, Service, 레이블, 간단한 YAML을 이미 알고 있어야 합니다. 클러스터, 애플리케이션 이미지, 웹사이트는 준비되어 있으므로 애플리케이션 코드를 작성하거나 클라우드 계정을 준비할 필요가 없습니다. 이 실습에서는 각 구성에 콘텐츠 기반의 고유 이름을 부여하는 데 필요한 Kustomize의 일부 기능을 소개합니다.
명령은 Workspace에서 실행하고, Juniper는 Café Menu에서, 별도의 독서실 카페는 Reference Menu에서 확인합니다. 모든 진입점은 하나의 교육용 VM을 공유합니다. 참조 카페, 애플리케이션 코드, Service, 복제본 수, 제공된 릴리스 이력은 변경하지 마세요. 저자가 예상한 40분에는 읽기와 일반적인 실수에 필요한 시간이 포함됩니다.
별도의 메뉴 릴리스 준비하기
이 단계에서는 현재 웹사이트와 구성의 관계를 확인하고, 서비스 중인 메뉴를 변경하지 않은 채 릴리스 디렉터리를 준비합니다.
Café Menu를 열고 Explore the menu를 선택한 다음 Maple Latte를 찾으세요. 현재 가격은 $4.20이며 Not available today로 표시됩니다. Cold Brew는 판매 중입니다. Oat Latte의 About this drink를 연 뒤 Back to the menu로 돌아오세요. 준비된 애플리케이션이 제공하는 실제 페이지입니다.
Reference Menu로 전환하고 Our menu를 선택하세요. 이곳은 계속 작동해야 하는 별도의 서비스인 Willow Reading Room입니다. Workspace로 전환하세요. 시작 디렉터리는 /home/labex/project/cafe-menu입니다. 현재 디렉터리를 출력하는 pwd로 확인하세요.
pwd
예상 결과:
/home/labex/project/cafe-menu
Kubernetes ConfigMap은 구성을 애플리케이션 이미지와 분리하여 저장합니다. Pod는 ConfigMap을 이름으로 참조합니다. 이 카페 프로세스는 마운트된 메뉴 파일을 시작할 때 한 번만 읽습니다. 구성을 편집해도 이미 실행 중인 프로세스가 자동으로 메뉴를 다시 읽지는 않습니다.
준비된 starter 디렉터리에는 작은 파일 세 개가 있습니다. ls로 목록을 확인합니다.
ls starter
deployment.json kustomization.yaml menu.json
JSON도 Kubernetes 매니페스트의 유효한 입력 형식입니다. deployment.json은 준비된 Deployment 정의입니다. 애플리케이션 설정은 유지하고 별도의 메뉴 데이터를 변경합니다.
cp -r로 자신이 사용할 디렉터리를 만드세요. cp는 복사하며, -r은 디렉터리 안의 내용까지 포함합니다. 대상인 release는 아직 존재하지 않습니다.
cp -r starter release
실수로 두 번 실행하면 cp가 중첩된 release/starter를 만들 수 있습니다. 필요한 세 파일은 여전히 release 바로 아래에 있어야 합니다. rm -r release/starter로 실수로 만들어진 중첩 복사본만 제거하세요. release, versions, approved는 제거하지 마세요.
파일을 출력하는 cat으로 구성을 읽으세요.
cat release/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: cafe-menu
resources:
- deployment.json
configMapGenerator:
- name: cafe-menu
files:
- menu.json
resources는 Deployment를 포함합니다. configMapGenerator는 menu.json을 ConfigMap 데이터로 변환합니다. Kustomize는 콘텐츠에서 파생한 접미사를 추가하고 Deployment의 참조를 생성된 이름으로 바꿉니다. 따라서 데이터가 바뀌면 새 Pod 템플릿과 새 롤아웃이 만들어질 수 있으며, 이전 ConfigMap은 그대로 사용할 수 있습니다. 접미사는 콘텐츠를 식별할 뿐, 가격이 올바른지는 알려 주지 않습니다.
승인된 가을 메뉴 작성하기
이 단계에서는 Kubernetes에 변경 사항을 적용하기 전에 완전한 가을 메뉴를 준비합니다.
Workspace에 그대로 있으세요. 카운터 팀의 승인 내역은 approved/menu.csv에 저장되어 있습니다. CSV는 쉼표로 구분한 값을 뜻합니다. 첫 줄은 열 이름이며, 이후 각 줄은 음료 하나를 설명합니다. price_cents는 센트 단위 정수이므로 450은 $4.50를 뜻합니다. true와 false는 해당 음료의 판매 가능 여부를 나타냅니다.
cat approved/menu.csv
id,name,price_cents,available
espresso,Espresso,250,true
oat-latte,Oat Latte,350,true
cold-brew,Cold Brew,390,false
maple-latte,Maple Latte,450,true
Espresso와 Oat Latte는 그대로 유지하세요. Cold Brew는 오늘 판매할 메뉴에서 제외하고, Maple Latte는 $4.50에 판매합니다. 시즌 레이블은 Autumn at Juniper여야 합니다. 카페 이름, 위치, 영업시간, 항목 식별 정보, 설명은 변경하지 않습니다.
아래의 전체 JSON을 작성하세요. JSON에서는 속성 이름을 따옴표로 감싸고, 항목 사이에 쉼표를 넣으며, 불리언은 따옴표 없이 소문자로 작성합니다. 셸 표현식 cat > release/menu.json <<'EOF'는 둘러싸인 텍스트를 해당 파일에 씁니다. >는 이전 내용을 덮어쓰며, 따옴표로 감싼 EOF는 텍스트를 문자 그대로 유지합니다. 마지막 EOF를 포함하여 붙여넣고, 이 마지막 표시는 한 줄에 단독으로 있어야 합니다.
cat > release/menu.json <<'EOF'
{
"name": "Juniper Café",
"season": "Autumn at Juniper",
"hours": "Mon–Sat · 08:00–17:00",
"address": "14 Willow Lane",
"items": [
{"id": "espresso", "name": "Espresso", "price_cents": 250, "available": true, "description": "A small, rich cup with a golden crema."},
{"id": "oat-latte", "name": "Oat Latte", "price_cents": 350, "available": true, "description": "Our espresso with smooth oat milk."},
{"id": "cold-brew", "name": "Cold Brew", "price_cents": 390, "available": false, "description": "Slow-steeped coffee, served over ice."},
{"id": "maple-latte", "name": "Maple Latte", "price_cents": 450, "available": true, "description": "Espresso, oat milk, and a little maple sweetness."}
]
}
EOF
사용하기 전에 JSON을 검증하세요. python3 -m json.tool은 JSON을 읽어 들여쓰기한 형태로 출력하며, 파일을 변경하지 않습니다.
python3 -m json.tool release/menu.json
성공한 출력에는 음료 네 가지가 모두 포함됩니다. 도구가 \u00e9를 é의 표현으로 표시할 수 있습니다. 이는 JSON 이스케이프 표현이며 카페 이름이 바뀐 것이 아닙니다. 쉼표나 따옴표가 빠지면 줄과 열 번호가 포함된 파싱 오류가 발생합니다. 위의 전체 블록을 다시 작성하여 복구한 뒤 검증을 반복하세요. 경로가 잘못되면 파일을 찾을 수 없다는 오류가 발생합니다. pwd를 실행하고 cd /home/labex/project/cafe-menu로 돌아온 뒤 다시 시도하세요.
지금은 릴리스 소스만 바꾸었으므로 웹사이트에는 여전히 일상 메뉴가 표시됩니다. 이는 예상된 동작입니다.
새 구성 버전 게시하기
이 단계에서는 릴리스를 렌더링하고 적용한 다음, 두 카페 복제본이 새 구성을 사용할 때까지 기다립니다.
Workspace에 그대로 있으세요. kubectl kustomize는 디렉터리의 구성을 적용하지 않고 렌더링합니다. 생성된 ConfigMap 이름과 이에 일치하는 Deployment 참조를 확인하세요.
kubectl kustomize release
출력에는 cafe-menu-... 형태의 이름이 포함되며, Deployment의 volumes 중 menu라는 항목 아래에도 같은 이름이 나타납니다. 정확한 접미사는 데이터에 따라 달라집니다. 이는 일상 메뉴의 구성과는 다른 구성 객체입니다.
kubectl apply -k로 디렉터리를 적용하세요. -k 옵션은 -f로 단일 매니페스트를 읽는 대신 Kustomize 디렉터리를 렌더링하도록 kubectl에 요청합니다.
kubectl apply -k release
예상 출력에는 다음이 포함됩니다.
configmap/cafe-menu-... created
deployment.apps/cafe configured
ConfigMap이 생성되었다는 사실만으로 실행 중인 애플리케이션이 변경되었다고 볼 수는 없습니다. rollout status는 Deployment 컨트롤러가 Pod를 교체할 때까지 기다립니다. -n cafe-menu는 이 실습의 네임스페이스를 선택하며, --timeout=120s는 대기 시간을 제한합니다.
kubectl rollout status deployment/cafe -n cafe-menu --timeout=120s
deployment "cafe" successfully rolled out
대기 시간이 초과되면 현재 상태를 유지하고 다음 명령으로 조사하세요. 이미지나 컨테이너 오류는 Pod 상태와 이벤트에 나타납니다. setup을 다시 실행하거나 네임스페이스를 삭제하지 마세요.
kubectl get pods -n cafe-menu
kubectl describe deployment cafe -n cafe-menu
정상적인 롤아웃 후 현재 Deployment와 ReplicaSet을 확인하세요. ReplicaSet은 특정 Pod 템플릿 하나를 유지합니다. Deployment는 이전 ReplicaSet을 롤아웃 이력으로 보관합니다.
kubectl get replicasets -n cafe-menu -l app=cafe
이름을 지정하여 Deployment 자체를 확인하세요.
kubectl get deployment cafe -n cafe-menu
준비된 복제본이 2/2로 표시되어야 합니다. 구성 객체는 여러 개가 남아 있습니다. 새 릴리스를 적용해도 이전 메뉴는 덮어써지지 않았습니다. 목록을 확인하세요.
kubectl get configmaps -n cafe-menu
이전 구성은 삭제하지 마세요. 나중에 이전 버전을 복원하려면 이전 ReplicaSet이 참조하는 정확한 이름의 구성이 필요합니다.
웹사이트 확인하고 메뉴 전달하기
이 단계에서는 실제 고객 경험을 검증하고 카운터 팀이 사용할 메뉴를 저장합니다.
Café Menu로 전환하여 Our menu를 선택하세요. 페이지가 이미 열려 있다면 새로고침하세요. Maple Latte는 $4.50에 Available today로 표시되어야 합니다. Cold Brew는 Not available today로 표시되어야 합니다. Maple Latte 상세 페이지를 열고 Back to the menu로 돌아온 뒤, Visit us를 사용하여 위치와 영업시간을 여전히 확인할 수 있는지 점검하세요.

판매 가능 여부 배지와 가격을 확인하세요. Cold Brew는 판매하지 않으며 Maple Latte는 $4.50에 판매합니다.
Download menu를 사용하여 실제 전체 CSV를 다운로드하세요. 파일을 열고 음료 네 가지를 모두 2단계의 승인된 표와 비교하세요. 다운로드에는 판매하지 않는 음료도 false와 함께 포함되므로, 직원은 이를 실수로 누락된 항목과 구분할 수 있습니다.
Reference Menu로 전환하여 Willow Reading Room의 일상 메뉴가 계속 작동하는지 확인하세요. 그런 다음 Workspace로 돌아오세요.
실제 Juniper 다운로드를 작업 공간에도 저장할 수 있습니다. curl은 로컬 브라우저 진입점에 요청하며, 이 진입점은 실제 Kubernetes Service로 전달합니다. --fail은 HTTP 오류를 보고하고, --silent는 진행률 표시를 숨기며, --show-error는 오류 메시지를 계속 표시합니다. -o는 출력 파일 이름을 지정합니다.
curl --fail --silent --show-error http://127.0.0.1:8081/menu.csv -o menu-handover.csv
diff -u로 수신한 파일과 승인 내역을 비교하세요. -u 옵션은 차이가 있을 때 주변 줄을 함께 보여 줍니다.
diff -u approved/menu.csv menu-handover.csv
출력이 없으면 파일이 일치한다는 뜻입니다. 차이가 있다면 유용한 증거가 됩니다. 메뉴 소스와 실행 중인 롤아웃으로 돌아가 원인을 수정하고, 다운로드와 비교를 반복하세요. 잘못된 웹사이트를 감추려고 수신한 CSV를 편집하지 마세요.
이제 사용 가능한 메뉴, 실제 직원용 다운로드, 실행 중인 구성을 재현하는 릴리스 디렉터리가 준비되었습니다. 이 환경의 복구 자료로 versions와 이전 ConfigMap을 온전히 보존하세요. 다음 수업에서는 독립된 환경을 별도로 준비합니다.
요약
완전한 메뉴 릴리스를 준비하고, 콘텐츠에 따라 이름이 지정되는 ConfigMap을 생성한 뒤, 두 애플리케이션 복제본에 대한 Deployment 롤아웃을 확인했습니다. 실제 페이지와 다운로드를 확인하고, 참조 카페와 이전 구성을 보존했으며, 실제 직원용 CSV를 전달했습니다.
다음 실습은 별도의 환경에서 시작합니다. 같은 개념을 활용하여 애플리케이션은 정상적으로 작동하지만 가격이 잘못된 메뉴를 복구합니다.



