容器网络域名解析

使用service的原因

1. Pod的IP不是固定的。
2. Pod实例之间需要负载均衡。

部署Service和Deploy

使用selector字段来声明这个Service只代理携带了app=hostnames标签的Pod。这个Service的80端口,代理的是Pod的9376端口。

apiVersion: v1
kind: Service
metadata:
  name: hostnames
spec:
  selector:
    app: hostnames
  ports:
  - name: default
    protocol: TCP
    port: 80
targetPort: 9376

应用的作用是每次访问9376端口时返回自己的hostname。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hostnames
spec:
  selector:
    matchLabels:
      app: hostnames
  replicas: 3
  template:
    metadata:
      labels:
        app: hostnames
    spec:
      containers:
      - name: hostnames
        image: k8s.gcr.io/serve_hostname
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9376
          protocol: TCP

手动下载serve_hostname镜像

docker pull anjia0532/google-containers.serve_hostname
docker tag docker.io/anjia0532/google-containers.serve_hostname:latest k8s.gcr.io/serve_hostname

查看ep

被selector选中的Pod称为Service的Endpoints。
只有处于Running状态且readinessProbe检查通过的Pod,才会出现在Service的Endpoints列表里。

$ kubectl get pod -owide 
NAME                         READY   STATUS    RESTARTS   AGE     IP            NODE            NOMINATED NODE   READINESS GATES
hostnames-7c89f997cf-pdg7p   1/1     Running   0          4m29s   10.244.1.8    192.168.0.106   <none>           <none>
hostnames-7c89f997cf-tzmcn   1/1     Running   0          3m22s   10.244.1.10   192.168.0.106   <none>           <none>
hostnames-7c89f997cf-vc4qc   1/1     Running   0          4m29s   10.244.1.9    192.168.0.106   <none>           <none>

$ kubectl get ep hostnames
NAME        ENDPOINTS                                          AGE
hostnames   10.244.1.10:9376,10.244.1.8:9376,10.244.1.9:9376   12m

访问service(负载均衡方式是轮询)

$ kubectl get svc hostnames
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
hostnames   ClusterIP   10.102.11.183   <none>        80/TCP    16m

$ curl 10.102.11.183:80
hostnames-7c89f997cf-tzmcn

实现原理

Service是由kube-proxy + iptables来实现的。kube-proxy通过Service的Informer感知hostnames Service对象的添加,在每个主机上创建iptables规则。

无法ping通cluster ip的原因

因为10.99.149.144只是一条iptables规则上的配置,没有真正的网络设备,所以ping这个地址是不会有响应的。

iptables规则

PREROUTING nat

# KUBE-SERVICES链插在DOCKER链前面
$ iptables -t nat -nvL PREROUTING
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  138 44896 KUBE-SERVICES  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
    9   932 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

