Kubernetes makes it really easy to work with HTTP/S websites as containers. Most ingress controllers work out of the box with them. But, I needed a way to use it with a different TCP service, such as SSH on TCP port 22. I am running this on Rancher 2.5 with Kubernetes 1.19. I don’t know if how it sets up the networking in Kubernetes is any different than any other setup.
Create the files
First, we need to create a deployment.yaml file to include the port we want to use on the container.
apiVersion: apps/v1
kind: Deployment
metadata:
name: debian
namespace: default
labels:
app-name: debian
version: buster
spec:
selector:
matchLabels:
app: debian
replicas: 1
template:
metadata:
labels:
app: debian
spec:
containers:
- name: debian
image: debian
livenessProbe:
tcpSocket:
port: 22
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
tcpSocket:
port: 22
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 20
ports:
- containerPort: 22
protocol: TCP
The “containerPort” line in the Ports section is where we specify the port we want to connect to for this container.
Next we create a service.yaml spec file using the same port number in it.
apiVersion: v1
kind: Service
metadata:
name: debian
namespace: default
spec:
selector:
app: debian
ports:
- protocol: TCP
port: 22
targetPort: 22
name: ssh
type: LoadBalancer
The above will take an incoming port 22 and forward it to our container. We also set the type to “LoadBalancer”.
Now we create a configmap.yaml file for the NGINX ingress controller. If you are going to use a UDP port for a different service, you can use “udp-services” on the fourth line below.
apiVersion: v1
kind: ConfigMap
metadata:
name: tcp-services
namespace: ingress-nginx
data:
22: "default/debian:22"
The last line is formatted as <incoming port>: “<namespace>/<container name>:<container port>.
Finally, we need to make a patch.yaml file for patching the ingress controller daemonset. This will open the port on the node’s IP address. The below is what is required to minimally add a new port. All of it was copied from my existing ingress controller config except for the containerPort section for the port we are adding. You can get your config by running this command.
kubectl --cluster=prod-wlan --user=prod-wlan --namespace=ingress-nginx get daemonsets.apps nginx-ingress-controller -o yaml
apiVersion: apps/v1
kind: DaemonSet
spec:
template:
spec:
containers:
- args:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
- --configmap=$(POD_NAMESPACE)/nginx-configuration
- --election-id=ingress-controller-leader
- --ingress-class=nginx
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- --annotations-prefix=nginx.ingress.kubernetes.io
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
image: rancher/nginx-ingress-controller:nginx-0.35.0-rancher1
imagePullPolicy: IfNotPresent
name: nginx-ingress-controller
ports:
- containerPort: 80
hostPort: 80
name: http
protocol: TCP
- containerPort: 443
hostPort: 443
name: https
protocol: TCP
- containerPort: 22
hostPort: 22
name: ssh
protocol: TCP
Remember to make sure all of the rest of the file looks the same as your existing config. We are only adding the last containerPort section.
Applying the files
All of the above files can be applied with these commands
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f configmap.yaml
kubectl patch daemonsets.apps nginx-ingress-controller --patch "$(patch.yaml)" --type=merge