zoukankan      html  css  js  c++  java
  • k8s系列---service

    来源 : http://blog.itpub.net/28916011/viewspace-2214745/

     service是要通过coreDNS来管理pod的。 

        kube-proxy始终监视着apiserver,获取与service资源的变动状态。一旦发现有service资源发生变动,kube-proxy都要把它转变为当前节点之上的,能够实现service资源调度,包括将客户端资源调度到pod的规则(iptables或者ipvs)。 

        service工作模式有三种:userspace(k8s 1.1版本之前),iptables(k8s 1.10版本之前)和ipvs(k8s 1.11版本之后)

        userspace模型:用户空间模型。k8s 1.11版本用ipvs了,这个比iptables效率高。

    [root@master ~]# kubectl get svc
    NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
    kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        16d
    redis        ClusterIP   10.106.138.181   <none>        6379/TCP       23h
    

      

    [root@master ~]# kubectl delete svc redis 
    service "redis" deleted
    

      

        注意kubernetes这个service千万别删,因为K8s都是通过10.96.0.1这个地址联系的。

    [root@master ~]# kubectl explain svc
    

      

      service类型:

        a)、ExternalName:表示把集群外部的服务引入到集群内部中来,即实现了集群内部pod和集群外部的服务进行通信;

        b)、ClusterIP:只能在集群内部通讯;

        c)、NodePort:可以和集群外部通讯;

        d)、LoadBalancer:这个表示我们把k8s部署在虚拟机上,自动在外部创建负载均衡器。比如在阿里云上,底层是LBAAS。

    ClusterIP

        以前我们使用kubectl expose创建service,下面我们使用清单来创建service。

    [root@master manifests]# cat redis-svc.yaml 
    apiVersion: v1
    kind: Service
    metadata:
      name: redis
      namespace: default
    spec:
      selector:
        app: redis
        role: logstor
      clusterIP: 10.97.97.97 #这个ip可以不指定,让它自动分配
      type: ClusterIP
      ports:
      - port: 6379 #service ip中的端口
        targetPort: 6379 #容器ip中的端口
    

      

    [root@master manifests]# kubectl apply -f redis-svc.yaml 
    service/redis created
    

      

    [root@master manifests]# kubectl get svc
    NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP    16d
    redis        ClusterIP   10.97.97.97   <none>        6379/TCP   1m
    

      

    [root@master manifests]# 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","ports":[{"por...
    Selector:          app=redis,role=logstor
    Type:              ClusterIP
    IP:                10.97.97.97
    Port:              <unset>  6379/TCP
    TargetPort:        6379/TCP
    Endpoints:         10.244.2.65:6379  ##这是pod的ip
    Session Affinity:  None
    Events:            <none>
    

      

    资源记录:SVC_NAME.NAMESPACE_NAME.DOMAIN.LTD 

     集群默认后缀是svc.cluster.local 

    比如我们创建的redis默认名称就是redis.defalut.svc.cluster.local

    NodePort 

    访问路径:client---->NodeIP:NodePoint----->ClusterIP:ServerPort---->PodIP:containerPort

    [root@master manifests]# cat myapp-svc.yaml 
    apiVersion: v1
    kind: Service
    metadata:
      name: myapp
      namespace: default
    spec:
      selector:
        app: myapp
        release: canary
      clusterIP: 10.99.99.99 #这个ip可以不指定,让他自动分配
      type: NodePort
      ports:
      - port: 80 #service ip的端口
        targetPort: 80 #容器ip的端口
        nodePort: 30080 #node节点上端口,这个端口也可以不指定,会自动分配端口
    

      

    [root@master manifests]# kubectl apply -f myapp-svc.yaml 
    service/myapp created
    

      

    [root@master manifests]# kubectl get svc
    NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
    kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        16d
    myapp        NodePort    10.99.99.99   <none>        80:30080/TCP   44s
    redis        ClusterIP   10.97.97.97   <none>        6379/TCP       15m
    

      

    [root@master manifests]# curl http://172.16.1.101:30080/hostname.html
    myapp-deploy-69b47bc96d-79fqh
    [root@master manifests]# curl http://172.16.1.101:30080/hostname.html
    myapp-deploy-69b47bc96d-tc54k
    

      

    注意:172.16.1.101是Node节点的Ip,并且可以看到访问是做了负载均衡的

    下面我们再把来自同一个客户端会话请求用sessionAffinity粘滞到一个固定的pod上,这样就不会出现负载均衡现象了,相当于nginx的 ip_hash功能,如下:

    [root@master manifests]# kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"ClientIP"}}'
    service/myapp patched
    

      

    上面打的补丁也可以直接用edit方法编辑。

    [root@master manifests]# kubectl describe svc myapp
    Session Affinity:         ClientIP
    

      

    再改回负载均衡模式:
    [root@master manifests]# kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"None"}}'
    service/myapp patched
    

      

    无头service 

        我们前面介绍的service是service name解析为cluster ip,然后cluster ip对应到后面的pod ip。 

        而无头service是指service name 直接解析为后面的pod ip。 

        无头就是没有cluster ip牵头了。 

    [root@master manifests]# cat myapp-svc-headless.yaml 
    apiVersion: v1
    kind: Service
    metadata:
      name: myapp-svc
      namespace: default
    spec:
      selector:
        app: myapp #挑选的pod还是myapp。一个pod可以有多个service
        release: canary
      clusterIP: None #None表示是无头service
      ports:
      - port: 80 #service ip中的端口
        targetPort: 80 #容器ip中的端口
    

      

    [root@master manifests]# kubectl apply -f myapp-svc-headless.yaml 
    service/myapp-svc created
    

      

    [root@master manifests]# kubectl get svc
    NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
    kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        16d
    myapp        NodePort    10.99.99.99   <none>        80:30080/TCP   1h
    myapp-svc    ClusterIP   None          <none>        80/TCP         28s
    redis        ClusterIP   10.97.97.97   <none>        6379/TCP       1h
    

      

    看到上面myapp-svc的cluster-ip是空,这就是无头service。

    [root@master manifests]# 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   16d
    

      

    可以看到coreDNS的地址是10.96.0.10

    [root@master manifests]# dig -t A myapp-svc.default.svc.cluster.local. @10.96.0.10
    ; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7_5.1 <<>> -t A myapp-svc.default.svc.cluster.local. @10.96.0.10
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10702
    ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 4096
    ;; QUESTION SECTION:
    ;myapp-svc.default.svc.cluster.local. INA
    ;; ANSWER SECTION:
    myapp-svc.default.svc.cluster.local. 5 IN A10.244.1.63
    myapp-svc.default.svc.cluster.local. 5 IN A10.244.2.51
    ;; Query time: 0 msec
    ;; SERVER: 10.96.0.10#53(10.96.0.10)
    ;; WHEN: Mon Sep 24 00:22:07 EDT 2018
    ;; MSG SIZE  rcvd: 166
    

      

    [root@master manifests]# kubectl get pods -o wide -l app=myapp
    NAME                            READY     STATUS    RESTARTS   AGE       IP            NODE
    myapp-deploy-69b47bc96d-79fqh   1/1       Running   0          1d        10.244.1.63   node1
    myapp-deploy-69b47bc96d-tc54k   1/1       Running   0          1d        10.244.2.51   node2
    

      

    上面看到无头service name直接被解析到另个pod上的ip了。 

    ExternalName

        我们可以用ExternalName对Service名称和集群外部服务地址做一个映射,使之访问Service名称就是访问外部服务。例如下面的例子是将 svc1 和 xxx.xxx.xxx.xxx 做了对等关系。

    kind: Service
    apiVersion: v1
    metadata:
      name: svc1
      namespace: default
    spec:
      type: ExternalName
      externalName: somedomain.org
    

      

     不过,ExternalName 类型的服务适用于外部服务使用域名的方式,缺点是不能指定端口。

        另外,要实现集群内访问集群外服务的这个需求,也是非常简单的。因为集群内的Pod会继承Node上的DNS解析规则。因此只要Node可以访问的服务,Pod中也可以访问到

    =========================================阿里云上某个服务的svc文件例子和解释===========================

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        service.beta.kubernetes.io/alicloud-loadbalancer-address-type: intranet
        service.beta.kubernetes.io/alicloud-loadbalancer-force-override-listeners: 'false'
        service.beta.kubernetes.io/alicloud-loadbalancer-id: xxxxxxx
      labels:
        app: xxxx
      name: xxxx-inner
      namespace: xxxx-dev
    spec:
      clusterIP: 10.129.16.253
      externalTrafficPolicy: Local
      healthCheckNodePort: 30265
      ports:
        - name: azvs-https
          nodePort: 32154
          port: 443
          protocol: TCP
          targetPort: 443
        - name: xxxx
          nodePort: 32470
          port: 80
          protocol: TCP
          targetPort: 8180
      selector:
        app: xxxx
      sessionAffinity: None
      type: LoadBalancer
    status:
      loadBalancer:
        ingress:
          - ip: 10.250.7.77
    externalTrafficPolicy: Local  表示此服务是否希望将外部流量路由到节点本地或集群范围的端点。
    有两个可用选项:”Cluster”(默认)和 “Local”。
    ”Cluster” 隐藏了客户端源 IP,可能导致第二跳到另一个节点,但具有良好的整体负载分布。
    “Local” 保留客户端源 IP 并避免 LoadBalancer 和 NodePort 类型服务的第二跳,但存在潜在的不均衡流量传播风险
    大白话就是:“Local 会在某个节点上把流量引过来,SLB上只能看到该端口通的那个节点,而Cluster把流量分到后面的所有work节点,阿里的SLB上能看到所有的work节点”


    service.beta.kubernetes.io/alicloud-loadbalancer-address-type: intranet  表示内部,把intranet 改成internet就是外部
    service.beta.kubernetes.io/alicloud-loadbalancer-force-override-listeners: 'false'  是否强制覆盖的意思

    service.beta.kubernetes.io/alicloud-loadbalancer-id: xxxxxxx  这个就是你的SLB的id
     
     
  • 相关阅读:
    c++语法(2)
    c++语法(1)
    前端之 BOM和DOM
    JavaScript
    CSS属性相关(续)
    CSS属性相关
    CSS选择器
    前端之CSS
    HTML常用标签
    HTML介绍
  • 原文地址:https://www.cnblogs.com/dribs/p/10281018.html
Copyright © 2011-2022 走看看