소개
Meadow Supply에는 작은 카탈로그와 작동하는 장바구니 견적 기능이 있습니다. 공개 페이지는 Shop API에 재고 상태를 요청합니다. API는 Application Programming Interface의 약자로, 여기서는 고객 페이지와 내부 재고 서비스 사이에 있는 애플리케이션의 요청 인터페이스입니다. 이 API가 페이지를 위해 재고를 읽습니다. 현재는 고객 프로세스와 별도의 방문자도 재고를 직접 읽을 수 있으며, 공개 카탈로그에 필요하지 않은 선반 세부 정보까지 볼 수 있습니다.
정상적인 고객 이용 흐름을 유지하면서 재고 연결을 승인된 네임스페이스의 승인된 API 역할로 제한하세요. 재사용 가능한 결과물은 저장된 NetworkPolicy와 이에 일치하는 실제 경계입니다. 이를 뒷받침하는 것은 녹색 다이어그램이 아니라 실제 요청입니다.
기본 터미널 경로, 간단한 YAML, 네임스페이스, Pod, Deployment, Service, 레이블을 이미 알고 있어야 합니다. 이 실습에서는 정책 필드, 제공된 진단 명령, 요청 결과를 사용 전에 설명합니다. Calico를 사용하는 실제 단일 노드 Kubernetes 클러스터, 애플리케이션, 합성 데이터가 준비되어 있습니다. 클러스터 설치, 이미지 빌드, 애플리케이션 프로그래밍은 필요하지 않습니다. 시간은 읽기와 일반적인 실수에 필요한 시간을 포함한 저자의 예상치입니다. 견적은 교육용이며 주문, 예약, 결제는 이루어지지 않습니다.
재고 접근을 승인된 경로로 제한하기
이 단계에서는 Shop API가 재고에 접근하도록 허용하면서 고객과 방문자 프로세스가 API를 우회하지 못하도록 합니다.
Shop 탭에서 시작하세요. Meadow Supply에는 Good things for everyday와 제품 세 개가 표시되어야 합니다. Glass water bottle을 열어 $18.00 가격과 Available · 6 in stock을 확인한 다음 Try a basket quote를 사용하며, Quantity는 1로 설정하세요. 결과에는 Ready for collection, $18.00, 그리고 아무것도 예약, 주문, 결제되지 않았다는 명시적인 안내가 있어야 합니다. Back to product를 사용한 뒤 Back to collection으로 돌아오세요.
실제 요청 경로는 다음과 같습니다.
Customer page → Shop API → Stock service
고객 페이지는 자체 Pod에서 실행됩니다. 사이트를 열어도 브라우저가 클러스터 Pod가 되는 것은 아닙니다. 재고로 향하는 요청은 준비된 애플리케이션 프로세스에서 나옵니다. API는 새 네트워크 연결로 재고를 읽고 승인된 카탈로그 가격과 결합합니다. 정적 재고 대체 데이터는 없습니다. 별도의 Reference 탭에는 Meadow Dispatch의 픽업 메모가 표시됩니다. 이를 열어 P-104와 P-108을 읽은 다음 Workspace로 전환하세요. 이 별도 서비스는 계속 작동해야 합니다.
터미널은 /home/labex/project/stock-policy에서 시작합니다. pwd는 현재 디렉터리를 출력하고, ls는 그 안의 항목을 나열합니다. 이곳으로 돌아와야 한다면 절대 경로 cd 명령을 사용하세요.
pwd
ls
cd /home/labex/project/stock-policy
scope.json, starter, tools가 있어야 합니다. cat은 준비된 작업 범위 파일을 출력합니다. 이 파일은 이름이 있는 값과 목록으로 이루어진 텍스트 형식인 JSON(JavaScript Object Notation)을 사용합니다. 가상의 토폴로지 상태가 아니라 실제 리소스 이름과 요청 대상을 나열합니다.
cat scope.json
--context=labex-v135는 준비된 실제 클러스터를 선택합니다. --show-labels는 객체 레이블을 표시합니다. 네임스페이스는 객체를 묶지만 그 자체로 네트워크 연결을 차단하지는 않습니다. 네임스페이스 식별 정보를 읽으세요.
kubectl --context=labex-v135 get namespaces meadow-shop meadow-stock meadow-visitors --show-labels
각 네임스페이스에는 이름과 같은 값의 기본 제공 kubernetes.io/metadata.name 레이블이 있습니다. -n은 네임스페이스를 선택합니다. Pod와 해당 레이블을 읽으세요.
kubectl --context=labex-v135 -n meadow-shop get pods --show-labels
kubectl --context=labex-v135 -n meadow-stock get pods --show-labels
kubectl --context=labex-v135 -n meadow-visitors get pods --show-labels
고객 프로세스에는 role=customer, API에는 role=shop-api, 재고에는 role=inventory가 있습니다. 별도 배송 서비스에는 role=dispatch가 있습니다. 방문자는 meadow-visitors에 있지만 실제 API와 같은 role=shop-api 레이블을 의도적으로 갖고 있습니다. 따라서 역할 레이블만으로는 승인된 네임스페이스를 식별할 수 없습니다.
Service를 읽으세요. Service는 준비된 Pod를 선택하고 안정적인 주소를 제공합니다. 포트는 애플리케이션의 수신 엔드포인트를 식별합니다. TCP(Transmission Control Protocol)는 이러한 웹 요청에 사용되는 연결을 제공합니다. 재고 프로세스는 TCP 포트 8080에서 수신합니다.
kubectl --context=labex-v135 -n meadow-stock get services
제공된 ./tools/network-test는 kubectl exec를 사용하여 기존 애플리케이션의 실행 신원으로 실제 요청을 실행합니다. 앞의 ./는 도구가 현재 디렉터리에 있다는 뜻입니다. 첫 번째 인수는 customer, api, visitor, stock, reference 중 하나를 선택합니다. 다음 인수는 http, dns, dns-tcp 중 하나를 선택하며, 마지막 인수는 대상입니다. 이 도구는 정책을 변경하거나 애플리케이션을 복구하지 않습니다. http 요청은 이 웹/API 엔드포인트의 요청-응답 프로토콜인 HTTP(Hypertext Transfer Protocol)를 사용합니다. 전체 이름 stock.meadow-stock.svc.cluster.local은 Service 이름을 주소로 해석하는 클러스터 DNS(Domain Name System)를 통해 해당 네임스페이스의 재고 Service를 식별합니다.
먼저 현재 연결과 내용을 확인하세요. 격리 전에는 두 요청이 모두 성공해야 합니다.
./tools/network-test api http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
./tools/network-test customer http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
HTTP_REPLY 200 뒤에 동일한 재고 데이터가 나와야 합니다. bottle은 선반 M-03에 6개, notebook은 M-08에 4개, bag은 M-12에 0개입니다. 고객은 이런 내부 직접 읽기 대신 API를 통해 공개 재고 상태를 받아야 합니다. 이 기준 확인은 제한하기 전에 대상이 살아 있음을 입증합니다.
NetworkPolicy는 Pod를 선택하고 특정 트래픽 방향의 연결을 허용합니다. Ingress는 선택된 Pod로 들어오는 연결을 뜻합니다. 인그레스 정책이 재고를 선택하면 Kubernetes에 문서화된 노드/자기 자신 트래픽 예외를 제외하고 허용된 수신 경로만 사용할 수 있습니다. 이는 Pod 네트워크 제어이며 사용자 인증이나 HTTP 권한 부여가 아닙니다.
릴리스 디렉터리를 만드세요. mkdir -p는 필요하면 디렉터리를 생성하고 기존 디렉터리는 유지합니다. 다음 cat 명령은 자신의 릴리스 파일에 전체 정책을 씁니다. >는 출력을 해당 파일로 리디렉션하고, 따옴표로 감싼 YAML 표시는 한 줄에 단독으로 놓인 마지막 표시까지 텍스트를 문자 그대로 유지합니다. 반복 실행하면 이 편집 가능한 정책 파일만 덮어씁니다.
mkdir -p release
cat > release/stock-ingress.yaml <<'YAML'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: stock-ingress
namespace: meadow-stock
spec:
podSelector:
matchLabels:
role: inventory
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: meadow-shop
podSelector:
matchLabels:
role: shop-api
ports:
- protocol: TCP
port: 8080
YAML
적용하기 전에 저장된 파일을 읽으세요.
cat release/stock-ingress.yaml
바깥쪽 podSelector는 재고만 선택하므로 배송 서비스는 이 정책 밖에 남습니다. 하나의 from 항목 안에서 namespaceSelector와 podSelector가 모두 일치해야 합니다. 출발지는 meadow-shop에 있어야 하고, role=shop-api를 가져야 합니다. 두 셀렉터는 같은 목록 항목 아래에 정렬됩니다. 안쪽 podSelector 앞에 대시를 하나 더 넣으면 두 번째 대안이 만들어져 OR를 뜻하게 되고, 승인된 네임스페이스의 다른 Pod도 허용하게 됩니다. 포트는 재고 Pod가 수신하는 TCP 포트입니다. 이 규칙은 API 이그레스를 제한하지 않습니다.
apply -f는 저장된 매니페스트를 읽고 해당 이름의 정책을 생성하거나 업데이트합니다. 애플리케이션을 재시작하지는 않습니다.
kubectl --context=labex-v135 apply -f release/stock-ingress.yaml
describe는 Kubernetes가 규칙을 어떻게 해석했는지 보여 줍니다.
kubectl --context=labex-v135 -n meadow-stock describe networkpolicy stock-ingress
선택된 재고 역할, 출발지 네임스페이스와 API 역할, TCP 포트를 읽으세요. 정책 적용이 수렴하는 데 몇 초가 걸릴 수 있습니다. 먼저 원래의 허용된 요청이 여전히 전체 데이터를 반환하는지 확인하세요.
./tools/network-test api http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
이제 출발지가 거부되어야 하는 두 가지 서로 다른 이유를 테스트하세요.
./tools/network-test customer http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
./tools/network-test visitor http http://stock.meadow-stock.svc.cluster.local:8080/stock.json
마지막 두 명령에서는 NETWORK_TIMEOUT과 0이 아닌 명령 종료 코드가 예상됩니다. Customer는 승인된 네임스페이스에 있지만 역할이 잘못되었고, Visitor는 역할이 일치하지만 네임스페이스가 잘못되었습니다. 연결 거부, DNS 오류, 중지된 대상은 격리의 증거가 아닙니다. 같은 대상에 대한 API의 성공한 요청이 정상 대조군입니다. 정책 적용 직후 반복한 요청이 아직 성공한다면 몇 초 기다린 뒤 반복하세요. 실제 거부 경로가 시간 초과될 때까지 격리되었다고 판단하지 마세요.
경로를 잘못 입력했다면 앞서 배운 pwd, ls, 절대 경로 cd를 사용한 뒤 실패한 작업을 반복하세요. YAML을 파싱할 수 없다면 릴리스 파일을 읽고 들여쓰기와 대시 위치를 전체 예제와 비교한 다음, 해당 편집 가능 파일을 다시 작성하여 적용하세요. API도 차단되었다면 describe와 이미 표시한 레이블 및 포트를 조사하고, 저장된 정책을 수정하여 다시 적용하세요. 원래 네임스페이스, 레이블, 워크로드, Pod, Service, 애플리케이션, 소스 파일, 진단 도구를 유지하세요. 거부 결과를 만들어 내려고 재고를 중지하거나, 레이블을 바꾸거나, Pod IP/CIDR 규칙을 사용하거나, 호스트 네트워킹을 바꾸거나, VM을 초기화하지 마세요.
전체 고객 이용 흐름 확인하기
이 단계에서는 격리 후 전체 고객 경험을 검증하고 별도 배송 서비스를 계속 사용할 수 있게 유지합니다.
Workspace의 /home/labex/project/stock-policy에서 시작하세요. Customer의 직접 재고 요청은 의도적으로 차단되지만, Customer는 여전히 Shop API에 접근할 수 있어야 합니다. 원래 경로로 카탈로그를 요청하세요.
./tools/network-test customer http http://api.meadow-shop.svc.cluster.local:8080/catalogue.json
HTTP_REPLY 200과 승인된 제품 세 개가 원래 가격 및 수량으로 나와야 합니다. Glass water bottle은 1800센트/6개, Everyday notebook은 1400/4, Canvas market bag은 2400/0입니다. API는 응답한 원래 재고 Pod도 보고하지만 공개 페이지에는 이 인프라 세부 정보가 노출되지 않습니다. 성공한 API 경로와 실패한 직접 경로는 양립합니다. API가 자체적으로 허용된 재고 연결을 만들기 때문입니다.
Shop으로 전환하여 새로고침하세요. Glass water bottle을 열고 Quantity를 2로 설정한 뒤 Try a basket quote를 선택하세요. Ready for collection, Quantity 2, Total $36.00, Units available 6이 예상됩니다. 교육 안내에서 재고가 예약되지 않음을 읽으세요. Back to product와 Back to collection을 사용하세요.
Canvas market bag을 여세요. 이 제품은 Back soon으로 표시됩니다. 이어서 Quantity 1의 견적을 시도하세요. Not enough stock, Total $24.00, Units available 0이 예상됩니다. 이는 유효한 비즈니스 응답이며 네트워크 실패가 아닙니다. 모든 견적을 성공시키려고 재고를 변경하지 마세요. Back to product, Back to collection을 차례로 사용하세요. Our approach를 열고 교육용 견적 설명을 읽은 뒤 Back to collection을 사용하세요.
완성된 카탈로그에는 원래 제품 세 개와 실시간 재고 상태가 있습니다. 제목, 가격, 재고 상태를 이 실행 예제와 비교하세요.

