zokper服务发现_Example:Service连接应用程序

本文档通过一个 nginx 示例详细介绍了 Kubernetes 的网络模型,包括 Pod 的内部通信、Service 的创建及其作用,展示了如何通过 Service 实现 Pod 的高可用和负载均衡。此外,还讨论了如何使用 DNS 和环境变量发现 Service,以及如何保护 Service 的安全,如配置 HTTPS 证书。
摘要由CSDN通过智能技术生成

# Example:Service连接应用程序

# Kubernetes 的网络模型

通过前面教程的学习,我们已经可以将容器化的应用程序在 Kubernetes 中运行起来,并且发布到 Kubernetes 内/外的网络上。

通常,Docker 使用一种 host-private 的联网方式,在此情况下,只有两个容器都在同一个节点(主机)上时,一个容器才可以通过网络连接另一个容器。为了使 Docker 容器可以跨节点通信,必须在宿主节点(主机)的 IP 地址上分配端口,并将该端口接收到的网络请求转发(或代理)到容器中。这意味着,用户必须非常小心地为容器分配宿主节点(主机)的端口号,或者端口号可以自动分配。

在一个集群中,多个开发者之间协调分配端口号是非常困难的。Kubernetes 认为集群中的两个 Pod 应该能够互相通信,无论他们各自在哪个节点上。每一个 Pod 都被分配自己的 “cluster-private-IP”,因此,您无需在 Pod 间建立连接,或者将容器的端口映射到宿主机的端口。因此: Pod 中的任意容器可以使用 localhost 直连同 Pod 中另一个容器的端口

集群中的任意 Pod 可以使用另一的 Pod 的 cluster-private-IP 直连对方的端口,(无需 NAT 映射)

本文档的后续章节使用了一个 nginx server 的例子,详细阐述了如何使用这种网络模型发布 Service。

# 在集群中部署 Pod

在前面的学习中,我们已经部署过 nginx 应用,此处,我们将该应用再部署一次,并将关注点放在网络连接方面(请留意该 Pod 指定了一个 containerPort)。 创建文件 run-my-nginx.yaml,文件内容如下 执行以下命令,部署 Pod 并检查运行情况:

输出结果如下: 执行命令 kubectl get pods -l run=my-nginx -o yaml | grep podIP, 检查 Pod 的 IP 地址,输出结果如下:

在集群中的任意节点上,您可以执行 curl 10.244.3.4 或 curl 10.244.2.5 获得 nginx 的响应。此时: 容器并没有使用节点上的 80 端口

没有使用 NAT 规则对容器端口进行映射

这意味着,您可以 在同一节点上使用 80 端口运行多个 nginx Pod

在集群的任意节点/Pod 上使用 nginx Pod 的 clusterIP 访问 nginx 的 80 端口

同 Docker 一样,Kubernets 中,仍然可以将 Pod 的端口映射到宿主节点的网络地址上(使用 nodePort),但是使用 Kubernetes 的网络模型时,这类需求已经大大减少了。

# 创建 Service

上面的步骤中,我们已经创建了 nginx Pod,运行在集群的 IP 地址空间。您可以直接通过 Pod 的地址访问其端口,但是如果某一个 Pod 终止了该怎么办?Pod 因为故障或其他原因终止后,Deployment Controller 将创建一个新的 Pod 以替代该 Pod,但是 IP 地址将发生变化。Kubernetes Service 解决了这样的问题。

Kubernetes Service: 定义了集群中一组 Pod 的逻辑集合,该集合中的 Pod 提供了相同的功能

被创建后,获得一个唯一的 IP 地址(ClusterIP)。直到该 Service 被删除,此地址不会发生改变

Pod 可以直接连接 Service IP 地址上的端口,且发送到该 IP 地址的网络请求被自动负载均衡分发到 Service 所选取的 Pod 集合中

执行命令 kubectl expose deployment/my-nginx 可以为上面的两个 nginx Pod 创建 Service,输出结果如下所示:

该命令等价于 kubectl apply -f nginx-svc.yaml,其中 nginx-svc.yaml 文件的内容如下所示:

该 yaml 文件将创建一个 Service: 该 Service 通过 label selector 选取包含 run: my-nginx 标签的 Pod 作为后端 Pod

该 Service 暴露一个端口 80(spec.ports[*].port)

该 Service 将 80 端口上接收到的网络请求转发到后端 Pod 的 80 (spec.ports[*].targetPort)端口上,支持负载均衡

执行命令 kubectl get svc my-nginx,输出结果如下所示:

Service 的后端 Pod 实际上通过 Endpoints 来暴露。Kubernetes 会持续检查 Service 的 label selector spec.selector,并将符合条件的 Pod 更新到与 Service 同名(my-nginx)的 Endpoints 对象。如果 Pod 终止了,该 Pod 将被自动从 Endpoints 中移除,新建的 Pod 将自动被添加到该 Endpoint。

执行命令 kubectl describe svc my-nginx,输出结果如下,请注意 Endpoints 中的 IP 地址与上面获得的 Pod 地址相同:

执行命令 kubectl get ep my-nginx,输出结果如下:

此时,您可以在集群的任意节点上执行 curl 10.0.162.149:80,通过 Service 的 ClusterIP:Port 访问 nginx。

TIP

Service 的 IP 地址是虚拟地址。请参考 虚拟 IP 的实现

# 访问 Service

Kubernetes 支持两种方式发现服务: 环境变量 参考 环境变量

DNS 参考 DNS

TIP

