今天这篇文章里我们来讲一下Kubernetes里的Service对象。其实前面的文章《Kubernetes初体验--部署运行Go项目》里我们已经与Service有过一次短暂接触了,在那篇文章里我说用Deployment对象部署完应用后还需要向外界暴露入口才能通过HTTP访问到Kubernetes集群里的应用Pod,当时使用的是这样一条命令,其实就是创建的Service对象:

kubectl expose deployment my-go-app --type=NodePort ...

那么在这篇文章里我们就来聊一下:

  • 什么是Service对象,在Kubernetes里它是干什么用的;

  • Kubernetes里怎么发现Service

  • 如何创建和使用Service

  • nodePort,port,targetPort都是啥;

文章前面半部分理论知识多一点,稍显枯燥,后半部分会用一个实践练习给之前用Deployment部署好的应用Pod们加上Service,让外部请求能访问到Kubernetes集群里的应用,并为Pod提供负载均衡。

Kubernetes Service

和之前文章里介绍的Pod,ReplicaSet,Deployment一样,Service也是Kubernetes里的一个API对象,而 Kubernetes 之所以需要 Service,一方面是因为Pod 的 IP 不是固定的,另一方面则是因为一组Pod 实例需要Service提供复杂均衡功能。所以Service是在逻辑抽象层上定义了一组Pod,为他们提供一个统一的固定IP和访问这组Pod的负载均衡策略

下面是Service对象的常用属性设置:

  • 使用label selector,在集群中查找目标Pod;

  • ClusterIP设置Service的集群内IP让kube-proxy使用;

  • 通过prot和targetPort将访问端口与目标端口建议映射(不指定targetPort时默认值和port设置的值一样);

  • Service支持多个端口映射

  • Service支持HTTP(默认),TCP和UDP协议;

下面是一个典型的Service定义:


apiVersion: v1
kind: Service
metadata:name: hostnames
spec:selector:app: hostnamesports:- name: defaultprotocol: TCPport: 80targetPort: 9376

都有哪些类型的Service

Kubernetes中有四种Service类型:

  • ClusterIP。这是默认的Service类型,会将Service对象通过一个内部IP暴露给集群内部,这种类型的Service只能够在集群内部使用<ClusterIP>:<port>访问。

  • NodePort。会在每个宿主机节点的一个指定的固定端口上暴露Service,与此同时还会自动创建一个ClusterIP类型的Service,NodePort类型的Service会将集群外部的请求路由给ClusterIP类型的Service。你可以使用<NodeIP>:<NodePort>访问NodePort类型的Service,NodePort的端口范围为30000-32767。

  • LoadBalancer。适用于公有云上的Kubernetes服务,使用公有云服务的CloudProvider创建LoadBalancer类型的Service,同时会自动创建NodePortClusterIP类型的ServiceLoadBalancer会把请求路由到NodePortClusterIP类型的Service上。

  • ExternalName。ExternalName 类型的 Service,是在 kube-dns 里添加了一条 CNAME 记录。这个CNAME记录是在Service的spec.externalName里指定的,

以上四种类型除了ExternalNameKuberneteskube-proxy组件都会为Service提供VIP(虚拟IP),kube-proxy支持两种模式:iptablesipvs。涉及到不少知识,感兴趣的可以去极客时间上看这篇文章:Service, DNS与服务发现[1]

上面的第三和第四种类型的Service在本地试验不了,所以后面的例子我们主要通过NodePort类型的Service学习它的基本用法。

怎么发现Service

Kubernetes里的内部组件kube-dns会监控Kubernetes API,当有新的Service对象被创建出来后,kube-dns会为Service对象添加DNS A记录(从域名解析 IP 的记录)

对于 ClusterIP 模式的 Service 来说,它的 A 记录的格式是:

serviceName.namespace.svc.cluster.local,当你访问这条 A 记录的时候,它解析到的就是该 Service 的 VIP 地址。

对于指定了 clusterIP=None 的 Headless Service来说,它的A记录的格式跟上面一样,但是访问记录后返回的是Pod的IP地址集合。Pod 也会被分配对应的 DNS A 记录,格式为:podName.serviceName.namesapce.svc.cluster.local

我们会在后面的实践练习里通过nslookup印证DNS记录是否符合这里说的格式

创建和使用Service

跟其他Kubernetes里的API对象,Service也是通过YAML文件定义然后提交给Kubernetes后由ApiManager创建完成。一个典型的NodePort类型的Service的定义如下所示:

apiVersion: v1
kind: Service
metadata:name: app-service
spec:type: NodePortselector:app: go-appports:- name: httpprotocol: TCPnodePort: 30080port: 80targetPort: 3000

这里定义的Service对象会去管控我们在之前的文章《K8s上的Go服务怎么扩容、发版更新、回滚、平滑重启?教你用Deployment全搞定!》里用Deployment创建的Go应用的三个Pod副本。

