kubernetes应用的各种访问方式
1. 通过 Pod 的 IP 地址访问应用
1.1 Pod 的IP地址
每个Pod 都会被分配一个IP地址,比如下面这儿pod的IP地址是 10.1.79.11.
- root@kub-node-0:/home/ubuntu# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE
- my-nginx8-b77fdd7bc-4t2kb 1/1 Running 0 3d 10.1.79.11 172.23.100.6
该 Pod 在某个 node 上有两个容器:
- root@kub-node-2:/home/ubuntu# docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- d199cb090c13 sammyliu8/nginx "nginx -g 'daemon of…" 3 days ago Up 3 days k8s_my-nginx8_my-nginx8-b77fdd7bc-4t2kb_default_cd1425fd-f48a-11e7-a605-fa163e9a22a6_0
- 0c647fb76c0b kubernetes/pause "/pause" 3 days ago Up 3 days k8s_POD_my-nginx8-b77fdd7bc-4t2kb_default_cd1425fd-f48a-11e7-a605-fa163e9a22a6_0
dockerd 会给 pause 容器分配一个ip,这个ip 就是 pod 的ip:
- root@kub-node-2:/home/ubuntu# ip netns exec pause0b ip addr77: eth0@if78: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP group default
- link/ether 02:42:0a:01:4f:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
- inet 10.1.79.11/24 brd 10.1.79.255 scope global eth0
- valid_lft forever preferred_lft forever
而 nginx 容器是跟 pause 容器共享 network namespace 的:
- root@kub-node-2:/home/ubuntu# ip netns exec nginx13 ip addr
- 77: eth0@if78: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP group default
- link/ether 02:42:0a:01:4f:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
- inet 10.1.79.11/24 brd 10.1.79.255 scope global eth0
- valid_lft forever preferred_lft forever
IP 所在的网段是在 dockerd 的启动参数中给的:
- root 11183 1 1 2017 ? 03:04:26 /usr/bin/dockerd -g /data/docker --bip=10.1.79.1/24 --mtu=1400
1.2 Pod IP 地址的由来
(1)管理员配置 flannel 使用的 network,并将配置保存在 etcd 中
- /opt/bin/etcdctl --endpoints="http://172.23.100.4:2379,http://172.23.100.5:2379,http://172.23.100.4:2379" mk /coreos.com/network/config \ '{"Network":"10.1.0.0/16", "Backend": {"Type": "vxlan"}}'
(2)在每个 minion 节点上,flannel 启动。它从 etcd 中获取 network 配置,并为本节点产生一个 subnet,也保存在 etcd 中。并且产生 /run/flannel/subnet.env 文件:
- FLANNEL_NETWORK=10.1.0.0/16 #这是全局的 falnnel network
- FLANNEL_SUBNET=10.1.1.1/24 #这是本节点上 falnnel subnet
- FLANNEL_MTU=1400 #本节点上 flannel mtu
- FLANNEL_IPMASQ=true
(3)flannel deamon 还会创建 flannel.1 的 vxlan vtep 端点:
- root@kub-node-1:/opt/bin# ifconfig flannel.1
- flannel.1 Link encap:Ethernet HWaddr 0a:6e:a6:6f:95:04
- inet addr:10.1.1.0 Bcast:0.0.0.0 Mask:255.255.255.255
- root@kub-node-1:/opt/bin# ip link show dev flannel.1
- 3: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UNKNOWN mode DEFAULT group default
- link/ether 0a:6e:a6:6f:95:04 brd ff:ff:ff:ff:ff:ff
其 mtu 正好是 1400. 该端点会负责接收和发送 vxlan 数据包。
(3)使用 subnet.env 中的变量,启动 dockerd 进程,它的 bip 对应 FLANNEL_SUBNET,mtu 对应 FLANNEL_MTU。
- /usr/bin/dockerd -g /data/docker --bip=10.1.1.1/24 --mtu=1400
(4)dockerd deamon 会创建 docker0 网桥
- root@kub-node-1:/opt/bin# ifconfig docker0
- docker0 Link encap:Ethernet HWaddr 02:42:30:ef:ef:18
- inet addr:10.1.1.1 Bcast:10.1.1.255 Mask:255.255.255.0
本节点上的容器都会使用一个 veth 设备挂接在该网桥上比如:
- root@kub-node-1:/opt/bin# brctl show docker0
- bridge name bridge id STP enabled interfaces
- docker0 8000.024230efef18 no veth295ded4
- veth5459316
(5)对每一个被调度到本节点上的 POD,kubelet 都会创建一个 pause 容器,该容器会通过一个 veth 设备挂接到 docker0 上;同时,POD 中的其他容器会共享 pause 容器的 network namespace。
1.3 POD 间通信
首先看下本节点上的路由表:
- root@kub-node-1:/opt/bin# route -n
- Kernel IP routing table
- Destination Gateway Genmask Flags Metric Ref Use Iface
- 0.0.0.0 172.23.100.1 0.0.0.0 UG 0 0 0 ens3
- 10.1.0.0 0.0.0.0 255.255.0.0 U 0 0 0 flannel.1 #flannel 网络内跨节点的通信会交给 flannel.1 处理
- 10.1.1.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0 #flannel 网络内节点内的通信会走 docker0
- 169.254.169.254 172.23.100.1 255.255.255.255 UGH 0 0 0 ens3
- 172.23.100.0 0.0.0.0 255.255.255.0 U 0 0 0 ens3
如果是同一个 deployment 的位于同一个 minon 上的两个 POD 之间通信,那实际上是同一个 subnet 间通信,此时经过 docker0 网桥即可;
如果是同一个 deployment 的位于两个 minon 上的两个 POD 之间通信,另一个POD 的IP 在 10.1.79.0 子网上,那么首先到 flannel.1, flannel 查询 etcd 获取对方容器所在的节点的IP地址,然后封装为 vxlan 的 udp 包,发到 ens3,走物理机网络达到对方节点。此时,完整的路径是:
- containerA --> docker0 --> flannel.1 --> NodeA --> (IP Address) --> NodeB --> flannel.1 --> docker0 --> containerB
根据subnet 从 etcd 中获取 node ip:
- root@kub-node-0:/home/ubuntu/kub# /opt/bin/etcdctl --endpoints="http://172.23.100.4:2379,http://172.23.100.5:2379,http://172.23.100.4:2379" get /coreos.com/network/subnets/10.1.79.0-24
- {"PublicIP":"172.23.100.6","BackendType":"vxlan","BackendData":{"VtepMAC":"6e:10:b3:53:1e:f4"}}
1.4 通过POD IP 访问应用
POD 的 IP 地址是 docker 分配的,在 falnnel 网络范围内,也就是 K8S 集群范围内,都可以使用 POD 的 IP 访问 POD 中的应用。比如:
- root@kub-node-0:/home/ubuntu/kub# kubectl get pods -o wide
- NAME READY STATUS RESTARTS AGE IP NODE
- my-nginx8-b77fdd7bc-4t2kb 1/1 Running 0 4d 10.1.79.11 172.23.100.6
- root@kub-node-0:/home/ubuntu/kub# curl 10.1.79.11:80
- <h1>Welcome to nginx!</h1>
- <p>If you see this page, the nginx web server is successfully installed and
- working. Further configuration is required.</p>
- <p>For online documentation and support please refer to
- <a href="http://nginx.org/">nginx.org</a>.<br/>
- Commercial support is available at
- <a href="http://nginx.com/">nginx.com</a>.</p>
- <p><em>Thank you for using nginx.</em></p>
- </body>
- </html>
而在集群之外,是无法访问POD的IP的。
2. 通过 Cluster Service 的IP地址访问应用
2.1 Service 的 Cluster IP
从上面内容可以看出,每个POD的IP 跟所在节点的配置有关,因此,随着POD在不同节点上的生生死死,其IP地址会发生变化。为了解决这个问题,K8S 提供了 Cluster 类型的 service。
创建一个 Cluster 类型的 service:
- root@kub-node-0:/home/ubuntu/kub# kubectl expose deployment my-nginx8 --type ClusterIP --name nginx-cluster-svc
- service "nginx-cluster-svc" exposed
该 service 由 kube-apiserver 服务分配了虚拟的 IP 地址 192.1.47.211:
- root@kub-node-0:/home/ubuntu/kub# kubectl get svc
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
- kubernetes ClusterIP 192.1.0.1 <none> 443/TCP 13d
- nginx-cluster-svc ClusterIP 192.1.47.211 <none> 80/TCP 1m
而这些 IP 地址的区间则是其启动参数 service-cluster-ip-range 指定的。在当前测试环境中,其值是 --service-cluster-ip-range=192.1.0.0/16。
2.2 Service Cluster IP 地址的由来
只能在 minon 节点上,而且只能使用 IP:Port/协议 才能访问 service。其它地方或者其它方式都不可以。
- root@kub-node-1:/home/ubuntu# iptables -S -t nat | grep KUBE-SERVICES
- -N KUBE-SERVICES
- -A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
- -A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
- -A KUBE-SERVICES -d 192.1.47.211/32 -p tcp -m comment --comment "default/nginx-cluster-svc: cluster IP" -m tcp --dport 80 -j KUBE-SVC-XQHY67DURS27F2QJ
- -A KUBE-SERVICES -d 192.1.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j KUBE-SVC-NPX46M4PTMTKRN6Y
- -A KUBE-SERVICES -d 192.1.233.219/32 -p tcp -m comment --comment "kube-system/kubernetes-dashboard: cluster IP" -m tcp --dport 443 -j KUBE-SVC-XGLOHA7QRQ3V22RZ
- -A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
root@kub-node-1:/home/ubuntu# iptables -S -t nat | grep KUBE-SVC-XQHY67DURS27F2QJ- -N KUBE-SVC-XQHY67DURS27F2QJ
- -A KUBE-SERVICES -d 192.1.47.211/32 -p tcp -m comment --comment "default/nginx-cluster-svc: cluster IP" -m tcp --dport 80 -j KUBE-SVC-XQHY67DURS27F2QJ
- -A KUBE-SVC-XQHY67DURS27F2QJ -m comment --comment "default/nginx-cluster-svc:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-FO4LSVXACD7WOMVW
- -A KUBE-SVC-XQHY67DURS27F2QJ -m comment --comment "default/nginx-cluster-svc:" -j KUBE-SEP-DCSHEKS5WGS4LYVT
root@kub-node-1:/home/ubuntu# iptables -S -t nat | grep KUBE-SEP-FO4LSVXACD7WOMVW- -N KUBE-SEP-FO4LSVXACD7WOMVW
- -A KUBE-SEP-FO4LSVXACD7WOMVW -s 10.1.1.4/32 -m comment --comment "default/nginx-cluster-svc:" -j KUBE-MARK-MASQ
- -A KUBE-SEP-FO4LSVXACD7WOMVW -p tcp -m comment --comment "default/nginx-cluster-svc:" -m tcp -j DNAT --to-destination 10.1.1.4:80
root@kub-node-1:/home/ubuntu# iptables -S -t nat | grep KUBE-SEP-DCSHEKS5WGS4LYVT
-N KUBE-SEP-DCSHEKS5WGS4LYVT
-A KUBE-SEP-DCSHEKS5WGS4LYVT -s 10.1.79.11/32 -m comment --comment "default/nginx-cluster-svc:" -j KUBE-MARK-MASQ
-A KUBE-SEP-DCSHEKS5WGS4LYVT -p tcp -m comment --comment "default/nginx-cluster-svc:" -m tcp -j DNAT --to-destination 10.1.79.11:80
从以上 iptables 规则可以看出,在该节点上通过 192.1.47.211:80 访问 cluster service,最终结果是以50% 和 50% 的概率发到了 10.1.1.4:80 和 10.1.79.11:80 上,而这两个的地址正是该service 的 两个 POD 的 IP 地址。
所以主要流程是:
- kube-proxy 根据 cluster service 的CRUD 来在每个节点上生成对应的 iptables 规则
- 当通过 cluster ip 访问时,这些 iptables 规则会通过 NAT 方式把流量导向 service的 POD
3. 通过 NodePort service 的 IP 访问应用
Cluster service 的 IP 地址是虚拟的,因此,只能从minon 节点上使用该IP 地址访问应用。为了从集群外访问应用,K8S 提供了使用 minon 节点的IP 地址访问应用的方式。
3.1 NodePort Service
创建一个 NodePort 类型的 service,系统会自动创建一个 cluster-ip,同时还多了一个 port。下图中是 31295. 该端口号的范围是 kube-apiserver 的启动参数 --service-node-port-range指定的,在当前测试环境中其值是 30000-32767。
- root@kub-node-0:/home/ubuntu/kub# kubectl expose deployment my-nginx8 --type NodePort --name nginx-nodeport-svc
- service "nginx-nodeport-svc" exposed
- root@kub-node-0:/home/ubuntu/kub# kubectl get svc
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
- kubernetes ClusterIP 192.1.0.1 <none> 443/TCP 13d
- nginx-nodeport-svc NodePort 192.1.88.35 <none> 80:31295/TCP 5s
通过每个 minon 节点的IP 和 31295 端口可以访问该service。
3.2 Service NodePort 的由来
- root@kub-node-1:/var/log/kubernetes# iptables -S -t nat | grep KUBE-NODEPORTS
- -N KUBE-NODEPORTS
- -A KUBE-NODEPORTS -p tcp -m comment --comment "default/nginx-nodeport-svc:" -m tcp --dport 31295 -j KUBE-MARK-MASQ
- -A KUBE-NODEPORTS -p tcp -m comment --comment "default/nginx-nodeport-svc:" -m tcp --dport 31295 -j KUBE-SVC-YN4D7LGVMIQA3S2Y
- root@kub-node-1:/var/log/kubernetes# iptables -S -t nat | grep KUBE-SVC-YN4D7LGVMIQA3S2Y
- -N KUBE-SVC-YN4D7LGVMIQA3S2Y
- -A KUBE-SVC-YN4D7LGVMIQA3S2Y -m comment --comment "default/nginx-nodeport-svc:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-H7QSASJ4XBTCRED7
- root@kub-node-1:/var/log/kubernetes# iptables -S -t nat | grep KUBE-SEP-H7QSASJ4XBTCRED7
- -N KUBE-SEP-H7QSASJ4XBTCRED7
- -A KUBE-SEP-H7QSASJ4XBTCRED7 -s 10.1.1.4/32 -m comment --comment "default/nginx-nodeport-svc:" -j KUBE-MARK-MASQ
- -A KUBE-SEP-H7QSASJ4XBTCRED7 -p tcp -m comment --comment "default/nginx-nodeport-svc:" -m tcp -j DNAT --to-destination 10.1.1.4:80
- -A KUBE-SVC-YN4D7LGVMIQA3S2Y -m comment --comment "default/nginx-nodeport-svc:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-H7QSASJ4XBTCRED7
- root@kub-node-1:/var/log/kubernetes# iptables -S -t nat | grep KUBE-SEP-YLSXRQMQKCP2ZZ6B
- -N KUBE-SEP-YLSXRQMQKCP2ZZ6B
- -A KUBE-SEP-YLSXRQMQKCP2ZZ6B -s 10.1.79.11/32 -m comment --comment "default/nginx-nodeport-svc:" -j KUBE-MARK-MASQ
- -A KUBE-SEP-YLSXRQMQKCP2ZZ6B -p tcp -m comment --comment "default/nginx-nodeport-svc:" -m tcp -j DNAT --to-destination 10.1.79.11:80
- -A KUBE-SVC-YN4D7LGVMIQA3S2Y -m comment --comment "default/nginx-nodeport-svc:" -j KUBE-SEP-YLSXRQMQKCP2ZZ6B
可见,同样地,通过 iptables 规则,通过 nodeport 访问service,最终转到了对该 servide 的所有 pod 轮流地访问。
即使某个 node 上没有service 的 pod,这些规则也会被创建,也就是说,NodePort 模式会在每个节点上开起一个端口,然后转发到内部 Pod IP 。这样可以保证使用任何一个 node 的ip,结合 nodeport,都可以访问到 service。
kubernetes应用的各种访问方式的更多相关文章
- 【Kubernetes】Kubernetes的Service外部访问方式:NodePort和LoadBalancer
Kubernetes的Pod的寿命是有限的,它们不会复活,因此尽管每个Pod都有自己的IP地址,但是这些IP地址是不可靠的,会随着Pod的消亡而消失. 这就带来一个问题,如果一些Pod的集合(称之为b ...
- Kubernetes的三种外部访问方式:NodePort、LoadBalancer和Ingress(转发)
原文 http://cloud.51cto.com/art/201804/570386.htm Kubernetes的三种外部访问方式:NodePort.LoadBalancer和Ingress 最近 ...
- 理解Kubernetes(2): 应用的各种访问方式
理解Kubernetes系列文章: 手工搭建环境 应用的各种访问方式 1. 通过 Pod 的 IP 地址访问应用 1.1 Pod 的IP地址 每个Pod 都会被分配一个IP地址,比如下面这儿pod的I ...
- 访问kubernetes CRD的几种方式
访问kubernetes CRD的几种方式 最近在使用代码操作VictoriaMetrics Operator的CRD资源的过程中,探究了集中访问CRD资源的方式.下面以VictoriaMetrics ...
- Kubernetes 企业级集群部署方式
一.Kubernetes介绍与特性 1.1.kubernetes是什么 官方网站:http://www.kubernetes.io • Kubernetes是Google在2014年开源的一个容器集群 ...
- ADO.NET编程之美----数据访问方式(面向连接与面向无连接)
最近,在学习ADO.NET时,其中提到了数据访问方式:面向连接与面向无连接.于是,百度了一下,发现并没有很好的资料,然而,在学校图书馆中发现一本好书(<ASP.NET MVC5 网站开发之美&g ...
- Objective-C 中self.与_访问方式的区别
Objective-C中属性self.a与_a访问的区别: 在OC中我们可以通过指令@property定义属性. OC对属性封装了许多方法,同时也会自动实现一些方法,相比实例变量,感觉更加面向对象些. ...
- 在APACHE服务器上的访问方式上去除index.php
在APACHE服务器上的访问方式上去除index.php 下面我说下 apache 下 ,如何 去掉URL 里面的 index.php 例如: 你原来的路径是: localhost/index ...
- Django 之 ForeignKey、ManyToMany的访问方式
1.ForeignKey 情况I: from django.db import models class Blog(models.Model): pass class Entry(models.Mod ...
随机推荐
- 【代码审计】QYKCMS_v4.3.2 任意文件读取漏洞分析
0x00 环境准备 QYKCMS官网:http://www.qykcms.com/ 网站源码版本:QYKCMS_v4.3.2(企业站主题) 程序源码下载:http://bbs.qingyunke. ...
- python virtualenv安装说明
环境说明: virtualenv安装: 第一步,创建目录code: 第二步,创建一个独立的Python运行环境,命名为venv: 新建的Python环境被放到当前目录下的venv目录. 第三步,有了v ...
- Git 学习笔记--git 查看某个文件的修改历史
1. git log -p filename 查看文件的每一个详细的历史修改,如果没有-p选项,只显示提交记录,不显示文件内容修改,git log -p -3 filename 显示最近的3次提交. ...
- 编译poco-1.7.8
运行build_vs140.cmd,运行之前可以修改一些参数,例如编译64位 buildwin 140 build shared both x64 nosamples notests devenv 修 ...
- Java中获取资源文件的方法总结
这里总结3中方法获取资源文件的 ServletContext Class ClassLoader 文件的位置 1. ServletContext public void doGet(HttpServl ...
- [Python] 正确复制列表的方法
new = old[:] Python老鸟都知道以上代码是什么意思.它复制列表old到new.它对于新手来说是种困惑而且应该避免使用这种方法.不幸的是[:]标记法被广泛使用,可能是Python程序员不 ...
- springboot 集成elasticsearch
In this article, we will discuss about “How to create a Spring Boot + Spring Data + Elasticsearch Ex ...
- /etc/profile /etc/profile .bash_profile .bashrc解释
1.用户登录系统时,bash首先执行/etc/profile配置文件和/etc/profile.d/目录下的配置文件,这些配置文件对系统的所有用户都有效,它们设置了普遍性的环境变量. 2.然后,Bas ...
- 五、K3 WISE 开发插件《K3 Wise 群发短信配置开发(一)之短信平台配置》
开发环境:K/3 Wise 13.0 目录 一.创建短信数据库 二.配置短信接口 三.设置帐套关键字 四.查询短信余额 一.创建短信数据库 打开帐套管理: 账号默认为Admin,密码不填: 菜单“系统 ...
- 【CSS系列】获取实时数据做进度
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...