<p>I have a container running an OPC-server on port 4840. I am trying to configure my microk8s to allow my OPC-Client to connect to the port 4840. Here are examples of my deployment and service:</p>
<p>(No namespace is defined here but they are deployed through azure pipelines and that is where the namespace is defined, the namespace for the deployment and service is &quot;jawcrusher&quot;)</p>
<p>deployment.yml</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: jawcrusher
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jawcrusher
  strategy: {}
  template:
    metadata:
      labels:
        app: jawcrusher
    spec:
      volumes:
        - name: jawcrusher-config
          configMap:
            name: jawcrusher-config
      containers:
      - image: XXXmicrok8scontainerregistry.azurecr.io/jawcrusher:#{Version}#
        name: jawcrusher
        ports:
          - containerPort: 4840
        volumeMounts:
          - name: jawcrusher-config
            mountPath: &quot;/jawcrusher/config/config.yml&quot;
            subPath: &quot;config.yml&quot;
      imagePullSecrets:
        - name: acrsecret
</code></pre>
<p>service.yml</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: jawcrusher-service
spec:
  ports:
  - name: 7070-4840
    port: 7070
    protocol: TCP
    targetPort: 4840
  selector:
    app: jawcrusher
  type: ClusterIP
status:
  loadBalancer: {}
</code></pre>
<p>I am using a k8s-client called Lens and in this client there is a functionality to forward local ports to the service. If I do this I can connect to the OPC-Server with my OPC-Client using the url localhost:4840. To me that indicates that the service and deployment is set up correctly.</p>
<p>So now I want to tell microk8s to serve my OPC-Server from port 4840 &quot;externally&quot;. So for example if my dns to the server is microk8s.xxxx.internal I would like to connect with my OPC-Client to microk8s.xxxx.internal:4840.</p>
<p>I have followed this tutorial as much as I can: <a href="https://minikube.sigs.k8s.io/docs/tutorials/nginx_tcp_udp_ingress/" rel="nofollow noreferrer">https://minikube.sigs.k8s.io/docs/tutorials/nginx_tcp_udp_ingress/</a>.</p>
<p>It says to update the tcp-configuration for the ingress, this is how it looks after I updated it:</p>
<p>nginx-ingress-tcp-microk8s-conf:</p>
<pre><code>apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-ingress-tcp-microk8s-conf
  namespace: ingress
  uid: a32690ac-34d2-4441-a5da-a00ec52d308a
  resourceVersion: '7649705'
  creationTimestamp: '2023-01-12T14:12:07Z'
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: &gt;
      {&quot;apiVersion&quot;:&quot;v1&quot;,&quot;kind&quot;:&quot;ConfigMap&quot;,&quot;metadata&quot;:{&quot;annotations&quot;:{},&quot;name&quot;:&quot;nginx-ingress-tcp-microk8s-conf&quot;,&quot;namespace&quot;:&quot;ingress&quot;}}
  managedFields:
    - manager: kubectl-client-side-apply
      operation: Update
      apiVersion: v1
      time: '2023-01-12T14:12:07Z'
      fieldsType: FieldsV1
      fieldsV1:
        f:metadata:
          f:annotations:
            .: {}
            f:kubectl.kubernetes.io/last-applied-configuration: {}
    - manager: kubectl-patch
      operation: Update
      apiVersion: v1
      time: '2023-02-14T07:50:30Z'
      fieldsType: FieldsV1
      fieldsV1:
        f:data:
          .: {}
          f:4840: {}
  selfLink: /api/v1/namespaces/ingress/configmaps/nginx-ingress-tcp-microk8s-conf
data:
  '4840': jawcrusher/jawcrusher-service:7070
