LoginSignup
2
7

More than 5 years have passed since last update.

【IBM Cloud k8s検証メモ】アプリをHTTPSとドメイン名でアクセスする

Last updated at Posted at 2017-09-11

今回の目標は、Cloud Foundry アプリと同様に、Bluemix k8sでロードバランサーによる負荷分散された高可用性環境にコンテナを配置して、Bluemixで自動付与されたドメイン名へHTTPSでアクセスできる様にすることです。

スクリーンショット 2017-09-11 10.01.59.png

前提条件

k8sで、HTTPSを利用できる様にするためには、有償の標準クラスタを利用する必要あります。 このため、フリーアカウントでは利用できません。また、Bluemix Infrastrucre と連携ができない Bluemix アカウントでは利用できませんので、ご了承願います。

  • k8s標準クラスタを作るために、クレジットカード登録または、IBM契約のあるBluemixのアカウント
  • Vagrant + Virtual Box が動作するPC環境 (Windows PC, Mac, Linux PCのいづれか)
  • インターネット接続 10Mbps以上

ローカル環境の構築

Cloud Foundry の場合には、コードをアップロードするだけで良かったのですが、k8sの場合は、ビルド済みのコンテナを利用します。 したがって、アプリを開発する場合には、Bluemix CLIコマンドやプラグイン以外に、Dockerのビルド環境が必要になります。

  • Bluemix環境と連携させるために bxコマンド、および プラグイン
  • k8sのマスターノードと連携するために、kubectl コマンド、
  • アプリケーションをコンテナ化するために Docker環境
  • プログラム言語の開発環境

Vagrant + Virtual Box を利用して開発環境を作っている方向けに、PHP,Ruby,Python,Node のバージョン管理、git, Bluemix CLI, kubectl などコマンドと前提パッケージを予めインストールした仮想サーバーを作るためのVagrantfile を作成してあります。
https://github.com/takara9/bluemix-dev

k8sクラスタの作成

ここからの操作は、前述のVagrantfileを利用して作成した仮想サーバー上での操作です。 それから、bx login を完了した状態から始めます。

k8sの標準クラスタを構築していきます。 この操作は、Bluemix の ウェブ画面からも同様の事が出来るのですが、この記事では、将来自動化しやすい様に、すべて、CLIで進めていきます。

最初に、どこのデータセンターにk8sのクラスタを構築するかを決めておきます。 現在k8sが利用出来るデータセンターを参照して決めると良いと思います。 近々、東京データセンターでも k8sクラスタが利用できる様になりますので、乞うご期待です。 

この資料では、Bluemix Infrastructure の ダラス 第12データセンター DAL12を選択して進めていきます。 まず、コンテナのホストになるサーバーを決めて、Nameの欄の表記をメモしておきます。 

$ bx cs machine-types dal12
OK
Name         Cores   Memory   Network Speed   OS             Storage   Server Type
u1c.2x4      2       4GB      1000Mbps        UBUNTU_16_64   100GB     virtual
b1c.4x16     4       16GB     1000Mbps        UBUNTU_16_64   100GB     virtual
b1c.16x64    16      64GB     1000Mbps        UBUNTU_16_64   100GB     virtual
b1c.32x128   32      128GB    1000Mbps        UBUNTU_16_64   100GB     virtual
b1c.56x242   56      242GB    1000Mbps        UBUNTU_16_64   100GB     virtual

ここでは、以前にDAL12を利用した事があり、VLANが割り当てられていれば表示されます。

$ bx cs vlans dal12
OK
ID        Name   Number   Type      Router
2114477          1441     private   bcr01a.dal12
2114475          1286     public    fcr01a.dal12

スタンダード・クラスタを作成します。 --name で指定する名前や --workers で指定するノードの数、 --machine-type で指定される サーバーのスペックなどは、目的に合わせて変更をお願いします。 また、 --public-vlan, --private-vlan の IDは省略すれば、自動割り当てとなります。

$ bx cs cluster-create --name mycluster3 --location dal12 --machine-type u1c.2x4 --private-vlan 2114477 --public-vlan 2114475 --workers 3
Creating cluster...
OK

2017年9月現在の実装状況では、DAL12で3ノードを指定した場合、上記コマンドを投入してから約30分でクラスタが完成しました。

$ bx cs clusters
OK
Name         ID                                 State    Created                    Workers   Datacenter
mycluster3   dc74ec9f2d9242ee824a2af3da894d31   normal   2017-09-09T15:11:17+0000   3         dal12

今回作成したクラスタの詳細を確認しておきます。 Ingress subdomein と Ingress secret は、後ほど利用しますのでメモしておきます。

