1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

IKS マルチゾーン クラスタの Ingress (ALB)

Posted at

IBM Cloud Kubernetes サービスでは、クラスタのノードを次のように配置できます。

  • シングルゾーン・クラスタ : 一つのデータセンターに k8sのワーカーノードを配置
  • マルチゾーン・クラスタ  : 複数のデータセンターに k8sのワーカーノードを配置

それぞれのデータセンターは、完全に独立した設備で運営されており、当然ネットワークのアドレスも、データセンター毎に独立しています。そのため、マルチゾーン・クラスタとした場合、データセンター横断で、ロードバランスできなければなりません。

今回は、マルチゾーン・クラスタのイングレスの動作について、確認していきます。

イングレス (Ingress)

イングレスは、k8sのサービス・オブジェクトを、DNS名で外部へ公開するもので、次の特長があります。

  • 利用できるクラスタ: 無料のクラスタでは利用できません。標準クラスタでのみ動作
  • プロトコル: HTTP(80), HTTPS(443) または、TCP / UDP でポート番号を指定可能
  • 一つのドメインネームで、パス部分に複数のアプリケーション(k8sのサービス)に対応づけて、要求をルーティングする。

イングレスの構成要素は、以下の3つです。

1.Ingress Resource  

基本的な設定は、CNCFのAPI仕様に従います。

2. Ingress Container ( IKSでは ALB )

IBMが独自実装する Ingress Controller を ALB (Application LoadBalancer) と表現されており、上記の Ingress Resource で記述されるマニフェストの annotation に、ALB に与える設定を記述します。このドキュメントは以下になります。

3. Multi Zone LoadBalancer (MZLB)

マルチゾーン・クラスタを作成すると、MZLBは自動的に作成されます。この実態は、仮想IPアドレスを持ちリクエストを分配するものでは無く、クラスタを代表するDNSアドレスに各ゾーンのALBのIPアドレスを対応づけます。しかし、DNSのラウンドロビンではありません。この動作には、Cloudflare のマルチゾーン・ロードバランサー(MZLB) が自動作成[1]されるとされていますが、その動作は隠蔽されており、Cloudflareを意識したり、別途注文する必要はありません。

マルチゾーンの MZLB と ALB 動作確認

次のターミナル画面に表示されたマルチゾーンに作成したクラスタがあります。 これは「ワーカー・ゾーン:」にあるように、3つのデータセンター tok02, tok04, tok05 にワーカーノードが配置されています。

$ ibmcloud ks cluster-get iks1

ロケーション:                   tok04
マスター URL:                   https://c1.jp-tok.containers.cloud.ibm.com:31963
マスター・ロケーション:         Tokyo
マスター状況:                   Ready (16 hours ago)
入口サブドメイン:               iks1.jp-tok.containers.appdomain.cloud
入口の秘密:                     iks1
ワーカー:                       4
ワーカー・ゾーン:               tok02, tok05, tok04
バージョン:                     1.12.5_1537
所有者:                         TAKARA@jp.ibm.com
ダッシュボードのモニタリング:   https://metrics.ng.bluemix.net/app/***
リソース・グループ ID:          6fcbec624d904ab19a28a1b75c58d467
リソース・グループ名:           default

これのクラスタのワーカーをリストすると、次のようになります。(見やすくなるように表示を編集しています)ゾーンはデータセンターと同じレベルで、3つのデータセンターで、ベアメタル(mb2c)を含む4つのノードが存在しています。

$ ibmcloud ks workers iks1
OK
ID                             プライベート IP  マシン・タイプ        状態     状況    ゾーン
kube-tok02-cr41679d0177fa-w18  10.132.253.30   u2c.2x4.encrypted     normal   Ready   tok02
kube-tok04-cr41679d0177fa-w11  10.192.9.68     mb2c.4x32.encrypted   normal   Ready   tok04
kube-tok04-cr41679d0177fa-w16  10.192.9.93     u2c.2x4.encrypted     normal   Ready   tok04
kube-tok05-cr41679d0177fa-w17  10.193.10.50    u2c.2x4.encrypted     normal   Ready   tok05

これらの ALB は、各ゾーンのワーカーノード上に、ポッドとして起動しています。そして、それらの上に マルチゾーン・ロードバランサー(MZLB)が動作しています。この動作をコマンドで参照することはできませんが、このクラスタを代表するDNS名でアドレスをひいてみると、MZLBの動作に一端がわかります。以下に、DNS名のアドレス解決結果を挙げます。この「iks1.jp-tok.containers.appdomain.cloud」は3つのIPアドレスに対応していることがわかります。

> iks1.jp-tok.containers.appdomain.cloud
サーバー:  google-public-dns-a.google.com
Address:  8.8.8.8

