Cloud Penguins

Flying penguins in the cloud.

最強のServerlessプラットフォーム? Knativeを動かしてみるぞい

ということで前回の記事に引き続き、発表されたばかりのKnativeを動かしてみました。

jaco.udcp.info

GKE環境を用意する

Knativeを動かすにはk8s環境が必要ですので、今回はGKEに環境を用意します。なおk8s本体とKubectlは1.10以上が必要です。

KnativeはIstioなども含むリッチな仕組みのため、それなりのリソースを要求します。なのでやや大きめのインスタンスで立ち上げていますが、節約したい方はmachine-typeやnodeの数を編集してください。

export CLUSTER_NAME=knative
export CLUSTER_ZONE=asia-northeast1-a

gcloud container clusters create $CLUSTER_NAME \
  --zone=$CLUSTER_ZONE \
  --cluster-version=latest \
  --machine-type=n1-standard-4 \
  --enable-autoscaling --min-nodes=1 --max-nodes=5 \
  --enable-autorepair \
  --scopes=service-control,service-management,compute-rw,storage-ro,cloud-platform,logging-write,monitoring-write,pubsub,datastore \
  --num-nodes=3

k8s立ち上がったらget-credentials

gcloud container clusters get-credentials knative

カレントユーザーにcluster-adminをつけます。

kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)

kubectlを使って、Istioをセットアップします

kubectl apply -f https://storage.googleapis.com/knative-releases/serving/latest/istio.yaml

defaultネームスペースにラベル設定

kubectl label namespace default istio-injection=enabled

Istioの諸々がRunningになっているか確認

kubectl get pods -n istio-system

NAME                                       READY     STATUS    RESTARTS   AGE
istio-citadel-7bdc7775c7-lktlt             1/1       Running   0          59s
istio-egressgateway-795fc9b47-tcp76        1/1       Running   0          1m
istio-ingress-84659cf44c-2gmlw             1/1       Running   0          1m
istio-ingressgateway-7d89dbf85f-qjpg5      1/1       Running   0          1m
istio-pilot-66f4dd866c-lr7zw               1/2       Running   0          1m
istio-policy-76c8896799-74m52              2/2       Running   0          1m
istio-sidecar-injector-645c89bc64-gz5vb    1/1       Running   0          59s
istio-statsd-prom-bridge-949999c4c-p97lv   1/1       Running   0          1m
istio-telemetry-6554768879-pmkqq           2/2       Running   0          1m

Knativeコンポーネントをセットアップ

Knative Servingをセットアップします

kubectl apply -f https://storage.googleapis.com/knative-releases/serving/latest/release.yaml

Runningになっているか確認してみましょう

kubectl get pods -n knative-serving

NAME                          READY     STATUS    RESTARTS   AGE
activator-6bb6f6755f-l4ks8    2/2       Running   0          30s
controller-79cbd84cfb-n6l6h   1/1       Running   0          29s
webhook-7c884f4554-h7tx5      1/1       Running   0          29s

なんとこれだけでKnativeのセットアップは終わりです。それでは、実際に何かデプロイしてみましょうか。

サンプルアプリのデプロイ

service.yamlを作成し、以下の内容を記述してください。

apiVersion: serving.knative.dev/v1alpha1 # Current version of Knative
kind: Service
metadata:
  name: helloworld-go # The name of the app
  namespace: default # The namespace the app will use
spec:
  runLatest:
    configuration:
      revisionTemplate:
        spec:
          container:
            image: gcr.io/knative-samples/helloworld-go # The URL to the image of the app
            env:
            - name: TARGET # The environment variable printed out by the sample app
              value: "Go Sample v1"

このサンプルアプリは、環境変数 TARGETの中身を表示するアプリケーションです。このyamlの例の場合、 "Go Sample v1" という文字を表示します。

保存した後、kubectl applyします

kubectl apply -f service.yaml

> service "helloworld-go" created

作成されたリソースをみてみます

kubectl get all

NAME                                    AGE
deploy/helloworld-go-00001-deployment   10s

NAME                                          AGE
rs/helloworld-go-00001-deployment-d47886fcb   10s

NAME                   AGE
routes/helloworld-go   10s

NAME                AGE
svc/helloworld-go   10s

NAME                           AGE
configurations/helloworld-go   10s

NAME                            AGE
revisions/helloworld-go-00001   10s

NAME                                                READY     STATUS    RESTARTS   AGE
po/helloworld-go-00001-deployment-d47886fcb-c97kx   3/3       Running   0          10s

NAME                              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
svc/helloworld-go                 ClusterIP   10.63.246.221   <none>        80/TCP         10s
svc/helloworld-go-00001-service   NodePort    10.63.252.252   <none>        80:30048/TCP   10s
svc/kubernetes                    ClusterIP   10.63.240.1     <none>        443/TCP        12h

なんかsvc/helloworld-go以外にもいっぱい作られてますね!

作成したアプリへのアクセス

istio-system namespaceを見てみると、knative-ingressgatewayというものが作られていることが分かります。

このknative-ingressgatewayが、アプリケーションへのルーティングを担うコンポーネントになります。

kubectl get svc knative-ingressgateway -n istio-system

