실습 목표
1. 매니페스트 정적 분석 및 보안 취약점 사전 차단
- Kube-linter 연동: PyGoat 배포 YAML 파일 내 Privileged, Root 실행 권한 등 고위험 설정 자동 탐지
- Hardening 설정: securityContext를 통한 컨테이너 격리 및 권한 최소화(Least Privilege) 구현
2. Admission Controller 기반의 정책 강제화 (PaC)
- Kyverno 정책 적용: 클러스터 배포 시점에 실시간으로 보안 정책을 검증하고, 규격 미달 리소스의 생성 원천 차단
- 가드레일 구축: latest 이미지 태그 금지 및 필수 보안 라벨링(Labeling) 자동화
3. 제로 트러스트 기반 동적 네트워크 격리
- Network Policy 설계: Default Deny 정책을 통한 마이크로서비스 간 동적 방화벽 구성
- 통신 최소화: Web(Flask)과 DB(PostgreSQL) 간의 필수 트래픽만 허용하는 화이트리스트(Allow-list) 체계 수립
4. GitOps 기반 보안 운영 자동화
- GitHub Actions 통합: 배포 전 단계에서 K8s 설정 오류를 검증하는 자동화 파이프라인 완성
- Compliance as Code: 보안 규정을 코드로 관리하여 인적 실수에 의한 보안 사고 방지 및 가시성 확보
실습
0. 전체 흐름도
step 1 : 인프라 준비
먼저 실제 서비스가 구동될 환경을 조성한다. 로컬 PC(WSL2)에서 Kind(Kubernetes IN Docker)를 실행하여 가상의 쿠버네티스 서버를 구축하고 이를 컨트롤하기 위한 kubectl를 설정한다.
step 2: 코드 및 설계도 개발
Pygoat 앱이 쿠버네티스 서버에서 어떤 모양으로 존재할지를 정의한 deployment.yaml(매니페스트) 파일을 k8s라는 디렉토리 내부에 작성한다. 이떄, 설계도 내부에 securityContext를 설정하여 컨테이너가 루트 권한을 갖지 못하게 하거나 파일 시스템을 수정할수 없게 만드는 최소 권한 원칙을 반영하는 등 Hardening 작업이 필요하다.
step 4: GitOps 검증
파이프라인을 따라 kubectl apply가 실행되면 미리 설치해둔 Kyverno가 Admission Control을 수행한다. 이는 서버 내부로 들어오는 모든 요청을 실시간으로 가로채서 정책 위반 여부를 확인하는 가드레일이다. 보안상 위험한 latest 태그 이미지를 사용하거나 필수적인 보안 라벨이 누락된 경우, 서버는 배포 명령 자체를 거부하여 클러스터의 무결성을 유지한다.
step 4: 파이프라인 가동
Github actions가 작동하며 Docker Hub에 pygoat 이미지를 업로드하고 kube-linter를 통한 정적 분석(Static Analysis)이 수행된다. 만약 개발자가 설계도에 관리자 권한을 실수로 넣었다면 파이프라인은 이를 탐지하여 빌드를 즉시 중단, 배포를 사전에 차단하는 Shift-left를 실현한다. 이후 빌드된 이미지 태그로 confing 저장소의 이미지 태그를 변경하면 ArgoCD가 알아차려서 Kyverno 정책 설정에 맞으면 배포
step 5: 운영 및 격리
서버는 Docker Hub에서 이미지를 내려받아 컨테이너를 실행한다. 이때 Network policy가 작동하여 Zero Trust 기반의 동적 격리를 실행한다. 모든 통신을 차단한 상태에서 특정 포트만 열어주는 화이트 리스트 방식을 적용한다.
1. 인프라 준비
쿠버네티스(Kubernetes, K8s)란 컨테이너화된 애플리케이션의 배포, 확장, 관리를 자동화하는 오케스트레이션 플랫폼으로 여러 대의 서버를 하나의 거대한 자원처럼 관리하며 컨테이너의 생명주기(생성,삭제,복구)를 제어한다.
Kind (kubernetes in Docker)는 로컬환경에서 Docker 컨테이너를 노드(서버)로 활용해 K8s 클러스터를 띄워주는 도구로 실제 물리 서버 없이도 내 Pc의 Docker 위에서 완벽한 클러스터 환경을 재현 가능하다.
1-1 ) kind 설치 및 클러스터 생성
# Kind 바이너리 다운로드
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-amd64
# 실행 권한 부여 및 시스템 경로로 이동
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
# 설치 확인
kind version
Docker Desktop 실행 후 클러스터 생성
# 'pygoat-cluster'라는 이름으로 서버 생성
kind create cluster --name pygoat-cluster
1-2) kubectl 설치 및 설정
# 최신 안정화 버전 다운로드
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
# 실행 권한 부여 및 이동
chmod +x kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
# 설치 확인
kubectl version --client
쿠버네티스 클러스터에 kubectl 연결
# 접속 정보(Kubeconfig)를 자동으로 업데이트
kind export kubeconfig --name pygoat-cluster
# 연결 확인 (Ready 상태가 나오면 성공)
kubectl get nodes
1-3) kyverno 설치
# Kyverno 공식 설치 매니페스트 실행
kubectl create -f https://github.com/kyverno/kyverno/releases/download/v1.11.1/install.yaml
# 설치 확인 (모든 Pod가 Running이 될 때까지 잠시 대기)
kubectl get pods -n kyverno
2. Kube-linter 기반의 Kubernetes manifest 정적 분석 및 container 하드닝
2-1) Manifest 파일 생성
먼저 쿠버네티스내에서 pygoat앱이 어떤식으로 실행될지를 설계하는 설계도파일을 먼저 작성한다.
먼저 프로젝트 폴더 내부에 manifest 파일을 관리할 전용 디렉토리(k8s) 생성후 취약한 설계도를 작성한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: pygoat-deployment
labels:
app: pygoat
spec:
replicas: 1
selector:
matchLabels:
app: pygoat
template:
metadata:
labels:
app: pygoat
spec:
containers:
- name: pygoat
# [결함 1] 불분명한 이미지 태그 사용 (latest)
image: pygoat/pygoat:latest
ports:
- containerPort: 8000
# [결함 2] 보안 설정 미비 (Hardening 부재)
securityContext:
privileged: true # [결함 3] 관리자 권한 부여 (매우 위험!)
runAsUser: 0 # Root 계정으로 실행
2-2) kube-linter 정적 분석
kube-linter 설치
# 1. 최신 v0.7.1 버전 바이너리 직접 다운로드
curl -L "https://github.com/stackrox/kube-linter/releases/download/v0.7.1/kube-linter-linux" -o kube-linter
# 실행 권한 부여
chmod +x kube-linter
# 시스템 경로로 이동
sudo mv kube-linter /usr/local/bin/
# 정상 작동 확인
kube-linter version
설계도 스캔
cd ~/pygoat/k8s
kube-linter lint deployment.yaml
2-3) 분석 결과 및 하드닝
주요 보안 결함은 다음과 같다.
- latest-tag: 고정되지 않은 latest 이미지 태그 사용으로 인한 무결성 위협
- no-read-only-root-fs: 컨테이너 내부 파일 시스템 쓰기 허용으로 인한 악성코드 잔존 위험
- privilege-escalation / privileged-container: 호스트 장치 접근 및 권한 상승 허용 (가장 치명적)
- run-as-non-root: Root(관리자) 계정 실행으로 인한 컨테이너 탈출 및 탈취 위험
- unset-cpu/memory-requirements: 자원 제한 미설정으로 인한 DoS(서비스 거부) 취약성
apiVersion: apps/v1
kind: Deployment
metadata:
name: pygoat-deployment
labels:
app: pygoat
spec:
replicas: 1
selector:
matchLabels:
app: pygoat
template:
metadata:
labels:
app: pygoat
spec:
containers:
- name: pygoat
# [수정] latest 대신 구체적인 태그 사용 (연습용으로 v1 지정)
image: pygoat/pygoat:v1
ports:
- containerPort: 8000
resources:
# [추가] 자원 사용량 제한 (DoS 방어)
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
securityContext:
# [수정] 보안 강화 설정
privileged: false
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1000 # Root(0)가 아닌 일반 사용자 ID 지정
readOnlyRootFilesystem: true # 파일 시스템 읽기 전용 설정
3. 저장소 분리 및 Gitops 아키텍처 설계
GitOps는 Git 저장소를 인프라 설계도의 유일한 원천으로 삼는 운영 방식이다. 운영자가 서버에 직접 접속해 명령을 내리는 대신, 원하는 시스템의 상태를 Git에 YAML 파일로 정의해두면 자동화 도구가 이를 실제 환경과 일치시킨다.
3-1) 설계 배경: 왜 저장소를 분리해야 하는가?
기존처럼 애플리케이션 코드와 쿠버네티스 설정 파일(YAML)이 하나의 저장소에 섞여있는 경우, 단순한 인프라 설정 변경만으로도 전체 빌드 파이프라인을 실행하는 비효율이 발생한다. 개발 단계의 코드와 운영 단계의 인프라를 독립적으로 관리하여 보안성과 운영 효율성을 동시에 확보하기 위해 아래 2가지 저장소로 분리한다.
- pygoat(app) : 소스 코드 담당
- pygoat-config (Infra) : 배포 형상 관리
3-2) 저장소 분리 및 환경 구축 실무
먼저 GitHub에 인프라 전용 저장소인 pygoat-config를 생성한다.
이후 WSL 환경에서도 동일한 명칭의 디렉토리를 만들어 git init -> remote add로 GitHub 원격 저장소와 연결한다.
기존 pygoat 저장소에 있던 k8s 매니페스트 파일들을 새로 만든 pygoat-config/manifests 디렉토리로 이동시킨다.
3-3) 자격 증명 체계: PAT와 Vault의 연동
저장소가 분리됨에 따라, pygoat 저장소의 파이프라인(GitHub Actions)을 따라 빌드 완료가 되면 pygoat-config 저장소에 접속하여 이미지 태그 정보를 수정해야 하는 필요성이 생긴다. 이를 위해 pygoat-config 저장소에만 접근 가능한 전용 통행증인 PAT(Personal Access Token)를 발급받는다.
이 민감한 토큰은 코드에 직접 노출되지 않도록, 기존에 구축한 Vault의 KV 엔진 내에 config_repo_pat이라는 이름으로 안전하게 저장한다.
3-4) GitOps 파이프라인의 완성 (ArgoCD & Kyverno)
준비된 인프라 저장소를 실시간으로 감시할 ArgoCD를 클러스터 내부에 설치한다. ArgoCD는 pygoat-config 저장소의 커밋을 감지하여 실제 클러스터 상태와 동기화하는 'GitOps 엔진' 역할을 수행한다.
배포가 이루어지는 마지막 관문에는 Kyverno를 배치하여 ArgoCD가 배포를 요청할 때, 사전에 정의된 보안 정책(예: Root 권한 실행 금지 등)과 대조하여 부적절한 설정이 포함된 경우 배포를 즉시 차단합니다. 이를 통해 '코드로서의 보안(Compliance as Code)'을 완성하게 된다.
ArgoCD 설치
ArgoCD는 쿠버네티스 전용 CD 도구이다. pygoat-config 저장소를 실시간으로 쳐다보다가 파일이 변경되면 즉시 클러스터에 반영해주는 역할을 한다. kubectl get pod -n argocd 에서 모두 running 상태로 변하면 완료
# 1. argocd 전용 네임스페이스 생성
kubectl create namespace argocd
# 2. 공식 설치 파일 적용 (안정화 버전)
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
ArgoCD 초기 설정
1. 통로 열기 (Port-Forward)
ArgoCD 서버는 클러스터 내부용이라 브라우저에서 바로 접속할 수 없습니다. 따라서 내 PC의 특정 포트(8080)를 클러스터 내부의 ArgoCD 서비스(443)로 직접 연결해 주는 터널링 작업이 필요합니다. (계속 열어둬야함)
kubectl port-forward svc/argocd-server -n argocd 8080:443
2. 관리자 비밀번호 확인
ArgoCD 설치 시 보안을 위해 복잡한 임의의 문자열이 초기 비밀번호로 자동 생성되어 시크릿(Secret)에 저장됩니다. 이를 읽어와서 사람이 볼 수 있게 디코딩하는 과정입니다.
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo
3. UI 접속 및 로그인
터널이 열리고 비밀번호를 확인했다면 이제 브라우저를 통해 관리자 화면에 접근합니다.
- 주소: https://localhost:8080
- 계정: admin
- 비밀번호: 위에서 확인한 문자열 입력
4. 저장소 등록 (UI 조작): 로그인 성공 후 왼쪽 메뉴에서 톱니바퀴 아이콘(Settings)을 클릭합니다.
- 메뉴 진입: Repositories 선택 후 상단의 CONNECT REPO 클릭
- 정보 입력:
- Repository URL: pygoat-config GitHub 주소
- Username: GitHub 아이디
- Password: GitHub에서 발급받은 PAT 입력
- 확인: 리스트에 등록된 저장소의 CONNECTION STATUS가 Successful로 바뀌는지 확인
5. 애플리케이션 생성 (배포 설정): 저장소 연결이 끝나면 왼쪽 상단 Applications 아이콘을 누르고 + NEW APP을 클릭합니다.
- General: Application Name 설정 (예: pygoat), Project는 default
- Sync Policy: Automatic 체크 (Git 수정 시 자동 배포를 위해)
- Source: 아까 등록한 pygoat-config 저장소 선택 및 매니페스트 경로 지정
- Destination: Cluster URL은 [https://kubernetes.default.svc](https://kubernetes.default.svc) 선택, Namespace는 배포될 방 이름 지정
kyverno 정책 설정
우선 가장 기본적이면서 중요한 "Root 계정 실행 금지" 정책을 클러스터에 배포, 아래 YAML 내용을 disallow-root.yaml로 저장하고 적용
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-root-user
spec:
validationFailureAction: Enforce # 위반 시 즉시 차단 (Audit은 기록만 남김)
background: true
rules:
- name: check-run-as-non-root
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Root 권한 실행은 금지됩니다. runAsNonRoot: true 설정을 추가하세요."
pattern:
spec:
containers:
- securityContext:
runAsNonRoot: true
1. Kyverno의 작동 아키텍처
Kyverno는 쿠버네티스의 Admission Controller 메커니즘을 활용하여, 모든 리소스 생성/수정 요청을 중간에서 가로채 검사합니다.
- 연결 고리 (apiVersion): kyverno.io/v1이라는 선언을 통해 쿠버네티스 API 서버가 해당 리소스를 Kyverno 엔진으로 전달하도록 경로를 지정함.
- 정책 배포 방식: 보안 요구사항이 생길 때마다 YAML 형태의 ClusterPolicy를 작성하여 kubectl apply로 클러스터에 상시 등록함.
- 실시간 개입: ArgoCD가 배포를 시도할 때, Kyverno가 메모리에 등록된 정책과 대조하여 승인(Allow) 또는 거부(Deny)를 결정함.
2. 핵심 정책 구성 요소 (YAML 구조)
정책은 크게 매칭(Match)과 검증(Validate) 단계로 나뉩니다.
- validationFailureAction:
- Enforce: 규정 위반 시 즉시 차단 (보안 가드레일의 핵심).
- Audit: 차단하지 않고 기록만 남김 (정책 적용 전 테스트 용도).
- rules:
- match: 어떤 리소스(예: Pod, Deployment)를 검사할지 정의함.
- validate: 준수해야 할 구체적인 보안 설정(패턴)을 명시함.
워크로드 격리 및 배포 타겟 최적화
1. 1단계: 클러스터에 네임스페이스 생성 (터미널)
가장 먼저 쿠버네티스 클러스터 안에 실제 공간을 마련해야 한다.
# pygoat라는 이름의 네임스페이스 생성
kubectl create namespace pygoat
2. 2단계: 매니페스트 파일에 연결 설정 (YAML)
생성한 네임스페이스와 deployment.yml을 연결하기 위해 metadata 섹션에 이름을 명시한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: pygoat-deployment
namespace: pygoat # [연결 포인트] 1단계에서 만든 네임스페이스 이름과 일치해야 함
labels:
app: pygoat
# ... 이하 생략
3. 3단계: ArgoCD Application 설정 확인
이미 ArgoCD에 앱을 등록하셨다면, ArgoCD 설정에서도 목적지 네임스페이스가 일치하는지 확인해야 한다.
- Destination Namespace: pygoat로 설정되어 있어야 한다.
kubectl patch app pygoat-config -n argocd --type merge -p '{"spec":{"destination":{"namespace":"pygoat"}}}'
4. 파이프라인 가동
기존 파이프라인에 pygoat-config에 접근해서 deployment.yml 내의 이미지태그를 변경하는 파이프라인 추가.
이떄 permission이 content:write를 허용해주고, vault에도 config_repo_pat 환경변수 추가해주기.
# ---------------------------------------------------------
# 4. GitOps Bridge (ArgoCD Config Update)
# ---------------------------------------------------------
- name: Update GitOps Manifest (pygoat-config)
run: |
# 1. 배포 설정 저장소 클론 (Vault에서 가져온 GH_TOKEN 활용)
git clone https://x-access-token:${{ env.CONFIG_REPO_PAT }}@github.com/a4527/pygoat-config.git
cd pygoat-config/manifests
# 2. deployment.yml 내의 이미지 태그를 현재 빌드된 IMAGE_TAG로 치환
# env.IMAGE_TAG 변수를 사용하여 일관성 유지
sed -i "s|image:${{ env.DOCKERHUB_USERNAME }}/pygoat:.*|image: ${{ env.DOCKERHUB_USERNAME }}/pygoat:${{ env.IMAGE_TAG }}|g" deployment.yml
# 3. 변경 사항 커밋 및 푸시
git config --global user.email "devsecops-bot@github.com"
git config --global user.name "DevSecOps Automation Bot"
git add deployment.yml
git commit -m "chore: update pygoat image tag to ${{ env.IMAGE_TAG }} [skip ci]"
git push origin main
1. DevSecOps 파이프라인 최종 가드레일 흐름
- 이미지 빌드 및 푸시: GitHub Actions가 최신 코드를 기반으로 Docker 이미지를 빌드하고, 보안 스캔(Trivy/Snyk) 완료 후 레지스트리에 푸시함.
- GitOps 브릿지 작동: 파이프라인이 pygoat-config 저장소의 deployment.yml 내 이미지 태그를 최신 버전으로 자동 업데이트(sed 명령어 및 push).
- ArgoCD 감지 및 동기화: ArgoCD가 pygoat-config의 변경 사항을 감지하고, 클러스터의 현재 상태(Desired State)를 갱신하기 위해 컨트롤 플레인(API Server)에 배포 요청을 보냄.
- Kyverno 정책 엔진 개입 (Final Gate): 배포 명령이 실제 노드에 전달되기 전, Admission Controller 단계에서 Kyverno가 개입하여 정책 준수 여부(예: Root 실행 금지, 특정 레지스트리만 허용 등)를 실시간 검증함.
- 최종 배포 및 런타임 보호: 모든 보안 정책을 통과한 컨테이너만 클러스터에 배포되며, 이후 Falco 등을 통한 실시간 위협 탐지 단계로 진입함.
argocd쪽 pod 생성에서 계속 실패해서
kubectl logs -n pygoat -l app=pygoat --previous 로 로그 확인하면서 계~~~~~~속 수정
최종 deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: pygoat-deployment
namespace: pygoat
labels:
app: pygoat
spec:
replicas: 1
selector:
matchLabels:
app: pygoat
template:
metadata:
labels:
app: pygoat
spec:
# [보안] Pod 수준의 보안 컨텍스트 설정
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
containers:
- name: pygoat
# [수정] Docker Hub ID를 사용하세요.
# 나중에 파이프라인이 이 태그를 자동으로 업데이트할 것입니다.
image: taemin010/pygoat:359ca0a1223602d8490ffc0738d4eb3e7dca5137
ports:
- containerPort: 8000
resources:
# [보안] 리소스 제한을 통한 DoS 방어
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
securityContext:
# [보안] 컨테이너 실행 권한 최소화 (Kyverno 통과 조건)
privileged: false
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1000
# [보안] 컨테이너 내 파일 변조 방지
readOnlyRootFilesystem: true
volumeMounts:
- name: tmp-volume
mountPath: /tmp
# [수정] 정적 파일 저장을 위한 경로 마운트
- name: static-volume
mountPath: /app/staticfiles
# [수정] /app 전체가 아닌 로그 파일이 생성될 위치만 정밀 마운트
- name: log-volume
mountPath: /app/logs
# [추가] DB 파일 저장을 위한 볼륨 마운트
- name: db-volume
mountPath: /app/db
volumes:
# [설정] readOnlyRootFilesystem 사용 시 쓰기가 필요한 /tmp를 위해 emptyDir 할당
- name: tmp-volume
emptyDir: {}
# [수정] staticfiles 경로를 위한 메모리 기반 임시 저장소 할당
- name: static-volume
emptyDir: {}
# [추가] 로그 쓰기를 위한 임시 디렉토리 할당
- name: log-volume
emptyDir: {}
# [추가] DB 전용 임시 저장소
- name: db-volume
emptyDir: {}
5. Network Policy
1. 네트워크 정책(Network Policy)의 핵심 개념
쿠버네티스의 네트워크 정책은 "포드(Pod) 단위의 화이트리스트 방화벽"입니다.
- 기본 상태 (Non-Isolated): 정책이 없는 네임스페이스 내의 모든 포드는 서로 자유롭게 통신 가능합니다.
- 격리 상태 (Isolated): 특정 포드에 네트워크 정책이 하나라도 적용되는 순간, 그 포드는 "명시적으로 허용하지 않은 모든 통신을 거부"하는 상태로 변합니다.
- 라벨 기반 제어: IP 주소가 아닌, app: pygoat와 같은 라벨(Label)을 기준으로 통신 허용 대상을 결정합니다.
2. 보안 실습 흐름 (Workflow)
제로 트러스트(Zero Trust) 환경을 구축하기 위해 보통 다음 4단계로 진행합니다.
1단계: Default Deny (모두 차단)
- 행동: pygoat 네임스페이스 내의 모든 인바운드/아웃바운드 트래픽을 막는 정책을 배포합니다.
- 결과: 외부 웹 접속, DNS 질의, DB 연결 등 모든 통신이 끊깁니다. (가장 안전하지만 서비스는 중단된 상태)
2단계: Ingress 허용 (입구 개방)
- 행동: 사용자가 웹 브라우저를 통해 PyGoat에 접속할 수 있도록 외부(Ingress Controller)에서 들어오는 특정 포트(8000) 트래픽만 허용합니다.
- 결과: 사용자가 다시 PyGoat 화면을 볼 수 있게 됩니다.
3단계: Egress 허용 (출구 개방)
- 행동: 앱이 정상 동작하기 위해 꼭 필요한 외부 통신을 허용합니다.
- DNS 허용: 도메인 주소(예: db-service)를 찾기 위해 kube-system 네임스페이스의 DNS 서버로 나가는 통신 허용.
- 결과: 앱 내부의 기능들이 정상적으로 작동하기 시작합니다.
4단계: 검증 (Validation)
- 행동: kubectl exec를 통해 포드 내부로 들어가서, 허용되지 않은 다른 네임스페이스나 외부 인터넷으로의 통신이 정말로 차단되는지 확인합니다.
3. 실습
1. default Deny
- Git 저장소 접속: 현재 ArgoCD가 바라보고 있는 GitHub 리포지토리로 이동합니다.
- 파일 생성: manifests/ 또는 기존 pygoat-deployment.yaml이 있는 디렉토리에 network-policy.yaml 파일을 새로 생성한 후 push
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: pygoat-network-policy
namespace: pygoat
spec:
podSelector:
matchLabels:
app: pygoat
policyTypes:
- Ingress
- Egress
# [Ingress] 외부(또는 인그레스)에서 PyGoat 8000 포트 접속 허용
ingress:
- from: [] # 모든 소스로부터 허용 (실습 편의상)
ports:
- protocol: TCP
port: 8000
# [Egress] 내부 도메인 해석(DNS)을 위한 통신만 허용
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
-
-
- 서비스 정상 동작 확인: 브라우저에서 PyGoat 웹 페이지가 잘 뜨는지 확인합니다. (Ingress 정책 검증)
- 비인가 통신 차단 확인 (가장 중요):
- Pod 내부로 접속합니다: kubectl exec -it <pygoat-pod-name> -n pygoat -- /bin/sh
- 외부 인터넷(예: google.com)으로 핑을 날려봅니다: ping 8.8.8.8 또는 curl google.com
- 결과: 통신이 나가지 않고 Timeout이 발생해야 합니다. (Egress 정책 검증 성공)
-
netwokr policy와 무관하게 pygoat 웹페이지도 안 뜨는데 아마 런타임 에러인것 같아서 4주차에서 해결하는걸로.