과거 Metallb 의 버전이 0.10 이였고 K8S 버전도 1.32 이여서 최신 버전으로 다시 설치를 해봤다.
환경
K8S 환경에서 설치를 하지만 CNI 등을 고려해 설치를 진행해야 한다. 내가 설치한 환경은 좀 더 특이한데, K8S 를 Hand Way 방법으로 설치한 상태다. Hand Way 로 설치를 하게 되면 Kube-apiserver, controller, kubelet, kube-scheduler, kube-proxy 같은 것을 컨테이너 방법이 아닌 OS 프로그램 방법으로 설치를 하게 된다. K8S 에서 사용하는 인증서도 수동으로 해줘야 한다.
요약하면 다음과 같다.
- K8S 설치: Handy way
- K8S Version: 1.32.2
- Containerd: 1.7.26
- CNI: Calico
다운로드
다운로드는 CURL 이나 WGET 명령어를 이용하면 된다.
| 1 | wget https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml | 
설치 문서를 보면 이 manifest 파일로 설치가 가능하다고 하지만 여러가지 환경으로 인해서 추가로 파일을 작성해야할 필요도 있다.
metallb 설치
다운로드 받은 metallb-native.yaml 파일을 적용해 설치해 준다.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ~$ kubectl apply -f metallb-native.yaml namespace/metallb-system created customresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io created customresourcedefinition.apiextensions.k8s.io/bgpadvertisements.metallb.io created customresourcedefinition.apiextensions.k8s.io/bgppeers.metallb.io created customresourcedefinition.apiextensions.k8s.io/communities.metallb.io created customresourcedefinition.apiextensions.k8s.io/ipaddresspools.metallb.io created customresourcedefinition.apiextensions.k8s.io/l2advertisements.metallb.io created customresourcedefinition.apiextensions.k8s.io/servicel2statuses.metallb.io created serviceaccount/controller created serviceaccount/speaker created role.rbac.authorization.k8s.io/controller created role.rbac.authorization.k8s.io/pod-lister created clusterrole.rbac.authorization.k8s.io/metallb-system:controller created clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created rolebinding.rbac.authorization.k8s.io/controller created rolebinding.rbac.authorization.k8s.io/pod-lister created clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created configmap/metallb-excludel2 created secret/metallb-webhook-cert created service/metallb-webhook-service created deployment.apps/controller created daemonset.apps/speaker created validatingwebhookconfiguration.admissionregistration.k8s.io/metallb-webhook-configuration created | 
설치는 아무런 문제 없이 모두 잘 설치가 된다.
IPAddressPool 생성
Metallb 에서 사용할 고정IP 대역을 Pool 로 가지고 있어야 하는데, 이것을 생성해 줘야 한다.
| 1 2 3 4 5 6 7 8 | apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata:   name: my-ippool   namespace: metallb-system spec:   addresses:   - 192.168.111.2-192.168.111.100 | 
위와 같은 addresses 를 할당해 준다. 필자는 집에서 K8S 를 구축했기 때문에 Private IP 대역을 할당해 줬다.
| 1 2 | ~$ kubectl apply -f metallb-ipaddress.yaml Error from server (InternalError): error when creating "metallb-ipaddress.yaml": Internal error occurred: failed calling webhook "ipaddresspoolvalidationwebhook.metallb.io": failed to call webhook: Post "https://metallb-webhook-service.metallb-system.svc:443/validate-metallb-io-v1beta1-ipaddresspool?timeout=10s": context deadline exceeded | 
생성을 위해서 파일을 적용해 주면 위와같은 오류가 발생하게 된다.
이러한 오류는 validatingwebhookconfiguration 에 metallb-webhook-configuration 설정에서 문제가 된다. Webhook 이 필요한 것인데, 이에 대한 추가적인 설정을 해줘도 되지만 일단 삭제하는 것으로 처리 한다.
| 1 2 | ~$ kubectl delete ValidatingWebhookConfiguration/metallb-webhook-configuration validatingwebhookconfiguration.admissionregistration.k8s.io "metallb-webhook-configuration" deleted | 
이렇게 한 후에 다시 metallb-ipaddress.yaml 파일을 적용하면 잘 된다.
L2 mode
필자의 경우에는 L2 mode 로 작동되도록 해야 한다. BGP 도 있기는 하지만, 필자의 경우에는 상관 없는 것이기 때문에 L2 mode 를 위해서 다음과 같이 manifest 파일을 작성한다.
| 1 2 3 4 5 6 7 8 | apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata:   name: my-l2-advertise   namespace: metallb-system spec:   ipAddressPools:   - my-ippool | 
metallb-L2Advertisement.yaml 파일을 적용한다.
LoadBalancer 타입 변경
이제 고정 IP 를 필요로 하는 Service 에 타입을 ClusterIP 에서 LoadBalancer 로 변경해 본다. Metallb 설치가 정상적이라면 다음과 같이 된다.
| 1 2 3 4 | $ kubectl get svc -A NAMESPACE        NAME                                                 TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                        AGE default          employee-consumer                                    ClusterIP      10.32.0.187   <none>          80/TCP                         3y32d default          employee-producer                                    LoadBalancer   10.32.0.74    192.168.111.3   8180:30701/TCP                 3y32d | 
EXTERNAL-IP 에 Metallb 의 IPAddresses Pool 중에 하나의 IP가 할당된다.
그리고 describe 결과는 다음과 같다.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | $ kubectl describe svc/employee-producer -n default Name:                     employee-producer Namespace:                default Labels:                   <none> Annotations:              metallb.io/ip-allocated-from-pool: my-ippool Selector:                 app=employee-producer Type:                     LoadBalancer IP Family Policy:         SingleStack IP Families:              IPv4 IP:                       10.32.0.74 IPs:                      10.32.0.74 LoadBalancer Ingress:     192.168.111.3 (VIP) Port:                     <unset>  8180/TCP TargetPort:               8180/TCP NodePort:                 <unset>  30701/TCP Endpoints:                192.168.96.50:8180 Session Affinity:         None External Traffic Policy:  Cluster Internal Traffic Policy:  Cluster Events:   Type    Reason        Age                From                Message   ----    ------        ----               ----                -------   Normal  nodeAssigned  54m                metallb-speaker     announcing from node "kworker3.systemv.local" with protocol "layer2"   Normal  nodeAssigned  53m (x4 over 54m)  metallb-speaker     announcing from node "kworker2.systemv.local" with protocol "layer2"   Normal  IPAllocated   8m35s              metallb-controller  Assigned IP ["192.168.111.3"]   Normal  nodeAssigned  3m29s              metallb-speaker     announcing from node "kworker1.systemv.local" with protocol "layer2" | 
EndPoints 는 Nodes IP가 보이고 Port 도 할당된게 보인다. 이건 아마도 Hand Way 설치로 인한 것으로 보인다. 원래 kubeadm 으로 설치를 하게 될 경우에 Node IP 조차도 K8S IP 여야 하는데, 여기서는 Node IP 자체가 OS 자체에 할당된 IP로 나타난다.