NAME                     TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                                      AGE
knative-ingressgateway   LoadBalancer   10.23.247.74   35.203.155.229   80:32380/TCP,443:32390/TCP,32400:32400/TCP   2d

以下のコマンドでknative-ingressgatewayのEXTERNAL-IPを取得しておきます

export IP_ADDRESS=$(kubectl get svc knative-ingressgateway -n istio-system -o 'jsonpath={.status.loadBalancer.ingress[].ip}')

次に、以下のコマンドで、services.serving.knative.devを取得します

kubectl get services.serving.knative.dev helloworld-go  -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain

NAME            DOMAIN
helloworld-go   helloworld-go.default.example.com

DOMAINというところに、今回のアプリ向けのドメインが記されています。 knative-ingressgatewayはリクエストを見て、このドメインへのアクセスであれば作成されたアプリケーションへのルーティングを行うという動きをします。

とはいえexample.comは例示用ドメインなので、今回はcurlでホストヘッダを指定することで動きを見てみます。

curl -H "Host: helloworld-go.default.example.com" http://${IP_ADDRESS}

Hello World: Go Sample v1!

ほら、期待した文字列が表示されていますよね?

まとめ

ということで、Knativeは簡単にセットアップできるよという話を紹介されていただきました。

ただ、ぶっちゃけ今回のサンプルアプリでは、Knativeの何がいいのか分からないですよね? うん、僕も分かりません。

そもそもServerlessって言ってたのにどこにもServerless要素ないやん、こんなん素のKubernetesと変わらんやん! ってツッコみたくなるかと思いますが、徐々に解説していきますのでもう少しお待ちください。

Knativeはさまざまな方法で利用が出来るプラットフォームです。なので、1記事ではとてもとても紹介しきれないのです。

今回は、KnativeはServerless Platformでありながらも、従来のようなアプリケーションも動かすことができる という点を理解して頂ければよいかなと思います。

次回は、Buildpackを利用したアプリケーションのデプロイについて解説する予定です。

(参考)お片付け

k8sをお片付けするには以下のコマンドで削除します

gcloud container clusters delete $CLUSTER_NAME --zone $CLUSTER_ZONE

最強のServerlessプラットフォーム? Knative登場

本日開催されている Google Cloud Next ’18 ですが、非常に面白いプロダクトが発表されました。

その名も Knative (kay-nay-tiv ケイネイティブと発音)  Kubernetes上でServerlessを実現するプロダクトです。

f:id:jaco-m:20180725040441p:plain

https://github.com/knative/docs より引用

KubernetesでServerlessって何が新しいの?

この界隈追っている方はご存じかもしれませんが、KubernetesでServerless Platformを実現するという考え方自体は新しいものではありません。

CNCF Serverless Landscape を見てみると分かりますが

などなど既に多くのOSSが存在しています。これら先行のServerlessプロダクトとKnativeは何が異なるのでしょうか?

既存のServerlessプロダクト乱立しすぎ問題

既に多くのOSSが存在していて、これといった標準が存在しない。それ自体が一番の問題と言えるかもしれません。

結果として、 Serverless(FaaS)≒Lambda といった状態が続いてしまっています。Serverlessのプロダクトを紹介するときに、一番分かりやすい説明が「AWS Lambdaのようなもの」だったりしますしね。

Lambdaは素晴らしいサービスですが、AWSのプロプラエタリでありこれ以外に選択肢が限られているのはあまり良い状況とは言えません。

より抽象度を高めてKubernetesの複雑さを低減

そもそもKubernetesだけではダメなの? Serverlessを載せるメリットは何なの? と思う人もいるかもしれません。

そのあたりについてはSoftware Designの2018年8月号にKubernetes(CaaS)、PaaS、Serverlessのメリット・デメリットを書いたのですが、端的にいうと「Kubernetes複雑すぎ、難しすぎ」 なのです。

gihyo.jp

Kubernetesはコンテナプラットフォームです。コンテナプラットフォームとは、コンテナそのものと関連するリソース(ネットワークやストレージなど) を管理するプラットフォームです。

KubernetesはManifestファイルでインフラを定義する、いわゆるInfrastructure as Codeを実現できる機能を提供していますが、要はすごく高度なインフラの技術なわけですね。

とても優れている仕組みなのですが、そこまでインフラ技術に通じていないアプリケーション開発者からみると、よく分からないKubernetes独自の概念を理解していかないと使えない、「めんどくさい」仕組みでもあるんです。

コンテナだとかオーバーレイネットワークだとかはどうでもいい。この作ったアプリをうまいこと動かしてくれれば、裏の仕組みはどうでもいいんだよ

そういった、アプリケーション開発者の要望に応えていくためには、もっと抽象度を上げたプラットフォームを提供していく必要があります。 Knativeも、まさにそのような希望に応えるためのプロダクトです。

Build, Event, Serving

詳しくは後続の記事で解説していく予定ですが、Knativeは疎結合な3つのコンポーネントから構成されています。

これらのコンポーネントはKubernetesのCRDを利用して実現されています。

Build

コンテナイメージを作成する仕組みです。Kubernetesではあらかじめ何らかの方法でコンテナイメージを作成し、レジストリに保存しておく必要がありますが、KnativeなこのBuildの働きにより、ソースコードからコンテナイメージを作成します。

