🖥😩

stop touching the computer

The Hardest Problem In Computer Science is Opening a Port

All I wanted was to open port 1935 so that I could run my MovieNight instance in a cluster. But I couldn’t find anywhere describing all the steps to actually open a port on Kubernetes. But #ShePersisted or whatever.

NB: a non-http port (like 1935 for RTMP, or 21 for FTP, or) can only be made accessible to one (1) service in your entire cluster. So choose wisely. Yes, this is batshit.

Configuration the Application

If you’re deploying your application with a Helm chart, make sure that its service type is NodePort, and specify each port you want accessible in its service.yaml:

apiVersion: v1
kind: Service
metadata:
name:
labels:
spec:
type: NodePort
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
- port: 1935
targetPort: rtmp
protocol: TCP
name: rtmp
selector:

List the same additional ports in your application’s deployment.yaml (here 8089 is what we are exposing as port 80, since that’s what MovieNight binds to by default):

      containers:
- name:
securityContext:
image: ":"
imagePullPolicy:
ports:
- name: http
containerPort: 8089
protocol: TCP
- name: rtmp
containerPort: 1935
protocol: TCP

Configure the Ingress Controller

Find your ingress controller service and deployments in the cluster:

$ kubectl get all

NAME READY STATUS RESTARTS AGE
pod/ingress-ingress-nginx-controller-7555b9d446-r5l46 1/1 Running 0 89s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-ingress-nginx-controller LoadBalancer 10.128.94.66 [not telling] 80:31896/TCP,443:31855/TCP,1935:32249/TCP 36h
service/ingress-ingress-nginx-controller-admission ClusterIP 10.128.105.144 443/TCP 36h
service/kubernetes ClusterIP 10.128.0.1 443/TCP 37h

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-ingress-nginx-controller 1/1 1 1 36h

NAME DESIRED CURRENT READY AGE
replicaset.apps/ingress-ingress-nginx-controller-7555b9d446 1 1 1 89s

To open port 1935 like you see above, first edit the deployment definition:

kubectl edit deployment.apps/ingress-ingress-nginx-controller

And add two things:

  1. in spec.containers.ports, add the port you want open (I want 1935, which is RTMP):
        ports:
- containerPort: 80
name: http
protocol: TCP
- containerPort: 443
name: https
protocol: TCP
- containerPort: 1935
name: rtmp
protocol: TCP
- containerPort: 8443
name: webhook
protocol: TCP
  1. in spec.containers.args, add a line for tcp-services-configmap:
    spec:
containers:
- args:
- /nginx-ingress-controller
- --publish-service=default/ingress-ingress-nginx-controller
- --election-id=ingress-controller-leader
- --ingress-class=nginx
- --configmap=default/ingress-ingress-nginx-controller
- --tcp-services-configmap=default/tcp-services
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key

default/tcp-services refers to the namespace and name of the ConfigMap you’re about to create:

---
apiVersion: v1
kind: ConfigMap
metadata:
name: tcp-services
namespace: default
data:
1935: "movienight/trashcloud-movienight:1935"

Here movienight/trashcloud-movienight refers to the namespace and service name of your application.

Install your ConfigMap:

kubectl apply -f tcp-services.yaml

Then, edit the service definition of the ingress controller:

kubectl edit service/ingress-ingress-nginx-controller

In spec.ports, add an entry for the new port, and assign it an unused NodePort between 30000 and 32767:

spec:
clusterIP: 10.128.94.66
externalTrafficPolicy: Cluster
ports:
- name: http
nodePort: 31896
port: 80
protocol: TCP
targetPort: http
- name: https
nodePort: 31855
port: 443
protocol: TCP
targetPort: https
- name: rtmp
nodePort: 32249
port: 1935
protocol: TCP
targetPort: 1935

And that should do it! I’m very sleep deprived on account of this nonsense so if I’ve forgotten a step let me know.