$ bx cs cluster-get mycluster3
Retrieving cluster mycluster3...
OK

Name:                   mycluster3
ID:                     dc74ec9f2d9242ee824a2af3da894d31
State:                  normal
Created:                2017-09-09T15:11:17+0000
Datacenter:             dal12
Master URL:             https://169.47.70.10:21530
Ingress subdomain:      mycluster3.us-south.containers.mybluemix.net
Ingress secret:         mycluster3
Workers:                3
Log Space:              7e209692-4e0c-40b2-a7a6-6abb874dba8d

Addons
Name                   Enabled
customer-storage-pod   true
storage-watcher-pod    true
basic-ingress          true

初期の頃に、k8sのクラスタを構築した場合、 Addonsが動作していない事がありました。 これらが Addons Enabked が false になっていた場合、関連する機能が働きません。 もし、false があれば、チケットに問い合わせるか、または、削除して再作成するのが良いです。

以上で、クラスタの準備ができましたので、次にアプリの開発へ触れていきます。

Node.js アプリの開発

この記事では、コンテナでアプリを開発する事が主眼ではないので、最も簡単と思う方法で、簡単なアプリを作ります。

開発用のディレクトリを作成して、そこへ移動します。

mkdir dev_app
cd dev_app

Node.js の Expressフレームワークのコード生成ツールをインストールします。

$ npm install express-generator -g

次のコマンドで、テンプレートアプリを作成します。

$ express --view=pug myapp

ローカル環境でのテストの為に、生成したアプリのディレクトリへ移動します。

$ cd myapp

アプリが実行に必要なモジュールをインストールします。

$ npm install

デバッグモードで起動してテストします。

$ DEBUG=myapp:* npm start

別のターミナル・ウィンドを立ち上げて、もう一つ、vagrant ssh でログインして、curlコマンドでアクセスして、下記のHTMLのレスポンスがあれば、アプリの準備完了です。

$ curl http://localhost:3000/
<!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>Express</h1><p>Welcome to Express</p></body></html>

アプリのコンテナ化

作成したアプリのディレクトリから、コンテナイメージを作成します。  この為に、ディレクトリを一つ上がって、dev_appに移動します。

$ cd ..

コンテナを作成する為に、Dockerfileの名前で、カレントディレクトリに次の内容のファイルを作成します。

Dockerfile
FROM ubuntu
RUN apt-get update
RUN apt-get install curl -y
RUN curl -sL https://deb.nodesource.com/setup_6.x | /bin/bash -
RUN apt-get install nodejs -y
ADD ./myapp /app
ENV NODE_ENV development
EXPOSE 3000
CMD ["node", "/app/bin/www"]

Dockerfileの内容について、以下に列挙します。 詳しい説明説明は、Docker referenceにあります。
* FROM ベースになるOSを指定するもので、https://hub.docker.com/_/ubuntu/ のlatest バージョンになります
* RUN 初回だけ実行するコマンドです。 nodeの環境などをインストールしています
* ADD アプリのディレクトリ ./myapp を コンテナのファイルシステム上の/app へコピーします
* ENV 環境変数設定
* EXPOSE 外部へ開くポート番号
* CMD コンテナ起動時に毎回実行するコマンド

次のコマンドで、アプリケーションのディレクトリから、Dockerコンテナを作成します。

$ docker build -t express-app . 

ビルドされたコンテナは、Dockerのローカル・リポジトリに登録されます。

$ docker images
REPOSITORY                                       TAG                 IMAGE ID            CREATED             SIZE
express-app                                      latest              94ffae43dcae        11 seconds ago      265MB

ローカル・リポジトリのコンテナを起動します。 -p は外部に公開するポートで、外部公開ポート番号:コンテナのEXPOSEで指定したポート番号となります。 例えば、-p 4000:3000 とすれば、EXPOSE で指定したポート番号を 4000番に対応させて外部からアクセスできる様になります。 また -t は TTYからアクセスできる様にします。 もし、-t を忘れると Ctrl + Cで止める事ができなくなります。

$ docker run -t -p 3000:3000 express-app

上記と別のウィンドから、curl コマンドでアクセスして、コンテナの動作を確認します。 以下のHTMLが表示されていれば、コンテナの動作は予定通りとなります。

$ curl http://localhost:3000/
<!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>Express</h1><p>Welcome to Express</p></body></html>

レジストリへの登録

k8sで利用できる様にする為に、ローカルリポジトリに保存されている コンテナのイメージを Bluemix の レジストリサービスへ転送します。
この中で、registry.ng.bluemix.net までがリポジトリとなり、その後の takara の部分が、ネームスペースと呼ばれる利用者が作成する部分になります。 このネームスペースを作成する為には、bx cr namespace-add を実行します。 詳しくは、bx cr --help を参照ください。

