This is part of a series on creating a Kubernetes cluster. In the previous post, we provisioned the persistent storage for our applications. In this post, we’ll start to build out the networking stack for our cluster.
Before we get deep into the various networking objects necessary for a fully-functioning cluster, I want to give a high-level overview of networking in k8s. I recommend that you first get familiar with all the pieces involved, then do some more in-depth reading on each aspect to better understand what’s happening behind the scenes. Networking in k8s is a complex topic with many facets. The information provided here should be enough to get you started and provide what we need for our application.
In k8s, networking is virtualized inside the cluster. There are a number of k8s network implementations, some specific to cloud providers. We used flannel
when creating out cluster.
Pods
are assigned private IP addresses inside the cluster. These addresses can change as Pods are created and destroyed. In order to reach the applications running in those Pods, requests are made to the cluster via a Service
. Services provide a single IP that will not change for the life of the Service and are backed by one or more Pods. The Pods backing the Service might change or scale, but the Service will be consistently available for requests.
A Service is likely only valuable if it is accessible from outside the cluster on an external IP. Kubernetes supports this in two ways, via NodePort
and LoadBalancer
. NodePort is simply when a Service is exposed on a port on the node’s IP. You can access the Service from inside the cluster by default, but you have to kubectl expose
the Service if you want to access it from outside. A LoadBalancer can also be used to expose Services, and is typically provided by a cloud platform, such as AWS or GCE. The LoadBalancer would make the Service publicly available by assigning an IP from a block of public addresses and then route requests to the Service.
The official docs have a great article that describes these concepts in more detail. I also recommend this very helpful blog post about various Ingress strategies for k8s.
Because we’re creating a baremetal k8s cluster, we will not have access to a cloud load balancer. However, there is a project called MetalLB that can provide the same load balancing in our cluster.
First install MetalLB using their yaml
file.
kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.8.3/manifests/metallb.yaml
This will deploy the components of MetalLB, but they will be in a pending state, waiting for a ConfigMap
to be deployed, defining how the load balancer will issue IP addresses.
Save the following yaml
into a file named metallb-config.yaml
. Substitute an appropriate address range based on your network and which IP addresses could be reserved for the load balancer. In my case, my DHCP server does not issue addresses in this range, and my DHCP reservations also do not use these addresses.
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.1.160-192.168.1.169
Now that we understand a little about networking in Kubernetes and created a LoadBalancer, we are ready to dig a little deeper and create an Ingress Controller.