Overview(概述)

Kubernetes Pod是平凡的,它门会被创建,也会死掉(生老病死),并且他们是不可复活的。 ReplicationControllers动态的创建和销毁Pods(比如规模扩大或者缩小,或者执行动态更新)。每个pod都由自己的ip,这些IP也随着时间的变化也不能持续依赖。这样就引发了一个问题:如果一些Pods(让我们叫它作后台,后端)提供了一些功能供其它的Pod使用(让我们叫作前台),在kubernete集群中是如何实现让这些前台能够持续的追踪到这些后台的?

答案是:Service

Kubernete Service 是一个定义了一组Pod的策略的抽象,我们也有时候叫做宏观服务。这些被服务标记的Pod都是(一般)通过label Selector决定的(下面我们会讲到我们为什么需要一个没有label selector的服务)

举个例子,我们假设后台是一个图形处理的后台,并且由3个副本。这些副本是可以相互替代的,并且前台并需要关心使用的哪一个后台Pod,当这个承载前台请求的pod发生变化时,前台并不需要直到这些变化,或者追踪后台的这些副本,服务是这些去耦

对于Kubernete原生的应用,Kubernete提供了一个简单的Endpoints API,这个Endpoints api的作用就是当一个服务中的pod发生变化时,Endpoints API随之变化,对于哪些不是原生的程序,Kubernetes提供了一个基于虚拟IP的网桥的服务,这个服务会将请求转发到对应的后台pod

Defining a service(定义一个服务)

一个Kubernete服务是一个最小的对象,类似pod,和其它的终端对象一样,我们可以朝paiserver发送请求来创建一个新的实例,比如,假设你拥有一些Pod,每个pod都开放了9376端口,并且均带有一个标签app=MyApp

{

“kind”: “Service”,

“apiVersion”: “v1”,

“metadata”: {

“name”: “my-service”

},

“spec”: {

“selector”: {

“app”: “MyApp”

},

“ports”: [

{

“protocol”: “TCP”,

“port”: 80,

“targetPort”: 9376

}

]

}

}

这段代码会创建一个新的服务对象,名称为:my-service,并且会连接目标端口9376,并且带有label app=MyApp的pod,这个服务会被分配一个ip地址,这个ip是给服务代理使用的(下面我们会看到),服务的选择器会持续的评估,并且结果会被发送到一个Endpoints 对象,这个Endpoints的对象的名字也叫“my-service”.

服务可以将一个“入端口”转发到任何“目标端口”,默认情况下targetPort的值会和port的值相同,更有趣的是,targetPort可以是字符串,可以指定到一个name,这个name是pod的一个端口。并且实际指派给这个name的端口可以是不同在不同的后台pod中,这样让我们能更加灵活的部署我们的服务,比如;我们可以在下一个更新版本中修改后台pod暴露的端口而不会影响客户的使用(更新过程不会打断)

服务支持tcp和UDP,但是默认的是TCP

Services without selectors(没有选择器的服务)

服务总体上抽象了对Pod的访问,但是服务也抽象了其它的内容,比如:

1:比如你希望有一个额外的数据库云在生产环境中,但是在测试的时候,我们希望使用自己的数据库

2:我们希望将服务指向其它的服务或者其它命名空间或者其它的云平台上的服务

3:我们正在向kubernete迁移,并且我们后台并没有在Kubernete中

如上的情况下,我们可以定义一个服务没有选择器

{

“kind”: “Service”,

“apiVersion”: “v1″,

“metadata”: {

“name”: “my-service”

},

“spec”: {

“ports”: [

{

“protocol”: “TCP”,

“port”: 80,

“targetPort”: 9376

}

]

}

}

因为没有选择器,所以相应的Endpoints对象就不会被创建,但是我们手动把我们的服务和Endpoints对应起来

{

“kind”: “Endpoints”,

“apiVersion”: “v1″,

“metadata”: {

“name”: “my-service”

},

“subsets”: [

{

“addresses”: [

{ “IP”: “1.2.3.4” }

],

“ports”: [

{ “port”: 80 }

]

}

]

}

这样的话,这个服务虽然没有selector,但是却可以正常工作,所有的请求都会被转发到1.2.3.4:80

Virtual IPs and service proxies(虚拟IP和服务代理)

