In Kubernetes, Pods have a life cycle. They are created and terminated, but cannot be resurrected. Create and delete pods dynamically in Kubernetes using ReplicationControllers. Each Pod then has its own IP address, but these IP addresses change over time. This leads to a question: if in a Kubernetes cluster, the front-end pods need to invoke the functionality of the back-end pods, how do these front-end pods find and track the back-end pods?

In Kubernetes, a Service is an abstract concept that defines a logical set of PODS and the policies for accessing these Pods. The Service selects the Pod through the Label Selector. For example, a Pod runs on the back end with three copies that are interchangeable, and the front end does not need to care about using that copy. The Service abstraction is used to achieve this decoupling capability. For Kubernetes-native applications, when a Pod in a Service changes, Kubernetes updates it through the Endpoints API class. For non-native applications, Kubernetes provides a virtual-IP-based bridge through which to redirect the Pod at the back end. In this article, you describe how to define a Service, publish a Service, and discover a Service.

1. Virtual IP and service proxy

In each Kubernetes Node, a Kube-proxy runs, which implements the virtual IP format for the service (except ExternalName). In Kubernetes V1.0, the service is a 4-tier (TCP/UDP over IP) structure that implements proxies purely in Userspace; In Kubernetes V1.1, the Ingress API was added, which expresses layer 7 (HTTP) services; Also added the iptables agent, which is the default after Kubernetes V1.2; In Kubernetes V1.8.0-beta.0, ipvS proxy was added.

In iptables mode, kube-proxy creates iptables rules to redirect Service virtual IP requests to Endpoints. Iptables code mode is implemented by using Linux IPtables NAT forwarding. Kube-proxy monitors Service and Endpoints objects in Kubernetes Master and adds and removes them to update the iptables rules.

  • For each Service, it will install the IPtable rule, which takes traffic to the Service’s clusterIP and port and passes the traffic to the Service back-end set.
  • For each Endpoints object, it installs the IPtable rule that selects the Pod on the back end.

2. Define services

In Kubernetes, a service is a REST object, similar to a Pod. Like all REST objects, the service definition can be passed to Apiserver to create a new instance. For example, here is a set of PODS exposed to port 9367 labeled APP: MyApp:

kind:Service apiVersion:v1 metadata: name:my-service spec: selector: app:MyApp ports: - protocol:TCP port:80 # Exposed port on the cluster Ip for use within the cluster targetPort:9376 # PORT on the PODCopy the code

In this configuration file, a service object named “my-service” is created with a targetPort of 9376 on each Pod labeled “app=MyApp”. The service will be assigned an IP address (sometimes called a “cluster IP”), the service selector will be evaluated continuously, and the evaluation results will be passed to Endpoints objects also named “my-service.”

Note that the service can map an input port to any targetPort. By default, targetPort will be set to the same value as port. TargetPort can be a string that references the port name in the backend Pod. The actual port value varies depending on the backend Pod. This provides a great deal of flexibility for deploying services. The Kubernetes service supports TCP and UDP. The default protocol is TCP.

2.1 Services without selectors

Services are typically used to proxy Pod access, but can also proxy other types on the back end, such as:

  • Use external databases in production, but use in-cluster data in test;
  • Services will need to be invoked by services in another namespace or on another cluster;
  • Migrating applications to Kubernetes and some back ends running outside Kubernetes.

In each of these scenarios, you can define a Service without a selector:

kind:Service apiVersion:v1 metadata: name:my-service spec: ports: - protocol:TCP port:80 #Cluster IP port 80, this port can only access the port on targetPort:9376 #Pod within the ClusterCopy the code

Since this Service has no selector, no corresponding Endpoints object will be created. You can manually map the Service to the specified Endpoints:

Kind :Endpoints apiVersion:v1 metadata: name:my-service subsets: -addresses: -ip :1.2.3.4 ports: -port :9376Copy the code

Note: The Endpoint IP cannot be loopback (127.0.0.0/8), link-local (169.254.0.0/16), or link-local multicast (224.0.0.0/24). Accessing a Service without a selector is the same as accessing a Service with a selector. Traffic will be routed through user-defined endpoints.

2.2 ExternalName service

ExternalName Service is a special case of Service that has no selector and does not define any ports or Endpoints. It returns the external alias of the Service outside the cluster.

kind:Service apiVersion:v1 metadata: name:my-service namespace:prod spec: Type: ExternalName # service type for an external service externalName:my.database.example.com # external servicesCopy the code

When my-service.prod.svc.cluster is searched, the CLUSTER DNS service will return a CNAME record with the value my.database.example.com. Of course, you can later migrate the database to a cluster so that it can be started with Pod, add appropriate selectors or Endpoints to it, and change the service type.

