infrastructure

Serverless on Kubernetes : Fission を使ってみた

Kubernetes 上で Serverless を実現する Fission を使ってみた

jedipunkz

2 minute read

こんにちは。 @jedipunkz です。

今日は Kubernetes を使って Serverless を実現するソフトウェア Fission を紹介します。

AWS の Lambda とよく似た動きをします。Lambda も内部では各言語に特化したコンテナが起動してユーザが開発した Lambda Function を実行してくれるのですが、Fission も各言語がインストールされた Docker コンテナを起動しユーザが開発したコードを実行し応答を返してくれます。

それでは早速なのですが、Fission を動かしてみましょう。

動作させるための環境

macOS か Linux を前提として下記の環境を用意する必要があります。また Kubernetes 環境は minikube が手っ取り早いので用いますが、もちろん minikube 以外の kubernetes 環境でも動作します。

  • macOS or Linux
  • minikube or kubernetes
  • kubectl
  • fission

ソフトウェアのインストール方法

簡単にですが、ソフトウェアのインストール方法を書きます。

OS

私は Linux で動作させましたが筆者の方は macOS を使っている方が多数だと思いますので、この手順では macOS を使った利用方法を書いていきます。

minikube

ここでは簡単な手順で kubernetes 環境を構築できる minikube をインストールします。

curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.16.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/fission

kubectl

直接必要ではありませんが、kubectl があると minikube で構築した kubernetes 環境を操作できますのでインストールしておきます。

curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.5.2/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/

Fission

Fission のインストールです。

curl http://fission.io/linux/fission > fission && chmod +x fission && sudo mv fission /usr/local/bin/fission

kubernetes の起動

ソフトウェアのインストールが完了したら minikube を使って kubernetes を起動します。

$ minikube start
$ minikube status
minikubeVM: Running
localkube: Running
$ kubectl get nodes
NAME       STATUS    AGE
minikube   Ready     1h

Fission の起動と環境変数の設定

Fission を起動します。

$ kubectl create -f http://fission.io/fission.yaml
$ kubectl create -f http://fission.io/fission-nodeport.yaml

次に環境変数を設定します。

$ export FISSION_URL=http://$(minikube ip):31313
$ export FISSION_ROUTER=$(minikube ip):31314

Fission を使って Python のコードを実行する

例として Python の Hello World を用意します。hello.py として保存します。

def main():
        return "Hello, world!\n"

ではいよいよ、kubernetes と Fission を使って上記の Hello World を実行させます。

まず Fission が用意してくれている Docker コンテナを扱うように ‘env’ を作ります。

$ fission env create --name python-env --image fission/python-env

次に Fission で Function を作ります。その際に上記の env と python コードを指定します。つまり、hello.py を fission/python-env という Docker コンテナで稼働する、という意味です。

$ fission function create --name python-hello -env python-env --code ./hello.py

次に Router を作ります。クエリの Path に対して Fuction を関連付けることができます。

$ fission route add --function python-hello --url /python-hello

Function を実行する環境ができました。実際に curl を使ってアクセスしてみましょう。

$ curl http://$FISSION_ROUTER/python-hello
Hello, world!

hello.py の実行結果が得られました。

まとめと考察

結果から Fission は “各言語の実行環境として Docker コンテナを用いていて、ユーザが開発したコードをそのコンテナ上で起動し実行結果を得られる。また各コード毎に URL パスが指定することができ、それをルータとして関係性を持たせられる” ということが分かりました。AWS の Lambda とほぼ同じことが実現出来ていることが分かると思います。

AWS には Lambda の実行結果を応答するための API Gateway があり、このマネージド HTTP サーバと併用することで API 環境を用意出来るのですが Fission の場合には HTTP サーバも込みで提供されていることも分かります。

あとは、この Fission を提供している元が “Platform9” という企業なのですが、この企業は OpenStack や kubernetes を使ったホスティングサービスを提供しているようです。開発元が一企業ということと、完全な OSS 開発体制になっていない可能性があって、万が一この企業に何かあった場合にこの Fission を使い続けられるのか問題がしばらくはありそうです。Fission 同等のソフトウェアを kubernetes が取り込むという話題は…あるのかなぁ?