每一个节点上都运行了一个kube-proxy,这个应用监控着Kubermaster增加和删除服务,对于每一个服务,kube-proxy会随机开启一个本机端口,任何发向这个端口的请求都会被转发到一个后台的Pod当中,而如何选择是哪一个后台的pod的是基于SessionAffinity进行的分配。kube-proxy会增加iptables rules来实现捕捉这个服务的Ip和端口来并重定向到前面提到的端口。

最终的结果就是所有的对于这个服务的请求都会被转发到后台的Pod中,这一过程用户根本察觉不到

默认的,后台的选择是随机的,基于用户session机制的策略可以通过修改service.spec.sessionAffinity 的值从NONE到ClientIP

Multi-Port Services(多端口服务)

可能很多服务需要开发不止一个端口,为了满足这样的情况,Kubernetes允许在定义时候指定多个端口,当我们使用多个端口的时候,我们需要指定所有端口的名称,这样endpoints才能清楚,例如

{

“kind”: “Service”,

“apiVersion”: “v1”,

“metadata”: {

“name”: “my-service”

},

“spec”: {

“selector”: {

“app”: “MyApp”

},

“ports”: [

{

“name”: “http”,

“protocol”: “TCP”,

“port”: 80,

“targetPort”: 9376

},

{

“name”: “https”,

“protocol”: “TCP”,

“port”: 443,

“targetPort”: 9377

}

]

}

}

选择自己的IP地址

我们可以在创建服务的时候指定IP地址,将spec.clusterIP的值设定为我们想要的IP地址即可。例如,我们已经有一个DNS域我们希望用来替换,或者遗留系统只能对指定IP提供服务,并且这些都非常难修改,用户选择的IP地址必须是一个有效的IP地址,并且要在API server分配的IP范围内,如果这个IP地址是不可用的,apiserver会返回422http错误代码来告知是IP地址不可用

为什么不使用循环的DNS

一个问题持续的被提出来,这个问题就是我们为什么不使用标准的循环DNS而使用虚拟IP,我们主要有如下几个原因

1:DNS不遵循TTL查询和缓存name查询的问题由来已久(这个还真不知道,就是DNS更新的问题估计)

2:许多的应用的DNS查询查询一次后就缓存起来

3:即使如上亮点被解决了,但是不停的进行DNS进行查询,大量的请求也是很难被管理的

我们希望阻止用户使用这些可能会“伤害”他们的事情,但是如果足够多的人要求这么作,那么我们将对此提供支持,来作为一个可选项.

Discovering services(服务的发现)

Kubernetes 支持两种方式的来发现服务 ,环境变量和 DNS

环境变量

当一个Pod在一个node上运行时,kubelet 会针对运行的服务增加一系列的环境变量,它支持Docker links compatible 和普通环境变量

举例子来说:

redis-master服务暴露了 TCP 6379端口,并且被分配了10.0.0.11 IP地址

那么我们就会有如下的环境变量

REDIS_MASTER_SERVICE_HOST=10.0.0.11

REDIS_MASTER_SERVICE_PORT=6379

REDIS_MASTER_PORT=tcp://10.0.0.11:6379

REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379

REDIS_MASTER_PORT_6379_TCP_PROTO=tcp

REDIS_MASTER_PORT_6379_TCP_PORT=6379

REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11

这样的话,对系统有一个要求:所有的想要被POD访问的服务,必须在POD创建之前创建,否则这个环境变量不会被填充,使用DNS则没有这个问题

DNS

一个可选择的云平台插件就是DNS,DNS 服务器监控着API SERVER ,当有服务被创建的时候,DNS 服务器会为之创建相应的记录,如果DNS这个服务被添加了,那么Pod应该是可以自动解析服务的。

举个例子来说:如果我们在my-ns命名空间下有一个服务叫做“my-service”,这个时候DNS就会创建一个my-service.my-ns的记录,所有my-ns命名空间下的Pod,都可以通过域名my-service查询找到对应的ip地址,不同命名空间下的Pod在查找是必须使用my-sesrvice.my-ns才可以。

Kubernete 同样支持端口的解析,如果my-service有一个提供http的TCP主持的端口,那么我们可以通过查询“_http._tcp.my-service.my-ns”来查询这个端口

Headless services