2.3 the headless service

In some scenarios, a service may not need to act as a load-balancing agent, but only need a single cluster IP. You can create a “headless” service by setting “spec.clusterIP” to None. This type of service allows developers to reduce their dependence on the Kubernetes system and implement automatic discovery of the service in their own way. Applications can also use other service discovery systems for self-registration and adaptors of services to realize automatic service discovery. For such a service:

  • Kubernetes unassigned cluster IP;
  • Kube-proxy will not handle these services;
  • Therefore, there is no load balancing or proxy.
  • However, it depends on whether the service has a selector for DNS configuration.

For a Headless service with a selector defined, the Endpoints controller creates Endpoints records in the API and returns a record that points to the Pod at the back end of the service by modifying the DNS configuration information. For headless services that do not have a selector defined, the Endpoints controller does not create Endpoints records; however, the DNS system will address and configure them.

  • CNAME record:ExternalName typeservice
  • Endpoints record: Any Endpoints that share a name with a service.

2.4. Multi-port service

In actual application scenarios, some services need to expose multiple ports. In Kubernetes, you can define multiple ports on a Service object. When multiple ports are used, you need to set a name for each port. For example, the following service YAML configuration file named my-service exposes an HTTP port and an HTTPS port.

kind:Service apiVersion:v1 metadata: name:my-service spec: selector: app:MyApp ports: - name: HTTP # Port with the name HTTP protocol:TCP port:80 targetPort:9376 - name: HTTPS # Port with the name HTTPS protocol:TCP # Port with the name TCP port:443 #ClusterIP port 443 targetPort:9377 #Pod port 9377Copy the code

2.5 Proxy external Services

In addition, in some scenarios, containerized applications in Kubernetes need to call applications outside of the cluster. Service can also proxy any other back-end applications, such as Oracle, MySQL, and Redis, that run outside the Kubernetes cluster. In Kubernetes, services and EndPoints of the same name are defined to implement the proxy for external applications so that they can be called by applications within the cluster.

Here are the access external Oralce endpoint YAML files:

ApiVersion: v1 kind: Endpoints metadata: name: oracle-service subsets: -addresses: -ip: 192.168.8.159 Ports: -port: 1521 protocol: TCPCopy the code
apiVersion: v1
kind: Service
metadata:
  name: oracle-service
spec:
  ports:
  - port: 1521
    targetPort: 1521
    protocol: TCPCopy the code

3. Discovery services

In Kubernetes, two modes of service discovery are supported:

  • The environment variable
  • DNS

3.1 Environment Variables

When a Pod is running on Node, Kubelet will add environment variables for each active Service. There are two types of environment variables:

  • DockerLink environment variable: equivalent to Docker’s -link parameter to implement container connection set environment variable.
  • {SVCNAME}_SERVICE_HOST and {SVCNAME}_SERVICE_PORT. The names of the environment variables are uppercase letters and underscores.

For example, there is a Service named “redies-master” whose cluster IP address is 10.0.0.11, port number is 6379, and protocol is TCP. Its environment variables are as follows:

REDIS_MASTER_SERVICE_HOST=10.0.0.11 REDIS_MASTER_SERVICE_PORT=6379 REDIS_MASTER_PORT = TCP: / / 10.0.0.11:6379 REDIS_MASTER_PORT_6379_TCP = TCP: / / 10.0.0.11:6379 TCP REDIS_MASTER_PORT_6379_TCP_PORT REDIS_MASTER_PORT_6379_TCP_PROTO = = 6379 REDIS_MASTER_PORT_6379_TCP_ADDR = 10.0.0.11Copy the code

Here, you can see that the ENVIRONMENT variable records the IP address and port of the “redies- Master” service, as well as the protocol information. Therefore, applications in Pod can discover this service through environment variables. However, the environment variable approach has the following limitations:

1) Environment variables can only be used in the same namespace;

2) In addition, the Service must be created before the Pod is created, otherwise the Service variable will not be set to the Pod;

3) THE DNS service discovery mechanism has no such restrictions.

3.2 the DNS

DNS service discovery is based on Cluster DNS. The DNS server monitors new services and creates DNS records for each service for domain name resolution. In a cluster, if DNS is enabled, all pods can automatically pass the name resolution service.

For example, if you have a service named “my-serivce” under the “my-ns” namespace, a DNS record named “my-service.my-ns” will be created.

  • Under the “my-ns” namespace, Pod will be able to discover this service by the name “my-service”.
  • In other namespaces, Pod must find this service by “my-serivce.my-ns”, which results in cluster IP.

