<p>SFTP server is not accessible when exposed using a NodePort service and an Kubernetes Ingress. However, if the same deployment is exposed using a Service of type LoadBalancer it works fine.</p>

<p>Below is the deployment file for SFTP in <a href="https://cloud.google.com/kubernetes-engine/" rel="nofollow noreferrer">GKE</a> using <a href="https://github.com/atmoz/sftp" rel="nofollow noreferrer">atmoz/sftp</a> Dockerfile.</p>

<pre><code>kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: sftp
  labels:
    environment: production
    app: sftp
spec:
  replicas: 1
  minReadySeconds: 10
  template:
    metadata:
      labels:
        environment: production
        app: sftp
      annotations:
        container.apparmor.security.beta.kubernetes.io/sftp: runtime/default
    spec:
      containers:
        - name: sftp
          image: atmoz/sftp:alpine
          imagePullPolicy: Always
          args: ["user:pass:1001:100:upload"]
          ports:
            - containerPort: 22
          securityContext:
            capabilities:
              add: ["SYS_ADMIN"]
          resources: {}
</code></pre>

<p>If I expose this deployment normally using a Kubernetes Service of type LoadBalancer like below:</p>

<pre><code>apiVersion: v1
kind: Service
metadata:
  labels:
    environment: production
  name: sftp-service
spec:
  type: LoadBalancer
  ports:
  - name: sftp-port
    port: 22
    protocol: TCP
    targetPort: 22
  selector:
    app: sftp
</code></pre>

<p>Above Service gets an external IP which I can simply use in the command <code>sftp xxx.xx.xx.xxx</code> command to get access using the <code>pass</code> password.</p>

<p>However, I try to expose the same deployment using GKE Ingress it does not work. Below is the manifest for the ingress:</p>

<pre><code>
# First I create a NodePort service to expose the deployment internally

---
apiVersion: v1
kind: Service
metadata:
  labels:
    environment: production
  name: sftp-service
spec:
  type: NodePort
  ports:
  - name: sftp-port
    port: 22
    protocol: TCP
    targetPort: 22
    nodePort: 30063
  selector:
    app: sftp

# Ingress service has SFTP service as it's default backend
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: basic-ingress-2
spec:
  backend:
    serviceName: sftp-service
    servicePort: 22
  rules:
  - http:
      paths:
      # "http-service-sample" is a service exposing a simple hello-word app deployment
      - path: /sample
        backend:
          serviceName: http-service-sample
          servicePort: 80
</code></pre>

<p>After an external IP is assigned to the Ingress (I know it takes a few minutes to completely set up) and <code>xxx.xx.xx.xxx/sample</code> starts working but <code>sftp -P 80 xxx.xx.xx.xxx</code> doesn't work.</p>

<p>Below is the error I get from the server:</p>

<pre><code>ssh_exchange_identification: Connection closed by remote host
Connection closed
</code></pre>

<p>What am I doing wrong in the above set-up? Why does LoadBalancer service is able to allow access to SFTP service, while Ingress fails?</p>

<p>That's currently not fully supported to route in Kubernetes Ingress any other traffic than HTTP/HTTPS protocols (see <a href="https://kubernetes.io/docs/concepts/services-networking/ingress/#what-is-ingress" rel="noreferrer">docs</a>). </p>

<p>You can try to make some workaround as described there: <a href="https://stackoverflow.com/questions/49439899/kubernetes-routing-non-http-request-via-ingress-to-container">Kubernetes: Routing non HTTP Request via Ingress to Container</a> </p>
