8W - 실리움 보안
개요
마지막으로 다루는 내용은 보안이다.
이번 주차는 실리움에서 제공하는 보안 기능과, isovalent에서 만든 다른 오픈소스인 Tetragon을 다룬다.
보안 관련 기능들은 이전 주차를 거치면서 몇 가지 이미 본 것들이 있어 조금 겹치기도 할 것이다.
이 문서에서는 먼저 실리움에서 제공하는 보안 기능들을 알아본다.
실리움에서 제공하는 보안 관련 기능은 크게 다음과 같이 정리할 수 있다.
- 신원 부여 - 신원을 기반으로 다양한 정책과 기능을 제공한다.
- 네트워크 정책 - Network Policy를 이용한 방화벽 정책
- 기본적으로는 신원을 기반으로 제어하며 이는 L3 수준의 정책에 해당한다.
- 그러나 여기에 포트, 프로토콜이나 어플리케이션 레벨의 인증 방식에 대해서도 설정을 적용할 수 있기에 L4, L7 수준의 정책도 가능하다.
- 기타
신원(identity) 부여
실리움은 네트워크 계층 별로 다양한 보안 정책 기능을 제공한다.
L3 레벨에서는 신원 기반 보안을 제공하는데, IP 자체를 신원으로 사용하지는 않는다.
같은 신원에 여러 IP가 묶일 수도 있고, IP의 가변성은 클라우드 네이티브 환경의 기본 문법 수준의 전제이기 때문이다.
대신 위와 같이 관리자가 지정한 역할을 기반으로 신원을 부여하며, 이 신원이 보안 정책의 적용 대상이 된다.
이때 신원은 각 네트워크 대상들이 가진 라벨을 기반으로 결정된다.
아래 네트워크 정책에서 조금 더 자세히 보겠으나, 트래픽 정책은 전부 stateful 기반으로 egress와 ingress 트래픽에 대해 적용 가능하다.[1]
또한 아무 정책이 없으면 기본적으로 모든 통신이 허용되며, 정책이 하나라도 생기는 순간부터 규칙에 매핑되지 않는 모든 통신은 거부된다.
엔드포인트 라이프사이클
신원 기반으로 네트워크 정책을 적용하기 이전에, 먼저 모든 네트워크의 대상들은 고유한 엔드포인트를 가진다.
에이전트는 이 엔드포인트에 대해 신원을 부여하며, 신원을 부여하는 과정에는 다음의 단계가 존재한다.[2]
restoring
- 엔드포인트가 실리움 시작 이전에 생성됐을 때, 해당 엔드포인트의 네트워크 설정을 확인하여 복구하는 상태waiting-for-identity
- 엔드포인트에 고유한 신원을 부여되기 전 상태waiting-to-regenerate
- 신원이 부여된 후 네트워크 설정이 (재)생성되기 전 상태regenerating
- 네트워크 설정이 (재)생성되고 있는 상태로, eBPF 설정 작업도 포함된다.ready
- 네트워크 설정까지 완료된 상태disconnecting
- 엔드포인트가 삭제되는 상태disconnected
- 삭제됨
신원 관리는 원래 각 노드의 에이전트가 알아서 관리하는 방식으로 이뤄진다.[3]
그러나 이 방식은 몇 가지 우려사항이 존재한다.
- 복수의 에이전트가 같은 라벨 집합을 가진 엔드포인트에 대해 동시에 신원을 부여하는 작업이 일어날 수 있다.
- 신원은 ebpf 맵에 저장되기에 클러스터 내에서 최대 사이즈가 한정된다.
최근에는 이러한 문제를 해소할 수 있도록 오퍼레이터에서 신원을 중앙 관리하는 모드가 베타 모드로 나온 상태이다.
헬름으로 identityManagementMode=operator
로 설정하여 활성화할 수 있다.
기존 방식에서 마이그레이션을 하고자 한다면, 먼저 모드를 both
로 세팅한 후 오퍼레이터를 재기동한다.
이후 모드를 operator
로 설정하고 에이전트를 재기동하면 된다.
다시 기존 방식으로 돌아가고자 할 때도 비슷한 순서를 거치면 된다.
네트워크 정책
이제 만들어낸 신원을 보안에 어떻게 활용하는지 본격적으로 살펴본다.
실리움에서 정책을 적용할 때는 네트워크 폴리시 리소스를 만들면 된다.[4]
신원을 기반으로 정책을 적용할 수는 있으나, 꼭 신원에 기반해 정책을 만드는 것만은 아니다.
또한 신원은 접근 제어 뿐 아니라 관측 가능성에 대해서도 사용되는 요소이다.
그러나 실리움은 쿠버 표준 네트워크 폴리시와 별도로 개별적인 커스텀 리소스를 제공한다.
위와 같이 다양한 기능을 제공하기 때문이다.
일단 정책의 대상으로 삼을 수 있는 종류가 훨씬 다양하고, 어떤 것을 기반으로 트래픽을 제어할 것인지 훨씬 세밀하게 조정할 수 있다.
이것 역시 2주차 모니터링 실습 당시 엔보이로 트래픽이 흘러가도록 하기 위해 세팅한 적 있던 부분이다.
정책은 잘못 적용했다간 피를 보는 경우가 많다..
그래서 네트워크 폴리시 에디터와 같이 미리 리소스를 만들어보고 결과를 확인해가면서 작업을 하는 것이 좋다.
실리움 네트워크 폴리시 뿐만 아니라 쿠버 표준 네트워크 폴리시를 만드는 실습도 할 수 있으니 익숙치 않다면 여기에서 감을 익히는 것을 추천한다.
L7 정책 적용 방식 - 엔보이
위 그림을 보면 알 수 있듯이 실리움의 네트워크 정책에서는 다양한 L7 프로토콜을 기반으로 정책을 적용할 수 있다.
L7 기반의 정책은 엔보이를 기반으로 적용되며, 에이전트는 L7 수준의 정책이 생겼을 때 관련한 트래픽을 엔보이로 보낼 수 있도록 ebpf 프로그래밍을 수행한다.[5]
에이전트와 엔보이는 UDS로 통신하며 에이전트가 XDS api를 통해 설정을 관리하기에, 레드햇 배포판이라면 SELinux에서 해당 통신에 대한 제어를 막지 않도록 설정해야 한다.
이때 엔보이는 기본 설정 상에서는 실리움 에이전트 파드 내부의 하위 프로세스로 실행된다.
하지만 당연히 이러한 방식은 자원 경합, 관리의 불편함을 야기하므로 실리움에서는 별도로 엔보이 데몬셋을 배치하는 모드를 지원한다.
헬름 설정으로 envoy.enabled=true
를 두면 별도 엔보이가 배치되며, 이는 다음의 장점을 가진다.
- 실리움 에이전트와 별도의 라이프사이클(헬스체크, 업데이트 독립적)
- CPU, 메모리 별도 관리 가능
- 로그가 혼합되지 않음
기본 정책 모드
대부분의 방화벽 정책이 그러하듯이, 실리움 역시 아무 정책이 없을 때는 모든 트래픽이 기본 허용된다.
그러나 정책이 하나라도 만들어지는 순간 조건에 매칭되지 않는 모든 트래픽이 거부되기에 주의가 필요하다.
실리움에서는 기본 정책 적용 모드를 헬름 변수 enable-policy: {}
와 같은 식으로 지정할 수 있다.[6]
정책 적용 모드에는 다음의 세 가지 종류가 있다.
- default
- 정책이 만들어지기 전 모든 트래픽이 허용된다.
- 정책이 만들어지는 순간 매칭되지 않는 트래픽은 거부된다.
- ingress, egress 별도로 적용된다.
- always
- 정책이 없어도 기본적으로 정책 강화가 적용된다.
- 헬스체크 등의 트래픽도 막히므로, 별도로 모든 리소스를 직접 만들어 적용해주어야 한다.
- never
- 정책 비활성화, 즉 정책을 사용하지 않으므로 모든 트래픽이 상시 허용된다.
일일히 방화벽 정책을 설정하는 게 꽤나 번거롭기 때문에, 대부분은 default 모드를 사용하게 될 것이다.
엄격하게 정책을 관리할 조직에서는 always를 사용하는 것도 좋은 선택지가 될 것이다.
default 모드일 때, 정책을 만들었을 때 기본 정책 적용을 enableDefaltDeny
로 커스텀할 수 있다.
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: intercept-all-dns
spec:
endpointSelector:
matchExpressions:
- key: "io.kubernetes.pod.namespace"
operator: "NotIn"
values:
- "kube-system"
- key: "k8s-app"
operator: "NotIn"
values:
- kube-dns
enableDefaultDeny:
egress: false
ingress: false
egress:
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: TCP
- port: "53"
protocol: UDP
rules:
dns:
- matchPattern: "*"
위와 같이 설정하면 정책이 생성되더라도 다른 트래픽을 거부하는 설정이 적용되지 않는다.
명확하게 정책을 적용하면서 발생할 수 있는 실수가 우려될 때 사용하기에 유용하다.
다만 L7 레벨의 트래픽에 대해서는 이 필드가 적용되지 않으므로 주의할 필요가 있다.
정책은 화이트리스트 기반으로, 허용할 트래픽을 지정하는 방식이며 합집합 기반으로 적용된다.
다음은 Go에서 정책 리소스를 다루는 구조체 형식이다.[7]
type Rule struct {
// 엔드포인트 셀렉터와 노드 셀렉터 중 하나는 반드시 명시돼야 하며 상호 배제적이다.
// +optional
EndpointSelector EndpointSelector `json:"endpointSelector,omitempty"`
// 노드 셀렉터는 CiliumClusterWideNetworkPoliciy에만 사용될 수 있다.
// +optional
NodeSelector EndpointSelector `json:"nodeSelector,omitempty"`
// 당연하겠지만 둘 다 없으면 실제로 이 정책은 아예 적용되지 않는다.
// +optional
Ingress []IngressRule `json:"ingress,omitempty"`
// +optional
Egress []EgressRule `json:"egress,omitempty"`
// 정책을 식별하거나 메타데이터를 저장할 때 사용되는 라벨
// 쿠버네티스에서 import된 정책은 io.cilium.k8s.policy.name=NAME의 라벨이 붙는다.
// +optional
Labels labels.LabelArray `json:"labels,omitempty"`
// 사람이 보기 편하라고 만드는 설명 필드
// +optional
Description string `json:"description,omitempty"`
}
네트워크 정책의 종류는 워낙 많고 문서에서도 실습의 형식으로 각 정책 케이스를 보여주고 있기에, 자세한 설정은 실습에서 확인하도록 한다.
실습 환경 구성
이번 주차는 다시 Vagrant를 이용해서 진행한다.
이후 세팅할 Tetragon의 경우에 컨테이너를 노드로 삼는 KIND로는 실습의 한계가 있기 때문이다.
###############################################################################
# 1. vagrant
###############################################################################
vagrant up
vagrant scp k8s-ctr:config config
mv ~/.kube/config ~/.kube/config.backup
mv config ~/.kube/config
###############################################################################
# 2. check
###############################################################################
cilium status
kaf y0-check.yaml
for i in ctr w1 w0 ; do echo ">> node : k8s-$i <<"; vagrant ssh k8s-$i -c 'ip -c route' ; echo; done
kubectl exec -it curl-pod -- sh -c 'while true; do curl -s --connect-timeout 1 webpod | grep Hostname; echo "---" ; sleep 1; done'
자세한 설정은 이전과 달라진 게 없으므로 레포를 참조하자.
통신 간 암호화 실습
내용이 상대적으로 짧으니 이 부분부터 실습해본다.
IPSec, 또는 Wireguard를 이용해 암호화를 진행할 수 있다.
어플리케이션 입장에서는 서비스 메시의 암호화와 같이 전혀 해당 사항을 알 수 없기에 투명한 암호화(transparent encryption)라고 표현한다.
두 방식은 각각 제한 사항이 존재한다.
- ipsec
- bpf 호스트 라우팅 환경에서 적용되지 않는다.
- 싱글 cpu를 사용하여 암복호화를 진행하여 트래픽 처리 지연을 야기할 수 있다.
- wireguard[8]
- 터널 라우팅 모드와 함께 쓸 시 트래픽은 결국 두 번 캡슐화된다.
실습에서는 제약 사항이 상대적으로 적은 wireguard를 사용해본다.
wireguard는 최근 리눅스 커널 모듈로 정식으로 들어왔기 때문에 모듈 여부를 확인할 수 있다.
uname -ar
grep -E 'CONFIG_WIREGUARD=m' /boot/config-$(uname -r)
본격적으로 와이어가드 세팅을 진행한다.
helm upgrade cilium cilium/cilium --version 1.18.1 --namespace kube-system --reuse-values \
--set encryption.enabled=true --set encryption.type=wireguard
kubectl -n kube-system rollout restart ds/cilium
세팅이 되면 각 노드의 커널에는 알아서 wireguard 모듈이 로딩된다.
실리움 설정으로 확인해 보자면..
cilium config view | grep -i wireguard
kubectl exec -it -n kube-system ds/cilium -- cilium status | grep Encryption
kubectl exec -it -n kube-system ds/cilium -- cilium encrypt status
각 에이전트는 특정 인터페이스를 열고, 공유할 공개키를 가지고 있다.
노드의 개수 만큼 피어가 잡히는 것도 확인할 수 있다.
vagrant ssh k8s-ctr -c 'ip -c a s cilium_wg0'
vagrant ssh k8s-ctr -c 'ip -c rule show'
vagrant ssh k8s-ctr -c 'sudo wg'
vagrant ssh k8s-ctr -c 'sudo wg show all public-key'
vagrant ssh k8s-ctr -c 'sudo wg show all private-key'
vagrant ssh k8s-ctr -c 'sudo wg show all preshared-keys'
vagrant ssh k8s-ctr -c 'sudo wg show all endpoints'
vagrant ssh k8s-ctr -c 'sudo wg show all transfer'
와이어가드가 활성화되면 실리움에서는 와이어가드 트래픽을 송수신할 인터페이스를 새로 만든다.
wg는 와이어가드를 조작하는 cli 툴이다.
보다시피 각 피어와 해당 피어들이 관리할 ip 대역 정보 등의 표시된다.
각각의 엔드포인트도 보이는데, 와이어가드의 호스트들은 서로를 피어값으로만 인지한다.
그래서 이후 엔드포인트에 변동이 생기더라도 이미 고유한 키를 가지고 있는 상대에 대해서 피어 값이 변동되지 않는다면 그대로 동일한 상대로 인식한다.
preshared key가 추가 보안을 위해 두는 대칭키라도 되는가 했는데, 그냥 피어의 키를 공유받은 정보를 담고 있는 건가 보다.
각 노드의 와이어가드는 저마다의 공개키를 가지며, 해당 값은 실리움 노드 리소스 어노테이션으로도 반영된다.
kubectl get cn -o yaml | grep annotations -A1
다음으로는 트래픽을 추적해본다.
먼저 기본적인 통신은 문제 없이 가능하다.
허블로 뭔가 볼 수 있는 게 없을까 했는데, 허블로는 추적하기 어려운 것 같다.
아예 노드에 접속해 패킷을 떠서 확인해본다.
tcpdump -eni any udp port 51871 -w /tmp/wg.pcap
termshark -r /tmp/wg.pcap
기본 포트로 51871 UDP를 사용하는 것을 확인할 수 있다.
초반에는 먼저 핸드쉐이크를 통해 암호 터널을 구성하고, 이후부터는 트래픽을 암호화한 채로 송수신한다.
와이어가드의 특징 중 하나인 지속 커넥션을 두지 않고 빠르게 핸드쉐이크를 수립하여 통신하는 모습이다.
다만 아예 연결 유지를 통신이 일체 없나 했는데, 서로 헬스체크 용도 정도의 통신은 주기적으로 주고받는 게 아닌가 싶다.
다음과 같이 정리한다.
helm upgrade cilium cilium/cilium --version 1.18.1 --namespace kube-system --reuse-values \
--set encryption.enabled=false
kubectl -n kube-system rollout restart ds/cilium
신원 실습
모든 워크로드, 네트워크 주체들은 엔드포인트를 가지고, 라벨을 기반으로 특정 보안 신원에 매칭된다.
kubectl get ciliumendpoints.cilium.io -A
kubectl get ciliumidentities.cilium.io -oyaml
엔드포인트를 기반으로 보면 위와 같이 상태에 대한 체크도 가능하다.
또 특정 신원이 부여되는데 사용된 라벨(security-labels)이 무엇인지도 확인 가능하다.
신원 수정하기
신원은 라벨을 기반으로 생성 및 관리되므로 라벨을 수정하면 신원 역시 수정되는 과정을 거친다.
k label po curl-pod app=curl --overwrite
kubectl get ciliumendpoints.cilium.io -w
라벨에 변경사항이 발생하자 상태가 waiting-for-identity로 바뀐 것이 보인다.
이후에는 아예 새로운 신원 번호를 부여받았다.
혹시나 하여 아예 watch를 걸어두고 봤는데, 바뀌는 작업 자체는 10초 가량 걸린 것 같다.
특이하다고 생각한 지점으로, curl2로 app 라벨을 바꿨다가 다시 curl로 원복시키자 이전과 동일한 신원 번호를 부여받았다.
에이전트를 뒤적거리면 해당 사항의 이유를 조금 더 자세히 알 수 있다.
kubectl exec -it -n kube-system ds/cilium -- cilium identity list
신원 리스트에는 이전에 만들어진 신원 데이터를 그대로 보존하고 있다.
신원에 최대 개수 제한이 존재할 텐데, 쓰이지 않는 신원 번호는 알아서 삭제되고 업데이트 되는 걸까?
신원은 모든 에이전트가 공유하지만, 엔드포인트 자체는 자신의 노드에 존재하는 워크로드에 대해서만 추적하는 것을 확인할 수 있다.
kubectl exec -it -n kube-system ds/cilium -- cilium endpoint list
조금 더 빠르게 테스트하기 위해 간단하게 세팅한다.
export CILIUMPOD0=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-ctr -o jsonpath='{.items[0].metadata.name}')
export CILIUMPOD1=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-w1 -o jsonpath='{.items[0].metadata.name}')
export CILIUMPOD2=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-w2 -o jsonpath='{.items[0].metadata.name}')
echo $CILIUMPOD0 $CILIUMPOD1 $CILIUMPOD2
# 단축키(alias) 지정
alias c0="kubectl exec -it $CILIUMPOD0 -n kube-system -c cilium-agent -- cilium"
alias c1="kubectl exec -it $CILIUMPOD1 -n kube-system -c cilium-agent -- cilium"
alias c2="kubectl exec -it $CILIUMPOD2 -n kube-system -c cilium-agent -- cilium"
alias c0bpf="kubectl exec -it $CILIUMPOD0 -n kube-system -c cilium-agent -- bpftool"
alias c1bpf="kubectl exec -it $CILIUMPOD1 -n kube-system -c cilium-agent -- bpftool"
alias c2bpf="kubectl exec -it $CILIUMPOD2 -n kube-system -c cilium-agent -- bpftool"
엔드포인트 관련 테스트를 몇 가지 해보고 싶어 명령어들을 넣어봤지만 생각보다 잘 되진 않았다.
왜인가 했더니 enpoint 관련 명령어는 identity가 아니라 정말 엔드포인트를 기준으로 입력해야 하기 때문이었다.
라벨을 조작했던 curl-pod의 endpoint 정보를 보면 유저가 직접 붙인 라벨이 무엇인지, 어떤 설정이 들어가 있는데 확인된다.
클러스터를 거치지 않고 라벨을 직접 추가하는 것도 가능하다.
이 경우 어떤 소스로부터 생긴 라벨인지 인식하지 않아 unspec으로 출처가 나오는 것을 볼 수 있다.
이 라벨 역시 identity를 업데이트하는 요소로 사용된다.
그럼 아예 클러스터 라벨로 붙어있던 것을 없애면 어떻게 되는가?
Disabled로 표시되는 라벨은 이후 바로 출력도 되지 않게 삭제된다.
실제 신원 번호 역시 수정됐다.
그러나 클러스터에서 해당 라벨은 그대로 남아있는 것을 볼 수 있다.
이 라벨은 이제 수정을 하더라도 신원이 변동되지 않는다.
identity의 잦은 변경은 부하를 유발하므로 적절하게 신원에 필요한 라벨을 제한하는 전략이 유효할 것이다.
신원 무관 라벨 전역 설정
그런데 위에서 사용한 방식은 각 엔드포인트에 대해 수정을 했기 때문에 실제 활용하기에는 번거로울 것으로 예상된다.
그래서 실리움에서는 아예 전체 설정으로 신원과 연관되지 않도록 라벨을 설정하는 필드를 마련해두고 있다.[9]
먼저 비활성화시켰던 라벨을 다시 활성화할 때는 아래와 같이 k8s란 출처를 명시해서 달아줘야 한다.
c0 endpoint labels 99 -a k8s:test
안 그러면 계속 unspec의 라벨이라고 나오게 되는데, 이는 클러스터의 라벨과 별개로 작용되기에 클러스터 라벨을 수정해도 해당 사항은 계속 비활성화된 채로 남게 된다.
수정 자체는 간편하게 cilium-config 컨피그맵을 수정해주면 된다.
다음과 같이 제외하고 싶은 라벨 앞에는 느낌표를 붙여주면 된다.
해당 사항이 적용되기 위해서는 에이전트를 재실행해줘야만 한다.
돌고 돌아 curl-pod에 test라는 라벨이 없던 5317 신원을 다시 받은 것을 확인할 수 있다.
참고로 여태 엔드포인트에 발생했던 변동사항을 로그로 확인해볼 수 있다.
c0 endpoint log 99
에이전트를 재시작하며 이전 로그가 날아가긴 했는데, 신원이 바뀔 때마다 로그가 축적된다.
엔드포인트와 신원을 계속 건드리다보니 확실하게 성능 최적화를 위해 고려할 만한 사항이 두 가지 있다.
- 엔드포인트마다 이력 정보가 남고 많은 개별 설정이 들어가기 때문에 별도의 분산 키값 저장소에 정보를 두는 것이 Etcd 부하를 줄이는데 도움될 것이다.
- 에이전트들이 개별적으로 신원과 엔드포인트를 관리하면 부하가 많이 발생할 확률이 높으므로, 오퍼레이터에서 관리하는 것이 유효하다.[3:1]
네트워크 정책 적용 실습
다음으로는 본격적으로 네트워크 정책들을 실습해본다.
L3
사용 가능한 필드가 많아서 전체적인 정리를 먼저 해본다.
egress 기준으로는 to 접두사가 붙는 필드들이 있는데 반대로 ingress라면 접두사로 from이 붙는다는 것을 염두하자.
toEndpoints: # 기본 라벨 기반
- matchLabels:
toServices: # 서비스 대상
- k8sService:
serviceName:
namespace:
- k8sServiceSelector:
selector:
matchLabels:
toEntities: # 특정 그룹 대상
- kube-apiserver
- host # 로컬 호스트
- remote-node # 로컬이 아닌 모든 원격 노드
- ingress # L7 트래픽 처리하는 엔보이
- init # 신원을 받기 이전의 상태 엔터티
toNodes: # 노드 라벨 기반. --enable-node-selector-labels=true가 돼야 노드마다 신원이 부여되며 설정 가능해짐
- matchLabels:
toCIDR:
toCIDRSet:
- cidr: 10.0.0.0/8
except:
- 10.96.0.0/12
toFQDNs: # dns 기반
- matchName
- matchPattern
L3 라면서 DNS 기반 필드가 있다는 것이 의아할 수 있다.
이건 외부로 나가는 트래픽에 대한 제한으로, 에이전트가 DNS 프록시 역할 수행하도록 설정돼있을 때 에이전트가 도메인 질의를 한 후 돌아온 응답을 어플리케이션으로 돌려보내지 않는 방식으로 동작한다.
그래서 dns 요청 자체를 제한하는 것은 아니나 결과적으로 응답을 반환하지 않으니 실질적인 제한을 가할 수 있다.
이 방식은 에이전트가 어느 정도 L7 기능을 수행해야 하기 때문에 --enable-l7-proxy=true
옵션이 요구된다.
L4
L4 예제는 포트, icmp 프로토콜 기반이다.
toPorts:
- ports:
- port: "80"
protocol: TCP
- port: "80"
endPort: 444 # 80~444 포트 허용
protocol: TCP
serverNames: # SNI 기반
- one.one.one.one
icmps:
- fields:
- type: 8
family: IPv4
- type: EchoRequest
family: IPv6
여기또 특이한 것이 serverNames
로, 이는 TLS 통신 시 SNI 헤더 값 기반으로 정책을 적용한다.
이것 역시 단순한 L4는 아니기에 L7 프록시 기능을 활성화해야만 적용된다.
L7
L7 영역 정책부터는 명확하게 엔보이로 트래픽이 전달되어 검증이 이뤄진다.
프로토콜로는 크게 HTTP, 카프카, DNS 3가지 범주로 나뉘며, L4를 위한 Port 필드 하위로 정책을 정의한다.
L7 정책의 특징은 패킷을 드랍하지 않고 가급적 명시적으로 프로토콜 별 에러 응답을 반환한다는 것이다.
# http
toPorts:
- ports:
- port: "80"
protocol: TCP
rules:
http:
- method: "GET"
path: "/public"
headers:
- 'X-My-Header: true'
# kafka
toPorts:
- ports:
- port: "9092"
protocol: TCP
rules:
kafka:
- role: "produce"
topic: "deathstar-plans"
- role: "produce"
topic: "empire-announce"
# dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchName: "cilium.io"
- matchPattern: "*.cilium.io"
- matchPattern: "*.api.cilium.io"
간단하게 위와 같은 방식으로 정책을 넣을 수 있다.
L3에서 본 응답을 버리는 DNS와 다르게, L7의 DNS는 DNS 요청을 날리는 것 자체를 원천 차단시킨다.
결론
실리움은 자체적으로 워크로드들의 신원을 관리하고 업데이트해주기에 보안 정책을 설정할 때 편한 지점이 있다.
여기에 세밀한 설정이 가능한 네트워크 정책 리소스가 있어서 높은 수준의 보안 강도를 달성할 수 있을 것으로 생각된다.
그러나 한편으로 위에서 보았듯 라벨이라는 충분히 가변적인 요소를 기반으로 신원을 설정하기 때문에 규모가 큰 클러스터일수록 많은 부하가 발생할 것으로 보인다.
이를 의식하고 최적화하는 고려가 필요할 것으로 보인다.
이전 글, 다음 글
하위 문서
이름 | is-folder | index | noteType | created |
---|---|---|---|---|
1W - 실리움 기본 소개 | false | 1 | published | 2025-07-19 |
1W - 클러스터 세팅 및 cni 마이그레이션 | false | 2 | published | 2025-07-19 |
1W - 기본 실리움 탐색 및 통신 확인 | false | 3 | published | 2025-07-19 |
2W - 허블 기반 모니터링 | false | 4 | published | 2025-07-26 |
2W - 프로메테우스와 그라파나를 활용한 모니터링 | false | 5 | published | 2025-07-26 |
3W - 실리움 기본 - IPAM | false | 6 | published | 2025-08-02 |
3W - 실리움 기본 - Routing, Masq, IP Frag | false | 7 | published | 2025-08-02 |
4W - 실리움 라우팅 모드 실습 - native, vxlan, geneve | false | 8 | published | 2025-08-09 |
4W - 실리움 로드밸런서 기능 - 서비스 IP, L2 | false | 9 | published | 2025-08-09 |
5W - BGP 실습 | false | 10 | published | 2025-08-16 |
5W - 클러스터 메시 | false | 11 | published | 2025-08-16 |
6W - 실리움 서비스 메시 - 인그레스 | false | 12 | published | 2025-08-23 |
7W - 실리움 성능 - 쿠버네티스 기본 | false | 13 | published | 2025-08-31 |
8W - 실리움 보안 | false | 14 | published | 2025-09-07 |
관련 문서
지식 문서, EXPLAIN
이름49 | is-folder | 생성 일자 |
---|---|---|
E-쿠버네티스 인증 실습 | false | 2025-01-21 16:09 |
E-로컬 ssh 서버 세팅 | - | 2024-00-13 |
E-openssl을 이용한 인증서 생성 실습 | false | 2025-03-22 12:47 |
E-Kyverno 기본 실습 | false | 2025-03-17 14:46 |
TLS | false | 2025-04-16 13:48 |
SockS | - | 2024-00-13 |
SSH | - | 2024-00-12 |
OIDC | false | 2025-01-13 22:48 |
OAuth | false | 2025-05-09 14:32 |
볼트 in 쿠버네티스 | false | 2025-04-14 09:35 |
Vault | true | 2025-04-11 10:36 |
암호 알고리즘 총괄 | false | 2025-03-15 12:30 |
code reuse attack | - | 2024-04-27 |
buffer overflow | - | 2024-04-27 |
TLS downgrade attack | - | 2024-04-27 |
Shamir Secret Sharing | false | 2025-04-11 12:32 |
Security | false | 2025-04-11 12:30 |
RBAC | false | 2025-01-19 12:42 |
JWT | false | 2025-05-05 08:00 |
sudo | false | 2024-06-13 18:25 |
openssl | false | 2025-01-18 13:12 |
cfssl | false | 2025-01-23 00:38 |
Secret | false | 2025-01-12 14:47 |
Vault Secret Operator | false | 2025-04-14 09:39 |
Cert Manager | false | 2025-03-15 17:25 |
시큐리티 | true | 2025-01-12 13:34 |
보안 체크리스트 | false | 2025-01-14 11:05 |
멀티 테넌시 | false | 2025-01-13 21:13 |
리눅스 커널 보안 제약 | false | 2025-01-14 00:41 |
Validation Admission Policy | false | 2025-03-17 11:02 |
ServiceAccount | false | 2025-01-13 16:18 |
Authorization | false | 2025-01-19 11:17 |
Audit | false | 2025-03-12 13:56 |
Admission Webhook | false | 2025-01-20 22:40 |
Admission Control | false | 2025-01-20 16:42 |
API 접근 제어 우회 | false | 2025-01-13 19:02 |
SPIFFE | false | 2025-05-04 20:06 |
Keycloak | false | 2025-01-27 10:21 |
Istio Security | true | 2025-05-04 19:58 |
Istio RequestAuthentication | false | 2025-05-04 20:16 |
Istio PeerAuthentication | false | 2025-05-04 20:00 |
Istio AuthorizationPolicy | false | 2025-05-04 20:19 |
Amazon Cognito | - | 2024-00-04 |
AWS Web Application Firewall | - | 2024-00-04 |
AWS Identity and Access Management | false | 2025-01-31 22:49 |
PKI | false | 2025-03-10 08:34 |
파드 시큐리티 스탠다드 | false | 2025-01-13 13:48 |
쿠버 RBAC | - | 2024-00-02 |
Authentication | false | 2025-01-13 21:15 |
기타 문서
Z0-연관 knowledge, Z1-트러블슈팅 Z2-디자인,설계, Z3-임시, Z5-프로젝트,아카이브, Z8,9-미분류,미완이름11 | 코드 | 타입 | 생성 일자 |
---|---|---|---|
T-각 네임스페이스 서비스 어카운트에 권한 바인딩 | Z3 | topic/temp | 2025-03-16 15:11 |
T-서비스 어카운트 토큰은 어떻게 인증되는가 | Z3 | topic/temp | 2025-03-16 15:31 |
나스 초기 세팅 | Z5 | project | 2024-12-11 23:21 |
6W - PKI 구조, CSR 리소스를 통한 api 서버 조회 | Z8 | published | 2025-03-15 12:21 |
6W - api 보안 2 - 인가, 어드미션 제어 | Z8 | published | 2025-03-16 00:15 |
3W - Public Key Infrastructure | Z8 | published | 2025-03-21 18:40 |
6W - api 구조와 보안 1 - 인증 | Z8 | published | 2025-03-15 15:39 |
5W - 이스티오 JWT 인증 | Z8 | published | 2025-05-11 00:03 |
5W - 이스티오 mTLS와 SPIFFE | Z8 | published | 2025-05-11 00:01 |
5W - 이스티오 인가 정책 설정 | Z8 | published | 2025-05-11 00:04 |
SSH 터널링 | Z9 | - | 2024-00-12 |
참고
https://docs.cilium.io/en/stable/security/network/policyenforcement/ ↩︎
https://docs.cilium.io/en/stable/security/policy/lifecycle/ ↩︎
https://docs.cilium.io/en/stable/network/kubernetes/identity-management-mode/ ↩︎ ↩︎
https://docs.cilium.io/en/stable/network/kubernetes/policy/ ↩︎
https://docs.cilium.io/en/stable/security/network/proxy/envoy/ ↩︎
https://docs.cilium.io/en/stable/security/policy/intro/#rule-basics ↩︎
https://docs.cilium.io/en/stable/security/network/encryption-wireguard/ ↩︎
https://docs.cilium.io/en/stable/operations/performance/scalability/identity-relevant-labels/#identity-relevant-labels ↩︎