본문으로 바로가기 본문 바로가기
WIKI 기술 지식 베이스

스테이지드 네트워크 정책

원문 보기 위키 갱신

스테이지드 네트워크 정책 (Staged network policy)

스테이지드 네트워크 정책 리소스(StagedNetworkPolicy)는 레이블 셀렉터에 일치하는 엔드포인트 컬렉션에 적용되는 순서가 있는 규칙 집합을 나타냅니다. 이 규칙들은 네트워크 동작을 미리 보기(preview) 위한 것이며 네트워크 트래픽을 강제하지는 않습니다. 트래픽을 실제로 강제하려면 네트워크 정책 리소스를 참고하세요. 이 문서에서는 StagedNetworkPolicy 리소스의 구조와 필드 구성을 살펴봅니다.

출처: 문서

본문

StagedNetworkPolicy는 네임스페이스에 속한 리소스입니다. 특정 네임스페이스의 StagedNetworkPolicy는 그 네임스페이스 안의 워크로드 엔드포인트 리소스에만 적용됩니다. 두 리소스는 namespace 값이 서로 같으면 같은 네임스페이스에 속합니다. 네임스페이스에 속하지 않는 스테이지드 네트워크 정책은 스테이지드 글로벌 네트워크 정책 리소스를 참고하세요.

StagedNetworkPolicy 리소스는 Calico 엔드포인트 그룹과 호스트 엔드포인트 그룹 사이의 네트워크 연결 규칙을 정의하는 데 사용할 수 있으며, 정의된 Profile 리소스가 있다면 그보다 우선 적용됩니다.

StagedNetworkPolicy는 티어(tier)로 구성됩니다. 티어는 추가적인 순서 계층을 제공하며, 특히 Pass 동작은 다음 티어로 건너뛰어 계층형 보안 정책을 가능하게 합니다.

kubectl 명령에서는 CLI에서 리소스 타입을 지정할 때 다음과 같은 대소문자를 구분하지 않는 별칭을 사용할 수 있습니다: stagednetworkpolicy.projectcalico.org, stagednetworkpolicies.projectcalico.org, 그리고 stagednetworkpolicy.p, stagednetworkpolicies.p 같은 축약형.

샘플 YAML

이 샘플 정책은 frontend 엔드포인트에서 database 엔드포인트의 6379 포트로 가는 TCP 트래픽을 허용합니다.

apiVersion: projectcalico.org/v3
kind: StagedNetworkPolicy
metadata:
  name: internal-access.allow-tcp-6379
  namespace: production
spec:
  tier: internal-access
  selector: role == 'database'
  types:
    - Ingress
    - Egress
  ingress:
    - action: Allow
      protocol: TCP
      source:
        selector: role == 'frontend'
      destination:
        ports:
          - 6379
  egress:
    - action: Allow

정의

메타데이터(Metadata)

필드 설명 허용 값 스키마 기본값
name 네트워크 정책의 이름입니다. 필수 항목입니다. 영숫자 문자열이며 ., _, -를 포함할 수 있습니다. string
namespace 네임스페이스는 리소스 이름에 추가적인 한정(qualifier)을 붙입니다. string "default"

스펙(Spec)

필드 설명 허용 값 스키마 기본값
order 우선순위 순서를 제어합니다. Calico는 값이 가장 낮은 정책을 먼저 적용합니다. float
tier 이 정책이 속한 티어의 이름입니다. string default
selector 이 정책이 적용될 엔드포인트를 선택합니다. selector all()
types 트래픽 방향에 따라 정책을 적용합니다. 인바운드 트래픽에 적용하려면 Ingress로, 아웃바운드 트래픽에 적용하려면 Egress로, 둘 모두에 적용하려면 Ingress, Egress로 설정하세요. Ingress, Egress List of strings ingress/egress 규칙 존재 여부에 따라 다릅니다\*
ingress 정책이 적용하는 ingress 규칙의 순서 목록입니다. List of Rule
egress 이 정책이 적용하는 egress 규칙의 순서 목록입니다. List of Rule
serviceAccountSelector 이 정책이 적용될 서비스 어카운트를 선택합니다. projectcalico.org/name 레이블을 사용해 이름으로 특정 서비스 어카운트를 선택할 수 있습니다. selector all()
performanceHints 정책을 더 효율적으로 처리하도록 Calico의 정책 엔진에 전달하는 힌트 목록입니다. 힌트는 정책의 시행 동작을 절대 바꾸지 않습니다. 사용 가능한 힌트는 아래에 설명되어 있습니다. AssumeNeededOnEveryNode List of strings

