kubernetes 상태 서비스 내보내기

kubernetes 상태 서비스 내보내기
김경의 칼럼 2018.7
온라인 게임 서버의 방 서버는 상태 서버로kubernetesstatefulset으로 여러 개의 실례를 열 수 있습니다.
클라이언트가 방 서버를 직접 연결할 수 있도록statefulset이 요구하는 headless 서비스를 제외하고는 모든 실례를 위해 NodePort 형식의 서비스를 만들고 Pod를 선택하고 전송을 금지해야 합니다.
아래bootcamp.yml는 먼저 bootcamp headless 서비스(cluster IP: None)를 만들었고 bootcamp StatefulSet를 만들었습니다. 실례 개수는 2입니다.그리고 bootcamp-0,1,2 서비스를 만들고 각각bootcamp-0,1,2pod에 대응합니다.
서비스 개수가 실례 개수보다 많은 것은 서비스가 대응하는 실례가 없을 때의 표현을 테스트하고자 하는 것이다.
네트워크 게임의 일치 서버는 클라이언트에게 방을 분배하고bootcamp-0,1,2pod가 있는 노드의 외부 네트워크 IP를 열거하며 대응하는 서비스의 포트와 연결하여 클라이언트에게 전송하여 클라이언트를 직접 연결시킨다.
[jinqing@host-10-240-79-10 statefulset]$ cat bootcamp.yml 
apiVersion: v1
kind: Service
metadata:
  name: bootcamp
  namespace: jq
  labels:
    name: bootcamp
spec:
  ports:
    - port: 8080
  clusterIP: None  # StatefulSet Headless 
  selector:
    app: bootcamp  #   bootcamp  

---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: bootcamp
  namespace: jq
spec:
  serviceName: bootcamp  #   Headless  
  replicas: 2
  template:
    metadata:
      labels:
        app: bootcamp  #  ,  selector  
    spec:
      containers:
      - name: bootcamp
        image: docker.io/jocatalin/kubernetes-bootcamp:v1

---
kind: Service
apiVersion: v1
metadata:
  name: bootcamp-0
  namespace: jq
spec:
  type: NodePort  #  
  externalTrafficPolicy: Local  #  
  selector:
    app: bootcamp
    statefulset.kubernetes.io/pod-name: bootcamp-0  #   pod
  ports:
  - protocol: TCP
    nodePort: 30880  #  
    port: 8080
---
kind: Service
apiVersion: v1
metadata:
  name: bootcamp-1
  namespace: jq
spec:
  type: NodePort
  externalTrafficPolicy: Local
  selector:
    app: bootcamp
    statefulset.kubernetes.io/pod-name: bootcamp-1
  ports:
  - protocol: TCP
    nodePort: 30881
    port: 8080
---
kind: Service
apiVersion: v1
metadata:
  name: bootcamp-2
  namespace: jq
spec:
  type: NodePort
  externalTrafficPolicy: Local
  selector:
    app: bootcamp
    statefulset.kubernetes.io/pod-name: bootcamp-2
  ports:
  - protocol: TCP
    nodePort: 30882
    port: 8080

statefulset의 실례마다 다른 탭이 있기 때문에 서비스에 실례를 선택할 수 있습니다.
externalTrafficPolicy: Local 설정을 사용하여 전송을 금지합니다.참고 서비스.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" created
statefulset.apps "bootcamp" created
service "bootcamp-0" created
service "bootcamp-1" created
service "bootcamp-2" created

서비스는 다음과 같습니다.
[jinqing@host-10-240-79-10 statefulset]$ kubectl get service -n jq
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
bootcamp     ClusterIP   None             <none>        8080/TCP         3m
bootcamp-0   NodePort    10.96.128.137    <none>        8080:30880/TCP   3m
bootcamp-1   NodePort    10.109.2.56      <none>        8080:30881/TCP   3m
bootcamp-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 wide
NAME         READY     STATUS    RESTARTS   AGE       IP            NODE
bootcamp-0   1/1       Running   0          4m        10.244.0.42   host-10-240-79-10
bootcamp-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:30880
Hello Kubernetes bootcamp! | Running on: bootcamp-0 | v=1
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.10:30881
curl: (7) Failed connect to 10.240.79.10:30881; Connection timed out
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30880
curl: (7) Failed connect to 10.240.79.11:30880; Connection timed out
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1

로드 밸런싱 없이 30881 포트는 항상 bootcamp-1에 액세스합니다.
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1

외부 네트워크에서도 접근할 수 있다.
30882 포트에 접속할 수 없음:
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30882
curl: (7) Failed connect to 10.240.79.11:30882; Connection refused
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.10:30882
curl: (7) Failed connect to 10.240.79.10:30882; Connection refused

3개의 포트 모두 감청:
[root@host-10-240-79-11 tmp]# netstat -ntl | grep 3088
tcp6       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

테스트에서 확장:
[jinqing@host-10-240-79-10 statefulset]$ kubectl get statefulset -n jq
NAME       DESIRED   CURRENT   AGE
bootcamp   2         2         45m
[jinqing@host-10-240-79-10 statefulset]$ kubectl scale --replicas=3 statefulset/bootcamp -n jq
statefulset.apps "bootcamp" scaled
[jinqing@host-10-240-79-10 statefulset]$ kubectl get statefulset -n jq
NAME       DESIRED   CURRENT   AGE
bootcamp   3         3         47m
[jinqing@host-10-240-79-10 statefulset]$ kubectl get pod -n jq -o wide
NAME         READY     STATUS    RESTARTS   AGE       IP            NODE
bootcamp-0   1/1       Running   0          48m       10.244.0.42   host-10-240-79-10
bootcamp-1   1/1       Running   0          48m       10.244.1.63   host-10-240-79-11
bootcamp-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:30882
Hello Kubernetes bootcamp! | Running on: bootcamp-2 | v=1

좋은 웹페이지 즐겨찾기