# 5. 怎样形成一个服务

## Service创建的流程

我们之前已经提过service 通过Label将一组pod实例捆绑在一起, 并对外提供服务, 这样弄出来的东西就是微服务 里面的那个服务, 具有一个稳定的 (相比较于pod经常变化的) ip地址, 我们首先描述一下全过程, 假设我们现在想要创建一个service:

**\[第一段: 创建一些pod]**

* 通过某种方式(比如deployment)发出一个创建pod的请求, 请求到达API Server
* API Server告诉Scheduler我想创建一组pod, Scheduler找到一些合适的节点,  告诉API Serve
* API-Server告诉节点上的kubelet让他起pod
* kubelet把容器创建好了以后告诉API Server, API Server把这些信息写到etcd里

**\[第二段: 创建一个Service]**

* 通过某种方式(比如kubectl apply)发出一个创建Service的请求, 请求到达API Server
* API Server根据label信息, 从etcd里找出对应的pod, 并创建endpoints对象
* API Server把endpoint对象信息写到etcd里, 并从IP池中拿出一个给这个endpoint
* 节点上的kube-proxy通过监听API Server得知了这个IP, 以及对应的pod ip们, 修改iptable (kube-proxy发现了一个服务, 因此这个过程我们也叫它服务发现)

## Service的实现原理

如果一个访问service的请求到达宿主机, 你应该怎么把它送到pod手上? 只要你能解决这个问题, 你就算实现了service. 那实现方式就五花八门了, 一个最常见的方式是通过iptables, 这种情况下service的本质就是iptable里的一条规则, 任何到访这台宿主机的, 想要访问这个服务的, 都会通过DNAT的方式将目的IP从 \[ServiceIP → PodIP]:

1. [通过 iptables 规则实现Service](https://github.com/XiaohanLiang/review/tree/cd7ce10a23aa8dcb59228d5bdc9213598b75208a/kube/iptables.md)
2. [IPVS也能实现Service](https://xiaohanliang.gitbook.io/xiaohanliang/docker/kubernetes-network/ipvs)

## 两种服务类型

**cluster ip型**: 这种就是我们之前说的仅仅在集群内部生效的service/serviceIP, 它主要是在每个node节点上使用iptables规则, 将发往 cluster ip 指定端口上的请求, 转发给后端pod

**node port型**: 这种类型的服务同时能做到被集群外部访问, nodeport 在宿主机上开一个真实的端口, 使得集群外部通过宿主机IP+端口就能访问这个服务, 实现的方式是 kube-proxy 会创建一个 iptable 规则, 使得所有访问这个端口的请求都会被直接转发到后端port上, 这种做法的确是暴露服务最快的办法, 但是问题出现在对于宿主机端口的占用上, 一旦服务多起来就会变得很难维护