\* types에 값이 없으면 Calico는 다음과 같이 기본값을 적용합니다.

Ingress 규칙 존재 Egress 규칙 존재 Types 값
No No Ingress
Yes No Ingress
No Yes Egress
Yes Yes Ingress, Egress

규칙(Rule)

하나의 규칙은 패킷 집합에 일치하고 그 패킷들에 어떤 동작을 적용합니다. 여러 규칙이 지정되면 순서대로 실행됩니다.

필드 설명 허용 값 스키마 기본값
metadata 규칙별 메타데이터입니다. RuleMetadata
action 이 규칙에 일치할 때 수행할 동작입니다. Allow, Deny, Log, Pass string
protocol 긍정(positive) 프로토콜 매치입니다. TCP, UDP, ICMP, ICMPv6, SCTP, UDPLite, 1-255 string | integer
notProtocol 부정(negative) 프로토콜 매치입니다. TCP, UDP, ICMP, ICMPv6, SCTP, UDPLite, 1-255 string | integer
icmp ICMP 매치 기준입니다. ICMP
notICMP ICMP에 대한 부정 매치입니다. ICMP
ipVersion 긍정 IP 버전 매치입니다. 4, 6 integer
source 소스 매치 파라미터입니다. EntityRule
destination 목적지 매치 파라미터입니다. EntityRule
http HTTP 요청 파라미터를 매치합니다. 이 필드를 사용하려면 애플리케이션 계층 정책이 활성화되어 있어야 합니다. HTTPMatch

Log 동작 이후에는 다음 규칙으로 처리가 계속됩니다. Allow와 Deny는 즉시이자 최종이며 이후 규칙은 처리되지 않습니다.

NetworkPolicy 또는 GlobalNetworkPolicy에서 action이 Pass이면 남은 정책들을 건너뛰고 엔드포인트에 할당된 첫 번째 profile로 점프해 profile에 설정된 정책을 적용합니다. 엔드포인트에 설정된 Profile이 없다면 기본 적용 동작은 Deny입니다.

RuleMetadata

정책 전체가 아니라 특정 규칙에 연결된 메타데이터입니다. 메타데이터 내용은 규칙이 해석되거나 시행되는 방식에 영향을 주지 않으며, Calico와 상호작용하는 운영자나 애플리케이션이 사용할 추가 정보를 저장하는 방법일 뿐입니다.

필드 설명 스키마 기본값
annotations 식별 목적이 아닌 임의의 메타데이터입니다. map of string to string

예시:

metadata:
  annotations:
    app: database
    owner: devops

어노테이션은 유효한 문법과 문자 집합에 관해 쿠버네티스와 동일한 규칙을 따릅니다.

iptables 데이터 플레인을 사용하는 Linux에서는 규칙 어노테이션이 Calico 규칙에 해당하는 iptables 규칙 위에 -m comment --comment "<key>=<value>" 형태의 주석으로 렌더링됩니다.

ICMP

필드 설명 허용 값 스키마 기본값
type ICMP 타입에 매치합니다. 0-254 정수를 사용할 수 있습니다 integer
code ICMP 코드에 매치합니다. 0-255 정수를 사용할 수 있습니다 integer

EntityRule

