CKAD备战笔记(6)- 服务与网络
1. 服务(Service)
Kubernetes中的每个Pod
都有它自己的IP地址,但Pod
经常会因为各种原因而挂掉,如果我们用Pod
的IP地址来访问该Pod
,会常出现IP地址无效的情况,我们用 服务(Service) 解决这个问题。服务提供了稳定的IP地址,我们永远可以找到服务的IP地址,然后通过该服务访问到想要找的应用Pod。
在创建Service的时候,k8s也会创建一个同名的Endpoint,这个Endpoint将跟踪哪些 Pod 是Service的端点,起到了一个实时数据存储的作用。
⚠️ 注意
- Service的端口(
port
)是任意的,而Service指向的Pod的端口(targetPort
)必须是Pod本身的端口- 一个Service可以开放多个端口,用于与不同的App进行沟通,但要注意的是,如果有多个端口开放,那么Service的每个端口都必须有一个名称
服务支持应用程序 内/外(Internal/External Networking) 的各种组件之间的通信。假设我们有一个前端的Pod,一个后端的Pod,以及一个数据库。他们之间的内部沟通正是由服务实现的(Internal Networking)。
集群上的IP地址
IP地址格式
IP address由两个部分组成:网络地址(Network ID) 和 主机地址(Host ID)。拿192.168.1.10
举例:
- 网络地址是前三个数:
192.168.1
,显示了当前所在的网络地址- 主机地址是最后一个数:
10
,显示当前网络中,主机的编号⚠️ 当你使用VPN(Virtual Private Network)的时候,你的网络地址是被隐藏的
IP地址类型
有两种类型:外部IP地址(external/public)和内部IP地址(internal/private)。一般来说,每个设备都有自己的外部IP和内部IP,且一般两者不同。
- 外部IP地址:由你的网络供应商提供,你访问一个网页时(比如百度),百度可以看到你的外部IP地址,知道你是从哪儿来的
- 内部IP地址:是自动生成的。人如其名,只做内部使用。比如,用于在家庭网络中识别你的身份信息
服务类型:
Service类型 | 功能 |
---|---|
NodePort | 该服务监听了Node的端口(Port),并将 在端口收到的请求 转发给某个Pod的端口 |
ClusterIP (默认类型) | 该服务在集群内部创建一个虚拟 IP,以实现不同服务之间的通信,例如前端服务器和后端服务器之间的通信。(Internal Networking) |
Headless | 帮助访问某个特定的Pod |
LoadBalancer | 该服务是负载均衡器,比如在用户访问量激增时,为Web 服务器分配负载 |
(1)NodePort类
从NodePort 服务的角度看,有三个端口:
(1)Pod的端口(TargetPort
):可选。如不写明,默认与Port
值相同
(2)Service的端口(Port
):必须写明,否则会报错。
(3)Node的端口(NodePort
):可选。如不写明,k8s会提供任意一个在 [30000, 32767] 范围内可用的端口
⚠️ 这三种Port的名字就是以 服务 自身为出发点设计的:
- 服务自己的Port就叫
Port
- Pod的端口是服务想要访问的目标,所以叫
TargetPort
;- Node的Port叫
NodePort
,对 外部访问 可见,所有外部访问都从这里进
比较
服务不存在 | 有了服务之后 |
---|---|
为了更好的理解,我们看一下如果 服务不存在 ,用户可以怎么访问Pod中的应用: 方法一: 如果用户本身在Cluster内部,可以直接通过 curl http:10.244.0.2 访问应用方法二: 如果在Cluster外部,可以通过 ssh 来访问 curl http:10.244.0.2 |
有了服务之后,Cluster外部对应用的访问会更方便。服务(Service)相当于一个虚拟服务器,有自己的IP地址(这里是10.106.127.123 )。这里我们不再需要 ssh ,而是直接访问Node所在的ip地址192.168.1.2 (⚠️用户本身的电脑IP和Node的IP是在同一个网络里面的,即IP地址中的前三部分时相同的,所以我们才能直接访问到Node得IP),入口则使用Service提供的端口( 30080 ),比如使用curl 192.168.1.2:30080 |
![]() |
![]() |
举例
# my_service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: NodePort # Service的类型
ports:
- targetPort: 80
port: 80
nodePort: 30008
# selector用于指定该服务要访问的Pod
selector:
app: myapp
function: frontend
⚠️
.spec.ports
容纳的是一个数组,意味着,在一个服务中,是可以多个这样的映射的(NodePort
->Port
->TargetPort
)
⚠️.spec.selector
指定targetPort
属于哪一个Pod,上面例子中绑定了一个labels
中有app=myapp
和function=frontend
的Pod。很多情况下,一个前端App会有多个replicas,但因为他们都有相同的labels
,他们会自动被service找到!
查看服务:
kubectl get services
结果如下:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <None> 443/TCP 7m30s
myapp-service NodePort 10.106.127.123 <None> 80:30008/TCP 30s
其中的 kubernetes服务
是k8s在启动时创建的默认服务。myapp-service
服务是我们创建的,现在作为用户可以通过curl http://192.168.1.2:30008
直接访问到前端App了!
多Node
当Pod的replicas分布在不同的Node上时,Service会自动扩展到多个Node上,我们不需要做任何多余的操作。
curl http://192.168.1.2:30008
curl http://192.168.1.3:30008

(2)ClusterIP类 服务
假设现在有前端后端组成的程序,而前端和后端各有自己的Replicas
(复制品,为了处理较大的用户访问而存在)。访问前端1的时候,前端1的API是发送给后端的哪一个replica
的呢?
Kubernetes的ClusterIP服务可以帮助我们将 Pod 分组在一起(所有的前端replicas为一组,后端replicas为另一组),并提供单个接口(即Service)来访问组中的 Pod。Pod会因为各种bug生生死死,每次重生之后拿到的IP地址还不一样,所以我们没有办法直接用Pod,因为我们不知道该去哪个IP地址找,而Service提供了稳定的IP地址。如图:
问:Service如何找到目标Pod?
答:Pod中的labels
== Service中的selectors
问:Service如何决定在目标Pod中,访问哪一个端口?
答:用.spec.ports
中的targetPort
决定
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
type: ClusterIP
ports