Service

每一个pod都有自己的IP地址,但是如果Pod重新启动了的话那么它的ip很有可能也就变化了。这样就带了一个问题:比如我们有一些后端的pod的集合为集群中其他前端pod集合提供API服务,如果我们在前端的pod中把所有的这些后端的pod的地址都写死,然后用某种方式去访问其中的一个pod的服务,这样看上去可以工作的,但是如果这个pod挂掉了,然后重新启动,这个ip地址很有可能就变了,这个时候前端就极大可能访问不到后端服务了。

在没有使用Kubernetes之前,都会遇到这样的问题,不一定时Ip变化问题,比如部署一个web服务的时候,前端一般部署一个nginx作为服务的入口,然后nginx后面肯定就是挂载的这个服务的大量后端,很早之前我们可能是去手动更改nginx配置的upstream项,来动态改变提供服务的数量,到后面出现了一些服务发现工具,比如consul,zookeeper还有我们熟悉的etcd等工具,有了这些工具过后我们就可以只需要把我们的服务注册到这些服务发现中心去就可以,然后让这些工具动态的去更新nginx的配置就可以了,我们完全不用手工的操作了。


同样的,要解决我们上面遇到的问题是不是实现一个服务发现的工具也可以解决了。当我们pod被销毁或重建时,我们可以把这个pod的地址注册到这个服务发现中心去就可以了。但是这样的话我们的前端的pod结合就不能直接去连接后台的pod集合了是吧?应该连接到一个能够做服务发现的中间件上。

kubernetes集群为我们提供了这样的一个对象---service,service始终抽象的对象,它定义了一组pod的逻辑集合和一个用于访问他们的策略,其实这个概念和微服务非常类似。一个service下面包含的pod集合一般是由label Selector来决定的。

比如我们上面的例子,假如我们后端运行了3个副本,这些副本都是可以替代的,因为前端并不关心他们使用的是哪一个后端服务。尽管由于各种原因后端的pod集合会发生变化,但是前端却不需要知道这些变化,也不需要自己用一个列表记录这些后端的服务,service的这种抽象就可以帮我们达到这种解耦的目的。

三种Ip

首先弄清楚kubenetes系统中三种ip的问题:
1、node IP: node节点的IP地址
2、Pod IP:pod的IP地址
3、Cluster IP:service的IP地址
首先,Node IP是kubernetes集群中节点的物理网卡IP地址(一般为内网),所有属于这个网络服务器之间都可以直接通信,所以kubernetes集群外要想访问kubernetes集群内部的某个节点或服务,肯定要通过Node IP进行通信的(这个时候一般是通过外网IP了)

然后Pod IP是每个pod的IP地址,他是Docker Engine 根据docker0网桥的Ip地址进行分配的(我们这里使用的是flannel这种网络插件保证所有节点的pod IP不会冲突)

最后cluster ip是一个虚拟的ip,仅仅作用于kubernetes service这个对象,由kubernetes自己来进行管理和分配地址,当然我们也无法ping这个这个地址,他没有一个真正的实体对象来响应,只能结合service port来组成一个可以通信的服务。

定义Service

定义service的方式和我们前面定义的各种资源对象的方式类型,例如,假定我们有一组Pod服务,他们对外暴漏了8080端口,同时都被打上了app=myapp这样的标签,那么我们就可以像下面这样laidingyiyigeservice对象:

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

然后通过使用 kubectl apply -f 就可以创建一个名为myservice的service对象了,它会将请求代理到使用TCP端口为8080,具有标签app=myapp的pod上,这个Service会被系统分配一个cluster ip,改Service还会持续的监听selector下面的pod,会把这些pod信息更新到一个名为myservice的Endpoints对象上去,这个对象就类似于我们上面说的pod集合了。

需要注意的是,service能够将一个接收端口映射到任意的targetPort。默认情况下,targetport将被设置为与pod字段相同的值。可能更有趣的是,targetport可以是一个字符串,引用backend pod的一个端口名称。因为实际指派给该端口名称的端口号,在每个backend Pod中可能并不相同,所以对于部署和设计的service,这种方式会提供更大的灵活性。

另外service能够支持TCP和UDP协议,默认是TCP协议。

kube-proxy

在kubernetes集群中,每个Node会运行一个kube-proxy进程,负责service实现一个虚拟vip(虚拟ip就是cluster ip)的代理形式,现在的kubernetes中默认是使用iptables这种模式来代理。这个模式,kube-proxy会监视kubernetes master对service对象和Endpoints对象的添加和移除。对每个service,他会添加上iptables规则,从而捕获到该service的clusterip(虚拟ip)和端口请求,进而重定向到Service的一组backend中的某一个上面。对于每个Endpoints对象,他也会安装iptables规则,这个规则会选择一个backend pod。

默认策略是,随机选择一个backend。我们也可以实现基于客户端ip的会话亲和性。可以将service.spec.sessionAffinity的值设置为“ClienIP”(默认值为“None”。)

另外需要了解的是如果最开始选择的pod没有响应,iptables代理能够自动地重试另一个pod,所以它需要依赖readiness probes。


image.png

Service 类型

我们在定义Service的时候可以指定一个自己需要的类型的Service,如果不指定的话默认是ClusterIP类型。

我们可以使用的服务类型如下:

ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的ServiceType。

NodePort:通过每个 Node 节点上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 :,可以从集群的外部访问一个 NodePort 服务。

LoadBalancer:使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务,这个需要结合具体的云厂商进行操作。
ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如, foo.bar.example.com)。没有任何类型代理被创建,这只有 Kubernetes 1.7 或更高版本的 kube-dns 才支持。

NodePort 类型

如果设置 type 的值为 "NodePort",Kubernetes master 将从给定的配置范围内(默认:30000-32767)分配端口,每个 Node 将从该端口(每个 Node 上的同一端口)代理到 Service。该端口将通过 Service 的 spec.ports[*].nodePort 字段被指定,如果不指定的话会自动生成一个端口。

需要注意的是,Service 将能够通过 :spec.ports[].nodePort 和 spec.clusterIp:spec.ports[].port 而对外可见。

接下来我们来给大家创建一个NodePort的服务来访问我们前面的Nginx服务:(保存为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
# 创建该Service:
$ kubectl create -f service-demo.yaml

# 然后我们可以查看Service对象信息:
$ 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

我们可以看到myservice的 TYPE 类型已经变成了NodePort,后面的PORT(S)部分也多了一个 32560 的映射端口。

ExternalName

ExternalName 是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。 对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。

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

当查询主机 my-service.prod.svc.cluster.local (后面服务发现的时候我们会再深入讲解)时,集群的 DNS 服务将返回一个值为 my.database.example.com 的 CNAME 记录。 访问这个服务的工作方式与其它的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发。 如果后续决定要将数据库迁移到 Kubernetes 集群中,可以启动对应的 Pod,增加合适的 Selector 或 Endpoint,修改 Service 的 type,完全不需要修改调用的代码,这样就完全解耦了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,113评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,644评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,340评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,449评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,445评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,166评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,442评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,105评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,601评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,066评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,161评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,792评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,351评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,352评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,584评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,618评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,916评论 2 344

推荐阅读更多精彩内容