kubernetes の Job Scheduler が同等の機能を提供してくれるかもしれませんが、まだ Job Scheduler は利用するには枯れていない印象があります。Fission と Job Scheduler 、どちらがいち早く完成度を上げられるのでしょうか。

Kubernetes Deployments を使ってみた!

Kubernetes Replication Controller の次世代版 Deployments を使ってみました

jedipunkz

4 minute read

こんにちは。 @jedipunkz です。

いま僕らは職場では GKE 上に Replication Controller と Services を使って Pod を起動しているのですが最近の Kubernetes 関連のドキュメントを拝見すると Deployments を使っている記事をよく見掛けます。Kubernetes 1.2 から実装されたようです。今回は Kubernetes の Replication Controller の次世代版と言われている Deployments について調べてみましたので理解したことを書いていこうかと思います。

参考資料

今回は Kubernetes 公式の下記のドキュメントに記されているコマンドを一通り実行していきます。追加の情報もあります。

Deployments を使って nginx Pod を起動

nginx をデプロイするための Yaml ファイルを用意します。

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

作成した yaml ファイルを指定して Pod を作ります。 下記の通りここで “–record” と記しているのは、後に Deployments の履歴を表示する際に “何を行ったか” を出力するためです。このオプションを指定しないと “何を行ったか” の出力が “NONE” となります。

$ kubectl create -f nginx.yaml --record

ここで

  • deployments
  • replica set
  • pod
  • rollout

の状態をそれぞれ確認してみます。

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2         2         2            2           8s

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-4087004473   2         2         2         10s

$ kubectl get pods --show-labels
NAME                                READY     STATUS    RESTARTS   AGE       LABELS
nginx-deployment-4087004473-6csa7   1/1       Running   0          21s       app=nginx,pod-template-hash=4087004473
nginx-deployment-4087004473-teyzc   1/1       Running   0          21s       app=nginx,pod-template-hash=4087004473

$ kubectl rollout status deployment/nginx-deployment
deployment nginx-deployment successfully rolled out

結果から、下記の事が分かります。

  • yaml に記した通り “nginx-deployment” という名前で deployment が生成された
  • “nginx-deployment-4087004473” という名前の rs (レプリカセット) が生成された
  • yaml に記した通り2つの Pod が起動した
  • “nginx-deployment” が正常に Rollout された

Replication Controller でデプロイした際には作られない replica set, rollout というモノが出てきました。後に Deployments を使うメリットに繋がっていきます。

nginx イメージの Tag を更新してみる

ここで yaml ファイル内で指定していた “image: nginx:1.7.9” を “image: nginx:1.9.1” と更新してみます。 Replication Controller で言う Rolling-Update になります。後に述べますが他にも更新方法があります。

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

ここで先ほどと同様に状態を確認してみます。

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2         2         2            2           2m

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-3599678771   2         2         2         39s
nginx-deployment-4087004473   0         0         0         2m

$ kubectl get pods
NAME                                READY     STATUS    RESTARTS   AGE
nginx-deployment-3599678771-0vj9m   1/1       Running   0          53s
nginx-deployment-3599678771-t1y62   1/1       Running   0          53s

ここで…

  • 新しい Replica Set “nginx-deployment-3599678771” が作成された
  • 古い Replica Set “nginx-deployment-4087004473” の Pod は 0 個になった
  • Pod 内コンテナが更新された (NAME より判断)

となったことが分かります。 Replication Controller と異なり、Deployments では以前の状態が Replica Set として保存されていて状態の履歴が追えるようになっています。

ここで Rollout の履歴を確認してみます。

$ kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment"
REVISION        CHANGE-CAUSE
1               kubectl create -f nginx.yaml --record
2               kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

REVISION という名前で履歴番号が付き、どの様な作業を行ったか CHANGE-CAUSE という項目で記されていることがわかります。作業の履歴がリビジョン管理されています。