# DNAT 通过轮询的方式把包传给ep
# KUBE-MARK-MASQ对流入的IP包设置标志(--set-xmark)
$ iptables -t nat -nvL KUBE-SERVICES
Chain KUBE-SERVICES (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    ...
    0     0 KUBE-MARK-MASQ  tcp  --  *      *      !10.244.0.0/16        10.102.11.183        /* default/hostnames:default cluster IP */ tcp dpt:80
    0     0 KUBE-SVC-ODX2UBAZM7RQWOIU  tcp  --  *      *       0.0.0.0/0            10.102.11.183        /* default/hostnames:default cluster IP */ tcp dpt:80
    ...

# 为了保证每条被选中的概率都相同,probability字段的值分别设置为 1/3(0.333…)、1/2 和 1。
# 第一条规则被选中的概率就是1/3;如果第一条规则没有被选中,那么只剩下两条规则了,第二条规则的probability设置为1/2;最后一条设置为1。
$ iptables -t nat -nvL KUBE-SVC-ODX2UBAZM7RQWOIU
Chain KUBE-SVC-ODX2UBAZM7RQWOIU (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 KUBE-SEP-N6BO7JPFL3IPM3GK  all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode random probability 0.33332999982
    0     0 KUBE-SEP-XBIWV66JPBUXLYCY  all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode random probability 0.50000000000
    0     0 KUBE-SEP-ZDT36JFL743NS3VU  all  --  *      *       0.0.0.0/0            0.0.0.0/0
$ iptables -t nat -nvL KUBE-SEP-N6BO7JPFL3IPM3GK
Chain KUBE-SEP-N6BO7JPFL3IPM3GK (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 KUBE-MARK-MASQ  all  --  *      *       10.244.1.10          0.0.0.0/0           
    0     0 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp to:10.244.1.10:9376


$ iptables -t nat -nvL KUBE-SEP-XBIWV66JPBUXLYCY
Chain KUBE-SEP-XBIWV66JPBUXLYCY (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 KUBE-MARK-MASQ  all  --  *      *       10.244.1.8           0.0.0.0/0           
    0     0 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp to:10.244.1.8:9376


$ iptables -t nat -nvL KUBE-SEP-ZDT36JFL743NS3VU
Chain KUBE-SEP-ZDT36JFL743NS3VU (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 KUBE-MARK-MASQ  all  --  *      *       10.244.1.9           0.0.0.0/0           
0     0 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp to:10.244.1.9:9376

如果源地址不是容器网络网段,那么需要设置标志,即不设置标志的情况是源地址不是容器网络网段中该Service后端Pod IP,DNAT处理后变成了容器之间直接访问。 
针对源地址不是容器网络网段的场景,设置标志的原因是nodePort场景:

                client 
                  \ v
                   \ \ 
                    v \ 
   node 1 <--- node 2 
    | v SNAT 
    | |  ---> 
    v | 
 endpoint

当外部client通过node 2的地址访问Service时,node2把请求转发给Pod所在的node1,node1中Pod处理完请求后响应node2,node2响应client。 
设置了标志的IP包,需要执行SNAT,即node2执行SNAT 如果不执行SNAT,那么client发送给node2的请求,会由node1来响应,报错。

$ iptables -t nat -nvL POSTROUTING
Chain POSTROUTING (policy ACCEPT 6 packets, 360 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    ...
 1984  122K KUBE-POSTROUTING  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */
 ...
 
 $ iptables -t nat -nvL KUBE-POSTROUTING
Chain KUBE-POSTROUTING (1 references)
 pkts bytes target     prot opt in     out     source               destination         
0     0 MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000

解析内部域名

Deployment的yaml文件中不能指定spec.serviceName,StatefulSet的yaml文件中需要指定spec.serviceName。 

Deployment常用ClusterIP模式的Service,解析svc的域名。 
StatefulSet常用Headless模式的Service,解析Pod的域名。

解析service域名

ClusterIP模式的Service,记录格式是svc-name.namespace.svc.cluster.local,指向Cluster IP。 
指定coredns后端实例来解析svc域名。

$ nslookup kubernetes.default.svc.cluster.local -po=53 10.244.1.2
Server:		10.244.1.2
Address:	10.244.1.2#53

Name:	kubernetes.default.svc.cluster.local
Address: 10.96.0.1

指定了clusterIP=None的Headless Service,记录格式也是svc-name.namespace.svc.cluster.local,返回所有被代理的Pod的IP地址的集合。

# nslookup hostnames.default.svc.cluster.local -po=53 10.244.1.2
Server:		10.244.1.2
Address:	10.244.1.2#53

Name:	hostnames.default.svc.cluster.local
Address: 10.244.1.22
Name:	hostnames.default.svc.cluster.local
Address: 10.244.1.21
Name:	hostnames.default.svc.cluster.local
Address: 10.244.1.20

解析Pod域名

ClusterIP模式和Headless模式的Service,代理的Pod记录格式是pod-name.svc-name.namespace.svc.cluster.local,指向Pod的IP地址。

1. 针对无状态应用的Pod,解析失败。

$ nslookup hostnames-7c89f997cf-bx2f7.hostnames.default.svc.cluster.local -po=53 10.244.1.2
Server:		10.244.1.2
Address:	10.244.1.2#53

** server can't find hostnames-7c89f997cf-bx2f7.hostnames.default.svc.cluster.local: NXDOMAIN

2. 针对有状态应用的Pod,解析成功。

$ nslookup hostnames-0.hostnames.default.svc.cluster.local -po=53 10.244.1.2
Server:		10.244.1.2
Address:	10.244.1.2#53

Name:	hostnames-0.hostnames.default.svc.cluster.local
Address: 10.244.1.23

配置域名解析配置文件

$ cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 10.96.0.10 # kube-dns service clusterIP 解析k8s域名
nameserver 192.168.1.1
nameserver 192.168.0.1

# 域名解析成功
$ nslookup hostnames-0.hostnames.default.svc.cluster.local
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	hostnames-0.hostnames.default.svc.cluster.local
Address: 10.244.1.23

域名解析出IPv6地址

# -query=AAAA 表示 IPv6。
nslookup -query=AAAA -po=53 域名 一个kube-dns的Pod的ipv6地址
或者
nslookup -query=AAAA 域名

参考资料

《深入剖析Kubernetes》

 

posted on 2023-07-16 10:35  王景迁  阅读(72)  评论(0编辑  收藏  举报

导航