i have deployed swagger UI on Kubernetes. now it's not sending a request to internal service of Kubernetes when clicking on the Try it out button.
Since all service running locally in Kubernetes we have to use HTTP but my swagger UI is on HTTPS so getting mixed content error also.
is there any way we can invoke internal service using swagger UI running inside Kubernetes.
this is my demo swagger.yaml :
openapi: 3.0.1
servers:
- url: '{scheme}://test-service'
variables:
scheme:
description: 'The Data Set API is accessible via https and http'
enum:
- 'https'
- 'http'
default: 'https'
info:
description: >-
i would rather suggest using ingress and add further rule with https domain.
ingress :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: swagger-staging
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: swagger-ingress
namespace: default
spec:
rules:
- host: example.com
http:
paths:
- path: /test-service(/|$)(.*)
backend:
serviceName: service-1
servicePort: 80
- path: service-2(/|$)(.*)
backend:
serviceName: service-2
servicePort: 80
- path: /service-3(/|$)(.*)
backend:
serviceName: service-3
servicePort: 80
- path: /service-4(/|$)(.*)
backend:
serviceName: service-4
servicePort: 80
- path: /service-5(/|$)(.*)
backend:
serviceName: service-5
servicePort: 80
note : if you will try updating ingress with https and later try with port-forward it will not work and same give error of browser mixed content .
You can use port-forwarding:
kubectl -n <namespace> port-forward svc/<your-swagger-service> <localhost-port>:<swagger-port-in-your-svc>
And then go to localhost:<localhost-port>
Another way to that is using internal load balancer there's some options depends on your cloud provider.
Related
I am trying to learn .NET Microservice. I have been following a great tutorial on Youtube (Time: 4:44:55, Adding An API Gateway). Everything worked well until NGINX Ingress came into the picture. I pasted the same YAML file from the GitHub account of the trainer I doubled checked all the things but couldn't find anything:
I can see all the pods and services are working fine:
I updated my host file.
What did I miss?
URL, I am using: http://acme.com/api/platforms/
Error: HTTP Error 404. The requested resource is not found.
The output of the Ingress YAML:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.k8s.io/v1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx","nginx.ingress.kubernetes.io/use-regex":"true"},"name":"ingress-srv","namespace":"default"},"spec":{"rules":[{"host":"acme.com","http":{"paths":[{"backend":{"service":{"name":"platforms-clusterip-srv","port":{"number":80}}},"path":"/api/platforms","pathType":"Prefix"},{"backend":{"service":{"name":"commands-clusterip-srv","port":{"number":80}}},"path":"/api/c/platforms","pathType":"Prefix"}]}}]}}
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
creationTimestamp: "2021-09-18T00:12:41Z"
generation: 1
name: ingress-srv
namespace: default
resourceVersion: "2274742"
uid: a7376202-8b1b-4f1a-a42f-08de5f602192
spec:
rules:
- host: acme.com
http:
paths:
- backend:
service:
name: platforms-clusterip-srv
port:
number: 80
path: /api/platforms
pathType: Prefix
- backend:
service:
name: commands-clusterip-srv
port:
number: 80
path: /api/c/platforms
pathType: Prefix
status:
loadBalancer:
ingress:
- hostname: localhost
Services:
UPDATE: Tried below commands and got some new information:
UPDATE: Result of
Kubectl get pods --namespace=ingress-nginx
Try removing the regex annotation from th ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
name: ingress-srv
namespace: default
spec:
rules:
- host: acme.com
http:
paths:
- backend:
service:
name: platforms-clusterip-srv
port:
number: 80
path: /api/platforms
pathType: Prefix
- backend:
service:
name: commands-clusterip-srv
port:
number: 80
path: /api/c/platforms
pathType: Prefix
or just try this nginx.ingress.kubernetes.io/rewrite-target: /
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: acme.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: commands-clusterip-srv
port:
number: 80
in above ingress, all requests will go to service commands-clusterip-srv so from browser side you pass anything either /api or /api/c ingress will route the traffic to that service if your host is acme.com
Error 404 clearly means there is some issue with your Nginx configuration path is not matching or host issue, Nginx not able to find upstream or target so it throws 404.
Update
Try adding IP and entry into the host file for
192.168.1.28 acme.com
i am not sure you have used the IP POD to curl ideally you should me using the acme.com as you can to access the data.
also hope you service, deployment and ingress are in same namespace.
First of all, Thank you Harsh for your precious time. I tried all the things but no error was found.
It was really a miracle that I am able to resolve it issue on HTTPS. I am able to access "https://acme.com/api/platforms". But still, HTTP is giving me the same error. However, I am fine with HTTPS
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.
I am trying to configure Traefik and WSO2 API Manager. Basically, I want to configure Traefik to handle https.
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.service-am-https.redirectscheme.scheme=https"
- "traefik.http.routers.service-am-http.entrypoints=web"
- "traefik.http.routers.service-am-http.rule=Host(`xx.xx.xx`) && Path(`/apim/admin`)"
- "traefik.http.routers.service-am-http.middlewares=service-am-https#docker"
- "traefik.http.routers.service-am.tls=true"
- "traefik.http.routers.service-am.rule=Host(`xx.xx.xx`) && Path(`/apim/admin`)"
- "traefik.http.routers.service-am.entrypoints=web-secure"
- "traefik.http.services.service-am.loadbalancer.server.port=9443"
I also included this in the deployment.toml file for API Manager.
[catalina.valves.valve.properties]
className = "org.apache.catalina.valves.RemoteIpValve"
internalProxies = "*"
remoteIpHeader ="x-forwarded-for"
proxiesHeader="x-forwarded-by"
trustedProxies="*"
When I try to access the service, https://xx.xx.xx/apim/admin, I get this error:
Bad Request
This combination of host and port requires TLS.
Traefik is successfully handling the https part but when it comes to WSO2 API Manager, this issue comes up. Any ideas on how to resolve this?
I just had this problem and solved including
annotations:
ingress.kubernetes.io/protocol: https
in my Ingress.
The full configuration:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: wso2-ingress
namespace: <namespace>
annotations:
kubernetes.io/ingress.class: traefik
traefik.frontend.rule.type: PathPrefixStrip
ingress.kubernetes.io/protocol: https
spec:
rules:
- host: <hostname>
http:
paths:
- path: /
backend:
serviceName: <service-name>
servicePort: 9443
I am trying to create an ingress controller that points to a service that I have exposed via NodePort.
Here is the yaml file for the ingress controller (taken from https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/):
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: hello-world.info
http:
paths:
- path: /
backend:
serviceName: appName
servicePort: 80
I can connect directly to the node port and the frontend is displayed.
Please note that I am doing this because the frontend app is unable to connect to other deployments that I have created and I read that an ingress controller would be able to solve the issue. Will I still have to add an Nginx reverse proxy? If so how would I do that? I have tried adding this to the nginx config file but with no success.
location /middleware/ {
proxy_pass http://middleware/;
}
You must use a proper hostname to reach the route defined in the Ingress object. Either update your /etc/hosts file or use curl -H "hello-world.info" localhost type command. Alternatively, you can delete the host mapping and redirect all traffic to one default service.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: appName
servicePort: 80
In a scenario where I set the context path of the Tomcat server by changing the server.xml file like this:
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="${catalinaContextPath}" docBase="${catalina.home}/atlassian-jira" reloadable="false" useHttpOnly="true">
<Resource name="UserTransaction" auth="Container" type="javax.transaction.UserTransaction"
factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60"/>
<Manager pathname=""/>
<JarScanner scanManifest="false"/>
<Valve className="org.apache.catalina.valves.StuckThreadDetectionValve" threshold="120" />
</Context>
</Host>
If catalinaContextPath is set to /my/new/context The server will start up in the Pod with the URL: localhost:8080/my/new/context. How do I change the service so that it sends all traffic arriving on service port 80 to container path <pod_ip>:8080/my/new/context
This is my current service:
apiVersion: v1
kind: Service
metadata:
namespace: jira
name: jira
spec:
selector:
app: jira
component: jira
ports:
- protocol: TCP
name: serverport
port: 80
targetPort: 8080
My use case is, I am deploying this this JIRA docker image in a Pod and I set the context path using the environment variable CATALINA_CONTEXT_PATH as specified in this documentation. When I try to access it, it results in a 404. I assume this is because traffic is being redirected to <pod_ip>:8080 and nothing is running on <pod_ip>:8080 since tomcat has started up on <pod_ip>:8080/my/new/context
EDIT:
This is the ingress.yaml I am using:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: {{ .Values.global.app }}
name: jira-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: myhost
http:
paths:
- path: /dev/jira(/|$)(.*)
backend:
serviceName: jira
servicePort: 80
- path: /prod/jira(/|$)(.*)
backend:
serviceName: jira
servicePort: 80
Whenever I visit myhost/dev/jira I need it to go to my JIRA instance.
Since your application "real" root is /my/new/context, you can rewrite every incoming request matching the /dev/jira URI using Nginx's AppRoot:
If the Application Root is exposed in a different path and needs to be redirected, set the annotation nginx.ingress.kubernetes.io/app-root to redirect requests for /.
If you're using this approach, there is no need to use capture groups with rewrite-target.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: {{ .Values.global.app }}
name: jira-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/app-root: /my/new/context
spec:
rules:
- host: myhost
http:
paths:
- path: /dev/jira(/|$)(.*)
backend:
serviceName: jira
servicePort: 80
- path: /prod/jira(/|$)(.*)
backend:
serviceName: jira
servicePort: 80
This is not possible with services... I would strongly suggest using Ingress paths.
see here: Can a host be redirected to a service path in Kubernetes?