下記のように REVSION 番号を付与して履歴内容を表示することも可能です。

$ kubectl rollout history deployment/nginx-deployment --revision=2
deployments "nginx-deployment" with revision #2
  Labels:       app=nginx
        pod-template-hash=3599678771
  Annotations:  kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
  Containers:
   nginx:
    Image:      nginx:1.9.1
    Port:       80/TCP
    Volume Mounts:      <none>
    Environment Variables:      <none>
  No volumes.

作業を切り戻してみる

先程 nginx の Image Tag を更新しましたが、ここで Deployments の機能を使って作業を切り戻してみます。下記の様に実行します。

$ kubectl rollout undo deployment/nginx-deployment

状態を確認します。

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2         2         2            2           5m

$ kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment"
REVISION        CHANGE-CAUSE
2               kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
3               kubectl create -f nginx.yaml --record

ここでは…

  • コンテナが2個、正常に起動した
  • REVISION 番号 3 として初期構築の状態 (kubectl create ..) が新たに保存

ということが分かります。注意したいのは REVSION 番号 1 が削除され 3 が生成されたことです。1 と 3 は同じ作業ということと推測します。

念のため ‘nginx’ コンテナの Image Tag が切り戻っているか確認してみます。

$ kubectl describe pod nginx-deployment-4087004473-nq35u | grep "Image:"
    Image:              nginx:1.7.9

最初の Yaml ファイルに記した ‘nginx’ イメージ Tag “1.7.9” となっていることが確認できました。set image … でイメージ更新をした作業が正常に切り戻ったことになります。

レプリカ数を 2->3 へスケールしてみる

更に replicas の数値を 2 から 3 へスケールしてみます。

$ kubectl scale deployment nginx-deployment --replicas 3

同様に状態を確認してみます。

kubectl get pods
NAME                                READY     STATUS    RESTARTS   AGE
nginx-deployment-4087004473-esj5l   1/1       Running   0          6s
nginx-deployment-4087004473-nq35u   1/1       Running   0          4m
nginx-deployment-4087004473-tyibo   1/1       Running   0          4m

kubectl get rs
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-3599678771   0         0         0         9m
nginx-deployment-4087004473   3         3         3         11m

kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment"
REVISION        CHANGE-CAUSE
2               kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
3               kubectl scale deployment nginx-deployment --replicas 3

ここで気になるのは REVISION 3 が上書きされたことです。REVSION 番号 4 が新たに作成されると思っていたからです。先程 REVISION 番号 3 として保存されていた下記の履歴が消えてしまいました。この点については引き続き検証してみます。今の自分には理解できませんでした。ご存知の方いましたら、コメントお願いします!

3               kubectl create -f nginx.yaml --record

Puase, Resume 機能を使ってみる

次は deployments の機能を使って Image Tag を更に 1.9.1 へ変更し、その処理をポーズしてみます。

kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1; kubectl

同様に状態を確認してみます。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-3599678771   2         2         2         10m
nginx-deployment-4087004473   2         2         2         12m

$ kubectl rollout status deployment/nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
Ctrl-C #<--- キー入力

rollout status で deployment “deployment/nginx-deployment” を確認すると “waiting for rollout to finish” と表示され処理がポーズされていることが確認できました。また古い Deployment “nginx-deployment-4087004473” 上に未だコンテナが残り、新しい Deployment もコンテナが生成中であることが分かります。

では Resume します。

$ kubectl rollout resume deployment/nginx-deployment
deployment "nginx-deployment" resumed

この時点の状態を確認しましょう。

$ kubectl rollout status deployment/nginx-deployment
deployment nginx-deployment successfully rolled out

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-3599678771   3         3         3         11m
nginx-deployment-4087004473   0         0         0         14m

ここからは…

  • 正常に Deployment “nginx-deployment” が Rollout されたこと
  • 古い Deployment 上のコンテナ数が 0 に、新しい Deployment 上のコンテナ数が 3 になった

ということが分かります。

Rolling-Update 相当の作業を行う方法

