호스트와 VM 보호하기
호스트 엔드포인트를 대상으로 하는 규칙을 작성해 Calico Open Source 정책으로 Kubernetes 호스트와 베어메탈 노드를 보호하는 방법을 안내해요.
출처: 문서
본문
큰 그림
Calico 네트워크 정책을 사용해 호스트와 VM 사이의 트래픽을 제한해요.
가치
호스트와 외부 세계 사이의 트래픽을 제한하는 것은 Calico만의 고유한 기능이 아니에요. 많은 솔루션이 이 기능을 제공해요. 하지만 Calico로 호스트를 보호하는 장점은 워크로드와 동일한 Calico 정책 구성을 사용할 수 있다는 점이에요. 도구를 하나만 배우면 돼요. 클러스터 전체 정책을 작성하면 모든 호스트에 즉시 적용돼요.
개념
호스트와 워크로드
Calico 구성의 맥락에서 워크로드는 Kubernetes에서 실행되는 컨테이너화된 컴퓨팅 인스턴스예요. 호스트는 Kubernetes 클러스터의 노드 역할을 하거나 Kubernetes 밖에서 애플리케이션 워크로드를 실행하는 컴퓨터나 가상 머신(VM)이에요. Calico는 워크로드와 호스트 모두에 대해, 그 호스트가 온프레미스 서버든 퍼블릭 클라우드의 VM이든, 일관된 방식으로 네트워크 정책을 적용하고 가시성을 제공할 수 있다는 점에서 독특해요.
호스트 엔드포인트
각 호스트에는 외부와 통신하는 데 사용하는 하나 이상의 네트워크 인터페이스가 있어요. Calico 네트워크 정책으로 이런 인터페이스(호스트 엔드포인트라고 불러요)를 보호할 수 있어요. Calico 호스트 엔드포인트는 라벨을 가질 수 있고, 워크로드 엔드포인트의 라벨과 동일하게 동작해요. 네트워크 정책 규칙은 라벨 셀렉터를 사용해 워크로드 엔드포인트와 호스트 엔드포인트 모두에 적용될 수 있어요.
Failsafe 규칙
없거나 잘못 구성된 네트워크 정책 때문에 호스트 연결을 실수로 모두 끊기 쉬워요. 이를 피하려고 Calico는 모든 호스트 엔드포인트에서 열려 있는 기본/구성 가능한 포트의 failsafe 규칙을 제공해요.
워크로드에서 호스트로 가는 트래픽의 기본 동작
기본적으로 Calico는 워크로드에서 자신의 로컬 호스트로의 모든 연결을 차단해요. 간단한 파라미터로 워크로드 엔드포인트에서 로컬 호스트로 가는 연결을 drop, return, accept 중 무엇으로 할지 제어할 수 있어요.
Calico는 호스트에서 실행되는 프로세스에서 호스트의 게스트 워크로드로 가는 모든 연결은 허용해요. 덕분에 호스트 프로세스가 게스트 워크로드에 대해 헬스 체크와 디버깅을 실행할 수 있어요.
외부 트래픽과 호스트 사이의 기본 동작
호스트 엔드포인트가 추가됐는데 네트워크 정책이 없다면, Calico의 기본 동작은 해당 엔드포인트를 드나드는 트래픽을 거부하는 것이에요(failsafe 규칙이 허용하는 트래픽 제외). 호스트 엔드포인트의 경우 Calico는 네트워크 정책에서 명시적으로 알려준 인터페이스의 트래픽만 차단해요. 다른 인터페이스의 트래픽은 무시해요.
기타 호스트 보호
Calico의 설계 일관성 측면에서 다음 사용 사례가 궁금할 수 있어요.
Calico는 워크로드로부터 로컬 호스트를 보호하나요?
네. DefaultEndpointToHostAction이 워크로드가 자신의 로컬 호스트에 접근할 수 있는지 제어해요.
Calico는 워크로드를 그것이 실행 중인 호스트로부터 보호하나요?
아니요. Calico는 호스트가 그 호스트에서 실행 중인 워크로드에 만드는 연결을 허용해요. Kubernetes 같은 일부 오케스트레이터는 워크로드 헬스 체크를 위해 이 연결성에 의존해요. 게다가 로컬 호스트에서 실행되는 프로세스는 로컬 Calico 정책을 우회할 만큼 충분한 권한을 갖고 있는 경우가 많아요. 호스트의 root 네트워크 네임스페이스에서 실행을 허용하는 프로세스는 매우 신중하게 선택하세요.
시작하기 전에...
이미 Kubernetes용 Calico를 실행 중이라면 바로 진행할 수 있어요. 호스트 보호만을 위해 클러스터에 속하지 않은 머신에 Calico를 설치하고 싶다면 Non-cluster hosts를 참고하세요.
방법
실수로 호스트 연결을 모두 끊는 일 피하기
없거나 잘못 구성된 네트워크 정책 때문에 호스트 연결을 실수로 모두 끊는 일을 피하려고, Calico는 모든 호스트 엔드포인트에서 특정 포트와 CIDR을 열어두는 failsafe 규칙을 사용해요.
다음 표를 검토해 기본값이 여러분의 구현에 맞는지 판단하세요. 맞지 않다면 Felix 구성의 FailsafeInboundHostPorts와 FailsafeOutboundHostPorts 파라미터로 기본 포트를 변경하세요.
| Port | Protocol | CIDR | Direction | Purpose |
|---|---|---|---|---|
| 22 | TCP | 0.0.0.0/0 | Inbound | SSH access |
| 53 | UDP | 0.0.0.0/0 | Outbound | DNS queries |
| 67 | UDP | 0.0.0.0/0 | Outbound | DHCP access |
| 68 | UDP | 0.0.0.0/0 | Inbound | DHCP access |
| 179 | TCP | 0.0.0.0/0 | Inbound & Outbound | BGP access (Calico networking) |
| 2379 | TCP | 0.0.0.0/0 | Inbound & Outbound | etcd access |
| 2380 | TCP | 0.0.0.0/0 | Inbound & Outbound | etcd access |
| 6443 | TCP | 0.0.0.0/0 | Inbound & Outbound | Kubernetes API server access |
| 6666 | TCP | 0.0.0.0/0 | Inbound & Outbound | etcd self-hosted service access |
| 6667 | TCP | 0.0.0.0/0 | Inbound & Outbound | etcd self-hosted service access |
정책으로 호스트 트래픽 제한하기
1단계: 호스트 트래픽을 제한하는 정책 만들기
failsafe 규칙이 호스트 연결이 모두 사라지는 상황을 막아주긴 하지만, 호스트 트래픽을 제한하는 GlobalNetworkPolicy를 만드는 것이 좋아요.
다음 예시에서는 모든 워커 노드(라벨로 정의)에 적용되는 GlobalNetworkPolicy를 사용해요. 정의된 "관리" 서브넷에서 오는 ingress SSH 접근을 허용해요. ICMP와 TCP 포트 10250(기본 kubelet 포트)의 ingress 트래픽도 허용해요. egress 트래픽은 특정 IP의 etcd로의 트래픽과, DNS와 DHCP를 위한 UDP 포트 53과 67을 허용해요.
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: k8s-worker
spec:
selector: "role == 'k8s-worker'"
order: 0
ingress:
- action: Allow
protocol: TCP
source:
nets:
- '<your management CIDR>'
destination:
ports: [22]
- action: Allow
protocol: ICMP
- action: Allow
protocol: TCP
destination:
ports: [10250]
egress:
- action: Allow
protocol: TCP
destination:
nets:
- '<your etcd IP>/32'
ports: [2379]
- action: Allow
protocol: UDP
destination:
ports: [53, 67]
2단계: 호스트 엔드포인트 만들기
정책으로 보호하려는 각 호스트 엔드포인트마다 HostEndpoint 객체를 만들어야 해요. 그러려면 인터페이스를 소유한 호스트의 Calico 노드 이름이 필요한데, 대부분의 경우 호스트의 호스트명과 같아요.
다음 예시에서는 my-host라는 호스트의 eth0 인터페이스, IP 10.0.0.1에 대한 HostEndpoint를 만들어요. node: 값은 Calico 노드 객체에 사용된 호스트명과 일치해야 한다는 점에 유의하세요.
HostEndpoint가 만들어지면 정책이 마련되어 있지 않은 한 해당 인터페이스를 드나드는 트래픽은 drop돼요.
apiVersion: projectcalico.org/v3
kind: HostEndpoint
metadata:
name: my-host-eth0
labels:
role: k8s-worker
environment: production
spec:
interfaceName: eth0
node: my-host
expectedIPs: ['10.0.0.1']
워크로드 엔드포인트에서 호스트로 가는 트래픽의 기본 동작 제어하기
기본 Calico 동작은 (워크로드에 적용된 egress 정책을 통과한 후) 워크로드에서 자신의 로컬 호스트로 가는 모든 연결을 차단해요. Felix 구성의 DefaultEndpointToHostAction 파라미터로 이 동작을 바꿀 수 있어요.
이 파라미터는 IP 테이블 수준에서 동작하며, 패킷 동작을 Drop(기본값), Accept, Return 중에서 지정할 수 있어요.
모든 호스트에 대해 이 파라미터를 바꾸려면 "default"라는 이름의 FelixConfiguration 객체를 편집해요.
-
편집할 객체의 사본을 구해요.
calicoctl get felixconfiguration default --export -o yaml > default-felix-config.yaml -
파일을 텍스트 편집기로 열고 defaultEndpointToHostAction 파라미터를 추가해요. 예를 들면:
apiVersion: projectcalico.org/v3 kind: FelixConfiguration metadata: name: default spec: ipipEnabled: true logSeverityScreen: Info reportingInterval: 0s defaultEndpointToHostAction: Accept -
클러스터의 FelixConfiguration을 업데이트해요.
calicoctl apply -f default-felix-config.yaml
추가 리소스
- Kubernetes node ports에 정책 적용하기
- Calico가 관리하는 호스트 엔드포인트로 Kubernetes 노드 보호하기
- DoS 공격 방어하기
- 글로벌 네트워크 정책
- 호스트 엔드포인트
더 알아보기 (Learn more)
호스트 보호의 핵심은 호스트 엔드포인트예요. HostEndpoint를 만드는 순간 해당 인터페이스 트래픽이 정책의 통제를 받기 때문에, failsafe 규칙으로 SSH·DNS·BGP 같은 필수 연결을 지키면서 정책을 점진적으로 좁혀 가는 접근이 안전해요.