当前位置: 首页 > news >正文

建设校园网站意义小说网站建设多少钱

建设校园网站意义,小说网站建设多少钱,学网站开发怎么样,中国国际贸易网K8s in Action 阅读笔记——【5】Services: enabling clients to discover and talk to pods 你已了解Pod以及如何通过ReplicaSets等资源部署它们以确保持续运行。虽然某些Pod可以独立完成工作#xff0c;但现今许多应用程序需要响应外部请求。例如#xff0c;在微服务的情况…K8s in Action 阅读笔记——【5】Services: enabling clients to discover and talk to pods 你已了解Pod以及如何通过ReplicaSets等资源部署它们以确保持续运行。虽然某些Pod可以独立完成工作但现今许多应用程序需要响应外部请求。例如在微服务的情况下Pod通常会响应来自群集内部或群集外部客户端的HTTP请求。 如果Pod想要使用其他Pod提供的服务它们需要找到这些Pod但与非Kubernetes世界不同系统管理员无法在客户端配置文件中指定提供服务的服务器的确切IP地址或主机名因为Pod是临时的。 在Kubernetes中Pod在调度到节点后在启动之前会被分配一个IP地址因此客户端在调用之前无法知道Pod的IP地址。此外由于水平扩展多个Pod可能提供相同的服务每个Pod都有自己的IP地址。因此客户端应该通过单个IP地址访问所有这些Pod而不需要关心支持服务的Pod数量及其IP地址不必维护所有单个Pod IP的列表。 为解决上述问题kubernetes提供了一个资源——Service。 5.1 Introducing services Kubernetes Service是为了创建一个单一和恒定的入口点到一组提供相同服务的Pod而创建的资源。每个服务都有一个IP地址和端口只要该服务存在它们不会改变。客户端可以打开到该IP和端口的连接然后这些连接会被路由到支持该服务的Pod之一。这样服务的客户端不需要知道提供服务的单个Pod的位置从而允许这些Pod随时在集群中移动。 让我们回顾一下这样一个例子你有一个前端Web服务器和一个后端数据库服务器。可能会有多个Pod都充当前端但只有一个后端数据库Pod。你需要解决两个问题才能使系统正常运行 外部客户端需要连接到前端Pod而不需要关心是否只有一个Web服务器或数百个。前端Pod需要连接到后端数据库。因为数据库运行在一个Pod内所以它可能随着时间的推移在集群中移动导致其IP地址发生变化。你不希望每次移动后端数据库时都重新配置前端Pod。 通过为前端Pod创建一个Service并配置为可从集群外部访问你可以公开一个单一且固定的IP地址外部客户端可以通过该地址连接到Pod。同样通过为后端Pod创建一个Service你为后端Pod创建了一个稳定的地址。即使Pod的IP地址发生变化服务地址也不会改变。此外通过创建Service你还可以通过环境变量或DNS轻松地通过名称找到后端服务以便前端Pod找到它。图5.1显示了系统的所有组件两个Service、支持这些Service的两组Pod以及它们之间的相互依赖关系。 现在你已经理解了服务背后的基本思想接下来让我们深入了解如何创建它们。 5.1.1 Creating services 一个服务可以由多个Pod支持连接会在这些支持Pod之间进行负载平衡。但是怎么定义哪些Pod是服务的一部分呢你可能还记得标签选择器在ReplicationController和其他Pod控制器中的使用以指定同一集合内的Pod。服务也使用同样的机制如图5.2所示。 通过kubectl expose创建服务 创建服务最简单的方法是通过kubectl expose命令在第2章中使用它来暴露先前创建的ReplicationController。该命令创建了一个Service资源其Pod选择器与ReplicationController使用的相同从而通过单个IP地址和端口公开所有Pod。 现在你将不使用expose命令而是通过向Kubernetes API服务器发布YAML手动创建服务。 通过YAML文件创建服务 # kubia-svc.yaml apiVersion: v1 kind: Service metadata:name: kubia spec:selector:app: kubiaports:- port: 80targetPort: 8080正在定义一个名为kubia的服务它将接受端口80上的连接并将每个连接路由到与appkubia标签选择器匹配的一个Pod的端口8080。 测试服务 应用上述YAML后可以查看已经创建的Service $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 none 443/TCP 14d kubia ClusterIP 10.97.113.157 none 80/TCP 6s从列表中可以看出分配给该服务的IP地址为10.97.113.157 。因为这是集群IP所以只能从集群内部访问它。服务的主要目的是向集群中的其他pod公开pod组但通常也希望向外部公开服务。 可以通过以下几种方式向集群内的服务发送请求 最显而易见的方式是创建一个 pod将请求发送到服务的集群 IP记录响应。然后可以检查 pod 的日志看看服务的响应是什么。可以 ssh 进入其中一个 Kubernetes 节点使用 curl 命令。可以通过 kubectl exec 命令在一个现有的 pod 中执行 curl 命令。 kubectl exec 命令允许你远程在 pod 中现有的容器内运行任意命令。当你想要检查一个容器的内容、状态和/或环境时这个命令非常有用。使用 kubectl get pods 命令列出 pods 并选择一个 pod 作为 exec 命令的目标在下面的示例中我选择了 kubia-7nog1 pod 作为目标。你还需要获取你的服务的集群 IP例如使用 kubectl get svc 命令。在自己运行下面的命令时请务必使用你自己的 pod 名称和服务 IP 替换它们 $ kubectl get pod NAME READY STATUS RESTARTS AGE kubia-2k9d4 1/1 Running 0 12m kubia-x4tl7 1/1 Running 0 12m kubia-xqvlb 1/1 Running 0 12m $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 none 443/TCP 14d kubia ClusterIP 10.97.113.157 none 80/TCP 12m$ kubectl exec kubia-2k9d4 -- curl -s http://10.97.113.157 Youve hit kubia-xqvlb命令中的双破折线–表示命令选项的结束后面的所有内容都是应该在 pod 中执行的命令。如果命令没有以破折号开头的参数则不需要使用双破折线。但在你的情况下如果你不在这里使用双破折线则 -s 选项会被解释为 kubectl exec 的选项并导致错误 让我们回顾一下运行该命令时发生的情况。图5.3显示了事件序列。你指示Kubernetes在一个pod的容器中执行curl命令。curl向由三个pod支持的服务IP发送了一个HTTP请求。Kubernetes服务代理拦截了连接从三个pod中选择了一个随机的pod并将请求转发给它。运行在该pod中的Node.js然后处理了请求并返回了一个包含pod名称的HTTP响应。curl然后将响应打印到标准输出中kubectl拦截并将其打印到本地机器的标准输出中。 在服务上配置会话关联 如果你多次执行相同的命令每次调用应该都会命中不同的pod因为服务代理通常会将每个连接转发到一个随机选择的后备pod即使连接来自同一个客户端。然而如果你希望某个特定客户端的所有请求都被重定向到同一个pod你可以将服务的sessionAffinity属性设置为ClientIP而不是默认值None如下所示。 这将使服务代理将所有源自同一个客户端IP的请求重定向到同一个pod。作为一个练习你可以创建一个额外的服务并将 session affinity设置为 ClientIP然后尝试发送请求。Kubernetes仅支持两种类型的服务会话亲和性: None和ClientIP。Kubernetes服务不在HTTP级别上操作。服务处理TCP和UDP数据包并不关心它们携带的有效负载。因为cookie是HTTP协议的一种构造所以服务不知道它们这就解释了为什么会话亲和性不能基于cookie。 在同一服务中公开多个端口 你的服务只暴露了一个端口但服务也可以支持多个端口。例如如果你的 pod 监听了两个端口比如说 8080 用于 HTTP8443 用于 HTTPS你可以使用一个单一的服务将端口80和443都转发到 pod 的端口8080和8443上。 创建具有多个端口的服务时必须为每个端口指定名称。 示例文件如下 apiVersion: v1 kind: Service metadata: name: kubia spec: ports: - name: http port: 80 targetPort: 8080 - name: https port: 443 targetPort: 8443 selector: app: kubia标签选择器作为一个整体应用于服务——它不能为每个端口单独配置。如果希望不同的端口映射到pod的不同子集则需要创建两个服务。 使用命名端口 在所有这些示例中你都是通过端口号来引用目标端口的但是你也可以为每个pod的端口指定一个名称并在服务规范中通过名称来引用它。这会使服务规范稍微清晰一些特别是在端口号不为人所知的情况下。 示例如下 # 在一个Pod中命名端口 kind: Pod spec: containers: - name: kubia ports: - name: http containerPort: 8080 - name: https containerPort: 8443然后可以在服务规范中按名称引用这些端口如下所示。 # 在Service中引用已经命名的端口 apiVersion: v1 kind: Service spec: ports: - name: http port: 80 targetPort: http - name: https port: 443 targetPort: https给端口命名能够使你以后在不改变Service配置的情况下更改端口号。 5.1.2 Discovering services 客户端 pods 怎么知道服务的 IP 和端口号呢你需要先创建服务然后手动查找它的 IP 地址并将 IP 地址传递给客户端 pod 的配置选项中吗并不是。Kubernetes 还提供了一些方式让客户端 pod 来发现服务的 IP 地址和端口号。 通过环境变量发现服务 当一个 pod 启动时Kubernetes 会初始化一组环境变量指向每个此时存在的服务。如果在创建客户端 pods 之前就创建了服务这些 pods 中的进程可以通过检查它们的环境变量来获取服务的 IP 地址和端口。 为了查看这些环境变量的内容让我们检查一个正在运行的 pod 中的环境变量。你已经学会了可以使用 kubectl exec 命令在 pod 中运行命令但是由于你在创建 pods 之后才创建了服务服务的环境变量可能还没有被设置。 因此你需要首先解决这个问题。在查看服务的环境变量之前你需要先删除所有的 pods并让 ReplicationController 创建新的 pods $ kubectl delete pod --all pod kubia-2k9d4 deleted pod kubia-x4tl7 deleted pod kubia-xqvlb deleted再来看看重新创建的Pod中的环境变量 $ kubectl exec kubia-ppvdj env PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAMEkubia-ppvdj KUBERNETES_PORTtcp://10.96.0.1:443 KUBIA_PORT_80_TCP_ADDR10.97.113.157 KUBERNETES_SERVICE_HOST10.96.0.1 KUBERNETES_PORT_443_TCP_PROTOtcp KUBERNETES_PORT_443_TCP_PORT443 KUBIA_SERVICE_PORT80 KUBIA_PORT_80_TCPtcp://10.97.113.157:80 KUBIA_PORT_80_TCP_PROTOtcp KUBERNETES_SERVICE_PORT443 KUBIA_PORTtcp://10.97.113.157:80 KUBERNETES_SERVICE_PORT_HTTPS443 KUBERNETES_PORT_443_TCP_ADDR10.96.0.1 KUBIA_SERVICE_HOST10.97.113.157 # 服务的集群IP KUBIA_PORT_80_TCP_PORT80 KUBERNETES_PORT_443_TCPtcp://10.96.0.1:443 NPM_CONFIG_LOGLEVELinfo NODE_VERSION7.9.0 YARN_VERSION0.22.0 HOME/root通过DNS发现服务 还记得在第三章中当你列出 kube-system 命名空间中的 pods 吗其中一个 pod 叫做 kube-dns。kube-system 命名空间还包括与该名称相同的相应服务。 正如其名称所示该 pod 运行 DNS 服务器所有在集群中运行的其他 pods 都会自动配置为使用该 DNS 服务器Kubernetes 通过修改每个容器的 /etc/resolv.conf 文件来实现这一点。在 pod 中运行的进程执行的任何 DNS 查询都将由 Kubernetes 自己的 DNS 服务器处理该 DNS 服务器知道你的系统中运行的所有服务。 pod是否使用内部DNS服务器可以通过每个pod的规范中的dnsPolicy属性进行配置。 每个服务在内部DNS服务器中获得一个DNS条目知道服务名称的客户机pod可以通过其完全限定域名(FQDN)访问它而不是求助于环境变量。 在Pod容器中运行Shell 你可以使用kubectl exec命令在pod的容器中运行bash(或任何其他shell)。通过这种方式你可以随意探索容器而不必为要运行的每个命令执行kubectl exec。 要正确使用shell你需要将-it选项传递给kubectl exec: $ kubectl exec kubia-ppvdj -it -- bash rootkubia-ppvdj:/#你现在在容器里了。你可以使用curl命令以以下任何一种方式访问kubiaservice rootkubia-ppvdj:/# curl http://kubia.default.svc.cluster.local Youve hit kubia-ppvdj rootkubia-ppvdj:/# curl http://kubia.default Youve hit kubia-ppvdj rootkubia-ppvdj:/# curl http://kubia Youve hit kubia-wxvx6你可以使用服务的名称作为请求 URL 中的主机名来访问服务。因为每个 pod 容器内部的 DNS 解析器配置你可以省略命名空间和 svc.cluster.local 后缀。查看容器中的 /etc/resolv.conf 文件: rootkubia-ppvdj:/# cat /etc/resolv.conf nameserver 10.96.0.10 search default.svc.cluster.local svc.cluster.local cluster.local cs1cloud.internal通过exit命令退出shell 理解为什么不能ping通服务IP 尝试ping通服务IP rootkubia-ppvdj:/# ping kubia PING kubia.default.svc.cluster.local (10.97.113.157): 56 data bytes ^C--- kubia.default.svc.cluster.local ping statistics --- 4 packets transmitted, 0 packets received, 100% packet loss发现无法Ping通这是因为服务的集群 IP 是一个虚拟 IP只有与服务端口结合才有意义。 5.2 Connecting to services living outside the cluster 到目前为止我们已经讨论了由群集内运行的一个或多个 pod 支持的服务。但有些情况下你想通过 Kubernetes 服务功能公开外部服务。而不是让服务重定向到群集中的 pod你希望它重定向到外部 IP 和端口。 这使你能够利用服务负载均衡和服务发现。在群集中运行的客户端 pod 可以像连接内部服务一样连接到外部服务。 5.2.1 Introducing service endpoints 在介绍如何操作之前先进一步解释服务的相关信息。服务并不会直接链接到 pod。相反在它们之间会有一个资源存在——Endpoints 资源。如果在服务上使用了 kubectl describe 命令你可能已经注意到了它的 endpoints如下所示 $ kubectl describe svc kubia Name: kubia Namespace: default Labels: none Annotations: none Selector: appkubia Type: ClusterIP IP Family Policy: SingleStack IP Families: IPv4 IP: 10.97.113.157 IPs: 10.97.113.157 Port: unset 80/TCP TargetPort: 8080/TCP Endpoints: 10.244.1.200:8080,10.244.1.201:8080,10.244.1.202:8080 Session Affinity: None Events: noneEndpoints资源是公开服务的IP地址和端口列表。端点资源和其他Kubernetes资源一样所以你可以用kubectl get命令显示它的基本信息: $ kubectl get endpoints kubia NAME ENDPOINTS AGE kubia 10.244.1.200:8080,10.244.1.201:8080,10.244.1.202:8080 94m尽管pod选择器是在服务规范中定义的但在重定向传入连接时并不直接使用它。相反选择器用于构建ip和端口列表然后将其存储在Endpoints资源中。当客户端连接到服务时服务代理选择其中一个IP和端口对并将传入的连接重定向到在该位置侦听的服务器。 5.2.2 Manually configuring service endpoints 服务端点与服务解耦使它们可以手动配置和更新。如果你创建了一个没有 Pod 选择器的服务Kubernetes甚至不会创建Endpoints资源毕竟没有选择器它不知道要包括哪些Pod在服务中。你需要自己创建Endpoints资源来指定服务的端点列表。要创建具有手动管理端点的服务你需要创建一个Service和一个Endpoints资源。 创建没有选择器的服务 # external-service.yaml apiVersion: v1 kind: Service metadata:# 服务的名称必须与Endpoints的名称匹配name: external-service spec: # 没有定义选择器ports:- port: 80为没有选择器的服务创建端点资源 Endpoints是一个单独的资源而不是服务的属性。因为你没有使用选择器创建服务因此相应的Endpoints资源没有自动创建所以你需要自己创建。如下所示 # external-service-endpoints.yaml apiVersion: v1 kind: Endpoints metadata:# 服务的名称必须与Endpoints的名称匹配name: external-service subsets:- addresses:# 服务将转发连接到的端点的ip- ip: 11.11.11.11 - ip: 22.22.22.22ports:# 端点的目标端口- port: 80Endpoints对象需要与服务具有相同的名称并包含服务的目标IP地址和端口列表。在Service和Endpoints资源都被发送到服务器后该服务就可以像具有Pod选择器的任何常规服务一样使用了。在创建服务之后创建的容器将包含服务的环境变量并且所有连接到其IP:port对的连接将在服务端点之间进行负载均衡。 图5.4显示了三个使用外部端点连接到服务的pod 如果后来你决定将外部服务迁移到在Kubernetes内运行的Pod你可以向服务添加选择器从而使它的Endpoints自动管理。相反地去掉一个Service的选择器就能让Kubernetes停止更新它的Endpoints。这意味着服务的IP地址可以保持不变而服务的实际实现也可以发生变化。 5.2.3 Creating an alias for an external service 不必手动配置服务端点来暴露外部服务还有一种更简单的方法就是通过完全限定域名fully qualified domain name FQDN引用外部服务。 创建ExternalName服务 要创建一个作为外部服务别名的服务你可以创建一个类型字段设置为ExternalName的Service资源。例如假设有一个公共API可用于api.somecompany.com。你可以定义一个指向它的服务如下所示。 # external-service-externalname.yaml apiVersion: v1 kind: Service metadata:name: external-servicenamespace: default spec:type: ExternalName# 服务的完全限定域名externalName: someapi.somecompany.comports:- port: 80创建服务之后Pod可以通过external-service.default.svc.cluster.local域名甚至是externalservice连接到外部服务而无需使用服务的实际FQDN。 5.3 Exposing services to external clients 到目前为止我们只讨论了如何在群集内部将服务提供给 Pod 使用。但是你还想将某些服务例如前端 Web 服务器暴露给外部客户端以便它们可以访问这些服务如图 5.5 所示。 你有几种方式使服务可从外部访问 将服务类型设置为 NodePort——对于 NodePort 服务每个群集节点都会在节点本身上打开一个端口因此得名并将接收到的流量重新定向到底层服务。该服务不仅可以在内部群集 IP 和端口上访问还可以通过所有节点上的专用端口访问。将服务类型设置为 LoadBalancer这是 NodePort 类型的扩展——这使服务通过云基础设施提供的专用负载均衡器可访问。负载均衡器会将流量重定向到所有节点上的节点端口。客户端通过负载均衡器的 IP 连接服务。创建 Ingress 资源这是一种通过单个 IP 地址暴露多个服务的根本不同的机制——它在 HTTP 层级网络层 运作因此可以提供更多的功能。 5.3.1 Using a NodePort service 暴露一组pod给外部客户端的第一种方法是创建一个服务并将其类型设置为NodePort。通过创建一个NodePort服务你让Kubernetes在所有节点上保留一个端口相同的端口号在所有节点上使用并将传入的连接转发给服务中的pod。 这类似于常规服务实际类型为ClusterIP但NodePort服务不仅可以通过服务的内部集群IP访问还可以通过任何节点的IP和保留的节点端口访问。 创建NodePort服务 # kubia-svc-nodeport.yaml apiVersion: v1 kind: Service metadata:name: kubia-nodeportnamespace: default spec:selector:app: kubiatype: NodePortports:- port: 80 # 这是服务的内部集群IP的端口targetPort: 8080 # 目标Pod的端口nodePort: 30123 # 可以通过每个集群节点的端口30123访问该服务。可以将类型设置为NodePort并指定此服务应跨所有集群节点绑定到的节点端口。指定端口不是必需的如果省略它Kubernetes将选择一个随机端口。 测试NodePort服务 可以查看已经创建的NodePort服务 $ kubectl get svc kubia-nodeport NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubia-nodeport NodePort 10.105.54.75 none 80:30123/TCP 59s看 EXTERNAL-IP 列。它显示 表示该服务可以通过任何群集节点的 IP 地址访问。PORT(S) 列显示了集群 IP 的内部端口 (80) 和节点端口 (30123)。该服务可以在以下地址访问 10.105.54.75:80节点一的IP:30123节点二的IP:30123、等等 rootyjq-k8s1:~# curl 10.105.54.75:80 Youve hit kubia-ppvdjrootyjq-k8s1:~# curl 33.33.33.110:30123 Youve hit kubia-ppvdjyjqDESKTOP-NKBDBDM:~$ curl 33.33.33.110:30123 Youve hit kubia-qfwt4图 5.6 显示了你的服务在集群节点的 30123 端口上暴露如果你在 GKE 上运行则适用此情况Minikube 只有一个节点但原理相同。对其中任一端口的传入连接都将重定向到随机选择的一个 pod 上该 pod 可能是正在运行传入连接所在的节点上的那个 pod也可能不是。 30123 端口接收到的连接可能会被转发到第一个节点上运行的 pod 或者第二个节点上运行的 pod 中的其中一个。 5.3.2 Exposing a service through an external load balancer 在云提供商上运行的 Kubernetes 集群通常支持从云基础架构自动提供负载均衡器。你只需要将服务的类型设置为 LoadBalancer 而不是 NodePort。负载均衡器将拥有自己独特的、公开可访问的 IP 地址并将所有连接重定向到你的服务。因此你可以通过负载均衡器的 IP 地址访问你的服务。 如果 Kubernetes 运行在不支持 LoadBalancer 服务的环境中负载均衡器将不会被提供但服务仍将像 NodePort 服务一样运行。这是因为 LoadBalancer 服务是 NodePort 服务的一个扩展。 5.3.3 Understanding the peculiarities of external connections 理解和避免不必要的网络跳跃 当外部客户端通过节点端口连接到服务时这也包括通过负载均衡器首先通过连接的情况随机选择的 pod 可能正在运行与接收连接的节点不同的节点上。需要进行额外的网络跳跃才能到达 pod但这可能并不总是理想的。 你可以通过将服务配置为仅将外部流量重定向到正在运行与接收连接的节点上的 pod来防止这种额外跳跃。这是通过在服务的 spec 部分中设置 externalTrafficPolicy 字段来完成的 spec: externalTrafficPolicy: Local如果一个服务定义包括这个设置并且一个外部连接通过服务的节点端口打开服务代理将选择一个本地运行的 pod。如果不存在本地的 pods则连接将挂起它不会像没有使用这个标注时那样被转发到一个随机的全局 pod。因此你需要确保负载均衡器仅将连接转发到至少有一个这样的 pod 的节点。 使用这个标注也有其他的缺点。通常连接会均匀地分布在所有的 pods 中但是当使用这个标注时情况就不再如此了。 想象一下有两个节点和三个 pods。假设节点 A 运行一个 pod节点 B 运行另外两个。如果负载均衡器均匀地将连接分布在这两个节点上节点 A 上的 pod 将收到所有连接的 50%但节点 B 上的两个 pods 将仅仅每个收到 25如图 5.8 所示。 注意客户端 IP 的非保留 通常情况下当集群内部的客户端连接到服务时支持服务的 pods 可以获得客户端的 IP 地址。但是当连接通过节点端口接收时数据包的源 IP 会被更改因为会对数据包执行源网络地址转换 (Source Network Address TranslationSNAT)。 支持 pod 无法看到实际的客户端 IP这可能会对一些需要知道客户端 IP 的应用程序造成问题。例如对于 web 服务器这意味着访问日志将不会显示浏览器的 IP。 5.4 Exposing services externally through an Ingress resource Ingress入口 使用Ingress其中一个重要的原因是每个 LoadBalancer 服务都需要自己的负载均衡器和公共 IP 地址而一个 Ingress 只需要一个即使提供对数十个服务的访问。当客户端向 Ingress 发送 HTTP 请求时请求中的主机和路径确定将请求转发到哪个服务如图 5.9 所示。Ingress 在网络协议栈HTTP的应用程序层运行并可以提供基于 cookie 的会话亲和性等功能但服务不能提供这些功能。 本集群中使用Istio实现Ingress功能。 5.5 Signaling when a pod is ready to accept connections 如果 pod 的标签与服务的 pod 选择器匹配那么它们将作为服务的endpoints包含在内。当创建一个带有正确标签的新 pod 时它将成为服务的一部分并且请求将开始被重定向到该 pod。但是如果该 pod 暂时还没有准备好立即开始服务请求呢 该 pod 可能需要时间来加载配置或数据或者可能需要执行启动前的一些准备工作以防止第一个用户请求花费太长时间影响用户体验。在这种情况下你不希望立即开始向 pod 发送请求特别是当已经运行的实例可以适当地且快速地处理请求时。因此在Pod完全准备好之前不要将请求转发到正在启动的Pod是有意义的。 5.5.1 Introducing readiness probes 在前一章我们学习了存活探针liveness probes接下来我们介绍就绪探针readiness probes readiness probe 周期性调用来确定特定 pod 是否应该接收客户端请求。当容器的 readiness probe 返回成功时表示容器可以准备接受请求。 就绪探针的类型 跟存活探针类型就绪探针也有三种类型 HTTP GET探针在你指定的容器IP地址、端口和路径上执行HTTP GET请求。如果探针接收到响应并且响应代码不表示错误换句话说如果HTTP响应代码是2xx或3xx则该探针被认为是成功的。如果服务器返回错误响应代码或根本没有响应则探针将被视为失败容器将被重新启动。TCP Socket 探针尝试打开容器指定端口的 TCP 连接。如果连接成功建立探针就算成功。否则容器将会被重启。Exec 探针在容器内部执行任意命令并检查该命令的退出状态码。如果状态码为 0探针就算成功。其他所有状态码都被视为失败。 就绪探针的工作机制 当一个容器被启动时可以配置Kubernetes在执行第一次readiness检查之前等待一段可配置的时间。此后它会定期地调用该探针并根据就绪探针的结果进行操作。如果一个Pod报告它不可用它将被从服务中移除。如果Pod再次变为就绪状态则重新添加。 与存活探针不同的是如果一个容器不能通过就绪探测它不会被杀死或重启。这是存活性和就绪性探针之间的重要区别。存活探针通过终止不健康的容器并将其替换为新的健康的容器来保持Pod的健康状态而就绪探针确保只有准备好为请求提供服务的Pod才能接收它们。这在容器启动后大多是必要的但在容器运行一段时间后也很有用。 正如图5.11中所示如果Pod的就绪检查失败则将其从Endpoints对象中删除。连接到服务的客户端将不会被重定向到Pod。这个效果与Pod根本不匹配服务的标签选择器时的效果相同。 5.5.2 Adding a readiness probe to a pod 向Pod模板中加入就绪探针 当ReplicationController的YAML文件在文本编辑器中打开时在Pod的模板中查找容器规范并将以下就绪性探针定义添加到spec.template.spec.containers下的第一个容器中 就绪性探针将定期在容器内执行命令ls /var/ready。如果文件存在则ls命令返回零退出代码否则返回非零退出代码。如果该文件存在则就绪性探针将成功否则将失败。 观察就绪探测结果 删除现有的Pod新定义的就绪探针就会起作用会发现所有的Pod都没有就绪这是因为他们当作还没有创建文件/var/ready。 $ kubectl get pod NAME READY STATUS RESTARTS AGE kubia-94xhp 0/1 Running 0 57s kubia-hddrx 0/1 Running 0 57s kubia-jnw56 0/1 Running 0 57s通过创建/var/ready文件使其中一个的就绪探测开始返回成功 $ kubectl exec kubia-94xhp -- touch /var/ready$ kubectl get pod NAME READY STATUS RESTARTS AGE kubia-94xhp 0/1 Running 0 112s kubia-hddrx 0/1 Running 0 112s kubia-jnw56 0/1 Running 0 112s可以发现Pod还没有准备好这是为什么呢使用kubectl describe命令来看看Pod $ kubectl describe kubia-94xhp Readiness: exec [ls /var/ready] delay0s timeout1s period10s #success1 #failure3就绪性探针会定期检查默认为每10秒检查一次。因为就绪性探针还没有被调用所以该Pod目前还没有准备好。但是最迟在10秒钟后该Pod应该变为就绪状态并将其IP列为服务的唯一endpoint运行kubectl get endpoints kubia-loadbalancer进行确认。 $ kubectl get pod NAME READY STATUS RESTARTS AGE kubia-94xhp 1/1 Running 0 5m1s kubia-hddrx 0/1 Running 0 5m1s kubia-jnw56 0/1 Running 0 5m1s$ kubectl get endpoints NAME ENDPOINTS AGE kubernetes 33.33.33.110:6443 14d kubia 10.244.1.232:8080 18h kubia-nodeport 10.244.1.232:8080 110m5.6 Using a headless service for discovering individual pods 你已经了解到如何通过服务提供稳定的IP地址让客户端连接到支持每个服务的Pod或其他终点。服务的每个连接被转发到一个随机选择的支持Pod。但是如果客户端需要连接到所有这些Pod如果支持的Pod本身每个都需要连接到所有其他支持Pod通过服务连接显然不是解决这个问题的方法。那么该怎么做呢 为了让客户端连接到所有Pod它需要找出每个单独Pod的IP。一个选项是让客户端调用Kubernetes API服务器并通过API调用获取Pod列表及其IP地址但由于你应该始终努力保持应用程序与Kubernetes松耦合因此使用API服务器并不理想。 幸运的是Kubernetes允许客户端通过DNS查找来发现Pod的IP。通常当你对服务执行DNS查找时DNS服务器会返回单个IP服务的集群IP。但是如果你告诉Kubernetes你对服务不需要集群IP通过在服务规范中将clusterIP字段设置为None来实现则DNS服务器将返回Pod IP而不是单个服务IP。 与返回单个DNSA记录不同DNS服务器将返回该服务的多个A记录每个A记录指向当时支持该服务的单个Pod的IP。因此客户端可以执行简单的DNSA记录查找并获得属于服务的所有Pod的IP。然后客户端可以使用该信息连接到其中的一个、多个或全部。 5.6.1 Creating a headless service 在服务规范中将clusterIP字段设置为None将使服务headless因为Kubernetes不会通过IP分配为其分配集群IP以便客户端可以通过此方式连接到其后面的Pod。现在你将创建一个名为kubia-headless的无头服务。如下所示 # kubia-svc-headless.yaml apiVersion: v1 kind: Service metadata:name: kubia-headlessnamespace: default spec:selector:app: kubiaclusterIP: None # 使服务变得headlessports:- port: 80 # 这是服务的内部集群IP的端口targetPort: 8080 # 目标Pod的端口你可以使用kubectl create命令创建服务然后使用kubectl get和kubectl describe命令查看服务。你会看到它没有集群IP而其Endpoints包括部分匹配其Pod选择器的Pod。我说“部分”因为你的Pod包含一个就绪性探针因此仅将准备就绪的Pod列为服务的终点。在继续之前请确保至少两个Pod报告为就绪状态方法是创建/var/ready文件如同前一个示例中所示 $ kubectl get pod NAME READY STATUS RESTARTS AGE kubia-94xhp 1/1 Running 0 26m kubia-hddrx 1/1 Running 0 26m kubia-jnw56 0/1 Running 0 26m5.6.2 Discovering pods through DNS 现在你的Pod已经就绪可以尝试执行DNS查找以查看是否获得了实际的Pod IP。你需要从其中一个Pod内部进行查找。不幸的是你的kubia容器映像不包含nslookup或dig二进制文件因此无法使用它来执行DNS查找。 你正在尝试的只是从集群内运行的Pod内部执行DNS查找。为什么不基于包含所需二进制文件的映像运行一个新的Pod呢为了执行与DNS相关的操作你可以使用Docker Hub上提供的tutum/dnsutils容器映像该映像包含nslookup和dig二进制文件。要运行Pod你可以通过创建一个YAML描述文件并将其传递给kubectl create的整个过程有一种更快的方式。 创建如下Pod $ kubectl run dnsutils --imagetutum/dnsutils --command -- sleep infinity让我们使用新创建的Pod执行DNS查找 $ kubectl exec dnsutils -- nslookup kubia-headless Server: 10.96.0.10 Address: 10.96.0.10#53Name: kubia-headless.default.svc.cluster.local Address: 10.244.1.232 Name: kubia-headless.default.svc.cluster.local Address: 10.244.1.231DNS服务器为kubia-headless.default.svc.cluster.local FQDN返回了两个不同的IP地址。这些IP地址是报告准备就绪的两个Pod的IP地址。你可以使用kubectl get pods -o wide命令来列出显示Pod的IP地址以确认这一点。 这与DNS返回常规非headless服务例如kubia服务的IP地址不同后者返回服务的集群IP地址。尽管headless服务可能与常规服务不同但从客户端的角度来看它们并没有太大区别。即使使用headless服务客户端仍然可以通过连接服务的DNS名称连接到其Pod。但对于headless服务因为DNS返回的是Pod的IP地址所以客户端直接连接到Pod而不是通过服务代理连接。 5.7 Troubleshooting services 如果无法通过服务访问Pod应该按照以下列表进行检查 首先请确保你是从集群内部连接到服务的集群IP而不是从外部连接。不要浪费时间通过ping服务IP来判断服务是否可访问记住服务的集群IP是虚拟IPping它永远不会起作用。如果定义了就绪探针请确保执行成功否则Pod将不是服务的一部分。要确认Pod是否是服务的一部分请使用kubectl get endpoints命令检查相应的Endpoints对象。如果你尝试通过服务的FQDN或部分FQDN例如myservice.mynamespace.svc.cluster.local或myservice.mynamespace来访问服务但无法访问请尝试使用其集群IP而不是FQDN。检查你是否连接到服务公开的端口而不是目标端口。尝试直接连接到Pod IP以确认Pod是否在正确的端口上接受连接。如果甚至无法通过Pod的IP访问应用程序请确保应用程序未仅绑定到localhost。
http://www.hkea.cn/news/14335245/

