Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
実践Play2+Kubernetes
Search
Tatsuya Atsumi
April 03, 2018
Technology
240
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
実践Play2+Kubernetes
市ヶ谷Geek★Nightでの発表資料
Tatsuya Atsumi
April 03, 2018
More Decks by Tatsuya Atsumi
See All by Tatsuya Atsumi
dbt運用の7つの疑問と対策
attsun1031
3
2.2k
builderscon2018 airflowを用いて、 複雑大規模なジョブフロー管理 に立ち向かう
attsun1031
1
2.6k
Pythonで入門するApache Spark
attsun1031
1
340
Other Decks in Technology
See All in Technology
AI × アーキテクト 第1・2章|生成AIの課題とアーキテクトの素養
daidaidai
0
170
スプシの手作業からの解脱 ~更新はClaude Codeに、見せ方と使い方はGASアプリに任せる~
kentarofujii
0
150
10年後、Engineering 行為を剥奪されるとして、わたしたちは、どう、何を創ればいいだろうか。 / If Engineering Is Taken Away in 10 Years, How and What Should We Create?
bitkey
PRO
1
190
ブラウザとサーバーから考えるAI時代のフロントエンド監視
shogo4131
3
940
⾮構造化データを価値に変える AI エージェント基盤とその組織
ivry_presentationmaterials
0
190
AI コーディングと人間の認知スループット / CTO Night & Day 2026 Morning Session / AI Coding and Human Cognitive Throughput
prog893
4
1k
エンタメ企業のM&Aを支えるデータ基盤 ― 統合から店舗のリアルタイム分析まで / Data Engineering Summit 2026
genda
0
170
JAWS-UGグッズ職人仕事の流儀
kentapapa
0
100
Classmethod Company Deck
satoshi7
1
680
M5Stackで作る BLEマウス GPSログの世界
tomokusaba
0
420
脆弱性診断って、何をしているの? 〜弱点を見つけて、会社の改善につなげるまで〜
keeg
0
920
大型犬好きによるPugの紹介
yamanoku
1
160
Featured
See All Featured
Faster Mobile Websites
deanohume
310
32k
Marketing to machines
jonoalderson
1
5.9k
brightonSEO & MeasureFest 2025 - Winning Strategies for Black Friday CRO & PPC - Christian Goodrich
cargoodrich
3
870
Ruling the World: When Life Gets Gamed
codingconduct
0
400
We Are The Robots
honzajavorek
0
400
Making the Leap to Tech Lead
cromwellryan
135
10k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
1
630
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
730
Measuring & Analyzing Core Web Vitals
bluesmoon
9
1k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
890
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
31k
First, design no harm
axbom
PRO
2
1.3k
Transcript
実践Play2 + Kubernetes 2018/04/03 市ヶ谷Geek★Night
• Twitter: https://twitter.com/__Attsun__ • ブレインパッドという会社で自社サービス開発してます • VP of Engineeringとかテックリードとかやってます •
得意な言語はPythonです!家ではGoです!Scalaは仕事です! ◦ ScalaはBetter Javaとして使っているだけのガチじゃない勢です • Kubernetesが好きで! 自己紹介:渥美 達也
ブレインパッドのご紹介 • データ分析の会社と思われがちですが、 • エンジニアがいるんです! • デジタルマーケティング領域の自社製品を作っています • RtoasterはDMP業界シェアNo.1 •
広告周りは新規製品開発が盛んです。 • もちろん、機械学習やデータ分析の知見はサービス開発にも活きています
アジェンダ 1. k8sを利用しているサービスのご紹介 2. k8sのおさらい 3. システム構成 4. Play2 on
k8sのプラクティス a. コンテナビルド b. k8sへのデプロイ c. 環境変数の設定 d. コンフィグの設定 e. ロギングの設定
今日お話しするシステムのサービスをご紹介
今日お話しするシステムのサービスをご紹介 スマホで広告管理が完結!
今日お話しするシステムのサービスをご紹介 スマホで広告管理が完結! 複数媒体の予算管理もお任 せ!
今日お話しするシステムのサービスをご紹介 スマホで広告管理が完結! 複数媒体の予算管理もお任 せ! わかりやすいレポートと、役に立 つサジェスト!
システム構成ざっくり Cloud Load Balancing Cloud DNS Cloud SQL GKE 1.9
admin Deployment web Deployment batch CronJob Firebase Media (G, Y, …) BigQuery MediaHub Accounts batch CronJob
Kubernetesを軽くおさらい
Kubernetesとは? 公式によると、以下だそうです。 Kubernetes is an open-source system for automating deployment,
scaling, and management of containerized applications. 雑に表現すると、コンテナベースのアプリケーションを管理する仕組みですね。
Pod / Deployment / Service / kubectl • Pod ◦
Kubernetesで実行されるアプリケーションの最小単位です。 ◦ 1個以上のコンテナから構成されます。 • Deployment ◦ 個々のPodをどのように実行するかを管理する単位です ◦ Podのレプリカの数や、Podが利用するコンテナを管理しており、Deploymentを更新することでPod が更新されます。 • Service ◦ Podを論理的な単位でまとめ、それらへのアクセスポリシーを定義する仕組みです。 ◦ Podはコンテナアップデートなどにより頻繁に生成されたり破棄されたりを繰り返しますが、Service を見ている限り影響されません。 • kubectl ◦ kubernetesのコマンドラインクライアントです。 ◦ kubectl apply xxx.yaml で、YAMLに記載されたDeploymentなどの設定を反映するなど。 今日必要な最低限の知識
[node-2] [node-1] Pod / Deployment / Service
[node-2] [node-1] Pod / Deployment / Service [pod-nginx-1] nginx container
[pod-nginx-2] nginx container Podは特定のノード上で稼働し ます。
[node-2] [node-1] [deployment-nginx] container=nginx:1.7.9 replica=2 port=80 Pod / Deployment /
Service [pod-nginx-1] nginx container [pod-nginx-2] nginx container Podがどのように稼働するかは、 Deploymentにより管理される (ReplicaSetは割愛)
[node-2] [node-1] [deployment-nginx] container=nginx:1.7.9 replica=2 port=80 Pod / Deployment /
Service [pod-nginx-1] nginx container [pod-nginx-2] nginx container [service-nginx] Serviceが、Podへのアクセスを管理 している。 このケースではLBとしても働いてい る。
Kubernetesについては、 今日はこれで十分
Play2+Kubernetes周りのtips
Podの構成 • 同じPodの中に複数のコンテナが動いているパターン • Nginxコンテナ ◦ 静的コンテンツのホスト ◦ Play2 APIへのプロキシ
• Play2コンテナ ◦ Nginxから流れてきたAPIを実行する ◦ ベースはJava8コンテナ ◦ Scala 2.11 + Play 2.5 • Cloud SQL Proxyコンテナ ◦ Cloud SQLへの接続に必要なやつ webapp Pod Nginx Container Play2 Container CloudSQLProxy Container
1. sbtでPlay2コンテナを生成してpush 2. k8sのDeployment/Serviceの定義ファイルを作成してkubectl apply めっちゃ簡単です Play2コンテナがk8sで動作するまで
sbtでPlay2コンテナ作成 lazy val webapp = project.in(file(“webapp”)) .dependsOn(依存パッケージたち) .enablePlugin(PlayScala, JavaAppPackaging, sbtdocker.DockerPlugin)
.settings(Scalaバージョンなどの共通セッティング) .settings( buildInfoPackage := “パッケージ名” buildOptions in docker := BuildOption(cache = false), imageNames in docker := Seq(s“${gcrRegion.value}/${moduleName.value}:${version.value}”), dockerfile in docker := { val appDir = stage.value val targetDir = “/opt/docker” new Dockerfile { from(java8イメージ) expose(9000) copy(appDir, targetDir) entryPoint(s”$targetDir/bin/${executableName.value}”) } } build := docker.value )
sbtでPlay2コンテナ作成 lazy val webapp = project.in(file(“webapp”)) .dependsOn(依存パッケージたち) .enablePlugin(PlayScala, JavaAppPackaging, sbtdocker.DockerPlugin)
.settings(Scalaバージョンなどの共通セッティング) .settings( buildInfoPackage := “パッケージ名” buildOptions in docker := BuildOption(cache = false), imageNames in docker := Seq(s“${gcrRegion.value}/${moduleName.value}:${version.value}”), dockerfile in docker := { val appDir = stage.value val targetDir = “/opt/docker” new Dockerfile { from(java8イメージ) expose(9000) copy(appDir, targetDir) entryPoint(s”$targetDir/bin/${executableName.value}”) } } build := docker.value ) これらのプラグインを使って、 jar 生成からコンテナビルドまで一 気にやります。
sbtでPlay2コンテナ作成 lazy val webapp = project.in(file(“webapp”)) .dependsOn(依存パッケージたち) .enablePlugin(PlayScala, JavaAppPackaging, sbtdocker.DockerPlugin)
.settings(Scalaバージョンなどの共通セッティング) .settings( buildInfoPackage := “パッケージ名” buildOptions in docker := BuildOption(cache = false), imageNames in docker := Seq(s“${gcrRegion.value}/${moduleName.value}:${version.value}”), dockerfile in docker := { val appDir = stage.value val targetDir = “/opt/docker” new Dockerfile { from(java8イメージ) expose(9000) copy(appDir, targetDir) entryPoint(s”$targetDir/bin/${executableName.value}”) } } build := docker.value ) Dockerfileのようなものをここで 定義しています。 jarをコピってentrypointにしま す。
sbtでPlay2コンテナ作成 lazy val webapp = project.in(file(“webapp”)) .dependsOn(依存パッケージたち) .enablePlugin(PlayScala, JavaAppPackaging, sbtdocker.DockerPlugin)
.settings(Scalaバージョンなどの共通セッティング) .settings( buildInfoPackage := “パッケージ名” buildOptions in docker := BuildOption(cache = false), imageNames in docker := Seq(s“${gcrRegion.value}/${moduleName.value}:${version.value}”), dockerfile in docker := { val appDir = stage.value val targetDir = “/opt/docker” new Dockerfile { from(java8イメージ) expose(9000) copy(appDir, targetDir) entryPoint(s”$targetDir/bin/${executableName.value}”) } } build := docker.value ) このビルドファイルに対して sbt buildすればコンテナがローカル に作成されます。
deployment.yamlの設定 apiVersion: apps/v1 kind: Deployment metadata: … spec: selector: …
template: metadata: … spec: containers: - name: webapp-server image: 先ほど作ったイメージ ports: - containerPort: 9000 envFrom: - configMapRef: name: webapp-env-config // 後述 - secretRef name: cloudsql-db-credentials // 後述 - name: webapp-client image: JSが入ったnginxコンテナ ports: - containerPort: 80 ... - name: b.gcr.io/cloudsql-docker/gce-proxy:x.xx ...
service.yamlの設定 apiVersion: apps/v1 kind: Service metadata: ... spec: type: NordPort
ports: - port: 80 selector: ... deployment / serviceのyamlをいつも 通りkubectl applyすれば完了!
Javaオプションなどの環境変数の指定は ConfigMapに切り出しています。 (deployment.yamlがごちゃつくので) deployment.yamlでConfigMapをenvFromす ることで設定。 コンフィグファイルパスもここで指定。 Play2の環境変数指定 apiVersion: v1 kind:
ConfigMap metadata: name: webapp-env-config data: JAVA_OPTS: >- -server -Xms… -Xmx… -XX:MetaspaceSize=... -Dconfig.resource=application.conf -Dlogger.resource=logback.xml ...
DBのパスワードなど、一部コンフィグに直 接書きたくなかったり、環境変数から取得し たい場合がある。 そういうときは、ConfigMap / Secretで設定 された環境変数を設定ファイル内に読み込 むことができます。 Play2のコンフィグレーション //
application.conf db { default.username=${?DB_USER} default.password=${?DB_PASSWORD} }
Play2のロギング // logback.xml <configuration> <appender name=”STDOUT” class=”ch.qos.core.ConsoleAppender”> <target>System.out</target> -- filter略
-- <encoder class=”ch.qos.logback.core.encoder.LayoutWrappingEncoder”> <layout class="ch.qos.logback.contrib.json.classic.JsonLayout"> <jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter"> </jsonFormatter> <includeContextName>false</includeContextName> <appendLineSeparator>true</appendLineSeparator> </layout> <charset>UTF-8</charset> </encoder> </appender>
Play2のロギング // logback.xml <configuration> <appender name=”STDOUT” class=”ch.qos.core.ConsoleAppender”> <target>System.out</target> -- filter略
-- <encoder class=”ch.qos.logback.core.encoder.LayoutWrappingEncoder”> <layout class="ch.qos.logback.contrib.json.classic.JsonLayout"> <jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter"> </jsonFormatter> <includeContextName>false</includeContextName> <appendLineSeparator>true</appendLineSeparator> </layout> <charset>UTF-8</charset> </encoder> </appender> GKEでは、標準出力、エラー出力 に垂れ流しておけば Stackdriverに 流してくれます。
Play2のロギング // logback.xml <configuration> <appender name=”STDOUT” class=”ch.qos.core.ConsoleAppender”> <target>System.out</target> -- filter略
-- <encoder class=”ch.qos.logback.core.encoder.LayoutWrappingEncoder”> <layout class="ch.qos.logback.contrib.json.classic.JsonLayout"> <jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter"> </jsonFormatter> <includeContextName>false</includeContextName> <appendLineSeparator>true</appendLineSeparator> </layout> <charset>UTF-8</charset> </encoder> </appender> 構造化されているほうが Stackdriverで扱いやすいので、 JSONでログ出力します。
Play2のロギング // 前ページから続き <appender name=”STDERR” class=”ch.qos.core.ConsoleAppender”> <target>System.err</target> -- STDOUTとほぼ同じなので省略 --
</appender> <root> <appender-ref ref="STDOUT" /> <appender-ref ref="STDERR" /> </root> </configuration> 標準エラー出力を捕まえる設定も 同じようにあります。
JVMオプションとリソースリミットの整合性 • k8sにはコンテナごとのCPU/Memoryリソースリミットを設定できる機能がある • XmxやMetaspaceSizeを考慮した値にしておかないと、OOMで落ちてしまうので注 意。
まとめ • Play2 + Kubernetesは簡単! • sbtでビルドからコンテナ作成まで完結できる • VMを直接意識しないアプリケーション管理&GAEやFaaSほど環境を制限されない ので、Kubernetesはちょうど良い
• (GKEの場合)ロギングは標準に垂れ流すだけでStackdriver行きになるのでロー テーションとかディスクの枯渇とかの悩みがなくなる ◦ もちろん、Stackdriver Loggingのお金がかかります • 調べきれていないところ ◦ JMX周りの話
We are Hiring的な宣伝 ブレインパッドでは、 業界シェアNo.1の自社サービスを開発する、 クラウドインフラからフロントエンドまでフルスタックしたい、 Java(Scala or Kotlin)/Python/Goエンジニアを 絶賛大募集中です!