Im tring to access a external API from my service (site-api) in kubernetes, this external API can only be accessed with IP Whitelist, so i gave the IP of my ingress (EXTERNAL IP), this ip is located in kubernetes dashboard (Discovery and Load Balancing / Ingresses), but i still get access denied, the ip which i have to provide is correct? it is missing some settings in ingress yaml ?
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: site-name
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/proxy-body-size: "15m"
spec:
tls:
- hosts:
- site-name
secretName: aks-ingress-tls
rules:
- host: site-name
http:
paths:
- path: /?(.*)
backend:
serviceName: site-web
servicePort: 443
- path: /message/?(.*)
backend:
serviceName: site-message
servicePort: 3001
- path: /api/?(.*)
backend:
serviceName: site-api
servicePort: 8443
• The IP shown in the dashboard on Discovery and Load Balancing/Ingress is not the IP address that is to be whitelisted. Instead, the service object(site-api) that is trying to access the external IP will expose the deployment as well as the external IP that needs to be whitelisted.
• So, first create a service object that exposes the deployment of the site-api and display information about that service object that is created for exposing the deployment.
• Once, we get the concise information about the service object, get the detailed information about that service object which will display the detailed information about the external IP that the site-api is trying to access.
• So, the external IP address will be exposed by this service object which will need to be whitelisted. Also, take a note of the endpoint IP addresses and their ports which are accessing the site-api through the ports and node ports. You can then access the site-api service using the external IP address and the port in the displayed information.
• Please find the below Kubernetes commands to execute the steps as above: -
kubectl expose deployment<site-api>--type=LoadBalancer --name=my-service Service object creation for exposing the deployment
kubectl get services my-service Display information about the service
kubectl describe services my-service Display detailed information about the service
kubectl get pods --output=wide Get endpoint information
curl http://<external-ip>:<port> Access the site-api through external IP
Please refer the below link for more information: -
https://kubernetes.io/docs/tutorials/stateless-application/expose-external-ip-address/
Related
Have deployed an application successfully using helm chart but I am unable to understand which url should I use to access it ..Here is the Nodeport service created by Helm for this web app :
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demo-springboot-demoweb NodePort 10.101.86.143 <none> 8080:31384/TCP 11m
xxxxxxx#xxxxxxxx5 charts % kubectl describe svc
Name: demo-springboot-demoweb
Namespace: springboot-demoweb
Labels: app=springboot-demoweb
app.kubernetes.io/managed-by=Helm
chart=springboot-demoweb-0.1.0
heritage=Helm
release=demo
Annotations: meta.helm.sh/release-name: demo
meta.helm.sh/release-namespace: springboot-demoweb
Selector: app=springboot-demoweb,release=demo
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.101.86.143
IPs: 10.101.86.143
Port: nginx 8080/TCP
TargetPort: 8080/TCP
NodePort: nginx 31384/TCP
Endpoints: 172.17.0.15:8080
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
You have deployed an application that is exposed using a Service of kind NodePort.
That means that all nodes of the cluster expose the application on the same port - the port number is coordinated.
So you need the ip of one of the nodes to access the cluster.
You can use kubectl get nodes -o wide to get the nodes and IP addresses. If it is a local cluster it will be shown as INTERNAL IP.
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
minikube Ready control-plane,master 155m v1.23.3 192.168.49.2 <none> Ubuntu 20.04.2 LTS 5.15.0-37-generic docker://20.10.12
Use one of the IPs together with your NodePort which is 31384. In my example it would be: http://192.168.49.2:31384
I have an openshift namespace (SomeNamespace), in that namespace I have several pods.
I have a route associated with that namespace (SomeRoute).
In one of pods I have my spring application. It has REST controllers.
I want to send message to that REST controller, how can I do it?
I have a route URL: https://some.namespace.company.name. What should I find next?
I tried to send requests to https://some.namespace.company.name/rest/api/route but it didn't work. I guess, I must somehow specify pod in my URL, so route will redirect requests to concrete pod but I don't know how I can do it.
You don't need to specify the pod in the route.
The chain goes like this:
Route exposes a given port of a Service
Service selects some pod to route the traffic to by its .spec.selector field
You need to check your Service and Route definitions.
Example service and route (including only the related parts of the resources):
Service
spec:
ports:
- name: 8080-tcp
port: 8080
protocol: TCP
targetPort: 8080
selector:
<label-key>: <label-value>
Where label-key and label-value is any label key-value combination that selects your pod with the http application.
Route
spec:
port:
targetPort: 8080-tcp <port name of the service>
to:
kind: Service
name: <service name>
When your app exposes some endpoint on :8080/rest/api, you can invoke it with <route-url>/rest/api
You can try it out with some example application (some I found randomly on github, to verify everything works correctly on your cluster):
create a new app using s2i build from github repository: oc new-app registry.redhat.io/openjdk/openjdk-11-rhel7~https://github.com/redhat-cop/spring-rest
wait until the s2i build is done and the pod is started
expose the service via route: oc expose svc/spring-rest
grab the route url: oc get route spring-rest -o jsonpath='{.spec.host}'
invoke the api: curl -k <route-url>/v1/greeting
response should be something like: {"id":3,"content":"Hello, World!"}
Routes are an OpenShift-specific way of exposing a Service outside the cluster.
But, if you are developing an app that will be deployed onto OpenShift and Kubernetes, then you should use Kubernetes Ingress objects.
Using Ingress means that your app’s manifests are more portable between different Kubernetes clusters.
From the official Kubernetes docs:
An Ingress may be configured to give Services externally-reachable URLs, load balance traffic, terminate SSL / TLS, and offer name-based virtual hosting.
Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster.
Traffic routing is controlled by rules defined on the Ingress resource.
So, if you want to reach your REST controllers:
from within the k8s cluster. Create a k8s Service to expose an application running on a set of Pods as a network service:
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: your-namespace
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 8080
This specification creates a new Service object named "my-service", which targets TCP port 8080 on any Pod with the app=MyApp label.
You can reach the REST controller using this URL:
http://my-service
externally. Create an Ingress resource to configure externally-reachable URLs (a k8s Service 'my-service' should exist):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-name
namespace: your-namespace
spec:
rules:
- host: "foo.bar.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: my-service
port:
number: 80
You can reach the REST controller using this URL:
http://foo.bar.com
I am trying to debug my app in testing environment, my app is running in pod, I said 'pod' because I am not familiar with Kubernetes, its manage client looks like this:app running schematic diagram. I have learn I should set idea like this idea RUN/Debug Configurations schematic diagram. And should restart and redeploy my app, I changed Dockfile firstly. the origin instruction is FROM xxx/java:alpine VOLUME /tmp ADD recruitment.jar app.jar ENTRYPOINT ["java","-Xmx2048m","-jar","/app.jar"] and I changed this to FROM xxx/java:alpine VOLUME /tmp ADD recruitment.jar app.jar ENTRYPOINT ["java","-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005","-jar","/app.jar"] but it always show error like this Error running 'face_remote': Unable to open debugger port (888.88.888.888[not real]:5005): java.io.IOException "handshake timeout". I am not sure with this ip,sicne I use 'ping 888.88.888.888' instruction can not success. I use this ip because Swagger request url's domain name's ip is this.this main enter image description here. and I guess if the app is running in docker or k8s and it will have a different Interactive mode. not same like just running in linux
most of the attached image are not visible.
IP address should be accessible from your local system
[888.88.888.888] note sure this is correct.
debug port also need to be mapped from your local system
-use port forwarding
ex:kubectl port-forward 5005:5005
If you have configure port forwarding then you can use localhost:5005 for debugging
I see three things that you can check:
Check the IP address:
The jar file runs inside a Docker container, which runs inside a pod. To access the pod you usually go through a service and an ingress. The ip you are using is most likely hitting the ingress/service or any other higher layer.
To attach a remote debugger, you will need to connect directly to the PodIP. One way of doing this is to first connect to your kubernetes cluster using the tool kubectl (some configuration required) and make a port forward from your pod: kubectl port-forward my-pod-c93b8b6df-8c4aa 5005:5005 pod (as an example, the pod instance name is my-pod-c93b8b6df-8c4aa).
This will open a connection from your local computer into the pod. Then you will need to identify the PodIP by kubectl describe pods my-pod-c93b8b6df-8c4aa and use that in IntelliJ
Check if the port is exposed:
Make sure you expose the port 5005 from the pod in your test environment (similar to exposing a port when you run the container locally).
How to do this depends a bit on how you are running your Kubernetes cluster. If you use Helm chart, you can just add a configuration like this in the port section of your deployment yaml:
- containerPort: 5005
name: debug
protocol: TCP
Check debug-command address:
Last thing is to make sure you are adding the correct address in the command line option. As IntelliJ suggest in the debug editor: for JDK9+ use …suspend=n,address=*:5005 and for JDK8 and below use …suspend=n,address=5005
Problem:
how to resolve host name of kubernetes pod?
I have the Following requirement we are using grpc with java where we have one app where we are running out grpc server other app where we are creating grpc client and connecting to grpc server (that is running on another pod).
We have three kubernetes pod running where our grpc server is running.
lets say :
my-service-0, my-service-1, my-service-2
my-service has a cluster IP as: 10.44.5.11
We have another three kubernetes pod running where our gprc client is running.
lets say:
my-client-0, my-client-1, my-client-2
Without Security:
i am try to connect grpc server pod with grpc client pod and it work fine.
grpc client (POD -> my-client) ----------------> groc server(POD -> my-service)
So without security i am giving host name as my-service and it's working fine without any problem..
ManagedChannel channel = ManagedChannelBuilder.forAddress("my-service", 50052)
.usePlaintext()
.build();
With SSL Security:
if i try to connect grpc server it will throw host name not match.
we have created a certificate with wild card *.default.pod.cluster.local
it will throw the below error:
java.security.cert.CertificateException: No name matching my-service found
at java.base/sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:225) ~[na:na]
at java.base/sun.security.util.HostnameChecker.match(HostnameChecker.java:98) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455) ~[na:na]
Not Working Code:
ManagedChannel channel = NettyChannelBuilder.forAddress("my-service", 50052)
.sslContext(GrpcSslContexts.forClient().trustManager(new File(System.getenv("GRPC_CLIENT_CA_CERT_LOCATION"))).build())
.build();
but if i give the host name as like this ==> 10-44-5-11.default.pod.cluster.local it will work fine correctly.
Working Code
ManagedChannel channel = NettyChannelBuilder.forAddress("10-44-5-11.default.pod.cluster.local", 50052)
.sslContext(GrpcSslContexts.forClient().trustManager(new File(System.getenv("GRPC_CLIENT_CA_CERT_LOCATION"))).build())
.build();
Now my problem is cluster ip of pod is dynamic and it will change every time during app deploy. what is the right way to resolve this host name?
is it possible if i give host name and it will return me the ip then i will append default.pod.cluster.local to hostname and try to connect to grpc server?
Addressing your pod directly is not a good solution since Kubernetes may need to move your pods around the cluster. This can occur for example because of the failing node.
To allow you clients/traffic to easy find desired containers you can place them behind a service with single static IP address. Service IP can be look up through DNS.
This is how you can connect to the service through it`s FQDN:
my-service.default.svc.cluster.local
Where my-service is your service name, default for your namespace and svc.cluster.local is a configurable cluster domain suffix used in all cluster services.
It's worth to know that you can skip svc.cluster.local suffix and even the namespace if the pods are in the same namespace. So you'll just refer to the service as my-service.
For more you can check K8s documents about DNS.
I'm a newbie to Spring Boot. I have a REST API application written in Spring Boot. When I execute my Spring Boot JAR, everything is okay and I can access the REST API with the localhost address instead of the actual one:
http://localhost:8083/articles
But when I try to access the REST API by my external IP address, I can't do it:
http://100.90.80.70:8083/articles
netstat -antu command in the Linux terminal gives me the following output:
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp6 0 0 :::8083 :::* LISTEN
As I understand, my app is accessible only in localhost, because it hasn't a foreign address.
My application.properties file has only this line:
server.port=8083
Also, when I try to add a server.address line to application.properties like that:
server.address=100.90.80.70
server.port=8083
I have the following Exception: Caused by: java.net.BindException: Cannot assign requested address.
So my question is: how to make Spring Boot application accessible by external IP address of the server? Thank you.
As #Mark said, the problem is in the firewall. I have opened 8083 port in the firewall settings and now I can access my REST API app by the external IP address:
http://100.90.80.70:8083/articles
Linux command to check firewall status:
sudo ufw status verbose
Open 8083 port for remote access by TCP protocol:
sudo ufw allow 8083/tcp
More settings here: https://www.cyberciti.biz/faq/how-to-open-firewall-port-on-ubuntu-linux-12-04-14-04-lts/
I fixed the same by configuring port forwarding on my router, to allow traffic from public ip
In my OpenStack environment, after much debugging, the solution was to create a new Security Group Rule, which looks like this:
Security Group Rule.
Note that my Spring Boot application was deployed on port 8080.
I also noticed that on ubuntu18 the firewall is disabled by default. It did not cause any problems.