📣 大家好,我是Zhan,一名个人练习时长一年半的大二后台练习生🏀
📣 这篇文章是学习 Kubernetes 的第五篇学习笔记📙
📣 如果有不对的地方,欢迎各位指正🙏🏼
📣 与君同舟渡,达岸各自归🌊
🔔 引语
在上篇文章【云原生 • Kubernetes】(四) k8s 原来不是直接创建 Pod!! - 掘金 (juejin.cn)中,我们讲解了 Kubernetes 中 四种Controller 的使用,了解到了,是 Controller 让 Pod 有了 运维的能力 以及更好的 管理,不过在文章末尾处我也提到了:Pod 无法提供网络服务、以及实现负载均衡,因此为了让 Pod 提供对外的网络访问,本文将会讲解 Service:
- 什么是 Service 以及 Service 的作用与特性
- Service 与 Pod 之间又是什么样的关系
- 如何使用和配置 Service
- Service 有哪些类型
1️⃣ 什么是 Service
1.1 定义
官网给出的定义是:Service 是 将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法。
通俗来讲,Service 是为 Pod 提供网络服务的一种方式
1.2 为什么需要 Service
在上文中我们也提到了,仅仅靠控制器无法提供网络服务,如果一组 Pod(例如 MySQL) 为集群内的其他的 Pod(Java) 提供服务,那么 Java 如何找到 MySQL 的 IP 地址,如果 MySQL 具有多个副本,又当如何呢?
有点类似于 SpringCloud 中的 注册中心,front pod 无需关心它们调用了哪个 backend pod,如果 backend pod 发生了何种变化,也无需 front pod 知情,Service 定义的抽象能够做到这种解耦。
1.3 Service 与 Ingess 的区别
Service和Ingress是Kubernetes中用于管理和公开应用程序的两个重要概念,它们有着不同的作用和功能。
Service是 Kubernetes 中的一种抽象,Service 允许应用程序内部的各个组件(Pod)能够通过Service名称和端口号来相互通信,而不需要直接暴露Pod的IP地址。Ingress是 Kubernetes 中的一种资源对象,Ingress可以将外部的HTTP请求路由到 Kubernetes 集群内部的Service,从而实现从集群外部访问应用程序的能力- 简而言之:
Service用于在Kubernetes 内部 管理和访问应用程序的不同组件Ingress用于从集群 外部 公开应用程序的路由和访问方式
- 通常情况下,Ingress会使用一个反向代理来处理外部的请求,并将其转发到相应的Service上。
2️⃣ 特性
- Pod 通过 Label 与 Service 进行关联。这与 Controller 中的 Selector 一样,通过标签进行筛选。
- Service 生命周期与 Pod 无关,不会因为 Pod 的重新创建而改变 IP。无论 Service 关联的 Pod 如何增缩,它的 IP 都不会变化。
- Service 提供了一种逻辑上的稳定网络端点,它可以将 请求负载均衡 到后端的多个Pod实例上,从而实现应用程序的高可用性和扩展性。
- 可以对集群外部提供访问端口。只是方便测试,在上面我们说的是通常使用情况,一般我们不会这么去用。
- 集群内部可以通过服务名字进行访问,不需要直接暴露Pod的IP地址。
3️⃣ 使用 Service
3.1 配置文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 3
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
restartPolicy: Always
selector:
matchLabels:
app: nginx
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
# 通过标签进行筛选
selector:
app: nginx
ports:
# Service 的端口
- port: 80
# Pod 的端口,也就是 Container 中应用服务的端口
targetPort: 80
# 暴露外部服务的端口,如果不写会自动分配,固定在 30000-32767
nodePort: 30080
# 通信协议:TCP / UDP
protocol: TCP
# Service 的类型,NodePort 代表公开NGINX应用程序
type: NodePort
3.2 配置解释
在spec部分:
selector指定了Service将路由到具有标签app: nginx的Pod。ports定义了Service的端口配置,这里将容器端口 80 映射到Service的端口 80。同时指定了NodePort为30080,表示该Service将在所有节点上的30080端口上公开。protocol设置为TCP,表示使用TCP协议进行通信。- 最后,Service的
type设置为NodePort,表示使用NodePort类型的Service来公开NGINX应用程序。
3.3 测试使用
至此,成功创建好一个 Service,我们可以做到:
- 在同一个命名空间下的其他容器,可以通过
curl Service的IP:port访问到 Pod 的targetPort- 查看 Service 的 IP 的方法:
kubectl get services -o wide - 可以创建一个
busybox:1.28去进行测试,使用命令wget Service的IP:80,就可以拉取到index.html
- 查看 Service 的 IP 的方法:
- 在容器外部访问该Service对应的Pod,可以访问
节点IP:NodePort访问到Nginx 的 Index.html- 查看 Pod 在哪个结点上:
kubectl get pods -o wide,拿到该节点所在的服务器的公网 IP - 浏览器访问:
http://节点IP:30080就可以访问到index.html
- 查看 Pod 在哪个结点上:
3.4 负载均衡
为了验证访问 Service 是否会有负载均衡,我们分别进入这三个容器:
- 修改它们的
Index.html分别为:Nginx-01、Nginx-02、Nginx-03 - 然后在某个节点不断的使用命令访问:
curl Service的IP:port,这里我们可以看到他们三者都会出现
4️⃣ 类型 type
上文中我们演示的类型为:NodePod,表示使用NodePort类型的Service来公开NGINX应用程序。而 type 其实有四种类型:
ClusterIP: 在集群内部暴露 Service,只能被集群内部的其他对象访问,通常用于内部服务发现,不会向集群外部访问。- 比如在一个 Web 应用中,你可能需要连接到一个数据库,但是这个数据库并不需要在应用之外暴露,这时就可以使用 ClusterIP 类型的 Service,让应用可以访问到数据库。
NodePort: 将 Service 暴露在 Node 的某个端口上,从而可以通过 Node 的 IP 和 端口号来访问 Service,通常用于开发和测试环境LoadBalancer: 通过云服务提供的负载均衡器来将 Service 暴露到公网上,使得外部用户可以访问 Service- 适用于需要将应用程序公开给公共互联网,或者需要通过云平台提供的负载均衡器来处理流量分发的情况。
ExternalName: 将 Service 映射到一个DNS名称上,从而可以通过DNS名称来访问 Service,通常用于外部访问服务- 适用于需要将Service名称解析为外部DNS名称的情况,例如连接到集群外部的数据库或其他服务。
💬 总结
为了解决 Controller 无法提供网络服务、以及实现负载均衡的问题,Service 应运而生,实现了 Pod 之间的通信,通过Service名称和端口号来相互通信,而不需要直接暴露Pod的IP地址,与 Ingress 之间的区别也要记住,Controller 是 内部 管理和访问应用程序的不同组件,Ingress 是 外部 公开应用程序的路由和访问方式。
🍁 友链
- ChatGPT
- 【编程不良人】Kubernetes(k8s)实战教程
- 【Kubernetes文档】| Kubernetes 官方文档
- 【云原生 • Kubernetes】(一) 初识 Kubernetes - 掘金 (juejin.cn)
- 【云原生 • Kubernetes】(二) Kubernetes 的组件与架构 - 掘金 (juejin.cn)
- 【云原生 • Kubernetes】(三) k8s 如何运行 Container? - 掘金 (juejin.cn)
- 【云原生 • Kubernetes】(四) k8s 原来不是直接创建 Pod!! - 掘金 (juejin.cn)
✒ 写在最后
都看到这里啦~,给个点赞再走呗~,也欢迎各位大佬指正以及补充,在评论区一起交流,共同进步!也欢迎加微信一起交流:Goldfish7710。咱们明天见~