[Services]
The each Pod has its own IP address.
Pods are ephemeral because are destory frequently when Pods delete OR terminated, recreating the new pods with existing YAML template OR command line interface.
So the Pod IP address are frequently keep on changing.
Service provides stable networking for pods (ephemeral pods) by bringing stable IP addresses and DNS names, and provide a way to Kubernetes to configuring a proxy to forward traffic to a set of pods.
Service selector matches a Pod label (OR) If the Label/Selector then Pod and Service match.
But the Service will maintain the stable static IP address to connect a set/group of pods in a cluster.
A service is assigned an IP address (cluster IP), which the service proxies use.
A service can map an incoming port to any targetPort. By default, the targetPort is set to the same value of the port field, and it can be defined as a string.
Services support TCP (default), UDP, and SCTP for protocols.
Services can be defined with or without a selector.
It is used to expose an application deployed on a set of pods using a single endpoint. It maps a fixed IP address to a logical group of pods.

          Client --> Worker Node IP --> NodePort --> ClusterIP/ClusterPort Service --> Pod
          Client --> LoadBalancer (Cloud, External like MetalLB) --> Worker Node IP --> NodePort --> ClusterIP/ClusterPort Service --> Pod

[ServiceTypes]
Kubernetes ServiceTypes allow you to specify what kind of Service you want.
● ClusterIP
The ClusterIP is the default for the service.
It is the default and most common service type.
This type makes the Service only reachable from with in the cluster via a cluster-internal IP.
Kubernetes will assign a cluster-internal IP address to ClusterIP service. This makes the service only reachable within the cluster.
It exposes the Pod to only within the cluster.
It assigns a private IP address in ClusterIP range.
It can talk to applications only with in the cluster.
So the Pods can reach the service on apps port number.
It exposes the service on an internal IP address in the cluster.
It exposes a service which is only accessible from within the cluster.
It cannot make requests to service (pods) from outside the cluster.
By default Kubernetes services are accessible at the ClusterIP which is an internal IP address reachable from inside of the Kubernetes cluster only.
It is the default type to expose the server only on an cluster-internal ip address.
This is the default type that exposes the service on an internal IP of the cluster. These services are only accessible within the cluster and is unreachable externally.
It is only used inside a Kubernetes cluster. It cannot be reached from outside the cluster and it’s not routable on the external network.
There are two ways to assign a virtual IP address for a Service.
* dynamically
The cluster control plane automatically picks a free IP address from within the configured IP range for "type: ClusterIP" Service.
* statically
So manually specify an IP address of choice, from within the configured IP range for Service.
● NodePort
A port that is the same on each node that is also reachable externally outside.
It exposes the Pod to outside the cluster.
It assigns a port on the worker nodes to expose it outside the cluster.
It exposes a service via a static port on each node’s IP.
It exposes the service on each node’s IP address at a static port.
Port is open on every node IP.
It exposes a port named NodePort on all worker nodes.
It exposes the service on the same port of each selected Node in the cluster.
Make the service accessible from outside the cluster using "NODE_PUBLIC_IP_ADDRESS:NODE_PORT_NO".
This type of service makes it possible to access a Service by directing requests to a specific port on every Node, accessed via the NodeIP (Kubernetes automatically creates a ClusterIP service to route the request). 
To make the service accessible from outside of the cluster a user can create a service of type NodePort.
When creating a NodePort service, the user can specify a port from the range 30000-32767, and each Kubernetes node will proxy that port to the pods selected by the service.
The nodePort is dynamically OR randomly took the port number range between 30000 to 32767 by default.
It defines a range of ports to use for NodePort allocation and usually defaults to 30000-32767.
But can also assign statically OR particular specific custom port number.
It allows to expose the service through a static OR dynamic port on the node.
A NodePort service exposes the service on the IP of each node at a static port.
Users can communicate with the service from the outside by requesting <NodeIP>:<NodePort>.
● LoadBalancer
It created by the cloud provider that will route external traffic to every node on the NodePort (ELB on AWS).
It exposes the Pod to outside the cluster.
It create a LoadBalancer in cloud.
It exposes the service via the cloud provider’s load balancer.
It exposes the service externally using a load balancer.
It allows to expose the service using a cloud provider’s external load balancer and automatically creates the necessary NodePorts and ClusterPorts OR ServicePorts (ClusterIPs) to route the desired traffic.
LoadBalancer builds on NodePort and create an external load-balancer in cloud such as AWS, Azure, GCP.
* Static IP
By default it get an ephemeral IP address assigned by the load balancer (GCP).
It specify a static IP address for the load balancer.
● ExternalName
It can provide a DNS name for the service.
This only works when the DNS add-on is enabled.
It add CNAME DNS record to coreDNS.
This type of service were used to maps the service to a CNAME record such as a Fully Qualified Domain Name.
This Service type uses DNS in place of a selector and creates an internal CNAME DNS entry that aliases another.

