Forward to ExternalName with traefik in kubernetes as the documenation suggests - kubernetes

Following the Official Guide I got to the section onForwarding to ExtternalNames. Where it says:
When specifying an ExternalName, Træfik will forward requests to the given host accordingly
which points to the docs from kubernetes services without selectors
Which led me to create a service
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
Of which Traefik happily ignores when I point to it:
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-service
namespace: kube-system
spec:
rules:
- host: my-service.example.com
http:
paths:
- path: /
backend:
serviceName: my-service
servicePort: 4080
I have also tried as an endpoint.
---
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace: kube-system
spec:
ports:
- protocol: TCP
port: 80
targetPort: 4080
---
kind: Endpoints
apiVersion: v1
metadata:
name: my-service
subsets:
- addresses:
- ip: 10.0.0.3
ports:
- port: 4080
Does anyone know how to get traefik to point to an externalname as the documentation suggests?

As I see, you missed at least one line in your Ingress object - traefik.frontend.passHostHeader: "false".
Also, you need to create an Ingress object in a same Namespace with your Service.
So, your Ingress should be like:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-service
namespace: prod
annotations:
traefik.frontend.passHostHeader: "false"
spec:
rules:
- host: my-service.example.com
http:
paths:
- path: /
backend:
serviceName: my-service
servicePort: 4080
And service:
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
ports:
- name: app-port
port: 4080
externalName: my.database.example.com

Related

Kubernetes ingress not routing

I have 2 services and deployments deployed on minikube on local dev. Both are accessible when I run minikube start service. For the sake of simplicity I have attached code with only one service
However, ingress routing is not working
CoffeeApiDeployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: coffeeapi-deployment
labels:
app: coffeeapi
spec:
replicas: 1
selector:
matchLabels:
app: coffeeapi
template:
metadata:
labels:
app: coffeeapi
spec:
containers:
- name: coffeeapi
image: manigupta31286/coffeeapi:latest
env:
- name: ASPNETCORE_URLS
value: "http://+"
- name: ASPNETCORE_ENVIRONMENT
value: "Development"
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: coffeeapi-service
spec:
selector:
app: coffeeapi
type: NodePort
ports:
- protocol: TCP
port: 8080
targetPort: 80
nodePort: 30036
Ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- http:
paths:
- path: /coffee
pathType: Prefix
backend:
service:
name: coffeeapi-service
port:
number: 8080
You are missing the ingress class in the spec.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
spec:
ingressClassName: nginx # (or the class you configured)
Using NodePort on your service may also be problematic. At least it's not required since you want to use the ingress controller to route traffic via the ClusterIP and not use the NodePort directly.

Services can't communicate because there is not DNS resolving in Kubernetes

I configure my services with type ClusterIP. And I want to make them communicated.
Service
apiVersion: v1
kind: Service
metadata:
labels:
app: app-backend-deployment
name: app-backend
spec:
type: ClusterIP
ports:
- port: 8020
protocol: TCP
targetPort: 8100
selector:
app: app-backend
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: app-backend
name: app-backend-deployment
spec:
replicas: 1
selector:
matchLabels:
app: app-backend
template:
metadata:
labels:
app: app-backend
spec:
containers:
- name: app-backend
image: app-backend
ports:
- containerPort: 8100
imagePullPolicy: Never
ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: backend-conf # name of configMap
data:
BACKEND_SERVICE_HOST: app-backend:8020
And that is what I pass to the frontend service, and I want to make a REST call through the DNS name for example http://app-backend:8020/get/1. But like I see in the console app cannot resolve DNS name net::ERR_NAME_NOT_RESOLVED.
I also check pod nslookup:
busybox nslookup app-backend.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: app-backend.default.svc.cluster.local
Address: 10.106.41.36
And compare it to
kubectl describe svc app-backend
Name: app-backend
Namespace: default
Labels: app=app-backend-deployment
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"...
Selector: app=app-backend
Type: ClusterIP
IP: 10.106.41.36
Port: <unset> 8020/TCP
TargetPort: 8100/TCP
And like you can see there is the same IP on Address but I don't know and where to look what is wrong why dns resolver doesn't work. kubectl version Client "v1.15.5", Server Version:"v1.17.3",
Because of that frontend service that was served to the local machine (that how Angular works) REST request cannot go through Kubernetes DNS with another backend service. I need to communicate them through the Ingress. Due to different annotations, I have to use 2 Ingress. Meaby there is a better way to use just one, but when I want to use only one Ingress I can't find a way to make them both working, with the same annotation.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: app-backend-ingress
spec:
rules:
- host: app.io
http:
paths:
- path: /api(/|$)(.*)
backend:
serviceName: app-backend
servicePort: 8020
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
name: app-frontend-ingress
spec:
rules:
- host: app.io
http:
paths:
- path: /
backend:
serviceName: app-frontend
servicePort: 80

Send TCP traffic to the ingress's namespace with Nginx Ingress

