LoadBalancer Service¶
In UTHPC managed Kubernetes, a way of publishing services to either University network, or to the public internet, is by using the LoadBalancer
Kubernetes Service
.
This Service
uses the same format as ClusterIP
or NodePort
services, but establishes a network endpoint which gives direct access to the Pods
, which are selected by the Service
.
Considerations for using LoadBalancer
Using LoadBalancer
potentially allows direct access from the internet to your application. Depending on the configuration chosen, it can open traffic for the whole internet, and there's no UTHPC managed security filters in-between. Use this method only if you are willing to commit to the security standard direct internet access requires.
On the other hand, this method is the only one which supports publishing non-HTTP protocol traffic. Do make sure to use encrypted connections with your applications.
There's two networks LoadBalancer
can claim IP addresses from - a University "campus" network, and a public network.
Type | Purpose | Access | Subnet |
---|---|---|---|
Campus | For University of Tartu internal applications and software. | Limited by NetworkPolicy of the namespace, accessible only from University of Tartu internal IP addresses, WIFI or via VPN. | 172.16.232.0/24 |
Public | For public applications and software. | Limited only by the NetworkPolicy of the namespace | 193.40.46.0/24 |
Using a LoadBalancer
is a two-step process:
- Firstly, you need to setup the
Service
itself to configure the IP address and interfaces. - Secondly, you need to allow traffic through the default
NetworkPolicy
, which is set in every namespace.
Creating a LoadBalancer
¶
LoadBalancer
needs a specific Kubernetes manifest to be used:
apiVersion: v1
kind: Service
metadata:
name: <service_name> # (1)!
namespace: <namespace> # (2)!
labels:
cilium.io/public-ip: "false" # (7)!
spec:
type: LoadBalancer
ports:
- protocol: TCP # (3)!
port: 80 # (4)!
targetPort: 8080 # (5)!
selector:
app: myapp # (6)!
- Give a name to your
Service
. - Make sure the
Service
runs in your namespace. - Choose a protocol - either TCP or UDP.
- This is the port which clients connect to, to access your application.
- This is the port the service needs to be listening inside the container.
- Make sure the selector matches a
Pod
which responds to the incoming traffic. - This option controls whether the
LoadBalancer
claims a public or campus network address. Defaults tofalse
, which means campus.
After deploying this configuration to the cluster, you can view the output of kubectl get services -n <namespace>
to see which IP address got claimed for your use:
$ kubectl get services -n default
default echo-service LoadBalancer 10.109.161.86 172.16.232.2 80:30152/TCP 1m
In this case, the service received the IP address 172.16.232.2
, which it keeps until the service is deleted.
apiVersion: v1
kind: Service
metadata:
name: <service_name> # (1)!
namespace: <namespace> # (2)!
labels:
cilium.io/public-ip: "true" # (7)!
spec:
type: LoadBalancer
ports:
- protocol: TCP # (3)!
port: 80 # (4)!
targetPort: 8080 # (5)!
selector:
app: myapp # (6)!
- Give a name to your
Service
. - Make sure the
Service
runs in your namespace. - Choose a protocol - either TCP or UDP.
- This is the port which clients connect to, to access your application.
- This is the port the service needs to be listening inside the container.
- Make sure the selector matches a
Pod
which responds to the incoming traffic. - This option controls whether the
LoadBalancer
claims a public or campus network address. Defaults tofalse
, which means campus.
After deploying this configuration to the cluster, you can view the output of kubectl get services -n <namespace>
to see which IP address got claimed for your use:
$ kubectl get services -n default
default echo-service LoadBalancer 10.109.161.86 193.40.46.245 80:30152/TCP 1m
In this case, the service received the IP address 193.40.46.245
, which it keeps until the service is deleted.
Allowing traffic through the default NetworkPolicy
¶
A default NetworkPolicy
is enforced on all namespaces in Kubernetes, which disallows external traffic to the namespace. This includes both traffic from other namespaces, but also traffic from clients, if LoadBalancer
is being used.
Allowing traffic through is as simple as making an allow rule, which specifies which traffic can go where.
Best practices
The principle of least privileges dictates, that you should only allow traffic that is needed. Please do not open the whole namespace up to external traffic, if only one Pod
requires it.
Here's a two examples of permissive NetworkPolicies
. Do keep in mind, that with NetworkPolicies
, you target Pod
objects.
This option is suitable, when you need to allow one or some specific endpoints access to your deployment.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: <name>
namespace: <namespace>
spec:
podSelector:
matchLabels:
app: myapp # (1)!
policyTypes:
- Ingress # (2)!
ingress:
- from:
- ipBlock:
cidr: 192.168.1.10/32 # (3)!
ports:
- protocol: TCP # (4)!
port: 80 # (5)!
- Make sure to select the correct
Pod
. - Apply the rule only to incoming (
Ingress
) traffic. If you includeEgress
here as well, then starts managing outgoing connections. - Specify the IP address you want to allow traffic from, in this case
192.168.1.10
. The/32
part specifies, that a single host should be allowed. - Allow TCP protocol.
- Allow traffic to a single port.
After applying this manifest, you should be able to access your Pod
via the IP address you gave it, on the correct port. If not, there's a mistake in configuration.
This option is suitable, when you want to allow traffic from everywhere, to a Pod
on a certain port. This use case is typical with public websites or services.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: <name>
namespace: <namespace>
spec:
podSelector:
matchLabels:
app: myapp # (1)!
policyTypes:
- Ingress # (2)!
ingress:
- ports:
- protocol: TCP # (3)!
port: 80 # (4)!
- Make sure to select the correct
Pod
. - Apply the rule only to incoming (
Ingress
) traffic. If you includeEgress
here, then it starts managing outgoing connections as well. - Allow TCP protocol.
- Allow traffic to a single port.
As you can see, removing the ipBlock
part allows traffic from everywhere. After applying this manifest, you should be able to access your Pod
via the IP address you gave it, on the correct port. If not, there's a mistake in configuration.
Feel free to write to support@hpc.ut.ee if you have any issues.