Ssoon
AWS EKS - Network Policies 본문
CloudNet@ 팀의 AWS EKS Workshop Study 2기 - 2주차
# EKS Workshop 참고
- 기본적으로 Kubernetes는 모든 포드가 제한 없이 자유롭게 서로 통신
- Kubernetes 네트워크 정책을 사용하면 포드, 네임스페이스 및 IP 블록(CIDR 범위) 간의 트래픽 흐름에 대한 규칙을 정의하고 적용
- 가상 방화벽 역할을 하며 포드 레이블, 네임스페이스, IP 주소 및 포트와 같은 다양한 기준에 따라 입력(수신) 및 출력(송출) 네트워크 트래픽 규칙을 지정하여 클러스터를 세분화하고 보안
- metadata
- 네트워크 정책의 이름과 네임스페이스를 지정할 수 있습니다.
- spec.podSelector
- 지정된 네트워크 정책이 적용될 네임스페이스 내의 레이블에 따라 특정 포드를 선택
- 빈 pod selector 또는 matchLabels 이 지정된 경우 정책이 네임스페이스 내의 모든 포드에 적용
- spec.policyTypes
- 정책을 선택한 포드에 대해 ingress traffic , egress traffic 또는 둘 다에 적용할지 여부를 지정
- 이 필드를 지정하지 않으면 기본 동작은 네트워크 정책에 egress 섹션이 없는 한 ingress traffic 에만 네트워크 정책을 적용 -> 이 경우 네트워크 정책은 ingress traffic 과 egress 트래픽 모두에 적용
- ingress
- 선택한 포드에 허용되는 포드(podSelector), 네임스페이스(namespaceSelector) 또는 CIDR 범위(ipBlock) 트래픽과 사용할 수 있는 포트 또는 포트 범위를 지정하는 입력 규칙을 구성
- 포트 또는 포트 범위가 지정되지 않은 경우 모든 포트를 통신에 사용
✅ 실습
- 각 구성 요소는 고유한 네임스페이스에 구현
- 현재 정의된 네트워크 정책은 없음
- 샘플 응용 프로그램의 모든 구성 요소는 다른 구성 요소 또는 외부 서비스와 통신 가능
- catalog 와 checkout 통신 확인
✅ Egress Controls
'UI' 네임스페이스에서 모든 egress 트래픽을 차단하는 네트워크 정책을 정의
- 클러스터의 모든 네임스페이스에 적용할 수 있는 일반 정책 => 네트워크 정책에 지정된 네임스페이스가 없음
- 정책적용
- 'UI' 에서 'catalog' 에 액세스 -> 통신할수 없음 확인
- 'ui' 컴포넌트
- 'catalog', 'orders' 등과 같은 다른 모든 서비스 컴포넌트와 통신
- 클러스터 시스템 네임스페이스와 통신
네트워크 정책 설계
- 데이터베이스에 대한 액세스를 제공하지 않고 'catalog', 'order' 등과 같은 모든 service 에 대한 egress 트래픽을 허용
- 파드 레이블이 "app.kubernetes.io/component: service"와 일치하는 모든 네임스페이스로의 egress 트래픽 허용
- kube-system 네임스페이스의 모든 egress 트래픽 허용
- 시스템 네임스페이스의 컴포넌트와 DNS 조회 및 기타 주요 통신
- allow-ui-egress.yaml
- metadata: 리소스의 메타데이터 정의
- namespace: ui: 이 네트워크 정책이 속하는 namespace 지정
- name: allow-ui-egress: 네트워크 정책의 이름을 지정
- spec: 네트워크 정책 정의
- podSelector: 정책이 적용될 파드
- matchLabels: 파드의 라벨을 기반으로 선택 (app.kubernetes.io/name: ui 라벨이 있는 파드 선택)
- policyTypes: 정책의 유형을 지정 (Egress 정책 사용하여 파드의 외부 트래픽을 제어)
- egress: 파드의 외부 트래픽을 제어하는 규칙을 정의
- to: 허용할 대상
- namespaceSelector: 네임스페이스 선택 (app.kubernetes.io/component: service 라벨이 있는 네임스페이스를 선택)
- podSelector: 파드 선택 (kubernetes.io/metadata.name: kube-system 라벨이 있는 네임스페이스를 선택)
- to: 허용할 대상
- podSelector: 정책이 적용될 파드
- 'catalog' 서비스에는 연결할 수 있지만
- 데이터베이스에는 app.kubernetes.io/component: service 레이블이 없으므로 연결할 수 없음
- 인터넷이나 기타 서비스에 대한 호출은 차단
✅ Ingress Controls
'catalog' 네임스페이스는 'ui' 네임스페이스에서만 트래픽을 수신하고 다른 네임스페이스에서는 트래픽을 수신하지 않음
' catalog ' 데이터베이스 는 ' catalog ' 서비스 컴포넌트로부터만 트래픽을 수신
'catalog' 네임스페이스로의 트래픽을 제어하는 인그레스 네트워크 정책을 사용하여 위의 네트워크 규칙을 구현할 수 있습니다.
- 정책을 적용하기 전
- 'ui' 에 액세스 가능
- 'orders' 액세스 가능
- 'ui' 에서만 'catalog' 서비스 로의 트래픽을 허용하는 네트워크 정책 정의
- allow-catalog-ingress-webservice.yaml
- metadata: 리소스의 메타데이터 정의
- namespace: catalog: 이 네트워크 정책이 속하는 namespace 지정 (catalog 네임스페이스)
- name: allow-catalog-ingress-webservice: 네트워크 정책의 이름 지정
- spec: 네트워크 정책 정의 .
- podSelector: 정책이 적용될 파드
- matchLabels: 파드의 라벨을 기반으로 선택 ( app.kubernetes.io/name: catalog와 app.kubernetes.io/component: service 라벨이 있는 파드를 선택)
- ingress: 파드로의 외부 트래픽을 제어하는 규칙을 정의
- from: 허용할 출발지
- namespaceSelector: 네임스페이스를 선택 (kubernetes.io/metadata.name: ui 라벨이 있는 네임스페이스)
- podSelector: 파드를 선택하는 옵션입니다. (app.kubernetes.io/name: ui 라벨이 있는 파드)
- from: 허용할 출발지
- podSelector: 정책이 적용될 파드
- 정책 적용
- 'UI'에서 'catalog' 에 계속 액세스 확인
- 하지만 'orders' 에서는 액세스 안됨
- 위의 결과에서 볼 수 있듯이 'ui' 에서만 'catalog' 서비스 와 통신할 수 있고, 'orders' 서비스는 통신할 수 없음
- 하지만 이렇게 해도 ' catalog ' 데이터베이스 는 여전히 열려 있으므로 ' catalog ' 서비스 만 ' catalog ' 데이터베이스 와 통신할 수 있도록 네트워크 정책을 구현
- allow-catalog-ingress-db.yaml
- metadata: 리소스의 메타데이터 정의
-
- namespace: catalog: 이 네트워크 정책이 속하는 namespace 지정 (catalog 네임스페이스)
- name: allow-catalog-ingress-db: 네트워크 정책의 이름 지정
-
- spec: 네트워크 정책 정의 .
- podSelector: 정책이 적용될 파드
- matchLabels: 파드의 라벨을 기반으로 선택 ( app.kubernetes.io/name: catalog와 app.kubernetes.io/component: mysql 라벨이 있는 파드를 선택)
- ingress: 파드로의 외부 트래픽을 제어하는 규칙을 정의
- from: 허용할 출발지
- podSelector : 파드를 선택
- matchLabels : 파드의 라벨을 기반으로 선택 ( app.kubernetes.io/name: catalog와 app.kubernetes.io/component: service 라벨이 있는 파드를 선택)
- podSelector : 파드를 선택
- from: 허용할 출발지
- podSelector: 정책이 적용될 파드
- 정책 적용
- 'orders' 구성 요소에서 'catalog' 데이터베이스에 연결할 수 없는지 확인
- 하지만 'catalog' 파드를 다시 시작하면 여전히 연결
- kubectl rollout restart deployment/catalog -n catalog:
- kubectl rollout restart :지정된 디플로이먼트의 롤링 업데이트를 트리거하여 해당 디플로이먼트의 파드를 다시 시작
- deployment/catalog : 다시 시작하려는 디플로이먼트의 이름
- -n catalog : 디플로이먼트가 속한 네임스페이스 지정
- kubectl rollout status deployment/catalog -n catalog --timeout=2m:
- kubectl rollout status : 디플로이먼트의 롤아웃 상태를 확인
- deployment/catalog :상태를 확인하려는 디플로이먼트의 이름을 지정
- -n catalog : 디플로이먼트가 속한 네임스페이스를 지정
- --timeout=2m : 상태 확인을 시도할 최대 시간을 지정 (여기서는 2분 동안 디플로이먼트가 배포되는 상태를 기다림 => 만약 디플로이먼트가 2분 이내에 롤아웃되지 않으면 타임아웃이 발생)
✅ Debugging
- Amazon VPC CNI는 네트워크 정책을 구현하는 동안 문제를 디버깅하는 데 사용할 수 있는 로그를 제공
- Amazon CloudWatch와 같은 서비스를 통해 이러한 로그를 모니터링할 수 있으며, CloudWatch 컨테이너 인사이트를 활용하여 네트워크 정책과 관련된 사용량에 대한 인사이트를 제공
- 'catalog' 서비스 에서 수행한 것과 유사하게 'ui' 에서만 'orders' 서비스 에 대한 액세스를 제한하는 인그레스 네트워크 정책 구현
- allow-order-ingress-fail-debug.yaml
- metadata: 리소스의 메타데이터 정의
-
- namespace: catalog: 이 네트워크 정책이 속하는 namespace 지정 ( orders 네임스페이스)
- name: allow-orders-ingress-webservice : 네트워크 정책의 이름 지정
-
- spec: 네트워크 정책 정의 .
- podSelector: 정책이 적용될 파드
- matchLabels: 파드의 라벨을 기반으로 선택 ( app.kubernetes.io/name: orders 와 app.kubernetes.io/component: service 라벨이 있는 파드를 선택)
- ingress: 파드로의 외부 트래픽을 제어하는 규칙을 정의
- from: 허용할 출발지
- podSelector : 파드를 선택
- matchLabels : 파드의 라벨을 기반으로 선택 ( app.kubernetes.io/name: ui 파드를 선택)
- podSelector : 파드를 선택
- from: 허용할 출발지
- podSelector: 정책이 적용될 파드
- 'ui' 컴포넌트의 호출이 성공했어야 하지만 실패
- 이 문제를 디버그하기 위해 네트워크 정책 에이전트 로그를 활용하여 문제가 어디에 있는지 확인
- 트워크 정책 에이전트 로그는 각 작업자 노드의 /var/log/aws-routed-eni/network-policy-agent.log 파일에서 확인
- 파일에 DENY 문이 기록되는지 확인
- kubectl get po --selector app.kubernetes.io/component=service -n orders -o json:
- kubectl get po: 파드 목록을 가져오는 Kubernetes CLI 명령어.
- --selector app.kubernetes.io/component=service: 라벨 셀렉터를 사용하여 특정 라벨을 가진 파드만 선택 (여기서는 app.kubernetes.io/component=service 라벨을 가진 파드를 선택)
- -n orders: orders 네임스페이스에서 파드를 찾도록 지정
- -o json: 결과를 JSON 형식으로 출력
- jq -r '.items[0].spec.nodeName':
- jq: JSON 데이터를 처리하기 위한 명령줄 도구
- -r: 결과를 로우 텍스트(raw text)로 출력하도록 지정
- '.items[0].spec.nodeName': JSON 데이터에서 파드 목록을 나타내는 items 배열의 첫 번째 요소의 spec.nodeName 값을 가져옵니다. (이는 해당 파드가 호스트하는 노드의 이름을 의미)
orders 네임스페이스에서 라벨이 app.kubernetes.io/component=service인 첫 번째 파드의 호스트 노드의 IP 주소를 가져와서 POD_HOSTIP_1 변수에 할당
- kubectl debug node/$POD_HOSTIP_1:
- kubectl debug node: 노드 디버깅을 시작
- $POD_HOSTIP_1: 이는 이전 명령어에서 설정한 변수로, 호스트 노드의 IP 주소
- 특정 노드에 디버깅을 시작
- -it:
- 터미널 인터랙션을 가능하게 하는 옵션
- -i는 표준 입력을 유지하고, -t는 터미널을 할당합니다.
- --image=ubuntu:
- 디버깅을 위한 컨테이너로 사용할 이미지를 지정
- level: 로그의 수준을 나타내는 필드로, 여기서는 "info"입니다. 이는 로그의 중요도를 나타냅니다.
- timestamp: 로그가 발생한 시간을 나타내는 필드입니다. 여기서는 "2024-03-16T07:18:44.031Z"입니다.
- logger: 로그를 생성한 로거의 이름을 나타내는 필드입니다. 여기서는 "ebpf-client"입니다.
- msg: 로그 메시지를 나타내는 필드입니다. 여기서는 "Flow Info: "입니다.
- Src IP: 소스 IP 주소를 나타내는 필드입니다. 여기서는 "10.42.97.134"입니다.
- Src Port: 소스 포트 번호를 나타내는 필드입니다. 여기서는 "35198"입니다.
- Dest IP: 대상 IP 주소를 나타내는 필드입니다. 여기서는 "10.42.158.67"입니다.
- Dest Port: 대상 포트 번호를 나타내는 필드입니다. 여기서는 "8080"입니다.
- Proto: 프로토콜을 나타내는 필드입니다. 여기서는 "TCP"입니다.
- Verdict: 트래픽에 대한 결정을 나타내는 필드입니다. 여기서는 "DENY"로 트래픽이 차단되었음을 나타냅니다.
- 네트워크 정책의 ingress 섹션에 podSelector만 있고 namespaceSelector가 없다는 것을 알 수 있습니다.
- namespaceSelector 가 비어 있기 때문에 네트워크 정책의 네임스페이스인 'orders'가 기본값으로 사용
- 따라서, 이 정책은 'orders' 네임스페이스에서 'app.kubernetes.io/name: ui' 레이블과 일치하는 파드를 허용하는 것으로 해석되며, 결과적으로 ui' 구성 요소의 트래픽이 거부된다.
- 네트워크 정책을 수정하고 다시 시도
- 'UI'가 연결될 수 있는지 확인
'AWS EKS Workshop Study 2기' 카테고리의 다른 글
AWS EKS - Observability - Logging in EKS (0) | 2024.03.30 |
---|---|
AWS EKS - Storage - EFS (2) | 2024.03.23 |
AWS EKS - Storage - EBS (0) | 2024.03.17 |
AWS EKS - Security Groups for Pods (0) | 2024.03.16 |
AWS EKS - 최적화 AMI (0) | 2024.03.09 |
Comments