LoginSignup
2
5

More than 3 years have passed since last update.

[Kubernetes]LoadBalancerサービスの動作を確認する

Last updated at Posted at 2020-04-11

はじめに

これまでServiceとして、ClusterIPやExternalIP、NodePortの動作を確認してきました。
クラスタの外部と通信できるサービスにはExternalIP、NodePortがありましたが、どちらもある1つのクラスタノードが外部との通信の入口となるため、ノード障害があった場合、通信できなくなります。
それを防ぐために、外部のLoadBalancerを使用した「LoadBalancerサービス」があります。使用できる外部のLoadBalancerはAWSなどのクラウドプロバイダーの機能を利用するのが一般的です。
利用できるクラウドプロバイダーの注意事項などはマニュアルに記載されています。IBM Cloudも使えると思いますが、書かれてないですね。

LoadBalancerタイプ
kubernetes.io

LoadBalancerの実装

上記のように「LoadBalancerサービス」を使用するには、外部のLoadBalancerが必要になります。が、今回の検証環境ではありません。
そもそも、1台のPCでVM切って作ってますからね。
そこで、今回はオンプレ上にLoadBalancerを実装できる「MetalLB」を使用しました。

MetalLBのインストール

ちゃんとログを取ってなかったので、概要だけご紹介します。
特に難しいことはなく、マニュアルの通りにできました。

MetalLB Installation

kubectl edit configmap -n kube-system kube-proxy

and set:

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
 strictARP: true

To install MetalLB, apply the manifest:

kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.9.3/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.9.3/manifests/metallb.yaml
# On first install only
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"

ConfigMapの作成

Layer 2 configuration

l2.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: my-ip-space
      protocol: layer2
      addresses:
      - 10.20.30.150-10.20.30.200

addressesは環境に合わせて指定します。

実装結果の確認

上記の結果、以下のように設定されました。これでLoadBalancerサービスの動作を確認できます。

$ kubectl -n metallb-system get all -o wide
NAME                              READY   STATUS    RESTARTS   AGE   IP               NODE           NOMINATED NODE   READINESS GATES
pod/controller-5c9894b5cd-59tmn   1/1     Running   2          24h   192.168.69.198   k8s-worker02   <none>           <none>
pod/speaker-l99nt                 1/1     Running   3          24h   10.20.30.10      k8s-master     <none>           <none>
pod/speaker-scqps                 1/1     Running   4          24h   10.20.30.20      k8s-worker01   <none>           <none>
pod/speaker-vdh69                 1/1     Running   4          24h   10.20.30.30      k8s-worker02   <none>           <none>

NAME                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                 AGE   CONTAINERS   IMAGES                   SELECTOR
daemonset.apps/speaker   3         3         3       3            3           beta.kubernetes.io/os=linux   24h   speaker      metallb/speaker:v0.9.3   app=metallb,component=speaker

NAME                         READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                      SELECTOR
deployment.apps/controller   1/1     1            1           24h   controller   metallb/controller:v0.9.3   app=metallb,component=controller

NAME                                    DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES                      SELECTOR
replicaset.apps/controller-5c9894b5cd   1         1         1       24h   controller   metallb/controller:v0.9.3   app=metallb,component=controller,pod-template-hash=5c9894b5cd

LoadBalancerサービスの作成

以下のマニフェストを作成しました。spec.typeが「LoadBalancer」である以外は、NodePortと同じですね。

sample-lb.yaml
apiVersion: v1
kind: Service
metadata:
  name: load-balancer
spec:
  ports:
  - name: load-balancer
    port: 8080
    protocol: TCP
    targetPort: 80
    nodePort: 30002
  selector:
    app: nginx-dep
  type: LoadBalancer

このマニフェストをapplyします。