このコンテナイメージは、ServerlessなFunctionの実行だけでなく、コンテナとしてのアプリケーション実行にも利用されます(別記事にて開設予定)

コンテナイメージの作成にはいくつかの手段が利用可能です。

  • Buildpack (Cloud Foundry)
  • Google Container Builder
  • Bazel
  • Kaniko
  • Jib

Cloud FoundryやHerokuで使われているBuildpackに対応しているのが要注目ポイントですね。 そう、KnativeはこれまでのPaaS的な要素も持ち合わせているんです。

Event

ServerlessといえばEvent Drivenなアーキテクチャが特徴の一つです。EventによりKafkaやGoogle Cloud Pub/SubへのPublish/Subscribeが可能です。Subscribe先からのメッセージによりFunctionやアプリケーションのトリガーが可能になります

Serving

コンピューティングリソースのスケーリングやライフサイクルの管理、ネットワークエンドポイントのマッピングなどを行うコンポーネントです

Istioの統合

https://github.com/knative/docs の図にもあるように、KnativeにはサービスメッシュであるIstioがガッツリ利用されています。 Google Cloud Nextでは、ちょうど Istio 1.0が発表されたところです。

Istioの統合により、例えばアプリケーションへの重み付けルーティングをこのように実現できたり

---
apiVersion: serving.knative.dev/v1alpha1
kind: Route
metadata:
  name: buildpack-sample-app
  namespace: default
spec:
  traffic:
  - configurationName: buildpack-sample-app
    percent: 100           ⇐これ

knative-ingressgatewayにより、ホストヘッダを利用してのリクエストルーティング(Cloud FoundryのGorouterみたいなもの) が実現されます。これまた面白い機能なので、後続の記事で解説して行ければと。

業界をリードする各社が関わっている

KnativeのAuthorsには以下の企業が記載されています。

Google LLC
Pivotal Software, Inc.
IBM Corp
Red Hat, Inc.
Cisco Systems, Inc.

GoogleだけでなくPivotalやRed Hatといった、コンテナやPaaS界隈をリードしてきた各社が関わっていますね。

例えば、Buildpackの機能やServerless周りはPivotalがコントリビュートしています。IBMも、OpenWhiskの知見をもとにコントリビュートを行っているようです。

このように、業界をリードする各社がガッツリ関わっていることは、冒頭にも書いた「事実上の標準の不在」に対しての解決策になるのではないかと思います。

試してみるには

正直Knativeの面白さは文字だけでは伝えられないと思っているので、もし興味のある方は是非試してみるのがよいでしょう。

試すには、公式のドキュメントを参考に手持ちのKubernetes環境に構築してくのが良いです。

github.com

GKEだけでなく、Pivotal Container ServiceやAKS、Minikubeなどへのインストール方法も記載されています。

ということで、次は実際に動かしてみます。

jaco.udcp.info

PaaS/k8s/Serverless使い分けの話とその補足

4/19に開催された、Japan Container Daysで登壇してきました。

www.slideshare.net

私のセッションは150人ほどの部屋でしたが、立ち見が出るほどの方に来て頂き感謝です。イベント自体もすごく良かったですね。歩留まりを考えて、定員よりもいくらか多めの人数まで申し込みを受け付けたようですが、想定を上回る出席率だった様子です。 いかにコンテナ技術が注目されているかよく分かるイベントでした。

さて、そんなコンテナづくしのイベントの中で、ちょっと違う切り口でお話をさせてもらいました。

なぜ発表しようと思ったか

昨年(2017年)一気に火がついたKubernetes。しかしその結果「そこk8sでやるべきなのか?」と疑問に思う話が各所で見られるようになりました。たとえば数コンテナの運用のためにオンプレ環境に自力でk8s立ち上げたり、その運用に○人もの専任をつけたり。

キーワード先行で上司から「コンテナやれ」「DevOpsやれ」と言われ、どうすれば分からずPaaS勉強会のk8s話聞きに来た、って人もいました。このあたりが、『コンテナ疲れ』という言葉を思いついたきっかけになりました。

また、PaaSやコンテナとは違ったパラダイムでServerlessが注目されつつあるのもみなさんご存じの通り。

じゃあ、この3つのカテゴリはどう絡んでいくんだろう? 僕らは何を選ぶべきなのか? と思い、今回の発表に至ったわけです。

発表の補足

コンテナつらくないですか?の話

f:id:jaco-m:20180424203841p:plainf:id:jaco-m:20180424203844p:plainf:id:jaco-m:20180424203847p:plainf:id:jaco-m:20180424203850p:plain

スライドだけみるとコンテナを否定しているようにも読めたので。

ここで言いたかったことは、「コンテナは楽しい」「けど、それだけで良いんだっけ?」 ということ。

僕もそうなんですけど、この界隈は毎日のように新しい技術やツールが出てくるので非常に楽しいんですよね。ただ、それを良しとしない人だって少なからず居る。

「新しいものについていけないエンジニアなんて云々」と言ってしまうのは簡単ですが、それなりの規模の企業で普及させようとなると、そういった人たちに対してもどうやって使ってもらうかを考えなくてはいけない。となると、この技術が持つ「つらさ」は明確にしておかないといけない。

