通常情况下k8s集群中pod使用的是单独划分的一个虚拟子网,处于这个子网中的pod通过nat地址转换的方式访问集群外部。
如果要在集群外部访问pod,通常可以使用三种方式:NodePort,HostPort和LoadBalancer。其中NodePort最为常用,在每个kube-proxy节点上开启代理端口以供外部访问。除此之外有没有别的办法可以在集群直接访问到Pod呢?答案是有的。
假设现在有一套已经搭建好的k8s集群,使用Calico做为cni组件,查看每个节点上的路由表
route -n | grep tunl0
可以看到如下内容
10.233.119.0 10.21.21.74 255.255.255.192 UG 0 0 0 tunl0
10.233.55.64 10.21.21.76 255.255.255.192 UG 0 0 0 tunl0
10.233.183.64 10.21.21.75 255.255.255.192 UG 0 0 0 tunl0
这是calico创建的tunnel,用于实现集群间容器的互相访问,通过这些可以得知每个节点中所划分的pod网段。
我们要做的是就是把这几个路由规则加入到路由器或者客户端机器上
route add -net 10.233.55.64 netmask 255.255.255.192 gw 10.21.21.76
route add -net 10.233.119.0 netmask 255.255.255.192 gw 10.21.21.74
route add -net 10.233.183.64 netmask 255.255.255.192 gw 10.21.21.75
之后我们在k8s中起一个容器做测试,如
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
spec:
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 80
volumeMounts:
- name: timezone
mountPath: /etc/localtime
volumes:
- name: timezone
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
再查看已启动的pod
kubectl get pod -o wide
结果如下:
NAME READY STATUS RESTARTS AGE IP NODE
centos 1/1 Running 0 2d 10.233.55.69 10.21.21.76
我们在客户端机器上直接访问该pod
ping 10.233.55.69
成功响应
PING 10.233.55.69 (10.233.55.69) 56(84) bytes of data.
64 bytes from 10.233.55.69: icmp_seq=1 ttl=63 time=0.442 ms
64 bytes from 10.233.55.69: icmp_seq=2 ttl=63 time=0.328 ms