$ kubectl apply -f sample-lb.yaml
service/load-balancer created
$ kubectl get svc
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)          AGE
kubernetes      ClusterIP      10.96.0.1       <none>         443/TCP          45d
load-balancer   LoadBalancer   10.102.190.16   10.20.30.150   8080:30002/TCP   4s
$ kubectl describe svc load-balancer
Name:                     load-balancer
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"load-balancer","namespace":"default"},"spec":{"ports":[{"name":"l...
Selector:                 app=nginx-dep
Type:                     LoadBalancer
IP:                       10.102.190.16
LoadBalancer Ingress:     10.20.30.150
Port:                     load-balancer  8080/TCP
TargetPort:               80/TCP
NodePort:                 load-balancer  30002/TCP
Endpoints:                192.168.69.251:80,192.168.79.110:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type    Reason        Age   From                Message
  ----    ------        ----  ----                -------
  Normal  IPAllocated   18s   metallb-controller  Assigned IP "10.20.30.150"
  Normal  nodeAssigned  18s   metallb-speaker     announcing from node "k8s-worker02"

LoadBalancerサービスのEXTERNAL-IPに外部LoadBalancerからIPアドレスがアサインされてますね。なお、外部LoadBalancerがない場合、サービスの作成はできますが、EXTERNAL-IPが<pending>になったままになります。

動作確認

LoadBalancerサービスを作成すると、NodePortとClusterIPも作成されます。ここでは、各レイヤー(Service)の動作を確認したいと思います。

LoadBalancerサービス

まずは、LoadBalancerの動作を確認してみたいと思います。
これまでと同様に、gatewayから疎通を確認します。

[gateway ~]$ for i in 1 2 3 4 5; do curl -s http://10.20.30.150:8080 | grep pod; sleep 5; done
pod1
pod2
pod1
pod2
pod1

疎通の確認とバランシングされていることがわかりますね。

NodePort

今度はNodePortとしての動作も確認してみたいと思います。

[gateway ~]$ for i in 1 2 3 4 5; do curl -s http://k8s-worker01:30002 | grep pod; sleep 5; done
pod1
pod2
pod1
pod2
pod1
[gateway ~]$ for i in 1 2 3 4 5; do curl -s http://k8s-worker02:30002 | grep pod; sleep 5; done
pod1
pod2
pod1
pod2
pod1

NodePortとしても動作していますね。

ClusterIP

次にClusterIPとしての動作も確認します。
以下のマニフェストのPodをデプロイして、logを確認します。

test_pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: centos
      image: centos:latest
      command:
      - sh
      - -c
      args:
      - for i in 1 2 3 4 5 ; do curl -s http://load-balancer.default.svc.cluster.local:8080 ; sleep 5; done ;exit 0
$ kubectl apply -f test_pod.yaml
pod/test-pod created
$ kubectl logs test-pod | grep pod
pod1
pod2
pod1
pod2
pod1

ClusterIPとしての動作も確認できます。

まとめ

今回はLoadBalancerの動作を確認しました。LoadBalancerサービスを作成すると、NodePortとClusterIPも同時に作成されますので、3層構造のような感じですね。

image.png

LoadBalancerは各workerノードにバランシングして、クラスタ内はClusterIPがバランシングするような動作だとわかりやすいです。
ただ、マニュアルには以下のように記載されていますので、この理解は厳密には違うのかも知れません。

LoadBalancerタイプ
外部のロードバランサーからのトラフィックはバックエンドのPodに直接転送されます。

これまでClusterIP、NodePort、LoadBalancerと順を追って動作を確認してきましたので、理解しやすかったです。
また、オンプレ環境でもLoadBalancerを使えることが確認できましたので、開発環境はクラウドを使わずにPCで開発してもよいですね。

補足

その他のパラメータについて、以下に記載します。

externalTrafficPolicy

NodePortと同じ動作です。詳細はこちらをご覧ください。
[Kubernetes]NodePortサービスの動作を確認する 2

loadBalancerIP

LoadBalancerサービスに付与されるIPアドレスは、特に指定しなければ自動でアサインされます。
しかし、「spec.loadBalancerIP」パラメータを設定することで、IPアドレスを指定することができます。
指定できるIPアドレスや指定方法は、クラウドプロバイダーによって異なりますので、各クラウドごとに確認する必要があります。

loadBalancerSourceRanges

外部LoadBalancerのFirewall機能を利用することで、LoadBalancerサービスでのアクセス制御が可能となります。
「spec.loadBalancerSourceRanges」に接続を許可する送信元IPアドレスの範囲を指定します。未指定の場合のデフォルトは、「0.0.0.0/0」なので、全ての通信を許可することになります。
なお、今回の検証環境で動作を試してみましたが、範囲外からの通信を遮断することはできませんでした。外部LoadBalancerのFirewall機能を利用する必要がありますので、今回構築した「MetalLB」に機能がないのか、設定できてないかだと思います。

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5