1.Service

在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。

为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务。service创建后, 会创建一个同名的endpoint控制器,用来管理后端endpoint。通过就绪探针来检测后端端点是否正常工作。为pod添加标签,service使用标签选择器,来选择自己的后端端点,还能够根据探针(使用endpoint)对后端端点进行就绪状态检测

img

Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程。当创建Service的时候会通过api-server向etcd写入创建的service的信息,而kube-proxy会基于监听的机制发现这种Service的变动,然后它会将最新的Service信息转换成对应的访问规则。

img

1.1kube-proxy的代理模型

最早的userpace模式:是通过iptables规则拦截,由kube-proxy代理,现在已经不受支持:因为要从用户空间-内核空间-用户空间。

iptables模式:iptables拦截规则后,然后重定向到Kube-proxy,然后在通过Kube-proxy代理。报文直接经过内核iptables规则转发。但是大型的K8s集群会产生大量的iptables规则,会影响性能。

ipvs模式:一个调度只需要一个规则。

1.2Service的类型

ClusterIP:通过集群内部IP地址,来暴露服务,该地址仅在集群内部可见、可达,它无法被集群外部的客户端访问;默认类型。

NodePort:NodePort是ClusterIP的增强类型,它会在ClusterIP的功能之外,在每个k8s主机节点上使用一个相同的端口号将外部流量引入到该service上来(端口号范围30000-32767)。

LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境支持。

ExternalName:把集群外部的服务引入集群内部,直接使用。

1.3修改kube-proxy为ipvs

[root@master1 service]# kubectl edit cm kube-proxy -n kube-system
    kind: KubeProxyConfiguration
    metricsBindAddress: ""
    mode: "ipvs" #默认为空,空即为ipvs,默认调度规则为rr
    nodePortAddresses: null
    oomScoreAdj: null
    portRange: ""
    showHiddenMetricsForVersion: ""
    
#检查pod是否重启
#如果没有重启,可以把标签带有proxy的pod全部删除(生产环境中禁止)
[root@master1 service]# kubectl delete pods -l k8s-app=kube-proxy -n kube-system

  
#此时去node节点上,可以看到kube-ipvs0的虚拟接口
[root@node1 ~]# ifconfig kube-ipvs0
kube-ipvs0: flags=130<BROADCAST,NOARP>  mtu 1500
        inet 10.96.0.10  netmask 255.255.255.255  broadcast 0.0.0.0
        ether 92:d3:97:76:dc:04  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0  
        
#每一个service 的clusterIP都配置在了这个网络接口上        
[root@node1 ~]# ip addr show kube-ipvs0
71: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default 
    link/ether 92:d3:97:76:dc:04 brd ff:ff:ff:ff:ff:ff
    inet 10.96.0.10/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.105.245.105/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.96.0.1/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.97.193.4/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever    

 #安装ipsvadm,可以看到所有的规则
