A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 不二晨 金牌黑马   /  2018-7-15 09:48  /  1133 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

kubernetes导出有状态服务

(金庆的专栏 2018.7)

网游服务器中的房间服务器是有状态服务器,可以用 kubernetes statefulset 开启多个实例。

为了让客户端能够直连房间服务器,除了 statefulset 要求的 headless 服务,
还须为每个实例创建 NodePort 类型的服务, 并且选择Pod和禁止转发。

下面 bootcamp.yml 先创建了 bootcamp headless 服务(clusterIP: None),
又创建了 bootcamp StatefulSet, 实例个数为 2.
然后创建 bootcamp-0,1,2 服务,分别对应 bootcamp-0,1,2 pod.

服务个数大于实例个数,是想测试下服务没有对应的实例时的表现。

网游中的匹配服务器将分配一个房间给客户端,列举 bootcamp-0,1,2 pod 所在节点的外网 IP,
连同对应服务的端口,发送给客户端,让客户端直连。

[jinqing@host-10-240-79-10 statefulset]$ cat bootcamp.yml apiVersion: v1kind: Servicemetadata:  name: bootcamp  namespace: jq  labels:    name: bootcampspec:  ports:    - port: 8080  clusterIP: None  # StatefulSet要求Headless服务  selector:    app: bootcamp  # 选择 bootcamp 应用---apiVersion: apps/v1beta1kind: StatefulSetmetadata:  name: bootcamp  namespace: jqspec:  serviceName: bootcamp  # 上面的 Headless 服务名  replicas: 2  template:    metadata:      labels:        app: bootcamp  # 应用名,与服务中的 selector 对应    spec:      containers:      - name: bootcamp        image: docker.io/jocatalin/kubernetes-bootcamp:v1---kind: ServiceapiVersion: v1metadata:  name: bootcamp-0  namespace: jqspec:  type: NodePort  # 对外服务  externalTrafficPolicy: Local  # 不要转发到其他节点  selector:    app: bootcamp    statefulset.kubernetes.io/pod-name: bootcamp-0  # 选择 pod  ports:  - protocol: TCP    nodePort: 30880  # 对外端口    port: 8080---kind: ServiceapiVersion: v1metadata:  name: bootcamp-1  namespace: jqspec:  type: NodePort  externalTrafficPolicy: Local  selector:    app: bootcamp    statefulset.kubernetes.io/pod-name: bootcamp-1  ports:  - protocol: TCP    nodePort: 30881    port: 8080---kind: ServiceapiVersion: v1metadata:  name: bootcamp-2  namespace: jqspec:  type: NodePort  externalTrafficPolicy: Local  selector:    app: bootcamp    statefulset.kubernetes.io/pod-name: bootcamp-2  ports:  - protocol: TCP    nodePort: 30882    port: 8080

因为 statefulset 的每个实例有不同的标签,所以可以为服务选择一个实例。

利用 externalTrafficPolicy: Local 设置来禁止转发。
参考 service.spec.externalTrafficPolicy 的说明:

https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-type-nodeport

Setting service.spec.externalTrafficPolicy to the value Local will only proxy requests to local endpoints, never forwarding traffic to other nodes and thereby preserving the original source IP address. If there are no local endpoints, packets sent to the node are dropped, …

因为有可能多个Pod开在同一节点上,所以对外端口设成了不同的 30880-30882。
如果限制每个节点只开一个实例,则对外端口可以设成同一个。

创建服务:

[jinqing@host-10-240-79-10 statefulset]$ kubectl apply -f bootcamp.yml service "bootcamp" createdstatefulset.apps "bootcamp" createdservice "bootcamp-0" createdservice "bootcamp-1" createdservice "bootcamp-2" created

服务如下:

[jinqing@host-10-240-79-10 statefulset]$ kubectl get service -n jqNAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGEbootcamp     ClusterIP   None             <none>        8080/TCP         3mbootcamp-0   NodePort    10.96.128.137    <none>        8080:30880/TCP   3mbootcamp-1   NodePort    10.109.2.56      <none>        8080:30881/TCP   3mbootcamp-2   NodePort    10.102.181.193   <none>        8080:30882/TCP   3m

2个实例:

[jinqing@host-10-240-79-10 statefulset]$ kubectl get pod -n jq -o wideNAME         READY     STATUS    RESTARTS   AGE       IP            NODEbootcamp-0   1/1       Running   0          4m        10.244.0.42   host-10-240-79-10bootcamp-1   1/1       Running   0          4m        10.244.1.63   host-10-240-79-11

访问服务必须指定节点,不会自动转发:

[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.10:30880Hello Kubernetes bootcamp! | Running on: bootcamp-0 | v=1[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.10:30881curl: (7) Failed connect to 10.240.79.10:30881; Connection timed out[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30880curl: (7) Failed connect to 10.240.79.11:30880; Connection timed out[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1

没有负载均衡,30881端口总是访问 bootcamp-1:

[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1

也可以从外网访问.

30882 端口无法连接:

[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30882curl: (7) Failed connect to 10.240.79.11:30882; Connection refused[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.10:30882curl: (7) Failed connect to 10.240.79.10:30882; Connection refused

3个端口都有监听:

[root@host-10-240-79-11 tmp]# netstat -ntl | grep 3088tcp6       0      0 :::30881                :::*                    LISTEN     tcp6       0      0 :::30882                :::*                    LISTEN     tcp6       0      0 :::30880                :::*                    LISTEN     

iptables-save 输出如下, 其中 10.244是Pod的网段。

没有实例运行的节点上,会丢弃请求:

-A KUBE-NODEPORTS -s 127.0.0.0/8 -p tcp -m comment --comment "jq/bootcamp-1:" -m tcp --dport 30881 -j KUBE-MARK-MASQ-A KUBE-NODEPORTS -p tcp -m comment --comment "jq/bootcamp-1:" -m tcp --dport 30881 -j KUBE-XLB-LJXDQ4W47M42IZBH-A KUBE-NODEPORTS -s 127.0.0.0/8 -p tcp -m comment --comment "jq/bootcamp-0:" -m tcp --dport 30880 -j KUBE-MARK-MASQ-A KUBE-NODEPORTS -p tcp -m comment --comment "jq/bootcamp-0:" -m tcp --dport 30880 -j KUBE-XLB-U5NEOQT6R5WSBVOH-A KUBE-XLB-LJXDQ4W47M42IZBH -s 10.244.0.0/16 -m comment --comment "Redirect pods trying to reach external loadbalancer VIP to clusterIP" -j KUBE-SVC-LJXDQ4W47M42IZBH-A KUBE-XLB-LJXDQ4W47M42IZBH -m comment --comment "jq/bootcamp-1: has no local endpoints" -j KUBE-MARK-DROP-A KUBE-XLB-U5NEOQT6R5WSBVOH -s 10.244.0.0/16 -m comment --comment "Redirect pods trying to reach external loadbalancer VIP to clusterIP" -j KUBE-SVC-U5NEOQT6R5WSBVOH-A KUBE-XLB-U5NEOQT6R5WSBVOH -m comment --comment "jq/bootcamp-0: has no local endpoints" -j KUBE-MARK-DROP

有实例运行的节点上会转发给 Pod 8080:

-A KUBE-NODEPORTS -s 127.0.0.0/8 -p tcp -m comment --comment "jq/bootcamp-0:" -m tcp --dport 30880 -j KUBE-MARK-MASQ-A KUBE-NODEPORTS -p tcp -m comment --comment "jq/bootcamp-0:" -m tcp --dport 30880 -j KUBE-XLB-U5NEOQT6R5WSBVOH-A KUBE-NODEPORTS -s 127.0.0.0/8 -p tcp -m comment --comment "jq/bootcamp-1:" -m tcp --dport 30881 -j KUBE-MARK-MASQ-A KUBE-NODEPORTS -p tcp -m comment --comment "jq/bootcamp-1:" -m tcp --dport 30881 -j KUBE-XLB-LJXDQ4W47M42IZBH-A KUBE-XLB-LJXDQ4W47M42IZBH -s 10.244.0.0/16 -m comment --comment "Redirect pods trying to reach external loadbalancer VIP to clusterIP" -j KUBE-SVC-LJXDQ4W47M42IZBH-A KUBE-XLB-LJXDQ4W47M42IZBH -m comment --comment "Balancing rule 0 for jq/bootcamp-1:" -j KUBE-SEP-LJQA4WUIKJUQ5ALU-A KUBE-XLB-U5NEOQT6R5WSBVOH -s 10.244.0.0/16 -m comment --comment "Redirect pods trying to reach external loadbalancer VIP to clusterIP" -j KUBE-SVC-U5NEOQT6R5WSBVOH-A KUBE-XLB-U5NEOQT6R5WSBVOH -m comment --comment "jq/bootcamp-0: has no local endpoints" -j KUBE-MARK-DROP-A KUBE-SEP-LJQA4WUIKJUQ5ALU -s 10.244.1.63/32 -m comment --comment "jq/bootcamp-1:" -j KUBE-MARK-MASQ-A KUBE-SEP-LJQA4WUIKJUQ5ALU -p tcp -m comment --comment "jq/bootcamp-1:" -m tcp -j DNAT --to-destination 10.244.1.63:8080

30882 端口无法连接

-A KUBE-EXTERNAL-SERVICES -p tcp -m comment --comment "jq/bootcamp-2: has no endpoints" -m addrtype --dst-type LOCAL -m tcp --dport 30882 -j REJECT --reject-with icmp-port-unreachable
  • 1

测试下扩容:

[jinqing@host-10-240-79-10 statefulset]$ kubectl get statefulset -n jqNAME       DESIRED   CURRENT   AGEbootcamp   2         2         45m[jinqing@host-10-240-79-10 statefulset]$ kubectl scale --replicas=3 statefulset/bootcamp -n jqstatefulset.apps "bootcamp" scaled[jinqing@host-10-240-79-10 statefulset]$ kubectl get statefulset -n jqNAME       DESIRED   CURRENT   AGEbootcamp   3         3         47m[jinqing@host-10-240-79-10 statefulset]$ kubectl get pod -n jq -o wideNAME         READY     STATUS    RESTARTS   AGE       IP            NODEbootcamp-0   1/1       Running   0          48m       10.244.0.42   host-10-240-79-10bootcamp-1   1/1       Running   0          48m       10.244.1.63   host-10-240-79-11bootcamp-2   1/1       Running   0          45s       10.244.2.60   host-10-240-79-12[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.12:30882Hello Kubernetes bootcamp! | Running on: bootcamp-2 | v=1



【转载】原文地址:https://blog.csdn.net/jq0123/article/details/81042119


5 个回复

正序浏览
优秀
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
奈斯
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马