Entity 규칙은 규칙 전체가 일치하기 위해 충족되어야 하는 패킷의 소스 또는 목적지 속성을 지정합니다. 패킷은 다음 조합으로 매치할 수 있습니다.

규칙에 여러 매치 기준이 포함되어 있다면(예: IP와 포트), 규칙 전체가 패킷에 일치하려면 모든 매치 기준이 일치해야 합니다.

필드 설명 허용 값 스키마 기본값
nets 나열된 CIDR 중 어디에든 IP가 속한 패킷을 매치합니다. 유효한 IPv4 CIDR 목록 또는 유효한 IPv6 CIDR 목록 (하나의 규칙에서 IPv4와 IPv6 CIDR을 섞으면 안 됩니다) list of cidrs
notNets CIDR에 대한 부정 매치입니다. 나열된 CIDR 어디에도 속하지 않는 IP를 가진 패킷을 매치합니다. 유효한 IPv4 CIDR 목록 또는 유효한 IPv6 CIDR 목록 (하나의 규칙에서 IPv4와 IPv6 CIDR을 섞으면 안 됩니다) list of cidrs
selector 선택된 엔드포인트에 긍정 매치합니다. namespaceSelector도 함께 정의되어 있다면 적용 대상 엔드포인트 집합은 선택된 네임스페이스 안의 엔드포인트로 한정됩니다. 유효한 셀렉터 selector
notSelector 선택된 엔드포인트에 부정 매치합니다. namespaceSelector도 함께 정의되어 있다면 적용 대상 엔드포인트 집합은 선택된 네임스페이스 안의 엔드포인트로 한정됩니다. 유효한 셀렉터 selector
namespaceSelector 선택된 네임스페이스에 긍정 매치합니다. 지정하면 선택된 쿠버네티스 네임스페이스 안의 워크로드 엔드포인트만 매치됩니다. 네임스페이스에 적용된 레이블을 기준으로 네임스페이스를 매치합니다. 셀렉터가 적용될 범위를 정의하며, 정의하지 않으면 셀렉터는 NetworkPolicy의 네임스페이스에 적용됩니다. kubernetes.io/metadata.name 레이블을 사용해 특정 네임스페이스를 이름으로 매치하세요. global() 셀렉터를 사용해 이 정책이 적용될 GlobalNetworkSet(s), 호스트 엔드포인트 같은 네임스페이스가 없는 리소스를 선택하세요. 유효한 셀렉터 selector
ports 지정된 포트에 긍정 매치합니다 list of ports
notPorts 지정된 포트에 부정 매치합니다 list of ports
serviceAccounts 서비스 어카운트로 실행 중인 엔드포인트를 매치합니다. namespaceSelector도 함께 정의되어 있다면 적용 대상 서비스 어카운트 집합은 선택된 네임스페이스 안의 서비스 어카운트로 한정됩니다. ServiceAccountMatch
services 쿠버네티스 데이터스토어 드라이버를 사용할 때만 지원되며 etcd 데이터스토어 드라이버는 무시합니다. 지정된 서비스를 매치합니다. egress 규칙 목적지에 지정하면 다른 선택 기준을 설정할 수 없습니다. ingress 규칙 소스에 지정하면 포트에 대한 긍정 또는 부정 매치만 지정할 수 있습니다. ServiceMatch

네트워크 정책에서 셀렉터를 사용할 때는 셀렉터는 (알려진) 리소스만 매치하고 규칙은 패킷을 매치한다는 점을 기억하세요. all() 셀렉터를 가진 규칙은 "모든 패킷"에 매치하는 것이 아니라 "범위 내 모든 엔드포인트와 네트워크 셋에서 오가는 패킷"에 매치합니다. 모든 패킷에 매치하려면 규칙에 셀렉터를 아예 포함하지 마세요.

빈 매치 필드

