top of page
작성자 사진LoxiLB

K8s: loxilb를 사용한 Multus 워크로드 로드 밸런싱

K8s의 Multus CNI 플러그인은 단일 파드에 여러 네트워크 인터페이스를 연결할 수 있는 기능을 제공합니다. K8s에서 각 Pod는 기본적으로 루프백 외에 하나의 네트워크 인터페이스만 가지지만, Multus CNI을 이용하면 다음과 같이 활용할 수 있습니다.

  • 고성능 애플리케이션을 위한 SRIOV 인터페이스를 파드에 연결

  • 파드에 다중 인터페이스를 제공해서 멀티호밍 기능 활용

Multus는 사용자에게 뛰어난 유연성과 활용법을 제공하지만 동시에 몇 가지 단점이 있습니다.

  • Multus가 제공하는 보조 네트워크는 로드밸런서 서비스를 사용할 수 없습니다.

  • K8s의 엑세스 제어 및 보안 정책이 적용되지 않습니다.

이 포스트에서는 loxilb를 사용해서 로드 밸런서 서비스를 Multus 기반 워크로드에 제공하는 방법을 설명합니다. (PS: 해당 loxilb 기능은 아직 베타 버전입니다.)

Multus 워크로드에 seamless한 LB 서비스를 제공할 수 있다면, Multus 사용자들에게 간편한 워크로드 확장 및 정책/엑세스 제어 기능을 지원할 수 있습니다. 이러한 요구사항을 해결하기 위해서 사람들이 몇 가지 아이디어를 제시하기도 했지만, 대부분 K8s에서 제시하는 컨벤션을 위반한다는 구조적 문제점을 가지고 있었습니다.


해당 포스트에서는 k3s를 사용해서 Kubernetes를 배포하겠습니다. k3s를 설치하는 방법은 다음 포스트를 참조하시면 됩니다. 주의할 점은, Multus와 k3s간 호환성 문제 때문에 최신 버전이 아니라 약간 이전 버전(v1.22.9+k3s1)을 선택해서 설치하셔야 합니다.


$ curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.22.9+k3s1 INSTALL_K3S_EXEC="server --disable traefik --disable servicelb --disable-cloud-controller --kubelet-arg cloud-provider=external" K3S_KUBECONFIG_MODE="644" sh - 

테스트에 사용할 토폴로지는 다음 그림과 같습니다.


loxilb는 일반적으로 로드 밸런서 역할을 수행하는 외부 노드에서 실행됩니다. 이 포스트의 예제처럼 Kubernetes의 daemonset으로 실행 역시 가능하지만, 여기서는 Multus 워크로드를 사용하는 파드로 로드 밸런싱이 이루어지는 것을 보여주기 위해서 외부 노드에서 loxilb를 실행하겠습니다.


loxilb 설치 방법은 다음과 같습니다.

  1. 해당 링크를 참조하여 외부 노드에서 loxilb 컨테이너를 실행합니다 (도커 필요)

  2. 해당 링크를 참조하여 Kubernetes에 kube-loxilb를 배포합니다.

  3. 네트워크 연결이 올바른지 확인합니다. Multus를 사용할 때는 IP 주소 할당에 각별히 주의할 필요가 있습니다. 동시에 loxilb 노드와 Kubernetes 워커 노드의 인터페이스(Multus 인터페이스의 마스터가 될 인터페이스) 간 연결을 확인합니다. 위 토폴로지 예제에서는 ensp0와 ens33 인터페이스를 통해서 loxilb 노드와 통신이 되어야 합니다.

다음은 Multus 플러그인을 K8s에 설치합니다. 설치 방법은 다음과 같습니다.


1. 해당 링크를 참조하여 Multus daemonset을 배포합니다.

2. Multus 설정을 위해, 다음 예시처럼 NetworkAttachmentDefinition을 생성합니다.


cat <<EOF | kubectl create -f - 
apiVersion: "k8s.cni.cncf.io/v1" 
kind: NetworkAttachmentDefinition 
metadata: 
  name: macvlan1 
spec: 
    config: '{ 
            "cniVersion": "0.3.1", 
            "type": "macvlan", 
            "master": "ensp0", 
            "mode": "bridge", 
            "ipam": {
                 "type": "host-local",
                 "ranges": [ 
                    [ { 
                         "subnet": "192.168.20.0/24", 
                         "rangeStart": "192.168.20.20", 
                         "rangeEnd": "192.168.20.200", 
                         "gateway": "192.168.20.1" 
                    } ] 
                ] 
            } 
        }' 
