Kubernetes: Handle connections with multiple LoadBalancer in cluster via traefik ingress controller - kubernetes

It might be hard to explain so sorry if ı can not explain correctly.
In our k8s cluster we have two OpenStack-Load Balancer because we would like to expose our application through ingress which has to be internet facing. In same cluster we also deployed pgadmin4 which has to be intranet facing.(only reachable from internal network.)
So in front of these OpenStack-LB, we have also f5 Load Balancer which handle https connection,ssl .. and also logic to expose via intranet or internet.
MyApp is internet facing and needs to reachable with host.internet.net
PgAdmin4 is intranet and needs to reachable via host.intranet.net/pgadmin4
So the issue is, when I try to expose my application through ingress using host.internet.net it won't works and ı received below error cause probably it can not able to communicate with correct openStack-LB. When ı tried to expose via openStack-lb IP everything works properly.
{"level":"error","msg":"Service not found for
dev/oneapihub-ui-dev","time":"2020-03-26T05:20:05Z"}
{"level":"error","msg":"endpoints not found for
dev/oneapihub-ui-dev","time":"2020-03-26T05:20:05Z"}
And the question is , how can I handle this issue via ingress controller? Should I intall another traefik ingress controller?
capel0068340585:~ semural$ kubectl get ingress -n ingress
NAME HOSTS ADDRESS PORTS AGE
ingress-traefik-dashboard * 80 21d
kubectl get tenantSpec -o yaml
loadBalancers:
- ip: <IP1>
name: LBaaS2
ports:
- extPort: 80
name: "80"
nodePort: 30001
- ip: <IP2>
name: LBaaS1
ports:
- extPort: 80
name: "80"
nodePort: 30000
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/oneapihub-ui-dev ClusterIP 10.254.173.130 <none> 80/TCP 15m
NAME ENDPOINTS AGE
endpoints/oneapihub-ui-dev 10.6.24.136:3000 15m
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: traefik
hosts:
- host: host.internet.net -> example
paths: [/]
tls: []
ingress:
enabled: ingress
annotations:
kubernetes.io/ingress.class: traefik
hosts:
- host: host.intranet.net
paths:
- /pgadmin4

You error state "Service not found for dev/oneapihub-ui-dev", which means traefik is trying to connect to a Service in the dev namespace called "oneapihub-ui-dev" which it cannot find.
You need to make sure that both the Service exists and that it has endpoints. You can check if the Service exists with kubectl -n dev get service oneapihub-ui-dev. If it exists, check if it has endpoints with kubectl -n dev get ep oneapihub-ui-dev.
EDIT: If the Service exists and has Endpoints, than you may want to look into the RBAC permissions of traefik to see if it has enough permissions to look in the dev namespace and if you do not deploy any NetworkPolicies on the dev namespace that prevent the ingress namespace from connecting.

I solved this issue using via using labelSelector for traefik.. The the services that I'd expose only for internal networking has a label such as traffic-type=internal.. You could also provide a namespace for RBAC permissions.
kubernetes:
namespaces:
- default
- database
- monitoring
- logging
- ingress
labelSelector: "traffic-type=internal"

Related

Remote access Zero to JupyterHub over Ethernet with ingress in Kubernetes

Context
I installed Kubernetes on a bare-metal server (4 nodes) and deployed Zero to JupyterHub to it.
This works fine; I can correctly access the hub from the master-node.
Now I want to access the Hub on the server from an external computer via Ethernet. Therefore, I followed the official instructions and installed MetalLB in order to provide an external IP for my proxy-public-service (which correctly sets).
Additionally, I installed the nginx-ingress-controller in order to be able to do an ingress, which also successfully gets an external IP (little hint: Use the Helm-chart; I couldn't get the service running when applying the other recommended steps).
Since I had a little trouble figuring out how to do this ingress, here is an example:
kubectl apply -f ingress.yaml --namespace jhub
#ingress.yaml:
#apiVersion: networking.k8s.io/v1beta1
#kind: Ingress
#metadata:
# name: jupyterhub-ingress
# annotations:
# nginx.ingress.kubernetes.io/rewrite-target: /$1
#spec:
# rules:
# - host: jupyterhub.cluster
# http:
# paths:
# - path: /
# backend:
# serviceName: proxy-public
# servicePort: 80
Anyhow, I cannot open the external IP proxy-public provides (meaning I'm inserting the external IP in my browser).
Question
How can I remotely access my JupyterHub over the external IP; what am I missing?
I missed that this can be achieved in the same way as with the Kubernetes-Dashboard: You have to establish an open ssh-connection (hence, open a tunnel -> tunneling) from the external computer.
Of course this is not the "exernal" access I had in mind, but a working and fast solution for my test-environment (and maybe yours).
How to establish this ssh-connect
First, get the external IP-address of your proxy-public:
$: kubectl get services --namespace jhub
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hub ClusterIP 10.99.241.72 <none> 8081/TCP 95m
proxy-api ClusterIP 10.107.175.27 <none> 8001/TCP 95m
proxy-public LoadBalancer 10.102.171.162 192.168.1.240 80:31976/TCP,443:32568/TCP 95m
Note: The range of the external IP was defined in my layer2 in my MetalLB-config.
Using this information (and assuming you're on Linux), open a terminal and use the following command:
$ ssh pi#10.10.10.2 -L 8000:192.168.1.240:80
# -L opens a localhost-connection
# pi#10.10.10.2 logs me into my second node with user pi
Note1: That localhost:8000 is configured as targetPort for proxy-public with http can also be seen when you describe the service and take a look at the specs respectively ports (you can also get the settings for https there):
kind: Service
apiVersion: v1
metadata:
name: proxy-public
namespace: jhub
...
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8000
nodePort: 31976
- name: https
...
Finally, type http://localhost:8000/ into your browser - et voila, you get to your JupyterHub login-page!

How to access kubernetes websites via https

I built my own 1 host kubernetes cluster (1 host, 1 node, many namespaces, many pods and services) on a virtual machine, running on a always-on server.
The applications running on the cluster are working fine (basically, a NodeJS backend and HTML frontend).
So far, I have a NodePort Service, which is exposing Port 30000:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
traefik-ingress-service NodePort 10.109.211.16 <none> 443:30000/TCP 147d
So, now I can access the web interface by typing https://<server-alias>:30000 in my browser adress bar.
But I would like to access it without giving the port, by only typing https://<server-alias>.
I know, this can be done with the kubectl port-forwarding command:
kubectl -n kube-system port-forward --address 0.0.0.0 svc/traefik-ingress-service 443:443
This works. But it does not seem to be a very professional thing to do.
Port forwarding also seems to keep disconnecting from time to time. Sometimes, it throws an error and quits, but leaves the process open, which leaves the port open - have to kill the process manually.
So, is there a way to do that access-my-application stuff professionally? How do the cluster provider (AWS, GCP...) do that?
Thank you!
Using Ingress Nginx you can access to you website with the name server:
Step 1: Install Nginx ingress in you cluster you can flow this link
After the installation is completed you will have a new pod
NAME READY STATUS
nginx-ingress-xxxxx 1/1 Running
And a new Service
NAME TYPE CLUSTER-IP EXTERNAL-IP
nginx-ingress LoadBalancer 10.109.x.y a.b.c.d
Step 2 : Create new deployment for you application but be sure that you are using the same name space for nginx ingress svc/pod and you application and you set the svc type to ClusterIP
Step 3: Create Kubernetes Ingress Object
Now you have to create the ingress object
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: **Same Name Space**
spec:
rules:
- host: your DNS <server-alias>
http:
paths:
- backend:
serviceName: svc Name
servicePort: svc Port
Now you can access to your website using the .
To create a DNS for free you can use freenom or you can use /etc/hosts
update it with :
server-alias a.b.c.d
Since the Type of your Traefik Ingress Service is NodePort, you get to access to the port provided which will have a value from 30000-32000.
You can also configure it to be of type LoadBalancer and interface with a cloud-based Load Balancer.
Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/
Here's a very related question: Should I use NodePort in my Traefik deployment on Kubernetes?

Kubernetes service is reachable from node but not from my machine

I have a timeout problem with my site hosted on Kubernetes cluster provided by DigitalOcean.
u#macbook$ curl -L fork.example.com
curl: (7) Failed to connect to fork.example.com port 80: Operation timed out
I have tried everything listed on the Debug Services page. I use a k8s service named df-stats-site.
u#pod$ nslookup df-stats-site
Server: 10.245.0.10
Address: 10.245.0.10#53
Name: df-stats-site.deepfork.svc.cluster.local
Address: 10.245.16.96
It gives the same output when I do it from node:
u#node$ nslookup df-stats-site.deepfork.svc.cluster.local 10.245.0.10
Server: 10.245.0.10
Address: 10.245.0.10#53
Name: df-stats-site.deepfork.svc.cluster.local
Address: 10.245.16.96
With the help of Does the Service work by IP? part of the page, I tried the following command and got the expected output.
u#node$ curl 10.245.16.96
*correct response*
Which should mean that everything is fine with DNS and service. I confirmed that kube-proxy is running with the following command:
u#node$ ps auxw | grep kube-proxy
root 4194 0.4 0.1 101864 17696 ? Sl Jul04 13:56 /hyperkube proxy --config=...
But I have something wrong with iptables rules:
u#node$ iptables-save | grep df-stats-site
(unfortunately, I was not able to copy the output from node, see the screenshot below)
It is recommended to restart kube-proxy with with the -v flag set to 4, but I don't know how to do it with DigitalOcean provided cluster.
That's the configuration I use:
apiVersion: v1
kind: Service
metadata:
name: df-stats-site
spec:
ports:
- port: 80
targetPort: 8002
selector:
app: df-stats-site
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: df-stats-site
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- fork.example.com
secretName: letsencrypt-prod
rules:
- host: fork.example.com
http:
paths:
- backend:
serviceName: df-stats-site
servicePort: 80
Also, I have a NGINX Ingress Controller set up with the help of this answer.
I must note that it worked fine before. I'm not sure what caused this, but restarting the cluster would be great, though I don't know how to do it without removing all the resources.
The solution for me was to add HTTP and HTTPS inbound rules in the Firewall (these are missing by default).
For DigitalOcean provided Kubernetes cluster, you can open it at https://cloud.digitalocean.com/networking/firewalls/.
UPDATE: Make sure to create a new firewall record rather than editing an existing one. Otherwise, your rules will be automatically removed in a couple of hours/days, because DigitalOcean k8s persists the set of rules in the firewall.
ClusterIP services are only accessible from within the cluster. If you want to access it from outside the cluster, it needs to be configured as NodePort or LoadBalancer.
If you are just trying to test something locally, you can use kubectl port-forward to forward a port on your local machine to a ClusterIP service on a remote cluster. Here's an example of creating a deployment from an image, exposing it as a ClusterIP service, then accessing it via kubectl port-forward:
$ kubectl run --image=rancher/hello-world hello-world --replicas 2
$ kubectl expose deployment hello-world --type=ClusterIP --port=8080 --target-port=80
$ kubectl port-forward svc/hello-world 8080:8080
This service is now accessible from my local computer at http://127.0.0.1:8080

How to fix: Empty IP Address for nginx-ingress on digital-ocean

In my k8s cluster the ingress does not work on the k8s cluster of digital ocean. I don't get an external ip and so it is not available. Locally there seems to be no problem.
I already searched a lot and tried some tutorials, f.e. https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes.
But it seems that it is an older version and the solution (and even the links) does not work anymore.
The nginx-ingress should call the service of a website backend which is on port 8080.
I stripped down my ingress code to the following one:
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: website
servicePort: 8080
With kubectl get ing I see the ingress, but it has no address. It looks like this
NAME HOSTS ADDRESS PORTS AGE
test-ingress * 80 50s
Can anyone help me out and tell me what I have to do to get my k8s cluster running?
Thanks
peter
Firstly, if you are using Nginx Ingress Controller, you don't need to see ingress address.
When you install Nginx Ingress Controller to your k8s cluster, it creates Load Balancer to handle all incoming requests. Make sure that below part completed as explained in Step 2 of guide you posted and you are able to see LoadBalancer External ip address.
$ kubectl get svc --namespace=ingress-nginx
You should see an external IP address, corresponding to the IP address of the DigitalOcean Load Balancer:
Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx LoadBalancer 10.245.247.67 203.0.113.0 80:32486/TCP,443:32096/TCP 20h
In above case, after deploying your ingress resource, if you hit http://203.0.113.0 you will get your website:8080 backend service.
Hope it helps!

How do I make my admin ui of cockroachdb publicly available via traefik ingress controller on kubernetes?

Kubernetes dedicated cockroachdb node - accessing admin ui via traefik ingress controller fails - page isn't redirecting properly
I have a dedicated kubernetes node running cockroachdb. The pods get scheduled and everything is setup. I want to access the admin UI from a subdomain like so: cockroachdb.hostname.com. I have done this with traefik dashboard and ceph dashboard so I know my ingress setup is working. I even have cert-manager running to have https enabled. I get the error from the browser that the page is not redirecting properly.
Do I have to specify the host name somewhere special?
I have tried adding this with no success: --http-host cockroachdb.hostname.com
This dedicated node has its own public ip which is not mapped to hostname.com. I think I need to change a setting in cockroachdb, but I don't know which because I am new to it.
Does anyone know how to publish admin UI via an ingress?
EDIT01: Added ingress and service config files
Ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cockroachdb-public
annotations:
kubernetes.io/ingress.class: traefik
traefik.frontend.rule.type: PathPrefixStrip
certmanager.k8s.io/issuer: "letsencrypt-prod"
certmanager.k8s.io/acme-challenge-type: http01
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/ssl-temporary-redirect: "true"
ingress.kubernetes.io/ssl-host: "cockroachdb.hostname.com"
traefik.frontend.rule: "Host:cockroachdb.hostname.com,www.cockroachdb.hostname.com"
traefik.frontend.redirect.regex: "^https://www.cockroachdb.hostname.com(.*)"
traefik.frontend.redirect.replacement: "https://cockroachdb.hostname.com/$1"
spec:
rules:
- host: cockroachdb.hostname.com
http:
paths:
- path: /
backend:
serviceName: cockroachdb-public
servicePort: http
- host: www.cockroachdb.hostname.com
http:
paths:
- path: /
backend:
serviceName: cockroachdb-public
servicePort: http
tls:
- hosts:
- cockroachdb.hostname.com
- www.cockroachdb.hostname.com
secretName: cockroachdb-secret
Serice:
apiVersion: v1
kind: Service
metadata:
# This service is meant to be used by clients of the database. It exposes a ClusterIP that will
# automatically load balance connections to the different database pods.
name: cockroachdb-public
labels:
app: cockroachdb
spec:
ports:
# The main port, served by gRPC, serves Postgres-flavor SQL, internode
# traffic and the cli.
- port: 26257
targetPort: 26257
name: grpc
# The secondary port serves the UI as well as health and debug endpoints.
- port: 8080
targetPort: 8080
name: http
selector:
app: cockroachdb
EDIT02:
I can access the Admin UI page now but only by going over the external ip address of the server with port 8080. I think I need to tell my server that its ip address is mapped to the correct sub domain?
EDIT03:
On both scheduled traefik-ingress pods the following logs are created:
time="2019-04-29T04:31:42Z" level=error msg="Service not found for default/cockroachdb-public"
Your referencing looks good on the ingress side. You are using quite a few redirects, unless you really know what each one is accomplishing, don't use them, you might end up in an infinite loop of redirects.
You can take a look at the following logs and methods to debug:
Run kubectl logs <traefik pod> and see the last batch of logs.
Run kubectl get service, and from what I hear, this is likely your main issue. Make sure your service exists in the default namespace.
Run kubectl port-forward svc/cockroachdb-public 8080:8080 and try connecting to it through localhost:8080 and see terminal for potential error messages.
Run kubectl describe ingress cockroachdb-public and look at the events, this should give you something to work with.
Try accessing the service from another pod you have running ping cockroachdb-public.default.svc.cluster.local and see if it resolves the IP address.
Take a look at your clusterrolebindings and serviceaccount, it might be limited and not have permission to list services in the default namespace: kubectl create clusterrolebinding default-admin --clusterrole cluster-admin --serviceaccount=default:default