Introduction to Kubernetes Services

Service

We have learned Podthe basic usage before, and we also learned Podthat life is limited, and there will be no resurrection after death. What we learn later RCcan Deploymentbe used to dynamically create and destroy Pod. Although each Podhas its own IPaddress, it is very likely that his will change if Podit is restarted . IPThis will bring about a problem: for example, we have some back-end collections that provide services Podfor other front-end collections in the cluster . If we hardcode the addresses of all these back-ends in the front-end , and then go to a certain way To access one of the services, it seems to work, right? But if it hangs up and then restarts, the address is very likely to change. At this time, the front-end may not be able to access the back-end services.PodAPIPodPodPodPodIP

How to solve such a problem? Before using it Kubernetes, I believe that many people may have encountered such a problem, and it is not necessarily IPa problem of change. For example, when we deploy a WEBservice, the front end usually deploys an Nginxentry as a service, and then Nginxit must be mounted later. There are a lot of backends for this service. A long time ago, we may manually change the options Nginxin the configuration to dynamically change the number of services provided. Later , some tools upstreamappeared , such as , and tools we are familiar with . With these After the tools are used, we can just register our services to these service discovery centers, and then let these tools dynamically update the configuration. We don't need to do manual operations at all, isn't it very convenient?服务发现ConsulZooKeeperetcdNginx
insert image description here

Similarly, to solve the problems we encountered above, is it possible to implement a service discovery tool? That's right, when we Podare destroyed or newly created, we can register this Podaddress to the service discovery center, but in this case, our front-end Podcombination can't directly connect to the background Podcollection, right? It should be connected to A middleware that can do service discovery, right?

That's right, Kubernetesthe cluster provides us with such an object - Servicean Serviceabstract object that defines a set Podof logical collections and a strategy for accessing them. In fact, this concept is very similar to microservices. A set of Serivcecontained below Podis generally determined Label Selectorby .

For example, in our example above, if we run 3 copies on the backend, these copies are all replaceable, because the frontend does not care which backend service they use. Although the back-end Podcollection will send changes due to various reasons, the front-end does not need to know these changes, nor does it need to use a list to record these back-end services. ServiceThis abstraction can help us achieve this decoupling. .

Three IPs

Before continuing to study Service, we need to figure out Kubernetesthe issue of the three IPs in the system, because people often get confused.

  • Node IP: the address Nodeof the nodeIP
  • Pod IP: PodThe IP address of the pod
  • Cluster IP: the address ServiceofIP

First of all, Node IPit is Kubernetesthe physical network card address of the nodes in the cluster IP(usually the intranet). All servers belonging to this network can communicate directly with each other. Therefore, if you Kuberneteswant to access Kubernetesa node or service inside the cluster outside the cluster, you must Node IPcommunicate through (At this time, it is usually through the external network IP)

Then Pod IPthere is each Podaddress IP, which is allocated Docker Engineaccording to the address segment docker0of the bridge (we use this kind of network plug-in here to ensure that all nodes will not conflict)IPflannelPod IP

Finally Cluster IP, it is a virtual one IP, which only acts on Kubernetes Servicethis object and Kubernetesmanages and assigns addresses by itself. Of course, we can’t use pingthis address. It doesn’t have a real entity object to respond to. It can only be combined Service Portto form a service that can communicate.

Define Service

The definition Servicemethod and the method types of the various resource objects we defined earlier, for example, suppose we have a group of Podservices that expose port 8080 to the outside world and are all labeled as app=myappsuch, then we can define a service as follows Serviceobject:

apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  selector:
    app: myapp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
    name: myapp-http

Then kubectl create -f myservice.yamlyou can create an object named myserviceby using Serviceit, which will proxy the request to the one with the label using TCP port 8080. This will be assigned by the system app=myappas we mentioned above , and it will continue to listen to the following , This information will be updated to an object named , which is similar to the collection we mentioned above .PodServiceCluster IPServiceselectorPodPodmyserviceEndpointsPod

