kubernetes Service:让客户端发现pod并与之通信(上)

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
传统型负载均衡 CLB,每月750个小时 15LCU
简介: kubernetes Service:让客户端发现pod并与之通信

1.Service介绍


1.1什么是Service


service是k8s中的一个重要概念,主要是提供负载均衡和服务自动发现。


Service 是由 kube-proxy 组件,加上 iptables 来共同实现的。


1.2.Service的创建


创建Service的方法有两种:


1.通过kubectl expose创建


    #kubectl expose deployment nginx --port=88 --type=NodePort --target-port=80 --name=nginx-service 这一步说是将服务暴露出去,实际上是在服务前面加一个负载均衡,因为pod可能分布在不同的结点上。–port:暴露出去的端口–type=NodePort:使用结点+端口方式访问服务–target-port:容器的端口–name:创建service指定的名称


    2.通过yaml文件创建


    创建一个名为nginx-service的服务,将在端口88接收请求并将链接路由到具有标签选择器是app=nginx的pod的80端口上


    使用kubectl create来创建serivice


      apiVersion: v1kind: Servicemetadata:  name: nginx-service  labels:     app: nginx   spec:  type: NodePort  ports:  - port: 88  //该服务的可用端口    targetPort: 80    selector:    app: nginx   //具有app=hostnames标签的pod都属于该服务


      1.3.检测服务


      使用如下命令来检查服务:


        [root@k8s-master ~]# kubectl get svc    NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGEnginx-service   NodePort    10.0.0.28    <none>        88:36877/TCP   13s


        2.连接集群外部的服务


        2.1.介绍服务endpoint


        服务并不是和pod直接相连的,介于他们之间的就是Endpoint资源。


        Endpoint资源就是暴露一个服务的IP地址和端口列表。


        通过service查看endpoint方法如下:


          [root@k8s-master ~]# kubectl -n kube-system get svc kube-dnsNAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGEkube-dns   ClusterIP   10.0.0.2     <none>        53/UDP,53/TCP   28d [root@k8s-master ~]# kubectl -n kube-system describe svc kube-dnsName:              kube-dnsNamespace:         kube-systemLabels:            addonmanager.kubernetes.io/mode=Reconcile                   k8s-app=kube-dns                   kubernetes.io/cluster-service=true                   kubernetes.io/name=CoreDNSAnnotations:       kubectl.kubernetes.io/last-applied-configuration:                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{"prometheus.io/port":"9153","prometheus.io/scrape":"true"},"labels":{"addon...                   prometheus.io/port: 9153                   prometheus.io/scrape: trueSelector:          k8s-app=kube-dnsType:              ClusterIPIP:                10.0.0.2Port:              dns  53/UDPTargetPort:        53/UDPEndpoints:         172.17.80.4:53Port:              dns-tcp  53/TCPTargetPort:        53/TCPEndpoints:         172.17.80.4:53 //代表服务endpoint的pod的ip和端口列表Session Affinity:  NoneEvents:            <none>


          直接查看endpoint信息方法如下:


            [root@k8s-master ~]# kubectl -n kube-system get endpoints kube-dnsNAME       ENDPOINTS                       AGEkube-dns   172.17.80.4:53,172.17.80.4:53   28d[root@k8s-master ~]# kubectl -n kube-system describe  endpoints kube-dnsName:         kube-dnsNamespace:    kube-systemLabels:       addonmanager.kubernetes.io/mode=Reconcile              k8s-app=kube-dns              kubernetes.io/cluster-service=true              kubernetes.io/name=CoreDNSAnnotations:  endpoints.kubernetes.io/last-change-trigger-time: 2020-01-01T23:38:21+08:00Subsets:  Addresses:          172.17.80.4  NotReadyAddresses:  <none>  Ports:    Name     Port  Protocol    ----     ----  --------    dns      53    UDP    dns-tcp  53    TCPEvents:  <none>


            2.2.手动配置服务的endpoint


            如果创建pod时不包含选择器,则k8s将不会创建endpoint资源。这样就需要创建endpoint来指的服务的对应的endpoint列表。


            service中创建endpoint资源,其中一个作用就是用于service知道包含哪些pod。


            640.png


            3.将服务暴露给外部客户端


            有3种方式在外部访问服务:


              1.将服务的类型设置成NodePort;

              2.将服务的类型设置成LoadBalance;

              3.创建一个Ingress资源。


            3.1.使用nodeport类型的服务


            NodePort 服务是引导外部流量到你的服务的最原始方式。NodePort,正如这个名字所示,在所有节点(虚拟机)上开放一个特定端口,任何发送到该端口的流量都被转发到对应服务。


            YAML 文件类似如下:


              apiVersion: v1kind: Servicemetadata:  name: nginx-service  labels:     app: nginxspec:  type: NodePort  //为NodePort设置服务类型  ports:  - port: 88    targetPort: 80    nodePort: 30123   //通过集群节点的30123端口可以访问服务  selector:    app: nginx


              这种方法有许多缺点:


                1.每个端口只能是一种服务


                2.端口范围只能是 30000-32767


              如果节点/VM 的 IP 地址发生变化,你需要能处理这种情况


              基于以上原因,我不建议在生产环境上用这种方式暴露服务。如果你运行的服务不要求一直可用,或者对成本比较敏感,你可以使用这种方法。这样的应用的最佳例子是 demo 应用,或者某些临时应用。


              3.2.通过Loadbalance将服务暴露出来


              LoadBalancer 服务是暴露服务到 internet 的标准方式。在 GKE 上,这种方式会启动一个 Network Load Balancer[2],它将给你一个单独的 IP 地址,转发所有流量到你的服务

              通过如下方法来定义服务使用负载均衡


                apiVersion: v1kind: Servicemetadata:  name: loadBalancer-nginxspec:  type: LoadBalancer  //该服务从k8s集群的基础架构获取负载均衡器  ports:  - port: 80     targetPort: 8080  selector:    app: nginx


                何时使用这种方式?


                如果你想要直接暴露服务,这就是默认方式。所有通往你指定的端口的流量都会被转发到对应的服务。它没有过滤条件,没有路由等。这意味着你几乎可以发送任何种类的流量到该服务,像 HTTP,TCP,UDP,Websocket,gRPC 或其它任意种类。


                这个方式的最大缺点是每一个用 LoadBalancer 暴露的服务都会有它自己的 IP 地址,每个用到的 LoadBalancer 都需要付费,这将是非常昂贵的。


                4.通过Ingress暴露服务


                为什么使用Ingress,一个重要的原因是LoadBalancer服务都需要创建自己的负载均衡器,以及独有的公有Ip地址,而Ingress只需要一个公网Ip就能为许多服务提供访问。


                640.png


                4.1.创建Ingress资源


                Ingress 事实上不是一种服务类型。相反,它处于多个服务的前端,扮演着“智能路由”或者集群入口的角色。


                你可以用 Ingress 来做许多不同的事情,各种不同类型的 Ingress 控制器也有不同的能力。


                640.png


                Ingress 组成


                • ingress controller
                  将新加入的Ingress转化成Nginx的配置文件并使之生效
                • ingress服务
                  将Nginx的配置抽象成一个Ingress对象,每添加一个新的服务只需写一个新的Ingress的yaml文件即可
                • Nginx:实现负载均衡到pod的集合
                • Ingress Controller:从集群api获取services对应pod的ip到nginx配置文件中
                • Ingress:为nginx创建虚拟主机


                了解Ingress 工作原理


                • ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化
                • 然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service或者单个域名多个location形式,生成一段nginx配置
                • 再动态注入到nginx-ingress-control的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx/nginx.conf文件中
                • 然后reload一下使配置生效。


                640.png


                何时使用这种方式?


                Ingress 可能是暴露服务的最强大方式,但同时也是最复杂的。Ingress 控制器有各种类型,包括 Google Cloud Load Balancer, Nginx,Contour,Istio,等等。它还有各种插件,比如 cert-manager[5],它可以为你的服务自动提供 SSL 证书。


                如果你想要使用同一个 IP 暴露多个服务,这些服务都是使用相同的七层协议(典型如 HTTP),那么Ingress 就是最有用的。如果你使用本地的 GCP 集成,你只需要为一个负载均衡器付费,且由于 Ingress是“智能”的,你还可以获取各种开箱即用的特性(比如 SSL、认证、路由等等)。


                4.2 如何部署配置Ingress


                ingress的部署,需要考虑两个方面:


                ingress-controller是作为pod来运行的,以什么方式部署比较好


                ingress解决了把如何请求路由到集群内部,那它自己怎么暴露给外部比较好


                下面列举一些目前常见的部署和暴露方式,具体使用哪种方式还是得根据实际需求来考虑决定


                Deployment+LoadBalancer模式的Service


                如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个type为LoadBalancer的service关联这组pod。大部分公有云,都会为LoadBalancer的service自动创建一个负载均衡器,通常还绑定了公网地址。只要把域名解析指向该地址,就实现了集群服务的对外暴露。


                Deployment+NodePort模式的Service


                同样用deployment模式部署ingress-controller,并创建对应的服务,但是type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口,所以测试的时候可以手动增加type: Nodeport,手动指定端口或者一般会在前面再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境ip地址不变的场景。


                nodePort的部署思路就是通过在每个节点上开辟nodePort的端口,将流量引入进来,而后通过iptables首先转发到ingress-controller容器中(图中的nginx容器),而后由nginx根据ingress的规则进行判断,将其转发到对应的应用web容器中。NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定影响。


                DaemonSet+HostNetwork+nodeSelector


                hostNetwork模式不再需要创建一个nodePort的svc,而是直接在每个节点都创建一个ingress-controller的容器,而且将该容器的网络模式设为hostNetwork。也就是说每个节点物理机的80和443端口将会被ingress-controller中的nginx容器占用。当流量通过80/443端口进入时,将直接进入到nginx中。而后nginx根据ingress规则再将流量转发到对应的web应用容器中。使用hostNetwork的方式,ingress-controller将会使用的是物理机的DNS域名解析(即物理机的/etc/resolv.conf)。而无法使用内部的比如coredns的域名解析


                用DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。比较适合大并发的生产环境使用。


                github提供了两种方式下载ingress部署文件 :


                默认下载最新的yaml

                指定版本号下载对应的yaml

                官方部署文件地址长期更新:https://kubernetes.github.io/ingress-nginx/deploy/

                Deployment+NodePort模式的service


                一、下载nginx-ingress的部署配置文件


                  wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml


                  将镜像拉下来并更改mandatory.yaml中的镜像地址或者去阿里云公开镜像找相关镜像替换


                    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.26.1


                    替换镜像地址


                      sed -i 's#quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1#registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.26.1#g' mandatory.yaml


                      相关实践学习
                      通过Ingress进行灰度发布
                      本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
                      容器应用与集群管理
                      欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
                      相关文章
                      |
                      2月前
                      |
                      存储 Kubernetes Docker
                      【赵渝强老师】Kubernetes中Pod的基础容器
                      Pod 是 Kubernetes 中的基本单位,代表集群上运行的一个进程。它由一个或多个容器组成,包括业务容器、基础容器、初始化容器和临时容器。基础容器负责维护 Pod 的网络空间,对用户透明。文中附有图片和视频讲解,详细介绍了 Pod 的组成结构及其在网络配置中的作用。
                      【赵渝强老师】Kubernetes中Pod的基础容器
                      |
                      2月前
                      |
                      Prometheus Kubernetes 监控
                      深入探索Kubernetes中的Pod自动扩展(Horizontal Pod Autoscaler, HPA)
                      深入探索Kubernetes中的Pod自动扩展(Horizontal Pod Autoscaler, HPA)
                      |
                      2月前
                      |
                      运维 Kubernetes Shell
                      【赵渝强老师】K8s中Pod的临时容器
                      Pod 是 Kubernetes 中的基本调度单位,由一个或多个容器组成,包括业务容器、基础容器、初始化容器和临时容器。临时容器用于故障排查和性能诊断,不适用于构建应用程序。当 Pod 中的容器异常退出或容器镜像不包含调试工具时,临时容器非常有用。文中通过示例展示了如何使用 `kubectl debug` 命令创建临时容器进行调试。
                      |
                      2月前
                      |
                      Kubernetes 调度 容器
                      【赵渝强老师】K8s中Pod中的业务容器
                      Pod 是 Kubernetes 中的基本调度单元,由一个或多个容器组成。除了业务容器,Pod 还包括基础容器、初始化容器和临时容器。本文通过示例介绍如何创建包含业务容器的 Pod,并提供了一个视频讲解。示例中创建了一个名为 &quot;busybox-container&quot; 的业务容器,并使用 `kubectl create -f firstpod.yaml` 命令部署 Pod。
                      |
                      2月前
                      |
                      Kubernetes 容器 Perl
                      【赵渝强老师】K8s中Pod中的初始化容器
                      Kubernetes的Pod包含业务容器、基础容器、初始化容器和临时容器。初始化容器在业务容器前运行,用于执行必要的初始化任务。本文介绍了初始化容器的作用、配置方法及优势,并提供了一个示例。
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(五)
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(五)
                      256 0
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(五)
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(四)
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(四)
                      241 0
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(四)
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(三)
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(三)
                      247 0
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(三)
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(二)
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(二)
                      206 0
                      KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(二)
                      |
                      8天前
                      |
                      Prometheus Kubernetes 监控
                      OpenAI故障复盘 - 阿里云容器服务与可观测产品如何保障大规模K8s集群稳定性
                      聚焦近日OpenAI的大规模K8s集群故障,介绍阿里云容器服务与可观测团队在大规模K8s场景下我们的建设与沉淀。以及分享对类似故障问题的应对方案:包括在K8s和Prometheus的高可用架构设计方面、事前事后的稳定性保障体系方面。

                      热门文章

                      最新文章