Google Container Engine (GKE, Kubernetes) を使ってサービスを外部公開する


こんにちは、@s_tsukaです。

今回はGKEを触ってみました。Kubernetesは以前にちょこっと触ってPod立てたくらいで知識が止まってます。

実際にGKE, Kubernetesを使うとなるとこれを使って何らかの仕事をさせたいわけで、特にWebアプリ、Webサービスの場合外部に公開する必要が出てきます。今回はその外部公開まわりを中心に試していきます。

今回はnginxを立てて、それを独自ドメインでアクセスできるようにするのが目標です。

こちらのサイトを参考にさせていただきました。正直やってることはほぼ同じなので、こちらのサイトを見たほうがいいかもしれません。

GKEでコンテナ作成/管理しよう!

Kubernetesクラスタを立てる

gcloud container clusters create nginx-example --zone asia-east1-a --num-nodes 2 --machine-type g1-small

この後使うkubectlコマンドはクラスタの操作コマンドなのでクラスタ自体はgcloudコマンドで作成。GUIからやってもOKです。

nginxコンテナ(Pod)を動かす

nginxを動かすための設定ファイルを作成します。

最近ではkind:Deploymentが高機能で良いようですね。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.11.8
        ports:
        - containerPort: 80

以下のコマンドを実行します。

kubectl create -f nginx-deployment.yaml --record

これでPodは動いたはずなので確認してみます。

$ kubectl get pods
NAME                                READY     STATUS    RESTARTS   AGE
nginx-deployment-3181428067-1b03w   1/1       Running   0          2m
nginx-deployment-3181428067-6673x   1/1       Running   0          2m
nginx-deployment-3181428067-jd546   1/1       Running   0          2m
$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           2m

ちゃんと動いているようです。

クラスタのWebUIも一応見てみます。

GKEのWebコンソール上でクラスタに接続と出るので、この指示通りに従います。自分の場合はproject名がtsukaby1となっているので、このあたりは各自自分の設定でやりましょう。

あとURLもブラウザに直入力で行くとUnauthorizedになるので、上記のリンクから辿ったほうが良いです。

CUIでわかってたことですが、ちゃんと3つポッドが起動していますね。DC/OSのような何やら期待感が高まるGUIで良いですね。

IPを作る

LBのServiceを作ってExternalIPを割り当ててもらいます。

$ kubectl expose deployment nginx-deployment --port=80 --type="LoadBalancer"
service "nginx-deployment" exposed
$ kubectl get services
NAME               CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes         10.247.240.1     <none>        443/TCP        28m
nginx-deployment   10.247.246.196   <pending>     80:31059/TCP   16s

# 少し待つ

$ kubectl get services
NAME               CLUSTER-IP       EXTERNAL-IP       PORT(S)        AGE
kubernetes         10.247.240.1     <none>            443/TCP        29m
nginx-deployment   10.247.246.196   104.155.237.186   80:31059/TCP   1m

はじめはですが少し経つとIPが振られました。

GCPのコンソール上でも確認できます。IPが作られてますね。

curlでアクセスできるか確認してみましょう。

$ curl http://104.155.237.186
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

きました。成功です!

独自ドメイン(Aレコード登録)

正直Global IPさえ出せれば後はDNSの話な気もしますが、一応独自ドメインも設定しておきます。

自分が持っているtsukaby.comはAWSで買っていて、そちらのRoute53で一通り登録しています。なのでそこでAレコードを追加します。

$ curl -I http://nginx.tsukaby.com
HTTP/1.1 200 OK
Server: nginx/1.11.8
Date: Sun, 12 Mar 2017 17:27:22 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 27 Dec 2016 14:23:08 GMT
Connection: keep-alive
ETag: "5862794c-264"
Accept-Ranges: bytes

追加後にcurlしたところちゃんと接続できました。

 

これで一通りアプリを公開できるところまで行けましたが、実際に運用すると遭遇しそうな他の操作についても確認していきます。

アプリ(コンテナ)のバージョンアップ

上記のcurlでServer: nginx/1.11.8とありますが、実際には作ったアプリなどはバージョンアップがあると思います。nginxで言うと2017/03/13現在、1.11.9のimageも存在します。そこでバージョンアップをしてみます。

Kubernetesのkind: Deploymentについては以下が詳しいです。ありがたや

Kubernetes: Deployment の仕組み

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.11.9
        ports:
        - containerPort: 80

ファイルをもう1つ作って1.11.9とします。

以下のコマンドを実行します。

$ kubectl apply -f nginx-deployment2.yaml --record
deployment "nginx-deployment" configured
$ kubectl get pods
NAME                                READY     STATUS    RESTARTS   AGE
nginx-deployment-3262692708-9zf20   1/1       Running   0          2m
nginx-deployment-3262692708-br016   1/1       Running   0          2m
nginx-deployment-3262692708-wv2mx   1/1       Running   0          2m

AGEが2mで若くなりました。早速curlで確認してみます。

[tsukaby@tsukamac gke2]% curl -I http://nginx.tsukaby.com
HTTP/1.1 200 OK
Server: nginx/1.11.9
Date: Sun, 12 Mar 2017 17:41:36 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 24 Jan 2017 14:02:19 GMT
Connection: keep-alive
ETag: "58875e6b-264"
Accept-Ranges: bytes

1.11.9になりました。バージョンアップ成功です。

他のアプリも動かす

実際の運用でどうなるかはわかりませんが、1つのクラスタで他の種類のdocker containerを動かしたいシーンは少なからずあると思います。それを想定して、nginxに加えてghost(軽量blog)も動かしてみます。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: ghost-deployment
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: ghost
    spec:
      containers:
      - name: ghost
        image: ghost:0.11.7
        ports:
        - containerPort: 2368
$ kubectl create -f ./ghost-deployment.yaml
deployment "ghost-deployment" created
$ kubectl expose deployment ghost-deployment --port=80 --target-port=2368 --type="LoadBalancer"
service "ghost-deployment" exposed
$ kubectl get service | grep ghost
ghost-deployment   10.247.249.181   104.199.218.54    80:30688/TCP   2m

$ curl -I http://104.199.218.54
HTTP/1.1 200 OK
X-Powered-By: Express
Cache-Control: public, max-age=0
Content-Type: text/html; charset=utf-8
Content-Length: 4524
ETag: W/"11ac-mtweQYo68TX0ynctU+jNcg"
Vary: Accept-Encoding
Date: Sun, 12 Mar 2017 18:27:10 GMT
Connection: keep-alive

GhostはnginxのExpressというフレームワークを使っているのでX-Powered-Byで正しいことが確認できました。

nginxもghostもどちらもLBを作りましたが別々のものですし、IPも別で。target portもghostの方は2368を見るようにしているので(Ghost imageは2368で開けてる)正しく到達できます。

Scale

Podを増やしてScaleするのと、クラスタのサイズ自体をScaleさせるので2種類あります。これは冒頭にも紹介したこちらの記事で十分実験されているので今回は省略します。

GKEでコンテナ作成/管理しよう!

まとめ

KubernetesクラスタをGKE上に作成しました。

nginxをKubernetes上で立ち上げました。

nginxをLB Service配下に設定し、LBのGlobal IPを独自ドメインと紐付けてnginxをドメインで参照できるようにしました。

他のPodも立ち上げて1つのクラスタで複数のアプリを共存させました。

Kubernetes、GKE、デプロイも設定ファイルを適用するだけで簡単ですね。今後も他の機能をチェックしていこうと思います。