一 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
- apiVersion: v1
- kind: ReplicationController
- metadata:
- name: frontend
- labels:
- name: frontend
- spec:
- replicas: 1
- selector:
- name: frontend
- template:
- metadata:
- labels:
- name: frontend
- spec:
- containers:
- - name: PHP-Redis
- image: kubeguide/guestbook-PHP-frontend
- env:
- - name: GET_HOSTS_FROM
- value: env
- ports:
- - containerPort: 80
- 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
- apiVersion: v1
- kind: Service
- metadata:
- name: frontend
- labels:
- name: frontend
- spec:
- ports:
- - port: 80
- selector:
- 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 上.
注意: 本实验更详细的步骤参考:.
来源: https://www.cnblogs.com/itzgr/p/12552430.html