Service对象创建和使用

Service对象要解决的问题:

我们有一组在一个扁平的、集群范围的地址空间中运行 Nginx 服务的 Pod。 理论上,你可以直接连接到这些 Pod,但如果某个节点死掉了会发生什么呢? Pod 会终止,Deployment 将创建新的 Pod,且使用不同的 IP。这正是 Service 要解决的问题。

Kubernetes Service 是集群中提供相同功能的一组 Pod 的抽象表达。 当每个 Service 创建时,会被分配一个唯一的 IP 地址(也称为 clusterIP)。 这个 IP 地址与 Service 的生命周期绑定在一起,只要 Service 存在,它就不会改变。 可以配置 Pod 使它与 Service 进行通信,Pod 知道与 Service 通信将被自动地负载均衡到该 Service 中的某些 Pod 上。

创建Service时有三种类型(ClusterIP,NodePort,Loadbanlance),在理解Service对象时,可先看看Service三种对象的区别:

ClusterIP
Service的默认类型,服务被发布到仅集群内部可见的虚拟IP地址上。
在API Server启动时,需要通过service-cluster-ip-range参数配置虚拟IP地址段,API Server中有用于分配IP地址和端口的组件,当该组件获取Service对象并创建时间时,会从配置的虚拟IP地址段中取一个有效的IP地址,分配给该Service对象。

NodePort
在API Service启动时,需要通过node-port-range参数配置nodePort的范围,同样的,API Server组件会捕获Service对象并创建时间,即从配置好的nodePort范围取一个有效端口,分配给该Service。
每个节点的kube-proxy会尝试在服务分配的nodePort上建立监听器接受请求,并转发给服务对应的后端Pod实例。

LoadBalancer
企业数据中心一般会采购一些负载均衡器,作为外网请求进入数据中心内部的统一流量入口。
针对不同的基础架构云平台,Kubernetes Clound Manager提供支持不同供应商API的Service Controller。如果需要在Openstack云平台上搭建Kubernetes集群,那么只需提供一份openstack.rc,Openstack Service Controller即可通过调用LBaas API完成负载均衡配置。

上面介绍了三种不同类型的Service,接下来再看看port,nodeport,targetport的区别。

NodePort

外部流量访问k8s集群service入口的一组方式(另一种方式是LoadBalaner),即nodeIP:nodePort是提供给外部流量访问k8s集群中service的入口。比如外部用户要访问k8s集群中的一个Web应用,那么我们可以配置对应service的type=NodePort,nodePort=30001。其他用户就可以通过浏览器http://node:30001访问到该web服务。

Port

k8s集群内部服务之间访问service的入口。即cluseterIP:poer是service保留是clusterIP上的端口

TargetPort

容器的端口(最终流量的端口)。targrtPort是pod上的端口,从port和nodePort上来的流量,经过kube-prosy流入到后端的pod的targetPort上,最终进入容器,与DockerFile中定义的EXPOSE保持一致。

上面介绍了一些概念,接下来看看具体的service创建问题。

这里是一个deployment的yaml文件,通过该yaml文件创建pod(kubectl create -f xx.yaml)。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          readinessProbe:
            exec:
              command:
                - cat
                - /tmp/healthy
            initialDelaySeconds: 5
            periodSeconds: 5

pod创建好后,创建service,这个service中有selector,如果service中有selector,那么在创建service的同时,还会同步创建endpoint。

apiVersion: v1
kind: Service
metadata:
  name: nginx-basic
spec:
  type: ClusterIP
  ports:
    - port: 80
      protocol: TCP
      name: http
  selector:
    app: nginx

查看pod信息,可以看到pod是Not Ready状态,NotReady的原因是创建pod的yaml文件中需要执行cat /tmp/healthy命令,而刚创建的pod下面不存在该文件,所以是NotReady状态。此时通过clusterIP:port也无法访问到部署的nginx应用。

通过 kubectl exec -it podname --touch /tmp/healthy,在pod下创建该文件,再次查看pod,pod变成ready状态。

Service对象创建和使用_第1张图片

 通过ClusterIP:port访问应用,可返回正确的信息。

Service对象创建和使用_第2张图片再查看endpoint,如果pod都是ready状态,那么endpoint的address中会记录pod的ip直至端口等信息,如果pod是notready状态,那么在NotReadyAddress中记录pod的ip地址和端口信息,只有pod处于ready状态,发送到service的请求才会转发到对应的pod上。那么endpoint的作用是什么呢?

endpoint实际就是记录service与pod之间的映射关系的(一个service可以对应多个pod,同理一个pod也可以对应多个service),为了更好的维护这个映射关系,所以有了endpoint。自动创建的endpoint名字与service名字一致,endpoint里面记录pod的ip地址的端口信息,这样就能把请求转发到具体的pod上面了。

Service对象创建和使用_第3张图片 

pod的ip地址和endpoint中存储的一致。

 上面创建的ClusterIP类型的service只能在集群内部访问,如果期望能在外部访问集群内部的pod,那么需要创建NodePort的Service,yaml文件如下:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  ports:
    - port: 8080
      targetPort: 80
      protocol: TCP
      name: http
    - port: 443
      protocol: TCP
      name: https
  selector:
    app: nginx

创建后,在外部用curl命令访问:node节点的public IP:nodePort,可以看到成功返回了nginx的信息,说明外部访问集群内部的服务成功。

Service对象创建和使用_第4张图片

在浏览器上,也能成功访问到nginx服务。

Service对象创建和使用_第5张图片

 在通过service完成请求转发的过程中,还可以在service的yaml文件中配置topology来控制流量

当topology key设置为:"kubernetes.io/hostname"时,调用服务的客户端,如果有服务实例正在运行,则实例处理请求,否则,调用失败。

当topology key设置为如下:则优先查看是否在同一个node节点上有服务运行,如果不存在,则找同一个zone下,如果还不存在,则找同一个region下,否则调用失败

- "kubernetes.io/hostname"

- "topology.kubernetes.io/zone"

- "topology.kubernetes.io/region"

如果在yaml文件中topology key配置上“*”,则表示如果前面的规则都没有找到运行的实例,那么就转发请求到任意服务实例上。

如下是service中添加topology key的yaml文件

apiVersion: v1
kind: Service
metadata:
  name: nodelocal
spec:
  ports:
    - port: 80
      protocol: TCP
      name: http
  selector:
    app: nginx
  topologyKeys:
    - "kubernetes.io/hostname"
apiVersion: v1
kind: Service
metadata:
  name: prefer-nodelocal
spec:
  ports:
    - port: 80
      protocol: TCP
      name: http
  selector:
    app: nginx
  topologyKeys:
    - "kubernetes.io/hostname"
    - "topology.kubernetes.io/zone"
    - "topology.kubernetes.io/region"
    - "*"

 

你可能感兴趣的:(云原生,kubernetes,云原生)