有时候我们可能不需要一个固定的IP和分发,这个时候我们只需要将spec.clusterIP的值设置为none就可以了

对于这样的服务来说,集群IP没有分配,这个时候当你查询服务的名称的时候,DNS会返回多个A记录,这些记录都是指向后端Pod的。Kube 代理不会处理这个服务,在服务的前端也没有负载均衡器。但是endpoints controller还是会创建Endpoints

(好吧,这个好处貌似我还理解好)

This option allows developers to reduce coupling to the Kubernetes system, if they desire, but leaves them freedom to do discovery in their own way. Applications can still use a self-registration pattern and adapters for other discovery systems could easily be built upon this API.

External services(外部服务)

对于我们的应用程序来说,我们可能有一部分是放在Kubernete外部的(比如我们有单独的物理机来承担数据库的角色),Kubernetes支持两种方式:NodePorts,LoadBalancers

每一个服务都会有一个字段定义了该服务如何被调用(发现),这个字段的值可以为:

ClusterIP:使用一个集群固定IP,这个是默认选项

NodePort:使用一个集群固定IP,但是额外在每个POD上均暴露这个服务,端口

LoadBalancer:使用集群固定IP,和NODEPord,额外还会申请申请一个负载均衡器来转发到服务(load balancer )

注意:NodePort 支持TCP和UDN,但是LoadBalancers在1.0版本只支持TCP

Type NodePort

如果你选择了“NodePort”,那么 Kubernetes master 会分配一个区域范围内,(默认是30000-32767),并且,每一个node,都会代理(proxy)这个端口到你的服务中,我们可以在spec.ports[*].nodePort 找到具体的值

如果我们向指定一个端口,我们可以直接写在nodePort上,系统就会给你指派指定端口,但是这个值必须是指定范围内的。

这样的话就能够让开发者搭配自己的负载均衡器,去撘建一个kubernete不是完全支持的系统,又或者是直接暴露一个node的ip地址

Type LoadBalancer

在支持额外的负载均衡器的的平台上,将值设置为LoadBalancer会提供一个负载均衡器给你的服务,负载均衡器的创建其实是异步的。下面的例子

{

“kind”: “Service”,

“apiVersion”: “v1″,

“metadata”: {

“name”: “my-service”

},

“spec”: {

“selector”: {

“app”: “MyApp”

},

“ports”: [

{

“protocol”: “TCP”,

“port”: 80,

“targetPort”: 9376,

“nodePort”: 30061

}

],

“clusterIP”: “10.0.171.239”,

“type”: “LoadBalancer”

},

“status”: {

“loadBalancer”: {

“ingress”: [

{

“ip”: “146.148.47.155”

}

]

}

}

}

所有服务的请求均会直接到到Pod,具体是如何工作的是由平台决定的

缺点

我们希望使用IPTABLES和用户命名空间来代理虚拟IP能在中小型规模的平台上正常运行,但是可能出现问题在比较大的平台上当应对成千上万的服务的时候。

这个时候,使用kube-proxy来封装服务的请求,这使得这些变成可能

LoadBalancers 只支持TCP,不支持UDP

Type 的值是设定好的,不同的值代表不同的功能,并不是所有的平台都需要的,但是是所有API需要的

Future work

在将来,我们预想proxy的策略能够更加细致,不再是单纯的转发,比如master-elected or sharded,我们预想将来服务会拥有真正的负载均衡器,到时候虚拟IP直接转发到负载均衡器

将来有倾向与将所的工作均通过iptables来进行,从而小从用户命名空间代理,这样的话会有更好的性能和消除一些原地值IP的问题,尽管这样的会减少一些灵活性.

更多讨论:QQ交流群  513817976  入群暗号: kubernetes.org.cn

更多请参考:http://kubernetes.io/docs/user-guide/services/#future-work