f:id:jaco-m:20180424203853p:plainf:id:jaco-m:20180424203859p:plainf:id:jaco-m:20180424203903p:plainf:id:jaco-m:20180424203908p:plainf:id:jaco-m:20180424203911p:plain

このあるある話もそう。だいたい僕の経験談なのですが、僕自身はこれに対して「新しい技術だしこのくらい当然だよね」と思っています。JKDで登壇するような人も同じだと思います。でも、『これはそういうもんだ、慣れろ!』と言ったところで他の人に通じるとは限りません。つらさはつらさとして認識して、共有したほうが次への道が拓けるんじゃないでしょうか。

なんでPaaSの話なのに○○○が無いの!

はてブのブコメにあったのですが・・・単にさまざまなPaaSに言及していたら時間も足りないし本題とずれる、ただそれだけです。Herokuはこのジャンルを切り拓いた存在だから、Cloud Foundryは自分が関わっているから、という理由で言及した次第です。

f:id:jaco-m:20180424210600p:plain

Google App EngineだろうとAzure App Serviceだろうと、Elastic BeanstalkだろうとDeisだろうとFlynnだろうとTsuruだろうと(ゼェゼェ)、今回の発表で言いたかった『PaaSはアプリケーションのライフサイクルを支援し、開発の効率を高める』という点においてはどれも同じ志向です。 特定のPaaSを掘り下げたい方は、PaaS勉強会へ是非どうぞ

Serverlessにしても、Lambdaは言及せざるを得ないとして、じゃあ他は?となると、なかなか平等に取り上げるのは難しい話ですね。

ベンダーロックインへの考え方

f:id:jaco-m:20180424211610p:plain

会場では口頭で補足したんですが、スライドだけだとベンダーロックインダメと言っているように取られそうだったので・・・。

個人的には、ベンダーロックインはそこまで否定的に思っていません。価値の無いものに対して嫌々ロックインされるならば別ですが、ロックインされることで快適になり生産性が向上するなら、それでいいじゃないかと。

もちろん、特定のベンダーに依存するリスクも否定しません。だからこそ、大事なのは『自分のビジネスをハッキリさせること』なわけです。

f:id:jaco-m:20180424212112p:plain

自分のビジネスを見つめ直して、依存リスクよりも生産性だ!となればロックインされにいけば良いし、万が一の自体で大きな損害が発生しうるのであれば、徹底的にベンダーロックインを避ければ良い。そこは、人それぞれ異なります。

ちなみに、自分のベンダーロックインに関する考えは、5年ほど前に行った座談会の影響を受けています。『心地良いロックイン』という言葉はここで出たもので、使い勝手が良いのでよく使っています。

codezine.jp

まとめ — 制約は創造性をはぐくむ

f:id:jaco-m:20180424212639p:plain

自分が好きな言葉として紹介させてもらいました。自分が高校生の時に偶然読んだ、戦うWebデザインという本に載っていた言葉です。

プラットフォームに関する議論をする上で、示唆に富んだ言葉だと思っているので最近よく使っています。

アプリケーションフレームワークにある、 『設定より規約(convention over configuration)』の考え方はこれに近いようで、Ruby on Railsの作者であるDavid Heinemeier Hanssonは、『制約は自由をもたらす(constraints are liberating)』と言っているそうです。

プラットフォーム選択においては、どうしても「あれができるか、これができるか」という考え方をしてしまいがちです。

しかし、あえて制約のある、しかしながら開発生産性の高いプラットフォームを選んで時間を節約すれば、より創造的な仕事ができるなんてことも多々あります。是非、この言葉を思い出しながら自身のプラットフォーム選択をしていただければと思っています

Cloud Foundry勢の2018年のすごしかた

Cloud Foundry Advent Calendarの25日目

最終日! 無事Advent Calendar完結しました。ご参加いただいた皆様ありがとうございました。

以前開催したときよりも参加人数も増え、記事もほぼ遅れること無く公開され、とてもよいAdvent Calendarになったと思います。

さて、今回は最終日ということで、日本でのCloud Foundry界隈の活動について書いていきたいなと。

Cloud Foundry Tokyo Meetup

今年に入り四半期に1回ペースで開催しているCloud Foundry Tokyo Meetup.

www.meetup.com

これに関しては、来年も変わらず同じくらいのペースで開催したいなと思います。四半期に1回プラス特別編1回の5回開催を目標にしようかなと。 以前のエントリーでも書きましたが、Cloud Foundryはブランドの再整理が行われ、PaaSであるCloud Foundry Advent Calendarと、Kubernetesを運用する仕組みであるCloud Foundry Container Runtimeの2プロダクトを内包するブランドとして位置づけられることになりました。

jaco.udcp.info

これまでのPaaSであるCFARに特化することも考えましたが、PaaSに特化するのであればPaaS勉強会もあるし、PaaSに限っても話題がだいたい限られてしまうこともあり、この勉強会ではCFCRも等しく扱っていこうかなと考えています。

CFARもCFCRもBOSHという共通の管理インフラがありその上に成り立つ仕組みです。つまり、双方をうまく連携させながら使っていくことは当然考えられているわけで、Meetupでもそのあたりの使いこなし事例もどんどん取り上げていきたいなと考えています。