権限のない回答:
名前:    iks1.jp-tok.containers.appdomain.cloud
Addresses:  165.192.71.230
          128.168.73.198
          169.56.27.94

これの3つのIPアドレスは、旧SoftLayerで開発されたポータブルIPアドレスで、ノードのIPアドレスから独立して確保されたIPアドレスです。各ゾーンのポータブルIPアドレスは、ALBが動作するノードにマップされています。もしも、ノードが停止した場合、ポータブルIPは、同じゾーンの別のワーカーノードに対応づけられ、役割りを継続します。また、ゾーンが動作できなくなった場合は、前述のDNSの割り当て先から削除されリクエストの分配が停止します。

次のコマンド実行結果は、ALBをリストしたものです。 ALB IPに注目してください。先に挙げたドメイン名に対応した IPアドレスと同じことがわかります。

$ ibmcloud ks albs --cluster iks1
OK
ALB ID                                            有効化   状況       タイプ    ALB IP           ゾーン   ビルド
public-cr41679d0177fa4f92ab10262fa586956c-alb1    true     enabled    public    128.168.73.198   tok04    ingress:404/ingress-auth:300
public-cr41679d0177fa4f92ab10262fa586956c-alb2    true     enabled    public    165.192.71.230   tok05    ingress:404/ingress-auth:300
public-cr41679d0177fa4f92ab10262fa586956c-alb3    true     enabled    public    169.56.27.94     tok02    ingress:404/ingress-auth:300

ここで、ALBの一つを停止させると、DNSから引けるIPアドレスのエントリは削除されます。次のコマンドでALBの一つを停止することができます。

$ bx ks alb-configure --albID public-cr41679d0177fa4f92ab10262fa586956c-alb2  --disable
ALB を構成中...

しばらくしてから、ALBをリストすると、2番目のALBが停止しており、ALB IPの一つが削除されていることがわかります。

$  ibmcloud ks albs --cluster iks1
ALB ID                                            有効化   状況       タイプ    ALB IP           ゾーン   ビルド
public-cr41679d0177fa4f92ab10262fa586956c-alb1    true     enabled    public    128.168.73.198   tok04    ingress:404/ingress-auth:300
public-cr41679d0177fa4f92ab10262fa586956c-alb2    false    disabled   public    -                tok05    ingress:404/ingress-auth:300
public-cr41679d0177fa4f92ab10262fa586956c-alb3    true     enabled    public    169.56.27.94     tok02    ingress:404/ingress-auth:300

アドレス解決で、MZLBの動作を確認すると、つぎのように、2番目のIPアドレスが削除されました。このようにMZLBは、DNSと連動してデータセンターレベルの障害に対して、リクエストの分配先を削除することで、サービスの継続を維持します。

> iks1.jp-tok.containers.appdomain.cloud
サーバー:  google-public-dns-a.google.com
Address:  8.8.8.8

権限のない回答:
名前:    iks1.jp-tok.containers.appdomain.cloud
Addresses:  128.168.73.198
          169.56.27.94

ALB と ポッドの対応づけ

クラスタのDNS名とポッドを対応づけるためには、つぎの3つの Kubernetes オブジェクトを作成します。

  • Ingress Resource (ingress-mz.yml イングレスの設定)
  • Service (deploy-web.yml のサービス部分)
  • Controller / Pod (deploy-web.yml のデプロイメント部分)

イングレスとサービスの対応づけは、イングレスのマニフェストに、サービス名を指定します。
そして、サービスとポッドの対応は、ラベルとセレクターによっておこないます。

マルチゾーンクラスタでの動作の様子

GitHub https://github.com/takara9/container-session-check からクローンして利用します。マニフェストのコードは、GitHubを参照ねがいます。ここで適用したマニフェストは、試験用PHPのアプリケーションのポッドを、デプロイメント・コントローラーで起動します。そして、これらのポッドを代表するサービスを起動します。
サービスは、ポッドのクラスタを代表するIPアドレス 172.21.7.146 を獲得しています。このIPアドレスは、サービスオブジェクトが存在している間は変更されること無く、k8sクラスタ内のDNSで名前で、IPアドレスを解決できます。

$ kubectl apply -f deploy-test.yaml
deployment.apps/web created
service/web-svc created

$ kubectl get all
NAME                      READY     STATUS    RESTARTS   AGE
pod/web-ddd5df9c7-6wk9m   1/1       Running   0          9s
pod/web-ddd5df9c7-7sf48   1/1       Running   0          9s
pod/web-ddd5df9c7-8px6k   1/1       Running   0          9s
pod/web-ddd5df9c7-9txgh   1/1       Running   0          9s
pod/web-ddd5df9c7-bn86q   1/1       Running   0          9s
pod/web-ddd5df9c7-dkg6f   1/1       Running   0          9s
pod/web-ddd5df9c7-hntc6   1/1       Running   0          9s
pod/web-ddd5df9c7-nvtjp   1/1       Running   0          9s
pod/web-ddd5df9c7-qkcgm   1/1       Running   0          9s
pod/web-ddd5df9c7-wm7tq   1/1       Running   0          9s

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/kubernetes   ClusterIP   172.21.0.1     <none>        443/TCP    115d
service/web-svc      ClusterIP   172.21.7.146   <none>        9080/TCP   9s

NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/web   10        10        10           10          9s

NAME                            DESIRED   CURRENT   READY     AGE
replicaset.apps/web-ddd5df9c7   10        10        10        9s

次の結果から読み取れるように、10個のポッドは、4つのサーバー(NODE)にデプロイされて動作していることがわかります。

$ kubectl get po -o wide
NAME                  READY     STATUS    RESTARTS   AGE       IP               NODE
web-ddd5df9c7-6wk9m   1/1       Running   0          15s       172.30.33.207    10.192.9.93
web-ddd5df9c7-7sf48   1/1       Running   0          15s       172.30.119.19    10.192.9.68
web-ddd5df9c7-8px6k   1/1       Running   0          15s       172.30.210.215   10.132.253.30
web-ddd5df9c7-9txgh   1/1       Running   0          15s       172.30.169.96    10.193.10.50
web-ddd5df9c7-bn86q   1/1       Running   0          15s       172.30.210.214   10.132.253.30
web-ddd5df9c7-dkg6f   1/1       Running   0          15s       172.30.119.18    10.192.9.68
web-ddd5df9c7-hntc6   1/1       Running   0          15s       172.30.210.216   10.132.253.30
web-ddd5df9c7-nvtjp   1/1       Running   0          15s       172.30.119.13    10.192.9.68
web-ddd5df9c7-qkcgm   1/1       Running   0          15s       172.30.169.97    10.193.10.50
web-ddd5df9c7-wm7tq   1/1       Running   0          15s       172.30.119.9     10.192.9.68

上記だけでは、ポッドのアプリケーションは、外部へ公開されませんから、イングレスコントローラー(ALB)に、サービス名 web-svc を登録して、ポッドへ転送できるようにします。

$ kubectl apply -f ingress.yml
ingress.extensions/ingress-web created

$ kubectl get ing
NAME          HOSTS                                    ADDRESS                                      PORTS     AGE
ingress-web   iks1.jp-tok.containers.appdomain.cloud   128.168.73.198,165.192.71.230,169.56.27.94   80        3s

$ kubectl describe ing
Name:             ingress-web
Namespace:        default
Address:          128.168.73.198,165.192.71.230,169.56.27.94
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host                                    Path  Backends
  ----                                    ----  --------
  iks1.jp-tok.containers.appdomain.cloud
                                          /   web-svc:9080 (<none>)
Annotations:
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{},"name":"ingress-web","namespace":"default"},"spec":{"rules":[{"host":"iks1.jp-tok.containers.appdomain.cloud","http":{"paths":[{"backend":{"serviceName":"web-svc","servicePort":9080},"path":"/"}]}}]}}

Events:
  Type    Reason   Age   From                                                             Message
  ----    ------   ----  ----                                                             -------
  Normal  Success  11s   public-cr41679d0177fa4f92ab10262fa586956c-alb2-64478db6dc-xswqh  Successfully applied ingress resource.
  Normal  Success  11s   public-cr41679d0177fa4f92ab10262fa586956c-alb1-668b6578db-p5pn5  Successfully applied ingress resource.
  Normal  Success  11s   public-cr41679d0177fa4f92ab10262fa586956c-alb3-b9df97448-j9skc   Successfully applied ingress resource.
  Normal  Success  11s   public-cr41679d0177fa4f92ab10262fa586956c-alb1-668b6578db-zslwp  Successfully applied ingress resource.

前述のように、コマンド「ibmcloud ks albs iks1」によって、ALBのリストを表示すると、各ゾーン(データセンター)ごとにALBが一つIPアドレスを確保して動作いています。ポッドのレベルで確認すると、待機中のALBポッドを含めて、各ノードに一つは動作しています。

$ kubectl get po -n kube-system -o wide |grep public-cr*
NAME                                                              READY     STATUS    RESTARTS   AGE       IP               NODE            NOMINATED NODE
public-cr41679d0177fa4f92ab10262fa586956c-alb1-668b6578db-p5pn5   4/4       Running   0          14h       172.30.33.205    10.192.9.93     <none>
public-cr41679d0177fa4f92ab10262fa586956c-alb1-668b6578db-zslwp   4/4       Running   0          17h       172.30.119.47    10.192.9.68     <none>
public-cr41679d0177fa4f92ab10262fa586956c-alb2-64478db6dc-kkp52   0/4       Pending   0          17h       <none>           <none>          <none>
public-cr41679d0177fa4f92ab10262fa586956c-alb2-64478db6dc-xswqh   4/4       Running   0          17h       172.30.169.87    10.193.10.50    <none>
public-cr41679d0177fa4f92ab10262fa586956c-alb3-b9df97448-j9skc    4/4       Running   0          17h       172.30.210.209   10.132.253.30   <none>
public-cr41679d0177fa4f92ab10262fa586956c-alb3-b9df97448-jm5rz    0/4       Pending   0          14h       <none>           <none>          <none>

