8
votes

I can't connect to my app running with nginx ingress (Docker Desktop win 10).

The nginx-ingress controller pod is running, the app is healthy, and I have created an ingress. However, when I try to connect to my app on localhost, I get "connection refused".

I see this error in the log:

[14:13:13.028][VpnKit            ][Info   ] vpnkit.exe: Connected Ethernet interface f6:16:36:bc:f9:c6

[14:13:13.028][VpnKit            ][Info   ] vpnkit.exe: UDP interface connected on 10.96.181.150

[14:13:22.320][GoBackendProcess  ][Info   ] Adding vpnkit-k8s-controller tcp forward from 0.0.0.0:80 to 10.96.47.183:80
[14:13:22.323][ApiProxy          ][Error  ] time="2019-12-09T14:13:22-05:00" msg="Port 443 for service ingress-nginx is already opened by another service"

I think port 443 is used by another app, possibly zscaler security or skype. Excerpt from netstat -a -b:

 [svchost.exe]
  TCP    0.0.0.0:443            0.0.0.0:0              LISTENING       16012
 [com.docker.backend.exe]
  TCP    0.0.0.0:443            0.0.0.0:0              LISTENING       8220

I don't know how to make the ingress work. Please help!

My ingress:

$ kubectl describe ing kbvalues-deployment-dev-ingress
Name:             kbvalues-deployment-dev-ingress
Namespace:        default
Address:          localhost
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host       Path  Backends
  ----       ----  --------
  localhost
             /   kbvalues-deployment-dev-frontend:28000 (10.1.0.174:8080)
Annotations:
  kubernetes.io/ingress.class:                     nginx
  nginx.ingress.kubernetes.io/cors-allow-headers:  X-Forwarded-For, X-app123-XPTO
Events:
  Type    Reason  Age               From                      Message
  ----    ------  ----              ----                      -------
  Normal  CREATE  42m               nginx-ingress-controller  Ingress default/kbvalues-deployment-dev-ingress
  Normal  UPDATE  6s (x5 over 42m)  nginx-ingress-controller  Ingress default/kbvalues-deployment-dev-ingress

My service:

$ kubectl describe svc kbvalues-deployment-dev-frontend
Name:              kbvalues-deployment-dev-frontend
Namespace:         default
Labels:            chart=tomcat-sidecar-war-1.0.4
                   environment=dev
                   name=kbvalues-frontend-dev
                   release=kbvalues-test
                   tier=frontend
Annotations:       <none>
Selector:          app=kbvalues-dev
Type:              ClusterIP
IP:                10.98.89.94
Port:              <unset>  28000/TCP
TargetPort:        8080/TCP
Endpoints:         10.1.0.174:8080
Session Affinity:  None
Events:            <none>

I am trying to access the app at: http://localhost:28000/health. I verified that the /health URL is accessible locally within the web server container.

I appreciate any help you can offer.

Edit:

I tried altering the ingress-nginx service to remove HTTPS, as suggested here: https://stackoverflow.com/a/56303330/166850

This got rid of the 443 error in the logs, but didn't fix my setup (still getting connection refused).

Edit 2: Here is the Ingress YAML definition (kubectl get -o yaml):

$ kubectl get ing -o yaml
apiVersion: v1
items:
- apiVersion: extensions/v1beta1
  kind: Ingress
  metadata:
    annotations:
      kubernetes.io/ingress.class: nginx
    creationTimestamp: "2019-12-09T18:47:33Z"
    generation: 5
    name: kbvalues-deployment-dev-ingress
    namespace: default
    resourceVersion: "20414"
    selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/kbvalues-deployment-dev-ingress
    uid: 5c34bf7f-1ab4-11ea-80e4-00155d169409
  spec:
    rules:
    - host: localhost
      http:
        paths:
        - backend:
            serviceName: kbvalues-deployment-dev-frontend
            servicePort: 28000
          path: /
  status:
    loadBalancer:
      ingress:
      - hostname: localhost
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

Edit 3: Output of kubectl get svc -A (ingress line only):

ingress-nginx   ingress-nginx                      LoadBalancer   10.96.47.183     localhost     80:30470/TCP             21h

Edit 4: I tried to get the VM's IP address from windows HyperV, but it seems like the VM doesn't have an IP?

PS C:\> (Get-VMNetworkAdapter -VMName DockerDesktopVM)

Name            IsManagementOs VMName          SwitchName MacAddress   Status IPAddresses
----            -------------- ------          ---------- ----------   ------ -----------
Network Adapter False          DockerDesktopVM DockerNAT  00155D169409 {Ok}   {}

