0
点赞
收藏
分享

微信扫一扫

Kubernetes Service ClusterIp为集群内部提供服务


Kubernetes Service ClusterIp为集群内部提供服务_nginx

 

Service 存在的意义

在进行业务升级的时候pod中容器的ip会发生变化,Service引入主要是解决Pod的动态变化,提供统一访问入口,下面是service的两个主要功能:

  • 防止Pod失联,准备找到提供同一个服务的Pod(服务发现)
  • 定义一组Pod的访问策略(负载均衡)

Kubernetes Service ClusterIp为集群内部提供服务_nginx_02

我们不应该期望 Kubernetes Pod 是健壮的,而是要假设 Pod 中的容器很可能因为各种原因发生故障而死掉。Deployment 等 controller 会通过动态创建和销毁 Pod 来保证应用整体的健壮性。换句话说,Pod 是脆弱的,但应用是健壮的。

每个 Pod 都有自己的 IP 地址。当 controller 用新 Pod 替代发生故障的 Pod 时,新 Pod 会分配到新的 IP 地址。这样就产生了一个问题:如果一组 Pod 对外提供服务(比如 HTTP),它们的 IP 很有可能发生变化,那么客户端如何找到并访问这个服务呢?

Kubernetes 给出的解决方案是 Service。(Service为了给客户端提供固定的访问端点,因此在客户端和服务端提供了中间层叫Service,Service名称解析是强依赖于Dns解析组件的,部署完k8s还需要部署CoreDns

 

Service三种常用类型

NodePort:在每个节点上启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址。

访问地址:<任意NodeIP>:<NodePort>

端口范围:30000-32767

除了 Cluster 内部可以访问 Service,很多情况我们也希望应用的 Service 能够暴露给 Cluster 外部。Kubernetes 提供了多种类型的 Service,默认是 ClusterIP。

Kubernetes Service ClusterIp为集群内部提供服务_nginx_03

ClusterIP 
Service 通过 Cluster 内部的 IP 对外提供服务,只有 Cluster 内的节点和 Pod 可访问,这是默认的 Service 类型。

Kubernetes Service ClusterIp为集群内部提供服务_kubernetes_04

LoadBalancer:与NodePort类似,在每个节点上启用一个端口来暴露服务。除此之外,Kubernetes会请求底层云平台(例如阿里云、腾讯云、AWS等)上的负载均衡器,将每个Node ([NodeIP]:[NodePort])作为后端添加进去

Kubernetes Service ClusterIp为集群内部提供服务_负载均衡_05

 

Pod与Service的关系

• Service通过标签关联一组Pod

• Service使用iptables或者ipvs为一组Pod提供负载均衡能力

Kubernetes Service ClusterIp为集群内部提供服务_html_06

 

 

创建测试Pod

Kubernetes Service 从逻辑上代表了一组 Pod,具体是哪些 Pod 则是由 label 来挑选。Service 有自己 IP,而且这个 IP 是不变的。客户端只需要访问 Service 的 IP,Kubernetes 则负责建立和维护 Service 与 Pod 的映射关系。无论后端 Pod 如何变化,对客户端不会有任何影响,因为 Service 没有变。

来看个例子,创建下面的这个 Deployment:

[root@k8s-master ~]# cat service-clusterip.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels: #这个标签很重要,service通过该标签来关联pod
app: nginx
spec:
containers:
- name: web
image: nginx:1.19
ports:
- containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
name: web
namespace: default
spec:
ports:
- port: 80 #service端口,相对于负载均衡器的端口,为前端提供的端口
protocol: TCP #协议
targetPort: 80 #容器端口
selector: # 指定关联Pod的标签
app: nginx
type: ClusterIP # 服务类型,默认为clusterip



#当使用clusterip的时候只有两个端口有用,servicer地址端口和容器端口
ports:
- port: 88 service地址上端口
targetPort: 80 容器端口

#selector 指明挑选那些 label 为 run: httpd 的 Pod 作为 Service 的后端

#将 Service 的 80 端口映射到 Pod 的 80 端口,使用 TCP 协议

我们启动了三个 Pod,label 是app​:nginx​,Service 将会用这个 label 来挑选 Pod。( Pod 分配了各自的 IP,这些 IP 只能被 Kubernetes Cluster 中的容器和节点访问。 )

[root@k8s-master ~]# kubectl get pod -l app=nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-559cd747d5-58v72 1/1 Running 0 3m29s 10.244.169.141 k8s-node2 <none> <none>
web-559cd747d5-cwmjt 1/1 Running 0 3m29s 10.244.36.77 k8s-node1 <none> <none>
web-559cd747d5-fz8c7 1/1 Running 0 3m29s 10.244.169.142 k8s-node2 <none> <none>

[root@k8s-master ~]# curl 10.244.169.141
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

看看service关联哪些pod 

[root@k8s-master ~]# kubectl get svc,ep
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 39d
service/web ClusterIP 10.111.237.182 <none> 80/TCP 10m

NAME ENDPOINTS AGE
endpoints/kubernetes 192.168.179.102:6443 39d
endpoints/web 10.244.169.141:80,10.244.169.142:80,10.244.36.77:80 10m

访问这个Ip就会转发到后端的pod,这里相对于lb负载均衡。前端要访问也是访问该service的clusterIP加上端口 

[root@k8s-master ~]# curl 10.111.237.182:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

 根据前面的端口映射,这里要使用 8080 端口。另外,除了我们创建的 ​​httpd-svc​​​,还有一个 Service ​kubernetes​,Cluster 内部通过这个 Service 访问 kubernetes API Server。

通过 ​​kubectl describe​​ 可以查看 web 与 Pod 的对应关系。

[root@k8s-master ~]# kubectl describe svc web
Name: web
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=nginx
Type: ClusterIP
IP: 10.111.237.182
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.169.141:80,10.244.169.142:80,10.244.36.77:80
Session Affinity: None
Events: <none>

 

Coredns解析

还可以通过名称去访问,注意这里的busybox版本要是这个1.28.4版本,最新版本会出现dns解析有问题,coredns只能解析出IP具体访问需要IP+端口 

[root@k8s-master ~]# kubectl run -it dns-test --rm --image=busybox:1.28.4 -- sh
If you don't see a command prompt, try pressing enter.
/ # nslookup web
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name: web
Address 1: 10.111.237.182 web.default.svc.cluster.local

/ # wget nginx-service:8888
Connecting to nginx-service:8888 (10.111.237.182:80)
index.html 100% |******************************************************************| 612 0:00:00 ETA

如果集群内部访问直接写 web.default这个名称就行或者clusterip也可以,写名称好一些,即使service重新创建了,名称也不会发生变化。如果service误删除了,重新创建那么还得去程序修改Ip

 

上面的​​Endpoints​​ 罗列了3个 Pod 的 IP 和端口。我们知道 Pod 的 IP 是在容器中配置的,那么 Service 的 Cluster IP 又是配置在哪里的呢?CLUSTER-IP 又是如何映射到 Pod IP 的呢?

答案是 iptables,下篇博客介绍。

举报

相关推荐

0 条评论