I'm using an Nginx Ingress controller to open connections to a postgres database with the --tcp-services-configmap=k8s-ingress/k8s-ingress-tcp flag. That configmap looks like
apiVersion: v1
data:
"5432": namespace-a/the-postgres-svc:5432
kind: ConfigMap
This portion works perfectly, however I would like to open up another service on the same port, 5432 to namespace-b/the-postgres-svc:5432.
Is there any way to have the namespace selected be based on the namespace from the ingress resource? Since the data key would be identical if I were to just add that record to the after the "namespace-a" record I am not able to just append to the configmap data.
Thanks!
So you would like to have services on the same port in different namespaces.
I have found interesting step-by-step tutorial for this approach.
Firstly you should create two namespaces:
apiVersion: v1
kind: Namespace
metadata:
name: namespace-a
apiVersion: v1
kind: Namespace
metadata:
name: namespace-b
Than have your services and deployment definition, where the difference is between name and namespace fields:
apiVersion: v1
kind: Service
metadata:
labels:
run: nginx
name: namespacea-nginx
namespace: namespace-a
spec:
ports:
- port: 5432
protocol: TCP
targetPort: 5432
selector:
run: nginx
apiVersion: v1
kind: Service
metadata:
labels:
run: nginx
name: namespaceb-nginx
namespace: namespace-b
spec:
ports:
- port: 5432
protocol: TCP
targetPort: 5432
selector:
run: nginx
Deployment files:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
run: nginx
name: nginx
namespace: namespace-a
spec:
...
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
run: nginx
name: nginx
namespace: namespace-b
spec:
...
And finally, Ingress files definitions:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress
namespace: namespace-a
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: namespacea.com
http:
paths:
- backend:
serviceName: namespacea-nginx
servicePort: 5432
path: /
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress
namespace: namespace-b
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: namespaceb.com
http:
paths:
- backend:
serviceName: namespaceb-nginx
servicePort: 5432
path: /

Kubernetes Ingress to External Service?

Say I have a service that isn't hosted on Kubernetes. I also have an ingress controller and cert-manager set up on my kubernetes cluster.
Because it's so much simpler and easy to use kubernetes ingress to control access to services, I wanted to have a kubernetes ingress that points to a non-kubernetes service.
For example, I have a service that's hosted at https://10.0.40.1:5678 (ssl required, but self signed certificate) and want to access at service.example.com.
You can do it by manual creation of Service and Endpoint objects for your external server.
Objects will looks like that:
apiVersion: v1
kind: Service
metadata:
name: external-ip
spec:
ports:
- name: app
port: 80
protocol: TCP
targetPort: 5678
clusterIP: None
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-ip
subsets:
- addresses:
- ip: 10.0.40.1
ports:
- name: app
port: 5678
protocol: TCP
Then, you can create an Ingress object which will point to Service external-ip with port 80:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: external-service
spec:
rules:
- host: service.example.com
http:
paths:
- backend:
serviceName: external-ip
servicePort: 80
path: /
So I got this working using ingress-nginx to proxy an managed external service over a non-standard port
apiVersion: v1
kind: Service
metadata:
name: external-service-expose
namespace: default
spec:
type: ExternalName
externalName: <external-service> # eg example.example.com
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: external-service-expose
namespace: default
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" #important
spec:
rules:
- host: <some-host-on-your-side> # eg external-service.yourdomain.com
http:
- path: /
pathType: Prefix
backend:
service:
name: external-service
port:
number: <port of external service> # eg 4589
tls:
- hosts:
- external-service.yourdomain.com
secretName: <tls secret for your domain>
of-course you need to make sure that the managed url is reachable from inside the cluster, a simple check can be done by launching a debug pod and doing
curl -v https://example.example.com:4589
If your external service has a dns entry configured on it, you can use kubernetes externalName service.
---
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: myexternal.http.service.com
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: externalNameservice
namespace: prod
spec:
rules:
- host: service.example.com
http:
paths:
- backend:
serviceName: my-service
servicePort: 80
path: /
In this way, kubernetes create cname record my-service pointing to myexternal.http.service.com
I just want to update #Moulick answer here according to Kubernetes version v1.21.1, as for ingress the configuration has changed a little bit.
In my example I am using Let's Encrypt for my nginx controller:
apiVersion: v1
kind: Service
metadata:
name: external-service
namespace: default
spec:
type: ExternalName
externalName: <some-host-on-your-side> eg managed.yourdomain.com
ports:
- port: <port of external service> eg 4589
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: external-service
namespace: default
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/proxy-body-size: 100m
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" #important
spec:
tls:
- hosts:
- <some-host-on-your-side> eg managed.yourdomain.com
secretName: tls-external-service
rules:
- host: <some-host-on-your-side> eg managed.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: external-service
port:
number: <port of external service> eg 4589

Cannot create Ingress for Prometheus

I would like to create an entry for Prometheus.
I have nodePort service deployed like this :
---
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: monitoring
labels:
app: prometheus
spec:
type: NodePort
ports:
- port: 9090
targetPort: 9090
nodePort: 31190
protocol: TCP
selector:
app: prometheus
And my Ingress is :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: prometheus-ingress
namespace: monitoring
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: prometheus.example.com
http:
paths:
- path: /
backend:
serviceName: prometheus
servicePort: 9090
Can you explain me why my ingress didn't work ?
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: prometheus-ingress
namespace: monitoring
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- pathType: Prefix
path: /prometheus(/|$)(.*)
backend:
service:
name: prometheus
port:
number: 9090