<p>I am using active FTP to transfer file(via the <strong>PORT</strong> command). I can initiate active FTP sessions using <strong>LoadBalancer IP</strong> and Loadbalancer Service <strong>Target Port</strong>. I tried a similar way to initiate active FTP session using <strong>Node External IP</strong> and <strong>Node Port</strong> but I am not able to do it. I am using npm.js <strong>basic-ftp</strong> module for it. The code for my connection is given below:</p>
<pre><code>let client = new ftp.Client(ftpTimeout * 1000);
client.prepareTransfer = prepareTransfer;
</code></pre>
<p>And prepareTransfer has  implementation like:</p>
<pre><code>export async function prepareTransfer(ftp: FTPContext): Promise&lt;FTPResponse&gt; {
  // Gets the  ip address of either LoadBalancer(for LoadBalancer service) or Node(For NodePort Service)
   const ip = await getIp();
  // Gets a TargetPort for LoadBalancer service or Node Port for NodePort service
  const port = await getFtpPort();

  // Example command: PORT 192,168,150,80,14,178
  // The first four octets are the IP address while the last two octets comprise the 
  //port that will be used for the data connection.
  // To find the actual port multiply the fifth octet by 256 and then add the sixth 
  //octet to the total.
  // Thus in the example above the port number is ( (14*256) + 178), or 3762
  const p1 = Math.floor(port / 256);
  const p2 = port % 256;
  const command = `PORT ${ip.replace(/\./g, ',')},${p1},${p2}`;

  // https://github.com/patrickjuchli/basic-ftp/issues/195
  // Data socket pipes before the connection so use the mock socket.
  const mockSocket = new MockSocket();
  ftp.dataSocket = mockSocket as any;

  let ftpResponse = new Promise&lt;FTPResponse&gt;((resolve, reject) =&gt; {
    let response: FTPResponse;
    const server = createServer(function (socket) {
      console.log('FTP Client connected');
      mockSocket.setSocket(socket, server, port);
    });

    server.on('error', err =&gt; {
      reject(err);
    });
    server.listen(port, async () =&gt; {
      console.log(`socket server for FTP started at port ${port}`);
      // send the port request
      response = await ftp.request(command);
      if (response.code !== 200) {
        reject('Could not connect');
        server.close();
      }
      resolve(response);
    });
  });

  return ftpResponse;
}
</code></pre>
<p>Any idea why NodePort is not working here?</p>
<p>Helm Chart for NodePort:</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: &quot;ftp-service&quot;
spec:
  type: NodePort
  externalTrafficPolicy: Local
  selector:
    statefulset.kubernetes.io/pod-name: &quot;pod1&quot;
  ports:
  - protocol: TCP
    name: ftp-8000
    port: 8000
    targetPort: 8000
    nodePort: 30014
</code></pre>
<p>Helm chart for loadbalancer:</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: &quot;ftp-service-load&quot;
spec:
  type: LoadBalancer 
  externalTrafficPolicy: Local
  selector:
    statefulset.kubernetes.io/pod-name: &quot;pod1&quot;
  ports:
  - protocol: TCP
    name: ftp-8000
    port: 8000
    targetPort: 8000
    nodePort: 30014
</code></pre>

<p>ok, finally I figured out the solution. I have been using <strong>Azure Kubernetes Service(AKS)</strong>. Need to set the inbound port rule for the appropriate <code>NodePort</code>(under  <strong>Virtual machine scale sets</strong>, selecting the right node pools whose public IPs are enabled, and under <strong>Networking</strong> tab). Also, need to make <code>externalTrafficPolicy</code> to <code>Cluster</code> or simply remove the line   <code>externalTrafficPolicy: Local</code> from the helm chart.</p>
