Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
実践Play2+Kubernetes
Search
Tatsuya Atsumi
April 03, 2018
Technology
230
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
330
Other Decks in Technology
See All in Technology
現場回帰したデータエンジニアが考える AI 時代のキャリア開発 / Career Development in the Age of AI Perspectives from a Hands-on Data Engineer
medley
0
120
モノリス Rails でも日中に rails db:migrate を走らせたい! / Daytime rails db:migrate on Monolithic Rails!
euglena1215
4
640
[ChatGPT Work LT]事務作業が苦手な人のための バックオフィスの「半」自動化
chimaki_iot
0
330
Kiro Crew入門 - 常駐エージェントの仕組みと使いどころ / Intro to Kiro Crew
k_adachi_01
1
480
ボトムアップ文化が強い組織で セキュリティをどう根付かせていくかの現在進行形の話 / Making Security Stick in a Bottom-Up Organization
yamaguchitk333
0
240
自宅NWにISR4331を導入してみた話
okaits
0
110
LLM・AIエージェントシステムベストプラクティス
shibuiwilliam
6
1.5k
Adding Right-to-Left support to your web application with CSS logical properties — Lessons from Redmine
vividtone
0
130
Apache Icebergインフラストラクチャ:ストレージ・カタログ・エンジンの選択肢とClouderaプラットフォームでの実装
tsugiyama
0
120
ラジオの科学
frievea
0
350
エンドユーザー視点で見る SansanのMeraki活用と内製自動化
sansantech
PRO
0
120
도구에서 동료까지: 10년차 AI 스타트업의 AI 적응기
inureyes
PRO
0
220
Featured
See All Featured
BBQ
matthewcrist
89
10k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.4k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
170
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4.2k
Building AI with AI
inesmontani
PRO
1
1.1k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.6k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
490
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
280
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
800
Information Architects: The Missing Link in Design Systems
soysaucechin
0
1.1k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
290
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
420
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エンジニアを 絶賛大募集中です!