IPv4/IPv6 이중 스택
IPv4/IPv6 이중 스택 (IPv4/IPv6 dual-stack)
Kubernetes를 사용하면 단일 스택 IPv4 네트워킹, 단일 스택 IPv6 네트워킹, 또는 두 네트워크 패밀리가 모두 활성화된 이중 스택 네트워킹을 구성할 수 있어요. 이 페이지에서는 그 방법을 설명할게요.
기능 상태: Kubernetes v1.23 [stable]
IPv4/IPv6 이중 스택 네트워킹은 Pod와 Service에 IPv4와 IPv6 주소를 모두 할당할 수 있게 해줘요.
IPv4/IPv6 이중 스택 네트워킹은 1.21부터 Kubernetes 클러스터에 기본적으로 활성화되어, IPv4와 IPv6 주소를 동시에 할당할 수 있게 해줘요.
지원되는 기능 (Supported Features)
Kubernetes 클러스터의 IPv4/IPv6 이중 스택은 다음 기능을 제공해요.
- 이중 스택 Pod 네트워킹(Pod당 단일 IPv4와 IPv6 주소 할당)
- IPv4와 IPv6 활성화 Service
- IPv4와 IPv6 인터페이스 모두를 통한 Pod의 클러스터 외부 이그레스 라우팅(예: 인터넷)
사전 요구사항 (Prerequisites)
IPv4/IPv6 이중 스택 Kubernetes 클러스터를 활용하려면 다음 사전 요구사항이 필요해요.
- Kubernetes 1.20 이상
이전 Kubernetes 버전으로 이중 스택 서비스를 사용하는 방법에 대한 정보는 해당 Kubernetes 버전의 문서를 참고하세요.
- 이중 스택 네트워킹에 대한 제공자 지원(클라우드 제공자든 아니든 Kubernetes 노드에 라우팅 가능한 IPv4/IPv6 네트워크 인터페이스를 제공할 수 있어야 해요)
- 이중 스택 네트워킹을 지원하는 네트워크 플러그인
IPv4/IPv6 이중 스택 구성하기
IPv4/IPv6 이중 스택을 구성하려면 이중 스택 클러스터 네트워크 할당을 설정해요.
- kube-apiserver:
--service-cluster-ip-range=<IPv4 CIDR>,<IPv6 CIDR>
- kube-controller-manager:
--cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR>--service-cluster-ip-range=<IPv4 CIDR>,<IPv6 CIDR>--node-cidr-mask-size-ipv4|--node-cidr-mask-size-ipv6기본값은 IPv4 /24, IPv6 /64
- kube-proxy:
--cluster-cidr=<IPv4 CIDR>,<IPv6 CIDR>
- kubelet:
--node-ip=<IPv4 IP>,<IPv6 IP>- 이 옵션은 베어 메탈 이중 스택 노드(
--cloud-provider플래그로 클라우드 제공자를 정의하지 않는 노드)에 필수예요. 클라우드 제공자를 사용하고 클라우드 제공자가 선택한 노드 IP를 재정의하려면--node-ip옵션을 설정하세요. - (레거시 내장 클라우드 제공자는 이중 스택
--node-ip를 지원하지 않아요.)
- 이 옵션은 베어 메탈 이중 스택 노드(
참고:
IPv4 CIDR의 예시:
10.244.0.0/16(물론 자체 주소 범위를 제공해야 해요)IPv6 CIDR의 예시:
fdXY:IJKL:MNOP:15::/64(형식을 보여주지만 유효한 주소는 아닙니다 — RFC 4193 참고)
Service (Services)
IPv4, IPv6, 또는 둘 다 사용할 수 있는 Service를 만들 수 있어요.
Service의 주소 패밀리는 기본적으로 첫 번째 service 클러스터 IP 범위(kube-apiserver의 --service-cluster-ip-range 플래그로 구성)의 주소 패밀리로 정해져요.
Service를 정의할 때 선택적으로 이중 스택으로 구성할 수 있어요. 원하는 동작을 지정하려면 .spec.ipFamilyPolicy 필드를 다음 값 중 하나로 설정해요.
SingleStack: 단일 스택 서비스예요. 컨트롤 플레인은 첫 번째로 구성된 service 클러스터 IP 범위를 사용해 Service의 클러스터 IP를 할당해요.PreferDualStack: 이중 스택이 활성화되면 Service에 IPv4와 IPv6 클러스터 IP를 모두 할당해요. 이중 스택이 활성화되지 않았거나 지원되지 않으면 단일 스택 동작으로 폴백해요.RequireDualStack: 이중 스택이 활성화되면 Service.spec.clusterIPs를 IPv4와 IPv6 주소 범위 모두에서 할당해요. 이중 스택이 활성화되지 않았거나 지원되지 않으면 Service API 객체 생성이 실패해요..spec.clusterIP를.spec.ipFamilies배열의 첫 번째 요소의 주소 패밀리를 기반으로.spec.clusterIPs목록에서 선택해요.
단일 스택에 사용할 IP 패밀리를 정의하거나 이중 스택에 대한 IP 패밀리의 순서를 정의하려면, Service에 선택 필드인 .spec.ipFamilies를 설정해 주소 패밀리를 선택할 수 있어요.
참고:
.spec.ipFamilies필드는 조건부로 변경 가능해요: 보조 IP 주소 패밀리를 추가하거나 제거할 수 있지만, 기존 Service의 기본 IP 주소 패밀리는 변경할 수 없어요.
.spec.ipFamilies를 다음 배열 값 중 하나로 설정할 수 있어요.
["IPv4"]["IPv6"]["IPv4","IPv6"](이중 스택)["IPv6","IPv4"](이중 스택)
나열한 첫 번째 패밀리가 레거시 .spec.clusterIP 필드에 사용돼요.
이중 스택 Service 구성 시나리오
이 예시들은 다양한 이중 스택 Service 구성 시나리오의 동작을 보여줘요.
새 Service의 이중 스택 옵션
- 이 Service 스펙은
.spec.ipFamilyPolicy를 명시적으로 정의하지 않아요. 이 Service를 만들면 Kubernetes는 첫 번째로 구성된service-cluster-ip-range에서 Service의 클러스터 IP를 할당하고.spec.ipFamilyPolicy를SingleStack으로 설정해요. (선택자가 없는 Service와 선택자가 있는 headless Service는 이와 같은 방식으로 동작해요.)
apiVersion: v1
kind: Service
metadata:
name: my-service
labels:
app.kubernetes.io/name: MyApp
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80
- 이 Service 스펙은
.spec.ipFamilyPolicy에PreferDualStack을 명시적으로 정의해요. 이중 스택 클러스터에서 이 Service를 만들면 Kubernetes는 서비스에 IPv4와 IPv6 주소를 모두 할당해요. 컨트롤 플레인은 Service의.spec을 업데이트해 IP 주소 할당을 기록해요..spec.clusterIPs필드가 기본 필드이고 할당된 두 IP 주소를 모두 포함해요..spec.clusterIP는 그 값이.spec.clusterIPs에서 계산되는 보조 필드예요.
apiVersion: v1
kind: Service
metadata:
name: my-service
labels:
app.kubernetes.io/name: MyApp
spec:
ipFamilyPolicy: PreferDualStack
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80
.spec.clusterIP필드의 경우 컨트롤 플레인은 첫 번째 service 클러스터 IP 범위와 같은 주소 패밀리의 IP 주소를 기록해요.- 단일 스택 클러스터에서는
.spec.clusterIPs와.spec.clusterIP필드 모두 하나의 주소만 나열해요. - 이중 스택이 활성화된 클러스터에서
.spec.ipFamilyPolicy에RequireDualStack을 지정하는 것은PreferDualStack과 동일하게 동작해요.
- 이 Service 스펙은
.spec.ipFamilies에IPv6와IPv4를 명시적으로 정의하고.spec.ipFamilyPolicy에PreferDualStack도 정의해요. Kubernetes가.spec.clusterIPs에 IPv6와 IPv4 주소를 할당하면,.spec.clusterIP는 IPv6 주소로 설정돼요. 그것이.spec.clusterIPs배열의 첫 번째 요소이기 때문에 기본값을 재정의해요.
apiVersion: v1
kind: Service
metadata:
name: my-service
labels:
app.kubernetes.io/name: MyApp
spec:
ipFamilyPolicy: PreferDualStack
ipFamilies:
- IPv6
- IPv4
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80
기존 Service의 이중 스택 기본값
이 예시들은 Service가 이미 존재하는 클러스터에서 이중 스택이 새로 활성화될 때의 기본 동작을 보여줘요. (기존 클러스터를 1.21 이상으로 업그레이드하면 이중 스택이 활성화돼요.)
- 클러스터에서 이중 스택이 활성화되면, 기존 Service(
IPv4든IPv6든)는 컨트롤 플레인이.spec.ipFamilyPolicy를SingleStack으로 설정하고.spec.ipFamilies를 기존 Service의 주소 패밀리로 설정하도록 구성해요. 기존 Service 클러스터 IP는.spec.clusterIPs에 저장돼요.
apiVersion: v1
kind: Service
metadata:
name: my-service
labels:
app.kubernetes.io/name: MyApp
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80
kubectl로 기존 서비스를 검사해 이 동작을 검증할 수 있어요.
kubectl get svc my-service -o yaml
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: MyApp
name: my-service
spec:
clusterIP: 10.0.197.123
clusterIPs:
- 10.0.197.123
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app.kubernetes.io/name: MyApp
type: ClusterIP
status:
loadBalancer: {}
- 클러스터에서 이중 스택이 활성화되면, 선택자가 있는 기존 headless Service는
.spec.clusterIP가None으로 설정되어 있어도 컨트롤 플레인이.spec.ipFamilyPolicy를SingleStack으로 설정하고.spec.ipFamilies를 첫 번째 service 클러스터 IP 범위(주소 패밀리)로 설정하도록 구성해요 (kube-apiserver의--service-cluster-ip-range플래그로 구성).
apiVersion: v1
kind: Service
metadata:
name: my-service
labels:
app.kubernetes.io/name: MyApp
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80
kubectl로 선택자가 있는 기존 headless 서비스를 검사해 이 동작을 검증할 수 있어요.
kubectl get svc my-service -o yaml
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: MyApp
name: my-service
spec:
clusterIP: None
clusterIPs:
- None
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app.kubernetes.io/name: MyApp
단일 스택과 이중 스택 사이에서 Service 전환
Service는 단일 스택에서 이중 스택으로, 이중 스택에서 단일 스택으로 변경될 수 있어요.
- Service를 단일 스택에서 이중 스택으로 바꾸려면
.spec.ipFamilyPolicy를 원하는 대로SingleStack에서PreferDualStack이나RequireDualStack으로 변경해요. Service를 단일 스택에서 이중 스택으로 변경하면 Kubernetes는 누락된 주소 패밀리를 할당해서 Service가 이제 IPv4와 IPv6 주소를 모두 갖게 해요.
Service 스펙을 편집해 .spec.ipFamilyPolicy를 SingleStack에서 PreferDualStack으로 업데이트해요.
변경 전:
spec:
ipFamilyPolicy: SingleStack
변경 후:
spec:
ipFamilyPolicy: PreferDualStack
- Service를 이중 스택에서 단일 스택으로 바꾸려면
.spec.ipFamilyPolicy를PreferDualStack이나RequireDualStack에서SingleStack으로 변경해요. Service를 이중 스택에서 단일 스택으로 변경하면 Kubernetes는.spec.clusterIPs배열의 첫 번째 요소만 유지하고,.spec.clusterIP를 그 IP 주소로 설정하며.spec.ipFamilies를.spec.clusterIPs의 주소 패밀리로 설정해요.
선택자가 없는 Headless Service
선택자가 없는 Headless Service이면서 .spec.ipFamilyPolicy가 명시적으로 설정되지 않은 경우, .spec.ipFamilyPolicy 필드는 기본적으로 RequireDualStack으로 설정돼요.
Service 유형 LoadBalancer
Service에 이중 스택 로드 밸런서를 프로비저닝하려면:
.spec.type필드를LoadBalancer로 설정해요..spec.ipFamilyPolicy필드를PreferDualStack이나RequireDualStack으로 설정해요.
참고:
이중 스택
LoadBalancer유형 Service를 사용하려면 클라우드 제공자가 IPv4와 IPv6 로드 밸런서를 지원해야 해요.
이그레스 트래픽 (Egress traffic)
공개적으로 라우팅할 수 없는 IPv6 주소를 사용하는 Pod에서 클러스터 외부 대상(예: 공용 인터넷)에 도달하기 위해 이그레스 트래픽을 활성화하려면, 투명 프록시나 IP 마스커레이딩 같은 메커니즘을 통해 Pod가 공개적으로 라우팅되는 IPv6 주소를 사용할 수 있게 해야 해요. ip-masq-agent 프로젝트는 이중 스택 클러스터에서 IP 마스커레이딩을 지원해요.
참고:
CNI 제공자가 IPv6를 지원하는지 확인하세요.
Windows 지원 (Windows support)
Windows의 Kubernetes는 단일 스택 "IPv6 전용" 네트워킹을 지원하지 않아요. 하지만 단일 패밀리 서비스를 가진 pod와 노드에 대한 이중 스택 IPv4/IPv6 네트워킹은 지원돼요.
l2bridge 네트워크로 IPv4/IPv6 이중 스택 네트워킹을 사용할 수 있어요.
참고:
Windows의 오버레이(VXLAN) 네트워크는 이중 스택 네트워킹을 지원하지 않아요.
Windows의 다양한 네트워크 모드에 대해 더 읽으려면 Networking on Windows 주제를 참고하세요.