$ docker tag express-app registry.ng.bluemix.net/takara/express-app

ローカルから、Bluemixへプッシュします。

$ docker push registry.ng.bluemix.net/takara/express-app

登録したイメージが存在するか確認します。 もし無ければ手順やネームスペースが存在しているかを確認します。

$ bx cr images

これで k8s のクラスタ環境へアプリを登録する準備ができました。 次に、k8s へデプロイしていきます。

k8sでの実行 (シングルでテスト)

まずは、コマンドラインだけで出来る方法で、k8sでコンテナを実行します。

$ kubectl run express-app --image=registry.ng.bluemix.net/takara/express-app

k8sのポッド、デプロイメント、サービス、レプリカセットなどの情報を確認します。 次の例では、AVAILABLE が 1となっており、動作している事が読み取れます。

$ kubectl get all
NAME                              READY     STATUS    RESTARTS   AGE
po/express-app-2177018659-tqhzf   1/1       Running   0          38s

NAME             CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
svc/kubernetes   10.10.10.1   <none>        443/TCP   1h

NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/express-app   1         1         1            1           38s

NAME                        DESIRED   CURRENT   READY     AGE
rs/express-app-2177018659   1         1         1         38s

コンテナを外部へテスト公開 (分散クラスタ)

これだけでは、外部へ公開されないので、--type NodePortで公開します。 この方法は、クラスタとして公開するのではなく、コンテナが実行されているワーカー(ノード)のポートで、公開するというものです。

$ kubectl expose deployment express-app --port 3000 --type NodePort

expose を実行した後に、再び状態を確認すると svc/express-app が増えており、EXTERNAL-IPが となり、 PORT(S)が、3000:31980/TCP となっています。 これは、ワーカー(ノード)の Public IP で参照可能であり、 TCP3000番を31980で公開している事が読み取れます。

$ kubectl get all
NAME                              READY     STATUS    RESTARTS   AGE
po/express-app-2177018659-tqhzf   1/1       Running   0          2m

NAME              CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
svc/express-app   10.10.10.217   <nodes>       3000:31980/TCP   6s
svc/kubernetes    10.10.10.1     <none>        443/TCP          1h

NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/express-app   1         1         1            1           2m

NAME                        DESIRED   CURRENT   READY     AGE
rs/express-app-2177018659   1         1         1         2m

そこで、ワーカーのPublic IPアドレスを次のコマンドで確認します。

vagrant@vagrant-ubuntu-trusty-64:~/k8s$ bx cs workers mycluster3

curl コマンドで、public IP と ポート番号を指定して、HTMLが表示されると、シングルでの確認は完了です。 この例では、ワーカーノードが3つあり、その何れかで稼働しています。 応答がなければ、IPアドレスを変えて試してみましょう。

$ curl http://xxx.xxx.211.236:31980/
<!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>Express</h1><p>Welcome to Express</p></body></html>

デプロイしたコンテナやサービスの削除

コンテナ単体の動作確認が完了したので、削除しておきます。 削除には以下2つが、必要です。

$ kubectl delete deployment express-app
$ kubectl delete service express-app

HTTPSとドメイン名でアクセスできる様にデプロイ

アプリを3つのワーカ(ノード)に展開して、暗号化可能なロードバランサーを実行するには、次の様にYAMLファイルを作成して設定を適用します。

publish.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: express-app
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: express-app
    spec:
      containers:
      - name: express-container
        image: registry.ng.bluemix.net/takara/express-app
        ports:
        - containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: express-svc
spec:
  type: NodePort
  selector:
    app: express-app
  ports:
  - protocol: TCP
    port: 3000
    nodePort: 31514
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: express-ingress
spec:
  tls:
  - hosts:
    - mycluster3.us-south.containers.mybluemix.net
    secretName: mycluster3
  rules:
  - host: mycluster3.us-south.containers.mybluemix.net
    http:
      paths:
      - path: /
        backend:
          serviceName: express-svc
          servicePort: 3000

最初に構成した3ノードのk8sクラスタに対して、このYAMLファイルで構築する構成を図にすると、次の様な内容になります。

スクリーンショット 2017-09-11 15.46.11.png

このYAMLファイルの説明は、TLS 終端ありで IBM 提供ドメインを使用するを参照してください。

kubectl、コマンドで前述のYAMLファイルを適用します。

$ kubectl create -f publish.yml
deployment "express-app" created
service "express-svc" created
ingress "express-ingress" created

