039.集群网络-Pod和SVC网络实践
程序员文章站
2022-06-26 13:59:49
一Pod和SVC网络 1.1实践准备及原理 Docker实现了不同的网络模式,Kubernetes也以一种不同的方式来解决这些网络模式的挑战。本完整实验深入剖析Kubernetes在网络层是如何实现及工作的。 实验节点架构: 如上图所示,Kubernetes的网络模型要求每个Node上的容器都可 ......
一 pod和svc网络
1.1 实践准备及原理
docker实现了不同的网络模式,kubernetes也以一种不同的方式来解决这些网络模式的挑战。本完整实验深入剖析kubernetes在网络层是如何实现及工作的。
实验节点架构:
如上图所示,kubernetes的网络模型要求每个node上的容器都可以相互访问。默认的docker网络模型提供了一个ip地址段是172.17.0.0/16的docker0网桥。每个容器都会在这个子网内获得ip地址,并且将docker0网桥的ip地址(172.17.42.1)作为其默认网关。需要注意的是,docker宿主机外面的网络不需要知道任何关于这个172.17.0.0/16的信息或者知道如何连接到其内部,因为docker的宿主机针对容器发出的数据,在物理网卡地址后面都做了ip伪装masquerade(隐含nat)。也就是说,在网络上看到的任何容器数据流都来源于那台docker节点的物理ip地址。这里所说的网络都指连接这些主机的物理网络。
默认的docker网络模型简单便捷,但需要依赖端口映射的机制。在kubernetes的网络模型中,每台主机上的docker0网桥都是可以被路由到的。也就是说,在部署了一个pod时,在同一个集群内,各主机都可以访问其他主机上的pod ip,并不需要在主机上做端口映射。
因此,可以在网络层将kubernetes的节点看作一个路由器,其网络架构如下:
二 pod和svc实验
2.1 检查环境
[root@k8smaster02 ~]# ifconfig #node1上检查网络地址
由上可知,有一个docker0网桥和一个本地eth0地址的网络端口。
2.2 创建rc
[root@k8smaster01 study]# vi frontend-controller.yaml
1 apiversion: v1 2 kind: replicationcontroller 3 metadata: 4 name: frontend 5 labels: 6 name: frontend 7 spec: 8 replicas: 1 9 selector: 10 name: frontend 11 template: 12 metadata: 13 labels: 14 name: frontend 15 spec: 16 containers: 17 - name: php-redis 18 image: kubeguide/guestbook-php-frontend 19 env: 20 - name: get_hosts_from 21 value: env 22 ports: 23 - containerport: 80 24 hostport: 80
[root@k8smaster01 study]# kubectl create -f frontend-controller.yaml
2.3 再次检查网络
[root@k8smaster01 study]# kubectl get pods -o wide
kubernetes为这个pod找了一个主机172.24.8.71(k8smaster01) 来运行它。另外,这个pod获得了一个在k8smaster01的docker0网桥上的ip地址。
[root@k8smaster01 study]# docker ps #k8smaster01上查看正在运行的容器
第2个运行的是一个google_containers/pause:latest的镜像,而且这个容器已经做了端口映射。
[root@k8smaster01 study]# docker inspect c6578085541b | grep networkmode #查看容器的网络模型
"networkmode": "default",
[root@k8smaster01 study]# docker inspect da8251102c93 | grep networkmode
"networkmode": "container:c6578085541b6f47ab624134d0ed0be352b30b42379493a71a8fc913d829989c",
解释:第1个容器是运行了“google_containers/pause:latest”镜像的容器,它使用了docker默认的网络模型bridge(默认网络模型即为桥接);
第2个容器,也就是在rc/pod中定义运行的php-redis容器,使用了非默认的网络配置和映射容器的模型,指定了映射目标容器为“google_containers/pause:latest”。
2.4 网络模型释义
首先,一个pod内的所有容器都需要共用同一个ip地址,这就意味着一定要使用网络的容器映射模式。然而,为什么不能只启动第1个pod中的容器,而将第2个pod中的容器关联到第1个容器呢?
kubernetes主要基于如下两个觉得考虑:
首先,如果在pod内有多个容器的话,则可能很难连接这些容器;
其次,后面的容器还要依赖第1个被关联的容器,如果第2个容器关联到第1个容器,且第1个容器异常的话,第2个容器也将异常。
启动一个基础容器,然后将pod内的所有容器都连接到基础容器相对容易。因为只需要为基础的这个google_containers/pause容器执行端口映射规则,这也简化了端口映射的过程。所以启动pod后的网络模型类似下图:
实际上,应用容器直接监听了这些端口,和google_containers/pause容器共享了同一个网络堆栈。这就是为什么在pod内部实际容器的端口映射都显示到google_containers/pause容器上了。
[root@k8smaster01 study]# docker port c6578085541b #通过dockerport命令来检验端口转发
80/tcp -> 0.0.0.0:80
综上所述,google_containers/pause容器实际上只是负责接管这个pod的endpoint。
2.5 发布svc
service允许我们在多个pod之间抽象一些服务,而且服务可以通过提供在同一个service的多个pod之间的负载均衡机制来支持水平扩展。
[root@k8smaster01 study]# vi frontend-service.yaml
1 apiversion: v1 2 kind: service 3 metadata: 4 name: frontend 5 labels: 6 name: frontend 7 spec: 8 ports: 9 - port: 80 10 selector: 11 name: frontend
[root@k8smaster01 study]# kubectl create -f frontend-service.yaml
[root@k8smaster01 study]# kubectl get svc
name type cluster-ip external-ip port(s) age
frontend clusterip 10.254.176.53 <none> 80/tcp 45s
释义:如上可知kubernetes集群已经为这个服务分配了一个虚拟ip地址10.254.176.53,这个ip地址是在kubernetes的portal network中分配的。 而这个portal network的地址范围是我们在kubmaster上启动api服务进程时,使用--service-cluster-ip-range=xx命令行参数指定:
[root@k8smaster01 study]# cat /etc/systemd/system/kube-apiserver.service | grep 10.254
--service-cluster-ip-range=10.254.0.0/16 \
注意:这个ip段可以是任何段,只要不和docker0或者物理网络的子网冲突即可。选择任意其他网段的原因是这个网段将不会在物理网络和docker0网络上进行路由。这个portal network针对每一个node都有局部的特殊性,实际上它存在的意义是让容器的流量都指向默认网关(也就是docker0网桥)。
2.6 确认验证
当所有的pod都运行起来,service将会把客户端请求负载分发到包含“name=frontend”标签的所有pod上。
注意:本实验更详细的步骤参考:。