聂永的博客

记录工作/学习的点点滴滴。

K8S Service 多种类型 Types 测试手记

前言

这里基于whoami示范服务,部署3个实例,分别一一验证各种类型的K8S Service服务范畴。

大致逐一从下面列表逐一验证每种类型的Service访问方式:

  • Service Name
  • 域名解析结果等
  • CLUSTER-IP
  • EXTERNAL-IP

一些设定如下:

  • 测试环境K8S版本号为v1.27.3
  • K8S集群Node节点IP地址段范围:10.0.1.0/24
  • K8S集群自动生成Pod网段为10.43.0.0/24
  • 本书所列代码皆可拷贝直接粘贴到终端界面直接运行

首先,部署whoami服务

先部署包含3个实例的whoami

# cat << 'EOF' | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  labels:
    app: whoami
spec:
  replicas: 3
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
      - name: whoami
        image: containous/whoami
        ports:
        - containerPort: 80
          name: web
EOF

查看一下:

# kubectl get all
NAME                                                      READY   STATUS      RESTARTS         AGE
pod/whoami-767d459f67-qffqw                               1/1     Running     0                23m
pod/whoami-767d459f67-xdv9p                               1/1     Running     0                23m
pod/whoami-767d459f67-gwpgx                               1/1     Running     0                23m

NAME                                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/whoami                                3/3     3            3           23m

NAME                                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/whoami-767d459f67                               3         3         3       23m

其次,安装busybox进行调试

安装一个包含有curl的busybox方便后续调试:

kubectl run busybox-curl --image=yauritux/busybox-curl --command -- sleep 3600

另起一个终端,输入下面命令进入:

kubectl exec -ti busybox-curl -n default -- sh

环境准备好之后,下面逐一测试各种类型:

默认Cluster IP模式

K8S默认Service为Cluster IP模式,面向内部Pod以及通过Ingress对外提供服务。

下面一张图很清晰解释清楚了PortTargetPort适用情景,Port为Service对外输出的端口,TargetPort为服务后端Pod的端口,两者之间有一个转换:port -> targetPort -> containerPort

创建一个Service:

cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  labels:
    name: whoami-clusterip
  name: whoami-clusterip
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: whoami
EOF

部署后可以查看一下:

NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/whoami-clusterip      ClusterIP      10.43.247.74    <none>        80/TCP         57s

下面就需要逐一测试了。

域名形式:

# curl whoami-clusterip
Hostname: whoami-767d459f67-gwpgx
IP: 127.0.0.1
IP: 10.42.8.35
RemoteAddr: 10.42.9.32:35968
GET / HTTP/1.1
Host: whoami-clusterip
User-Agent: curl/7.81.0
Accept: */*

Cluster IP形式:

# curl 10.43.247.74
Hostname: whoami-767d459f67-qffqw
IP: 127.0.0.1
IP: 10.42.3.73
RemoteAddr: 10.42.9.32:42398
GET / HTTP/1.1
Host: 10.43.247.74
User-Agent: curl/7.81.0
Accept: */*

域名解析,只解析到Cluster IP上:

# nslookup whoami-clusterip
Server:		10.43.0.10
Address:	10.43.0.10:53

Name:	whoami-clusterip.default.svc.cluster.local
Address: 10.43.247.74

External IP模式

原理同Cluster IP模式,为指定服务绑定一个额外的一个IP地址。当终端访问该IP地址,将流量一样转发到Service。

当访问external IP,其端口转换过程:port -> targetPort -> containerPort

与默认Service相比,端口转换流程没有增加,但好处对外暴露了一个可访问的IP地址,不过可能需要在交换机/路由器层面提供动静态路由支持。

cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  labels:
    name: whoami-externalip
  name: whoami-externalip
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: whoami
  externalIPs:
  - 10.10.10.10
EOF

服务显示如下,绑定了指定的扩展IP地址10.10.10.10

# NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/whoami-externalip     ClusterIP      10.43.192.118   10.10.10.10   80/TCP         57s

kube-proxy 将在每一个Node节点为10.10.10.10上建立一个转发规则,该IP地址的80端口将直接转发到对应的后端三个whoami Pod 上。