相关文章:

  • 推荐邵阳网站建设百度云wordpress怎么搭建网站
  • 县级门户网站建设的报告中端网站建设公司
  • 公司网站建设费用包括哪些慈溪网站建设哪家好
  • 网站建设分工表wordpress延迟加载插件
  • 乐辰科技网站建设百度做的网站 如果不做推广了 网站还保留吗
  • 域名转移影响网站访问吗wordpress404页面跳转到首页
  • 视频网站建站费用番禺外贸型网站建设
  • 深圳网站建设是哪个平面设计现在怎么样
  • 苏州企业如何建站代运营公司
  • 网站未备案wordpress代价网站建设
  • 如何对网站进行改版北京做网站推广兼职
  • 温州英文网站建设淘宝客网站开发视频
  • 如何将网站上传到万网主机本地网站搭建软件
  • 网站开发怎么挣外快qq企业邮箱登录入口
  • 河南网站制作工作室深圳公司建立网站
  • 网站前台显示数据库指定分类怎么做php开发助手
  • .net flash网站模板网站建设详细设计
  • 网站加入购物车的代码怎样在百度做网站表白
  • 怎么自己做网站挂到百度上专业微网站建设
  • 医疗手机网站建设手机搭建网站
  • 建站快车的应用场景aso是什么意思
  • 南靖企业网站建设公司做网站好赚钱
  • 个人网站制作流程恒彩装饰和圣都哪个好
  • 做初中物理题目的网站虚拟主机装2个wordpress
  • 灵璧哪有做网站的淘宝联盟推广网站怎么做
  • 关于做外汇现货的网站建设一个网站成本多少
  • 网站程序找人做还是自己做wordpress用户角色
  • WordPress 站点图标链接网站开发慕枫
  • 织梦本地做的网站内网访问不网站建设谈单思路
  • 网站开发市场人员的招聘烟台网站制作哪家好