Small meetup or workshopの開催

どこまで実現できるかは分かりませんが、従来ながらの座学だけでなく、もっと小規模に、よりきめ細やかにCF触っていくイベントをやりたいなあと考えています。

というのも、CFに関わる皆さんなら感じているように、プラットフォームという性質上かなり大規模なシステムになりがちであり、個人でかるく触るには敷居の高いものになっています。Dockerはその手軽さから流行ったのも事実で、それに比べてCFは個人のエンジニアが一人で学ぶのは非常に難しい存在です。

そこで、何らしかの方法で環境を用意し、普段個人では試せないようなことをやってみる会をやっても面白いのではないかと。もちろん、そこには我々のようなCFに知見のあるメンバーも含めて。

日本Cloud Foundryグループ(CFGRJP)

これは僕個人で決められることではないのですが、ozz怪鳥会長ともども、もっと盛り上げていきたいなと。 基本的にはMeetupの開催がメインになると思いますが、もっとビジネスサイドの開拓もできると良いな〜と。ここについてはまだ具体的なアイディアがないのですが、もし俺に考えがある!という方が居たら教えてください。

ちなみにCFGRJPのSlackはこちらからご参加ください。

Join CFGRJP on Slack!

Advent Calendar 2018

来年もやるよ!

みなさま2018年もよいCloud Foundryライフをお過ごしください。で、是非来年のAdvent Calendarにもご参加ください。

コロケ芸の実例を見せながらBOSHのops fileの書き方を解説する

Cloud Foundry Advent Calendarの19日目

前回の投稿でCFにはコロケ芸というリソース節約方法があるということを書いたのですが、記事を公開した直後に同僚making氏から速攻でツッコミが。

すみませんすみませんすみません。

前回記事を書いたとき、手元でも動作する例を用意していたのですが、それはmanifestを直接修正してデプロイする形にしていました。 BOSH v1であればこうするしかなかったんですが、もう時代はBOSH v2。BOSH v2であればmanifestを直接修正するのは古い。やはりここはops fileを使わねば。

ということで、CFをコロケする例を示しつつ、併せてops fileをどう書いていくかという話をしたいと思います。

そもそもOps fileとは

正確にはOperations fileっていいます。

https://bosh.io/docs/cli-ops-files.html

ベースとなるYAMLに対して、特定の記法でops fileを渡すことで、値のオーバーライドや削除を行うことができます。

たとえば以下のようなベースYAMLがあったとして

name: my-cf

以下のようなOps fileを加えると

- type: replace
  path: /name
  value: other-cf

以下のような出力が得られます

name: other-cf

Path

ベースとなるYAMLのどの部分を指定するかを、このpathで表現します。

/と指定するとYAMLのルートを示します。上記の書き換え例だと、ルートに連なるnameというkeyに対して操作を行いたいので、/nameと指定しています。

他にもシンタックスがあるため、ドキュメントをを参照してください。

https://bosh.io/docs/cli-ops-files.html

Operation

上記のops file例でいうと、typeの部分がoperationに当たります。ここにはreplaceもしくはremoveを指定することができます。

pathに対して、値をreplaceするのか、あるいはremoveするか。replaceする場合は、valueで指定した値に差し替わります。

Ops fileで何が嬉しいの

CFをデプロイする場合、今後はcf-deployment を使ってデプロイするのが主流になりますが、たとえばこのデプロイするCFにカスタマイズをしたいとします。

昔のBOSHですと、この中のcf-deployment.ymlを直接編集するしかありませんでした。 しかし、このやり方はcf-deploymentをフォークしてしまうことになり、upstreamが更新された際にコンフリクトを起こしてしまうことになります。これはスマートなやり方とはいえません。

そこで、カスタマイズしたい内容をops fileとして切り出すことで、ベースとなるcf-deploymentに手を加えること無く行うことができます。

cf-deploymentのリポジトリには、よくあるカスタマイズについてはあらかじめops fileが同梱されており、-o オプションで指定するだけで適用することが可能です。

cf-deployment/operations at master · cloudfoundry/cf-deployment · GitHub

コロケするOps fileを作ってみよう

ということで、今回は例としてCloud ControllerとUAAを同居させる「Control」VMを作成する例を作ってみました。 完成版Ops fileはこちらにおいてあります。

UAAとAPIの中身をマージする

以下が、単純にUAAとAPIのjobをマージしたyamlです。

https://gist.github.com/jacopen/e447fb3f409ae5935c9e69c27dcae531#file-first-yml

これで流せば無事コロケ完了・・・かというとそうはいきません。いくつか問題点があります

  • 項目かぶり -- この例でいうとstatsd_injectorやroute_registrarなどの項目が重複しています。このままではエラーになってしまうため、この中身も適切にマージしてあげる必要があります。
  • ポートかぶり -- このJobsでは明示されていませんが、実はUAAとpolicy-serverはともにデフォルトで8080で上がってしまいます。このままではポートかぶりにより、どちらかのプロセスが正常に立ち上がりません。どちらかの設定を被らないポートに変更してやる必要があります。

ということで、ここのあたりは地味ーな作業をやって良い感じにコロケできる設定を作っていきます。

既存のUAAとAPIを無効にする

