[K 8 s]サービス


1.サービス


1-1. サービスとは?


パイドで実行されているアプリケーションをネットワークサービスに暴露する方法

1-2. サービス・タイプ


クラスタIPタイプ


クバーネディス内部がフォードに近い場合にのみ使用されます.外部に露出しないので、クバーネディスクラスタ内部で使用するフォードに適しています.

NodePortタイプ


クラスタ内のすべてのノードに同じポートを開き、シードにアクセスします.そのため、外部からフォードに近づくことができるサービスタイプです.
アクセス可能なポートはランダムに決定されますが、特定のポートにアクセスするように設定できます.

LoadBarangerタイプ


クラウドプラットフォームが提供する負荷バランサを動的に構成し、フォードに接続します.
NodePortタイプと同様に、フォードに外部からアクセスできるサービスタイプです.ただし、AWS、GCPなどのクラウドプラットフォーム環境でのみ使用できます.

2. Cluster IP Services


2-1. シードの作成


Yamlテンプレート

  • pod.yaml
  • apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: deploy-cndk
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: deploy-websrv
      template:
        metadata:
          labels:
            app: deploy-websrv
        spec:
          containers:
          - name: cndk-websrv
            image: gcr.io/google-samples/kubernetes-bootcamp:v1
            ports:
            - containerPort: 8080

    作成と確認


    作成
  • # kubectl apply -f pod.yaml
    deployment.apps/deploy-cndk created
  • 確認
  • # watch -d 'kubectl get pods,svc,ep -o wide'
    Every 2.0s: kubectl get pods,svc,ep -o wide                                                                                                          master: Sun Jul 18 03:47:37 2021
    
    NAME                               READY   STATUS    RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
    pod/deploy-cndk-6cbc8c75db-fjd4v   1/1     Running   0          4m27s   172.16.189.102   worker2   <none>           <none>
    pod/deploy-cndk-6cbc8c75db-nssqs   1/1     Running   0          4m27s   172.16.182.38    worker3   <none>           <none>
    pod/deploy-cndk-6cbc8c75db-zs2lg   1/1     Running   0          4m28s   172.16.235.136   worker1   <none>           <none>
    
    NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
    service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   12m   <none>
    
    NAME                   ENDPOINTS            AGE
    endpoints/kubernetes   192.168.1.211:6443   12m

    2-2. 接続テスト用シード配布(Master)


    Yamlテンプレート

  • podnet.yaml
  • NodeNameにマスターノードの名前を入力
    apiVersion: v1
    kind: Pod
    metadata:
      name: netshoot-pod
    spec:
      **nodeName: master**
      containers:
      - name: netshoot-pod
        image: nicolaka/netshoot
        command: ["tail"]
        args: ["-f", "/dev/null"]

    作成と確認


    作成
  • # kubectl apply -f podnet.yaml
    pod/netshoot-pod created
  • 確認
  • # watch -d 'kubectl get pods,svc,ep -o wide'
    Every 2.0s: kubectl get pods,svc,ep -o wide                                                                                                          master: Sun Jul 18 03:48:42 2021
    
    NAME                               READY   STATUS    RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
    pod/deploy-cndk-6cbc8c75db-fjd4v   1/1     Running   0          5m32s   172.16.189.102   worker2   <none>           <none>
    pod/deploy-cndk-6cbc8c75db-nssqs   1/1     Running   0          5m32s   172.16.182.38    worker3   <none>           <none>
    pod/deploy-cndk-6cbc8c75db-zs2lg   1/1     Running   0          5m33s   172.16.235.136   worker1   <none>           <none>
    **pod/netshoot-pod                   1/1     Running   0          15s     172.16.219.70    master    <none>           <none>**
    
    NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
    service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   13m   <none>
    
    NAME                   ENDPOINTS            AGE
    endpoints/kubernetes   192.168.1.211:6443   13m
    
    # kubectl exec -it netshoot-pod -- zsh
                        dP            dP                           dP   
                        88            88                           88   
    88d888b. .d8888b. d8888P .d8888b. 88d888b. .d8888b. .d8888b. d8888P 
    88'  `88 88ooood8   88   Y8ooooo. 88'  `88 88'  `88 88'  `88   88   
    88    88 88.  ...   88         88 88    88 88.  .88 88.  .88   88   
    dP    dP `88888P'   dP   `88888P' dP    dP `88888P' `88888P'   dP   
                                                                        
    Welcome to Netshoot! (github.com/nicolaka/netshoot)
                                                                    
    

    2-3. 導入サービス(クラスタIPタイプ)


    Yamlテンプレート

  • svc-clusterip.yaml
  • apiVersion: v1
    kind: Service
    metadata:
      name: svc-clusterip
    spec:
      ports:
        - name: svc-webport
          **port: 9000
          targetPort: 8080**
      selector:
        app: deploy-websrv
      **type: ClusterIP**

    作成と確認


    作成
  • # kubectl apply -f svc-clusterip.yaml
    service/svc-clusterip created
  • 確認
  • # watch -d 'kubectl get pods,svc,ep -o wide'
    Every 2.0s: kubectl get pods,svc,ep -o wide                                                                                                          master: Sun Jul 18 03:57:19 2021
    
    NAME                               READY   STATUS    RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
    pod/deploy-cndk-6cbc8c75db-fjd4v   1/1     Running   0          14m     172.16.189.102   worker2   <none>           <none>
    pod/deploy-cndk-6cbc8c75db-nssqs   1/1     Running   0          14m     172.16.182.38    worker3   <none>           <none>
    pod/deploy-cndk-6cbc8c75db-zs2lg   1/1     Running   0          14m     172.16.235.136   worker1   <none>           <none>
    pod/netshoot-pod                   1/1     Running   0          8m52s   172.16.219.70    master    <none>           <none>
    
    NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE   SELECTOR
    service/kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP    22m   <none>
    **service/svc-clusterip   ClusterIP   10.104.187.17   <none>        9000/TCP   29s   app=deploy-websrv**
    
    NAME                      ENDPOINTS                                                    AGE
    endpoints/kubernetes      192.168.1.211:6443                                           22m
    **endpoints/svc-clusterip   172.16.182.38:8080,172.16.189.102:8080,172.16.235.136:8080   29s**
    
    [root@master dkos-w05 (|kube:default)]# curl 10.104.187.17:9000
    Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-nssqs | v=1
    [root@master dkos-w05 (|kube:default)]# curl 10.104.187.17:9000
    Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-fjd4v | v=1
    [root@master dkos-w05 (|kube:default)]# curl 10.104.187.17:9000
    Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-zs2lg | v=1
    [root@master dkos-w05 (|kube:default)]# curl 10.104.187.17:9000
    Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-zs2lg | v=1
    [root@master dkos-w05 (|kube:default)]# curl 10.104.187.17:9000
    Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-nssqs | v=1
    [root@master dkos-w05 (|kube:default)]#
    作成したサービス(クラスタIP)により,クラスタ内部から3バンドに接続できる. しかし,欠点はクラスタ外部に接続できないことである. これを克服するために、NodePortサービスタイプを利用してみます。

    削除
  • # kubectl delete deploy,svc --all
    deployment.apps "deploy-cndk" deleted
    service "kubernetes" deleted
    service "svc-clusterip" deleted

    3. NodePort Services


    3-1. シードの作成


    Yamlテンプレート

  • nginx11.yaml
  • apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: deploy-nginx11
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: deploy-nginx11
      template:
        metadata:
          labels:
            app: deploy-nginx11
        spec:
          containers:
          - name: deploy-nginx11
            image: nginx:1.11

    作成と確認


    作成
  • # kubectl apply -f nginx11.yaml
    deployment.apps/deploy-nginx11 created
  • 確認
  • # watch -d 'kubectl get pods,svc,ep -o wide'
    Every 2.0s: kubectl get pods,svc,ep -o wide                                                                                                          master: Sun Jul 18 04:27:14 2021
    
    NAME                                  READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
    pod/deploy-nginx11-656d5495b7-9rndv   1/1     Running   0          94s   172.16.235.137   worker1   <none>           <none>
    pod/deploy-nginx11-656d5495b7-km865   1/1     Running   0          94s   172.16.189.103   worker2   <none>           <none>
    pod/deploy-nginx11-656d5495b7-xw8sk   1/1     Running   0          94s   172.16.182.39    worker3   <none>           <none>
    
    NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
    service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   10m   <none>
    
    NAME                   ENDPOINTS            AGE
    endpoints/kubernetes   192.168.1.211:6443   10m

    3-2. 接続テスト用シード配布(Master)


    上記の実践で使用したpodnet.yamlの作成または削除
    # watch -d 'kubectl get pods,svc,ep -o wide'
    Every 2.0s: kubectl get pods,svc,ep -o wide                                                                                                          master: Sun Jul 18 04:27:53 2021
    
    NAME                                  READY   STATUS    RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
    pod/deploy-nginx11-656d5495b7-9rndv   1/1     Running   0          2m13s   172.16.235.137   worker1   <none>           <none>
    pod/deploy-nginx11-656d5495b7-km865   1/1     Running   0          2m13s   172.16.189.103   worker2   <none>           <none>
    pod/deploy-nginx11-656d5495b7-xw8sk   1/1     Running   0          2m13s   172.16.182.39    worker3   <none>           <none>
    **pod/netshoot-pod                      1/1     Running   0          31m     172.16.219.70    master    <none>           <none>**
    
    NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
    service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   11m   <none>
    
    NAME                   ENDPOINTS            AGE
    endpoints/kubernetes   192.168.1.211:6443   11m

    3-3. NodePortサービスの導入


    Yamlテンプレート

  • svc-nodeport.yaml
  • apiVersion: v1
    kind: Service
    metadata:
      name: svc-nodeport
    spec:
      ports:
        - name: svc-webport
          port: 9000
          targetPort: 80
    ****        ports:
            - containerPort: 8080
      selector:
        app: deploy-nginx11
      **type: NodePort**

    作成と確認


    作成
  • # kubectl apply -f svc-nodeport.yaml
    service/svc-nodeport created
  • 確認
  • # watch -d 'kubectl get pods,svc,ep -o wide'
    Every 2.0s: kubectl get pods,svc,ep -o wide                                                                                                          master: Sun Jul 18 04:30:09 2021
    
    NAME                                  READY   STATUS    RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
    pod/deploy-nginx11-656d5495b7-9rndv   1/1     Running   0          4m30s   172.16.235.137   worker1   <none>           <none>
    pod/deploy-nginx11-656d5495b7-km865   1/1     Running   0          4m30s   172.16.189.103   worker2   <none>           <none>
    pod/deploy-nginx11-656d5495b7-xw8sk   1/1     Running   0          4m30s   172.16.182.39    worker3   <none>           <none>
    pod/netshoot-pod                      1/1     Running   0          41m     172.16.219.70    master    <none>           <none>
    
    NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE   SELECTOR
    service/kubernetes     ClusterIP   10.96.0.1      <none>        443/TCP          13m   <none>
    **service/svc-nodeport   NodePort    10.97.24.204   <none>        9000:30000/TCP   23s   app=deploy-nginx11**
    
    NAME                     ENDPOINTS                                              AGE
    endpoints/kubernetes     192.168.1.211:6443                                     13m
    **endpoints/svc-nodeport   172.16.182.39:80,172.16.189.103:80,172.16.235.137:80   22s**
    
    # curl localhost:30000
    # curl 192.168.1.211:30000
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    ... 생략 ...
    
    # curl 10.97.24.204:9000
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    ... 생략 ...
    
    # Worker Node 1
    # curl 192.168.1.212:30000
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    ... 생략 ...
    
    # Worker Node 2
    # curl 192.168.1.213:30000
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    ... 생략 ...
    
    # Worker Node 3
    # curl 192.168.1.214:30000
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    ... 생략 ...
    
    <サービスIP内部ポート(9000)>を使用して接続できます。 <プライマリノード:外部ポート(30000)>接続をサポートします。 また、<ワークノード:外部ポート(30000)>を使用して接続することもできます。

    削除
  • # kubectl delete deploy,svc --all
    deployment.apps "deploy-nginx11" deleted
    service "kubernetes" deleted
    service "svc-nodeport" deleted

    4. LoadBalancer Services


    外部クライアントに接続する場合は、kube-proxyに直接アクセスするのではなく、そのフロントエンドにあり、Load Bankにアクセスします.
    クラウド事業者については,それぞれ実現するLoadBank,OnPremisについてはMetalbなどのLoadBankを用いて実現する.
    現在の実習環境はオンライン予習なので、METALLBで実習しています.

    4-1. Metalbの概要

  • は、オープン環境でロード・バランシング・サービスを実現します.
  • Memberlistの2つのモード:第2層モード(IPv 4-ARP、IPv 6-NDP)、BGPモード
  • Layer 2モード:メンバー(ノード)の1つのノードがキャプテンとして1つのサービスIP(ARP応答)→単一ノードボトルネック(単一ノードボトルネック)}を受け入れることで、負荷をトップルータからECMPパスに分散することができる.
  • BGPモード:フェイルオーバー時により早くカットできるが、最終的には1つの位置から処理→第2層上のルータECMPを導入する方が効率的!
  • インストール
  • :Kubernetesリスト、Kustomize、またはHelm
  • 4-2. インストールMetalb(Kubernetesリスト)

  • 公式文書:https://metallb.universe.tf/installation/2
  • インストールと検証

  • 取付
  • # kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/namespace.yaml
    namespace/metallb-system created
    # kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/metallb.yaml
    Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
    podsecuritypolicy.policy/controller created
    podsecuritypolicy.policy/speaker created
    serviceaccount/controller created
    serviceaccount/speaker created
    clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
    clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
    role.rbac.authorization.k8s.io/config-watcher created
    role.rbac.authorization.k8s.io/pod-lister created
    role.rbac.authorization.k8s.io/controller created
    clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
    clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
    rolebinding.rbac.authorization.k8s.io/config-watcher created
    rolebinding.rbac.authorization.k8s.io/pod-lister created
    rolebinding.rbac.authorization.k8s.io/controller created
    daemonset.apps/speaker created
    deployment.apps/controller created
  • 確認
  • # kubectl get namespaces
    NAME              STATUS   AGE
    default           Active   32d
    ingress-nginx     Active   6d16h
    kube-node-lease   Active   32d
    kube-public       Active   32d
    kube-system       Active   32d
    **metallb-system    Active   44s**
    
    # kubectl get all -n metallb-system
    NAME                              READY   STATUS    RESTARTS   AGE
    pod/controller-6b78bff7d9-9nl82   1/1     Running   0          46s
    pod/speaker-68jzn                 1/1     Running   0          46s
    pod/speaker-6xcvb                 1/1     Running   0          46s
    pod/speaker-l9b8w                 1/1     Running   0          46s
    pod/speaker-rpctf                 1/1     Running   0          46s
    
    NAME                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
    daemonset.apps/speaker   4         4         4       4            4           kubernetes.io/os=linux   46s
    
    NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/controller   1/1     1            1           46s
    
    NAME                                    DESIRED   CURRENT   READY   AGE
    replicaset.apps/controller-6b78bff7d9   1         1         1       46s

    設定

  • metallb-config.yaml
  • apiVersion: v1
    kind: ConfigMap
    metadata:
      namespace: metallb-system
      name: config
    data:
      config: |
        address-pools:
        - name: default
          protocol: layer2
          addresses:
          - 192.168.1.221-192.168.1.229
  • 構成
  • # kubectl apply -f metallb-config.yaml
    configmap/config created

    4-3. シードの作成


    上記の実践で使用したpod.yamlテンプレートを使用

    作成と確認


    作成
  • # kubectl apply -f pod.yaml
    deployment.apps/deploy-cndk created
  • 確認
  • # watch -d 'kubectl get pods,svc,ep -o wide'
    Every 2.0s: kubectl get pods,svc,ep -o wide                                                                                                          master: Sun Jul 18 05:18:51 2021
    
    NAME                               READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
    **pod/deploy-cndk-6cbc8c75db-cscvj   1/1     Running   0          8s    172.16.235.139   worker1   <none>           <none>
    pod/deploy-cndk-6cbc8c75db-h5htx   1/1     Running   0          8s    172.16.182.40    worker3   <none>           <none>
    pod/deploy-cndk-6cbc8c75db-jsbp7   1/1     Running   0          8s    172.16.189.104   worker2   <none>           <none>**
    pod/netshoot-pod                   1/1     Running   0          90m   172.16.219.70    master    <none>           <none>
    
    NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
    service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   30m   <none>
    
    NAME                   ENDPOINTS            AGE
    endpoints/kubernetes   192.168.1.211:6443   30m

    4-4. リモートLBサービスの導入


    Yamlテンプレート

  • mtlb.yaml
  • apiVersion: v1
    kind: Service
    metadata:
      name: svc-mtlb-1
    spec:
      ports:
        - name: svc-mtlb-webport
          port: 9000
          targetPort: 8080
          nodePort: 30001
      selector:
        app: deploy-websrv
      type: LoadBalancer
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: svc-mtlb-2
    spec:
      ports:
        - name: svc-mtlb-webport
          port: 9000
          targetPort: 8080
          nodePort: 30002
      selector:
        app: deploy-websrv
      type: LoadBalancer
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: svc-mtlb-3
    spec:
      ports:
        - name: svc-mtlb-webport
          port: 9000
          targetPort: 8080
          nodePort: 30003
      selector:
        app: deploy-websrv
      type: LoadBalancer

    作成と確認


    作成
  • # kubectl apply -f mtlb.yaml
    service/svc-mtlb-1 created
    service/svc-mtlb-2 created
    service/svc-mtlb-3 created
  • 確認
  • # watch -d 'kubectl get pods,svc,ep -o wide'
    Every 2.0s: kubectl get pods,svc,ep -o wide                                                                                                          master: Sun Jul 18 05:32:34 2021
    
    NAME                               READY   STATUS    RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
    pod/deploy-cndk-6cbc8c75db-h5htx   1/1     Running   0          13m     172.16.182.40    worker3   <none>           <none>
    pod/deploy-cndk-6cbc8c75db-jsbp7   1/1     Running   0          13m     172.16.189.104   worker2   <none>           <none>
    pod/deploy-cndk-6cbc8c75db-pbgzz   1/1     Running   0          3m26s   172.16.182.41    worker3   <none>           <none>
    pod/netshoot-pod                   1/1     Running   0          104m    172.16.219.70    master    <none>           <none>
    
    NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)          AGE   SELECTOR
    service/kubernetes   ClusterIP      10.96.0.1        <none>          443/TCP          44m   <none>
    **service/svc-mtlb-1   LoadBalancer   10.99.211.249    192.168.1.221   9000:30001/TCP   8s    app=deploy-websrv
    service/svc-mtlb-2   LoadBalancer   10.104.210.238   192.168.1.222   9000:30002/TCP   8s    app=deploy-websrv
    service/svc-mtlb-3   LoadBalancer   10.97.123.170    192.168.1.223   9000:30003/TCP   8s    app=deploy-websrv**
    
    NAME                   ENDPOINTS                                                   AGE
    endpoints/kubernetes   192.168.1.211:6443                                          44m
    **endpoints/svc-mtlb-1   172.16.182.40:8080,172.16.182.41:8080,172.16.189.104:8080   8s
    endpoints/svc-mtlb-2   172.16.182.40:8080,172.16.182.41:8080,172.16.189.104:8080   8s
    endpoints/svc-mtlb-3   172.16.182.40:8080,172.16.182.41:8080,172.16.189.104:8080   8s**
    
    # for i in {1..100}; do curl -s 192.168.1.221:9000 ; done | sort | uniq -c | sort -nr
         42 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-jsbp7 | v=1
         34 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-h5htx | v=1
         24 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-pbgzz | v=1
    # for i in {1..100}; do curl -s 192.168.1.222:9000 ; done | sort | uniq -c | sort -nr
         36 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-h5htx | v=1
         35 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-pbgzz | v=1
         29 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-jsbp7 | v=1
    # for i in {1..100}; do curl -s 192.168.1.223:9000 ; done | sort | uniq -c | sort -nr
         42 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-jsbp7 | v=1
         32 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-pbgzz | v=1
         26 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-h5htx | v=1
    
    # for i in {1..100}; do curl -s 192.168.1.211:30001 ; done | sort | uniq -c | sort -nr
         38 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-h5htx | v=1
         34 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-pbgzz | v=1
         28 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-jsbp7 | v=1
    # for i in {1..100}; do curl -s 192.168.1.211:30002 ; done | sort | uniq -c | sort -nr
         38 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-h5htx | v=1
         33 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-jsbp7 | v=1
         29 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-pbgzz | v=1
    # for i in {1..100}; do curl -s 192.168.1.211:30003 ; done | sort | uniq -c | sort -nr
         35 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-h5htx | v=1
         34 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-jsbp7 | v=1
         31 Hello Kubernetes bootcamp! | Running on: deploy-cndk-6cbc8c75db-pbgzz | v=1
    今回NodePortと違うのはmetallb-configサービスの外部IPはyamlで定義されたアドレス範囲内で生成される.