binaryData: {}
</code></pre>
<p>It also says to update a deployment called ingress-nginx-controller but in microk8s it seems to be a daemonset called nginx-ingress-microk8s-controller. This is what it looks like after adding a new port:</p>
<p>nginx-ingress-microk8s-controller:</p>
<pre><code>spec:
      containers:
        - name: nginx-ingress-microk8s
          image: registry.k8s.io/ingress-nginx/controller:v1.2.0
          args:
            - /nginx-ingress-controller
            - '--configmap=$(POD_NAMESPACE)/nginx-load-balancer-microk8s-conf'
            - &gt;-
              --tcp-services-configmap=$(POD_NAMESPACE)/nginx-ingress-tcp-microk8s-conf
            - &gt;-
              --udp-services-configmap=$(POD_NAMESPACE)/nginx-ingress-udp-microk8s-conf
            - '--ingress-class=public'
            - ' '
            - '--publish-status-address=127.0.0.1'
          ports:
            - name: http
              hostPort: 80
              containerPort: 80
              protocol: TCP
            - name: https
              hostPort: 443
              containerPort: 443
              protocol: TCP
            - name: health
              hostPort: 10254
              containerPort: 10254
              protocol: TCP
            ####THIS IS WHAT I ADDED####
            - name: jawcrusher
              hostPort: 4840
              containerPort: 4840
              protocol: TCP
</code></pre>
<p>After I have updated the daemonset it restarts all the pods. The port seem to be open, if I run this script is outputs:</p>
<pre><code> Test-NetConnection -ComputerName microk8s.xxxx.internal -Port 4840                                                                                                                                                                                                                                                                             
 ComputerName     : microk8s.xxxx.internal                                                                            
 RemoteAddress    : 10.161.64.124                                                                                        
 RemotePort       : 4840                                                                                                 
 InterfaceAlias   : Ethernet 2                                                                                           
 SourceAddress    : 10.53.226.55
 TcpTestSucceeded : True
</code></pre>
<p>Before I did the changes it said TcpTestSucceeded: False.</p>
<p>But the OPC-Client cannot connect. It just says:
Could not connect to server: BadCommunicationError.</p>
<p>Does anyone see if I made a mistake somewhere or knows how to do this in microk8s.</p>
<p>Update 1:
I see an error message in the ingress-daemonset-pod logs when I try to connect to the server with my OPC-Client:</p>
<blockquote>
<p>2023/02/15 09:57:32 [error] 999#999: *63002 connect() failed (111:
Connection refused) while connecting to upstream, client:
10.53.225.232, server: 0.0.0.0:4840, upstream: &quot;10.1.98.125:4840&quot;, bytes from/to client:0/0, bytes from/to upstream:0/0</p>
</blockquote>
<p>10.53.225.232 is the client machines ip address and 10.1.98.125 is the ip number of the pod running the OPC-server.</p>
<p>So it seems like it has understood that external port 4840 should be proxied/forwarded to my service which in turn points to the OPC-server-pod. But why do I get an error...</p>
<p>Update 2:
Just to clearify, if I run kubectl port forward command and point to my service it works. But not if I try to connect directly to the 4840 port. So for example this works:</p>
<pre><code>kubectl port-forward service/jawcrusher-service 5000:4840 -n jawcrusher --address='0.0.0.0'
</code></pre>
<p>This allows me to connect with my OPC-client to the server on port 5000.</p>

Viktor Eriksson
<p>You should simply do a port forwarding from your localhost port x to your service/deployment/pod on port y with kubectl command.<br />
Lets say you have a Nats streaming server in your k8s, it's using tcp over port 4222, your command in that case would be:<br />
<code>kubectl port-forward service/nats 4222:4222</code><br />
In this case it will forward all traffic on localhost over port 4222 to the service named nats inside your cluster on port 4222. Instead of service you could forward to a specific pod or deployment...<br />
Use <code>kubectl port-forward -h</code> to see all your options...<br />
In case you are using k3d to setup a k3s in docker or rancher desktop you could add the port parameter to your k3d command:<br />
<code>k3d cluster create k3s --registry-create registry:5000 -p 8080:80@loadbalancer -p 4222:4222@server:0</code></p>