Reference로 전환하여 새로고침하세요. P-104 · Ready와 P-108 · Packed가 계속 보여야 합니다. Download notes를 선택하고 실제 notes.json 다운로드를 여세요. 재고 데이터가 아니라 변경되지 않은 배송 기록 두 개가 들어 있습니다. 브라우저 다운로드와 터미널 작업 공간은 서로 다른 위치입니다. 이 작업에서는 해당 파일을 작업 공간에 복사할 필요가 없습니다.
Workspace로 돌아와 Customer에서 같은 별도 Service를 읽으세요.
./tools/network-test customer http http://dispatch.meadow-stock.svc.cluster.local:8080/notes.json
HTTP_REPLY 200과 원래 메모 두 개가 예상됩니다. 정책은 재고 네임스페이스 전체가 아니라 inventory Pod를 선택했습니다. 배송 프로세스, 데이터, 원래 Service를 유지하세요. 이를 꺼 버리면 지나치게 넓은 규칙을 감추게 됩니다.
전달할 결과물은 release/stock-ingress.yaml과 이에 일치하는 실제 경계입니다. 전체 카탈로그와 두 견적 결과가 원래 애플리케이션을 통해 계속 작동해야 하며, 두 직접 재고 우회는 계속 거부되어야 합니다. 준비된 모든 소스 파일, 애플리케이션 객체, 원래 Pod를 유지하세요. 페이지에 Live availability unavailable이 표시되면 배운 레이블, 정책, 요청 검사로 돌아가 릴리스 정책만 수정하고 다시 적용하세요. 정적 대체 페이지는 복구가 아닙니다. 이 테스트는 준비된 클러스터 하나에서 이루어지는 유한한 실제 TCP 요청이며, 프로덕션 보안이나 중단 없는 가용성을 보장하지 않습니다.
요약
잘못된 역할의 고객과 다른 네임스페이스에서 역할이 일치하는 방문자의 직접 재고 읽기를 모두 방지하면서 실제 고객 → API → 재고 흐름을 유지했습니다. 저장된 인그레스 정책은 네임스페이스와 역할의 AND 관계를 표현하며, 실제 카탈로그, 교육용 견적, 별도 배송 서비스는 계속 작동합니다.
NetworkPolicy는 고객 인증이 아니라 Pod 네트워크 경로를 제어합니다. 시간 초과는 대상과 승인된 연결이 계속 작동할 때만 유용한 증거입니다. 다음 독립 실습에서는 반대 방향인 API 이그레스와 DNS, 다른 정책이 추가하는 권한을 살펴봅니다.



