Search code examples
kubernetesnginx-ingressmetallb

Exposing Kubernetes cluster with MetalLB


I have a baremetal cluster composed of a master node and 2 workers. The master node has 2 network interfaces. One of the network interfaces has a PUBLIC_IP assigned to it.

The nodes are connected by using the second network interface in the master node. As follows:

kubeadm init --apiserver-advertise-address INTERNAL_MASTER_IP

Then, the workers are joined as follows:

kubeadm join INTERNAL_MASTER_IP:6443 --token TOKEN --discovery-token-ca-cert-hash sha256:CERT

I have installed Weave, as follows:

kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

And everything works fine so far and the state is as follows:

kubectl get nodes -o wide
NAME    STATUS   ROLES    AGE     VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
node0   Ready    master   3h44m   v1.17.0   PUBLIC_IP       <none>        Ubuntu 18.04.3 LTS   4.15.0-72-generic   docker://18.6.2
node1   Ready    <none>   3h40m   v1.17.0   10.6.129.228    <none>        Ubuntu 18.04.3 LTS   4.15.0-72-generic   docker://18.6.2
node2   Ready    <none>   3h40m   v1.17.0   10.6.129.47     <none>        Ubuntu 18.04.3 LTS   4.15.0-72-generic   docker://18.6.2

I am trying expose services through the PUBLIC_IP. For this, I have installed MetalLB as follows:

kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.8.3/manifests/metallb.yaml

The ConfigMap is as follows:

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - PUBLIC_IP

NGINX is deployed as follows:

kubectl run nginx --image=nginx --port=80
kubectl expose deployment nginx --type=LoadBalancer --name=nginx-service

However, the result is as follows:

kubectl get deployments
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/1     1            1           31m


kubectl get services
NAME            TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP      10.96.0.1      <none>        443/TCP        3h50m
nginx-service   LoadBalancer   10.96.114.88   <pending>     80:31246/TCP   31m


kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5578584966-vkgvv   1/1     Running   0          32m`enter code here`


kubectl describe service nginx-service
Name:                     nginx-service
Namespace:                default
Labels:                   run=nginx
Annotations:              <none>
Selector:                 run=nginx
Type:                     LoadBalancer
IP:                       10.96.114.88
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  31246/TCP
Endpoints:                10.36.0.0:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

As can be seen, the external IP is still as pending. Do you have some idea? Thank you in advance :)


Solution

  • You need to provide IP address range in the metallb config. The IPs you give to metallb also should be virtual IPs. There shouldn't be an endpoint using the IP already.

    apiVersion: v1
    kind: ConfigMap
    metadata:
      namespace: metallb-system
      name: config
    data:
      config: |
        address-pools:
        - name: default
          protocol: layer2
          addresses:
          - PUBLIC_IP-PUBLIC_IP      ## This line