Service
最后更新于
最后更新于
From the outset, Kubernetes incorporated mechanisms for container service discovery and load balancing, establishing the Service resource and, in conjunction with kube-proxy and cloud provider, adapted it to different application scenarios. With the explosive growth of Kubernetes users and increasingly diverse user scenarios, some new load balancing mechanisms have emerged. Currently, the load balancing mechanisms in Kubernetes can be roughly classified into the following categories, each with its specific application scenario:
Service: Directly uses Service to provide internal cluster load balancing, and leverages the LB provided by the cloud provider for external access.
Ingress Controller: Still uses Service for internal cluster load balancing, but external access is enabled via customized Ingress Controller.
Service Load Balancer: Runs the load balancer directly in the container, implementing Bare Metal's Service Load Balancer.
Custom Load Balancer: Customized load balancing replaces kube-proxy and is usually used when deploying Kubernetes physically, facilitating the connection to existing external services in the company.
A Service is an abstraction of a group of Pods providing the same functionality, providing them with a unified access point. With Service, applications can easily implement service discovery and load balancing, as well as zero-downtime upgrades. Service selects service backends through labels, usually working with Replication Controller or Deployment to ensure the normal operation of backend containers. The Pod IPs and port lists matching these labels form endpoints, with kube-proxy responsible for load balancing the service IP to these endpoints.
There are four types of Service:
ClusterIP: Default type, automatically assigns a virtual IP that can only be accessed internally by the cluster.
NodePort: Based on ClusterIP, binds a port for the Service on each machine, allowing access to the service through <NodeIP>:NodePort
. If kube-proxy has set --nodeport-addresses=10.240.0.0/16
(supported by v1.10), then this NodePort is only valid for IPs set within this range.
LoadBalancer: Based on NodePort, creates an external load balancer with the help of the cloud provider, redirecting requests to <NodeIP>:NodePort
.
ExternalName: Redirects the service to a specified domain (set through spec.externlName
) via DNS CNAME record. Requires kube-dns version 1.7 or later.
Additionally, existing services can be added to the Kubernetes cluster in Service format. When creating a Service, do not specify a Label selector. Instead, manually add an endpoint after the Service is created.
A Service is defined through yaml or json, such as the below example that defines a service called nginx, which forwards the service's port 80 to port 80 of the Pod labeled run=nginx
in the default namespace.
When the service requires multiple ports, each port must be given a name.
Service, Endpoints, and Pod support three types of protocols:
TCP (Transmission Control Protocol) is a connection-oriented, reliable, byte-stream transport layer communication protocol.
UDP (User Datagram Protocol) is a connectionless transport layer protocol used for unreliable information delivery services.
SCTP (Stream Control Transmission Protocol) is used to transmit SCN (Signaling Communication Network) narrow band signaling messages over IP networks.
Kubernetes Version | Core API Version |
---|---|
v1.5+ | core/v1 |
When creating a Service, you can also choose not to specify Selectors, used to forward the service to services outside the Kubernetes cluster (instead of to Pods). At present, two methods are supported:
(1) Custom endpoints, that is, create a service and endpoint of the same name and set the IP and port of the external service in the endpoint.
(2) Forwarding via DNS, specifying externalName in the service definition. In this case, the DNS service will create a CNAME record for <service-name>.<namespace>.svc.cluster.local
, with its value set to my.database.example.com
. Moreover, the service will not be automatically assigned a Cluster IP and needs to be accessed through the service's DNS.
Note: The IP address of the Endpoints cannot be 127.0.0.0/8, 169.254.0.0/16 or 224.0.0.0/24, nor can it be the clusterIP of other services in Kubernetes.
A Headless Service is one that does not require a Cluster IP. This is specified when creating a service by setting spec.clusterIP=None
. This includes two types:
No Selectors specified but an externalName is set (See above 2), handled by the CNAME record.
Selectors specified, with a DNS A record setting the backend endpoint list.
Note: Some of the information queried in the dig command is omitted.
Different types of Service handle the source IP differently:
ClusterIP Service: Using iptables mode, the source IP within the cluster is retained (no SNAT). If the client and server pod are on the same Node, the source IP is the IP address of the client pod; if on different Nodes, the source IP depends on how the network plugin handles it. For instance, when using flannel, the source IP is the node flannel IP address.
NodePort Service: By default, the source IP would undergo SNAT, and the server pod would see the source IP as Node IP. To avoid this, the service can be set to spec.ExternalTrafficPolicy=Local
(for versions 1.6-1.7, set Annotation service.beta.kubernetes.io/external-traffic=OnlyLocal
), allowing the service to proxy requests for local endpoints only (if there are no local endpoints, the packets are directly dropped), thus retaining the source IP.
LoadBalancer Service: By default, the source IP would undergo SNAT, and the server pod sees the source IP as Node IP. After setting service.spec.ExternalTrafficPolicy=Local
, the Node without local endpoints will be automatically removed from the cloud platform load balancer, thus retaining the source IP.
By default, Kubernetes considers all Endpoints IP in the cluster to be Service backends. By setting .spec.internalTrafficPolicy=Local
, kube-proxy will only load balance for local Endpoints on the Node.
Note, with the internal network policy enabled, even if other Nodes have functioning Endpoints, if there are no Pods running locally on the Node, the Service will be inaccessible.
kube-proxy is responsible for load balancing the service to the backend Pod, as shown in the diagram:
Although Service solves the problems of service discovery and load balancing, it still has some limitations in use, for example:
It only supports layer 4 load balancing and lacks layer 7 functionality.
For external access, NodePort type requires additional load balancing at the external, whereas LoadBalancer requires Kubernetes to run on a supported cloud provider.
Ingress is a newly introduced resource designed to address these limitations, mainly used to expose services outside the cluster and allows customizing service access policies. For instance, if you want to access different services through different subdomains via a load balancer:
You can define Ingress like this:
Note the Ingress itself does not automatically create a load balancer, an ingress controller needs to be operating within the cluster managing the load balancer according to the Ingress definition. The community currently provides reference implementations for nginx and gce.
Traefik offers an easy-to-use Ingress Controller, the use of which is explained at https://doc.traefik.io/traefik/providers/kubernetes-ingress/.
For a more in-depth introduction to Ingress and Ingress Controller, see ingress.
Before the introduction of Ingress, Service Load Balancer was the recommended method to address the limitations of Service. Service Load Balancer runs haproxy in containers and monitors changes in service and endpoints, providing layer 4 and layer 7 load balancing services through container IP.
The community provided Service Load Balancer supports four load balancing protocols: TCP, HTTP, HTTPS and SSL TERMINATION, and also supports ACL access control.
Note: Service Load Balancer is no longer recommended for use. The use of Ingress Controller is recommended instead.
Despite Kubernetes offering a variety of load balancing mechanisms, in practice, some complex scenarios are unsupported, such as:
Connecting to existing load balancing equipment
In multi-tenant network situations, the container network and host network are isolated, rendering kube-proxy
dysfunctional.
At these times, components can be customized and used to replace kube-proxy for load balancing. The basic idea is to monitor changes in service and endpoints in Kubernetes and configure the load balancer according to these changes, seen in weave flux, nginx plus, kube2haproxy, and more.
A Service's ClusterIP is an internal virtual IP address in Kubernetes that cannot be accessed directly from outside. But what if it's necessary to access these services from the outside? There are several ways:
Use NodePort service to bind a port on each machine, allowing access to the service through <NodeIP>:NodePort
.
Use LoadBalancer service to create an external load balancer with the help of Cloud Provider, redirecting requests to <NodeIP>:NodePort
. This method is only applicable to Kubernetes clusters running on the cloud platform. For clusters deployed on physical machines, MetalLB can implement similar functionality.
Create L7 load balancing atop Service through Ingress Controller and open it to the public.
Use ECMP to route the Service ClusterIP network segment to each Node, allowing direct access through ClusterIP and even direct use of kube-dns outside the cluster. This method is applied in situations of depolyment on physical machines.
[https://github