zoukankan      html  css  js  c++  java
  • kubernetes的Service是什么?

    • service到底是什么?
      k8s的service定义了一个服务的访问入口地址,前端的应用通过这个入口地址访问其背后的一组由pod副本组成的集群实例。来自外部的访问请求被负载均衡到后端的各个容器应用上。Service与其后端Pod副本集群之间则是通过Label Selector来实现对接。
      RC的作用相当于保证Service的服务能力和服务质量始终处于预期的标准。Service定义可以基于POST方式。请求apiserver创建新的实例。
      例如:
      1.创建一个新的nginx pod
    [root@wf-01 ~]# kubectl run nginx-deploy --image=nginx:1.14-alpine --port=80 --replicas=1
    

    2.查看创建的pod

    [root@wf-01 ~]# kubectl get pod |grep nginx
    nginx-deploy-84cbfc56b6-7v59n   1/1     Running   0          4m1s
    

    3.查看deploy

    [root@wf-01 ~]# kubectl get deploy
    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deploy   1/1     1            1           4m28s
    

    4.查看是否可以访问

    [root@wf-01 ~]# curl 172.20.0.64
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
             35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    
    • 这时我们访问的IP为Pod的IP,那么问题来了,如果我把Pod删除,则deploy控制器会重新启动一个pod以实现第一次创建Pod时指定的副本数为1的条件。这个时候pod ip会发生变化。显而这个不是我们期望的。所以需要创建一个service来保证pod的IP的变化对pod客户端(其它pod,集群内部客户端)来说是透明的。总而言之,service为pods提供固定的访问端点。
    • 创建service, service有很多类型。如ClusterIP,NodePort,LoadBalancer或者ExternalName。默认为ClusterIP,意思是这个services IP只能被集群内的Pod客户端访问。
    # 创建service
    [root@wf-01 ~]# kubectl expose deployment nginx-deploy --name=nginx --port=80 --target-port=80 --protocol=TCP 
    service/nginx exposed
    # 查看nginx的service
    [root@wf-01 ~]# kubectl get svc |grep nginx
    nginx          ClusterIP   10.68.23.129   <none>        80/TCP     18s
    # 访问
    [root@wf-01 ~]# curl 10.68.23.129
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
             35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    
    • 如果集群部署了coredns,则集群内的节点DNS为coredns的地址。则可以通过service name直接解析到对应的IP
    # 集群的coredns地址
    [root@wf-01 ~]# kubectl get svc -n kube-system 
    NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
    kube-dns        ClusterIP   10.68.0.2    <none>        53/UDP,53/TCP,9153/TCP   5d18h
    
    • 创建一个client(使用busybox)来验证是否可以实现dns功能
    [root@wf-01 ~]# kubectl run client --image=busybox --replicas=1 -it --restart=Never
    # 查看解析的dns地址
    ~ # cat /etc/resolv.conf 
    nameserver 10.68.0.2
    search default.svc.cluster.local. svc.cluster.local. cluster.local.
    options ndots:5
    ~ # wget -O - -q http://nginx:80
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
             35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    

    可以看到client获取的dns为default.svc.cluster.local。nginx服务的完整域名为: nginx.default.svc.cluster.local

    • 手动删除一个nginx pod,deploy控制器会自动创建一个新的nginx pod调度至对应的node节点。这时使用busybox再次解析nginx,查看service是否生效
    [root@wf-01 ~]# kubectl delete pod nginx-deploy-84cbfc56b6-7v59n 
    pod "nginx-deploy-84cbfc56b6-7v59n" deleted
    [root@wf-01 ~]# kubectl get pod |grep nginx
    nginx-deploy-84cbfc56b6-hcmwv   1/1     Running   0          30s
    # 在busybox容器中执行下面操作查看
    ~ # wget -O - -q http://nginx:80
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
             35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    

    service深入理解

    service是一个iptables或ipvs规则。使用标签选择器,将访问service_ip:port所有的都调度至相应的pod后端。

    怎么知道service关联到哪些pod?

    [root@wf-01 ~]# kubectl describe svc nginx
    Name:              nginx
    Namespace:         default
    Labels:            run=nginx-deploy
    Annotations:       <none>
    Selector:          run=nginx-deploy
    Type:              ClusterIP
    IP:                10.68.23.129
    Port:              <unset>  80/TCP
    TargetPort:        80/TCP
    Endpoints:         172.20.0.66:80
    Session Affinity:  None
    Events:            <none>
    

    其中上面的Endpoints:170.20.0.66:80就是关联的pods,而Selector: run=nginx=deploy就是选择相应的pod进行关联。下面查看nginx pod的标签是否为"run=nginx-deploy"

    [root@wf-01 ~]# kubectl describe pods nginx-deploy-84cbfc56b6-hcmwv 
    Name:           nginx-deploy-84cbfc56b6-hcmwv
    Namespace:      default
    Node:           192.168.30.79/192.168.30.79
    Start Time:     Tue, 14 May 2019 10:53:11 +0800
    Labels:         pod-template-hash=84cbfc56b6
                    run=nginx-deploy
    Annotations:    <none>
    Status:         Running
    IP:             172.20.0.66
    Controlled By:  ReplicaSet/nginx-deploy-84cbfc56b6
    

    如果对应的pod资源被删除,则services后端关联的pod_ip会动态变化。我们也可以去改service的ip。则kube-dns内对应的几率也会动态变化。

    • 一个创建好的deployment是可以动态改变副本数。也就是意味着可以实现动态扩容
    # 创建一个双副本的deployment
    [root@wf-01 ~]# kubectl run myapp --image=ikubernetes/myapp:v1 --replicas=2
    deployment.apps/myapp created
    # 查看deployment的副本信息
    [root@wf-01 ~]# kubectl get deployment
    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    myapp          2/2     2            2           37s
    # 查看pod的详情
    [root@wf-01 ~]# kubectl get pod -o wide |grep myapp
    myapp-9b4987d5-jngkk            1/1     Running   0          89s     172.20.0.68   192.168.30.79   <none>           <none>
    myapp-9b4987d5-tcg4p            1/1     Running   0          89s     172.20.0.67   192.168.30.79   <none>           <none>
    
    • 使用busybox访问查看是否生效
    ~ # wget -O - -q 172.20.0.67
    Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
    ~ # wget -O - -q 172.20.0.68
    Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
    ~ # wget -O - -q 172.20.0.67/hostname.html
    myapp-9b4987d5-tcg4p
    ~ # wget -O - -q 172.20.0.68/hostname.html
    myapp-9b4987d5-jngkk
    
    • 我们创建一个service来提供固定访问端点
    [root@wf-01 ~]# kubectl expose deployment myapp --name=myapp --port=80 
    service/myapp exposed
    [root@wf-01 ~]# kubectl get svc |grep myapp
    myapp          ClusterIP   10.68.20.152   <none>        80/TCP     12s
    
    • 客户端再次访问,并测试负载均衡的效果
    ~ # wget -O - -q myapp
    Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
    ~ # wget -O - -q myapp.default.svc.cluster.local.
    Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
    ~ # while true;do wget -O - -q myapp/hostname.html; sleep 1;done
    myapp-9b4987d5-tcg4p
    myapp-9b4987d5-tcg4p
    myapp-9b4987d5-tcg4p
    myapp-9b4987d5-tcg4p
    myapp-9b4987d5-jngkk
    myapp-9b4987d5-jngkk
    myapp-9b4987d5-jngkk
    myapp-9b4987d5-jngkk
    myapp-9b4987d5-jngkk
    myapp-9b4987d5-tcg4p
    myapp-9b4987d5-tcg4p
    myapp-9b4987d5-jngkk
    myapp-9b4987d5-tcg4p
    myapp-9b4987d5-tcg4p
    myapp-9b4987d5-tcg4p
    
    • 验证service到底是什么?
    [root@wf-01 ~]# iptables -vnL -t nat
    Chain PREROUTING (policy ACCEPT 1 packets, 78 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    43607 6509K KUBE-SERVICES  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
      689 43750 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
      481 30744 CNI-HOSTPORT-DNAT  all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
    
    Chain INPUT (policy ACCEPT 1 packets, 78 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    
    Chain OUTPUT (policy ACCEPT 7 packets, 420 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    1070K   64M KUBE-SERVICES  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
     2950  211K DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL
     563K   34M CNI-HOSTPORT-DNAT  all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
    
    Chain POSTROUTING (policy ACCEPT 7 packets, 420 bytes)
     pkts bytes target     prot opt in     out     source               destination         
     696K   42M CNI-HOSTPORT-MASQ  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* CNI portfwd requiring masquerade */
       17  1126 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
    1074K   65M KUBE-POSTROUTING  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */
     205K   12M RETURN     all  --  *      *       172.20.0.0/16        172.20.0.0/16       
       49  3391 MASQUERADE  all  --  *      *       172.20.0.0/16       !224.0.0.0/4         
        4   240 RETURN     all  --  *      *      !172.20.0.0/16        172.20.0.0/24       
        0     0 MASQUERADE  all  --  *      *      !172.20.0.0/16        172.20.0.0/16       
        0     0 CNI-fdae7f8826f90d050b196ad2  all  --  *      *       172.20.0.0/16        0.0.0.0/0            /* name: "mynet" id: "f8addbe803325c3cbfaa04f8635c3958eb01d98e08d2aabb6831ea429c627237" */
    
    Chain CNI-DN-461bdacb794105fd5230f (1 references)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 CNI-HOSTPORT-SETMARK  tcp  --  *      *       172.20.0.63          0.0.0.0/0            tcp dpt:3306
        0     0 CNI-HOSTPORT-SETMARK  tcp  --  *      *       127.0.0.1            0.0.0.0/0            tcp dpt:3306
        0     0 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3306 to:172.20.0.63:3306
    
    Chain CNI-HOSTPORT-DNAT (2 references)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 CNI-DN-461bdacb794105fd5230f  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* dnat name: "cbr0" id: "eb4ac0f03261276c559f1b981aa7c3e8fca1c0882bb36e53517d62905f500ea9" */ multiport dports 3306
    
    Chain CNI-HOSTPORT-MASQ (1 references)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0            mark match 0x2000/0x2000
    
    Chain CNI-HOSTPORT-SETMARK (2 references)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* CNI portfwd masquerade mark */ MARK or 0x2000
    
    

    service_ip存在于每个节点的iptables和ipvs。所以导致无法ping通。但是可以正常使用。如果想在集群外部访问到myapp,可以修改service类型为NodePort。

    [root@wf-01 ~]# kubectl edit svc myapp
    
    # Please edit the object below. Lines beginning with a '#' will be ignored,
    # and an empty file will abort the edit. If an error occurs while saving this file will be
    # reopened with the relevant failures.
    #
    apiVersion: v1
    kind: Service
    metadata:
      creationTimestamp: "2019-05-14T03:14:41Z"
      labels:
        run: myapp
      name: myapp
      namespace: default
      resourceVersion: "863716"
      selfLink: /api/v1/namespaces/default/services/myapp
      uid: 69f9d888-75f6-11e9-8cb1-0050569931cd
    spec:
      clusterIP: 10.68.20.152
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        run: myapp
      sessionAffinity: None
      type: ClusterIP
    status:
      loadBalancer: {}
    
  • 相关阅读:
    前端进击的巨人(一):执行上下文与执行栈,变量对象
    读书笔记(06)
    前端博客收藏
    Nodejs-Can't set headers after they are sent
    Mac OS安装包管理工具Homebrew教程
    webpack自动化构建脚本指令npm run dev/build
    使用express搭建node中间件
    【转】基于localStorage的资源离线和更新技术
    web前端性能优化
    Vue生命周期详解
  • 原文地址:https://www.cnblogs.com/yuhaohao/p/10862421.html
Copyright © 2011-2022 走看看