【IBM Cloud k8s検証メモ】フロントエンドPODとバックエンドPODを連携させる方法
フロントエンドのPODから、DBコンテナが入っているバックエンドのPODに接続する方法のメモです。 docker-compose であれば depends_onやlinkで設定すれば良いのですが、Kubernetesでは、どの様に実現したら良いのでしょうか?との疑問の解を探ってみました。
Kubernetesの概念について
k8sのクラスター、ボッド、デプロイメント、サービスという言葉の意味について、Bluemix のドキュメントに親切な説明がありましたので、一部注釈を付けて、そのまま引用します。[1]
Cluster (クラスター)
Kubernetes クラスターは、ワーカー・ノードと呼ばれる 1 つ以上の仮想マシンから成ります。 各ワーカー・ノードは、コンテナー化アプリをデプロイ、実行、管理できる場所であるコンピュート・ホストを表します。 ワーカー・ノードは、クラスター内のすべての Kubernetes リソースを一元的に制御してモニターする Kubernetes マスターによって管理されます。 コンテナー化アプリをデプロイする際、Kubernetes マスターは、デプロイメント要件とクラスターの使用可能容量を考慮に入れて、どこにアプリをデプロイするかを決定します。(注釈: IBMでは、ワーカー・ノードとして表記されていますが、Kubernetes のドキュメントには、単にノードとして表されています。)
POD (ポッド)
Kubernetes クラスターにデプロイされる各コンテナー化アプリは、ポッドによってデプロイ、実行、管理されます。 ポッドは Kubernetes クラスター内のデプロイ可能な最小のユニットを表し、単一のユニットとして処理される必要があるコンテナーをグループ化するのに使用します。ほとんどの場合、各コンテナーはそのコンテナー独自のポッドにデプロイされます。ただしアプリでは、コンテナーとその他のヘルパー・コンテナーを 1 つのポッドにデプロイすることによって、同じプライベート IP アドレスを使用してそれらのコンテナーをアドレス指定できるようにする必要がある場合もあります。(注釈:複数のコンテナが同一POD内で動作する際には、コンテナのポート番号が同じにならない様に、管理が必要です。)
Deployment (デプロイメント)
デプロイメントは Kubernetes リソースであり、デプロイメントの中でコンテナーと、アプリの実行に必要な他の Kubernetes リソース (永続ストレージ、サービス、アノテーションなど) が指定されます。 デプロイメントは Kubernetes デプロイメント・スクリプトで文書化されます。デプロイメントを実行するときは、 Kubernetes マスターが、クラスターのワーカー・ノードで使用可能な容量を考慮しながら、指定されたコンテナーをポッドにデプロイします。 他の Kubernetes リソースは、デプロイメント・スクリプトの指定どおりに作成され、構成されます。
デプロイメントを使用して、ローリング更新中に追加するポッドの数や、1 度に使用不可にできるポッドの数など、アプリの更新戦略を定義できます。 ローリング更新の実行時には、デプロイメントによって、リビジョンが動作しているかどうかが確認され、障害が検出されるとロールアウトが停止されます。
Service (サービス)
Kubernetes サービスによってポッドのセットをグループ化し、クラスター内の他のサービスからそれらのポッドにアクセスするためのネットワーク接続を提供します。そうすれば、各ポッドの実際のプライベート IP アドレスを公開する必要はありません。 サービスを使用することにより、アプリをクラスター内または公開インターネットで使用可能にできます。
KubernetesのServiceについて
上記の説明文では、サービスが、PODにアクセスするためのネットワーク接続を提供するとあります。この内容について、今度は、Kubernetesのドキュメントで参照すると、次の様に書かれています。[2]
Kebernetes のサービスとは、論理的ポッドのセットとアクセス方針を定義を 抽象化したものです。 そして、サービスは 通常 Label Selector によって識別される。
ここで、サービスの定義の例を見てみましょう。 ここで、selector の中、app: mini-mysql が POD との対応づけになります。 そして、ports 以下が PODへのアクセス方針で、TCP 3306 を 3306で公開する様に定義してあります。
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
selector:
app: mini-mysql <--- PODを指定するには、selector に一致するラベルを記述する
tier: backend
ports:
- protocol: TCP
port: 3306
targetPort: 3306
これを設定することで、PODにアクセスするためのIPアドレスが付与され、kube-dnsへ登録され、他のPODで、DNSを利用してホスト名をIPアドレスを引いて、目的のPODにアクセスできる様になります。
次のYAMLファイルは、PODを作成するためのもので、前述のServiceとの一致する箇所を確認するための抜粋です。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mysql-deploy
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: mini-mysql <--- これが サービスの selector の app の値と一致している必要がある。
tier: backend
track: stable
spec:
containers:
- name: mysql
kube-dnsのアドレス解決
前述のservice の yaml を適用すると、サービスのリストに、ココとして指摘した行が表示される様になります。 これと同時に、kube-dnsにも登録されるので、mysqlというホスト名でIPアドレスを得られる様になります。
$ kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend-svc 172.21.127.62 169.60.13.186 80:32408/TCP 19h
kubernetes 172.21.0.1 <none> 443/TCP 2d
mysql 172.21.78.144 <none> 3306/TCP 19h <-- ココ
redis 172.21.20.30 <none> 6379/TCP 19h
AP Container に入って、npingで確認します。 npingは、nmapパッケージに含まれるポートでpingを実行するためのツールです。
最初は、ホスト名 mysql で nping を実行します。 以下の結果から、アドレスが解決され、応答を受けていることが確認できます。
$ kubectl exec -it frontend-deploy-1665229993-12gd0 -c app bash
root@frontend-deploy-1665229993-12gd0:/var/www# nping --tcp -p 3306 -c 3 mysql
Starting Nping 0.6.47 ( http://nmap.org/nping ) at 2017-09-29 02:53 UTC
SENT (0.0333s) TCP 172.30.212.137:32598 > 172.21.78.144:3306 S ttl=64 id=19140 iplen=40 seq=325308650 win=1480
RCVD (0.2196s) TCP 172.21.78.144:3306 > 172.30.212.137:32598 SA ttl=62 id=0 iplen=44 seq=733617065 win=28800 <mss 1440>
SENT (1.0336s) TCP 172.30.212.137:32598 > 172.21.78.144:3306 S ttl=64 id=19140 iplen=40 seq=325308650 win=1480
RCVD (1.2236s) TCP 172.21.78.144:3306 > 172.30.212.137:32598 SA ttl=62 id=0 iplen=44 seq=749241736 win=28800 <mss 1440>
SENT (2.0345s) TCP 172.30.212.137:32598 > 172.21.78.144:3306 S ttl=64 id=19140 iplen=40 seq=325308650 win=1480
RCVD (2.2236s) TCP 172.21.78.144:3306 > 172.30.212.137:32598 SA ttl=62 id=0 iplen=44 seq=764881349 win=28800 <mss 1440>
Max rtt: 189.863ms | Min rtt: 186.162ms | Avg rtt: 188.318ms
Raw packets sent: 3 (120B) | Rcvd: 3 (132B) | Lost: 0 (0.00%)
Nping done: 1 IP address pinged in 2.25 seconds
今度は、同じくAPコンテナで、nslookup を利用して他のサービスも含めて、アドレス解決を試みてみました。 期待通りに、IPアドレスが返されます。
root@frontend-deploy-1665229993-12gd0:/var/www# nslookup
> server
Default server: 172.21.0.10
Address: 172.21.0.10#53
> mysql
Server: 172.21.0.10
Address: 172.21.0.10#53
Name: mysql.default.svc.cluster.local
Address: 172.21.78.144
> redis
Server: 172.21.0.10
Address: 172.21.0.10#53
Name: redis.default.svc.cluster.local
Address: 172.21.20.30
環境変数の提供
既にサービスが提供されている下記の状態で、新たにPODをデプロイすると、サービスと接続するための環境変数がコンテナにセットされます。
$ kubectl get service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend-svc 172.21.218.44 169.60.13.186 80:30305/TCP 1h
kubernetes 172.21.0.1 <none> 443/TCP 2d
mysql 172.21.115.104 <none> 3306/TCP 1h
redis 172.21.27.5 <none> 6379/TCP 1h
web-phpmyadmin 172.21.168.132 <nodes> 80:31580/TCP 2h
サービスの環境変数の例を以下に示します。これらの環境変数を利用してサービスへ接続することも可能です。 注意点としては、環境変数の場合、コンテナ稼働中の変更は反映されないので留意して利用する必要があります。
$ kubectl exec -it frontend-deploy-1665229993-37d57 -c app bash
root@frontend-deploy-1665229993-37d57:/var/www# env |grep MYSQL |sort
MYSQL_PORT=tcp://172.21.115.104:3306
MYSQL_PORT_3306_TCP=tcp://172.21.115.104:3306
MYSQL_PORT_3306_TCP_ADDR=172.21.115.104
MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_PORT_3306_TCP_PROTO=tcp
MYSQL_SERVICE_HOST=172.21.115.104
MYSQL_SERVICE_PORT=3306
root@frontend-deploy-1665229993-37d57:/var/www# env |grep REDIS |sort
REDIS_PORT=tcp://172.21.27.5:6379
REDIS_PORT_6379_TCP=tcp://172.21.27.5:6379
REDIS_PORT_6379_TCP_ADDR=172.21.27.5
REDIS_PORT_6379_TCP_PORT=6379
REDIS_PORT_6379_TCP_PROTO=tcp
REDIS_SERVICE_HOST=172.21.27.5
REDIS_SERVICE_PORT=6379
アプリサーバーからのアクセス
サービスが定義が完了すれば、APコンテナからは、ホスト名を指定してアクセスするだけとなります。 次のPHPの例ですが、host=mysqlとすることで、mysqlのホスト名がkube-dnsによってIPアドレスが求められ、アクセスできる様になります。
<?php
Class DaoAnimals
{
private $dsn;
private $dbh;
// Constructor
function __construct() {
$this->dsn = "mysql:host=mysql;port=3306;dbname=testdb";
$this->dbh = new PDO($this->dsn, getenv('DB_USER'),getenv('DB_PASSWORD'));
}
ラベル tier について
例えば、次の様に tier を無効にして動作に支障はありません。 このtierは何のためにあるのでしょうか? この疑問に答えてくれるのが、Labels and Selectors[5]です。
labels:
app: mini-mysql
# tier: backend
# track: stable
このラベルを設定しておくことで、フロントエンドだけ、または、バックエンドだけといったリストを出すなど、クロスカットのオペレーションができる様になります。
$ kubectl get pods -l tier=frontend
NAME READY STATUS RESTARTS AGE
frontend-deploy-1665229993-5nrr9 2/2 Running 0 40s
$ kubectl get pods -l tier=backend
NAME READY STATUS RESTARTS AGE
mysql-deploy-3344093262-b92p1 1/1 Running 0 57s
redis-deploy-2921693572-z87qn 1/1 Running 0 1m
Bluemix-k8s 残念なところ
現在 2017年9月28日で、Bluemix-k8sには Internal LoadBalancerが実装されていません。 AWS,GCP,Azureでは、既に提供済みで、とても残念です。
参考資料
[1] Kubernetes クラスターと IBM Bluemix Container Service について https://console.bluemix.net/docs/containers/cs_ov.html?pos=2#cs_ov
[2] Services https://kubernetes.io/docs/concepts/services-networking/service/
[3] Connect a Front End to a Back End Using a Service https://kubernetes.io/docs/tasks/access-application-cluster/connecting-frontend-backend/
[4] Internal Load Balancer https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer
[5] Labels and Selectors https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
Author And Source
この問題について(【IBM Cloud k8s検証メモ】フロントエンドPODとバックエンドPODを連携させる方法), 我々は、より多くの情報をここで見つけました https://qiita.com/MahoTakara/items/098a794c71f0ae2be429著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .