Kubernetes (docker-desktop) with multiple LoadBalancer services - docker

Is it true that I cannot have two LoadBalancer services on a docker-desktop cluster (osx), because they would both use localhost (and all ports are forwarded)?
I created an example and the latter service is never assigned an external IP address but stays in state pending. However, the former is accessible on localhost.
> kubectl get all
NAME READY STATUS RESTARTS AGE
pod/whoami-deployment-9f9c86c4f-l5lkj 1/1 Running 0 28s
pod/whoareyou-deployment-b896ddb9c-lncdm 1/1 Running 0 27s
pod/whoareyou-deployment-b896ddb9c-s72sc 1/1 Running 0 27s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 95s
service/whoami-service LoadBalancer 10.97.171.139 localhost 80:30024/TCP 27s
service/whoareyou-service LoadBalancer 10.97.171.204 <pending> 80:32083/TCP 27s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/whoami-deployment 1/1 1 1 28s
deployment.apps/whoareyou-deployment 2/2 2 2 27s
NAME DESIRED CURRENT READY AGE
replicaset.apps/whoami-deployment-9f9c86c4f 1 1 1 28s
replicaset.apps/whoareyou-deployment-b896ddb9c 2 2 2 27s
Detailed state fo whoareyou-service:
kubectl describe service whoareyou-service
Name: whoareyou-service
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"whoareyou-service","namespace":"default"},"spec":{"ports":[{"name...
Selector: app=whoareyou
Type: LoadBalancer
IP: 10.106.5.8
Port: http 80/TCP
TargetPort: 80/TCP
NodePort: http 30333/TCP
Endpoints: 10.1.0.209:80,10.1.0.210:80
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>

I decided to copy my comments, as they partially explain the problem, and make a Community Wiki answer out of them so it is more clearly seen and available for possible further edits by the Community:
It works probably exactly the same way as in Minikube. As docker-desktop is unable to provision real LoadBalancer it can still "simulate" creating Service of such type using NodePort (this can easily be seen from port range it uses). I'm pretty sure you cannot use same IP address as the ExternalIP of the LoadBalancer Service and if you create one more Service of such type, your docker-desktop has no other choice than to use your localhost one more time. As it is already used by one Service it cannot be used by another one and that's why it remains in a pending state.
Note that if you create real LoadBalancer in a cloud environment, each time new IP is provisioned and there is no situation that next LoadBalancer you create gets the same IP that is already used by the existing one. Apparently here it cannot use any other IP then one of localhost, and this one is already in use. Anyway I would recommend you to simply use NodePort if you want to expose your Deployment to the external world.

Think about using Ingress controller instead.
So basically, it's 3 steps after installing docker-desktop :
Wilcard Certificate locally
SSL certificate For local env
Install Ingress Controller
Detailed here: https://github.com/kubernetes-tn/guideline-kubernetes-enterprise/blob/master/general/desktop-env-setup.md

I came across this question while looking to set up a lightweight local environment with minimal dependencies.
I found that two LoadBalancer work on localhost when using different port numbers.
---
apiVersion: v1
kind: Service
metadata:
name: webapp-one-lb
spec:
ports:
- name: 8081-tcp
port: 8081
protocol: TCP
targetPort: 8080
selector:
name: webapp-one
type: LoadBalancer
status:
loadBalancer: {}
---
apiVersion: v1
kind: Service
metadata:
name: webapp-two-lb
spec:
ports:
- name: 8082-tcp
port: 8082
protocol: TCP
targetPort: 8080
selector:
name: webapp-two
type: LoadBalancer
status:
loadBalancer: {}
As others have said, Ingress is more flexible and allows for sub-domain and path based routing without having to worry about port conflicts, but it comes with an additional learning curve.

Related

Not able to access service from the public ip in kubernetes

I am using kubernetes and run one service. Service is running and is showing in service. But i am not able to access it from the public ip of the instance. Below is my deployment file.
apiVersion: v1
kind: Service
metadata:
name: apache-service
spec:
selector:
app: apache
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: apache-deployment
spec:
selector:
matchLabels:
app: apache
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: apache
spec:
containers:
- name: apache
image: mobingi/ubuntu-apache2-php7:7.2
ports:
- containerPort: 80
Here is my list of service.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
apache-service NodePort 10.106.242.181 <none> 80:31807/TCP 9m5s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 11m
But when i check the same service from the follwing telnet with the public ip of cluster and node. It is not responding.
telnet public-ip:31807
Any type of help will be appreciable.
What do you mean by cluster IP? Do you mean the node that acts as kunernetes master? It won't work if you use master IP. Because masters don't have deployments scheduled due to security concerns.
Exposing a service via nodeport means that the service listens to a particular port in each of the worker nodes. So you can access the kunernetes worker nodes with the nodeports and get response. However if you created the cluster using cloud providers like aws, the worker nodes security groups are secured. Probably, you need to edit the security groups of worker nodes to access the service.

Cannot Use a static IP address outside of the node resource group

I am trying to use a static ip address for the dashboard that is created outside of the node resource group following the guide located here, but it is not working. (This is for a firewalled dev-only cluster and won't go to production.)
What I have done so far:
Created a public ip address in resourcegroup1
Create an AKS cluster in resourcegroup1 tied to a azure ad application.
Added the azure ad application's service principal as a "Network Contributer" in resourcegroup1.
Added service.beta.kubernetes.io/azure-load-balancer-resource-group: resourcegroup1 to my service.yaml file.
Added loadBalancerIP with the ip address from step 1.
Whenever I apply service.yaml, the service says it's in a pending state. When I run kubectl describe service, it shows the following output:
Name: kubernetes-dashboard
Namespace: kube-system
Labels: <none>
Annotations: externalTrafficPolicy=Local
service.beta.kubernetes.io/azure-load-balancer-resource-group=resourcegroup1
Selector: k8s-app=kubernetes-dashboard
Type: LoadBalancer
IP: 10.0.42.112
IP: <IP FROM STEP 1>
Port: <unset> 80/TCP
TargetPort: 9090/TCP
NodePort: <unset> 31836/TCP
Endpoints: 10.244.0.6:9090
Session Affinity: None
External Traffic Policy: Cluster
LoadBalancer Source Ranges: <SNIPPED>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal EnsuringLoadBalancer 38s (x6 over 3m) service-controller Ensuring load balancer
Warning CreatingLoadBalancerFailed 38s (x6 over 3m) service-controller Error creating load balancer (will retry): failed to ensure load balancer for service kube-system/kubernetes-dashboard: user supplied IP Address <IP FROM STEP 1> was not found
Here is my service.yaml
apiVersion: v1
kind: Service
metadata:
name: kubernetes-dashboard
namespace: kube-system
annotations:
service.beta.kubernetes.io/azure-load-balancer-resource-group: resourcegroup1
spec:
type: LoadBalancer
loadBalancerIP: <IP FROM STEP 1>
ports:
- port: 80
protocol: TCP
targetPort: 9090
selector:
k8s-app: kubernetes-dashboard
loadBalancerSourceRanges:
- <SNIP>
- <SNIP>
For the error you got, it means the public IP cannot be found in the resourcegroup1 with the same region as the AKS. Different region causes the error like this as yours:
So you should create public IP in the same region with your AKS. Then it will work for you.
My AKS cluster was 1.9.x which was older than the required 1.10.x. I was using Terraform to create the cluster and there appears to be a bug with how a missing kubernetes_version is handled. I submitted an issue on their repo.

How to integrate vuejs into minikube with a RESTful backend?

I want to integrate my vuejs app into a minikube cluster.
I used the Dockerfile from the VueJs tutorial for the production with the Nginx webserver and with the first option localhost:8080 here. I changed the ports in the yml files accordingly meaning for the localhost to 8080 and for the nginx version as seen below to 80
Then in my config/index.js
dev: {
[...]
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
[...]
},
I have set the default 8080 port. For my minikube deployment and service I added
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: vuejs
spec:
selector:
matchLabels:
app: vuejs
tier: frontend
replicas: 1
template:
metadata:
labels:
app: vuejs
tier: frontend
spec:
imagePullSecrets:
- name: regcred
containers:
- name: vuejs
image: <secret registry>
ports:
- containerPort: 80
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
---
apiVersion: v1
kind: Service
metadata:
name: vuejs
labels:
app: vuejs
tier: frontend
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
# Replace with the IP of your minikube java / master java
# externalIPs:
# - 192.168.99.105
selector:
app: vuejs
tier: frontend
How do I connect to the vuejs/nginx webserver. Moreover since I set the DNS name of the backend to java how do I set the java REST API address in vuejs?
I set the address to 'http://java:8080/' without any response. The Java REST backend is integrated into minikube with this yml.
The curios issue is that after starting the vuejs deployment I can access the vuejs app at 127.0.0.1:8080. When I understood correctly I thought that the kubernetes cluster opens up its own network and is only accessible via external IP
Looking at my kubectl get all I would say that vuejs should be reachable 192.168.99.105:8080 - when using the dockerimage without the nginx.
NAME READY STATUS RESTARTS AGE
pod/java-fbf949cbc-rqstq 0/1 Error 4 2d
pod/maria-7b67c8ddf-xp8xx 1/1 Running 2 2d
pod/private-reg 1/1 Running 5 5d
pod/vuejs-5f4c657d74-885j9 1/1 Running 1 18h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/java LoadBalancer 10.101.207.98 192.168.99.100 8080:31011/TCP 2d
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d
service/maria ClusterIP 10.99.177.228 <none> 3306/TCP 2d
service/vuejs NodePort 10.104.108.44 192.168.99.105 8080:30001/TCP 17h
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deployment.apps/java 1 1 1 0 2d
deployment.apps/maria 1 1 1 1 2d
deployment.apps/vuejs 1 1 1 1 18h
NAME DESIRED CURRENT READY AGE
replicaset.apps/java-fbf949cbc 1 1 0 2d
replicaset.apps/maria-7b67c8ddf 1 1 1 2d
replicaset.apps/vuejs-5f4c657d74 1 1 1 18h
You can use minikube service command to get the url exposed to your own host. For your deployment, try:
minikube service vuejs --url
It would show an IP with the NodePort added to it. Copy and paste the result of that command to your browser.
Update: How it works
Minikube starts a virtual machine inside your host (your laptop) with a single-node Kubernetes cluster, assigning a local IP that you can get with minikube ip command. That’s the IP of the Kubernetes node.
When you expose a "NodePort" service inside Kubernetes, it allocates a static port from range 30000-32767 (default) so you can access that service with <NodeIP>:<NodePort>
There are two ways to expose resources from a Kubernetes cluster:
Use an Ingress. For more information, you can visit this link.
Expose a Service. You can do it in two ways:
type: LoadBalancer. However, it works only with cloud providers.
type: NodePort. And it is the easiest way in your case, you need to change spec.type from LoadBalancer to NodePort in your YAML description for the Service. After that, to access service inside the Kubernetes cluster, you need to use the IP address of your Node and the port from the field nodePort. For example, 192.168.12.34:30001

Gcloud Kubernetes connection refused to exposed service

I am unable to connect to an exposed IP for a docker container deployed on Google Could Kubernetes. I have been roughly following this tutorial but using my own application.
The deployment seems to work fine, everything is green and running when visiting the cloud dashboard but when trying to visit the deployed application on the exposed IP, I get a browser error:
This site can’t be reached
35.231.27.158 refused to connect
If I ping the IP I do get a response back.
kubectl get pods produces the following:
NAME READY STATUS RESTARTS AGE
mtg-dash-7874f6c54d-nktjn 1/1 Running 0 21m
and kubectl get service shows the following:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.7.240.1 <none> 443/TCP 23m
mtg-dash LoadBalancer 10.7.242.240 35.231.27.158 80:30306/TCP 20m
and kubectl describe svc show the following:
Name: mtg-dash
Namespace: default
Labels: run=mtg-dash
Annotations: <none>
Selector: run=mtg-dash
Type: LoadBalancer
IP: 10.7.242.240
LoadBalancer Ingress: 35.231.27.158
Port: <unset> 80/TCP
TargetPort: 8080/TCP
NodePort: <unset> 30306/TCP
Endpoints: 10.4.0.6:8080
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal EnsuringLoadBalancer 37m service-controller Ensuring load balancer
Normal EnsuredLoadBalancer 37m service-controller Ensured load balancer
My Dockerfile contains the following:
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
WORKDIR /usr/share/nginx/html
COPY dist/mtg-dash .
I have a feeling I have missed something obvious.
What more do I need to do to configure this to be accessible on the internet?
Here is a screenshot of running service:
As per the comments the target port should be 80 since that is what the application is set to listen on. Glad I could help. Picked it up from the documentation a month or so ago.
https://kubernetes.io/docs/concepts/services-networking/service/

minikube service %servicename% --url return nothing

I'm trying to expose my api so I can send request to it. However when I used the command minikube service api --url I get nothing. All my pods are running fine according to kubectl get pods so I'm abit stuck about what this could be.
api-1007925651-0rt1n 1/1 Running 0 26m
auth-1671920045-0f85w 1/1 Running 0 26m
blankit-app 1/1 Running 5 5d
logging-2525807854-2gfwz 1/1 Running 0 26m
mongo-1361605738-0fdq4 1/1 Running 0 26m
jwl:.build jakewlace$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
api 10.0.0.194 <none> 3001/TCP 23m
auth 10.0.0.36 <none> 3100/TCP 23m
kubernetes 10.0.0.1 <none> 443/TCP 5d
logging 10.0.0.118 <none> 3200/TCP 23m
mongo 10.0.0.132 <none> 27017/TCP 23m
jwl:.build jakewlace$
jwl:.build jakewlace$ minikube service api --url
jwl:.build jakewlace$
Any help would be massively appreciated, thank you.
I realised that the question here could be perceived as being minimal, but that is because I'm not sure what more information I could show from the tutorials I've been following it should just work. If you need more information please do let me know I will let you know.
EDIT:
api-service.yml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
io.kompose.service: api
name: api
spec:
ports:
- name: "3001"
port: 3001
targetPort: 3001
selector:
io.kompose.service: api
status:
loadBalancer: {}
api-deployment.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
creationTimestamp: null
labels:
io.kompose.service: api
name: api
spec:
replicas: 1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
io.kompose.service: api
spec:
containers:
- image: blankit/web:0.0.1
name: api
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3001
resources: {}
restartPolicy: Always
status: {}
Your configuration is fine, but only missing one thing.
There are many types of Services in Kubernetes, but in this case you should know about two of them:
ClusterIP Services:
Exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster. This is the default.
NodePort:
Exposes the service on each Node’s IP at a static port (the NodePort). A ClusterIP service, to which the NodePort service will route, is automatically created. You’ll be able to contact the NodePort service, from outside the cluster, by requesting <NodeIP>:<NodePort>.
Note:
If you have a multi-node cluster and you've exposed a NodePort Service, you can access is from any other node on the same port, not necessarily the same node the pod is deployed onto.
So, getting back to your service, you should specify the service type in your spec:
kind: Service
apiVersion: v1
metadata:
...
spec:
type: NodePort
selector:
...
ports:
- protocol: TCP
port: 3001
Now if you minikube service api --url, it should return a URL like http://<NodeIP>:<NodePort>.
Note: The default Kubernetes configuration will chose a random port from 30000-32767. But you can override that if needed.
Useful references:
Kubernetes / Publishing services - service types
Kubernetes / Connect a Front End to a Back End Using a Service

Resources