I have Kubernetes running in Docker for Windows.
I am using NGINX ingress controller, I have applied the mandatory.yaml
and the cloud-generic.yaml
.
> kubectl get services -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx LoadBalancer 10.110.198.161 localhost 80:30037/TCP,443:31218/TCP 5h
I have an image in my local registry test-app/mock-service:1.0.0
which exposes port 8080 running a server with a single endpoint GET /mocks
. Running this in Docker using docker run -d -p 8080:8080 test-app/mock-service:1.0.0
works and I can see the expected result.
My intention is to deploy this using Kubernetes.
I created a deployment and service resource:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: test-app-mock-service-deployment
namespace: test-app
spec:
selector:
matchLabels:
app: test-app-mock-service
replicas: 1
template:
metadata:
labels:
app: test-app-mock-service
spec:
containers:
- name: test-app-mock-service-container
image: "test-app/mock-service:1.0.0"
---
apiVersion: v1
kind: Service
metadata:
name: test-app-mock-service
namespace: test-app
spec:
type: ClusterIP
selector:
app: test-app-mock-service
ports:
- port: 8080
targetPort: 8080
protocol: TCP
And an ingress resource:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-app-ingress
namespace: test-app
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
spec:
rules:
- http:
paths:
- path: /mocks
backend:
serviceName: test-app-mock-service
servicePort: 8080
I can see the service:
> kubectl get services -n test-app
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
test-app-mock-service ClusterIP 10.108.10.246 <none> 8080/TCP 1h
And the pod:
> kubectl get pods -n test-app
NAME READY STATUS RESTARTS AGE
test-app-mock-service-deployment-6b9b58fcb9-mdskn 1/1 Running 0 59m
I can see the ingress:
> kubectl describe ingress test-app-ingress -n test-app
Name: test-app-ingress
Namespace: test-app
Address: localhost
Default backend: default-http-backend:80 (<none>)
Rules:
Host Path Backends
---- ---- --------
*
/mocks test-app-mock-service:8080 (<none>)
Annotations:
ingress.kubernetes.io/ssl-redirect: true
kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"ingress.kubernetes.io/ssl-redirect":"true"},"name":"test-app-ingress","namespace":"test-app"},"spec":{"rules":[{"http":{"paths":[{"backend":{"serviceName":"test-app-mock-service","servicePort":8080},"path":"/mocks"}]}}]}}
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CREATE 1h nginx-ingress-controller Ingress test-app/test-app-ingress
Normal UPDATE 53m (x2 over 1h) nginx-ingress-controller Ingress test-app/test-app-ingress
However when I browse to http://localhost/mocks
i get a 308 to https://localhost/mocks
where I get a 404.
I'm not sure if the ingress is incorrectly configured or if it is another problem.
What is likely happening is that the SSL portion is using SNI and since there is no host or default backend set nginx doesn't know where to send the request. There are two things you can do to solve this.
You can add an annotation to set a default backend for requests without a host or route. The documentation for this is at https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#default-backend. In your example it would be:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-app-ingress
namespace: test-app
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/default-backend: test-app-mock-service
spec:
rules:
- http:
paths:
- path: /mocks
backend:
serviceName: test-app-mock-service
servicePort: 8080
Your spec contains no TLS hostname. Adding one should allow SNI to know what name needs to be used for the routing rules specified:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-app-ingress
namespace: test-app
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/default-backend: test-app-mock-service
spec:
tls:
- hosts:
- localhost
secretName: tls-secret
rules:
- http:
paths:
- path: /mocks
backend:
serviceName: test-app-mock-service
servicePort: 8080
Though, if you are using the self-signed certificate you will likely need to find the name of it. You may need to generate your own. See https://kubernetes.github.io/ingress-nginx/user-guide/tls/ for more information on that.