Note that it is Servicepossible to map a receive port to any targetPort. By default, targetPortwill be set to portthe same value as the field. Perhaps more interestingly, targetPort can be a string referencing the name of a port on the backend Pod. Because the port number actually assigned to the port name may not be the same in each backend Pod, this method will provide greater flexibility for deploying and designing the Service.

In addition, Serviceit can support TCP and UDP protocols, and the default is TCP protocol.

be a proxy

As we mentioned earlier, in Kubernetesthe cluster, each Nodewill run a kube-proxyprocess, which is responsible for Serviceimplementing a proxy form of VIP (virtual IP, which is what we said above clusterIP), which is now Kubernetesused by default iptablesin this mode to proxy. This mode kube-proxymonitors Kubernetes masterthe addition and removal of Service objects and Endpoints objects. For each Service, it will add iptables rules to capture the request to the clusterIP (virtual IP) and port of the Service, and then redirect the request to one of the set of backends of the Service. For each Endpoints object, it also installs iptables rules that select a backend Pod.

The default strategy is to randomly select a backend. We can also implement session affinity based on client IP, which can be service.spec.sessionAffinityset to "ClientIP" (the default value is "None").

Another thing to understand is that the iptables proxy can automatically retry another Pod if the initially selected Pod does not respond, so it needs to rely on readiness probes.

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-sD0QIvZU-1678238488098)(./images/services-iptables-overview.svg)]

Service type

We Servicecan specify a type we need when we define it Service. If we don't specify it, it defaults to ClusterIPthe type.

The types of services we can use are as follows:

  • ClusterIP: The service is exposed through the internal IP of the cluster. If this value is selected, the service can only be accessed within the cluster. This is also the default ServiceType.

  • NodePort: Expose services through IP and static port (NodePort) on each Node node. The NodePort service will be routed to the ClusterIP service, which will be created automatically. A NodePort service can be accessed from outside the cluster by requesting:

  • LoadBalancer: Use the cloud provider's load balancer to expose services to the outside. External load balancers can be routed to NodePort services and ClusterIP services, which need to be operated in conjunction with specific cloud vendors.

  • ExternalName: By returning the CNAME and its value, the service can be mapped to the contents of the externalName field (for example, foo.bar.example.com). No proxy of any kind is created, this is only supported by kube-dns for Kubernetes 1.7 or higher.

NodePort type

If you set the value of type to "NodePort", the Kubernetes master will allocate a port from the given configuration range (default: 30000-32767), and each Node will proxy to the Service from this port (the same port on each Node). The port will be specified through the spec.ports[*].nodePort field of Service, if not specified, a port will be generated automatically.

It should be noted that Service will be visible externally through :spec.ports[ ].nodePort and spec.clusterIp:spec.ports[ ].port.

Next, let's create a NodePortservice for everyone to access our previous Nginxservice: (save as service-demo.yaml)

apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  selector:
    app: myapp
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    name: myapp-http

Create this Service:

$ kubectl create -f service-demo.yaml

Then we can view Servicethe object information:

$ kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        27d
myservice    NodePort    10.104.57.198   <none>        80:32560/TCP   14h

We can see myservicethat the TYPE type has changed , and there is an additional mapped port of 32560 in the NodePortlatter part.PORT(S)

ExternalName

ExternalNameIt is a special case of Service, it has no selector, nor does it define any ports and Endpoints. For services running outside the cluster, it provides services by returning the alias of the external service.

kind: Service
apiVersion: v1
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

When querying the host my-service.prod.svc.cluster.local (we will explain it in depth later in service discovery), the DNS service of the cluster will return a CNAME record whose value is my.database.example.com. Accessing this service works the same as the others, the only difference is that the redirection happens at the DNS layer and there is no proxying or forwarding. If you later decide to migrate the database to the Kubernetes cluster, you can start the corresponding Pod, add a suitable Selector or Endpoint, and modify the type of Service without modifying the calling code at all, so that it is completely decoupled.


Guess you like

Origin blog.csdn.net/u010674953/article/details/129396464