問題が無いか確認します。

$ kubectl get all
NAME                              READY     STATUS    RESTARTS   AGE
po/express-app-1882574706-pfhjv   1/1       Running   0          8s
po/express-app-1882574706-pqmf2   1/1       Running   0          8s
po/express-app-1882574706-xlgr4   1/1       Running   0          8s

NAME              CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
svc/express-svc   10.10.10.57   <nodes>       3000:31514/TCP   7s
svc/kubernetes    10.10.10.1    <none>        443/TCP          1h

NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/express-app   3         3         3            3           8s

NAME                        DESIRED   CURRENT   READY     AGE
rs/express-app-1882574706   3         3         3         8s

ingressの動作を確認してみます。 ADDRESSが表示されないですが、Bluemixでは、これで正常な動作です。

$ kubectl get ing
NAME              HOSTS                                          ADDRESS   PORTS     AGE
express-ingress   mycluster3.us-south.containers.mybluemix.net             80, 443   1d

それでは、https://mycluster3.us-south.containers.mybluemix.net/ でアクセスした結果が、次のスクリーン・ショットになります。
HTTPSとドメイン名でアクセスできる事がわかります。

スクリーンショット 2017-09-10 1.48.52.png

トラブル・シューティング

今年の4月初めにオープンしたk8sの環境ですが、9月に入って、安定的に利用できる様になった様に思います。 トラブルの中で、とても困ったケースについて、症状と対策を記載しておきます。

Ingress のドメイン名でアクセスしても、タイムアウトになる

暗号化と負荷分散を受け持つ Ingress を設定しているのですが、

$ kubectl get ing
NAME              HOSTS                                                ADDRESS   PORTS     AGE
express-ingress   mycluster-241320.us-south.containers.mybluemix.net             80, 443   15s

curl コマンドで、アクセスしても、応答がありません。

$ curl https://mycluster-241320.us-south.containers.mybluemix.net/
curl: (7) Failed to connect to mycluster-241320.us-south.containers.mybluemix.net port 443: Operation timed out

k8sの中を調べても、異常が見つかりません。

$ kubectl get all
NAME                              READY     STATUS    RESTARTS   AGE
po/express-app-1065668149-14x76   1/1       Running   0          21s
po/express-app-1065668149-pzxjq   1/1       Running   0          21s
po/express-app-1065668149-sccx3   1/1       Running   0          21s

NAME              CLUSTER-IP     EXTERNAL-IP     PORT(S)          AGE
svc/express-lb    10.10.10.216   169.48.212.10   80:31520/TCP     20s
svc/express-svc   10.10.10.86    <nodes>         3000:31514/TCP   20s
svc/kubernetes    10.10.10.1     <none>          443/TCP          16d

NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/express-app   3         3         3            3           21s

NAME                        DESIRED   CURRENT   READY     AGE
rs/express-app-1065668149   3         3         3         21s

Bluemix CLIで クラスタ状態を確認すると、Addonsの部分の Enabled が全て falseになっていました。
kubectl で操作できない為、本クラスタを破棄して、再作成した処、正常に動作する様になりました。

$ bx cs cluster-get mycluster
Retrieving cluster mycluster...
OK

Name:                   mycluster
ID:                     852830a347cc4280b8985489fb883cbf
State:                  normal
Created:                2017-08-24T06:46:39+0000
Datacenter:             dal12
Master URL:             https://169.47.70.10:25428
Ingress subdomain:      mycluster-241320.us-south.containers.mybluemix.net
Ingress secret:         mycluster-241320
Workers:                3
Log Space:              db39e8a1-5cb6-4fcc-83d2-3e8f0c8c259a

Addons
Name                   Enabled
storage-watcher-pod    false
basic-ingress          false
customer-storage-pod   false

参考資料

(1) GitHub bluemix-dev https://github.com/takara9/bluemix-dev
(2) Ingress を使用してインターネットにアプリを公開する https://console.bluemix.net/docs/containers/cs_planning.html#cs_ingress
(3) IBM Bluemix Container Service での Kubernetes クラスターとデプロイメントのセキュリティー設定 https://console.bluemix.net/docs/containers/cs_security.html#cs_security_network_policies
(4) TLS 終端ありで IBM 提供ドメインを使用する https://console.bluemix.net/docs/containers/cs_apps.html#cs_apps_public_ingress
(5) Kubernetes and IBM Bluemix: How to deploy, manage, and secure your container-based workloads – Part 3 https://www.ibm.com/blogs/bluemix/2017/06/kubernetes-and-bluemix-container-based-workloads-part3/

2
7
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
7