学练结合,快速掌握Kubernetes Service
今天这篇文章里我们来讲一下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,同时会自动创建NodePort和ClusterIP类型的Service,LoadBalancer会把请求路由到NodePort和ClusterIP类型的Service上。ExternalName。ExternalName 类型的 Service,是在 kube-dns 里添加了一条 CNAME 记录。这个CNAME记录是在Service的spec.externalName里指定的,
以上四种类型除了ExternalName
,Kubernetes
的kube-proxy
组件都会为Service
提供VIP(虚拟IP),kube-proxy
支持两种模式:iptables和ipvs。涉及到不少知识,感兴趣的可以去极客时间上看这篇文章: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
被Service
的selector
选中的Pod
,就称为Service
的 Endpoints
,可以使用 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
,才会出现在Service
的 Endpoints
列表里。当某一个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>
访问Service
的EndPoints
(Service
选中的Pod)。nodePort:指定向集群外部暴露
Service
所使用的端口,从集群外部使用<NodeIp>:<NodePort>
访问Service
的EndPoints
。如果你不显式地声明nodePort
字段,会随机分配可用端口来设置代理。这个端口的范围默认是 30000-32767。targetPort:
targetPort
是后面的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
发给不同的应用Pod
。Pod
里的应用就是在原来的文章里一直使用的例子的基础上加了一行获取系统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
对于Service
的EndPoints
也是有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
数量能够对上。
总结
今天的文章里我结合实例讲述了Kubernetes
里Service
对象的基本使用方法和对象本身的一些原理,其实需要计算机网络知识掌握的好才能从更深层次了解各种模式的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相关推荐
- 快速了解Kubernetes微服务中的通信
by Adam Henson 亚当·汉森(Adam Henson) 快速了解Kubernetes微服务中的通信 (A quick look at communication in Kubernetes ...
- Kubernetes Service(溪恒)
本文将主要分享以下四方面的内容: 为什么需要 K8s service: K8s service 用例解读: K8s service 操作演示: K8s service 架构设计. 需求来源 为什么需要 ...
- k8s从入门到放弃--使用kubeadm快速安装kubernetes
kubeadm是Kubernetes官方提供的用于快速安装 Kubernetes 集群的工具,通过将集群的各个组件进行容器化安装管理,通过kubeadm的方式安装集群比二进制的方式安装要方便不少,但是 ...
- 高效便捷组卷功能,学练考一体化让考试更轻松
在线考试系统是很多企业甚至企事业单位想要搭建的平台,无论是平时内部考试考核还是定期的员工培训都需要用到线上考试系统.尤其现在线上考试系统和培训功能挂钩,学练考一体化平台对于使用者来说是更加方便的. 而 ...
- k8s技术预研8--深入掌握Kubernetes Service
本文内容已经基于k8s v1.8.8进行了验证测试. k8s的Service定义了一个服务的访问入口地址,前端的应用通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,来自外部的访问请求被负载 ...
- ② kubeadm快速部署Kubernetes集群
文章目录 1. 安装要求 2. 目标 3. 准备环境 4. 所有节点安装Docker/kubeadm/kubelet 4.1 安装Docker(以一台为例,其他相同) 4.2 添加kubernetes ...
- 最新版kubeadm快速部署Kubernetes
最新版kubeadm快速部署Kubernetes kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具 一.操作要求 在开始之前,部署kubernetes集群需要满足以下几个条 ...
- 基于kubeadm快速部署kubernetes K8S V1.17.4集群-无坑完整版
基于kubeadm快速部署kubernetes K8S V1.17.4集群,并部署Dashboard Web页面,实现可视化查看Kubernetes资源 主机配置规划 服务器名称(hostname) ...
- 年度重磅!《2022华为开发者宝典》多元生态技术精选,学练考一站式能力进阶
摘要:华为多元生态技术精选集,"学-练-考"一站式进阶资料包,内含华为云开发者认证考试折扣券.希望开发者们基于华为端.边.云多元技术能力协同,激发无限创新力量! 本文分享自华为云社 ...
最新文章
- 微软.net一些类的源码
- 自定义Kettle数据库插件
- python sanic 向别的服务器发送post请求_Sanic框架请求与响应实例分析
- ElasticSearch搜索引擎: 内存分析与设置
- C++STL- 函数对象
- FZU OJ:2230 翻翻棋
- 论:开发者信仰之“天下IT是一家“(Java .NET篇)
- JS与Object-C交互补充
- Saturn分布式调度之系统架构简介
- Android Button 实现透明 + 圆角按钮效果
- 外排序 External sorting
- Atitit spring 3.0 3.1 3.2 4.0 4.3 5.0 新特性
- CXF学习(1)——CXF框架
- ISO20000/ISO27001体系认证最短周期
- 深度学习-文档检测方案整理
- 微信小程序 实时音视频通话
- LDN双模键盘常见问题(FAQ)
- 基于GIS的中国历代名人人生轨迹研究
- 【Android】Android Studio Profiler Memery (一)
- 帆软思迈特软件Smartbi两家区别在哪里?