Edit 5:

Output of netstat -a -n -o -b for port 80:

  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       4
 Can not obtain ownership information
4
Are you able to access the service without Ingress? Like directly hitting the service IP and port works?Shubham
You should try doing kubectl exec -it <your nginx pod> /bin/bash, run the curl command for what Shubham suggested and check your outputs.randominstanceOfLivingThing
What's the output of kubectl get svc -A (only pasting the ingress line)? I suspect your ingress service is not configured correctly. For cloud environments, i'd expect the Type to be LoadBalancer however for your case, I think you may need to configure it to use NodePort where you'd access your ingress using a port (E.g., localhost:30252/myapp).leeman24
@Shubham @randominstanceOfLivingThing I was able to access the service successfully using: kubectl port-forward svc/kbvalues-deployment-dev-frontend 28000 and hitting: http://localhost:28000/healthRMorrisey
@RMorrisey if your comment solved your problem please provide an answer to your post and accept it for future reference.Dawid Kruk

4 Answers

23
votes

I have managed to create Ingress resource in Kubernetes on Docker in Windows.

Steps to reproduce:

  • Enable Hyper-V
  • Install Docker for Windows and enable Kubernetes
  • Connect kubectl
  • Enable Ingress
  • Create deployment
  • Create service
  • Create ingress resource
  • Add host into local hosts file
  • Test

Enable Hyper-V

From Powershell with administrator access run below command:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

System could ask you to reboot your machine.

Install Docker for Windows and enable Kubernetes

Install Docker application with all the default options and enable Kubernetes

Connect kubectl

Install kubectl .

Enable Ingress

Run this commands:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml

Edit: Make sure no other service is using port 80

Restart your machine. From a cmd prompt running as admin, do: net stop http Stop the listed services using services.msc

Use: netstat -a -n -o -b and check for other processes listening on port 80.

Create deployment

Below is simple deployment with pods that will reply to requests:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
spec:
  selector:
    matchLabels:
      app: hello
      version: 2.0.0
  replicas: 3
  template:
    metadata:
      labels:
        app: hello
        version: 2.0.0
    spec:
      containers:
      - name: hello
        image: "gcr.io/google-samples/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50001"

Apply it by running command:

$ kubectl apply -f file_name.yaml

Create service

For pods to be able for you to communicate with them you need to create a service.

Example below:

apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  type: NodePort
  selector:
    app: hello
    version: 2.0.0
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 50001

Apply this service definition by running command:

$ kubectl apply -f file_name.yaml

Create Ingress resource

Below is simple Ingress resource using service created above:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hello-ingress 
spec:
  rules:
  - host: kubernetes.docker.internal
    http:
      paths:
      - path: /
        backend:
          serviceName: hello-service 
          servicePort: http

Take a look at:

spec:
  rules:
  - host: hello-test.internal 

hello-test.internal will be used as the hostname to connect to your pods.

Apply your Ingress resource by invoking command:

$ kubectl apply -f file_name.yaml

Add host into local hosts file

I found this Github link that will allow you to connect to your Ingress resource by hostname.

To achieve that add a line 127.0.0.1 hello-test.internal to your C:\Windows\System32\drivers\etc\hosts file and save it. You will need Administrator privileges to do that.

Edit: The newest version of Docker Desktop for Windows already adds a hosts file entry: 127.0.0.1 kubernetes.docker.internal

Test

Display the information about Ingress resources by invoking command: kubectl get ingress

It should show:

NAME            HOSTS                 ADDRESS     PORTS   AGE
hello-ingress   hello-test.internal   localhost   80      6m2s

Now you can access your Ingress resource by opening your web browser and typing

http://kubernetes.docker.internal/

The browser should output:

Hello, world!
Version: 2.0.0
Hostname: hello-84d554cbdf-2lr76

Hostname: hello-84d554cbdf-2lr76 is the name of the pod that replied.

If this solution is not working please check connections with the command: netstat -a -n -o (with Administrator privileges) if something is not using port 80.

1
votes

On Windows the Kubernetes cluster is running in a VM. Try to access ingress on that VM-s IP address instead of localhost.

0
votes

i was facing similar issue while deploying ingress-nginx controller using the manual steps mentioned for bareMetal node at ingress-nginx-deploy however was facing an issue , however referred to the link Github link mentioned by @RMorrisey which leads to other threads where they have mentioned to install ingress-nginx using the steps mentioned for mac and it worked without making cny changes to host file , etc

0
votes

The problem is that your service has a type of ClusterIP, which isn't accessible externally. You need it to be of type NodePort, which is what is done in Dawid Kruk's instructions.