Kubernetes中如何使用ClusterDNS进行服务发现?

原创 半夏透心凉 [云原生技术爱好者社区](javascript:void(0)😉 2019-12-26

“本文主要介绍了kubernetes网络结构、pod和service之间域名通信”

  • 常见使用场景

​ 在常见集群中经常会出现服务之间彼此通过http或者tcp、RPC的形式进行访问,在kubernetes集群中,pod和pod、service之间的网络是互通的,但是service的ip地址是存储在etcd中,如果创建完成之后,一直使用apply,那么ip不会变化,如果不小心执行了kubectl delete -f yaml,那么service的ip将发生变化,如果此ip被很多服务使用,将会带来灾难性的修改,这时我们可以借助kube-dns解决问题。

  • kubernetes网络模型

​ 一个完整的Kubernetes集群应该包含三层网络,首先第一层是mater和node节点之间的网络,这个网络需要在部署kubernetes集群之前配置完成,
第二层网络是pod的网络通过kubenet或者cni插件实现,用于pod之间或者内部的通信,集群中的所有pod均处在同一个网络平面空间内,可以直接通信,
第三层网络是Service资源的网络,是一个虚拟网络,用于为Kubernetes集群配置IP地址,但此地址并不配置于任何主机或者容器的网络接口之上,而是通过kubeproxy配置为iptables规则,将发往该地址的所有流量调度至后端的pod之上。

  • Kubernetes网络中常见四种通信方式
    1 同一个pod的内部通信;
    2 各个pod彼此通信;
    3 pod和service的通信;
    4 集群外部流向service的通信。

看到上面这些你就不难理解为什么在yaml中存在port,targetPort,nodePort?

containerPort:一个信息性数据,他只是为集群提供一个可以快速了解相关pod可以访问端口的途径,而且显式指定容器端口,无论你是否指定都不影响其他节点上的客户端pod对其进行访问。

port:服务提供端口,用于kubernetes集群内部服务访问。

targetPort:pod目标端口,如果不设置使用默认port端口,port和nodePort的数据通过这个端口进入到Pod内部,Pod里面的containers的端口映射到这个端口,提供服务。

nodePort:外部用户访问端口

  • kubernetes中如何发现服务?

    通过如下yaml创建两个nginx服务

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
         labels:
          app: nginx
        spec:
          containers:
          - name: nginx
            image: docker.hub.com/ops/openresty:1.15
            ports:
            - containerPort: 80
    

    通过进入服务内部进行访问nginx服务

    kubectl exec nginx-deployment-74fd67c98d-26j9r -it /bin/bash
    
    [root@nginx-deployment-74fd67c98d-26j9r /]# curl 10.244.1.49:80  
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to OpenResty!</title>
    <style>
        body {
            width: 35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to OpenResty!</h1>
    <p>If you see this page, the OpenResty web platform is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="https://openresty.org/">openresty.org</a>.<br/>
    Commercial support is available at
    <a href="https://openresty.com/">openresty.com</a>.</p>
    
    <p><em>Thank you for flying OpenResty.</em></p>
    </body>
    </html>
    

    看到这里可能有人要说,这简直没法用,每次创建pod ip都要改变,总不能每次手动修改ip地址访问吧?如此访问,我怎么才能做负载均衡?

  • 如何通过service解决问题负载问题

    创建如下service,通过selector选择nginx服务

    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
      labels:
        app: nginx
    spec:
      type: NodePort
      ports:
      - name: http
        port: 80
        targetPort: 80
        nodePort: 30007
      - name: https
        port: 443
        targetPort: 443
        nodePort: 30003
      selector:
        app: nginx
    

    查看服务对应服务ip,并访问服务。

    [root@k8s-m opt]# kubectl get svc nginx-service
    NAME            TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
    nginx-service   NodePort   10.99.251.122   <none>        80:30007/TCP,443:30003/TCP   29h
    [root@k8s-master opt]# 
    [root@nginx-deployment-745fd7c98d-2xj9r /]# curl 10.99.251.122:80
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to OpenResty!</title>
    <style>
        body {
            width: 35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to OpenResty!</h1>
    <p>If you see this page, the OpenResty web platform is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="https://openresty.org/">openresty.org</a>.<br/>
    Commercial support is available at
    <a href="https://openresty.com/">openresty.com</a>.</p>
    
    <p><em>Thank you for flying OpenResty.</em></p>
    </body>
    </html>
    

    通过如上service的方式已经实现了负载均衡,但是我们在服务没有创建之前仍然是不知道服务对外提供服务IP是什么?当然我们可以在service的yaml中内置ClusterIP,但是即使如此,还可能会出现ip占用的问题。

  • kube-dns是如何解决如上问题的?

    在创建pod资源时,kubelet会将其所属名称空间中的所有service对象以环境变量的形式注入其中。如下所示:

    [root@nginx-deployment-745fd7c98d-2xj9r /]# printenv|grep NGINX
    NGINX_SERVICE_PORT_443_TCP=tcp://10.99.251.123:443
    NGINX_SERVICE_PORT_80_TCP_PORT=80
    NGINX_SERVICE_PORT_443_TCP_PORT=443
    NGINX_SERVICE_PORT_80_TCP_PROTO=tcp
    NGINX_SERVICE_PORT_443_TCP_PROTO=tcp
    NGINX_SERVICE_SERVICE_HOST=10.99.251.123
    NGINX_SERVICE_SERVICE_PORT_HTTP=80
    NGINX_SERVICE_PORT=tcp://10.99.251.123:80
    NGINX_SERVICE_PORT_80_TCP=tcp://10.99.251.123:80
    NGINX_SERVICE_SERVICE_PORT_HTTPS=443
    NGINX_SERVICE_SERVICE_PORT=80
    NGINX_SERVICE_PORT_80_TCP_ADDR=10.99.251.123
    NGINX_SERVICE_PORT_443_TCP_ADDR=10.99.251.123
    

    所以我们可以直接通过如下形式进行访问(当然如果存在集群内服务调用的话,我们就可以直接配置成域名的形式):

    [root@nginx-deployment-745fd7c98d-2xj9r /]# curl nginx-service:80
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to OpenResty!</title>
    <style>
        body {
            width: 35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to OpenResty!</h1>
    
  • 域名格式

具体为:<service_name>..svc.<cluster_domain>和<service_name>..<cluster_domain>,当然后面cluster_domain取决于本地/etc/resolv.conf是否配置,如上我的示例就没有使用命名空间也没有配置集群域名,那么我直接service名称就可以直接访问。

  • 总结

    在k8s集群中,服务是运行在Pod中的,Pod的发现和副本间负载均衡是我们面临的问题。我们使用Service解决了负载均衡的问题,但是集群环境中,service经常伴随着ip的变动而变动,得益于kubedns插件,使其可以直接通过域名进行访问。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值