I'm trying to create a Service on cluster A that points to the IP address of cluster B. I do not have a domain name for cluster B, so can't use ExternalName. The way that I'm trying to do this is by creating a Service without a selector on cluster A and manually creating an EndpointSlice resource for that service which will point to cluster B. According to Kubernetes documentation, I need to "link an EndpointSlice to a Service by setting the kubernetes.io/service-name label on that EndpointSlice." But even after doing so, my service apparently has no endpoints.
Code
endpointslice.yaml
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: hack-svc-1
labels:
kubernetes.io/service-name: hack-svc
kubernetes.io/managed-by: manual
addressType: IPv4
ports:
- port: 80
endpoints:
- addresses:
- "cluster B's IPv4 address here"
conditions:
ready: true
service.yaml
apiVersion: v1
kind: Service
metadata:
name: hack-svc
spec:
ports:
- port: 80
After kubectl describe service hack-svc:
Name: hack-svc
Namespace: default
Labels: <none>
Annotations: <none>
Selector: <none>
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: <IPv4 address here>
IPs: <IPv4 address here>
Port: http 80/TCP
TargetPort: 80/TCP
Endpoints: <none> <-- No endpoints??
Session Affinity: None
Events: <none>
How can I associate the EndpointSlice with my Service?
EndpointSlice API is a scalable and extensible alternative to the Endpoints API. EndpointSlices gathers information such as IP addresses, ports, readiness, and topology from the pods of a service. Follow this tutorial and verify whether there are any mismatches while configuring EndpointSlices for your clusters it helped in my case.
Related
As per Helm docs, The lookup function can be used to look up resources in a running cluster.
Is there any way to get the api server endpoint URL using that function?
So far I was able to get the endpoint in two ways.
kubectl describe svc kubernetes -n default
Name: kubernetes
Namespace: default
Labels: component=apiserver
provider=kubernetes
Annotations: <none>
Selector: <none>
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.43.0.1
IPs: 10.43.0.1
Port: https 443/TCP
TargetPort: 6443/TCP
Endpoints: 10.0.50.111:6443
Session Affinity: None
Events: <none>
kubectl config view -o jsonpath="{.clusters[?(#.name==\"joseph-rancher-cluster-2\")].cluster.server}"
https://api.joseph-rancher-cluster-2.rancher.aveshalabs.io
But having trouble to use them with lookup. Thanks in advance.
Update:
I tried to extract the ip & https port from the Endpoints resource on the running cluster.
kubectl get ep -n default -o yaml
apiVersion: v1
items:
- apiVersion: v1
kind: Endpoints
metadata:
creationTimestamp: "2023-01-04T05:08:43Z"
labels:
endpointslice.kubernetes.io/skip-mirror: "true"
name: kubernetes
namespace: default
resourceVersion: "208"
uid: db5e0476-9169-41cf-bd00-f6f52162c0ef
subsets:
- addresses:
- ip: 10.0.50.111
ports:
- name: https
port: 6443
protocol: TCP
kind: List
metadata:
resourceVersion: ""
But the problem is, it returns a private IP which is unusable in case of cloud clusters. What I need is this;
kubectl cluster-info
Kubernetes control plane is running at https://api.joseph-rancher-cluster-2.rancher.aveshalabs.io
CoreDNS is running at https://api.joseph-rancher-cluster-2.rancher.aveshalabs.io/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
Which can be extracted from the kubeconfig file as well. So is there any template function which I can use to get the api server endpoint ?
I've been following multiple tutorials on how to deploy my (Spring Boot) api on Minikube. I already got it (user-service running on 8081) working in a docker container with an api gateway (port 8080) and eureka (port 8087), but for starters I just want it to run without those. Steps I took:
Push docker container or image (?) to docker hub, I don't know the proper term.
Create a deployment.yaml:
apiVersion: v1
kind: Service
metadata:
name: kwetter-service
spec:
type: LoadBalancer
selector:
app: kwetter
ports:
- protocol: TCP
port: 8080
targetPort: 8081
nodePort: 30070
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: kwetter-deployment
labels:
app: kwetter
spec:
replicas: 1
selector:
matchLabels:
app: kwetter
template:
metadata:
labels:
app: kwetter
spec:
containers:
- name: user-api
image: cazhero/s6-kwetter-backend_user:latest
ports:
- containerPort: 8081 #is the port it runs on when I manually start it up
kubectl apply -f deployment.yaml
minikube service kwetter-service
It takes me to an empty site with url: http://192.168.49.2:30070 which I thought I could use to make API calls to, but apparently not. How do I make api calls to my application running on minikube?
Get svc returns:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d4h
kwetter-service LoadBalancer 10.106.42.56 <pending> 8080:30070/TCP 4d
describe svc kwetter-service:
Name: kwetter-service
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=kwetter
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.106.42.56
IPs: 10.106.42.56
Port: <unset> 8080/TCP
TargetPort: 8081/TCP
NodePort: <unset> 30070/TCP
Endpoints: 172.17.0.4:8081
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Type 6s service-controller LoadBalancer -> NodePort
Made an Ingress in the yaml, used kubectl get ing:
NAME CLASS HOSTS ADDRESS PORTS AGE
kwetter-ingress <none> * 80 49m
To make some things clear:
You need to have pushed your docker image cazhero/s6-kwetter-backend_user:latest to docker hub, check that at https://hub.docker.com/, in your personal repository.
What's the output of minikube service kwetter-service, does it print the URL http://192.168.49.2:30070?
Make sure your pod is running correctly by the following minikube command:
# check pod status
minikube kubectl -- get pods
# if the pod is running, check its container logs
minikube kubectl -- logs po kwetter-deployment-xxxx-xxxx
I see that you are using LoadBalancer service, where a LoadBalancer service is the standard way to expose a service to the internet. With this method, each service gets its own IP address.
Check external IP
kubectl get svc
Use the external IP and the port number in this format to access the
application.
http://REPLACE_WITH_EXTERNAL_IP:8080
If you want to access the application using Nodeport (30070), use the Nodeport service instead of LoadBalancer service.
Refer to this documentation for more information on accessing applications through Nodeport and LoadBalancer services.
I've created a Kubernetes Service whose backend nodes aren't part of the Cluster but a fixed set of nodes (having fixed IPs), so I've also created an Endpoints resource with the same name:
apiVersion: v1
kind: Service
metadata:
name: elk-svc
spec:
ports:
- port: 9200
targetPort: 9200
protocol: TCP
---
kind: Endpoints
apiVersion: v1
metadata:
name: elk-svc
subsets:
-
addresses:
- { ip: 172.21.0.40 }
- { ip: 172.21.0.41 }
- { ip: 172.21.0.42 }
ports:
- port: 9200
Description of Service and Endpoints:
$ kubectl describe svc elk-svc
Name: elk-svc
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"elk-svc","namespace":"default"},"spec":{"ports":[{"port":9200,"protocol":"TCP"...
Selector: <none>
Type: ClusterIP
IP: 10.233.17.18
Port: <unset> 9200/TCP
Endpoints: 172.21.0.40:9200,172.21.0.41:9200,172.21.0.42:9200
Session Affinity: None
Events: <none>
$ kubectl describe ep elk-svc
Name: elk-svc
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Endpoints","metadata":{"annotations":{},"name":"elk-svc","namespace":"default"},"subsets":[{"addresses":[{"ip":"172.21.0.40"...
Subsets:
Addresses: 172.21.0.40,172.21.0.41,172.21.0.42
NotReadyAddresses: <none>
Ports:
Name Port Protocol
---- ---- --------
<unset> 9200 TCP
Events: <none>
My pods are able to communicate with ElasticSearch using the internal cluster IP 10.233.17.18. Everything goes fine !
My question is about if there's any way to have some kind of healthCheck mechanism for that Service I've created so if one of my ElasticSearch nodes goes down, ie: 172.21.0.40, then the Service is aware of that and and will no longer route traffic to that node, but to the others. Is that possible ?
Thanks.
This is not supported in k8s.
For more clarification refer this issue raised on your requirement ::
https://github.com/kubernetes/kubernetes/issues/77738#issuecomment-491560980
For this use-case best practice would be to use a loadbalancer like haproxy
My suggestion will be to have a reverse proxy such as nginx or haproxy infront of the elastic nodes which will do health check for those nodes.
I've provisioned a kubernetes cluster on my own couple of virtual machines via kubespray. Kubespray uses project-calico as default network-plugin which fits my requirements of proxying services in the cluster network to the outer world pretty well.
Kubespray deploys the apiserver itself as a ClusterIP Service. To make it reachable from outside it defines an Endpoint of this service with the master nodes Host IP Adress, which is routed to the internal ClusterIP by Calico as far as I could figure it out by myself.
My Question is: How is it possible to define my own endpoint (for another service), as these get implicietly defined already by provisioning the service.yaml and cannot be overwritten. I would like to follow a similar approach to get my Rook/Ceph Dashboard visible from outside the cluster.
EDIT: Note that kubectl get ingresses.networking.k8s.io --all-namespaces returns No resources found. and kubectl describe service kubernete returns
Name: kubernetes
Namespace: default
Labels: component=apiserver
provider=kubernetes
Annotations: <none>
Selector: <none>
Type: ClusterIP
IP: 10.233.0.1
Port: https 443/TCP
TargetPort: 6443/TCP
Endpoints: 192.168.103.254:6443
Session Affinity: None
Events: <none>
I'll refer to your question:
How is it possible to define my own endpoint?
You'll have to:
1 ) Create a Service without a Pod selector:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- protocol: TCP
port: 8080
targetPort: 9376
(At this point, no auto-generated Endpoints will be created by K8S because it can't decide to which pods those Endpoints should be referring).
2 ) Crate an Endpoints object and map it to the desired network address and port where the external resource is running:
apiVersion: v1
kind: Endpoints
metadata:
name: my-service
subsets:
- addresses:
- ip: 192.0.2.45
ports:
- port: 9376
(*) Notice that there should be a match between the service name and the name of the Endpoints object.
I am not exactly sure if what You mean but i think what You are looking for is ability to expose services externally.
You can expose Your services like Rook/Ceph Dashboard with "Publishing Services" (service types that expose internal services externally).
As quoted from kubernetes documentation:
For some parts of your application (for example, frontends) you may
want to expose a Service onto an external IP address, that’s outside
of your cluster.
Kubernetes ServiceTypes allow you to specify what kind of Service
you want. The default is ClusterIP.
Type values and their behaviors are:
ClusterIP: Exposes the Service on a cluster-internal IP. Choosing this value makes the Service only reachable from within the
cluster. This is the default ServiceType.
NodePort:
Exposes the Service on each Node’s IP at a static port (the
NodePort). A ClusterIP Service, to which the NodePort
Service routes, is automatically created. You’ll be able to contact
the NodePort Service, from outside the cluster, by requesting
<NodeIP>:<NodePort>.
LoadBalancer:
Exposes the Service externally using a cloud provider’s load balancer.
NodePort and ClusterIP Services, to which the external load
balancer routes, are automatically created.
ExternalName:
Maps the Service to the contents of the externalName field (e.g.
foo.bar.example.com), by returning a CNAME record with its value. No proxying of any kind is set up.
Here is an example from documentation.
You can also define the Services with yaml manifests like this:
apiVersion: v1
kind: Service
metadata:
name: examplelb
spec:
type: LoadBalancer
selector:
app: asd
ports:
-
name: koala
port: 22223
targetPort: 22225
nodePort: 31913
-
name: grisly
port: 22224
targetPort: 22226
nodePort: 31914
-
name: polar
port: 22225
targetPort: 22227
nodePort: 31915
This makes pods with label: app: asd have following ports exposed with pattern
internal port 22223 exposed on 31913.
$ kubectl get svc examplelb
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
examplelb LoadBalancer 10.111.8.204 <pending> 22223:31913/TCP,22224:31914/TCP,22225:31915/TCP 7d2h
If service with type LoadBalancer has External-IP pending you can still access all those ports on each node as NodePort.
Hope this helps.
In the following code, which URL will be exposed to the outside of kubernetes cluster. Is it 78.11.24.19 or 146.148.47.155?
I am trying to understand the loadbalancer and ingress here.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
clusterIP: 10.0.171.239
loadBalancerIP: 78.11.24.19
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 146.148.47.155
This is nicely explained on Create an External Load Balancer section Finding your IP address
.
You can find the IP address created for your service by getting the service information through kubectl:
kubectl describe services example-service
which should produce output like this:
Name: example-service
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=example
Type: LoadBalancer
IP: 10.67.252.103
LoadBalancer Ingress: 192.0.2.89
Port: <unnamed> 80/TCP
NodePort: <unnamed> 32445/TCP
Endpoints: 10.64.0.4:80,10.64.1.5:80,10.64.2.4:80
Session Affinity: None
Events: <none>
The IP address is listed next to LoadBalancer Ingress.
Update:
It's explained at Object Spec and Status:
Every Kubernetes object includes two nested object fields that govern the object’s configuration: the object spec and the object status. The spec, which you must provide, describes your desired state for the object–the characteristics that you want the object to have. The status describes the actual state of the object, and is supplied and updated by the Kubernetes system. At any given time, the Kubernetes Control Plane actively manages an object’s actual state to match the desired state you supplied.`