EOF

3. 아래 예제처럼 Multus 인터페이스가 추가된 파드를 생성합니다. 2번에서 생성한 NetworkAttachmentDefinition의 이름을 k8s.v1.cni.cncf.io/networks annotations에 사용합니다.


cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
  name: pod-01
  labels:
    app: pod-01
  annotations:
    k8s.v1.cni.cncf.io/networks: macvlan1
spec:
  containers:
    - name: nginx-multus-test
      image: nginx:stable
      ports:
        - containerPort: 80
EOF

4. 아래 예시처럼 서비스를 생성합니다. 서비스의 annotations를 보면 loxilb.io/multus-nets 어노테이션을 사용합니다. 이 어노테이션은 LB 룰을 생성할 때 사용할 Multus 네트워크를 지정합니다. 해당 어노테이션을 사용하면 loxilb는 Multus 인터페이스를 사용하는 로드 밸런서 룰만 생성합니다.


cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Service
metadata:
  name: multus-service
  annotations:
    loxilb.io/multus-nets : macvlan1,macvlan2
spec:
  loadBalancerClass: loxilb.io/loxilb
  selector:
    app: pod-01
  ports:
    - port: 55003
      targetPort: 80
  type: LoadBalancer
EOF
  

이제 생성된 결과물을 확인합니다.


1. 다음 명령어로 Multus 및 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

위에서 Multus 네트워크 구성에 사용한 macvlan 플러그인은 기본적으로 k3s에 설치되어 있지 않기 때문에 파드를 생성하는 과정에서 에러가 발생할 수 있습니다.


  $ kubectl get pods -A | grep pod-01
default       pod-01                               0/1     ContainerCreating   0          66s

$ kubectl describe pods pod-01 | grep -i "failed"
  Warning  FailedCreatePodSandBox  3s    kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "e3e214462723c973ff5a343a9cff1e370fed5c4ccd570c8d84a408ede6419acb": plugin type="multus" name="multus-cni-network" failed (add): [default/pod-case-01:macvlan-conf-1]: error adding container to network "macvlan-conf-1": failed to find plugin "macvlan" in path [/opt/cni/bin /var/lib/rancher/k3s/data/995f5a281daabc1838b33f2346f7c4976b95f449c703b6f1f55b981966eba456/bin]

해당 에러가 발생하면 macvlan 플러그인을 수동으로 빌드해서 설치해야 합니다.


$ git clone https://github.com/containernetworking/plugins.git
$ cd plugins
$ ./build_linux.sh
$ ls bin/macvlan
$ sudo cp -f ./bin/macvlan /var/lib/rancher/k3s/data/current/bin/

2. 서비스가 올바르게 생성되었는지 확인합니다.


$ kubectl get svc
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)           AGE
kubernetes       ClusterIP      10.43.0.1       <none>          443/TCP           48m
nginx-service    ClusterIP      10.43.177.140   <none>          8080/TCP          47m
multus-service   LoadBalancer   10.43.134.27    123.123.123.1   55003:31250/TCP   4s

3. loxilb 룰이 올바르게 생성되었는지 확인합니다. (loxilb 노드에서 확인해야 합니다)


$ docker exec -it loxilb loxicmd get lb -o wide
|  EXTERNAL IP  | PORT  | PROTOCOL | BLOCK | SELECT |  MODE   |  ENDPOINT IP   | TARGET PORT | WEIGHT |  STATE   |
|---------------|-------|----------|-------|--------|---------|----------------|-------------|--------|----------|
| 123.123.123.1 | 55003 | tcp      |     0 | rr     | default | 192.168.20.20  |          80 |     10 | -        |

4. 마지막으로 트래픽이 정상적으로 흐르는지 확인합니다.


$ curl -s --connect-timeout 10 http://123.123.123.1:55003

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

조회수 201회댓글 0개

최근 게시물

전체 보기

Comments


GIThub

Learn, Contribute & Share

GETTING STARTED

Get started with deploying LoxiLB in your cluster

Documentation

Check LoxiLB Documentation for more information.

Join the LoxiLB slack channel to chat with the developers community.

bottom of page