Skip to content

Instantly share code, notes, and snippets.

@dunn
Last active June 24, 2020 08:09
Show Gist options
  • Save dunn/7df5a5426b8216a86b514e6d8e9c7733 to your computer and use it in GitHub Desktop.
Save dunn/7df5a5426b8216a86b514e6d8e9c7733 to your computer and use it in GitHub Desktop.

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: {{ include "movienight.fullname" . }}
  labels:
    {{- include "movienight.labels" . | nindent 4 }}
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
    - port: 1935
      targetPort: rtmp
      protocol: TCP
      name: rtmp
  selector:
    {{- include "movienight.selectorLabels" . | nindent 4 }}

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: {{ .Chart.Name }}
          securityContext:
            {{- toYaml .Values.securityContext | nindent 12 }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          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   <none>          443/TCP                                     36h
service/kubernetes                                   ClusterIP      10.128.0.1       <none>          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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment