Enable Ingress controller on Docker Desktop with WLS2 - docker

Currently, I'm using Docker Desktop with WSL2 integration. I found that Docker Desktop automatically had created a cluster for me. It means I don't have to install and use Minikube or Kind to create cluster.
The problem is that, how could I enable Ingress Controller if I use "built-in" cluster from Docker Desktop?
I tried to create an Ingress to check if this work or not, but as my guess, it didn't work.
The YAML file I created as follows:
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
minReadySeconds: 30
selector:
matchLabels:
app: webapp
replicas: 1
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nodejs-helloworld:v1
---
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
selector:
app: webapp
ports:
- name: http
port: 3000
nodePort: 30090 # only for NotPort > 30,000
type: NodePort #ClusterIP inside cluster
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: webapp-ingress
spec:
defaultBackend:
service:
name: webapp-service
port:
number: 3000
rules:
- host: ingress.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp-service
port:
number: 3000
I tried to access ingress.local/ but it was not successful. (I added ingress.local to point to 127.0.0.1 in host file. And the webapp worked fine at kubernetes.docker.internal:30090 )
Could you please help me to know the root cause?
Thank you.

Finally I found the way to fix. I have to deploy ingress Nginx by command:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.41.2/deploy/static/provider/cloud/deploy.yaml
(Follows the instruction at https://kubernetes.github.io/ingress-nginx/deploy/#docker-for-mac. It works just fine for Docker for Windows)
Now I can access http://ingress.local successfully.

You have to install an ingress-nginx controller on your cluster, so that your nodes will have an opened port 80/443.
Using helm (v3 - see documentation):
helm install --namespace kube-system nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx
Using kubectl (see documentation):
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.43.0/deploy/static/provider/cloud/deploy.yaml
Then manually adding your ingresses' hostnames to /etc/hosts:
127.0.0.1 ingress.local
127.0.0.1 my.other.service.local
# ...
Then if you make a request on http://ingress.local:
the DNS resolution will route to your cluster node
then the ingress controller will serve the request on port 80
then ingress will route the request to the configured backend service
and the service will route to an available pod

The newest version of Docker Desktop for Windows already adds a hosts file entry: 127.0.0.1 kubernetes.docker.internal.
You had to do use kubernetes.docker.internal URL as a hostname in Ingress definition if you want to point to 127.0.0.1. This should be in the docs on this page kubernetes.github.io/ingress-nginx/deploy but there is no Docker Desktop for Windows section there.
Your files should look like this:
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
type: NodePort
selector:
app: webapp
ports:
- name: http
protocol: TCP
port: 3000
nodePort: 30090
Your Ingress file should look like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: webapp-ingress
spec:
rules:
- host: kubernetes.docker.internal
http:
paths:
- path: /
backend:
serviceName: webapp-service
servicePort: http
Then you are able to connect to app using http://kubernetes.docker.internal/.
Example you can see here: wsl2-docker-for-desktop.

I used the Docker-Desktop version to install the nginx-ingress controller
https://kubernetes.github.io/ingress-nginx/deploy/#docker-desktop
curl http://kubernetes.docker.internal/
Offcourse I've not installed any workload yet but the default ingress controller works just fine.

With Kustomize you can simply use
helmCharts:
- name: ingress-nginx
releaseName: ingress-nginx
repo: https://kubernetes.github.io/ingress-nginx

This is just to point out that Amel Mahmuzićs comment is still valid with a recent (I used the ingress-nginx Helm Chart 4.4.2) ingress deployment.
I could not get this to work for far too long (I tried to follow the Strapi fodadvisor example with Docker Desktop build in Kubernetes instead of minikube) and always received a 404 from the ingress.
However, after using this yaml with the added annotation
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: foodadvisor.backend
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: foodadvisor-backend
port:
number: 1337
- host: foodadvisor.client
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: foodadvisor-frontend
port:
number: 3000
it worked immediately. The K82 docs mention, that this annotation is deprecated.

Related

Nginx Ingress: doesn't run services and get 503 service unavailable

I am trying to create an ingress file to route urls into the inside services. but after calling in postman, it just returns 503 error.
this is my ingress file config:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-srv
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
rules:
- host: posts.com
http:
paths:
- path: /posts/create
pathType: Prefix
backend:
service:
name: posts-clusterip-srv
port:
number: 7000
this is my posts deployment file and cluster ip:
apiVersion: apps/v1
kind: Deployment
metadata:
name: posts-depl
spec:
replicas: 1
selector:
matchLabels:
app: posts
template:
metadata:
labels:
app: posts
spec:
containers:
- name: posts
image: 4765/posts
---
apiVersion: v1
kind: Service
metadata:
name: posts-clusterip-srv
spec:
selector:
app: posts
ports:
- name: posts
protocol: TCP
port: 7000
targetPort: 7000
when in postman I send this request http://posts.com/posts/create just returns 503 service unavailable. I try to curl the cluster Ip curl http://posts-clusterip-srv:7000 but it responses Could not resolve host: posts-clusterip-srv
I don't know what to do?
Does your app server accept request on /?
As path: /posts/create will forward the request to your server which will receive a request on /.
Concerning the curl http://posts-clusterip-srv:7000 it depends of the set up of your cluster:
If you are using a local cluster on your computer you should modify your /etc/hosts add your local IP as posts.com then you should be able to curl it.
If your cluster is on a server it seems that it is a DNS problem, same way as above you can add the server IP to your hosts file to avoid using the DNS.

Minikube exposed service url returns connection refused but kubectl port-forward working fine

I did this setup to test kubernetes with minikube 'Set up Ingress on Minikube' and everything worked fine.
Then I tried to do the same with my own app and am having a problem after configuring all the steps.
The steps that I did to setup my app and kubernetes are:
Create an app that works on port 5000
Containarized the app in a docker image and upload to the minikube image registry
Created a deployment for kubernetes with my container
Run kubectl port-forward pod/app 5000 and everyting works fine
Created a service with type Nodeport to expose the deployment
Run kubectl port-forward service/app-service 5000 and everyting works fine
Created an ingress to expose the service
Run curl app.info and it returns 502 bad gateway
Tryied again kubectl port-forward service/app-service 5000 and it still works fine
Check minikube service app-service --url and tried the result URL and it returns Connection refused, the equivalent url in the demo setup that I did previously works fine so it looks like something is wrong in this step even when doing the port-forwarding works correctly.
kind: Deployment
metadata:
namespace: echo-app
name: app
labels:
app: echo
tier: services
spec:
replicas: 1
selector:
matchLabels:
tier: services
template:
metadata:
labels:
tier: services
spec:
containers:
- name: echo-api
image: echo/api:v1.0.0b39c8f9a
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5000
apiVersion: v1
kind: Service
metadata:
name: app-service
namespace: echo-app
spec:
type: NodePort
selector:
tier: services
ports:
- protocol: TCP
port: 5000
targetPort: 5000
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
namespace: echo-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: echo.info
http:
- paths:
path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 5000

How to expose postgres tcp port using Docker Desktop for Windows Kubernetes and ingress-nginx

I'm using "Docker Desktop for Windows" with kubernetes. So far, its great.
I'd like to manage my postgress db (TCP:5432). I'm using the kubernetes "ingress-nginx" ingress controller, which saws it can be configured to expose TCP using a configmap.
Here is what I have so far:
apiVersion: v1
kind: ConfigMap
metadata:
name: tcp-services
namespace: ingress-nginx
data:
5432: "ingress-nginx/postgres:5432"
---
# SEE: https://kubernetes.io/docs/concepts/services-networking/ingress/
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-myproject.com
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: clusterissuer-selfsigned
# See: https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/rewrite/README.md
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
spec:
tls:
- hosts:
- www.myproject.com
secretName: tls-myproject
rules:
# Avoid Quasar build paths: /css, /fonts, /icons, /js
- http:
paths:
# See https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/rewrite/README.md
- path: /data(/|$)(.*)
pathType: Prefix
backend:
service:
name: backend
port:
number: 80
...
Now I need to:
add the "--tcp-services-configmap=" argument
expose 5432 if 1) doesn't do this automatically.
I found the ingress-nginx-controller in the kubernetes dashboard and hand edited like below, but it's behavior didn't change.
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
template:
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
spec:
volumes:
- name: webhook-cert
secret:
secretName: ingress-nginx-admission
defaultMode: 420
containers:
- name: controller
image: >-
k8s.gcr.io/ingress-nginx/controller:v0.41.0#sha256:e6019e536cfb921afb99408d5292fa88b017c49dd29d05fc8dbc456aa770d590
args:
- /nginx-ingress-controller
- '--publish-service=$(POD_NAMESPACE)/ingress-nginx-controller'
- '--election-id=ingress-controller-leader'
- '--ingress-class=nginx'
- '--configmap=$(POD_NAMESPACE)/ingress-nginx-controller'
- '--validating-webhook=:8443'
- '--validating-webhook-certificate=/usr/local/certificates/cert'
- '--validating-webhook-key=/usr/local/certificates/key'
- '--tcp-services-configmap=ingress-nginx/tcp-services'
What am I missing? How can I configure this w/o having to hand edit it? Thank you!
I think there are 2 issues.
You need to install nginx separately from your postgress installation. This means that you will have some nginx pods/deployments, and a service that exist in the ingress-nginx namespace. To do this, follow the guide here. It is recommended that you follow a yaml file from the cloud section for a docker desktop deployment. This is someone who has gone through the process.
Once nginx is installed on your cluster, you need to go from you postgress deployment/pod -> service -> ingress. These will be in a different namespace than your ingress-nginx one (default is fine). To configure it, you can follow the guide located here. If you want to test things along the way, you can use kubernetes port-forwarding command to forward your postgress pod to your local machine. You can also test your service with the same method.

Kubernetes Nginx Ingress Controller expose Nginx Webserver

I basically want to access the Nginx-hello page externally by URL. I've made a (working) A-record for a subdomain to my v-server running kubernetes and Nginx ingress: vps.my-domain.com
I installed Kubernetes via kubeadm on CoreOS as a single-node cluster using these tutorials: https://kubernetes.io/docs/setup/independent/install-kubeadm/, https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/, and nginx-ingress using https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal.
I also added the following entry to the /etc/hosts file:
31.214.xxx.xxx vps.my-domain.com
(xxx was replaced with the last three digits of the server IP)
I used the following file to create the deployment, service, and ingress:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- name: http
containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
type: ClusterIP
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
run: my-nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
ingress.kubernetes.io/ssl-redirect: "False"
spec:
rules:
- host: vps.my-domain.com
http:
paths:
- backend:
serviceName: my-nginx
servicePort: 80
Output of describe ing:
core#vps ~/k8 $ kubectl describe ing
Name: my-nginx
Namespace: default
Address:
Default backend: default-http-backend:80 (<none>)
Rules:
Host Path Backends
---- ---- --------
vps.my-domain.com
my-nginx:80 (<none>)
Annotations:
kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"extensions/v1beta1",...}
kubernetes.io/ingress.class: nginx
ingress.kubernetes.io/ssl-redirect: False
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal UPDATE 49m (x2 over 56m) nginx-ingress-controller Ingress default/my-nginx
While I can curl the Nginx hello page using the nodeip and port 80 it doesn't work from outside the VM. Failed to connect to vps.my-domain.com port 80: Connection refused
Did I forgot something or is the configuration just wrong? Any help or tips would be appreciated!
Thank you
EDIT:
Visiting "vps.my-domain.com:30519` gives me the nginx welcome page. But in the config I specified port :80.
I got the port from the output of get services:
core#vps ~/k8 $ kubectl get services --all-namespaces | grep "my-nginx"
default my-nginx ClusterIP 10.107.5.14 <none> 80/TCP 1h
I also got it to work on port :80 by adding
externalIPs:
- 31.214.xxx.xxx
to the my-nginx service. But this is not how it's supposed to work, right? In the tutorials and examples for kubernetes and ingress-nginx, it worked always without externalIPs. Also the ingress rules doesn't work now (e.g. if I set the path to /test).
So apparently I was missing one part: the load balancer. I'm not sure why this wasn't mentioned in those instructions as a requirement. But i followed this tutorial: https://kubernetes.github.io/ingress-nginx/deploy/baremetal/#a-pure-software-solution-metallb and now everything works.
Since metallb requires multiple ip addresses, you have to list your single ip-adress with the subnet \32: 31.214.xxx.xxx\32

How to access MySql hosted with Nginx Ingress+Kubernetes from client

I am new to Kubernetes and Nginx Ingress tools and now i am trying to host MySql service using VHost in Nginx Ingress on AWS. I have created a file something like :
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
type: NodePort
ports:
- port: 3306
protocol: TCP
selector:
app: mysql
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: mysql
labels:
app: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: password
ports:
- name: http
containerPort: 3306
protocol: TCP
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: mysql
labels:
app: mysql
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: mysql.example.com
http:
paths:
- path: /
backend:
serviceName: mysql
servicePort: 3306
My LoadBalancer (created by Nginx Ingress) port configuration looks like :
80 (TCP) forwarding to 32078 (TCP)
Stickiness options not available for TCP protocols
443 (TCP) forwarding to 31480 (TCP)
Stickiness options not available for TCP protocols
mysql.example.com is pointing to my ELB.
I was expecting something like, from my local box i can connect to MySql if try something like :
mysql -h mysql.example.com -u root -P 80 -p
Which is not working out. Instead of NodePort if i try with LoadBalancer, its creating a new ELB for me which is working as expected.
I am not sure if this is right approach for what i want to achieve here. Please help me out if there is a way for achieving same using the Ingress with NodePort.
Kubernetes Ingress as a generic concept does not solve the issue of exposing/routing TCP/UDP services, as stated in https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/exposing-tcp-udp-services.md you should use custom configmaps if you want that with ingress. And please mind that it will never use hostname for routing as that is a feature of HTTP, not TCP.
I succeded to access MariaDB/MySQL hosted on Google Kubernetes Engine through ingress-nginx, using the hostname specified in the ingress created for the database Cluster IP.
As per the docs, simply create the config map and expose the port in the Service defined for the Ingress.
This helped me to figure how to set --tcp-services-configmap and --udp-services-configmap flags.

Resources