[Headless]
It allows us to interact directly with the Pods instead of a proxy.
It allows direct connection to a Pod. So it won't take any support in ServiceTypes. 
The client/user wants to communicate with one specific Pod directly.
Pods want to talk directly with specific Pod.
Headless service is accessible only from within the cluster (just like ClusterIP service).
A virtual IP address is not allocated for the Headless service. So there is no load balancing performed (which also means that kube-proxy does not play a role within this type of service).
Headless service addresses the use cases where the clients need to connect to any or all of those pods directly using the endpoint (pod) IP address.
So not randomly selected, mostly it will be used in Stateful applications like Databases.
Headless Service mostly will be used in Databases. The below diagram will be example to understand.
                    POD_MySQL-0                                              POD_MySQL-1
                     (master)                                                 (worker)
                       |  |                                                     |  |
                       |  |                                                     |  |
              writing  |  |  reading <-- continuous syncronization --> reading  |  |  reading
                                              (data replicas)
Only master is allowed to write to Database (DB).
A scenario for this type of direct connectivity would be with databases where the client needs to connect to the primary database node.
In those scenarios a client would need to figure out the endpoint IP (rather than the service' s virtual IP address) and then connect to them directly.

{Port in YAML}
● targetPort
The 'targetPort' will be connect to the Pod Container port number.
The 'targetPort' on the pod to forward traffic.
This port on the pod that the request get sent to that pod will be listening on.
So application in the container will needs to be listening for network requests on this port for the service. 
● port
The 'port' will be connect to the 'targetPort' to the Pod Container port number.
The port of this service.
It exposes the service on the specific port internally with in the cluster.
So other pods with in the cluster can communicate with this server on the specific port.
● nodePort
It exposes the service externally visible outside the cluster by node public ip address and node port no. The service also has to be of type NodePort.

[hostPort]
The hostPort setting applies to the Kubernetes containers.
The container port will be exposed to the external network at <hostIP>:<hostPort>, where the hostIP is the IP address of the Kubernetes node where the container is running and the hostPort is the port requested by the user.
The hostPort feature allows to expose a single container port on the host IP.
Using the hostPort to expose an application to the outside of the Kubernetes cluster.
The host IP can change when the container is restarted, two containers using the same hostPort cannot be scheduled on the same node.

[hostNetwork]
When a pod is configured with "hostNetwork: true", the applications running in such a pod can directly see the network interfaces of the host machine where the pod was started.
An application that is configured to listen on all network interfaces will in turn be accessible on all network interfaces of the host machine.
The every time the pod is restarted Kubernetes can reschedule the pod onto a different node and so the application will change its IP address.
Besides that two applications requiring the same port cannot run on the same node. 
This can lead to port conflicts when the number of applications running on the cluster grows.

[Endpoints]
Endpoint defines which pods (or other servers) are exposed through a service.
For Kubernetes Services, Kubernetes creates a Endpoint object. 
This endpoint will have the ip address mapping of the pods. This is created automatically for services with a defined selector.
Endpoints can also be used to connect to external services like they were internal to the kubernetes cluster.
Service selector matches a pod label, Kubernetes will automatically create an Endpoints object with the same name as the service, which stores the pod’s IP address and port.
When the service receives a request, its proxy will redirect it to one of those IPs and ports.
Kubernetes will automatically update the endpoint resource IPs in case of editing or scaling of a deployment in which pods are already linked to a service.
If create a service without specifying a pod selector, Kubernetes will not generate the endpoint resource and it will be up to create one with the endpoints to link to the service.
● With selectors
If a selector is used, the endpoint controller creates an endpoint record in the API, modifying DNS record and returning an A record that points to the required pods.
● Without selectors
If a selector is not used, the endpoint controller will not create any endpoint records without having the selectors configured.

[EndpointSlice]
It provide a simple way to track network endpoints within a Kubernetes cluster.
It offer a more scalable and extensible alternative to Endpoints.
It contains references to a set of network endpoints.

[IPs and Ports]
● Pod IP
In the Pod Container inside the port number of an application.
In a Service the 'targetPort' will connect to the Pod Container port number.
$ curl http://POD_IP_ADDRESS:POD_CONTAINER_PORT_NO
The above command will only work with in the Pod.
● Service IP
In a Service the 'port' will connect to the 'targetPort' to the Pod Container port number.
$ curl http://CLUSTER_IP_ADDRESS:SERVICE_PORT_NO
$ curl http://CLUSTER_IP_ADDRESS:CLUSTER_PORT_NO
The above command will only work with in the Cluster.
The "--port=SERVICE_PORT_NO" mean that "--port=CLUSTER_PORT_NO".
● Node IP
If need to access the application from outside then need a "NODE_PUBLIC_IP_ADDRESS:NODE_PORT_NO".
$ curl http://NODE_PUBLIC_IP_ADDRESS:NODE_PORT_NO
The above command will work to access inside and outside of the cluster.

[IP]
The below options is used for manually to assign the IP address.
● clusterIP
The 'clusterIP' option field can manually assign to a clusterIP between the range of a IP address for used with in the internal cluster.
● externalIPs
The 'externalIPs' option field can manually assign an one OR more cluster nodes IP address.
The 'externalIPs' that route to one or more cluster nodes, Kubernetes Services can be exposed on those externalIPs.
Traffic that ingresses into the cluster with the external IP (as destination IP), on the Service port, will be routed to one of the Service endpoints.
The 'externalIPs' are not managed by Kubernetes and are the responsibility of the cluster administrator.
● loadBalancerIP
The 'loadBalancerIP' option field can manually assign a IP address for expose to outside the cluster.