前述した通り、Replication Controller 時代にあった Rolling-Update 作業 (イメージタグ・レプリカ数等の更新) ですが、Deployments では下記の方法をとることが出来ます。

set オプションを付与する場合

set オプションを付与して Key 項目に対して新しい Value を渡します。

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

yaml ファイルを修正する場合

yaml ファイルの内容を更新して適用したい場合、下記のように apply オプションを付与します。

$ kubectl apply -f <新しいYamlファイル>

まとめと考察

REVISION の履歴が上書きされる点など、まだ未完成な感が否めませんでしたが(自分の勘違いかもしれません!)、Replication Controller と比べると作業の切り戻しや、履歴が保存され履歴内容も確認できる点など機能が追加されていることが分かりました。公式ドキュメントを読んでいてもコマンド結果等怪しい点があって流石に API バージョンが “v1beta1” だなぁという感じではありますが、機能が整理されていて利便性が上がっているので Replication Controller を使っているユーザは自然と今後、Deployments に移行していくのではないかと感じました。

1 minute read

こんにちは。@jedipunkz です。

今回は Google Cloud Platform の Google CloudCDN について調べてみたので記したいと思います。

CloudCDN は GCP のロードバランサのバックエンドサービスに紐付けられるサービスです。このバックエンドサービスで CloudCDN を有効にしていると CDN サービスを機能させることが出来ます。先に書いておくとこの CloudCDN はとてもシンプルで扱いやすいサービスだと判りました。高機能な他の CDN サービスと比べると機能が足らない感ありますが、必要最低限なところを抑えているのと、価格がとても安いです。(価格は下記の URL 参照)

価格表 : https://cloud.google.com/cdn/pricing

構成

構成と構成の特徴です。

+----------+                                    +---------+
| instance |--+                               +-| EndUser |
+----------+  |  +------------+  +----------+ | +---------+
              +--|LoadBalancer|--| CloudCDN |-+-| EndUser |
+----------+  |  +------------+  +----------+ | +---------+
| instance |--+                               +-| EndUser |
+----------+                                    +---------+
  • コンテンツが初めてリクエストされた場合キャッシュミスする
  • キャッシュミスした際に近くにあるキャッシュからコンテンツを取得しようと試みる
  • 近くのキャッシュがコンテンツがある場合、最初のキャッシュにコンテンツが送信される
  • 近くのキャッシュにコンテンツがない場合、HTTP ロードバランサにリクエストが転送される
  • その後のリクエストはキャッシュが応答する(キャッシュヒット)
  • キャッシュ間のフィルは EndUser のリクエストに応じて実行される
  • キャッシュを事前に読み込むことできない
  • キャッシュは世界各地に配置されている

CloudCDN を導入する方法

導入する方法は簡単で下記のとおりです。

  • 新規 LB を WebUI で作成
  • バックエンドサービスを作成
  • 右パネルの下にある [Cloud CDN を有効にする] チェックボックスをオンに
  • 作成ボタンを押下

HTTPD サーバ側 (今回は Apache を使います) でキャッシュに関する設定を行います。 下記は例です。3600秒、キャッシュさせる設定になります。

Header set Cache-control "public, max-age=3600"

キャッシュされる条件は RFC7324 に規定されているとおりです。

特定のキャッシュを削除する方法

Google Cloud SDK https://cloud.google.com/sdk/ を使うと CLI でコンテンツを指定してキャッシュのクリアが出来ます。また WebUI でもクリアは可能です。

$ gcloud compute url-maps invalidate-cdn-cache <url-map の名前> --path "コンテンツのパス"

このときに –path で指定できるコンテンツの記し方は下記のように指定することも可能です。

--path "/cat.png # <--- 1つのコンテンツキャッシュを削除
--path "/*"      # <--- 全てのコンテンツキャッシュを削除
--path "/pix/*"  # <--- ディレクトリ指定で削除

まとめ

価格が低価格で必要最低限な機能に絞られている印象です。シンプルな分、理解し易いですしキャッシュクリアについても Hubot 化などすれば開発者の方に実行してもらいやすいのではないでしょうか。