매치 필드의 빈 값은 아무것도 매치하지 않는 빈 집합이 아니라, 필드가 아예 설정되지 않은 것처럼 처리됩니다. 예를 들어 nets: []는 규칙의 매치를 막지 않습니다. 규칙을 IP 주소 제약에서 벗어나게 해서 모든 소스 또는 목적지 주소에 매치됩니다. notNets, ports, notPorts도 마찬가지이며, selector, notSelector, namespaceSelector의 빈 문자열도 동일합니다. Calico는 보통 리소스를 저장할 때 빈 값을 버리므로 정책을 다시 읽으면 해당 필드가 없습니다.

notSelector 이해하기

notSelector는 다소 미묘합니다. notSelector의 not은 셀렉터가 아니라 패킷 매치를 부정하기 때문입니다.

  • selector: !has(foo)는 "foo" 레이블이 없는 엔드포인트와 네트워크 셋에서 오가는 패킷에 매치합니다.
  • notSelector: has(foo)는 "foo" 레이블을 가진 엔드포인트와 네트워크 셋에서 오가는 트래픽을 제외한 모든 곳(클러스터 외부 포함)에서 오가는 패킷에 매치합니다.

EntityRule에서의 셀렉터 성능

정책을 데이터 플레인에 렌더링할 때 Calico는 활성 규칙들의 셀렉터에 일치하는 엔드포인트를 식별해야 합니다. 이 계산은 특정 일반적인 셀렉터 타입에 대해 최적화되어 있습니다. 최적화된 셀렉터 타입을 사용하면 CPU 사용량(그리고 정책 렌더링 시간)이 몇 자릿수 줄어듭니다. 이는 높은 규모(수백 개의 활성 규칙, 수십만 개의 엔드포인트)에서 중요해집니다.

최적화된 연산자는 다음과 같습니다.

  • label == "value"
  • label in { 'v1', 'v2' }
  • has(label)
  • <expression 1> && <expression 2>는 <expression 1> 또는 <expression 2> 둘 중 하나라도 최적화되어 있으면 최적화됩니다.

다음은 has(label)과 비슷하게 동작합니다. 해당 레이블을 가진 모든 엔드포인트를 스캔해 매치를 찾습니다.

  • label contains 's'
  • label starts with 's'
  • label ends with 's'

나머지 연산자, 특히 all(), !, ||, !=는 최적화되지 않습니다.

예시:

  • a == 'b' - 최적화됨
  • a == 'b' && has(c) - 최적화됨
  • a == 'b' || has(c) - ||를 사용하므로 최적화되지 않음
  • c != 'd' - !=를 사용하므로 최적화되지 않음
  • !has(a) - !를 사용하므로 최적화되지 않음
  • a == 'b' && c != 'd' - 최적화됨, a == 'b'가 최적화되어 있으므로 a == 'b' && <무엇이든>은 최적화됩니다.
  • c != 'd' && a == 'b' - 최적화됨, a == 'b'가 최적화되어 있으므로 <무엇이든> && a == 'b'는 최적화됩니다.

셀렉터(Selector)

레이블 셀렉터는 리소스의 레이블을 기준으로 그 리소스에 매치하거나 매치하지 않는 표현식입니다.

Calico 레이블 셀렉터는 여러 연산자를 지원하며, 불리언 연산자와 괄호를 사용해 더 큰 표현식으로 조합할 수 있습니다.

