什么是Service?
Service 是一个应用服务抽象,定义了 Pod 逻辑集合和访问这个 Pod 集合的策略。
Service提供了一个虚拟的 IP 地址(Cluster IP)和端口号,k8s集群里的任何服务都可以通过Cluster IP+端口的方式来访问此服务,至于访问请求最后会被转发到哪个pod,则由运行在每个node上的kube-proxy 负责。kube-proxy进程其实就是一个智能的软件负载均衡器,负责把对Service的请求转发到后端的某个pod实例上,并在内部实现服务的负载均衡与会话保持机制。
Service 实例
-
[root@k8s-master01 ~]# docker pull daocloud.io/library/tomcat:9.0.22-jdk11-openjdk-slim 9.0.22-jdk11-openjdk-slim: Pulling from library/tomcat 1ab2bdfe9778: Pull complete 7aaf9a088d61: Pull complete b9283b89acb2: Pull complete 16677eca0612: Pull complete 9ce560afbba4: Pull complete 966cea1f0cfd: Pull complete e3d3da405d9d: Pull complete Digest: sha256:5fd04ca3e001a526415339b1e1398d40bda128d2aecb7e4c74dd408052acfa24 Status: Downloaded newer image for daocloud.io/library/tomcat:9.0.22-jdk11-openjdk-slim [root@k8s-master01 ~]# docker run -d -p 18080:8080 --name mytomcat daocloud.io/library/tomcat:9.0.22-jdk11-openjdk-slim 726060e52f4ed0cebb71a5f5a714535ba7007aab19b66f0522c91a4e4bf212d9 [root@k8s-master01 ~]# docker ps -a|grep tomcat 726060e52f4e daocloud.io/library/tomcat:9.0.22-jdk11-openjdk-slim "catalina.sh run" About a minute ago Up About a minute 0.0.0.0:18080->8080/tcp mytomcat [root@k8s-master01 ~]# vi deployment-hello.yaml apiVersion: apps/v1 kind: Deployment metadata: name: frontend spec: replicas: 1 selector: matchLabels: tier: frontend template: metadata: labels: app: app-demo tier: frontend spec: containers: - name: tomcat-demo image: tomcat imagePullPolicy: IfNotPresent ports: - containerPort: 8080 resources: requests: cpu: 0.1 memory: 300Mi limits: cpu: 0.5 memory: 320Mi --- apiVersion: v1 kind: Service metadata: name: tomcat labels: name: tomcat1 spec: type: NodePort ports: - port: 80 targetPort: 8080 protocol: TCP nodePort: 31111 selector: tier: frontend
多端口为什么需要给每个端口命名呢?这就涉及 Kubernetes 的服务发现机制了。
Kubernetes 的服务发现机制
每个k8s中的 Service 都有一个唯一的 Cluster IP 及唯一的名字,名字是由我们自己定义的,k8s通过 Add-On 增值包的方式引入了 DNS 系统,把服务名作为 DNS 域名,这样程序就可以直接使用服务名来建立连接了。
端口详解
port
The port that the service is exposed on the service’s cluster ip (virsual ip). Port is the service port which is accessed by others with cluster ip.
这里的port表示:service暴露在cluster ip上的端口,:port 是提供给集群内部客户访问service的入口。
nodePort
On top of having a cluster-internal IP, expose the service on a port on each node of the cluster (the same port on each node). You'll be able to contact the service on any:nodePortaddress. So nodePort is alse the service port which can be accessed by the node ip by others with external ip.
首先,nodePort是kubernetes提供给集群外部客户访问service入口的一种方式(另一种方式是LoadBalancer),所以,nodePort 是提供给集群外部客户访问service的入口。
targetPort
The port on the pod that the service should proxy traffic to.
targetPort很好理解,targetPort是pod上的端口,从port和nodePort上到来的数据最终经过kube-proxy流入到后端pod的targetPort上进入容器。
port、nodePort总结
总的来说,port和nodePort都是service的端口,前者暴露给集群内客户访问服务,后者暴露给集群外客户访问服务。从这两个端口到来的数据都需要经过反向代理kube-proxy流入后端pod的targetPod,从而到达pod上的容器内。
NAME:定义的用户名,DNS就是使用这个域名;
TYPE:NodePort类型;
CLUSTER-IP:分配的集群内IP;
EXTERNAL-IP:针对外部访问集群的IP,NodePort的none意思就是随便一个节点的IP+port;
PORT:80是集群内的映射,31111就是node节点的端口
kube-proxy反向代理
当service有了port和nodePort之后,就可以对内/外提供服务,kube-proxy在本地node上创建的iptables规则。
Kube-Proxy 通过配置 DNAT 规则(从容器出来的访问,从本地主机出来的访问两方面),将到这个服务地址的访问映射到本地的kube-proxy端口(随机端口)。然后 Kube-Proxy 会监听在本地的对应端口,将到这个端口的访问给代理到远端真实的 pod 地址上去。
不管是通过集群内部服务入口:port还是通过集群外部服务入口:nodePort的请求都将重定向到本地kube-proxy端口(随机端口)的映射,然后将到这个kube-proxy端口的访问给代理到远端真实的 pod 地址上去。