Ingress tutorials
Load balance TCP services
The HAProxy Kubernetes Ingress Controller can load balance TCP services.
Load balancing TCP services is different from load balancing HTTP services. With HTTP, the ingress controller listens on ports 80 and 443, receiving traffic for all backend services and then routing requests based on the requested DNS hostname or URL path. With TCP, however, you must expose entirely new ports and map them to backend services.
Choose one of the following methods, but use only one. Using both could cause port conflicts:
Define TCP services with a custom resource Jump to heading
Available since
- HAProxy Kubernetes Ingress Controller 3.0
- HAProxy Enterprise Kubernetes Ingress Controller - not yet available. Instead, see Define TCP services with a ConfigMap..
To define the mapping of TCP ports to backend services, you will create a YAML file that contains a TCP
custom resource. We will name the file tcp-customresource.yaml
.
-
Install the
TCP
custom resource definition.Skip if using Helm
If you installed the ingress controller with Helm, this CRD is installed and updated automatically. Once installed, to perform updates on this CRD with Helm see: Update CRDs.
nixkubectl apply -f https://www.haproxy.com/documentation/kubernetes-ingress/community/crd/v3-0/ingress.v1.haproxy.org_tcps.yamlnixkubectl apply -f https://www.haproxy.com/documentation/kubernetes-ingress/community/crd/v3-0/ingress.v1.haproxy.org_tcps.yaml -
Define the listening TCP port and the Kubernetes service to which it should be mapped:
tcp-customresource.yamlyamlapiVersion: ingress.v1.haproxy.org/v1kind: TCPmetadata:name: example-service1-tcpspec:- name: example-tcpfrontend:name: example-frontendtcplog: truebinds:- name: bind1port: 2000service:name: example-service1port: 3000tcp-customresource.yamlyamlapiVersion: ingress.v1.haproxy.org/v1kind: TCPmetadata:name: example-service1-tcpspec:- name: example-tcpfrontend:name: example-frontendtcplog: truebinds:- name: bind1port: 2000service:name: example-service1port: 3000In this example:
- The
frontend
section configure a new frontend in the ingress controller. You can add other frontend arguments. See the CRD reference page (/kubernetes-ingress/community/configuration-reference/tcps-crd/) for a list of supported keywords. - The
binds
section sets TCP port on which to listen for incoming connections. - The
service
section sets the Kubernetes service to relay requests to.
- The
-
Apply the custom resource:
nixkubectl apply -f tcp-customresource.yamlnixkubectl apply -f tcp-customresource.yaml -
Define your backend service:
example-service.yamlyamlapiVersion: v1kind: Servicemetadata:name: example-service1namespace: defaultspec:selector:app: example-service1ports:- protocol: TCPport: 3000targetPort: 3000example-service.yamlyamlapiVersion: v1kind: Servicemetadata:name: example-service1namespace: defaultspec:selector:app: example-service1ports:- protocol: TCPport: 3000targetPort: 3000In this example:
- The service’s
name
should match the mapped service in the custom resource. For example,example-service1
. - The
protocol
should beTCP
. - The
port
should match the service’s port in the custom resource. For example,3000
. - The
targetPort
is your pod’s listening port.
- The service’s
-
Apply the service:
nixkubectl apply -f example-service.yamlnixkubectl apply -f example-service.yamloutputservice/example-service1 created
outputservice/example-service1 created
-
If you deployed the ingress controller as a NodePort service, which is the default, then in addition to publishing the listening ports on the ingress controller, you will also need to define NodePort port numbers. How you do this depends on whether you are using Helm.
-
Create or edit your Helm values file to set the
service.tcpPorts
section:myvals.yamlyamlcontroller:name: controllerservice:tcpPorts:- name: example-service1port: 2000targetPort: 2000nodePort: 30000protocol: TCPmyvals.yamlyamlcontroller:name: controllerservice:tcpPorts:- name: example-service1port: 2000targetPort: 2000nodePort: 30000protocol: TCPIn this example, for each TCP service:
- Provide a name for the port. The name of the port cannot exceed 11 characters.
port
andtargetPort
are both the port at which the ingress controller is listening.nodePort
is the port to publish for external access. Valid NodePorts are in the 30000-32767 range.- Set
protocol
toTCP
.
-
Execute the
helm upgrade
command, providing the name of the YAML values file with-f
:nixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress --namespace haproxy-controllernixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress --namespace haproxy-controlleroutputRelease "haproxy-kubernetes-ingress" has been upgraded. Happy Helming! NAME: haproxy-kubernetes-ingress [...] Service ports mapped are: - name: http containerPort: 8080 protocol: TCP - name: https containerPort: 8443 protocol: TCP - name: stat containerPort: 1024 protocol: TCP - name: quic containerPort: 8443 protocol: UDP - name: service-1-tcp containerPort: 2000 protocol: TCP
outputRelease "haproxy-kubernetes-ingress" has been upgraded. Happy Helming! NAME: haproxy-kubernetes-ingress [...] Service ports mapped are: - name: http containerPort: 8080 protocol: TCP - name: https containerPort: 8443 protocol: TCP - name: stat containerPort: 1024 protocol: TCP - name: quic containerPort: 8443 protocol: UDP - name: service-1-tcp containerPort: 2000 protocol: TCP
The
tcpPorts
we specified in the YAMLmyvals.yaml
file are present in the output above. Note that to the ingress controller, the names of our ports have changed and have-tcp
appended to the end of their names. This does not affect operation.
-
To view/edit the
haproxy-kubernetes-ingress
service, callkubectl edit service
. The command will open the service file in your configured editor.You can define your default editor by using the
KUBE_EDITOR
orEDITOR
environment variables or, if neither are defined,vi
is used for Linux ornotepad
for Windows.nixkubectl -n haproxy-controller edit svc haproxy-kubernetes-ingressnixkubectl -n haproxy-controller edit svc haproxy-kubernetes-ingressAdd entries to the
ports
section for each of your TCP services.yamlspec:[...]ports:[...]- name: example-service1nodePort: 30000port: 2000protocol: TCPtargetPort: 2000yamlspec:[...]ports:[...]- name: example-service1nodePort: 30000port: 2000protocol: TCPtargetPort: 2000In this example, for each TCP service:
- Name the port. For example,
example-service1
. - Specify a
nodePort
. Valid NodePorts are in the 30000-32767 range. - Set the
port
andtargetPort
to the port the ingress controller service will listen on. For example,2000
. - Set the
protocol
toTCP
.
- Name the port. For example,
-
Save the changes and close the file. The display shows that the file was edited:
outputservice/haproxy-kubernetes-ingress edited
outputservice/haproxy-kubernetes-ingress edited
You can connect to your TCP service through the load balancer on the port you specify as the
nodePort
. -
See the extended example for more details, including how to customize the generated backend.
Define TCP services with a ConfigMap Jump to heading
Available since
- HAProxy Kubernetes Ingress Controller 1.4
- HAProxy Enterprise Kubernetes Ingress Controller 1.4
To define the mapping of TCP ports to backend services, you will create a YAML file that contains a ConfigMap definition. We will name the file tcp-configmap.yaml
.
-
Define the listening TCP ports and the Kubernetes services to which they should be mapped:
tcp-configmap.yamlyamlapiVersion: v1kind: ConfigMapmetadata:name: tcp-configmapnamespace: haproxy-controllerdata:2000:default/example-service1:30002001:mynamespace/example-service2:3001tcp-configmap.yamlyamlapiVersion: v1kind: ConfigMapmetadata:name: tcp-configmapnamespace: haproxy-controllerdata:2000:default/example-service1:30002001:mynamespace/example-service2:3001In this example:
- We set the ConfigMap’s
name
totcp-configmap
, but you can use any name. Later, we will reference this name. - In the
data
section, add the ports that you will open on the ingress controller for receiving traffic, mapped to their associated backend services. Here, the ingress controller will listen on ports 2000 and 2001.
- We set the ConfigMap’s
-
Apply the ConfigMap:
nixkubectl apply -f tcp-configmap.yamlnixkubectl apply -f tcp-configmap.yamloutputconfigmap/tcp-configmap created
outputconfigmap/tcp-configmap created
-
Edit the ingress controller to use the
--configmap-tcp-services
startup argument to reference the ConfigMap. How you do this depends on whether you are using Helm.-
Create or edit your Helm values file to set the
--configmap-tcp-services
argument under theextraArgs
key:myvals.yamlyamlcontroller:extraArgs:- --configmap-tcp-services=haproxy-controller/tcp-configmapmyvals.yamlyamlcontroller:extraArgs:- --configmap-tcp-services=haproxy-controller/tcp-configmap -
Execute the
helm upgrade
command, providing the name of the YAML values file with-f
:nixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress --namespace haproxy-controllernixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress --namespace haproxy-controlleroutputRelease "haproxy-kubernetes-ingress" has been upgraded. Happy Helming! NAME: haproxy-kubernetes-ingress
outputRelease "haproxy-kubernetes-ingress" has been upgraded. Happy Helming! NAME: haproxy-kubernetes-ingress
-
To view/edit the
haproxy-kubernetes-ingress
deployment, callkubectl edit deployment
. The command will open the deployment file in your configured editor.You can define your default editor by using the
KUBE_EDITOR
orEDITOR
environment variables or, if neither are defined,vi
is used for Linux ornotepad
for Windows.nixkubectl -n haproxy-controller edit deployment haproxy-kubernetes-ingressnixkubectl -n haproxy-controller edit deployment haproxy-kubernetes-ingress -
Add the
--configmap-tcp-services
argument inargs
and set the value to the name of your ConfigMap (haproxy-controller/tcp-configmap
in this example).yamlspec:containers:- args:- --default-ssl-certificate=haproxy-controller/kubernetes-ingress-default-cert- --configmap=haproxy-controller/kubernetes-ingress- --http-bind-port=8080- --https-bind-port=8443- --ingress.class=haproxy- --publish-service=haproxy-controller/kubernetes-ingress- --log=info- --configmap-tcp-services=haproxy-controller/tcp-configmap[...]yamlspec:containers:- args:- --default-ssl-certificate=haproxy-controller/kubernetes-ingress-default-cert- --configmap=haproxy-controller/kubernetes-ingress- --http-bind-port=8080- --https-bind-port=8443- --ingress.class=haproxy- --publish-service=haproxy-controller/kubernetes-ingress- --log=info- --configmap-tcp-services=haproxy-controller/tcp-configmap[...] -
Save the changes and close the file. The display shows that the file was edited:
outputdeployment.apps/haproxy-kubernetes-ingress edited
outputdeployment.apps/haproxy-kubernetes-ingress edited
-
-
Define your backend services. The example below defines two services:
example-services.yamlyamlapiVersion: v1kind: Servicemetadata:name: example-service1namespace: defaultspec:selector:app: example-service1ports:- protocol: TCPport: 3000targetPort: 3000---apiVersion: v1kind: Servicemetadata:name: example-service2namespace: mynamespacespec:selector:app: example-service2ports:- protocol: TCPport: 3001targetPort: 3001example-services.yamlyamlapiVersion: v1kind: Servicemetadata:name: example-service1namespace: defaultspec:selector:app: example-service1ports:- protocol: TCPport: 3000targetPort: 3000---apiVersion: v1kind: Servicemetadata:name: example-service2namespace: mynamespacespec:selector:app: example-service2ports:- protocol: TCPport: 3001targetPort: 3001In this example:
- The service’s
name
should match the mapped entry in the ConfigMap. For example,example-service1
. - The
protocol
should beTCP
. - The
port
should match the service’s port in the ConfigMap. For example,3000
. - The
targetPort
is your pod’s listening port.
- The service’s
-
Apply the services:
nixkubectl apply -f example-services.yamlnixkubectl apply -f example-services.yamloutputservice/example-service1 created service/example-service2 created
outputservice/example-service1 created service/example-service2 created
-
If you deployed the ingress controller as a NodePort service, which is the default, then in addition to publishing the listening ports on the ingress controller, you will also need to define NodePort port numbers. How you do this depends on whether you are using Helm.
-
Create or edit your Helm values file to set the
service.tcpPorts
section. Also, if you previously set the--configmap-tcp-services
argument, keep that too.myvals.yamlyamlcontroller:name: controllerservice:tcpPorts:- name: example-service1port: 2000targetPort: 2000nodePort: 30000protocol: TCP- name: example-service2port: 2001targetPort: 2001nodePort: 30001protocol: TCPextraArgs:- --configmap-tcp-services=haproxy-controller/tcp-configmapmyvals.yamlyamlcontroller:name: controllerservice:tcpPorts:- name: example-service1port: 2000targetPort: 2000nodePort: 30000protocol: TCP- name: example-service2port: 2001targetPort: 2001nodePort: 30001protocol: TCPextraArgs:- --configmap-tcp-services=haproxy-controller/tcp-configmapIn this example, for each TCP service:
- Provide a name for the port. The name of the port cannot exceed 11 characters.
port
andtargetPort
are both the port at which the ingress controller is listening.nodePort
is the port to publish for external access. Valid NodePorts are in the 30000-32767 range.- Set
protocol
toTCP
.
-
Execute the
helm upgrade
command, providing the name of the YAML values file with-f
:nixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress --namespace haproxy-controllernixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress --namespace haproxy-controlleroutputRelease "haproxy-kubernetes-ingress" has been upgraded. Happy Helming! NAME: haproxy-kubernetes-ingress [...] Service ports mapped are: - name: http containerPort: 8080 protocol: TCP - name: https containerPort: 8443 protocol: TCP - name: stat containerPort: 1024 protocol: TCP - name: quic containerPort: 8443 protocol: UDP - name: service-1-tcp containerPort: 2000 protocol: TCP - name: service-2-tcp containerPort: 2001 protocol: TCP
outputRelease "haproxy-kubernetes-ingress" has been upgraded. Happy Helming! NAME: haproxy-kubernetes-ingress [...] Service ports mapped are: - name: http containerPort: 8080 protocol: TCP - name: https containerPort: 8443 protocol: TCP - name: stat containerPort: 1024 protocol: TCP - name: quic containerPort: 8443 protocol: UDP - name: service-1-tcp containerPort: 2000 protocol: TCP - name: service-2-tcp containerPort: 2001 protocol: TCP
The
tcpPorts
we specified in the YAMLmyvals.yaml
file are present in the output above. Note that to the ingress controller, the names of our ports have changed and have-tcp
appended to the end of their names. This does not affect operation.
-
To view/edit the
haproxy-kubernetes-ingress
service, callkubectl edit service
. The command will open the service file in your configured editor.You can define your default editor by using the
KUBE_EDITOR
orEDITOR
environment variables or, if neither are defined,vi
is used for Linux ornotepad
for Windows.nixkubectl -n haproxy-controller edit svc haproxy-kubernetes-ingressnixkubectl -n haproxy-controller edit svc haproxy-kubernetes-ingressAdd entries to the
ports
section for each of your TCP services.yamlspec:[...]ports:[...]- name: example-service1nodePort: 30000port: 2000protocol: TCPtargetPort: 2000- name: example-service2nodePort: 30001port: 2001protocol: TCPtargetPort: 2001yamlspec:[...]ports:[...]- name: example-service1nodePort: 30000port: 2000protocol: TCPtargetPort: 2000- name: example-service2nodePort: 30001port: 2001protocol: TCPtargetPort: 2001In this example, for each TCP service:
- Name the port. For example,
example-service1
. - Specify a
nodePort
. Valid NodePorts are in the 30000-32767 range. - Set the
port
andtargetPort
to the port the ingress controller service will listen on. For example,2000
. - Set the
protocol
toTCP
.
- Name the port. For example,
-
Save the changes and close the file. The display shows that the file was edited:
outputservice/haproxy-kubernetes-ingress edited
outputservice/haproxy-kubernetes-ingress edited
You can connect to your TCP service through the load balancer on the port you specify as the
nodePort
. -
Examples Jump to heading
In this section, we’ll show more examples of configuring TCP services in the ingress controller.
Load balance a TCP service using a ConfigMap Jump to heading
In the following example, we will deploy a Pod running BusyBox and we will configure the ingress controller for load balancing traffic to it over TCP. BusyBox provides several Linux utilities and is useful for troubleshooting and testing. We will use an instance of BusyBox to run netcat (nc
) which will listen for the incoming traffic.
-
To deploy an instance of BusyBox in your Kubernetes cluster, copy the following YAML and save it to a file named
busybox.yaml
:busybox.yamlyamlapiVersion: apps/v1kind: Deploymentmetadata:name: busybox-deploymentlabels:app: busyboxspec:replicas: 1selector:matchLabels:app: busyboxtemplate:metadata:labels:app: busyboxspec:containers:- name: busyboximage: busyboxcommand: ["sh", "-c", "while true; do nc -v -lk -p 5570; done"]ports:- containerPort: 5570protocol: TCP---apiVersion: v1kind: Servicemetadata:name: busybox-servicespec:selector:app: busyboxports:- protocol: TCPport: 5570targetPort: 5570---apiVersion: v1kind: ConfigMapmetadata:name: tcp-configmapnamespace: haproxy-controllerdata:2000:default/busybox-service:5570busybox.yamlyamlapiVersion: apps/v1kind: Deploymentmetadata:name: busybox-deploymentlabels:app: busyboxspec:replicas: 1selector:matchLabels:app: busyboxtemplate:metadata:labels:app: busyboxspec:containers:- name: busyboximage: busyboxcommand: ["sh", "-c", "while true; do nc -v -lk -p 5570; done"]ports:- containerPort: 5570protocol: TCP---apiVersion: v1kind: Servicemetadata:name: busybox-servicespec:selector:app: busyboxports:- protocol: TCPport: 5570targetPort: 5570---apiVersion: v1kind: ConfigMapmetadata:name: tcp-configmapnamespace: haproxy-controllerdata:2000:default/busybox-service:5570This YAML contains the definitions for:
- A Deployment for BusyBox named
busybox-deployment
. We specify that we want to use the busybox image.- We specify a
containerPort
of5570
. We will run netcat on this port and connect to it through the load balancer. - The deployment includes a command that will run netcat (
nc
) listening on TCP port5570
.
- We specify a
- A Service named
busybox-service
that will expose port5570
. Note that in the next steps, we will configure the ingress controller to connect to this port. - A ConfigMap named
tcp-configmap
. This provides the ingress controller with connection information. Note that this ConfigMap belongs to thehaproxy-controller
namespace (the namespace created when you installed the ingress controller), whereas the other BusyBox components belong to thedefault
namespace. This ConfigMap specifies that the ingress controller will make connection to the service namedbusybox-service
on port5570
. We will map port2000
to a NodePort in ourhaproxy-kubernetes-ingress
service.
- A Deployment for BusyBox named
-
Apply the changes to create the resources:
nixkubectl apply -f busybox.yamlnixkubectl apply -f busybox.yamloutputdeployment.apps/busybox-deployment created service/busybox-service created configmap/tcp-configmap created
outputdeployment.apps/busybox-deployment created service/busybox-service created configmap/tcp-configmap created
-
Edit the
haproxy-kubernetes-ingress
deployment and thehaproxy-kubernetes-ingress
service to configure the ingress controller to make connection to the Service namedbusybox-service
on port5570
. Depending on whether you installed the ingress controller with Helm or Kubectl, you can edit these resources as follows:We will use the
helm upgrade
command to automatically update thehaproxy-kubernetes-ingress
deployment and service. We will provide a values file to the command using the-f
option. This values file will specify an additional argument for the ingress controller deployment and it will configure our ports.-
Create a file named
myvals.yaml
and add the following:myvals.yamlyamlcontroller:name: controllerservice:tcpPorts:- name: busyboxport: 2000targetPort: 2000nodePort: 30000protocol: TCPextraArgs:- --configmap-tcp-services=haproxy-controller/tcp-configmapmyvals.yamlyamlcontroller:name: controllerservice:tcpPorts:- name: busyboxport: 2000targetPort: 2000nodePort: 30000protocol: TCPextraArgs:- --configmap-tcp-services=haproxy-controller/tcp-configmap -
Execute the
helm upgrade
command, providing the name of the YAML values file with-f
:nixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress \--namespace haproxy-controllernixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress \--namespace haproxy-controlleroutputRelease "haproxy-kubernetes-ingress" has been upgraded. Happy Helming! NAME: haproxy-kubernetes-ingress [...] Service ports mapped are: - name: http containerPort: 8080 protocol: TCP - name: https containerPort: 8443 protocol: TCP - name: stat containerPort: 1024 protocol: TCP - name: quic containerPort: 8443 protocol: UDP - name: busybox-tcp containerPort: 2000 protocol: TCP
outputRelease "haproxy-kubernetes-ingress" has been upgraded. Happy Helming! NAME: haproxy-kubernetes-ingress [...] Service ports mapped are: - name: http containerPort: 8080 protocol: TCP - name: https containerPort: 8443 protocol: TCP - name: stat containerPort: 1024 protocol: TCP - name: quic containerPort: 8443 protocol: UDP - name: busybox-tcp containerPort: 2000 protocol: TCP
-
To view/edit the
haproxy-kubernetes-ingress
deployment, callkubectl edit deployment
. The command will open the deployment file in your configured editor:nixkubectl -n haproxy-controller edit deployment haproxy-kubernetes-ingressnixkubectl -n haproxy-controller edit deployment haproxy-kubernetes-ingress-
Add the
--configmap-tcp-services
argument inargs
and set the value to the name of your ConfigMap (haproxy-controller/tcp-configmap
).yamlspec:containers:- args:- --default-ssl-certificate=haproxy-controller/kubernetes-ingress-default-cert- --configmap=haproxy-controller/kubernetes-ingress- --http-bind-port=8080- --https-bind-port=8443- --ingress.class=haproxy- --publish-service=haproxy-controller/kubernetes-ingress- --log=info- --configmap-tcp-services=haproxy-controller/tcp-configmap[...]yamlspec:containers:- args:- --default-ssl-certificate=haproxy-controller/kubernetes-ingress-default-cert- --configmap=haproxy-controller/kubernetes-ingress- --http-bind-port=8080- --https-bind-port=8443- --ingress.class=haproxy- --publish-service=haproxy-controller/kubernetes-ingress- --log=info- --configmap-tcp-services=haproxy-controller/tcp-configmap[...] -
Save the changes and close the file. The display shows that the file was edited:
outputdeployment.apps/haproxy-kubernetes-ingress edited
outputdeployment.apps/haproxy-kubernetes-ingress edited
-
-
To view/edit the
haproxy-kubernetes-ingress
service, callkubectl edit service
. The command will open the service file in your configured editor:nixkubectl -n haproxy-controller edit svc haproxy-kubernetes-ingressnixkubectl -n haproxy-controller edit svc haproxy-kubernetes-ingress-
Add an entry in the
ports
section with the following:yaml- name: busyboxport: 2000targetPort: 2000nodePort: 30000protocol: TCPyaml- name: busyboxport: 2000targetPort: 2000nodePort: 30000protocol: TCP -
Save the changes and close the file. The display shows that the file was edited:
outputservice/haproxy-kubernetes-ingress edited
outputservice/haproxy-kubernetes-ingress edited
-
You can define your default editor by using the
KUBE_EDITOR
orEDITOR
environment variables or, if neither are defined,vi
is used for Linux ornotepad
for Windows. -
Test the connection through the load balancer (click to expand)
To test the connection to the BusyBox instance running netcat through the load balancer:
-
Get the name of the BusyBox pod by calling
kubectl get pod
:nixkubectl get podnixkubectl get podExample outputNAME READY STATUS RESTARTS AGE busybox-deployment-6fbb645fd4-cfkwp 1/1 Running 0 12m
Example outputNAME READY STATUS RESTARTS AGE busybox-deployment-6fbb645fd4-cfkwp 1/1 Running 0 12m
-
From a server that has connection to your cluster, such as the server from which you run
kubectl
, use netcat to connect to the port you specified as the NodePort for your TCP service when you configured the ingress controller. In this example, the NodePort we specified was30000
.nixnc 127.0.0.1 30000nixnc 127.0.0.1 30000 -
Check the logs of the BusyBox pod to confirm that a connection was made:
nixkubectl logs busybox-deployment-6fbb645fd4-cfkwpnixkubectl logs busybox-deployment-6fbb645fd4-cfkwpoutputconnect to [::ffff:10.244.0.10]:5570 from 10-244-0-8.haproxy-kubernetes-ingress.haproxy-controller.svc.cluster.local:60598 ([::ffff:10.244.0.8]:60598)
outputconnect to [::ffff:10.244.0.10]:5570 from 10-244-0-8.haproxy-kubernetes-ingress.haproxy-controller.svc.cluster.local:60598 ([::ffff:10.244.0.8]:60598)
Load balance an external endpoint using a ConfigMap Jump to heading
In the following example, we will load balance traffic to an external endpoint at ifconfig.info. This service displays your IP address.
We will create a Service and then map an Endpoint to it at port 80
.
-
Copy the following YAML and save it to a file named
ifconfig.yaml
:ifconfig.yamlyamlapiVersion: v1kind: Servicemetadata:name: ifcservicespec:ports:- port: 80protocol: TCPname: http---apiVersion: v1kind: Endpointsmetadata:name: ifcservicesubsets:- addresses:- ip: 104.21.4.246ports:- port: 80protocol: TCPname: http---apiVersion: v1kind: ConfigMapmetadata:name: tcp-configmapnamespace: haproxy-controllerdata:1981:default/ifcservice:80ifconfig.yamlyamlapiVersion: v1kind: Servicemetadata:name: ifcservicespec:ports:- port: 80protocol: TCPname: http---apiVersion: v1kind: Endpointsmetadata:name: ifcservicesubsets:- addresses:- ip: 104.21.4.246ports:- port: 80protocol: TCPname: http---apiVersion: v1kind: ConfigMapmetadata:name: tcp-configmapnamespace: haproxy-controllerdata:1981:default/ifcservice:80This YAML contains the definitions for:
- A Service named
ifcservice
that will expose port80
. Note that in the next steps, we will configure the ingress controller to connect to this port. - An Endpoint mapped to
ifcservice
. Note that this Endpoint must have the same name as the Service. - A ConfigMap named
tcp-configmap
. This provides the ingress controller with connection information. Note that this ConfigMap belongs to thehaproxy-controller
namespace (the namespace created when you installed the ingress controller), whereas the other components belong to thedefault
namespace. This ConfigMap specifies that the ingress controller will make connection to the service namedifcservice
on port80
. We will map port1981
to a NodePort in ourhaproxy-kubernetes-ingress
service.
- A Service named
-
Apply the changes to create the resources:
nixkubectl apply -f busybox.yamlnixkubectl apply -f busybox.yamloutputservice/ifcservice created endpoints/ifcservice created configmap/tcp-configmap created
outputservice/ifcservice created endpoints/ifcservice created configmap/tcp-configmap created
-
Edit the
haproxy-kubernetes-ingress
deployment and thehaproxy-kubernetes-ingress
service to configure the ingress controller to make connection to the Service namedifcservice
on port80
. Depending on whether you installed the ingress controller with Helm or Kubectl, you can edit these resources as follows:We will use the
helm upgrade
command to automatically update thehaproxy-kubernetes-ingress
deployment and service. We will provide a values file to the command using the-f
option. This values file will specify an additional argument for the ingress controller deployment and it will configure our ports.-
Create a file named
myvals.yaml
and add the following:myvals.yamlyamlcontroller:name: controllerservice:tcpPorts:- name: ifconnport: 1981targetPort: 1981nodePort: 30681protocol: TCPextraArgs:- --configmap-tcp-services=haproxy-controller/tcp-configmapmyvals.yamlyamlcontroller:name: controllerservice:tcpPorts:- name: ifconnport: 1981targetPort: 1981nodePort: 30681protocol: TCPextraArgs:- --configmap-tcp-services=haproxy-controller/tcp-configmap -
Execute the
helm upgrade
command, providing the name of the YAML values file with-f
:nixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress \--namespace haproxy-controllernixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress \--namespace haproxy-controlleroutputRelease "haproxy-kubernetes-ingress" has been upgraded. Happy Helming! NAME: haproxy-kubernetes-ingress [...] Service ports mapped are: - name: http containerPort: 8080 protocol: TCP - name: https containerPort: 8443 protocol: TCP - name: stat containerPort: 1024 protocol: TCP - name: quic containerPort: 8443 protocol: UDP - name: ifconn-tcp containerPort: 1981 protocol: TCP
outputRelease "haproxy-kubernetes-ingress" has been upgraded. Happy Helming! NAME: haproxy-kubernetes-ingress [...] Service ports mapped are: - name: http containerPort: 8080 protocol: TCP - name: https containerPort: 8443 protocol: TCP - name: stat containerPort: 1024 protocol: TCP - name: quic containerPort: 8443 protocol: UDP - name: ifconn-tcp containerPort: 1981 protocol: TCP
-
To view/edit the
haproxy-kubernetes-ingress
deployment, callkubectl edit deployment
. The command will open the deployment file in your configured editor:nixkubectl -n haproxy-controller edit deployment haproxy-kubernetes-ingressnixkubectl -n haproxy-controller edit deployment haproxy-kubernetes-ingress-
Add the
--configmap-tcp-services
argument inargs
and set the value to the name of your ConfigMap (haproxy-controller/tcp-configmap
).yamlspec:containers:- args:- --default-ssl-certificate=haproxy-controller/kubernetes-ingress-default-cert- --configmap=haproxy-controller/kubernetes-ingress- --http-bind-port=8080- --https-bind-port=8443- --ingress.class=haproxy- --publish-service=haproxy-controller/kubernetes-ingress- --log=info- --configmap-tcp-services=haproxy-controller/tcp-configmap[...]yamlspec:containers:- args:- --default-ssl-certificate=haproxy-controller/kubernetes-ingress-default-cert- --configmap=haproxy-controller/kubernetes-ingress- --http-bind-port=8080- --https-bind-port=8443- --ingress.class=haproxy- --publish-service=haproxy-controller/kubernetes-ingress- --log=info- --configmap-tcp-services=haproxy-controller/tcp-configmap[...] -
Save the changes and close the file. The display shows that the file was edited:
outputdeployment.apps/haproxy-kubernetes-ingress edited
outputdeployment.apps/haproxy-kubernetes-ingress edited
-
-
To view/edit the
haproxy-kubernetes-ingress
service, callkubectl edit service
. The command will open the service file in your configured editor:nixkubectl -n haproxy-controller edit svc haproxy-kubernetes-ingressnixkubectl -n haproxy-controller edit svc haproxy-kubernetes-ingress-
Add an entry in the
ports
section with the following:yaml- name: busyboxport: 1981targetPort: 1981nodePort: 30681protocol: TCPyaml- name: busyboxport: 1981targetPort: 1981nodePort: 30681protocol: TCP -
Save the changes and close the file. The display shows that the file was edited:
outputservice/haproxy-kubernetes-ingress edited
outputservice/haproxy-kubernetes-ingress edited
-
You can define your default editor by using the
KUBE_EDITOR
orEDITOR
environment variables or, if neither are defined,vi
is used for Linux ornotepad
for Windows. -
Test the connection through the load balancer (click to expand)
To test the connection to the external Endpoint through the load balancer:
-
From a server that has connection to your cluster, such as the server from which you run
kubectl
, usecurl
to connect to the port you specified as the NodePort for your TCP service when you configured the ingress controller. In this example, the NodePort we specified was30681
.nixcurl -H "host: ifconfig.info" 127.0.0.1:30681nixcurl -H "host: ifconfig.info" 127.0.0.1:30681Your IP address should display.
output172.31.35.253
output172.31.35.253
Load balance a TCP service using a custom resource Jump to heading
In the following example, we will deploy a Pod running BusyBox and we will configure the ingress controller for load balancing traffic to it over TCP. BusyBox provides several Linux utilities and is useful for troubleshooting and testing. We will use an instance of BusyBox to run netcat (nc
) which will listen for the incoming traffic.
-
To deploy an instance of BusyBox in your Kubernetes cluster, copy the following YAML and save it to a file named
busybox.yaml
:busybox.yamlyamlapiVersion: apps/v1kind: Deploymentmetadata:name: busybox-deploymentlabels:app: busyboxspec:replicas: 1selector:matchLabels:app: busyboxtemplate:metadata:labels:app: busyboxspec:containers:- name: busyboximage: busyboxcommand: ["sh", "-c", "while true; do nc -v -lk -p 5570; done"]ports:- containerPort: 5570protocol: TCP---apiVersion: v1kind: Servicemetadata:name: busybox-servicespec:selector:app: busyboxports:- protocol: TCPport: 5570targetPort: 5570busybox.yamlyamlapiVersion: apps/v1kind: Deploymentmetadata:name: busybox-deploymentlabels:app: busyboxspec:replicas: 1selector:matchLabels:app: busyboxtemplate:metadata:labels:app: busyboxspec:containers:- name: busyboximage: busyboxcommand: ["sh", "-c", "while true; do nc -v -lk -p 5570; done"]ports:- containerPort: 5570protocol: TCP---apiVersion: v1kind: Servicemetadata:name: busybox-servicespec:selector:app: busyboxports:- protocol: TCPport: 5570targetPort: 5570This YAML contains the definitions for:
- A Deployment for BusyBox named
busybox-deployment
. We specify that we want to use the busybox image.- We specify a
containerPort
of5570
. We will run netcat on this port and connect to it through the load balancer. - The deployment includes a command that will run netcat (
nc
) listening on TCP port5570
.
- We specify a
- A Service named
busybox-service
that will expose port5570
. Note that in the next steps, we will configure the ingress controller to connect to this port.
- A Deployment for BusyBox named
-
Apply the changes to create the resources:
nixkubectl apply -f busybox.yamlnixkubectl apply -f busybox.yamloutputdeployment.apps/busybox-deployment created service/busybox-service created
outputdeployment.apps/busybox-deployment created service/busybox-service created
-
Install the
TCP
custom resource definition.nixkubectl apply -f https://www.haproxy.com/documentation/kubernetes-ingress/community/crd/v3-0/ingress.v1.haproxy.org_tcps.yamlnixkubectl apply -f https://www.haproxy.com/documentation/kubernetes-ingress/community/crd/v3-0/ingress.v1.haproxy.org_tcps.yaml -
Define the listening TCP port and the Kubernetes service to which it should be mapped:
tcp-customresource.yamlyamlapiVersion: ingress.v1.haproxy.org/v1kind: TCPmetadata:name: busybox-service-tcpspec:- name: busybox-tcpfrontend:name: busybox-frontendtcplog: truebinds:- name: bind1port: 2002service:name: busybox-serviceport: 5570tcp-customresource.yamlyamlapiVersion: ingress.v1.haproxy.org/v1kind: TCPmetadata:name: busybox-service-tcpspec:- name: busybox-tcpfrontend:name: busybox-frontendtcplog: truebinds:- name: bind1port: 2002service:name: busybox-serviceport: 5570 -
Apply the custom resource:
nixkubectl apply -f tcp-customresource.yamlnixkubectl apply -f tcp-customresource.yaml -
Edit the
haproxy-kubernetes-ingress
service to map the listening port2002
to NodePort30000
. Depending on whether you installed the ingress controller with Helm or Kubectl, you can edit these resources as follows:We will use the
helm upgrade
command to automatically update thehaproxy-kubernetes-ingress
service. We will provide a values file to the command using the-f
option. This values file will configure our ports.-
Create a file named
myvals.yaml
and add the following:myvals.yamlyamlcontroller:name: controllerservice:tcpPorts:- name: busyboxport: 2002targetPort: 2002nodePort: 30000protocol: TCPmyvals.yamlyamlcontroller:name: controllerservice:tcpPorts:- name: busyboxport: 2002targetPort: 2002nodePort: 30000protocol: TCP -
Execute the
helm upgrade
command, providing the name of the YAML values file with-f
:nixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress --namespace haproxy-controllernixhelm upgrade haproxy-kubernetes-ingress -f myvals.yaml haproxytech/kubernetes-ingress --namespace haproxy-controller
-
To view/edit the
haproxy-kubernetes-ingress
service, callkubectl edit service
. The command will open the service file in your configured editor:You can define your default editor by using the
KUBE_EDITOR
orEDITOR
environment variables or, if neither are defined,vi
is used for Linux ornotepad
for Windows.nixkubectl -n haproxy-controller edit svc haproxy-kubernetes-ingressnixkubectl -n haproxy-controller edit svc haproxy-kubernetes-ingress-
Add an entry in the
ports
section with the following:yaml- name: busyboxport: 2002targetPort: 2002nodePort: 30000protocol: TCPyaml- name: busyboxport: 2002targetPort: 2002nodePort: 30000protocol: TCP -
Save the changes and close the file. The display shows that the file was edited:
outputservice/haproxy-kubernetes-ingress edited
outputservice/haproxy-kubernetes-ingress edited
-
-
-
Customize the backend service by defining a
Backend
custom resource. For example, below we change the load balancing algorithm to beleastconn
.-
Create the custom resource. Below we set the load balancing algorithm to
leastconn
:backend-crd.yamlyamlapiVersion: "ingress.v1.haproxy.org/v1"kind: Backendmetadata:name: example-backendnamespace: defaultspec:config:name: example-configbalance:algorithm: "leastconn"backend-crd.yamlyamlapiVersion: "ingress.v1.haproxy.org/v1"kind: Backendmetadata:name: example-backendnamespace: defaultspec:config:name: example-configbalance:algorithm: "leastconn" -
Apply the change:
nixkubectl apply -f backend-crd.yamlnixkubectl apply -f backend-crd.yamloutputbackend.ingress.v1.haproxy.org/example-backend created
outputbackend.ingress.v1.haproxy.org/example-backend created
-
Update your Service definition to use this custom resource by adding the
haproxy.org/cr-backend
annotation:busybox.yamlyamlapiVersion: v1kind: Servicemetadata:name: busybox-servicenamespace: defaultannotations:haproxy.org/cr-backend: default/example-backendspec:selector:app: busyboxports:- protocol: TCPport: 5570targetPort: 5570busybox.yamlyamlapiVersion: v1kind: Servicemetadata:name: busybox-servicenamespace: defaultannotations:haproxy.org/cr-backend: default/example-backendspec:selector:app: busyboxports:- protocol: TCPport: 5570targetPort: 5570 -
Apply the service:
nixkubectl apply -f busybox.yamlnixkubectl apply -f busybox.yamloutputservice/busybox-service created
outputservice/busybox-service created
In the end, the generated load balancer configuration inside the ingress controller pod will look like this:
haproxyfrontend tcpcr_default_busybox-frontendmode tcpbind :2002 name bind1option tcplogdefault_backend default_busybox-service_3000backend default_busybox-service_3000mode tcpbalance leastconnserver SRV_1 10.244.0.2:3000 enabledhaproxyfrontend tcpcr_default_busybox-frontendmode tcpbind :2002 name bind1option tcplogdefault_backend default_busybox-service_3000backend default_busybox-service_3000mode tcpbalance leastconnserver SRV_1 10.244.0.2:3000 enabled -
Test the connection through the load balancer (click to expand)
To test the connection to the BusyBox instance running netcat through the load balancer:
-
Get the name of the BusyBox pod by calling
kubectl get pod
:nixkubectl get podnixkubectl get podExample outputNAME READY STATUS RESTARTS AGE busybox-deployment-6fbb645fd4-cfkwp 1/1 Running 0 12m
Example outputNAME READY STATUS RESTARTS AGE busybox-deployment-6fbb645fd4-cfkwp 1/1 Running 0 12m
-
From a server that has connection to your cluster, such as the server from which you run
kubectl
, use netcat to connect to the port you specified as the NodePort for your TCP service when you configured the ingress controller. In this example, the NodePort we specified was30000
.nixnc 127.0.0.1 30000nixnc 127.0.0.1 30000 -
Check the logs of the BusyBox pod to confirm that a connection was made:
nixkubectl logs busybox-deployment-6fbb645fd4-cfkwpnixkubectl logs busybox-deployment-6fbb645fd4-cfkwpoutputconnect to [::ffff:10.244.0.10]:5570 from 10-244-0-8.haproxy-kubernetes-ingress.haproxy-controller.svc.cluster.local:60598 ([::ffff:10.244.0.8]:60598)
outputconnect to [::ffff:10.244.0.10]:5570 from 10-244-0-8.haproxy-kubernetes-ingress.haproxy-controller.svc.cluster.local:60598 ([::ffff:10.244.0.8]:60598)
Do you have any suggestions on how we can improve the content of this page?