[root@node1 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.17.0.1:30253 rr
  -> 10.244.1.61:80               Masq    1      0          0         
  -> 10.244.2.48:80               Masq    1      0          0         
TCP  192.168.10.102:30253 rr
  -> 10.244.1.61:80               Masq    1      0          0         
  -> 10.244.2.48:80               Masq    1      0          0         
TCP  10.96.0.1:443 rr
  -> 192.168.10.101:6443          Masq    1      0          0         
TCP  10.96.0.10:53 rr
  -> 10.244.0.2:53                Masq    1      0          0         
  -> 10.244.0.3:53                Masq    1      0          0         
TCP  10.96.0.10:9153 rr
  -> 10.244.0.2:9153              Masq    1      0          0         
  -> 10.244.0.3:9153              Masq    1      0          0         
TCP  10.97.193.4:80 rr
  -> 10.244.1.61:80               Masq    1      0          0         
  -> 10.244.2.48:80               Masq    1      0          0         
TCP  10.105.245.105:443 rr
  -> 10.244.1.58:4443             Masq    1      0          0         
TCP  10.244.1.0:30253 rr
  -> 10.244.1.61:80               Masq    1      0          0         
  -> 10.244.2.48:80               Masq    1      0          0         
TCP  10.244.1.1:30253 rr
  -> 10.244.1.61:80               Masq    1      0          0         
  -> 10.244.2.48:80               Masq    1      0          0         
UDP  10.96.0.10:53 rr
  -> 10.244.0.2:53                Masq    1      0          0         
  -> 10.244.0.3:53                Masq    1      0          0  

1.4创建service

资源清单

apiVersion: v1
kind: Service
metadata: 
  name: 
  namespace: 
spec:
  type <string> #service的类型,默认为clusterIP
  selector <map[string]string> #等值类型的标签选择器,内含"与"逻辑
  ports: #Service的端口列表
  - name: <string> #端口名称
    protocol <string> #协议,目前仅支持TCP、UDP和STCP,默认为TCP
    port <integer> #service的端口号
    targetPort <string> #后端pod目标进程的端口号或者名称,名称需由Pod规范定义
    nodePort <integer> #节点端口号,仅适用于NodePort和LoadBalancer类型
  clusterIP <String> #service的集群IP,建议由系统自动分配
  externalTrafficPolicy <string> #外部流量策略的处理方式,local表示当前节点处理,cluster表示向集群范围调度。如果式local的话,本机无pod会服务不可达。
  loadBalancer <string> #外部负载均衡器使用的IP地址,仅适用于LoadBalancer
  externalName <string> #外部服务名称,该名称将作为Service的 DNS CNAME值

首先通过deploy创建一组pod。这个镜像可以输出pod的内部地址,方便检验。

[root@master service]# cat deploy-demoapp.yaml 
apiVersion: apps/v1
kind: Deployment      
metadata:
  name: deployment-demoapp
spec: 
  replicas: 3
  selector:
    matchLabels:
      app: demoapp-pod
  template:
    metadata:
      labels:
        app: demoapp-pod
    spec:
      containers:
      - name: nginx
        image: ikubernetes/demoapp:v1.0
[root@master service]# kubectl apply -f deploy-demoapp.yaml 
deployment.apps/deployment-demoapp created

[root@master service]# kubectl get pods -o wide
NAME                                  READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
deployment-demoapp-56c4f6b8f4-55hzx   1/1     Running   0          71s   10.244.2.64   node2   <none>           <none>
deployment-demoapp-56c4f6b8f4-brfln   1/1     Running   0          71s   10.244.1.67   node1   <none>           <none>
deployment-demoapp-56c4f6b8f4-vbx82   1/1     Running   0          71s   10.244.2.65   node2   <none>           <none>

#访问测试
[root@master service]# curl 10.244.2.64
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-55hzx, ServerIP: 10.244.2.64!

1.4.1clusterIP类型

[root@master1 service]# cat service-clusterip-demo.yaml 
apiVersion: v1
kind: Service
metadata:
  name: demoapp-clusterip-service
  namespace: default
spec:
  clusterIP:
  selector:
    app: demoapp-pod
  ports: 
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
[root@master service]# kubectl apply -f service-clusterip-demo.yaml 
service/demoapp-clusterip-service created
[root@master service]# kubectl get svc
NAME                        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
demoapp-clusterip-service   ClusterIP   10.97.37.131   <none>        80/TCP    3s
kubernetes                  ClusterIP   10.96.0.1      <none>        443/TCP   3d

#访问service,可以看出来是轮询
[root@master service]# curl 10.97.37.131
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-vbx82, ServerIP: 10.244.2.65!
[root@master service]# curl 10.97.37.131
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-55hzx, ServerIP: 10.244.2.64!
[root@master service]# curl 10.97.37.131
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-brfln, ServerIP: 10.244.1.67!
[root@master service]# curl 10.97.37.131
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-vbx82, ServerIP: 10.244.2.65!
[root@master service]# curl 10.97.37.131
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-55hzx, ServerIP: 10.244.2.64!
[root@master service]# curl 10.97.37.131
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-brfln, ServerIP: 10.244.1.67!

1.4.2NodePort类型

在之前的样例中,创建的Service的ip地址只有集群内部才可以访问,如果希望将Service暴露给集群外部使用,那么就要使用到另外一种类型的Service,称为NodePort类型。NodePort的工作原理其实就是将service的端口映射到Node的一个端口上,然后就可以通过NodeIp:NodePort来访问service了。

创建service-nodeport.yaml

apiVersion: v1
kind: Service
metadata:
  name: service-nodeport
spec:
  selector:
    app: demoapp-pod
  type: NodePort # service类型
  ports:
  - port: 80
    nodePort: 30002 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
    targetPort: 80
[root@master service]# kubectl apply -f service-nodeport.yaml 
service/service-nodeport created
[root@master service]# kubectl get svc
NAME                        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
demoapp-clusterip-service   ClusterIP   10.97.37.131   <none>        80/TCP         108m
kubernetes                  ClusterIP   10.96.0.1      <none>        443/TCP        3d2h
service-headliness          ClusterIP   None           <none>        80/TCP         4m44s
service-nodeport            NodePort    10.106.67.51   <none>        80:30002/TCP   3s
[root@master service]# curl 192.168.10.101:30002
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-vbx82, ServerIP: 10.244.2.65!
[root@master service]# curl 192.168.10.101:30002
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-55hzx, ServerIP: 10.244.2.64!
[root@master service]# curl 192.168.10.101:30002
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-brfln, ServerIP: 10.244.1.67!
[root@master service]# curl 192.168.10.102:30002
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.0, ServerName: deployment-demoapp-56c4f6b8f4-vbx82, ServerIP: 10.244.2.65!
[root@master service]# curl 192.168.10.102:30002
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.0, ServerName: deployment-demoapp-56c4f6b8f4-55hzx, ServerIP: 10.244.2.64!
[root@master service]# curl 192.168.10.102:30002
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.1, ServerName: deployment-demoapp-56c4f6b8f4-brfln, ServerIP: 10.244.1.67!
[root@master service]# curl 192.168.10.102:30002
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.0, ServerName: deployment-demoapp-56c4f6b8f4-vbx82, ServerIP: 10.244.2.65!

1.4.3 LoadBalancer类型的Service

LoadBalancer和NodePort很相似,目的都是向外部暴露一个端口,区别在于LoadBalancer会在集群的外部再来做一个负载均衡设备,而这个设备需要外部环境支持的,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。

img

1.4.4ExternalName类型的Service

ExternalName类型的Service用于引入集群外部的服务,它通过externalName属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。

img

apiVersion: v1
kind: Service
metadata:
  name: service-externalname
  namespace: dev
spec:
  type: ExternalName # service类型
  externalName: www.baidu.com  #改成ip地址也可以
# 创建service
[root@k8s-master01 ~]# kubectl  create -f service-externalname.yaml
service/service-externalname created

# 域名解析
[root@k8s-master01 ~]# dig @10.96.0.10 service-externalname.dev.svc.cluster.local
service-externalname.dev.svc.cluster.local. 30 IN CNAME www.baidu.com.
www.baidu.com.          30      IN      CNAME   www.a.shifen.com.
www.a.shifen.com.       30      IN      A       39.156.66.18
www.a.shifen.com.       30      IN      A       39.156.66.14

1.4.5补充externalIP

如果集群中本身只有一个节点具有一个公网IP,可以通过该公网IP引入外部流量。

例如:在node1上增加一个虚拟IP演示。

[root@node1 ~]# ip addr add 192.168.10.105/24  dev eth0

#创建service
[root@master service]# vim service-external-demo.yaml 
apiVersion: v1
kind: Service
metadata:
  name: demo-externalip-svc
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: demoapp-pod
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
  externalIPs:
    - 192.168.10.105
    
  [root@master service]# kubectl apply -f service-external-demo.yaml 
service/demo-externalip-svc created
[root@master service]# kubectl get svc
NAME                        TYPE        CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
demo-externalip-svc         ClusterIP   10.99.14.50    192.168.10.105   80/TCP         3s
demoapp-clusterip-service   ClusterIP   10.97.37.131   <none>           80/TCP         141m
kubernetes                  ClusterIP   10.96.0.1      <none>           443/TCP        3d2h
service-headliness          ClusterIP   None           <none>           80/TCP         37m
service-nodeport            NodePort    10.106.67.51   <none>           80:30002/TCP   32m


#访问测试
[root@master service]# curl 192.168.10.105
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-vbx82, ServerIP: 10.244.2.65!
[root@master service]# curl 192.168.10.105
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-55hzx, ServerIP: 10.244.2.64!
[root@master service]# curl 192.168.10.105
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-brfln, ServerIP: 10.244.1.67!
[root@master service]# curl 192.168.10.105
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: deployment-demoapp-56c4f6b8f4-vbx82, ServerIP: 10.244.2.65!
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