-A KUBE-SERVICES -d 10.10.10.10/32 -p tcp -m comment --comment "default/whoami-externalip external IP" -m tcp --dport 80 -j KUBE-EXT-QN5HIEVYUPDP6UNK

......
-A KUBE-EXT-QN5HIEVYUPDP6UNK -j KUBE-SVC-QN5HIEVYUPDP6UNK
......

-A KUBE-SVC-QN5HIEVYUPDP6UNK ! -s 10.42.0.0/16 -d 10.43.192.118/32 -p tcp -m comment --comment "default/whoami-externalip cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
-A KUBE-SVC-QN5HIEVYUPDP6UNK -m comment --comment "default/whoami-externalip -> 10.42.2.79:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-JSAT6D2KFCSF4YLF
-A KUBE-SVC-QN5HIEVYUPDP6UNK -m comment --comment "default/whoami-externalip -> 10.42.3.77:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-2R66UI3G2AY2IMNM
-A KUBE-SVC-QN5HIEVYUPDP6UNK -m comment --comment "default/whoami-externalip -> 10.42.8.42:80" -j KUBE-SEP-ZHHIL2SAN2G37GCM

访问域名:

# curl whoami-externalip
Hostname: whoami-767d459f67-gwpgx
IP: 127.0.0.1
IP: 10.42.8.35
RemoteAddr: 10.42.9.32:46746
GET / HTTP/1.1
Host: whoami-externalip
User-Agent: curl/7.81.0
Accept: */*

访问ClusterIP形式:

# curl 10.43.192.118
Hostname: whoami-767d459f67-qffqw
IP: 127.0.0.1
IP: 10.42.3.73
RemoteAddr: 10.42.9.32:47516
GET / HTTP/1.1
Host: 10.43.192.118
User-Agent: curl/7.81.0
Accept: */*

访问暴露的External IP:

# curl 10.10.10.10
Hostname: whoami-767d459f67-gwpgx
IP: 127.0.0.1
IP: 10.42.8.35
RemoteAddr: 10.42.9.0:38477
GET / HTTP/1.1
Host: 10.10.10.10
User-Agent: curl/7.81.0
Accept: */*

域名解析结果只解析到其对应的Cluster IP:

# nslookup whoami-externalip
Server:		10.43.0.10
Address:	10.43.0.10:53

Name:	whoami-externalip.default.svc.cluster.local
Address: 10.43.192.118

NodePort 模式

Cluster IP相比,多了一个nodePort,这个NodePort会在K8S所有Node节点上都会开放。

这里有一个端口转换过程:nodePort -> port -> targetPort -> containerPort,多了一层数据转换过程。

服务定义如下:

cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  labels:
    name: whoami-nodeport
  name: whoami-nodeport
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
    protocol: TCP
  selector:
    app: whoami
EOF

查看一下服务分配地址:

NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/whoami-nodeport       NodePort       10.43.215.233   <none>        80:30080/TCP   57s

访问域名:

# curl whoami-nodeport
Hostname: whoami-767d459f67-xdv9p
IP: 127.0.0.1
IP: 10.42.2.75
RemoteAddr: 10.42.9.32:36878
GET / HTTP/1.1
Host: whoami-nodeport
User-Agent: curl/7.81.0
Accept: */*

测试 CLUSTER IP :

# curl 10.43.215.233
Hostname: whoami-767d459f67-qffqw
IP: 127.0.0.1
IP: 10.42.3.73
RemoteAddr: 10.42.9.32:40552
GET / HTTP/1.1
Host: 10.43.215.233
User-Agent: curl/7.81.0
Accept: */*

因为是在每一个K8S Node节点上都会开放一个30080端口,因此可以这样访问 {Node IP}:{nodePort},如下Node IP地址为10.0.1.11

# curl 10.0.1.11:30080
Hostname: whoami-767d459f67-qffqw
IP: 127.0.0.1
IP: 10.42.3.73
RemoteAddr: 10.42.1.0:1880
GET / HTTP/1.1
Host: 10.0.1.11:30080
User-Agent: curl/7.81.0
Accept: */*

域名还是只解析到对应Cluster IP:

# nslookup whoami-nodeport
Server:		10.43.0.10
Address:	10.43.0.10:53