ControlVMでUAAとAPIをデプロイしてしまうので、以下のようにremoveを書くことで個別のVMが作成されないようにしました。

- type: remove
  path: /instance_groups/name=uaa
- type: remove
  path: /instance_groups/name=api

1az構成にする

Multi AZにするのであればこの作業はスキップできますが、今回はコロケで極限までVMを削る、というのを試してみたいので、1AZ構成に変更したいと思います。

cf-deploymentの中の operations/scale-one-az.yml を指定すると、1AZ構成に変更されます・・・が、今回はuaa/apiをremoveしてしまったため、単純に食わせるとエラーになってしまいます。ということで、美しくないですがopsfileの中に該当ファイルからuaa/apiを抜いた項目を追加する形にしました。(もっと良い案思いついたらなんとかします)

同じ理由で、NW名を引数で渡せるようにする operations/rename-network.ymlの中身も含めてしまっています。

ということで完成版

Collocate UAA and API · GitHub

・・・なんかもっとシンプルかつスマートにずばっとコロケできるようなのを目指したんですが、何か・・・長いですね。 とはいえcf-deployment.ymlを直接弄ってしまうよりはマシなものになっている、たぶんきっと。

あとは-oオプションでこのops fileを指定してやれば、デプロイできるはずです

bosh deploy -d cf cf-deployment.yml --vars-store env-repo/deployment-vars.yml -v system_domain=example.com -v network_name=bosh-network -o collocate.yml

必要にに応じて他のops fileも読ませてデプロイしてください。ただ、/instance_groups/name=apiや/instance_groups/name=uaa を操作するops fileの場合、エラーがでちゃうかも。

おいでよコロケ芸の森

Cloud Foundry Advent Calendar 2017の13日目

最近どうぶつを高く積み上げていくe-sportsを始めてみたのですが、あれよあれよと時間を吸われます。やばい。

さてみなさん。コロケ芸という言葉をご存じでしょうか。

もし知っているという人は、おそらく某所関係者かと思われますので多分この記事読まなくても大丈夫です。

CFの必要リソースでかいねん問題

Cloud Foundryの構築はBOSHを用いますが、BOSHはVMを用いてデプロイを行う仕組みなので、コンポーネントが増えれば増えるほどVMの数がすごいことになります。Cloud Foundryは数多くのコンポーネントから成りますので、デプロイするだけでものすごいVM数になります・・・というのは、CFに関わる人であればご存じでしょう。

きちんと理由があってコンポーネントが分けられているので、BOSHで管理する以上VM数が増えてしまうのは仕方ない・・・と言いたいところですが、とはいってもやっぱりコンパクトな環境でフル機能CFを使いたい。 BOSH-lite でAll in oneを構築してしまう手はありますが、そうではなく・・・と。

「なんとかしてリソースを節約しつつもプロダクションレディなCFクラスタを構築したい」

そういう考えから、VMに多くのコンポーネントを同居させつつも運用性は失わない、コロケーションのノウハウ、すなわちコロケ芸が、都内某所で脈々と受け継がれているという噂があります。

コロケ芸の広まり?

そんな門外不出のコロケ芸ですが、やはり同じことを考える人は多いようで。

Pivotal Cloud Foundryを提供するPivotalが、9月にリリースしたバージョン1.12で"Small Footprint Runtime (SRTと略す)"というリソース削減版を公開しました。これはまさに、コロケ芸そのものだったりします。

SRTの仕組み

Pivotalのドキュメントを見ると、以下のようなことが書いてあります。

The Small Footprint Runtime is a repackaging of the Elastic Runtime components into a smaller and more efficient deployment. A standard Elastic Runtime deployment must have at least 24 virtual machines (VMs), but the Small Footprint Runtime requires only 14.

24必要だったVMが14になる!とのこと。・・・うーん、確かに大きく減りましたがびっくりするほどの削減ではないですね・・・。 ですが、よく見てみましょう。

f:id:jaco-m:20171213195124p:plain

よく見ると、必要と言われているVMのうち多くをErrandが占めていることがわかります。ErrandはBOSHでrun-errandを行ったときに必要になってくるVMであり、常に立ち上がっているVMではありません。そのため、本当の意味で必要なVMはより限られることになります。

この図の中で、CF自体の動作に必要なVMは以下の4つのみです。

  • Control
  • Compute
  • Router
  • Database

つまり、HAを考えないのならば4VMでいける、というわけです。

コロケの実現方法

さてこのコロケ芸、どうやって実現しているんでしょうか。Pivotal Cloud Foundryも内部的にはBOSHなので、OSS CF でも同じことは出来るはずです。

cf-deploymentのUAAの記述をみてみましょう

https://github.com/cloudfoundry/cf-deployment/blob/master/cf-deployment.yml#L367-L577

インスタンス数、VMの種類の指定が続いたあと、jobs: にてどのjobをどういう設定で構築するか記述されていることが分かるでしょう。 もしUAAとCloud Controllerを同居させたい場合は、両方のJobを動かせるだけのインスタンスを指定し、jobs: の項目をマージしてやればいけそうです。

・・・というと簡単そうに聞こえますが、実際にはなかなかムズかしかったりします。そもそもマージさせていく作業が超絶地味だったり、jobの中でも重複する項目があったりと。

