zoukankan      html  css  js  c++  java
  • kubernetes 实践五:Service详解

    Service 是 k8s 的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。

    Service 的定义

    Service YAML格式的定义文件如下:

    apiVersion: v1      // Required
    kind: Service       // Required
    metadata:           // Required
      name: string      // Required
      namespace: string // Required
      labels:
        - name: string
      annotations:
        - name: string
      spec:             // Required
        selectors: []   // Required
        type: string    // Required
        clusterIP: string
        sessionAffinity: string
        ports:
          - name: string
            protocol: string
            port: int
            targetPort: int
            nodePort: int
        status:
          loadBalancer:
            ingress:
              ip: string
              hostname: string
    

    各属性的说明:




    Service的基本用法

    一般k8s的Pod都会以RC或者Deployment对外进行发布,并使用TCP/IP+Port的方式使得外部可以访问内部得服务。例如一个提供Web服务RC,由两个tomcat容器组成,每个容器都通过containerPort设置服务得端口号为8080。

    # webapp-rc.yaml
    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: webapp
    spec:
      replicas: 2
      template:
        metadata:
          name: webapp
          labels:
            app: webapp
        spec:
          containers:
          - name: webapp
            image: tomcat
            ports:
              - containerPort: 8080  ## containerPort 要和 镜像暴露得端口要一直。
    

    创建该RC:

    kubectl apply -f webapp-rc.yaml
    

    创建成功之后:

    NAME           READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
    webapp-nfrzq   1/1     Running   0          96s   10.244.1.44   k8s-node1    <none>           <none>
    webapp-sxlmk   1/1     Running   0          96s   10.244.0.73   k8s-master   <none>           <none>
    

    这样就可以使用Pod得IP+Port得方式访问Tomcat服务了:

    # curl 10.244.1.44:8080
    # curl 10.244.0.73:8080
    

    但是以这种方式访问服务是有问题得,首先我们需要知道每个Pod得地址,如果该Pod故障,就需要切换使用另一个Pod得IP。所以k8s中Service组件就是用于解决这些问题的。

    Service的简单使用

    创建Service有两种方法,使用命令kubectl export或者根据定义文件创建。

    先来使用命令创建Service,例如为之前的RC提供一个Service,使用命令如下:

    [root@k8s-master service]# kubectl expose rc webap
    [root@k8s-master service]# kubectl get svc webapp
    NAME     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
    webapp   ClusterIP   10.107.38.14   <none>        8080/TCP   27s
    

    创建Service后就可以直接使用Service的IP:Port的格式访问服务,请求会被自动负载分发到后端的Pod上。

    我们还可以使用yaml定义文件创建Service,定义文件如下:

    apiVersion: v1
    kind: Service
    metadata:
      name: webapp
    spec:
      ports:
        - port: 8081
          targetPort: 8080
      selector:
        app: webapp
    

    创建该Service:

    [root@k8s-master service]# kubectl create -f webapp-svc.yaml  
    service/webapp created
    [root@k8s-master service]# kubectl get svc webapp
    NAME     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
    webapp   ClusterIP   10.109.63.40   <none>        8081/TCP   7s
    

    目前k8s提供了两种负载分发策略:

    • RoundRobin:轮询模式,即轮询将请求转发到后端的各个Pod上。
    • SessionAffinity:基于客户端IP地址进行会话保持的模式,即第1次将某个客户端发起的请求转发到后端的某个Pod上,之后从相同的客户端发起的请求都将被转发到后端相同的Pod上。

    默认情况下,k8s采用RoundRobin模式,通过设置参数service.spec.sessionAffinity=ClientIP来启用SessionAffinity策略。

    多端口Service

    Service 支持设置多个端口对应到多个应用服务,配置文件如下:

    apiVersion: v1
    kind: Service
    metadata:
      name: webapp
    spec:
      ports:
        - port: 8080
          targetPort: 8080
          name: web
        - port: 8005
          targetPort: 8005
          name: management
      selector:
        app: webapp
    

    也可以指定协议:

    ...
    spec:
      ports:
        - port: 53
          procotol: UDP
          name: dns
        - port: 53
          procotol: TCP
          name: dns-tcp
    ...
    

    外部服务service

    外部服务Service可以将k8s集群外的应用纳入到集群服务,可以通过创建一个无Label Selector的Service实现:

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      ports:
        - port: 8080
          procotol: TCP
          targetPort: 80
    

    同时还需要创建一个和该Service同名的Endpoint资源,用于指向实际的后端访问地址,配置文件如下:

    apiVersion: v1
    kind: Endpoint
    metadata:
      name: my-service
    subsets:
    - address:
      - IP: 1.2.3.4
      ports:
        - port: 80
    

    Headless Service

    k8s支持用户自定义负载均衡的策略,k8s提供了Headless Service来实现这种功能,即不为Service设置ClusterIP(入口IP地址),仅通过Label Selector将后端的Pod列表返回给调用的客户端。例如:

    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
    spec:
      ports:
        - port: 80
        clusterIP: None
      selector:
        app: nginx
    

    这样,Service就不再具有一个特定的clusterIP,对其访问将获得包含Label “app=nginx”的全部Pod列表,然后客户端程序自行决定如何处理这个Pod列表。StatefulSet就是使用Headless Service为客户端返回多个服务地址的,而且Headless Service十分适用于“去中心化”类的应用集群。

    从集群外部访问Pod或者Service

    由于Pod和Service都是k8s集群范围内的虚拟概念,所以集群外的客户端无法通过Pod的IP地址或者Service的虚拟IP地址访问。因此可以将Pod或者Service的端口号映射到宿主机,让容器外部的客户端也可以访问。

    将容器应用的端口号映射到物理机

    1.设置容器级别的hostPort

    # pod-hostport.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: webapp
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: tomcat
        ports:
        - containerPort: 8080
          hostPort: 9000
    

    创建Pod

    kubectl create -f pod-hostport.yaml
    

    创建完成后就可以访问k8s node的IP:Port。

    2.设置Pod级别的hostNetwork=true

    该Pod中所有容器的端口号都将被直接映射到物理机上。在设置hostNetwork=true时需要注意,在容器的ports定义部分如果不指定hostPort,则默认hostPort等于containerPort,如果指定了hostPort,则hostPort必须等于containerPort的值:

    ## pod-hostnetwork.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: webapp
      labels:
        app: webapp
    spec:
      hostNetwork: true
      containers:
      - name: webapp
        image: tomcat
        imagePullPolicy: Never
        ports:
        - containerPort: 8080
    

    将Service的端口号映射到物理机

    1.设置nodePort映射到物理机

    apiVersion: v1
    kind: Service
    metadata:
      name: webapp
    spec:
      type: NodePort
      ports:
        - port: 8080
          targetPort: 8080
          nodePort: 31080 # 默认有效值 30000 - 32767
      selector:
        app: webapp
    

    对该Service的访问也将被负载分发到后端的多个Pod上。

    2.设置LoadBalancer映射到云平台

    这种用法仅用于在公有云服务提供商的云平台上设置Service的场景。 在下面的例子中, status.loadBalancer.ingress.ip设置的146.148.47.155为云服务商提供的负载均衡器的IP地址。 对该Service的访问请求将会通过LoadBalancer转发到后端Pod上, 负载分发的实现方式则依赖于云服务商提供的LoadBalancer的实现机制:

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      selector:
        app: MyApp
      ports:
        - protocol: TCP
          port: 80
          targetPort: 9376
          nodePort: 30061
        clusterIP: 10.0.171.239
        loadBalancerIP: 78.11.24.19
        type: LoadBalancer
      status:
        loadBalancer:
          ingress:
          - ip: 146.148.47.155
    
  • 相关阅读:
    008 同步
    007 优雅的关闭线程
    006 线程中的join方法
    005 线程ID和线程的优先级
    004 后台线程
    003 Thread的构造
    群发 图片和语音失败原因是 ,返回 content是 null,
    状态,
    Shape Of My Heart
    转码 的状态,嘿嘿,小bug,少了一个 !
  • 原文地址:https://www.cnblogs.com/xingyys/p/11647275.html
Copyright © 2011-2022 走看看