Name:	whoami-nodeport.default.svc.cluster.local
Address: 10.43.215.233

LoadBalancer 模式

LoadBalancer模式,会强制K8S Service自动开启nodePort

这里有一张图,详细解析数据流向。

服务数据端口转换过程:port -> nodePort -> port -> targetPort -> containerPort

  • 与默认Cluster IP相比,多了两层数据转换过程
  • nodePort相比,对了一层数据转换过程
  • externalIP相比,在小流量场景下就没有什么优势了

具体服务定义:

cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  labels:
    name: whoami-clusterip-none
  name: whoami-clusterip-none
spec:
  clusterIP: None
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: whoami
EOF

查看一下部署结果:

NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/whoami-loadbalancer   LoadBalancer   10.43.63.92     <pending>     80:30906/TCP   57s

服务域名形式:

# curl whoami-loadbalancer
Hostname: whoami-767d459f67-qffqw
IP: 127.0.0.1
IP: 10.42.3.73
RemoteAddr: 10.42.9.32:57844
GET / HTTP/1.1
Host: whoami-loadbalancer
User-Agent: curl/7.81.0
Accept: */*

测试 CLUSTER-IP

# curl 10.43.63.92
Hostname: whoami-767d459f67-xdv9p
IP: 127.0.0.1
IP: 10.42.2.75
RemoteAddr: 10.42.9.32:42400
GET / HTTP/1.1
Host: 10.43.63.92
User-Agent: curl/7.81.0
Accept: */*

域名解析到Cluster IP:

#  nslookup whoami-loadbalancer
Server:		10.43.0.10
Address:	10.43.0.10:53

Name:	whoami-loadbalancer.default.svc.cluster.local
Address: 10.43.63.92

安装LoadBalancer

此时whoami-loadbalancer服务对应的EXTERNAL-IP<pending>,我们需要安装一个负载均衡器,可以选择MetalLB作为负载均衡器。

# kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.11/config/manifests/metallb-native.yaml

稍后分配可用的LoadBalaner可分配的地址池:

cat << 'EOF' | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: default-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.0.1.100-10.0.1.200
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: default
  namespace: metallb-system
spec:
  ipAddressPools:
  - default-pool
EOF

等安装完成之后,可以看到服务whoami-loadbalancer分配的IP地址为 10.0.1.101

NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
......
service/whoami-loadbalancer LoadBalancer   10.43.63.92     10.0.1.101         80:30906/TCP   27h
......

测试负载均衡IP地址

测试一下:

# curl 10.0.1.101
Hostname: whoami-767d459f67-xdv9p
IP: 127.0.0.1
IP: 10.42.2.78
RemoteAddr: 10.42.8.0:33658
GET / HTTP/1.1
Host: 10.0.1.101
User-Agent: curl/7.79.1
Accept: */*

我们看到该服务分配的端口为80:30906/TCP30906为K8S为该服务自动生成的NodePort类型端口。

可以找任一K8S Node节点IP地址测试一下:

# curl 10.0.1.12:30906
Hostname: whoami-767d459f67-qffqw
IP: 127.0.0.1
IP: 10.42.3.77
RemoteAddr: 10.42.2.0:9717
GET / HTTP/1.1
Host: 10.0.1.12:30906
User-Agent: curl/7.81.0
Accept: */*

分析一下路由表,可以分析到该负载均衡的External_IP:80的打流量到NodePort:30906上,然后走Service对应{Pod:80}流量分发逻辑。

-A KUBE-NODEPORTS -p tcp -m comment --comment "default/whoami-loadbalancer" -m tcp --dport 30906 -j KUBE-EXT-NBTYBEEXACZI7DPC

......

-A KUBE-SERVICES -d 10.0.1.101/32 -p tcp -m comment --comment "default/whoami-loadbalancer loadbalancer IP" -m tcp --dport 80 -j KUBE-EXT-NBTYBEEXACZI7DPC

......

-A KUBE-EXT-NBTYBEEXACZI7DPC -m comment --comment "masquerade traffic for default/whoami-loadbalancer external destinations" -j KUBE-MARK-MASQ
-A KUBE-EXT-NBTYBEEXACZI7DPC -j KUBE-SVC-NBTYBEEXACZI7DPC

