Kubernetes 是一款流行的容器编排平台,它能够帮助我们自动化管理容器应用。在 Kubernetes 中,容器是运行在 pod 中的,多个容器可以被组合在同一个 pod 中,并且它们可以共享同一个网络命名空间和存储卷。
在这篇文章中,我们将介绍 Kubernetes 中 pod 和容器互相通信的方式,并提供代码示例和实践指导。为了更好地理解 pod 和容器之间的通信,我们需要首先了解 Kubernetes 中的网络模型。
Kubernetes 网络模型
Kubernetes 的网络模型是基于 Docker 容器网络模型(CNM)的。在 Kubernetes 中,每个 pod 都有一个唯一的 IP 地址,这个 IP 地址是由 Kubernetes 集群中的 CNI 插件负责分配的。每个 pod 中的容器都共享同一个网络命名空间,它们之间可以相互访问。
Kubernetes 支持以下三种网络模式:
- HostNetwork 模式:容器使用主机网络,pod 中的容器可以直接使用主机网络接口。这种模式通常用于需要使用主机网络资源的特殊应用场景。
- Bridge 模式:每个 pod 中都有一个独立的 Linux bridge,pod 中的容器都连接到这个 Linux bridge 上。这种模式是 Kubernetes 默认的网络模式,它可以支持多个 pod 共享一个节点上的 IP 地址和端口号。
- Overlay 模式:使用虚拟网络把不同的节点上的 pod 连接起来,通常会使用基于 VXLAN、Geneve 或者 GRE 协议的 Overlay 网络。
在 Kubernetes 中,pod 中的容器可以使用以下方式与其他 pod 中的容器、服务或者外部网络进行通信。
容器之间通信
在同一个 pod 中的容器可以使用 localhost
或者 pod IP 地址来相互通信。下面是一个简单的示例,我们创建了一个 pod 中包含两个容器的 YAML 配置文件。
-- -------------------- ---- ------- ----------- -- ----- --- --------- ----- ----- ----- ----------- - ----- ---------- ------ ----- - ----- ---------- ------ ------- -------- ------ ----- ----- -----------展开代码
在上面的示例中,我们使用了 nginx
镜像和 busybox
镜像创建了两个容器。busybox
容器使用 ping
命令来向本地主机(即 localhost 或者 pod IP 地址)发送 ICMP 消息。
使用 kubectl apply
命令来创建这个 pod:
$ kubectl apply -f mypod.yaml pod/mypod created
然后可以使用 kubectl logs
命令查看 pod 中 container2
的输出:
$ kubectl logs mypod -c container2 PING 127.0.0.1 (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.036 ms 64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.057 ms 64 bytes from 127.0.0.1: seq=2 ttl=64 time=0.041 ms ...
在上面的输出中,我们可以看到容器 container2
成功向本地主机发送了 ICMP 消息。通过这种方式,同一个 pod 中的容器可以相互通信,并且不需要暴露端口或者使用公共网络。
Pod 之间通信
在 Kubernetes 中,不同的 pod 之间可以使用 Service
资源来实现通信。Service
是 Kubernetes 中抽象出来的一种服务,它是一个稳定的 IP 地址和端口号的组合,可以代表一个或者多个后端 pod。
当 Service
被创建时,Kubernetes 会自动把它的 IP 地址和端口号注入到所有 pod 的环境变量中。有了这些信息,pod 就可以使用这个 Service 的稳定 IP 地址和端口号来访问后端 pod。
下面是一个简单的示例,我们创建了两个 pod,每个 pod 中都运行了一个 busybox
容器。
-- -------------------- ---- ------- ----------- -- ----- --- --------- ----- ---- ----- ----------- - ----- ---------- ------ ------- -------- ------ ----- ------ ----- -- ---- ------- ----- -- ------ --- ----------- -- ----- --- --------- ----- ---- ----- ----------- - ----- ---------- ------ ------- -------- ------ ----- ------ ----- -- ---- -------- ----- -- ------展开代码
在上面的示例中,我们在 pod1
中运行了一个循环脚本,不停地输出 pod1
;在 pod2
中运行了一个循环脚本,不停地访问 pod1
的 80
端口,并输出结果。请注意,在 pod2
中直接使用 pod1:80
来访问 pod1
,这是因为 Kubernetes 已经为我们定义了一个 Service 来对 pod 进行路由。
使用 kubectl apply
命令来创建这两个 pod:
$ kubectl apply -f pods.yaml pod/pod1 created pod/pod2 created
然后可以使用 kubectl logs
命令查看 pod2
的输出:
$ kubectl logs pod2 -c container1 pod1 pod1 pod1 ...
在上面的输出中,我们可以看到 pod2
成功访问了 pod1
,并输出了 pod1
的内容。通过使用 Service
资源,不同的 pod 之间可以相互通信,并且不需要了解后端 pod 的具体 IP 地址。
容器与外部网络通信
在 Kubernetes 中,pod 中的容器可以使用以下方式与外部网络进行通信。
NodePort 网络模式
NodePort 模式是一种简单的方式,在指定节点上开放指定的端口号,并转发到 Service 的稳定 IP 地址和端口号。这种方式适合于需要从外部网络访问 Kubernetes 集群中的服务。
在 NodePort 模式下,Kubernetes 会在每个节点上创建一个端口范围,这个范围可以是 30000
到 32767
。我们可以通过 Service 的 spec.ports.nodePort
属性来指定节点上的端口号。
下面是一个简单的示例,我们创建了一个 httpd
pod 和一个 Service
,并使用 NodePort 网络模式来开放 80
端口。
-- -------------------- ---- ------- ----------- -- ----- --- --------- ----- ----- ----- ----------- - ----- ----- ------ ----- ------ - -------------- -- --- ----------- -- ----- ------- --------- ----- ----- ----- --------- ---- ----- ----- -------- ------ - ----- ---- ----- -- --------- -----展开代码
在上面的示例中,我们使用 httpd
镜像创建了一个 pod,并在 Service 的 spec.ports
中定义了对 httpd
pod 的路由。使用 kubectl get service
命令可以查看 Service 的节点端口:
$ kubectl get service httpd NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE httpd NodePort 10.101.92.130 <none> 80:30080/TCP 36m
可以看到这个 Service 的 PORT(S)
一栏中包含了 80:30080/TCP
,表示将本地的 30080
端口映射到 Service 的 80
端口上。
我们可以使用 curl
命令来测试这个 pod 是否可以被外部网络访问:
$ curl localhost:30080
在上面的命令中,我们使用 localhost:30080
来访问在 Kubernetes 中运行的 httpd
pod。如果输出了预期的内容,则表示容器与外部网络通信成功。
LoadBalancer 网络模式
LoadBalancer 网络模式是在外部网络中创建负载均衡器,然后将请求转发给 Service 的稳定 IP 地址和端口号。这种方式通常用于将 Kubernetes 应用程序暴露给外部网络。
在 LoadBalancer 模式下,Kubernetes 会自动为我们创建一个负载均衡器,负载均衡器会把请求转发到 Service 的稳定 IP 地址和端口号。同时,Kubernetes 也会自动为 Service 分配一个外部 IP 地址,这个 IP 地址可以由外部网络访问 Service。
下面是一个简单的示例,我们创建了一个 httpd
pod 和一个 Service
,并使用 LoadBalancer 网络模式来暴露 HTTP 服务。
-- -------------------- ---- ------- ----------- -- ----- --- --------- ----- ----- ----- ----------- - ----- ----- ------ ----- ------ - -------------- -- --- ----------- -- ----- ------- --------- ----- ----- ----- --------- ---- ----- ----- ------------ ------ - ----- ---- ----- -- ----------- --展开代码
在上面的示例中,我们使用 httpd
镜像创建了一个 pod,并在 Service 的 spec.ports
中定义了对 httpd
pod 的路由。使用 kubectl get service
命令可以查看 Service 的外部 IP 地址:
$ kubectl get service httpd NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE httpd LoadBalancer 10.101.173.107 10.0.2.15 80:31914/TCP 41m
可以看到 Service 的 EXTERNAL-IP
一栏包含了分配给它的 IP 地址 10.0.2.15
。我们可以使用这个 IP 地址来访问在 Kubernetes 中运行的 httpd
pod。
总结
在 Kubernetes 中,pod 和容器之间可以使用不同的方式互相通信。容器之间可以使用 localhost
或者 pod IP 地址来相互通信;pod 之间可以使用 Service
并使用稳定的 IP 地址和端口号进行通信;容器可以使用 NodePort 或者 LoadBalancer 网络模式来与外部网络通信。
针对不同的场景和需求,我们可以选择不同的通信方式,在不同方式之间进行平衡。正确地使用 Kubernetes 中的网络模型,可以帮助我们更好地管理和部署容器应用,并提高应用程序的可扩展性和可靠性。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6650182ad3423812e4222fa1