service mysql k8s_Kubernetes(k8s)中文文档 名词解释 Services_Kubernetes中文社区相关推荐

  1. k8s mysql volume_Kubernetes(k8s)中文文档 名词解释 Volumes_Kubernetes中文社区

    容器中的磁盘的生命周期是短暂的,这就带来了一系列的问题,第一,当一个容器损坏之后,kubelet 会重启这个容器,但是文件会丢失-这个容器会是一个全新的状态,第二,当很多容器在同一Pod中运行的时候, ...

  2. config kubectl_Kubernetes(k8s)中文文档 kubectl config set-context_Kubernetes中文社区

    译者:hurf 在kubeconfig配置文件中设置一个环境项. 摘要 在kubeconfig配置文件中设置一个环境项. 如果指定了一个已存在的名字,将合并新字段并覆盖旧字段. kubectl con ...

  3. CDH中文文档下载,Cloudera中文手册,CM中文文档

    CDH中文文档下载 链接:https://pan.baidu.com/s/1G-8WCafpPZ3p7ZDeXLcgug  提取码:ubxz

  4. service mysql k8s_Kubernetes/K8S基础使用方法总结【五】——Service

    Service有userspace.iptables.ipvs三种工作模式,可在配置文件/etc/sysconfig/kubelet中添加配置参数KUBE_PROXY_MODE=ipvs来改变kube ...

  5. python 停止工作 scapy_常见问题 - Scapy 中文文档_教程_Python开发社区

    常见问题 我的 TCP 连接被 Scapy 或者是我的内核重置了 内核不知道 Scapy 在他背后做什么. 如果 Scapy 发送 SYN,目标回复 SYN-ACK,并且你的内核看到它,它将回复 RS ...

  6. imx226_IMX226_中文文档_电路图_IMX226_中文资料_芯片数据手册

    品牌:Rohm Semiconductor 描述:TRANS 2NPN 20V 0.3A 6SMT 详细描述:Bipolar (BJT) Transistor Array 2 NPN (Dual) 2 ...

  7. Spring系列中文文档

    Spring系列中文文档 Spring源码 中文手册 Spring Core上 Spring Core下 Spring容器扩展点(Container Extension Points) Factory ...

  8. 中文文档规范化,zh.md 来帮你!丨TiDB Hackathon 2020 优秀项目分享

    近日,由 TiDB 社区主办,专属于全球开发者与技术爱好者的顶级挑战赛事--TiDB Hackathon 2020 比赛圆满落幕.今年是 TiDB Hackathon 第四次举办,参赛队伍规模创历届之 ...

  9. Spring Cloud Dalston.RELEASE中文文档

    Spring Cloud Dalston.RELEASE中文文档 Spring Cloud 目录 特性 云原生应用程序 Spring Cloud上下文:应用程序上下文服务 引导应用程序上下文 应用程序 ...

最新文章

  1. ACM提交,C++,G++,C,GCC的区别
  2. 完美解决:"library not found for - "
  3. 通过TA binary查看TA的uuid和stack
  4. 机械错题集锦2017-12-21
  5. Cannot access repo1 (http://repo1.maven.org/maven2) in offline mode and the
  6. leetcode55. 跳跃游戏
  7. 2003 64位系统 IIS6 32位模式运行
  8. 12句让人心疼的话 哪一句说到你心里了?
  9. html自动生成工具_「写论文神器」一个好用的论文自动生成工具,内含30w 文献数据...
  10. java万年历JFrame_Java Gui万年历
  11. 黑客X档案的《黑客免杀入门》
  12. 计算机芯片级维修包括哪些,电脑芯片级维修教程
  13. 【数据库学习】数据库平台:Postgres(PG)与PostgreSQL
  14. html+js实现分页功能
  15. IntelliJ IDEA如何自动生成serialVersionUID?
  16. 电脑屏幕“重影”解决方法
  17. Android Native 崩溃日志收集
  18. Kali [CobaltStrike]CS神器
  19. jekyll php,使用Jekyll在Github上搭建个人博客(文章分类索引)
  20. Python爬虫实战+数据分析+数据可视化(豆瓣八佰电影影评)

热门文章

  1. MTK:MVRAM操作
  2. 移动机器人综合性能对比分析
  3. 暗影之枪显示连接服务器失败,暗影之枪传奇进不去怎么办?游戏更新进不去问题详解[多图]...
  4. 高德地图 map.setcenter 动画_娄底三维动画制作公司价格2020行情-立艺数字
  5. 找出数组的最大公约数
  6. THREEJS - 模型的裁切消隐
  7. python测试udp端口_zabbix上使用外部检查的方式监测公网tcp/udp端口开放情况
  8. put与putIfAbsent区别
  9. postgresql9.5.9相关的日志文件介绍
  10. Linux命令解释之awk