......

-A KUBE-SVC-NBTYBEEXACZI7DPC ! -s 10.42.0.0/16 -d 10.43.63.92/32 -p tcp -m comment --comment "default/whoami-loadbalancer cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
-A KUBE-SVC-NBTYBEEXACZI7DPC -m comment --comment "default/whoami-loadbalancer -> 10.42.2.79:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-E3K3SUYNFWT2VICE
-A KUBE-SVC-NBTYBEEXACZI7DPC -m comment --comment "default/whoami-loadbalancer -> 10.42.3.77:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-HG5MYVVID7GJOZA7
-A KUBE-SVC-NBTYBEEXACZI7DPC -m comment --comment "default/whoami-loadbalancer -> 10.42.8.42:80" -j KUBE-SEP-GFJH72YCBKBFB6OG

Headless 无头模式

一般应用在有状态的服务,或需要终端调用者自己实现负载均衡,等一些特定场景。

通过调用者从端口角度分析,数据转换流程:targetPort -> containerPort

在意服务性能的场景,不妨试试无头模式。


服务定义:

cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  labels:
    name: whoami-clusterip-none
  name: whoami-clusterip-none
spec:
  clusterIP: None
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: whoami
EOF

查看服务部署情况:

NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/whoami-clusterip-none   ClusterIP      None            <none>                     80/TCP         9h

通过service域名访问,K8S会自动根据服务域名whoami-clusterip-none进行pick后端对应Pod IP地址。

# curl whoami-clusterip-none
Hostname: whoami-767d459f67-xdv9p
IP: 127.0.0.1
IP: 10.42.2.75
RemoteAddr: 10.42.9.32:34998
GET / HTTP/1.1
Host: whoami-clusterip-none
User-Agent: curl/7.81.0
Accept: */*

查询DNS会把所有节点都列出来。

# nslookup whoami-clusterip-none
Server:		10.43.0.10
Address:	10.43.0.10:53

Name:	whoami-clusterip-none.default.svc.cluster.local
Address: 10.42.3.73
Name:	whoami-clusterip-none.default.svc.cluster.local
Address: 10.42.2.75
Name:	whoami-clusterip-none.default.svc.cluster.local
Address: 10.42.8.35

External Name模式

用于引进带域名的外部服务,这里引入内部服务作为测试。

多了一层域名解析过程,端口转换流程依赖于所引入服务的服务设定。

服务定义:

cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  labels:
    name: whoami-externalname
  name: whoami-externalname
spec:
  type: ExternalName
  externalName: whoami-clusterip.default.svc.cluster.local
EOF

这里外联的是whoami-clusterip服务的完整访问域名。

查看服务部署情况:

NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/whoami-externalname     ExternalName   <none>          whoami-clusterip.default   <none>         9h

根据域名访问测试:

# curl whoami-externalname
Hostname: whoami-767d459f67-qffqw
IP: 127.0.0.1
IP: 10.42.3.77
RemoteAddr: 10.42.9.35:36756
GET / HTTP/1.1
Host: whoami-externalname
User-Agent: curl/7.81.0
Accept: */*

DNS解析结果:

# nslookup whoami-externalname
Server:		10.43.0.10
Address:	10.43.0.10:53

whoami-externalname.default.svc.cluster.local	canonical name = whoami-clusterip.default.svc.cluster.local
Name:	whoami-clusterip.default.svc.cluster.local
Address: 10.43.247.74

小结

简要分析了各种类型Service定义、服务引用场景以及测试流程等,整理清楚了,也方便在具体业务场景中进行抉择选择具体服务类型。

posted on 2023-09-13 10:13 nieyong 阅读(133) 评论(0)  编辑  收藏 所属分类: 容器


只有注册用户登录后才能发表评论。


网站导航:
 

公告

所有文章皆为原创,若转载请标明出处,谢谢~

新浪微博,欢迎关注:

导航

<2023年9月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

统计

常用链接

留言簿(58)

随笔分类(130)

随笔档案(151)

个人收藏

最新随笔

搜索

最新评论

阅读排行榜

评论排行榜