➜ kubectl get pods -l app=go-app
NAME                         READY   STATUS    RESTARTS   AGE
my-go-app-864496b67b-6hm7r   1/1     Running   1          16d
my-go-app-864496b67b-d87kl   1/1     Running   1          16d
my-go-app-864496b67b-qxrsr   1/1     Running   1          16d
➜

我们用kubectl apply -f service.yaml命令把定义好的Service提交给Kubernetes

➜ kubectl apply -f service.yaml
service/app-service created

Serviceselector选中的Pod,就称为ServiceEndpoints,可以使用 kubectl get ep 命令看到它们,如下所示:

➜  kubectl get ep app-service
NAME          ENDPOINTS                                         AGE
app-service   172.17.0.6:3000,172.17.0.7:3000,172.17.0.8:3000   8m38s

需要注意的是,只有处于Running状态,且 readinessProbe 检查通过的Pod,才会出现在ServiceEndpoints 列表里。当某一个Pod出现问题时,Kubernetes 会自动把它从 Service 里摘除掉。

使用 kubectl get svc可以查看到刚才看到的Service的信息和状态。

➜ kubectl get svc
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
app-service   NodePort    10.108.26.155   <none>        80:30080/TCP   116m
kubernetes    ClusterIP   10.96.0.1       <none>        443/TCP        89d

nodePort 、port、targetPort都是啥

上面我们创建了一个NodePort类型的Service,在下面的端口映射spec.ports配置里,每个端口映射里出现了三种port:nodePort、port、targetPort。那这三种port都代表的什么意思呢?

  • port:指定在集群内部暴露Service 所使用的端口,集群内部使用<ClusterIP>:<port>访问ServiceEndPointsService选中的Pod)。

  • nodePort:指定向集群外部暴露Service 所使用的端口,从集群外部使用<NodeIp>:<NodePort>访问ServiceEndPoints。如果你不显式地声明 nodePort 字段,会随机分配可用端口来设置代理。这个端口的范围默认是 30000-32767。

  • targetPorttargetPort是后面的Pod监听的端口,容器里的应用也应该监听这个端口,Service会把请求发送到这个端口。

所以结合刚才我们创建的app-service这个Service的信息,在集群内部使用10.108.26.155:80 访问Pod里的应用。因为我们试验使用的minikube是个单节点的集群,NodeIP可以通过 minikube ip命令获得。

➜ minikube ip192.168.64.4

所以从集群外部,通过192.168.64.4:30080访问Pod里的应用。

➜ curl 192.168.64.4:30080
Hello World
Hostname: my-go-app-75d6d768ff-mlqnh%                                                                                                                    ➜ curl 192.168.64.4:30080
Hello World
Hostname: my-go-app-75d6d768ff-4x8p8%                                                                                                                    ➜  curl 192.168.64.4:30080
Hello World
Hostname: my-go-app-75d6d768ff-vt7dx%

通过多次访问,我们可以看到请求会通过Service发给不同的应用PodPod里的应用就是在原来的文章里一直使用的例子的基础上加了一行获取系统Hostname的代码:

...func index(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "Hello World")hostname, _ := os.Hostname()fmt.Fprintf(w, "Hostname: %s", hostname)
}...

最后我们进到Pod里看一下Service创建后kube-dns组件在集群里为app-service这个Service对象创建的DNS A记录,因为Service定义里指定的名字是app-service,命名空间的话因为没有指定就是默认的default命名空间,所以我们使用nslookup app-service.default.svc.cluster.local 查看一下这条DNS记录,进入到其中一个Pod里,执行上述查询的结果如下:

nslookup app-service.default.svc.cluster.localServer:         10.96.0.10
Address:        10.96.0.10:53Name:   app-service.default.svc.cluster.local
Address: 10.108.26.155

对于ServiceEndPoints 也是有DNS记录的,因为不是Headless Service,所以需要用nslookup *.app-service.default.svc.cluster.local查询DNS记录。

nslookup *.app-service.default.svc.cluster.localServer:         10.96.0.10
Address:        10.96.0.10:53Name:   *.app-service.default.svc.cluster.local
Address: 172.17.0.8
Name:   *.app-service.default.svc.cluster.local
Address: 172.17.0.6
Name:   *.app-service.default.svc.cluster.local
Address: 172.17.0.7

上面查询出来三条DNS记录,正好跟Service管控的Pod数量能够对上。

总结

今天的文章里我结合实例讲述了KubernetesService对象的基本使用方法和对象本身的一些原理,其实需要计算机网络知识掌握的好才能从更深层次了解各种模式的Service的实现原理,这方面的内容推荐极客时间里的专栏文章深入剖析Kubernetes Service[2]

到这里如果你认真看了我写的关于Kubernetes的这几篇文章,再回看我之前的文章Kubernetes入门实践--部署运行Go项目,就会觉得文章里的例子很好理解了。Kubernetes的确是学习曲线比较陡峭,我也是在边学边练。希望我的这些入门文章能帮助到想学Kubernetes的后端程序员们,大家一起进步。

