SCTP(Stream Control Transmission Protocol)는 엔드포인트에서 한 개 이상의 IP 주소를 가지고 있을 때, Multihoming(멀티호밍)을 지원합니다. SCTP는 전송계층의 프로토콜로 엔드포인트간의 신뢰성이 있는 메세지 기반 통신을 제공합니다. TCP의 경우 두 호스트간 한개의 연결만 지원했지만 SCTP는 여러개의 호스트를 동시에 연결 하는 “Association”을 지원합니다.
SCTP의 멀티 호밍(Multi-homing)을 통해 엔드포인트는 중복 네트워크 경로 및 IP 주소를 유지 관리할 수 있습니다. 이러한 이중화는 통신의 전반적인 신뢰성과 내결함성을 향상시킬 수 있습니다. 하나의 네트워크 경로 또는 IP 주소를 사용할 수 없거나 문제가 발생하는 경우 엔드포인트는 통신을 중단하지 않고 대체 경로 또는 주소로 전환할 수 있습니다.
Importance of SCTP multi-homing in 5G /Telco networks
SCTP 멀티호밍 기능은 로드밸런싱을 가능하게 하며, 다중 경로 활용을 통해 원활한 핸드오버를 지원하여 중복성 및 복원력을 제공함으로서 네트워크의 신뢰성을 향상시킵니다. 이러한 기능들은 5G 환경에서 동작하는 다양한 애플리케이션과 서비스가 요구하는 성능과 안정성을 확보하는 데 필수적인 것들입니다. 다음은 SCTP 멀티호밍이 5G에서 중요한 이유들입니다:
신뢰성 향상: 5G 네트워크는 다양한 요구 사항을 가진 애플리케이션과 서비스를 지원할 것으로 예상됩니다. SCTP 멀티호밍을 통해 여러 개의 네트워크 연결을 설정함으로써, 5G 장치는 네트워크 장애나 중단이 발생하더라도 안정적인 통신을 보장할 수 있습니다. 하나의 네트워크 경로나 IP 주소를 사용할 수 없게 되면 장치가 다른 경로로 전환되어 지속적인 연결을 보장할 수 있습니다.
로드 밸런싱: 데이터 집약적인 애플리케이션의 확산과 5G 네트워크에서 연결된 장치의 수가 증가함에 따라 네트워크 트래픽을 효율적으로 분산하는 것이 중요합니다. SCTP 멀티호밍을 사용하면 장치가 여러 사용 가능한 경로에 데이터를 분산할 수 있으므로 로드 밸런싱이 가능합니다. 이를 통해 네트워크 리소스 활용률을 최적화하고 단일 경로에서의 정체를 방지할 수 있습니다.
다중 경로: 5G 네트워크는 자율 주행 차량, 원격 수술 및 증강 현실과 같은 애플리케이션을 지원하기 위한 저지연 및 고대역폭 연결을 제공하는 것을 목표로 합니다. SCTP 멀티 호밍은 장치가 대기 시간, 대역폭 및 네트워크 조건과 같은 요소를 기반으로 가장 적합한 네트워크 경로를 선택하여 경로 다양성을 활용할 수 있도록 합니다. 이렇게 하면 사용 가능한 네트워크 리소스에 동적으로 적응하여 애플리케이션이 최고의 성능을 얻을 수 있습니다.
핸드 오버: 5G 네트워크는 이동성을 지원하여 지속적인 연결을 유지하면서 서로 다른 기지국 또는 네트워크 슬라이스 간에 장치를 전환할 수 있도록 합니다. SCTP 멀티 호밍은 장치가 여러 연결을 동시에 설정하고 유지할 수 있도록 하여 핸드 오버를 용이하게 합니다. 이를 통해 핸드오버 이벤트 중에도 중단 없는 통신을 보장하여 지연 시간을 줄이고 서비스 중단을 최소화할 수 있습니다.
중복성 및 복원력: 5G 네트워크는 높은 가용성과 내결함성을 제공하도록 설계되었습니다. SCTP 멀티 호밍은 다중 네트워크 경로 및 IP 주소를 통해 이중화를 제공합니다. 링크 또는 노드 중단과 같은 네트워크 장애가 발생할 경우 5G 장치를 대체 경로 또는 주소로 전환하여 중단 없는 통신과 향상된 네트워크 복원력을 보장할 수 있습니다.
5G환경에서 SCTP 멀티호밍은 다양한 시나리오로 제공됩니다. 이번 포스트는 클라우드 환경에서 작동하는 5G 코어중 하나인 AMF와 gNB(RAN)사이의 SCTP에 대해서 말씀 드리겠습니다.
SCTP multi-homing for micro-services
K8s에서는 많은 Layer들이 가상화되어있기 때문에, NAT’ing 과 Proxy’ing은 K8s의 네트워크에서 불가피한 기능입니다. 따라서 첫 스텝으로 멀티호밍을 클라우드 네이티브인 마이크로서비스 환경에서 작동하게 하기 위해서, 기존 쿠버네티스 서비스 추상화의 목적을 가능한 변경이 없는 선에서 이 기능을 도입하기 위해 노력했습니다.
NAT을 사용하는 SCTP 멀티호밍은 다양한 방법으로 구현할 수 있습니다. NAT과 함께 SCTP 멀티호밍을 구현하는 방법에 대해 많은 논의와 제안이 있지만 클라우드 네이티브 측면에 대해서는 논의된 바가 없습니다. LoxiLB팀은 이 문제를 해결하려고 시도했습니다. 주로 두 개의 요구 사항이 왔습니다:
1. Client <-> Multi-homed LB/NAT
2. Client<-> LB/NAT <-> 엔드포인트 멀티호밍
이 포스트에서는 Client ↔ Multi-homed LB/NAT 방식으로 구현한 방법에 대해 설명합니다.
LB/NAT<->엔드포인트 멀티호밍은 LB와 엔드포인트가 일반적으로 동일한 클러스터에 위치하고 k8s 내부 네트워킹 구현이 Failover를 처리할 수 있을 정도로 강력하기 때문에 k8s환경에서 특별히 중요하지 않습니다. 또한 엔드포인트 Pod에서 멀티 호밍을 사용할 수 있도록 하는 복잡함이 있습니다. Pod당 여러 개의 인터페이스가 필요하기 때문에 Multus 같은 플러그인을 추가해야 합니다. 즉 LB/NAT<->엔드포인트 멀티호밍의 이득은 크게 없다고 판단했습니다.
Client to multi-homed LB
Considerations and Limitations (for LoxiLB’s implementation)
Endpoint는 single homed 상태여야 합니다.
Multi-homing은 fullNAT 모드에서만 작동합니다.
LB Rule에는 최대 3 개의 secondary IP를 설정할 수 있습니다.
Client ↔ Multi-homed LB은 LB가 Primary IP주소 하나만 갖는 것이 아닌 SCTP association을 위해 여러개의 secondary IP주소를 갖는 경우입니다. 클라이언트는 Primary IP를 사용해서 SCTP assoication을 시작합니다.
Service rule for LB SCTP Multi-homing
SCTP 멀티호밍 서비스를 시작하기 위해서는 loxicmd 또는 Kube-loxilb 를 통해서 LB의 룰이 생성되어야 합니다. LB 룰은 Primary service IP등을 포함한 파라미터와 같이 생성되어야 합니다. Primary Service IP에 도달하는것을 실패하는 경우, 클라이언트는 SCTP프로토콜의 디자인을 따라 Secondary Service IP를 사용하여 통신을 시작합니다.
Configuring SCTP Multihoming service with kube-loxilb
Kube-LoxiLB는 쿠버네티스의 서비스 LB spec을 통해 실행됩니다. 이것은 또한 kubernetes 클러스터에서 SCTP 멀티호밍 서비스 배포를 완벽하게 지원하도록 향상되었습니다. Kube-LoxiLB Daemonset을 실행하기 위해서는 다음과 같은 작업을 진행합니다.
Kube-loxilb yaml파일 가져오기
$ wget https://github.com/loxilb-io/kube-loxilb/raw/main/manifest/kube-loxilb.yaml
(옵션) Multi-homing 부분의 내용 수정하기
args:
- --externalCIDR=123.123.123.1/24
- --externalSecondaryCIDRs=124.124.124.1/24,125.125.125.1/24
- --setBGP
여기서 externalCIDR 과 externalSecondaryCIDRs의 설명은 다음과 같습니다.
externalCIDR : Primary IP 주소
externalSecondaryCIDRs : Secondary/backup IP 주소
변경된 yaml 파일 적용하기
$ kubectl apply -f kube-loxilb.yaml
Kube-loxiLB 작동 확인하기
$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system local-path-provisioner-84bb864455-qr2l5 1/1 Running 0 50m
kube-system coredns-7796b77cd4-nd2p2 1/1 Running 0 50m
kube-system metrics-server-ff9dbcb6c-8sgvd 1/1 Running 0 50m
kube-system kube-loxilb-f9c5cd878-25ppx 1/1 Running 0 49m
kube-system kube-multus-ds-amd64-7kbms 1/1 Running 0 20m
default pod-01 1/1 Running 0 6m41s
이제 Kube-LoxiLB의 컴포넌트들은 모두 실행되고있습니다. 실제 SCTP 멀티호밍 서비스를 시작하는것은 간단합니다. 아래와 같은 예시로 서비스를 실행 할 수 있습니다 :
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Service
metadata:
name: sctp-lb1
annotations:
loxilb.io/num-secondary-networks: "2"
loxilb.io/liveness: "yes"
loixlb.io/lbmode: "fullnat"
spec:
loadBalancerClass: loxilb.io/loxilb
selector:
what: sctp-test
ports:
- port: 55002
protocol: SCTP
targetPort: 9999
type: LoadBalancer
---
apiVersion: v1
kind: Pod
metadata:
name: sctp-test
labels:
what: sctp-test
spec:
containers:
- name: sctp-test
image: alpine/socat
command: [ "sh", "-c"]
args:
- while true; do
socat -v -T2 sctp-l:9999,reuseaddr,fork system:"echo 'server1'; cat";
sleep 20;
done;
ports:
- containerPort: 9999
EOF
loxilb.io/num-secondary-networks : "2" 는 주의가 필요합니다. 이 숫자는 SCTP 멀티호밍 서비스의 백업으로 사용할 보조 네트워크의 수를 의미합니다. 이 내용들을 기반으로 kube-LoxiLB는 kube-loxilb.yaml에 "externalSecondary"로 정의된 CIDR 범위에서 보조 IP 주소 할당(IPAM)을 수행합니다.
Verifying created services in K8s
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 3m53s
nginx-lb1 LoadBalancer 10.43.60.79 123.123.123.1 55002:31706/TCP 2m23s
sctp-lb1 LoadBalancer 10.43.77.241 123.123.123.1 55002:32153/SCTP 49s
Verifying service LB Rules with loxicmd
$ docker exec -it llb1 loxicmd get lb -o wide
| EXTERNAL IP | SECONDARY IPS | PORT | PROTOCOL | BLOCK | SELECT | MODE | ENDPOINT IP | TARGET PORT | WEIGHT | STATE |
|---------------|------------------------------|-------|----------|-------|--------|---------|--------------|-------------|--------|--------|
| 123.123.123.1 | | 80 | tcp | 0 | rr | default | 172.30.1.177 | 30820 | 10 | - |
| 123.123.123.1 | 124.124.124.1, 125.125.125.1 | 55002 | sctp | 0 | rr | fullnat | 172.30.1.177 | 32153 | 10 | active |
| 123.123.123.1 | | 55002 | tcp | 0 | rr | default | 172.30.1.177 | 31706 | 10 | - |
| 20.20.20.1 | | 2020 | tcp | 0 | rr | fullnat | 31.31.31.1 | 8080 | 1 | - |
| | | | | | | | 32.32.32.1 | 8080 | 1 | - |
| | | | | | | | 33.33.33.1 | 8080 | 1 | - |
Deploying multiple LoxiLB instances
일반적으로 로드 밸런서나 프록시는 단일 장애점(Single point of failure)을 제거하기 위해 클러스터로 구현됩니다. LoxiLB는 다양한 클러스터 모드(예: Maglev 클러스터링 또는 State-aware 클러스터)를 지원합니다. 다음 섹션에서 보게 될 SCTP 멀티호밍의 경우 동일한 서비스에 속하는 여러 튜플 세트로 인해 Maglev 클러스터링을 수행하는 것이 실질적으로 불가능할 것입니다. 다음 예제에서 LoxiLB 인스턴스는 State-aware 클러스터 세트로 배포되어야 합니다. SCTP 멀티호밍 상태는 LoxiLB 노드 간에 공유되며 전부 일관성있게 작동합니다.
Secondary Service IP advertisement through BGP
위의 kube-loxilb.yaml 예시와 같이 LB 룰의 bgp 플래그가 있는 경우 LoxiLB는 Primary IP 주소와 함께 Secondary IP 주소도 Advertisement합니다.
LoxiLB가 클러스터로 배포되면 LoxiLB 인스턴스가 클러스터 노드 내에서 추적된 모든 연결을 동기화하고 모든 멀티호밍 세션 정보도 동기화됩니다. 기본 또는 보조 네트워크 경로에 대해 서로 다른 LoxiLB 인스턴스를 사용하도록 클러스터를 구성할 수도 있습니다. 이 경우 LoxiLB 인스턴스는 우선 순위가 다른 Primary, Secondary IP 주소로 서로 다른 네트워크 경로를 사용합니다.
SCTP Connection establishment in fullNAT mode
현재 FullNat모드에서만 SCTP 멀티호밍을 지원합니다. SCTP의 동작방식을 하나하나 보겠습니다. 우선 Client가 SCTP 통신을 위해 INIT 패킷을 전송합니다. LoxiLB에서는 INIT패킷의 도착지 IP주소를 Primary service IP로 변경합니다. 그리고 그외의 IP주소들을 Secondary IP주소로 변경하고 Endpoint로 전달합니다. Endpoint에서는 INIT ACK를 Primary IP로 전송합니다. LoxiLB는 Primary IP주소를 클라이언트의 primary IP주소로 변경하고 secondary IP주소들을 그대로 포함하여 INIT ACT 패킷에 넣어 클라이언트로 전달합니다. 여기서 클라이언트, 엔드포인트, LoxiLB 모두 다 sctp 연결을 위해 Primary, Secondary IP주소를 알고 있어야 합니다.
연결이 성립(Established) 이 된 후에는 LoxiLB는 이제 Primary, Secondary IP 를 가진 여러 개의 경로를 통해 SCTP 멀티호밍 트래픽을 받을 준비가 되었습니다.
DATA Traffic flow in SCTP multi-homing
클라이언트는 처음에 Primary IP 를 통한 경로로 데이터를 전송합니다. 이때의 데이터는 Fullnat모드의 SCTP single-homed 설정과 동일한 방식으로 흐릅니다. 데이터 패킷에 대한 특별한 제어를 하지 않으며, 아래 그림과 같이 데이터와 SACK 트래픽의 흐름을 보여줍니다.
HEARTBEAT Management in SCTP multi-homing
클라이언트와 엔드포인트는 하트비트(HEARTBEAT) 메세지를 통해 Primary, Secondary IP주소의 경로 상태를 확인합니다. HEARTBEAT 메시지가 오면 Endpoint는 HEARTBEAT ACK가 HEARTBEAT를 보낸 동일한 IP 주소에서 돌아올 것으로 예상합니다.
LoxiLB는 클라이언트, 엔드포인트로부터 데이터 패킷과 같이 하트비트 메세지를 받는데, 이때 하트비트 메세지를 특별히 따로 처리하지 않고 일반적인 FullNAT를 수행한 후 하트비트 메시지가 엔드포인트 혹은 클라이언트로 전달됩니다. LoxiLB의 FullNAT 모드에서는 클라이언트가 엔드포인트에서 HEARTBEAT ACK를 수신할 때 HEARTBEAT 메시지에 사용한 목적지 IP 주소를 알고있다고 가정하고 메세지를 전달합니다. 클라이언트와 엔드포인트간 하트비트 메세지는 양방향으로 따로 특별히 처리 되는 작업이 없으며, LoxiLB에 설정된 fullNAT모드로 처리됩니다.
PATH failover in SCTP multi-homing
위 섹션에서 설명한 대로 SCTP 엔드포인트는 모든 네트워크 경로에 대해 하트비트 메시지를 교환하여 상태를 확인합니다. 엔드포인트가 데이터 메시지에 대한 하트비트 메시지 또는 SACK(재전송 포함)에 응답하지 않으면 해당 경로는 비활성으로 간주됩니다. Primary 경로가 비활성이 되면, Secondary 경로들 중 하나를 선택하여 Primary경로로 사용합니다.
아래 다이어그램은 LoxiLB가 경로 페일오버를 처리하는 방법을 보여줍니다.
SHUTDOWN in SCTP multi-homing
모든 SCTP 엔드포인트는 SCTP SHUTDOWN을 할 수 있습니다. SCTP 엔드포인트는 Primary 경로만 사용하여 SHUTDOWN 패킷을 보냅니다. 만약 Primary경로가 Secondary로 되어있을 경우 LoxiLB가 가능한 모든 네트워크 경로를 추적했기 때문에 SHUTDOWN 패킷은 다른 엔드포인트로 전달됩니다. LoxiLB는 SHUTDOWN 패킷이 어느 엔드포인트의 IP가 보냈는지 여부를 확인할 필요가 없으며, 이러한 상태 확인은 엔드포인트에서 검증을 수행합니다. 즉 데이터 패킷 또는 하트비트 패킷이 처리되는 것과 동일한 방식으로 포워딩 처리됩니다.
Conclusion
LoxiLB는 K8s 환경에서 SCTP Multi-homing을 최초로 지원합니다. 클라우드 내이티브 환경에서의 마이크로서비스 기반 SCTP 기능은 서비스의 안정성, 확장성, 리질라이언스(resilience, 회복력)을 더해 주는데 큰 도움이 될거라 믿어 의심치 않습니다. LoxiLB팀은 다음 블로그에서 Multus를 사용한 Amazon의 EKS환경에서 SCTP의 예시에 대해서 작성하겠습니다.
이 포스트에 흥미를 가지고 더 깊이 알고 싶으신 분은 LoxiLB's sctp-CI testing scripts를 참조하면 더욱 좋습니다.
Comments