microk8s(二)深入
2019-07-21 本文已影响0人
印随2018
本文讨论的内容需要先阅读《microk8s(一)安装》
上一篇内容中,使用下面这条命令,讲Pod的开发端口映射到本地节点,其中是怎么实现的呢?
kubectl port-forward --namespace=kube-system --address=0.0.0.0 pod/kubernetes-dashboard-6fd7f9c494-dgxlj 8443:8443
一般来说,端口映射,也就是NAT的功能大多是通过Iptables来实现,那我们先来看看iptables的规则
iptables -vL -t nat --line-numbers
iptables -vL -t filter
iptables -vL -t mangle
iptables -vL -t raw
iptables -vL -t security
检查了所有规则,没有发现关于端口8443的内容。好吧,那我们来看看是哪个进程在监听8443端口
root@iZt4n3mancztn8h975gqptZ:~# lsof -i:8443
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
kubectl 17985 root 6u IPv4 463409 0t0 TCP *:8443 (LISTEN)
上面的输出说明,进程号为17985在监听8443端口的数据, 我们看看这个进程的启动参数
# cat /proc/17985/cmdline
/snap/microk8s/687/kubectl \
--kubeconfig=/var/snap/microk8s/687/credentials/client.config \
port-forward \
--namespace=kube-system \
--address=0.0.0.0 \
pod/kubernetes-dashboard-6fd7f9c494-dgxlj8443:8443
查看进程已经打开的文件
# ls -l /proc/17985/fd
total 0
lrwx------ 1 root root 64 Jul 21 11:25 0 -> /dev/pts/4
lrwx------ 1 root root 64 Jul 21 11:25 1 -> /dev/pts/4
lrwx------ 1 root root 64 Jul 21 11:25 2 -> /dev/pts/4
lrwx------ 1 root root 64 Jul 21 11:25 3 -> 'socket:[463392]'
lrwx------ 1 root root 64 Jul 21 11:25 4 -> 'anon_inode:[eventpoll]'
lrwx------ 1 root root 64 Jul 21 11:25 5 -> 'socket:[463398]'
lrwx------ 1 root root 64 Jul 21 11:25 6 -> 'socket:[463409]'
lrwx------ 1 root root 64 Jul 21 11:27 7 -> 'socket:[472139]'
查看文件对应的socket连接
# cat /proc/net/tcp | grep `echo "obase=16; 8443" | bc ` | awk '{print $2,$3,$10}'
00000000:20FB 00000000:0000 0A 463409
7C6615AC:20FB ACC96871:3EFC 01 472139
上面都是16进制显示的,翻译成10进制如下
本地 远端 inode
0.0.0.0:8443 0.0.0.0:0 463409
172.21.102.124:8443 113.104.201.172:16124 472139
查看网络连接,跟上面的输出是一一对应的
root@iZt4n3mancztn8h975gqptZ:~# netstat -ant | grep 8443
tcp 0 0 0.0.0.0:8443 0.0.0.0:* LISTEN
tcp 0 0 172.21.102.124:8443 113.104.201.172:16124 ESTABLISHED
下面把线索串联一下
port(8443) -> pid(17985) -> inode(472139) -> tcp(172.21.102.124:8443,113.104.201.172:16124) -> client-ip(113.104.201.172)
113.104.201.172是我本机的外网IP地址。现在可以确定,8443端口的数据是直接被用户进程kubelet接受并处理。后续可以再执行
tcpdump -i cbr0 port 8443 -A -nn
可以发现,kubelet确实转发数据到Pod的8443端口,进程是一个真实的TCP代理,负责从Node到Pod的访问流量转发,这种模式称为userspace(用户空间代理)模式。
查看一下进程17985,发现总共有6个子进程,并且所有的子进程都共享同样的文件描述符。
ps -eLf|grep 17985|grep -v "grep" | awk '{print $4}' | xargs -I {} ls -l /proc/{}/fd
看起来是启用了SO_REUSEPORT,允许多个进程或者线程绑定到同一端口,提高服务器程序的性能,解决的问题:
- 允许多个套接字 bind()/listen() 同一个TCP/UDP端口
- 每一个线程拥有自己的服务器套接字
- 在服务器套接字上没有了锁的竞争
- 内核层面实现负载均衡
- 安全层面,监听同一个端口的套接字只能位于同一个用户下面