표현식 의미
논리 연산자
( <expression> ) <expression>이 매치할 때 그리고 그때만 매치합니다. (괄호는 표현식을 묶는 데 사용합니다.)
! <expression> <expression>이 매치하지 않을 때 그리고 그때만 매치합니다. 팁: !는 YAML 문자열의 시작 위치에서 특수 문자입니다. YAML 문자열 시작에 !를 사용해야 한다면 문자열을 따옴표로 감싸세요.
<expression 1> && <expression 2> "And": <expression 1>과 <expression 2>가 모두 매치할 때 그리고 그때만 매치합니다
<expression 1> \|\| <expression 2> "Or": <expression 1> 또는 <expression 2>가 매치할 때 그리고 그때만 매치합니다.
매치 연산자
all() 범위 내 모든 리소스에 매치합니다. 어떤 리소스도 매치하지 않으려면 이 연산자를 !와 조합해 !all()을 만드세요.
global() 네임스페이스가 없는 모든 리소스에 매치합니다. namespaceSelector에서 글로벌 네트워크 셋 같은 글로벌 리소스를 선택할 때 유용합니다.
k == 'v' 레이블 'k'와 값 'v'를 가진 리소스에 매치합니다.
k != 'v' 레이블 'k'가 없거나 레이블 'k'의 값이 v와 같지 않은 리소스에 매치합니다
has(k) 값과 상관없이 레이블 'k'를 가진 리소스에 매치합니다. 레이블 k가 없는 파드를 매치하려면 이 연산자를 !와 조합해 !has(k)를 만드세요
k in { 'v1', 'v2' } 레이블 'k'와 주어진 집합 안의 값을 가진 리소스에 매치합니다
k not in { 'v1', 'v2' } 레이블 'k'가 없거나 레이블 'k'의 값이 주어진 집합에 속하지 않는 리소스에 매치합니다
k contains 's' 레이블 'k'와 부분 문자열 's'를 포함하는 값을 가진 리소스에 매치합니다
k starts with 's' 레이블 'k'와 부분 문자열 's'로 시작하는 값을 가진 리소스에 매치합니다
k ends with 's' 레이블 'k'와 부분 문자열 's'로 끝나는 값을 가진 리소스에 매치합니다

연산자의 우선순위는 다음과 같습니다.

  • 가장 높음: 모든 매치 연산자
  • 괄호 ( ... )
  • !를 사용한 부정
  • &&를 사용한 논리곱
  • 가장 낮음: ||를 사용한 논리합

예를 들어 표현식

! has(my-label) || my-label starts with 'prod' && role in {'frontend','business'}

은 다음처럼 "괄호로 묶입니다":