由于如下原因,您可能不想激活 Service 的环境变量发现机制: 可能与应用程序的环境变量冲突

太多的环境变量

只想使用 DNS 等

您可以在 Pod 的定义中,将 enableServiceLinks 标记设置为 false

# 环境变量

针对每一个有效的 Service,kubelet 在创建 Pod 时,向 Pod 添加一组环境变量。这种做法引发了一个 Pod 和 Service 的顺序问题。例如, 执行命令 kubectl exec my-nginx-3800858182-jr4a2 -- printenv | grep SERVICE (您的 Pod 名字可能不一样),输出结果如下:

请注意,此时环境变量中没有任何与您的 Service 相关的内容。因为在本教程的前面部分,我们先创建了 Pod 的副本,后创建了 Service。如果我们删除已有的两个 Pod,Deployment 将重新创建 Pod 以替代被删除的 Pod。此时,因为在创建 Pod 时,Service 已经存在,所以我们可以在新的 Pod 中查看到 Service 的环境变量被正确设置。

执行命令 kubectl delete pods -l run=my-nginx以删除 Pod

执行命令 kubectl get pods -l run=my-nginx -o wide 查看新建Pod,输出结果如下:

执行命令 kubectl exec my-nginx-3800858182-e9ihh -- printenv | grep SERVICE (Pod 重建后,名字将会发生变化。请使用您的 Pod 名),输出结果如下,Service 相关的环境变量已经被正确设置

# DNS

Kubernetes 提供了一个 DNS cluster addon,可自动为 Service 分配 DNS name。如果您参考 www.kuboard.cn 上的文档安装 Kubernetes 集群,则该 addon 已经默认安装。

执行命令 kubectl get services kube-dns --namespace=kube-system 查看该 addon 在您的集群上是否可用,输出结果如下所示:

本章节假设: 您已经按照本文前面的章节创建了 Service(my-nginx)

您已经安装了 DNS Server(CoreDNS cluster addon)

此时,您可以从集群中任何 Pod 中按 Service 的名称访问该 Service。 执行命令 kubectl run curl --image=radial/busyboxplus:curl -i --tty 获得 busyboxplus 容器的命令行终端,该命令输出结果如下所示: 然后,单击回车键,并执行命令 nslookup my-nginx,输出结果如下所示:

执行命令 curl my-nginx:80,可获得 Nginx 的响应。

执行命令 exit 可推出该容器的命令行

执行命令 kubectl delete deployment curl 可删除刚才创建的 curl 测试容器

# 保护 Service 的安全

到目前为止,我们只是从集群内部访问了 nginx server。在将该 Service 公布到互联网时,您可能需要确保该通信渠道是安全的。为此,您必须: 准备 https 证书(购买,或者自签名)

将该 nginx 服务配置好,并使用该 https 证书

配置 Secret,以使得其他 Pod 可以使用该证书

您可按照如下步骤配置 nginx 使用自签名证书: 创建密钥对

将密钥对转换为 base64 编码

创建一个如下格式的 nginxsecrets.yaml 文件,使用前面命令输出的 base64 编码替换其中的内容(base64编码内容不能换行)(请使用前面两行命令生成的结果替换 nginx.crt 和 nginx.key 的内容,)

使用该文件创建 Secrets

输出结果为:

修改 nginx 部署,使 nginx 使用 Secrets 中的 https 证书,修改 Service,使其暴露 80 端口和 443端口。nginx-secure-app.yaml 文件如下所示:

关于 nginx-secure-app.yaml 该文件同时包含了 Deployment 和 Service 的定义

nginx server 监听 HTTP 80 端口和 HTTPS 443 端口的请求, nginx Service 同时暴露了这两个端口

nginx 容器可以通过 /etc/nginx/ssl 访问到 https 证书,https 证书存放在 Secrets 中,且必须在 Pod 创建之前配置好。

执行命令使该文件生效:

此时,您可以从任何节点访问该 nginx server

curl -k 在 curl 命令中指定 —k 参数,是因为我们在生成 https 证书时,并不知道 Pod 的 IP 地址,因此,在执行 curl 命令时必须忽略 CName 不匹配的错误。

通过创建 Service,我们将 https 证书的 CName 和 Service 的实际 DNS Name 联系起来,因此,我们可以尝试在另一个 Pod 中使用 https 证书的公钥访问 nginx Service。此时,curl 指令不在需要 -k 参数

创建 curlpod.yaml 文件,内容如下:

执行命令,完成 curlpod 的部署

输出结果如下:

执行 curl,访问 nginx 的 https 端口(请使用您自己的 Pod 名称)

# 暴露 Service

在您的应用程序中,可能有一部分功能需要通过 Service 发布到一个外部的 IP 地址上。Kubernetes 支持如下两种方式:

在上一个章节 保护 Service 的安全 中创建的 Service 已经是 NodePort 类型的了,此时,如果您的节点有公网地址,则 nginx HTTPS 部署已经可以接受来自于互联网的请求了。

执行命令 kubectl get svc my-nginx -o yaml | grep nodePort -C 5,输出结果如下: 结果中的 nodePort 将被标记为红色字体

假设您的某一节点的公网 IP 地址为 23.251.152.56,则您可以使用任意一台可上网的机器执行命令 curl https://23.251.152.56:32453 -k。输出结果为:

Ingress 对于 HTTP、HTTPS 形式的访问推荐使用 Ingress 替代这种用法,参考 Ingress通过互联网访问您的应用

对于 TCP、UDP 等形式的访问,您仍然应该使用 Service NodePort

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值