看到这里了,如果喜欢我的文章可以帮我点个赞,我会每周通过技术文章分享我的所学所见,感谢你的支持。微信搜索关注公众号「网管叨bi叨」第一时间获取我的文章推送。

参考资料

[1]

Service, DNS与服务发现: https://time.geekbang.org/column/article/68636

[2]

深入剖析Kubernetes Service: https://time.geekbang.org/column/article/68636

- END -

关注公众号,获取更多精选技术原创文章

学练结合,快速掌握Kubernetes Service相关推荐

  1. 快速了解Kubernetes微服务中的通信

    by Adam Henson 亚当·汉森(Adam Henson) 快速了解Kubernetes微服务中的通信 (A quick look at communication in Kubernetes ...

  2. Kubernetes Service(溪恒)

    本文将主要分享以下四方面的内容: 为什么需要 K8s service: K8s service 用例解读: K8s service 操作演示: K8s service 架构设计. 需求来源 为什么需要 ...

  3. k8s从入门到放弃--使用kubeadm快速安装kubernetes

    kubeadm是Kubernetes官方提供的用于快速安装 Kubernetes 集群的工具,通过将集群的各个组件进行容器化安装管理,通过kubeadm的方式安装集群比二进制的方式安装要方便不少,但是 ...

  4. 高效便捷组卷功能,学练考一体化让考试更轻松

    在线考试系统是很多企业甚至企事业单位想要搭建的平台,无论是平时内部考试考核还是定期的员工培训都需要用到线上考试系统.尤其现在线上考试系统和培训功能挂钩,学练考一体化平台对于使用者来说是更加方便的. 而 ...

  5. k8s技术预研8--深入掌握Kubernetes Service

    本文内容已经基于k8s v1.8.8进行了验证测试. k8s的Service定义了一个服务的访问入口地址,前端的应用通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,来自外部的访问请求被负载 ...

  6. ② kubeadm快速部署Kubernetes集群

    文章目录 1. 安装要求 2. 目标 3. 准备环境 4. 所有节点安装Docker/kubeadm/kubelet 4.1 安装Docker(以一台为例,其他相同) 4.2 添加kubernetes ...

  7. 最新版kubeadm快速部署Kubernetes

    最新版kubeadm快速部署Kubernetes kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具 一.操作要求 在开始之前,部署kubernetes集群需要满足以下几个条 ...

  8. 基于kubeadm快速部署kubernetes K8S V1.17.4集群-无坑完整版

    基于kubeadm快速部署kubernetes K8S V1.17.4集群,并部署Dashboard Web页面,实现可视化查看Kubernetes资源 主机配置规划 服务器名称(hostname) ...

  9. 年度重磅!《2022华为开发者宝典》多元生态技术精选,学练考一站式能力进阶

    摘要:华为多元生态技术精选集,"学-练-考"一站式进阶资料包,内含华为云开发者认证考试折扣券.希望开发者们基于华为端.边.云多元技术能力协同,激发无限创新力量! 本文分享自华为云社 ...

最新文章

  1. 微软.net一些类的源码
  2. 自定义Kettle数据库插件
  3. python sanic 向别的服务器发送post请求_Sanic框架请求与响应实例分析
  4. ElasticSearch搜索引擎: 内存分析与设置
  5. C++STL- 函数对象
  6. FZU OJ:2230 翻翻棋
  7. 论:开发者信仰之“天下IT是一家“(Java .NET篇)
  8. JS与Object-C交互补充
  9. Saturn分布式调度之系统架构简介
  10. Android Button 实现透明 + 圆角按钮效果
  11. 外排序 External sorting
  12. Atitit spring 3.0 3.1 3.2 4.0 4.3 5.0 新特性
  13. CXF学习(1)——CXF框架
  14. ISO20000/ISO27001体系认证最短周期
  15. 深度学习-文档检测方案整理
  16. 微信小程序 实时音视频通话
  17. LDN双模键盘常见问题(FAQ)
  18. 基于GIS的中国历代名人人生轨迹研究
  19. 【Android】Android Studio Profiler Memery (一)
  20. 帆软思迈特软件Smartbi两家区别在哪里?

热门文章

  1. 美国百亿亿次超算要比中国晚两三年,但真实性能更恐怖
  2. 做项目时的几个感慨(持续更新...)
  3. python 判断当前系统的Python编译器类型
  4. DOM(二)使用DOM
  5. Mysql高级之主从复制
  6. IPsec   在企业网中的应用
  7. 纯MASM32打造BootClos——查看、备份系统开关机记录(0.0.0001 beta1,9KB)
  8. [转]XHTML+CSS兼容性解决方案小集
  9. docker搞个wordpress
  10. 理解 CI 和 CD 之间的区别(翻译)