• Kubernetes ---- Service介绍


    Service

    介绍:

    实现方式:
       1. userspace: 用户空间
           用户的请求到达对应节点之上的iptables or ipvs规则(Service的规则),由Service先将他转为本地监听在某个套接字上的用户空间的kube-proxy进行处理,处理完成后再转给Service IP,最终代理至后端Pod.
       2. iptables: 直接调度 
           用户请求到达iptables后直接进行调度,无需进入用户空间处理;
       3. ipvs: 直接调度
           用ipvs进行调度,与iptables类似


    kube-proxy
      始终监视着master上的api server服务中有关Service的变动信息;
      api server上有关Service对象的变动比如创建、删除,kube-proxy都要将其转化为当前节点上能够实现将用户请求调度到后端特定Pod资源之上的规则(iptables or ipvs)取决于Service实现方式


    通过YAML文件创建Service:

    1. 类型介绍

    # 可手动指定Service的虚拟IP地址
    svc.spec.clusterIP <string>
    
    # 标签选择器,用于关联后端的Pod
    svc.spec.selector <map[string]string>
    
    # 关联后端Pod的端口
    svc.spec.ports <[]Object>
    
    # service的类型(ExternalName, ClusterIP, NodePort, LoadBalancer)
    svc.spec.type <string>

    ClusterIP: 默认为此类型,仅用于集群内通信
    NodePort: 接入机器外部的流量,客户端直接通过节点的IP+NodePort暴露出来的端口就可访问
    LoadBalancer: 比如在云环境上搭建了K8S集群(阿里云、AWS云),使用此种类型的Service会自动创建负载均衡器(阿里云的SLB)
    ExternalName: 需要被kube-dns能够解析,用于将Service关联至外围服务以供Pod访问,外围服务将处理结果转交个Node,Node再返回给Service,Service再返回给Pod client,从而让Pod访问外围的服务(集群内不存在的服务)

    资源记录格式(CoreDns):
       SVC_NAME.NS_NAME.DOMAIN.LTD.

       svc.cluster.local.

       redis.default.svc.cluster.local.

    2.创建ClusterIP类型的Service.

    $ vim svc-demo.yaml
      apiVersion: v1
       kind: Service
       metadata:
         name: redis
         namespace: default
       spec:
         clusterIP: 10.97.97.97
         type: ClusterIP
         selector:
           app: redis
           role: logstor
       ports:
       - name: redis
         port: 6479
         targetPort: 6379
         protocol: TCP
    
    $ kubectl apply -f svc-demo.yaml
    $ kubectl get svc NAME   TYPE   CLUSTER
    -IP   EXTERNAL-IP   PORT(S)   AGE redis ClusterIP 10.97.97.97   <none>     6379/TCP   2m52s # 后端的Pod是之前创建的一个redis $ 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: redis 6379/TCP TargetPort: 6379/TCP Endpoints: 10.244.1.63:6379 Session Affinity: None Events: <none> # 下列的Pod是之前搞Deployment的时候创建的,现在要把这些发布出去. $ kubectl get pods --show-labels NAME               READY STATUS RESTARTS AGE       LABELS deploy-demo-f5dfc4cf4-cb58r 1/1   Running   1    20h   app=myapp,pod-template-hash=f5dfc4cf4,release=canary deploy-demo-f5dfc4cf4-mm27c 1/1   Running   1    20h   app=myapp,pod-template-hash=f5dfc4cf4,release=canary deploy-demo-f5dfc4cf4-p7zvp 1/1   Running   1    20h   app=myapp,pod-template-hash=f5dfc4cf4,release=canary deploy-demo-f5dfc4cf4-rbqnh 1/1   Running   1   20h   app=myapp,pod-template-hash=f5dfc4cf4,release=canary deploy-demo-f5dfc4cf4-wz8tr 1/1   Running   1   20h   app=myapp,pod-template-hash=f5dfc4cf4,release=canary

    3.创建NodePort类型的Service.

    $ vim svc-np-demo.yaml
    apiVersion: v1
    kind: Service
    metadata:
    name: redis
    namespace: default
    spec:
    type: NodePort
    selector:
    app: myapp
    release: canary
    ports:
    - name: myapp-port
    nodePort: 30001
    port: 80
    targetPort: 80
    
    $ kubectl apply -f svc-np-demo.yaml
    
    $ kubectl get svc
    NAME         TYPE     CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE
    kubernetes   ClusterIP    10.96.0.1    <none>      443/TCP     14d
    myapp     NodePort     10.97.65.55  <none>       80:30001/TCP  61s
    redis     ClusterIP    10.97.97.97   <none>        6379/TCP    20m
    
    $ kubectl describe svc myapp
    Name: myapp
    Namespace: default
    Labels: <none>
    Annotations: kubectl.kubernetes.io/last-applied-configuration:
    {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"ports":[{"name":"myapp-por...
    Selector: app=myapp,release=canary
    Type: NodePort
    IP: 10.97.65.55
    Port: myapp-port 80/TCP
    TargetPort: 80/TCP
    NodePort: myapp-port 30001/TCP
    Endpoints: 10.244.1.64:80,10.244.1.65:80,10.244.1.66:80 + 2 more...
    Session Affinity: None
    External Traffic Policy: Cluster
    Events: <none>
    
    # 集群外部机器一直访问此Service,会发现返回的结果中包含所有Pod.
    $ while true;do curl http://192.168.222.100:30001/hostname.html;sleep 1; done
    deploy-demo-f5dfc4cf4-wz8tr
    deploy-demo-f5dfc4cf4-p7zvp
    deploy-demo-f5dfc4cf4-p7zvp
    deploy-demo-f5dfc4cf4-cb58r
    deploy-demo-f5dfc4cf4-wz8tr
    deploy-demo-f5dfc4cf4-cb58r
    deploy-demo-f5dfc4cf4-rbqnh
    deploy-demo-f5dfc4cf4-rbqnh
    deploy-demo-f5dfc4cf4-wz8tr
    deploy-demo-f5dfc4cf4-rbqnh
    deploy-demo-f5dfc4cf4-p7zvp
    deploy-demo-f5dfc4cf4-rbqnh
    deploy-demo-f5dfc4cf4-cb58r
    .....

    小功能如果启用下面这个功能的话那么来自同一客户端的请求始终发送给第一次接收请求的Pod

    svc.spec.sessionAffinity <string>
      string:

        ClientIP

        None(默认值)

    # 打补丁更新配置,也可以使用"kubectl edit -f xxx"或直接vim文件,随后使用"kubectl apply -f xxx"也可以.
    $ kubectl patch svc myapp -p '{"spec":{"sessionAffinity":{"ClientIP"}}}' # 再次查看,会发现多了"**"那一行. $ kubectl describe svc myapp Name: myapp Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"ports":[{"name":"myapp-por... Selector: app=myapp,release=canary Type: NodePort IP: 10.97.65.55 Port: myapp-port 80/TCP TargetPort: 80/TCP NodePort: myapp-port 30001/TCP Endpoints: 10.244.1.64:80,10.244.1.65:80,10.244.1.66:80 + 2 more... ** Session Affinity: ClientIP External Traffic Policy: Cluster Events: <none> # 而且客户端访问这个Service的结果永远都是一样的

    4. headless Service(无头Service)

    说明:

      之前的Service的工作过程我想大家应该都知道,当客户端访问Service的时候,实际是会有kube-dns进行解析Service的名称,将名称解析为ClusterIP,随后根据算法调度后端Pod以便响应客户端请求,这个headless Service无需配置ClusterIP
    要设为"None",那么当客户端请求过来的时候会将Service Name直接解析为后端Pod的地址以便提供响应.

    4.1 使用YAML文件创建的方法

    $ vim myapp-svc-headless.yaml
      apiVersion: v1
      kind: Service
      metadata:
        name: myapp-headless
        namespace: default
      spec:
        clusterIP: None
        type: ClusterIP
          selector:
            app: myapp
            release: canary
        ports:
        - port: 80
          targetPort: 80 
    $ kubectl apply -f myapp-svc-headless.yaml
    
    # 会发现"**"标记的那一行中的ClusterIP为None,不用慌,这是正常现象.
    $ kubectl get svc 
    NAME     TYPE     CLUSTER-IP     EXTERNAL-IP     PORT(S)     AGE
    kubernetes ClusterIP   10.96.0.1     <none>        443/TCP     15d
    myapp     NodePort   10.97.65.55    <none>        80:30001/TCP   160m
    ** myapp-headless ClusterIP None      <none>        80/TCP       15m
    redis     ClusterIP   10.97.97.97    <none>        6379/TCP      179m
    
    # 随后我们手动解析这个没有ClusterIP的Service,查看结果(answer上边的和下边的省略了),发现解析结果为后端的所有Pod的地址.
    $ dig -t A myapp-headless.default.svc.cluster.local @10.96.0.10
    .....
    ;; ANSWER SECTION:
    myapp-headless.default.svc.cluster.local. 30 IN    A 10.244.1.64
    myapp-headless.default.svc.cluster.local. 30 IN    A 10.244.1.66
    myapp-headless.default.svc.cluster.local. 30 IN    A 10.244.1.65
    myapp-headless.default.svc.cluster.local. 30 IN    A 10.244.2.67
    myapp-headless.default.svc.cluster.local. 30 IN    A 10.244.2.68
    ......
  • 相关阅读:
    实现自动更新文件
    IP零碎知识总结
    有关数据库操作的一些函数
    AppConfig有关零碎知识
    将文件上传到数据库 和 从数据库下载文件到本地
    如何学习编程
    像素、英寸、厘米之间的换算关系
    局域网
    JSP基础知识
    Exchange a,b without using other variables
  • 原文地址:https://www.cnblogs.com/k-free-bolg/p/13099709.html
Copyright © 2020-2023  润新知