((!(has(my-label)) || ((my-label starts with 'prod') && (role in {'frontend','business'}))

이 표현식은 다음에 매치합니다.

  • "my-label" 레이블이 없는 모든 리소스.

  • 다음을 모두 만족하는 모든 리소스:

    • my-label 값이 "prod"로 시작하고,
    • role 레이블 값이 "frontend" 또는 "business" 중 하나입니다.

포트(Ports)

Calico는 포트를 표현하기 위해 다음 문법을 지원합니다.

문법 예시 설명
int 80 지정된 정확한(숫자) 포트
start:end 6040:6050 start ≤ x ≤ end 범위 안의 모든(숫자) 포트
string named-port 하나 이상의 엔드포인트의 ports 목록에 정의된 이름 있는 포트

개별 숫자 포트는 YAML/JSON 정수로 지정할 수 있습니다. 포트 범위나 이름 있는 포트는 문자열로 표현해야 합니다. 예를 들어 다음은 유효한 포트 목록입니다:

ports: [8080, '1234:5678', 'named-port']

이름 있는 포트(Named ports)

EntityRule에서 숫자 포트 대신 이름 있는 포트를 사용하면 간접 계층이 하나 생겨서 이름 있는 포트가 엔드포인트마다 서로 다른 숫자 값으로 매핑될 수 있습니다.

예를 들어 여러 HTTP 서버가 워크로드로 실행 중이라고 해봅시다. 일부는 HTTP 포트를 80으로, 다른 일부는 8080으로 노출합니다. 각 워크로드에서 올바른 로컬 포트로 매핑되는 http-port라는 이름 있는 포트를 만들 수 있습니다. 그러면 규칙에서 서버 타입마다 다른 규칙을 작성하는 대신 http-port라는 이름을 참조할 수 있습니다.

보조 설명(SECONDARY): 각 이름 있는 포트는 많은 엔드포인트를 참조할 수 있고(Calico는 이름 있는 포트를 엔드포인트/포트 조합의 집합으로 확장해야 합니다), 이름 있는 포트를 사용하는 것은 단순 숫자 포트보다 CPU 측면에서 훨씬 비쌉니다. 추가 간접 계층이 실제로 필요한 곳에서만 아껴 쓰기를 권장합니다.

ServiceAccountMatch

ServiceAccountMatch는 EntityRule 안에서 서비스 어카운트를 매치합니다.

필드 설명 스키마
names 이름으로 서비스 어카운트를 매치합니다 list of strings
selector 레이블로 서비스 어카운트를 매치합니다 selector

ServiceMatch

ServiceMatch는 EntityRule 안에서 서비스를 매치합니다.

필드 설명 스키마
name 서비스의 이름입니다. string
namespace 서비스의 네임스페이스입니다. string

서비스 매치는 쿠버네티스 데이터스토어 드라이버를 사용할 때만 지원됩니다. etcd 데이터스토어 드라이버는 지원하지 않습니다.

성능 힌트(Performance Hints)

성능 힌트는 정책의 의도된 용도를 Calico에 알려줘서 더 효율적으로 처리하게 하는 방법입니다. 현재 힌트는 하나만 정의되어 있습니다.

  • AssumeNeededOnEveryNode: 평소에 Calico는 정책이 실제 사용 중인 노드(즉, 셀렉터가 로컬 엔드포인트에 매치되는 노드)에서만 정책의 규칙과 셀렉터를 계산합니다. 이는 대부분의 경우 작업을 절약합니다. AssumeNeededOnEveryNode 힌트는 Calico에게 모든 노드에서 정책을 "사용 중"으로 취급하라고 알려줍니다. 모든(또는 거의 모든) 엔드포인트에 적용될 것을 알고 있는 대규모 정책 집합에 유용합니다. 사실상 모든 노드에 정책을 "프리로드"해서 정책에 매치되는 첫 엔드포인트가 나타났을 때 해야 할 일을 줄여줍니다. 또한 마지막 엔드포인트가 드레인될 때 정책을 해체하는 작업이 수행되는 것도 막아줍니다.

지원되는 작업(Supported operations)

데이터스토어 타입 생성/삭제 업데이트 Get/List 비고
Kubernetes API datastore Yes Yes Yes

티어별 목록 필터링

list 및 watch 작업은 레이블 셀렉터나 필드 셀렉터를 지정해 API 서버가 반환하는 티어별로 StagedNetworkPolicy 리소스를 필터링할 수 있습니다. 셀렉터를 지정하지 않으면 API 서버는 사용자가 접근 권한을 가진 모든 티어의 StagedNetworkPolicy 리소스를 반환합니다.

필드 셀렉터(Field selector)

필드 셀렉터를 사용할 때 지원되는 연산자는 =와 ==입니다.

다음 예시는 모든 네임스페이스에서 default 티어의 모든 StagedNetworkPolicy 리소스를 조회하는 방법을 보여줍니다.

kubectl get stagednetworkpolicy.p --field-selector spec.tier=default --all-namespaces
레이블 셀렉터(Label selector)

레이블 셀렉터를 사용할 때 지원되는 연산자는 =, ==, IN입니다.

다음 예시는 모든 네임스페이스에서 default와 net-sec 티어의 모든 StagedNetworkPolicy 리소스를 조회하는 방법을 보여줍니다.

kubectl get stagednetworkpolicy.p -l 'projectcalico.org/tier in (default, net-sec)' --all-namespaces

더 알아보기 (Learn more)

StagedNetworkPolicy는 정책을 실제 적용 전에 미리 검토해 볼 수 있는 "드라이런" 도구입니다. 정책을 티어로 묶어 순서를 관리하는 구조도 함께 익혀두면 좋습니다. 실제 트래픽 강제가 필요하면 같은 구조의 NetworkPolicy로 전환하세요.