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

 

Service 存在的意义


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

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

我们不应该期望 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。

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

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

 

Pod与Service的关系


• Service通过标签关联一组Pod

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

 

 

创建测试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,下篇博客介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值