前述のマニフェストでデプロイされるコンテナ maho/session-check:1.2 が返す結果をリストしたものです。

このリストの中で、ALBは、NGINXをベースとするプロキシサーバーのポッドであるため、HTTP_X_FORWARDED_FOR の ALBが動作するノードのIPアドレス、REMOTE_ADDRに、ALBのポッドのIPアドレスがセットされる。

  • HTTP_X_FORWARDED_FOR HTTPプロキシサーバまたはロードバランサを経由してウェブサーバに接続するクライアントの送信元IPアドレスを特定する際のデファクトスタンダード
  • REMOTE_ADDR クライアントの接続元IPアドレスであるが、ロードバランサやプロキシを間に挟むと、REMOTE_ADDR がロードバランサ等のアドレスになる
$ while true; do curl -s http://iks1.jp-tok.containers.appdomain.cloud;sleep 60; done
Hostname: web-ddd5df9c7-9txgh<br>
1th time access.
<br>
HTTP_CLIENT_IP = <br>
HTTP_X_FORWARDED_FOR = 10.193.10.50<br>
HTTP_X_FORWARDED = <br>
HTTP_X_CLUSTER_CLIENT_IP = <br>
HTTP_FORWARDED_FOR = <br>
HTTP_FORWARDED = <br>
REMOTE_ADDR = 172.30.169.87<br>
Hostname: web-ddd5df9c7-nvtjp<br>
1th time access.
<br>
HTTP_CLIENT_IP = <br>
HTTP_X_FORWARDED_FOR = 10.132.253.30<br>
HTTP_X_FORWARDED = <br>
HTTP_X_CLUSTER_CLIENT_IP = <br>
HTTP_FORWARDED_FOR = <br>
HTTP_FORWARDED = <br>
REMOTE_ADDR = 172.30.210.209<br>
Hostname: web-ddd5df9c7-qkcgm<br>
1th time access.
<br>
HTTP_CLIENT_IP = <br>
HTTP_X_FORWARDED_FOR = 10.193.10.50<br>
HTTP_X_FORWARDED = <br>
HTTP_X_CLUSTER_CLIENT_IP = <br>
HTTP_FORWARDED_FOR = <br>
HTTP_FORWARDED = <br>
REMOTE_ADDR = 172.30.169.87<br>
Hostname: web-ddd5df9c7-nvtjp<br>
1th time access.
<br>
HTTP_CLIENT_IP = <br>
HTTP_X_FORWARDED_FOR = 10.192.9.68<br>
HTTP_X_FORWARDED = <br>
HTTP_X_CLUSTER_CLIENT_IP = <br>
HTTP_FORWARDED_FOR = <br>
HTTP_FORWARDED = <br>
REMOTE_ADDR = 172.30.119.47<br>
Hostname: web-ddd5df9c7-nvtjp<br>
1th time access.
<br>
HTTP_CLIENT_IP = <br>
HTTP_X_FORWARDED_FOR = 10.192.9.68<br>
HTTP_X_FORWARDED = <br>
HTTP_X_CLUSTER_CLIENT_IP = <br>
HTTP_FORWARDED_FOR = <br>
HTTP_FORWARDED = <br>
REMOTE_ADDR = 172.30.33.205<br>

まとめ

IKSのクラスタを複数ゾーンで構成する場合のイングレスについて、ポイントをまとめると以下になりました。

  • マルチゾーンにノードを立てると、自動的にMZLBが設定され、別途CISをオーダーしたり設定する必要はない。
  • MZLBを利用するためには、イングレス(ALB)を利用しなければならない。
  • ALBは、NGINXイングレス・コントローラと同等のポッドベースのため、アプリケーションはクライアントのIPアドレスを知ることができない。
  • ALBのIPアドレスは、ポータブルIPのアドレスが利用される。
  • MZLBのDNS名は、代表IPアドレスを持つものでは無く、ALBのIPアドレスを返す。

参考資料

[1] Ingress のコンポーネントとアーキテクチャー https://cloud.ibm.com/docs/containers/cs_ingress.html#planning
[2] ウィキペディア X-Forwarded-For https://ja.wikipedia.org/wiki/X-Forwarded-For

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?