もしVM数を削減してみたいという方は、是非一度チャレンジしてみてはどうでしょうか

PCFを買ってSRTでセットアップすれば一瞬ですが

どういう単位でコロケするか

どのJobをどうコロケーションさせていくのがいいか。これは知恵の出しどころかなと思います。 たとえばコロケさせたうち特定のJobだけ過負荷でスケールアウトさせないと・・・という場合、コロケの仕方によっては不要なJobまで増やしてしまい、リソース削減のために行ったコロケが逆効果なんてことも起きえます。

先ほども紹介した、PCFのSRTはその分け方の参考になるかもしれません。

  • Control
  • Compute
  • Router
  • Database

の4VMが必須と書きましたが、そのうちComputeはdiego-cellそのものです。他のものは同居していません。 また、Routerに関してもGorouterそのものです。

つまり、CFを使う上で一番負荷がかかりやすいであろう、Gorouterとcellだけは他と同居させず、そのままというわけです。

CFの主要なコンポーネントの多くは、Controlに集約されています

f:id:jaco-m:20171213212033p:plain

また、Consul, NATS, MySQLに関してはDatabaseに集約されます

f:id:jaco-m:20171213212122p:plain

Consulは仕組み上、クラスタを組むのであれば3台, 5台といった奇数にする必要があります。つまり、HAで組む場合Databaseは3台必要ということになりますね。

ControlやRouter, Computeは2台以上あればHA構成になります

ここらでひとつCFの昔話をしながら変遷を振り返る(その2)

Cloud Foundry Advent Calendar 2017の11日目

前回に引き続きCFの昔話を。

言語

現在のCFはほとんどがGoで書かれていますが、CFv1はRubyで書かれていました。CFv2も当初はRubyで書かれていましたが、徐々にGoに書き換えられていきました。

現在Rubyが残っているのはCloud Controllerくらいでしょうか。なおUAAに関しては出た当初から今に至るまでJavaで書かれています。おそらくSpring Securityを使いたかったからかと思われます。

Router

現在はGoで書かれたGorouterが使われていますが、CFv1からCFv2の初期に使われていたRouterは、Nginx+Lua+Rubyという構成でした。

github.com

NATS経由でのルーティング情報のやりとりはRubyで書かかれたアプリケーションが担い、実際にトラフィックを捌くのはNginx+Luaという仕組みです。 枯れているNginxを利用しているだけあってパフォーマンスは悪くなく、Gorouterの登場当初は旧Routerよりも速いというのが公式の見解でしたが、実際には旧Routerのほうがパフォーマンスが良いというケースもしばしばありました。

CLI

CFv1はcfコマンドではなく、vmcコマンドというものを使っていました。

vmcコマンドはRubyで書かれており、利用するにはまずRuby環境をととのえ、その上でgem install vmcを行う必要がありました。今みたいにGolangで書いて1バイナリで配布なんてことが出来なかった時代です。

現在でもRubygems.orgに残っており、インストールできます。(といっても使い道はないですが)

vmc | RubyGems.org | your community gem host

最終バージョンは0.5.1となっていますが、0.5系や0.4系は非常に不安定であり、かつUAA導入の過渡期でもあったため、利用できない環境が数多く存在しました。

CFv1利用者の中では「CFを使うならvmc 0.3.23を使え」が合い言葉であり、結局CFv1終焉まで0.3.23が利用され続けました。

vmc tunnel

vmcコマンドでユニークなものとしては、vmc tunnel コマンドが挙げられます。 vmc tunnelコマンドを打つとCF上にcaldecottと呼ばれるアプリがデプロイされ、caldecottとvmcコマンド間でトンネルが張られ、サービス(MySQLやPostgres)にコマンドを打ったりdumpしたり出来ました。

なぜか当時は存在しなかったはずのPivotalのサイトにblog記事が残っていました。 Now You Can Tunnel into Any Cloud Foundry Data Service

$ vmc tunnel postgresql-12345

Trying to deploy Application: 'caldecott'.
    Create a password: 

Uploading Application:
 Checking for available resources: OK
 Processing resources: OK
 Packing application: OK
 Uploading (1K): OK
Push Status: OK
Binding Service [postgresql-12345]: OK
Staging Application: OK
Starting Application: OK
Getting tunnel connection info: .OK

Service connection info:
 username : ua76003139485469989d57b22f9cb83xx
 password : p8214ebd2a7254698913e01c86a4432xx
 name : da281fa2162f947028876d0500ae31cxx

Starting tunnel to postgresql-12345 on port 10000.
1: none
2: psql
What client would you like to start?: 2
Launching 'PGPASSWORD='p8214ebd2a7254698913e01c86a4432xx' psql -h localhost -p 10001 -d da281fa2162f947028876d0500ae31cxx -U ua76003139485469989d57b22f9cb83xx -w'

psql (9.0.4)
Type "help" for help.
da281fa2162f947028876d0500ae31cxx=> d
                     List of relations
 Schema | Name  | Type  |               Owner
--------+-------+-------+-----------------------------------
 public | hotel | table | ua76003139485469989d57b22f9cb83xx

da281fa2162f947028876d0500ae31cxx> select * from hotel;
  1 | 3555 S. Ocean Drive                    | Hollywood           | USA           | Westin Diplomat                | 199.00 | FL        | 33019
  2 | 890 Palm Bay Rd NE                     | Palm Bay            | USA           | Jameson Inn                    |  60.00 | FL        | 32905
  3 | The Cottage, Southampton Business Park | Southampton         | UK            | Chilworth Manor                | 199.00 | Hants     | SO16 7JF

結構便利じゃないですか?これ。

vmcコマンドからサービスに直接psqlコマンド叩きにいけるんですよ。

CFv2に移行して一番不便に感じたのが、この機能が無いことでした。初期のCFv2はcf sshコマンドも無かったため、v1で出来たこのあたりの操作を行う代替案が限られていたんですよね。

CFv1のデプロイ方法からBOSHに至るまで

現在はCFといえばBOSH、BOSHといえばCFというくらい重要な存在になっていますが、BOSHはCFv1の開発と運用の結果、既存の仕組みでは運用に耐えられないということで開発されたものです。つまり、CFv1はBOSHじゃない別の仕組みを使っていたというわけです。

CFv1は、dev_setupというchef-soloを利用した仕組みでデプロイを行っていました。

github.com

chef-soloですのでそのままでは複数台構成にできません。そこで、CFを構築する人たちはcapistranoなどを使ってdev_setupを各ノードに送り込み、コンポーネントごとの設定ファイルを食わせてchef-soloを実行していました。

d.hatena.ne.jp

しかしこの運用はほんとうにツライものでした。

https://github.com/cloudfoundry-attic/vcap/blob/master/dev_setup/cookbooks/python/recipes/default.rb#L9-L11

たとえばChefのcookbook読むとこんな書き方が普通に行われています。

%w[ python-dev python-setuptools ].each do |pkg|
  package pkg
end

aptのリポジトリからpython-devやpython-setuptoolsが落とされてくるわけですが、何が起きるかというと「セットアップを流した時点での最新版が入る」わけです。つまり、昔構築した環境と、新しい環境では異なったバージョンがセットアップされている可能性が高い。

「でも、それが何か? 多少バージョン異なっても問題ないでしょ?」 って思われるかもしれません。でもそれは甘い。

https://github.com/cloudfoundry-attic/vcap/tree/master/dev_setup/cookbooks

これだけのCookbookがあり、それぞれのライブラリが複雑な依存関係を持っている。こうなると、結構高い頻度で依存関係のエラーが起きるんですよね。エラーでセットアップが止まってしまうのもツライし、その後原因特定もツライ。複雑に絡み合った依存関係の中から原因となっているパッケージとバージョンを切り分けて、問題が起きないように修正するという作業は、何も価値を生まない割には時間ばっかり消費する、できれば二度と経験したくないものでした。

BOSHはこういうトラブルが起きないよう、考え抜かれた仕組みになっています。

BOSHは導入の敷居が高く、あまり好ましく思わない人も多いのですが、じゃあたとえば同じ運用をChefでなくAnsibleでやれば上手くいくか?となると、おそらくダメでしょう。Chefの二の舞になって死ぬのが目に見えています。このあたりの運用を経験しないと、なかなかBOSHの良さって理解されないんですよね・・・。

Serviceの仕組み

CFはv1の頃から、今と変わらないServiceの仕組みを備えていました。

vmc create-service vmc bind-service vmc delete-service

一緒ですね。

しかしバックエンドの仕組みは微妙に異なりました。

ozalog.blogspot.jp

Cloud Controllerからのリクエストを受け取るService Proxyと、実際のバックエンドサービスがデプロイされているService Nodeに分かれており、Service ProxyとNode間はNATSで通信を行っていました。

現在のCFで利用されているService Brokerの考え方は、このService Proxyをより汎用的にAPI化したものです。Brokerがどういった形でバックエンドサービスをプロビジョニングするかは定義されおらず、好きに実装してくれというのが今の形です。

CF側でServiceを提供することしか考えられていなかったv1に対し、サードパーティーの提供するServiceも幅広くサポートしようという、エコシステムを意識して発展させた仕組みが現在のService Brokerといえるでしょう。

日本のコミュニティの誕生と今について

日本では2011/10/18に第1回 Cloud Foundry輪読会が開催されています。 当時CFの採用を検討していたNTTや楽天、富士通といった会社のメンバーが中心になっていますね。

atnd.org

また、2012年2月にはNTTをはじめ数社で日本Cloud Foundryグループが設立されています。

www.ntt.co.jp

ビジネス的な色合いの強い日本Cloud Foundryグループと、コードリーディングというディープ志向のCF輪読会。いきなりコミュニティの分断が起きてしまい、一体感を持った盛り上げ方が上手くいかなかったなーというのは振り返っても感じます。

その後日本Cloud Foundryグループは引き続き活動を続けており、関係するメンバーでCloud Foundry Tokyo meetupというものもやっています。

Cloud Foundry輪読会は、その後PaaS勉強会と名前を変え、今でも続いています。

2018年はCloud Foundry Container Runtimeの登場により、Cloud Foundryがカバーする範囲も大きく変わってきます。再度Cloud Foundryのコミュニティを活性化するよう、いろいろ活動していきたいなあと考える今日この頃です。