8.4.3 폴리시 타입 (Policy Types): Ingress, Egress
쿠버네티스 네트워크 폴리시(Network Policy)는 파드(Pod)를 기준으로 네트워크 트래픽의 흐름을 제어하는 강력한 도구입니다. 우리가 특정 파드 그룹에 대한 통신 규칙을 정의하고자 할 때, 이 규칙이 어떤 방향의 트래픽에 적용될 것인지를 명확히 지정해야 합니다. 마치 건물의 출입 관리를 할 때, 건물로 들어오는 사람(Ingress)에 대한 규칙과 건물에서 나가는 사람(Egress)에 대한 규칙을 별도로 설정하는 것과 같습니다.
네트워크 폴리시 명세(spec) 내의 policyTypes 필드는 바로 이러한 트래픽의 방향, 즉 해당 폴리시가 어떤 종류의 트래픽 흐름을 제어할 것인지를 정의하는 역할을 합니다. 이 필드는 선택 사항이며, 만약 생략될 경우의 기본 동작은 폴리시에 ingress 규칙이 정의되어 있으면 Ingress 타입을, egress 규칙이 정의되어 있으면 Egress 타입을, 둘 다 정의되어 있으면 두 타입 모두를 의미하는 것으로 해석될 수 있습니다 (단, 명확성을 위해 명시적으로 지정하는 것이 좋습니다).
policyTypes 필드에는 다음 두 가지 주요 값을 포함하는 배열을 지정할 수 있습니다.
- Ingress (인그레스, 수신 트래픽): 이 타입을 지정하면, 해당 네트워크 폴리시는 **선택된 파드(들)로 들어오는 트래픽(inbound traffic)**에 대한 규칙을 정의하고 적용합니다. 즉, 어떤 다른 파드나 네트워크 소스에서 이 파드로 연결을 시도할 수 있는지, 그리고 어떤 포트를 통해 연결할 수 있는지를 제어합니다.
- Egress (이그레스, 송신 트래픽): 이 타입을 지정하면, 해당 네트워크 폴리시는 **선택된 파드(들)에서 나가는 트래픽(outbound traffic)**에 대한 규칙을 정의하고 적용합니다. 즉, 이 파드가 어떤 다른 파드나 외부 네트워크 대상으로 연결을 시도할 수 있는지, 그리고 어떤 포트를 통해 연결할 수 있는지를 제어합니다.
하나의 네트워크 폴리시 리소스 내에서 Ingress 규칙과 Egress 규칙을 함께 정의하여 양방향 트래픽을 모두 제어할 수도 있습니다. 이 경우 policyTypes 필드에는 [“Ingress”, “Egress”] 와 같이 두 가지 타입을 모두 명시합니다.
이제 각 폴리시 타입이 구체적으로 어떤 의미를 가지며, 어떻게 사용되는지 예시와 함께 자세히 살펴보겠습니다.
8.4.3.1 Ingress (인그레스) 폴리시 타입: 파드로 들어오는 문 지키기
Ingress 폴리시 타입은 네트워크 폴리시가 적용되는 대상 파드(들) (보통 spec.podSelector로 선택됨)로 향하는 모든 수신 네트워크 연결을 제어합니다. 기본적으로 쿠버네티스 클러스터 내의 모든 파드는 서로 자유롭게 통신할 수 있지만, 특정 파드 그룹에 Ingress 타입의 네트워크 폴리시가 적용되면 상황이 달라집니다. 만약 이 폴리시 내에 어떠한 명시적인 ingress 허용 규칙도 정의되어 있지 않거나, 정의된 ingress 규칙과 일치하는 수신 트래픽이 없다면, 해당 파드 그룹으로의 모든 다른 수신 트래픽은 기본적으로 차단(deny)됩니다. 이는 매우 중요한 특징으로, “기본 거부(default deny)” 원칙을 수신 트래픽에 대해 구현하는 핵심적인 방법입니다. 즉, 초대받지 않은 손님은 문 앞에서 돌려보내는 것과 같습니다.
Ingress 규칙은 다음과 같은 핵심적인 질문에 대한 답을 정의합니다.
- “어떤 소스(Source)에서 오는 트래픽을 이 파드(들)에게 허용할 것인가?”
- 이 소스는 레이블 셀렉터(podSelector)를 사용하여 특정 레이블을 가진 다른 파드들을 지정할 수도 있고, 네임스페이스 셀렉터(namespaceSelector)를 사용하여 특정 네임스페이스에 속한 모든 파드를 지정할 수도 있습니다. 또한, 특정 IP 주소 범위(ipBlock의 cidr)를 지정하여 클러스터 내부 또는 외부의 특정 네트워크 대역으로부터의 접근을 허용할 수도 있습니다. 이러한 조건들은 from 필드 아래에 배열 형태로 여러 개 정의될 수 있으며, 이 중 하나라도 만족하면 해당 소스로부터의 트래픽이 고려 대상이 됩니다.
- “허용한다면, 어떤 프로토콜(TCP, UDP, SCTP)과 어떤 대상 포트 번호(또는 명명된 포트)를 통해 들어오는 연결을 허용할 것인가?”
- 이는 ports 필드 아래에 정의되며, 특정 프로토콜과 포트 번호를 명시하여 오직 해당 서비스 포트로의 연결만을 선택적으로 허용할 수 있습니다. 예를 들어, 웹 서버 파드라면 TCP 80번 또는 443번 포트로의 접근만 허용하고 다른 포트로의 접근은 차단할 수 있습니다.
예시: 특정 프론트엔드 파드에서만 백엔드 API 파드로의 HTTP 접근 허용
다음은 app: my-backend-api 레이블을 가진 파드 그룹(백엔드 API)에 대해, 오직 role: frontend-web 레이블을 가진 파드들(프론트엔드 웹 서버)로부터의 TCP 80번 포트로의 수신 트래픽만을 허용하는 Ingress 네트워크 폴리시 예시입니다.
이 정책이 적용되면, my-backend-api 파드들은 role: frontend-web 레이블을 가진 파드들로부터 80번 포트를 통해 들어오는 요청은 수신할 수 있지만, 그 외의 다른 모든 소스(다른 레이블의 파드, 다른 네임스페이스의 파드, IP 블록 등)로부터의 모든 수신 연결은 차단됩니다. 이는 백엔드 API를 오직 허가된 프론트엔드 애플리케이션만이 사용할 수 있도록 보호하는 효과적인 방법입니다.
8.4.3.2 Egress (이그레스) 폴리시 타입: 파드에서 나가는 문 지키기
Egress 폴리시 타입은 네트워크 폴리시가 적용되는 대상 파드(들)에서 외부로 향하는 모든 송신 네트워크 연결을 제어합니다. Ingress와 마찬가지로, 기본적으로 쿠버네티스 파드는 클러스터 내부의 다른 파드나 외부 네트워크로 자유롭게 연결을 시도할 수 있습니다. 하지만 특정 파드 그룹에 Egress 타입의 네트워크 폴리시가 적용되고, 이 폴리시 내에 어떠한 명시적인 egress 허용 규칙도 정의되어 있지 않거나, 정의된 egress 규칙과 일치하는 송신 트래픽이 없다면, 해당 파드 그룹에서의 모든 다른 목적지로의 송신 트래픽은 기본적으로 차단(deny)됩니다. 이는 파드가 의도치 않거나 악의적인 외부 연결을 맺는 것을 방지하는 데 매우 중요합니다. 마치 자녀에게 “이 가게들만 가고, 다른 곳은 가면 안 돼!”라고 허용된 목적지만을 정해주는 것과 같습니다.
Egress 규칙은 다음과 같은 핵심적인 질문에 대한 답을 정의합니다.
- “이 파드(들)가 어떤 목적지(Destination)로 트래픽을 보내는 것을 허용할 것인가?”
- Ingress 규칙의 from 필드와 유사하게, Egress 규칙의 to 필드 아래에는 허용할 목적지를 정의합니다. 목적지는 레이블 셀렉터(podSelector)를 사용하여 특정 레이블을 가진 다른 파드들을 지정하거나, 네임스페이스 셀렉터(namespaceSelector)를 사용하여 특정 네임스페이스에 속한 모든 파드를 지정할 수 있습니다. 또한, 특정 IP 주소 범위(ipBlock의 cidr)를 지정하여 클러스터 외부의 특정 서비스(예: 외부 데이터베이스, 공용 API 엔드포인트)나 내부의 특정 네트워크 대역으로의 연결을 허용할 수 있습니다.
- “허용한다면, 어떤 프로토콜(TCP, UDP, SCTP)과 어떤 목적지 포트 번호(또는 명명된 포트)를 통해 나가는 연결을 허용할 것인가?”
- ports 필드를 사용하여, 특정 프로토콜과 목적지 포트 번호를 명시하여 오직 해당 서비스 포트로의 송신 연결만을 선택적으로 허용할 수 있습니다. 예를 들어, 애플리케이션 파드가 외부 데이터베이스에 접속해야 한다면, 해당 데이터베이스의 IP 주소와 포트로의 TCP 연결만 허용하고 다른 모든 외부 연결은 차단할 수 있습니다.
예시: 애플리케이션 파드가 특정 외부 IP 대역의 HTTPS 포트로만 송신 허용
다음은 app: my-application 레이블을 가진 파드 그룹(애플리케이션)이 오직 10.0.0.0/24 IP 주소 블록에 있는 서버들의 TCP 443번 포트(일반적으로 HTTPS)로만 송신 트래픽을 보낼 수 있도록 제한하는 Egress 네트워크 폴리시 예시입니다. (또한, DNS 조회를 위해 클러스터 내부 DNS 서비스로의 통신도 허용해야 합니다.)
이 정책이 적용되면, app: my-application 파드들은 10.0.0.0/24 대역의 443번 포트와 클러스터 내부 DNS 서비스의 53번 포트로만 나가는 연결을 맺을 수 있으며, 그 외의 다른 모든 목적지(예: 인터넷의 다른 웹사이트, 클러스터 내의 다른 허용되지 않은 파드)로의 송신 트래픽은 차단됩니다. 이는 애플리케이션 파드가 악성코드에 감염되어 외부로 데이터를 유출하거나 다른 시스템을 공격하는 것을 효과적으로 방지하는 데 도움을 줄 수 있습니다.
policyTypes 필드의 중요성 및 기본 동작 재확인:
앞서 간략히 언급했듯이, policyTypes 필드는 네트워크 폴리시의 의도를 명확히 하고 예측 가능한 동작을 보장하는 데 매우 중요합니다.
- policyTypes: [“Ingress”]: 오직 수신 트래픽만 이 폴리시의 규칙에 따라 제어됩니다. 송신 트래픽은 제한 없이 모두 허용됩니다.
- policyTypes: [“Egress”]: 오직 송신 트래픽만 이 폴리시의 규칙에 따라 제어됩니다. 수신 트래픽은 제한 없이 모두 허용됩니다.
- policyTypes: [“Ingress”, “Egress”]: 수신 및 송신 트래픽 모두 이 폴리시의 해당 규칙에 따라 제어됩니다.
- policyTypes 필드 생략 시:
- ingress 규칙만 정의되어 있으면: [“Ingress”]와 동일하게 동작 (Egress는 모두 허용).
- egress 규칙만 정의되어 있으면: [“Egress”]와 동일하게 동작 (Ingress는 모두 허용).
- ingress와 egress 규칙이 모두 정의되어 있으면: [“Ingress”, “Egress”]와 동일하게 동작.
- policyTypes: [] (빈 배열): 해당 podSelector에 매칭되는 파드는 모든 Ingress 및 Egress 트래픽이 차단됩니다 (단, 이 폴리시 외에 다른 허용 폴리시가 없다면). 이는 “기본 거부” 정책을 설정하는 강력한 방법입니다.
결론적으로, Ingress와 Egress라는 두 가지 폴리시 타입을 통해 우리는 파드를 중심으로 들어오고 나가는 네트워크 트래픽의 흐름을 마치 성벽의 문지기처럼 철저하게 통제할 수 있습니다. 이는 쿠버네티스 클러스터 내에서 “최소 권한의 원칙”을 네트워크 레벨에서 구현하고, 애플리케이션의 보안 경계를 명확히 하며, 전반적인 시스템의 보안 태세를 강화하는 데 있어 핵심적인 역할을 수행합니다.
