• 41、service资源 Sky


    service资源
    一个service刻意看作一组提供相同服务的Pod的对外的访问接口;
    service作用于哪些pod时通过标签选择器来定义的;
    service强依赖dns解析服务:coredns,kube-dns(k8s1.1以前版本)
    https://cloud.tencent.com/developer/article/1718429
    service工作模式:userspace,iptables,ipvs
        userspace:kubernetes 1.1-
        iptables:kubernetes 1.10-
        ipvs:kubernetes1.11+
    
    userspace代理模式
    
    这种模式,kube-proxy 会监视 Kubernetes master 对 Service 对象和 Endpoints 对象的添加和移除。 对每个 Service,它会在本地 Node 上打开一个端口(随机选择)。 任何连接到“代理端口”的请求,都会被代理到 Service 的backend Pods 中的某个上面(如 Endpoints 所报告的一样)。 使用哪个 backend Pod,是 kube-proxy 基于 SessionAffinity 来确定的。
    
    最后,它配置 iptables 规则,捕获到达该 Service 的 clusterIP(是虚拟 IP)和 Port 的请求,并重定向到代理端口,代理端口再代理请求到 backend Pod。
    
    默认情况下,userspace模式下的kube-proxy通过循环算法选择后端。
    
    默认的策略是,通过 round-robin 算法来选择 backend Pod。
    
    iptables 代理模式
    
    这种模式,kube-proxy 会监视Kubernetes控制节点对Service对象和Endpoints对象的添加和移除。对每个Service,它会配置iptables规则,从而捕获到达该Service的clusterIP和端口的请求,进而将请求重定向到Service的一组backend中的某个上面。对于每个Endpoints对象,它也会配置 iptables 规则,这个规则会选择一个backend组合。
    
    
    
    默认的策略是,kube-proxy在iptables模式下随机选择一个backend。
    
    
    
    使用 iptables 处理流量具有较低的系统开销,因为流量由Linux netfilter 处理,而无需在用户空间和内核空间之间切换。 这种方法也可能更可靠。
    
    
    
    如果kube-proxy在 iptables模式下运行,并且所选的第一个 Pod 没有响应,则连接失败。 这与userspace模式不同:在这种情况下,kube-proxy 将检测到与第一个 Pod 的连接已失败,并会自动使用其他后端Pod重试。
    
    
    
    我们可以使用 Pod readiness 探测器验证后端 Pod 是否可以正常工作,以便 iptables 模式下的 kube-proxy 仅看到测试正常的后端。这样做意味着可以避免将流量通过 kube-proxy 发送到已知已失败的Pod。
    
    IPVS 代理模式
    
    在 ipvs 模式下,kube-proxy监视Kubernetes服务(Service)和端点(Endpoints),调用 netlink 接口相应地创建 IPVS 规则, 并定期将 IPVS 规则与 Kubernetes服务(Service)和端点(Endpoints)同步。该控制循环可确保 IPVS 状态与所需状态匹配。访问服务(Service)时,IPVS 将流量定向到后端Pod之一。
    
    IPVS代理模式基于类似于 iptables 模式的 netfilter 挂钩函数,但是使用哈希表作为基础数据结构,并且在内核空间中工作。 这意味着,与 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通信的延迟要短,并且在同步代理规则时具有更好的性能。与其他代理模式相比,IPVS 模式还支持更高的网络流量吞吐量。
    
    IPVS提供了更多选项来平衡后端Pod的流量。这些是:
    
    rr: round-robin
    
    lc: least connection (smallest number of open connections)
    
    dh: destination hashing
    
    sh: source hashing
    
    sed: shortest expected delay
    
    nq: never queue
    
    注意:要在 IPVS 模式下运行 kube-proxy,必须在启动 kube-proxy 之前使 IPVS Linux 在节点上可用。 当 kube-proxy 以 IPVS 代理模式启动时,它将验证 IPVS 内核模块是否可用。 如果未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。
    
    service服务类型:
    ClusterIP:默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP
    
    NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。以ClusterIP为基础,NodePort 服务会路由到 ClusterIP 服务。通过请求 <NodeIP>:<NodePort>,可以从集群的外部访问一个集群内部的 NodePort 服务。
    
    LoadBalancer:使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。
    
    ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如,foo.bar.example.com)。没有任何类型代理被创建。
    headless:
    
    需要注意的是:Service 能够将一个接收port映射到任意的targetPort。默认情况下,targetPort将被设置为与port字段相同的值。
    Service域名格式:(servicename).(namespace).svc.cluster.local,其中cluster.local为指定的集群的域名
    
    service主要包含:apiVsersion,kind,metadata,spec几个字段
    kubectl explain svc
    spec.ports字段:
      nodePort:节点上面的端口,该端口一定不能被占用
      port:service的端口,提供该服务的端口
      targetPort:容器上的端口
    
    命令式:
    
    kubectl expose deployment goweb --name=gowebsvc --port=80  --target-port=8000  
    声名式:yaml
    
    资源记录:
        SERVIC_NAME.NAMESPACE_NAME.DOMAIN>LTD
        svc.cluster.local.   如:redis.default.svc.cluster.local.
    
    service -->endpoint-->pod
    
    ClusterIP类型:
    # vi redis-svc.yaml
    apiVersion: v1
    kind: Service
    metadata:
        name: redis
        namespace: default
    spec:
        selector:
            app: redis
            role: logstor      
        clusterIP: 10.97.97.97
        type: ClusterIP
        ports:
        - port: 6397
          targetPort: 6397
        
    # kubectl apply -f redis-svc.yaml 
    # kubectl get svc
    NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP    28h
    redis        ClusterIP   10.97.97.97      <none>        6397/TCP   8s
    
    # kubectl describe svc redis
    Name:              redis
    Namespace:         default
    Labels:            <none>
    Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                         {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"redis","namespace":"default"},"spec":{"clusterIP":"10.97.97.97","...
    Selector:          app=redis,role=logstor
    Type:              ClusterIP
    IP:                10.97.97.97
    Port:              <unset>  6397/TCP
    TargetPort:        6397/TCP
    Endpoints:         <none>
    Session Affinity:  None
    Events:            <none>
    
    
    NodePort类型:
    # vi myapp-np-svc.yaml
    apiVersion: v1
    kind: Service
    metadata:
        name: myapp-np
        namespace: default
    spec:
        selector:
            app: myapp-np
            release: canary     
        clusterIP: 10.98.98.98
        type: NodePort
        ports:
        - port: 800
          targetPort: 800
          nodePort: 30800
    
    # kubectl apply -f myapp-np-svc.yaml
    # kubectl get svc
    NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
    kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP         28h
    myapp-np     NodePort    10.98.98.98      <none>        800:30800/TCP   32m
    
    # kubectl describe svc myapp-np
    Name:                     myapp-np
    Namespace:                default
    Labels:                   <none>
    Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                                {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp-np","namespace":"default"},"spec":{"clusterIP":"10.98.98.98...
    Selector:                 app=myapp-np,release=canary
    Type:                     NodePort
    IP:                       10.98.98.98
    Port:                     <unset>  800/TCP
    TargetPort:               800/TCP
    NodePort:                 <unset>  30800/TCP
    Endpoints:                <none>
    Session Affinity:         None
    External Traffic Policy:  Cluster
    Events:                   <none>
    
    # curl 192.168.31.11:30800/hostname.html   #轮询
    # kubectl path svc myapp-np -p '{"spec":{"sessionAffinity":"ClientIP"}}'    #打补丁直接生效,会话保持
    # curl 192.168.31.11:30800/hostname.html 
    
    # kubectl get svc -n kube-system
    NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
    kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   28h
    
    查看解析:
    # dig -t A myapp-np.default.svc.cluster.local. @10.96.0.10
    
    ; <<>> DiG 9.9.4-RedHat-9.9.4-50.el7 <<>> -t A myapp-np.default.svc.cluster.local. @10.96.0.10
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9942
    ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
    ;; WARNING: recursion requested but not available
    
    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 4096
    ;; QUESTION SECTION:
    ;myapp-np.default.svc.cluster.local. IN    A
    
    ;; ANSWER SECTION:
    myapp-np.default.svc.cluster.local. 5 IN A    10.98.98.98
    
    ;; Query time: 41 msec
    ;; SERVER: 10.96.0.10#53(10.96.0.10)
    ;; WHEN: Sun Apr 07 00:22:36 CST 2019
    ;; MSG SIZE  rcvd: 113
    ------------------------
    
    Deployment的yaml信息
    cat myapp-deploy.yaml 
    
    apiVersion: apps/v1
    
    kind: Deployment
    
    metadata:
    
      name: myapp-deploy
    
      namespace: default
    
    spec:
    
      replicas: 3
    
      selector:
    
        matchLabels:
    
          app: myapp
    
          release: v1
    
      template:
    
        metadata:
    
          labels:
    
            app: myapp
    
            release: v1
    
            env: test
    
        spec:
    
          containers:
    
          - name: myapp
    
            image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1
    
            imagePullPolicy: IfNotPresent
    
            ports:
    
            - name: http
    
              containerPort: 80
    # kubectl apply -f myapp-deploy.yaml 
    # kubectl get pod -owide
    
    NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE   NOMINATED NODE   READINESS GATES
    
    myapp-deploy-577fbb58c6-j45bg   1/1     Running   0          35s   10.244.1.30   vm2    <none>           <none>
    
    myapp-deploy-577fbb58c6-pdcpr   1/1     Running   0          35s   10.244.2.3    vm3    <none>           <none>
    
    myapp-deploy-577fbb58c6-wb45k   1/1     Running   0          35s   10.244.2.2    vm3    <none>           <none>
    
    [root@vm1 manifest]# kubectl get rs
    
    NAME                      DESIRED   CURRENT   READY   AGE
    
    myapp-deploy-577fbb58c6   3         3         3       38s
    
    
    # curl 10.244.1.30
    # curl 10.244.1.30/hostname.html
    
    ClusterIP类型示例
    
    yaml文件
    # cat myapp-svc-ClusterIP.yaml 
    
    apiVersion: v1
    
    kind: Service
    
    metadata:
    
      name: myapp-clusterip
    
      namespace: default
    
    spec:
    
      type: ClusterIP  # 可以不写,为默认类型
    
      selector:
    
        app: myapp
    
        release: v1
    
      ports:
    
      - name: http
    
        port: 80
    
        targetPort: 80
    # kubectl apply -f myapp-svc-ClusterIP.yaml
    # kubectl get svc
    
    NAME              TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
    
    kubernetes        ClusterIP   10.1.0.1      <none>        443/TCP   42d
    
    myapp-clusterip   ClusterIP   10.1.186.57   <none>        80/TCP    5s
    
    # curl 10.1.186.57
    # curl 10.1.186.57/hostname.html
    
    Headless Services
    
    有时不需要或不想要负载均衡,以及单独的Service IP。遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 “None” 来创建 Headless Service。
    
    
    
    这对headless Service并不会分配 Cluster IP,kube-proxy不会处理它们,而且平台也不会为它们进行负载均衡和路由。
    
    
    
    使用场景:
    
    
    
    第一种:自主选择权,有时候client想自己来决定使用哪个Real Server,可以通过查询DNS来获取Real Server的信息。
    
    第二种:Headless Services还有一个用处(PS:也就是我们需要的那个特性)。Headless Service对应的每一个Endpoints,即每一个Pod,都会有对应的DNS域名;这样Pod之间就可以互相访问。【结合statefulset有状态服务使用,如Web、MySQL集群】
    
    # cat myapp-svc-headless.yaml 
    
    apiVersion: v1
    
    kind: Service
    
    metadata:
    
      name: myapp-headless
    
      namespace: default
    
    spec:
    
      selector:
    
        app: myapp
    
        release: v1
    
      clusterIP: "None"
    
      ports:
    
      - port: 80
    
        targetPort: 80
    # kubectl apply -f myapp-svc-headless.yaml
    # kubectl get svc
    
    NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    
    kubernetes       ClusterIP   10.1.0.1     <none>        443/TCP   42d
    
    myapp-headless   ClusterIP   None         <none>        80/TCP    16s
    
    # kubectl describe svc myapp-headless
    
    Name:              myapp-headless
    
    Namespace:         default
    
    Labels:            <none>
    
    Annotations:       <none>
    
    Selector:          app=myapp,release=v1
    
    Type:              ClusterIP
    
    IP Families:       <none>
    
    IP:                None
    
    IPs:               <none>
    
    Port:              <unset>  80/TCP
    
    TargetPort:        80/TCP
    
    Endpoints:         10.244.1.30:80,10.244.2.2:80,10.244.2.3:80
    
    Session Affinity:  None
    
    Events:            <none>
    
    
    service只要创建成功就会写入到coredns。得到coredns IP的命令如下:
    kubectl get pod -o wide -A | grep 'coredns'
    
    kube-system   coredns-7ff77c879f-5w99f        0/1     running   9          28m   10.244.0.6     vm1    <none>           <none>
    
    kube-system   coredns-7ff77c879f-f5vtn        0/1     running   249        28h   10.244.1.26    vm2    <none>           <none>
    
    coredns记录信息如下
    
    # 其中 10.244.0.61 为 coredns IP
    
    # myapp-headless.default.svc.cluster.local 为Headless Service域名。格式为:$(service name).$(namespace).svc.cluster.local,其中 cluster.local 指定的集群的域名
    
    # nslookup myapp-headless.default.svc.cluster.local 10.244.0.61
    # dig -t A myapp-headless.default.svc.cluster.local. @10.244.0.61
    
    
    NodePort类型示例
    
    如果将 type 字段设置为 NodePort,则 Kubernetes 控制层面将在 --service-node-port-range 标志指定的范围内分配端口(默认值:30000-32767)。
    
    
    
    # cat myapp-svc-NodePort.yaml 
    
    apiVersion: v1
    
    kind: Service
    
    metadata:
    
      name: myapp-nodeport
    
      namespace: default
    
    spec:
    
      type: NodePort
    
      selector:
    
        app: myapp
    
        release: v1
    
      ports:
    
      - name: http
    
        # 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。
    
        port: 80         # Service对外提供服务端口
    
        targetPort: 80   # 请求转发后端Pod使用的端口
    
        nodePort: 31682  # 可选字段,默认情况下,为了方便起见,Kubernetes 控制层面会从某个范围内分配一个端口号(默认:30000-32767)
    # kubectl apply -f myapp-svc-NodePort.yaml
    # kubectl get svc
    
    NAME             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
    
    kubernetes       ClusterIP   10.1.0.1       <none>        443/TCP        42d
    
    myapp-nodeport   NodePort    10.1.122.197   <none>        80:31682/TCP   15s
    
    
    端口查看,可见在本地宿主机监听了相应的端口(备注:集群所有机器都监听了该端口)
    tcp        0      0 0.0.0.0:31682           0.0.0.0:*               LISTEN      2534/kube-proxy
    
    curl通过节点IP访问
    # curl 192.168.1.85:31682
    # curl 192.168.1.85:31682/hostname.html
    
    
    ExternalName类型示例
    这种类型的Service通过返回CNAME和它的值,可以将服务映射到externalName字段的内容(例如:my.k8s.example.com;可以实现跨namespace名称空间访问)。ExternalName Service是Service的特例,它没有selector,也没有定义任何的端口和Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式提供服务。
    # cat myapp-svc-ExternalName.yaml 
    
    apiVersion: v1
    
    kind: Service
    
    metadata:
    
      name: myapp-externalname
    
      namespace: default
    
    spec:
    
      type: ExternalName
    
      externalName: my.k8s.example.com
    # kubectl apply -f myapp-svc-ExternalName.yaml 
  • 相关阅读:
    将u8BF7字符串转换为汉字
    ubuntu扩容
    python面试题
    OCR开源项目
    58到家数据库30条军规解读
    dvwa sql盲注教程
    python time模块详解,时间格式转换
    python正则表达式
    tr命令详解
    腐烂
  • 原文地址:https://www.cnblogs.com/skyzy/p/16891004.html
Copyright © 2020-2023  润新知