Kubernetes also supports DNS SRV (SerivCE) records for ports. If the my-service.my-ns service has a TCP port with the name HTTP, the value of the HTTP port can be discovered by the name _http._tcp.my-service.my-ns. The Kubernetes DNS server is the only way to discover services of type ExternalName.

4. Publish services – Service types

For some applications (for example, a front-end), you may need to expose a Sevice that uses an external IP address. Kubernetes ServiceType allows you to specify the type of service to be used. ClusterIP is used by default. Kubernetes offers the following types of services:

  • ClusterIP(default) – The IP address that exposes the service to the cluster. This type of IP address can be used only within the cluster.
  • NodePort– Expose services on the same port of each selected Node<NodeIP>:<NodePort>Mode to access the service.
  • LoadBalancer– Create an external load balancer in the current cluster and assign a fixed external load balancer to the service.
  • ExternalNameExpose the service with an arbitrary name (specified in the specification) and return a CNAME record with the name. This type does not use proxies and is only supported on Kube-DNS V1.7.

4.1 Host Port type (NodePort)

If the Service type is “NodePort”, Kubernetes Master will expose an external port for the Service on each Node (default: 3000-32767). External networks will be able to access the service through [NodeIP]:[NodePort]. You can also specify this port through nodePort. However, the value of this port must be in the range of 30,000-32767. If you specify this port manually, note the possibility of port conflicts. This type gives developers the freedom to set up their own load balancing, or to use load balancing techniques not supported by Kubernetes.

Kind :Service apiVersion:v1 Metadata: name:my-service spec: type: NodePort # app:MyApp ports: - protocol:TCP port:80 targetPort:9376Copy the code

4.2 type of LoadBalancer

The load balancing service is a LoadBalance service based on the NodePord service. Kubernetes assigns an internal virtual IP to the LoadBalance service and exposes the NodePort. Requests coming in via LoadBalanceIP will be forwarded to NodePort.

kind:Service apiVersion:v1 metadata: name:my-service spec: selector: app:MyApp ports: - protocol: TCP port: 80 and targetPort: 9376 clusterIP: 10.0.171.239 loadBalancerIP: 78.11.24.19 type: LoadBalancer LoadBalancer status: LoadBalancer: ingress: -ip :146.148.47.155Copy the code

Traffic from the external load balancer is directed to the Pod at the back end.

4.3 the external IP

If there are externalIP addresses that can be routed to one or more clustered nodes, the Kubernetes service can be exposed to these externalIPs. Traffic imported into the cluster by ingress is routed to one of the service endpoints using an external IP address (as the destination IP). ExternalIPs is managed by a cluster administrator. All service types can be specified as externalIPs. In the following my-service, the customer port can access the my-service through the external port 80.11.12.10:80.

kind:Service apiVersion:v1 metadata: name:my-service spec: selector: app:MyApp ports: - name: HTTP protocol:TCP port:80 targetPort:9376 externalIPs: # Define the externalIP address -80.11.12.10Copy the code

Kubectl commands for the service

Kubectl commands related to services are listed in this section, and services can be created either through YAML or directly by command. Details of the command can refer to: https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands.

1) Kubectl Create Service ClusterIP

This command is used to create a ClusterIP service as shown in the following example:

$ kubectl create service clusterip my-cs --tcp=5678:8080Copy the code

2) kubectl create service externalname

This command is used to create a service of type ExternalName as shown in the following example:

$ kubectl create service externalname my-ns --external-name bar.comCopy the code

A service of type ExternalName refers to an external DNS address rather than just a POD, which will allow applications to reference services on other platforms, in other clusters, and locally.

3) kubectl create service loadbalancer

This command is used to create a LoadBalancer service as shown in the following example:

$ kubectl create service loadbalancer my-lbs --tcp=5678:8080Copy the code

4) kubectl create service nodeport

This command is used to create a NodePort type service as shown in the following example:

$ kubectl create service nodeport my-ns --tcp=5678:8080Copy the code

5) kubectl x.

This command is used to expose services for resources such as POD (Po), service (SVC), ReplicationController (RC), Deployment (deploy), replicaset (RS). Here is an example of deploying exposed services for Nginx:

$ kubectl expose deployment nginx --port=80 --target-port=8000Copy the code

The deployment or replica set is exposed as a service only if it has selectors that can be converted to service-supported selectors, that is, if the selectors contain only matchLabels components. Note that if ports are not specified through -port and the exposed resource has multiple ports, the service will use those ports. In addition, if no label is specified, the new service will use the label from the resource.

The resources

1. “Services” address: https://kubernetes.io/docs/concepts/services-networking/service/

2. The kubectl – commands the service address: https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#-em-service-em-

About the author: Ji Xiangyuan, product manager of Beijing Shenzhou Aerospace Software Technology Co., LTD. The copyright of this article belongs to the author.