Kubernetes中最重要的组件来了-Services
所谓Services就是给对应的客户端提供一个固定的访问端点,所以在客户端和服务端Pod中间添加一个中间层,这个中间层就叫Service,而Service工作严重依赖一个服务叫做CoreDNS,较新版本用的叫CoreDNS ,1.11之前的版本叫Kube-DNS。
Kubernetes中的网络方案要由第三方提供(例如flannel),部署好Kubernetes之后,会有三类网络分别叫做node network、pod network 、service network .前两种是实实在在配置在网络接口之上的,也许是Node网络接口,也许是Pod的虚拟网络接口,而service network是一种virtual IP,他没有配置在某一个软硬件上,而是一个IPtables或IPVS规则。
在每个node节点之上都会有一个组件叫做Kube-Proxy,他时时刻刻的监视着APIserver上有关service的变动信息。获取到变化之后都会转化为node之上的IPtables规则。servics公有三种工作模型,分别叫做 userspace 1.1- 、iptables 1.10- 、ipvs 1.11+。
较新版本使用的模型叫做ipvs ,而userspace由于效率较低而不再被使用。下面是ipvs 的工作模型图。

ipvs工作原理:
来自内部的请求(client pod)直接发送给内核空间的IPtables,而后由iptables直接调度至各个Pod,如果service的标签选择器适用的Pod多一个,此时这种状态会立即反映至apiserver,由apiserver存贮至etcd,这种变化会立即被node之上的kube-Proxy观察到并立即转为service的ipvs规则。这一切变动都是立即同步的。
怎么使用清单创建Service:
kubectl explain svc

可以看到Service依然是由这四项组成 :apiVersion、kind、metadata、spec
spec中比较重要的字段有 :
# port : 打算用哪个端口与后端的容器建立关联关系
# selector : 标签选择器,选择要关联的pod
# clusterIP : 如果不指定 service的IP是动态分配的,如果希望固定IP则需要指定这一参数
# type :
- ExternalName:把集群外部的服务引入到集群内部,直接使用
- ClusterIP:默认类型,仅适用于内部通讯
- NodePort:外部通讯
- LoadBalancer:适用在云环境中。
type为clusterIP清单示例:
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: default
spec:
selector:
app: redis
role: logstor
clusterIP: 10.97.97.97
# 此处port有三种port 1、service Port 2、node Port (类型为NodePort的时候才会用到)3、container Port
ports:
- port: 6379
targetPort: 6379
type: ClusterIP
创建 kubectl apply -f redis-svc.yaml
查看后端关联pod kubectl describe svc redis

创建之后service会直接在dns解析记录中添加资源记录,而后便可直接使用服务名访问。
type为NodePort的资源清单示例
aipVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
selector:
app: myapp
release: cannary
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080
clusterIP: 10.99.99.99
创建好之后在集群外部的主机随机访问一个端点即可实现负载均衡

在service实现调度的时候还支持一个字段叫做
sessinoAffinity
这是一个非常有用的字段,默认是none 如果定义成ClientIP则表示,把来自同一个客户端的请求调度至同一个Node之上。下面看效果
我们可以用打补丁的方式为之前创建好的svc添加这一字段
kubectl patch svc myapp -p '{"spec:"{"sessionAffinity":"ClientIP"}}'
改完之后,之前的随机调度变成了只调度至同一个Node。
立即生效~非常高大上
还有一种叫做 headless service 即没有clusterIP,访问服务名直接解析至pod IP,抽掉了中间serviceIP层,具体设置方法:clusterIP :None
解析效果如下:
