2018/12/14 freee Tech Night #1 「freee on Rails の今とこれからの話」
freee 株式会社Rails on Kubernetes-どうする?〇〇-2018.12.14Takeru Ichii
View Slide
みなさま
知ってる人
つかったことある人
正しく「くーばねぃてす」って書ける人
「くーべるねてす」って覚えてます
今日はそんなお話
● 2017/10月 freee入社○ きっかけはガード下● 副業でプロカメラマンっぽいあれ● freeeではRailsApp開発やってますTakeru Ichiiいっちーfreee株式会社 エンジニア12
13おしながき 06 まとめ 05 逆引き Rails on Kubernetes どうする?〇〇 04 Kubernetesで動かすRailsの実例 03 Kubernetes基礎知識(用語解説) 02 Kubernetesのメリット・デメリット 01 Kubernetesとは?
01 Kubernetesとは?14Section
Kubernetesとは?15● コンテナ化されたAppのDeploy/Scaling等の管理を自動化○ 一般に「コンテナオーケストレーションエンジン」● 類似にDocker Swarm● 曰く「コンテナオーケストレーションのデファクトスタンダード」● GCPではGKEがマネージドサービスとして提供されている○ AWSでは2018/6からEKSが一部リージョンで利用可能● つまり「ナウなヤングにバカウケな、イケてるコンテナオーケストレーション」
Kubernetesができること16● Node管理○ 複数台のマシンの管理● ローリングアップデート○ 無停止でのアプリケーションアップデート● スケーリング○ リソース監視によるオートスケール● 死活監視○ プロセス死亡時のオートリカバリ● ロードバランス○ 複数のプロセスへのトラフィック振り分け● and more
ざっくりいうと
Kubernetesができることざっくりver.これが、ドッカーン!
ドッカーンとなって、Kubernetesができることざっくりver.ドッカーン!ドッカーン!ドッカーン!ドッカーン!ドッカーン!
めっちゃすごい。(=ロードバランス・スケーリング)Kubernetesができることざっくりver.ドッカーン!ドッカーン!ドッカーン!ドッカーン!ドッカーン!
こわれても、Kubernetesができることざっくりver.
とても安心。(=死活監視・ローリングアップデート)Kubernetesができることざっくりver.
Kubernetesができることざっくりver.ってやつですドヤッ
02 Kubernetesのメリット・デメリット28Section
Kubernetesのメリット29● Appの要件からインフラに要求してたことがアプリエンジニアでできる○ Ex:非同期実行基盤をつくりたい(sidekiq, Resque, ...)■ いままで● インフラ部隊に実行環境の準備をお願いして、疎通確認やらなんやら● 「これ実行環境がわるいんちゃう?」「いやアプリの実装やろ」■ これから● アプリエンジニアがKubernetesのマニフェストを書くだけでOK● Kubernetesに標準でついてる強力な機能の享受
Kubernetesのデメリット30● 学習コスト○ アプリケーションを動かす概念が違うので、最初は戸惑うかも?● Kubernetesの運用保守○ これはマネージドサービスを使えばある程度軽減できる?○ インフラ部隊はKubernetesの運用保守に専念すれば良いので、大きな組織ではメリットになりうる?○ freeeではmumoshuさんをはじめSREチームの力で安定的に稼働してます
03 Kubernetes基礎知識(用語解説)31Section
Kubernetesワード32kubectl
Kubernetesワード33kubectlPod● 一つ以上のContainerを有するアプリケーション実行の最小単位
Kubernetesワード34kubectlService● クラスタ内・外からPodへまでを疎通させるLBリソース● イメージとしてはL4 LB
Kubernetesワード35kubectlIngress● (雑に)外界からServiceまでをつなぐLBリソース● イメージとしてはL7 LB
Kubernetesワード36kubectlDeployment● 複数のPodのローリングアップデートやロールバックなどを実現する
Kubernetesワード37kubectlJob● コンテナを利用して一度きりの処理を実行するリソース● 実行はPodを介して行われる
Kubernetesワード38kubectlNode● Podを動かすリソースを提供する● Clusterを構成する実マシンを指す場合もある
Kubernetesワード39kubectlMaster● KubernetesのAPIエンドポイントの提供● NodeやPodを始めとするリソースの管理
04 Kubernetesで動かすRailsの実例40Section
41というサービスでKubernetesを使っています
顧問先管理freeeのサービス構成(2018/12現在)42
05 逆引き Rails on Kubernetesどうする?〇〇43Section
さまざまな疑問Rails on Kubernetesを行う上で代表的な疑問44Build,Deploy,Health Check● コンテナビルドはどうしている?● デプロイはどのように行っている?● DBマイグレーションは?● デプロイが失敗したときは?Configration● マニフェストファイルの種類は?● 環境変数はどう管理している?● Token等の情報の管理はどうしている?Network,Scalability● Assetsの配信はどうする?● L7 LBをやりたい場合は?● 負荷時のAuto Scaleはどうする?
さまざまな疑問Rails on Kubernetesを行う上で代表的な疑問45Build,Deploy,Health Check● コンテナビルドはどうしている?● デプロイはどのように行っている?● DBマイグレーションは?● デプロイが失敗したときは?Configration● マニフェストファイルの種類は?● 環境変数はどう管理している?● Token等の情報の管理はどうしている?Network,Scalability● Assetsの配信はどうする?● L7 LBをやりたい場合は?● 負荷時のAuto Scaleはどうする?
46コンテナビルドPod内で動かすDockerコンテナはCircleCIの一連のJobでビルドしている
47コンテナビルドコンテナビルドを高速化するために、いくつかの手法の取り入れ● レイヤーキャッシング○ 有料プランであれば docker_layer_caching で有効化可能● ビルド用イメージの作成と成果物のボリュームマウント○ Appに必要なlibraryを事前に別コンテナでインストールし、ホストにmount○ AppコンテナでそれをADDし利用するDockerコンテナのビルド手法● CircleCI Cache○ ビルド用イメージで生成した成果物を別のビルドでも使えるようにするためにCircleCI側で指定の成果物を再利用する
48コンテナビルドビルド用イメージとCircleCI Cacheの併用vendor/bundle/node_modules/Gemfile, Gemfile.lockpackage.json,yarn.lockADDADDdocker run \-v vender/bundle:/app/vender/bundle \-- bundle install --deploymentdocker run \-v node_modules:/app/node_modules \-- yarn install
49コンテナビルドビルド用イメージとCircleCI Cacheの併用vendor/bundle/node_modules/(other files)ADD
50コンテナビルドビルド用イメージとCircleCI Cacheの併用vendor/bundle/node_modules/(other files)Cache
51コンテナビルドビルド用イメージとCircleCI Cacheの併用vendor/bundle/node_modules/RestoreCache
52コンテナビルドビルド用イメージとCircleCI Cacheの併用vendor/bundle/node_modules/Gemfile, Gemfile.lockpackage.json,yarn.lockADDADDdocker runRestoreCachedocker run
53デプロイ・マイグレーション● デプロイはCircleCIから行う(kind: Deployment)● DBマイグレーションもCircleCIから実施(kind: Job)● デプロイ・マイグレーションのWait○ kubectl get で取得できる情報をパースして判定するsh scriptを自作● デプロイの成功判定にReadiness/Liveness Probe を利用○ Readiness Probe■ 失敗したらLBから外され、成功したら再びLBターゲットに入る○ Liveness Probe■ 失敗したら再起動
54マイグレーションdbmigration.job.ymlapiVersion: batch/v1kind: Jobmetadata:name: hoge-app-migration-jobspec:backoffLimit: 3parallelism: 1completions: 1template:metadata:labels:app: hoge-app-migrationspec:restartPolicy: Nevercontainers:- name: hoge-app-migrationimage: HOGE_APP_IMAGE_NAMEimagePullPolicy: Alwayscommand: ["bin/rails","db:migrate"]apiVersion: batch/v1kind: Jobmetadata:name: hoge-app-migration-jobspec:backoffLimit: 3parallelism: 1completions: 1template:metadata:labels:app: hoge-app-migration
55マイグレーションapiVersion: batch/v1kind: Jobmetadata:name: hoge-app-migration-jobspec:backoffLimit: 3parallelism: 1completions: 1template:metadata:labels:app: hoge-app-migrationspec:restartPolicy: Nevercontainers:- name: hoge-app-migrationimage: HOGE_APP_IMAGE_NAMEimagePullPolicy: Alwayscommand: ["bin/rails","db:migrate"]spec:restartPolicy: Nevercontainers:- name: hoge-app-migrationimage: HOGE_APP_IMAGE_NAMEimagePullPolicy: Alwayscommand: ["bin/rails", "db:migrate"]dbmigration.job.yml
56マイグレーション
57マイグレーションkubectl apply -f \dbmigration.job.yml
58マイグレーションdocker pull
59マイグレーションbin/rails db:migrate
60マイグレーションbin/rails db:migrateMigration
61マイグレーションbin/rails db:migrateMigrationkubectl get \job hoge-app-migration-jobdeploy/wait_job.sh \hoge-app-migration-job \10 \default
62デプロイdeploy.ymlapiVersion: extensions/v1beta1kind: Deploymentmetadata:name: hoge-appspec:template:metadata:labels:app: hoge-appspec:containers:- name: hoge-appimage: HOGE_APP_IMAGE_NAMEimagePullPolicy: Alwaysports:- containerPort: 8080readinessProbe:httpGet:path: /readyport: 8080initialDelaySeconds: 10periodSeconds: 10failureThreshold: 5livenessProbe:httpGet:path: /liveport: 8080initialDelaySeconds: 10periodSeconds: 10failureThreshold: 5selector:matchLabels:app: hoge-appapiVersion: extensions/v1beta1kind: Deploymentmetadata:name: hoge-appspec:template:metadata:labels:app: hoge-appspec:containers:
63デプロイdeploy.ymlapiVersion: extensions/v1beta1kind: Deploymentmetadata:name: hoge-appspec:template:metadata:labels:app: hoge-appspec:containers:- name: hoge-appimage: HOGE_APP_IMAGE_NAMEimagePullPolicy: Alwaysports:- containerPort: 8080readinessProbe:httpGet:path: /readyport: 8080initialDelaySeconds: 10periodSeconds: 10failureThreshold: 5livenessProbe:httpGet:path: /liveport: 8080initialDelaySeconds: 10periodSeconds: 10failureThreshold: 5selector:matchLabels:app: hoge-appcontainers:- name: hoge-appimage: HOGE_APP_IMAGE_NAMEimagePullPolicy: Alwaysports:- containerPort: 8080
64デプロイdeploy.ymlapiVersion: extensions/v1beta1kind: Deploymentmetadata:name: hoge-appspec:template:metadata:labels:app: hoge-appspec:containers:- name: hoge-appimage: HOGE_APP_IMAGE_NAMEimagePullPolicy: Alwaysports:- containerPort: 8080readinessProbe:httpGet:path: /readyport: 8080initialDelaySeconds: 10periodSeconds: 10failureThreshold: 5livenessProbe:httpGet:path: /liveport: 8080initialDelaySeconds: 10periodSeconds: 10failureThreshold: 5selector:matchLabels:app: hoge-appreadinessProbe:httpGet:path: /readyport: 8080initialDelaySeconds: 10periodSeconds: 10failureThreshold: 5livenessProbe:httpGet:path: /liveport: 8080initialDelaySeconds: 10periodSeconds: 10failureThreshold: 5
65デプロイbin/rails s
kubectl apply -f \deploy.yml66デプロイbin/rails s
67デプロイbin/rails s
68デプロイdockerpullbin/rails s
69デプロイbin/rails sbin/rails s
70デプロイSELECT 1;GET /readyGET /livebin/rails sbin/rails s
71デプロイbin/rails s
72デプロイkubectl get \deploy hoge-appdeploy/wait_deployment.sh \hoge-app \20 \defaultbin/rails s
さまざまな疑問Rails on Kubernetesを行う上で代表的な疑問73Build,Deploy,Health Check● コンテナビルドはどうしている?● デプロイはどのように行っている?● DBマイグレーションは?● デプロイが失敗したときは?Configration● マニフェストファイルの種類は?● 環境変数はどう管理している?● Token等の情報の管理はどうしている?Network,Scalability● Assetsの配信はどうする?● L7 LBをやりたい場合は?● 負荷時のAuto Scaleはどうする?
74マニフェストファイルの管理● マニフェストファイルとはKubernetesを設定するファイルのこと● appレポジトリのdeploy/下にすべて配置● JSONとYAMLが選べる○ 自分のPJではYAML● deploy/○ deploy.yml○ dbmigration.job.yml○ service.yml○ Dockerfile(s)○ configmaps/■ production.configmap.yml■ staging.configmap.yml○ secrets/■ production.secret.yml.enc■ staging.secret.yml.enc○ kubeconfig/■ production.kubeconfig.enc■ staging.kubeconfig.enc
75マニフェストファイルの管理● deployment/Job(migration)は全環境(Production/Staging)で統一● 環境差異がある箇所はsedやyqでアンカーテキストをCIでデプロイ時にリプレース● deploy/○ deploy.yml○ dbmigration.job.yml○ service.yml○ Dockerfile(s)○ configmaps/■ production.configmap.yml■ staging.configmap.yml○ secrets/■ production.secret.yml.enc■ staging.secret.yml.enc○ kubeconfig/■ production.kubeconfig.enc■ staging.kubeconfig.enc
76マニフェストファイルの管理● 環境変数設定はすべてConfigMapやSecretに記述○ DeploymentのPodSpecには記載しない● SecretはSOPSをつかってAWS KMSの鍵情報による暗号化を実施○ .enc という拡張子をつけてレポジトリに保管○ .gitignoreの設定で間違えて平文を保管しないようにする必要がある■ /deploy/secrets/*!/deploy/secrets/*.enc● deploy/○ deploy.yml○ dbmigration.job.yml○ service.yml○ Dockerfile(s)○ configmaps/■ production.configmap.yml■ staging.configmap.yml○ secrets/■ production.secret.yml.enc■ staging.secret.yml.enc○ kubeconfig/■ production.kubeconfig.enc■ staging.kubeconfig.enc
77マニフェストファイルの管理● kubeconfigはKubernetesClusterに 接 続 するための鍵情報が入っている● こちらもSOPSによる暗号化を実施● deploy/○ deploy.yml○ dbmigration.job.yml○ service.yml○ Dockerfile(s)○ configmaps/■ production.configmap.yml■ staging.configmap.yml○ secrets/■ production.secret.yml.enc■ staging.secret.yml.enc○ kubeconfig/■ production.kubeconfig.enc■ staging.kubeconfig.enc
さまざまな疑問Rails on Kubernetesを行う上で代表的な疑問78Build,Deploy,Health Check● コンテナビルドはどうしている?● デプロイはどのように行っている?● DBマイグレーションは?● デプロイが失敗したときは?Configration● マニフェストファイルの種類は?● 環境変数はどう管理している?● Token等の情報の管理はどうしている?Network,Scalability● Assetsの配信はどうする?● L7 LBをやりたい場合は?● 負荷時のAuto Scaleはどうする?
79L7 LB/Assets配信● Rails AssetsをKubernetesで配信する2つのアプローチ○ kind: Ingressをつかって /assets は別のPodで動かすnginxで配信する○ passenger-rubyによる1PodでAssets配信とrailsServer両方動かす● 採用したのはpassenger-ruby○ ある程度設定がなされているので導入が容易○ ただし、細かいL7 LBをしたい場合に対応できない○ Assets配信にリソースが取られるのであればIngressアプローチが良い
80L7 LB/Assets配信/assets/*/*
81L7 LB/Assets配信/assets/*/*
82Auto Scale● KubernetesにはPodのAutoScaleに標準でHPAが用意されている○ Horizontal Pod Autoscaler(水平ポッドオートスケーラー)○ 指定メトリクスになるようにPod数を調節する○ 例えばCPU平均使用率が50%になるようにPod数を調整するなど● 垂直オートスケールも存在する(スケールアップ)
06 まとめ83Section
84まとめ● インフラ部隊による細かなサポートを必要とせずにアプリケーションエンジニアが柔軟にアプリケーション構成を変更することができる● 強力な機能によってトラフィックがおおくてもとても安心● ナウなヤングにバカウケな、イケてるコンテナオーケストレーション● 「くーべるねてす」って覚えるとスペルミスしない
スモールビジネスを、世界の主役に。
86(おまけ)Sli.do 質問の回答● コンテナのログとかはなにを使って収集していますでしょうか?○ Containerの標準出力をnodeごとにfluentdで集めてS3に配置したり、Kibanaで見れるようにしたりしてます。● Kunerness と aws の連携でなにができますか?それでよかったことはなんでしょうか?○ PodにIAM RoleつけてセキュアにAWSのマネージドサービス使えたりがよいと思っています。あとはS3アップロードするみたいな場合にNetwork的に高速に利用できるところでしょうか。EKSが来ればより簡単にAWS上でKubernetesが利用できるのでそういうところは(東京リージョンに来たときに)期待してます!
87(おまけ)Sli.do 質問の回答● k8sをメンテする担当のインフラ担当者はいますか。いたとしたら何名ほどいますか?○ SREチームがメンテ担当ですが、Kubernetes専門の担当者はいないはずです。今までのインフラもみつつ、Kubernetesも見るという感じの担当者が多いです。人数に関しては詳しく言えませんが、SREチームは5~とおもっていただければと思います。● EKS 使ってますか?○ 現状では使っていません。東京リージョンにまだ来てないからです。○ ちなみにたびたび紹介していたmumoshuさん曰く「東京に来たらマッハでEKSに移行したい」って言ってました。
88(おまけ)Sli.do 質問の回答● データストア(永続化)はやはり主にNASですか?○ NASと言っても様々な答えがあって、なんとも答えにくいのですが、AWSで利用している場合には一般的にEBSの利用が考えられます。○ Kubernetensでは永続化ストレージにPersistentVolumeが利用でき、標準のプラグイン実装にEBSもあるので、簡単にEBSをつかってストレージを構成・マウントすることができます。