オイシックス_ら_大地におけるマイクロサービス高速開発に向けた取り組み.pdf

0d1076d3a26279d1a2fbc2d02d140210?s=47 川上徹
February 21, 2019

 オイシックス_ら_大地におけるマイクロサービス高速開発に向けた取り組み.pdf

0d1076d3a26279d1a2fbc2d02d140210?s=128

川上徹

February 21, 2019
Tweet

Transcript

  1. 2.

    1. 自己紹介 & 会社紹介 2. ECサイトのマイクロサービス化を行う背景 3. システム・アーキテクチャ概観 4. 開発環境構成

    5. 開発高速化へ向けた取り組み事例 6. Azure活用事例 7. エンジニア募集中! アジェンダ
  2. 5.
  3. 11.
  4. 13.

    国内某 Cloud Data Center On-Premise ECサイトのマイクロサービス化を行う背景 Oracle RAC • 全てを司る神Oracle

    通称:Core DB • Monolithic Application • Stateful Application Server • Session Sticky ・ ・ Not Scalable & Low Testability
  5. 15.
  6. 18.

    Azure API Management Azureが提供するフルマネージドのAPI ゲートウェイサービス • API呼び出しのバックエンドへのルーティング • JWT検証/証明書検証などの資格情報の検証 •

    流量制御 • リクエスト/レスポンスの変換 • 分析データの取得 参考:Azure API Management の概要と主な概念 https://docs.microsoft.com/ja-jp/azure/api-management/api-management-key-concepts
  7. 19.

    Azure Kubernetes Service ▪Azure Kubernetes Service Azure が提供するフルマネージドの Kubernetesコンテナーオーケストレーションサービス ▪Kubernetes

    コンテナ化したアプリケーションのデプロイ/スケーリング および管理を行うためのオープンソースの コンテナオーケストレーションシステム 参考:Azure Kubernetes Service の概要 https://docs.microsoft.com/ja-jp/azure/aks/intro-kubernetes
  8. 20.

    Spring Boot デファクトになりつつあるJavaフレームワーク Spring Bootを使用すると、スタンドアロンで実稼動グレードのSpringベー スのアプリケーションを簡単に実行できます (Google翻訳) • IoCコンテナ(DIコンテナ) •

    AOP を中心に高機能なJavaフレームワークである Spring Frameworkの機能を効率的に利用できるようにしたもの 参考:Spring Boot https://spring.io/projects/spring-boot
  9. 21.
  10. 23.
  11. 30.

    Spring BootでRedisを使う場合 public class ContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public

    void initialize(ConfigurableApplicationContext applicationContext) { GenericContainer redisContainer = new GenericContainer("redis:5.0.2").withExposedPorts(6379); redisContainer.start(); String containerIpAddress = redisContainer.getContainerIpAddress(); Integer mappedPort = redisContainer.getMappedPort(6379); TestPropertyValues values = TestPropertyValues.of("spring.redis.host=" + containerIpAddress, "spring.redis.port=" + mappedPort); values.applyTo(applicationContext); } } ApplicationContextInitializerの実装 @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration(initializers = ContextInitializer.class) public class SampleControllerTest { // … } テストクラスでの利用
  12. 31.

    Mockの活用 Dockerイメージでリソースを用意できない場合はMock化 • Storage キュー/Service Bus キュー • Blob Storage

    • 他サービスの呼び出し Spring BootではIoCコンテナ内の特定のインスタンスを Mock化することも容易 Mock化を考慮したクラス設計を @MockBean private AzureGetQueueService azureGetQueueService;
  13. 36.

    Swagger API定義の定番 Swagger(OpenAPI) API仕様を管理するOSSフレームワーク Swagger Specと呼ばれるYAML/JSONでREST APIの仕様を記述できる • Swagger Specを記述するためのSwagger

    Editor • プログラムコードを生成するSwagger Codegen • HTMLベースのAPI仕様書としてSwagger UI などのオープンソースのツール群として普及している 参考:swagger.io https://swagger.io/
  14. 39.

    Swagger UI CircleCIでのテスト時にSwagger UIを生成 .circleci/config.yml ビルドのArtifactsとしてSwagger UIを保存 GithubのPull Requestに紐付いて参照可能 -

    run: name: SwaggerUI command: ./gradlew :server-project:generateSwaggerUI - store_artifacts: path: ./server-project/build/swagger-ui-v1-server-project destination: swagger-ui-v1-server-project
  15. 40.

    Swaggerを使った開発プロセス Write Swagger Spec Generate Swagger Code (Spring MVC Controller

    Interface) (RestTemplate Client) (And More) Write Business Logic Generate Swagger UI Code Review Publish Client Libraly Swagger UI
  16. 44.

    Spring Boot Auto-configuration Spring Bootの主要機能「Auto-configuration」 Starterへの依存関係を追加するだけで諸々設定が行われる https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-starters • spring-boot-starter-web •

    spring-boot-starter-data-jdbc • spring-boot-starter-data-jpa • spring-boot-starter-security • spring-boot-starter-data-redis Starterは作れる! https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
  17. 45.

    Starterは作れる! @Configuration @ConditionalOnClass({AdjustDateGetter.class, AdjustDateFilter.class}) public class AdjustDateWebConfiguration { @Bean @ConditionalOnProperty(prefix

    = "oisix.common.web", value = "adjust-date", havingValue = "true", matchIfMissing = false) public FilterRegistrationBean businessDatetimeFilter() { FilterRegistrationBean bean = new FilterRegistrationBean(new AdjustDateFilter()); bean.addUrlPatterns("/*"); bean.setOrder(Integer.MAX_VALUE); return bean; } } Configuration Class org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ jp.co.oisixradaichi.oisixbootautoconfigure.web.AdjustDateWebConfiguration META-INF/spring.factories
  18. 48.

    CI/CD flow Application Development Test & Code Review Build &

    Push Image Create k8s Manifest Code Review Apply Manifest Different Repository Image Tag with Commit Hash
  19. 49.

    Spring Profile & Config Map Application Development Test & Code

    Review Build & Push Image Create k8s Manifest Code Review Apply Manifest Different Repository Image Tag with Commit Hash
  20. 50.

    Spring Profile & Config Map ビルドしたコンテナイメージはどの環境でも動く必要がある • Spring Profile 環境変数やVMオプションなどでプロパティ等を切り替える仕組み

    • 環境変数の値を参照可能 プロダクトコードの環境差分値は環境変数で吸収 テスト時の設定等をSpring Profileで解決 application.yml application-production.yml application-staging.yml application-development.yml spring: redis: host: ${REDIS_HOST} port: ${REDIS_PORT} password: ${REDIS_PASSWORD}
  21. 51.

    Spring Profile & Config Map • Config Map kubernetesで設定値を扱うためのリソース apiVersion:

    v1 kind: ConfigMap metadata: name: sample-service-config namespace: ns1 data: SPRING_PROFILES_ACTIVE: "production" apiVersion: apps/v1 kind: Deployment metadata: name: sample-service namespace: ns1 spec: template: spec: containers: - name: sample-service env: - name: SPRING_PROFILES_ACTIVE valueFrom: configMapKeyRef: name: sample-service-config key: SPRING_PROFILES_ACTIVE
  22. 52.

    kustomize Application Development Test & Code Review Build & Push

    Image Create k8s Manifest Code Review Apply Manifest Different Repository Image Tag with Commit Hash
  23. 53.

    kustomize 環境への反映はkubectl applyで行うが・・・ 各環境用のkubernetes manifestをフルセットで管理するのは面倒 kustomizeを使って基本設定 + 環境差分値に分割して管理 ├ base

    │ ├ kustomization.yaml │ ├ config.yaml │ ├ deployment.yaml │ ├ secret.yaml │ └ service.yaml ├ production-ns1 │ ├ kustomization.yaml │ ├ config.yaml │ ├ deployment.yaml │ ├ secret.yaml │ └ service.yaml # omit
  24. 54.

    kustomize base/kustomization.yaml production-ns1/kustomization.yaml bases: - ../base patches: - config.yaml -

    secret.yaml - deployment.yaml - service.yaml resources: - config.yaml - secret.yaml - deployment.yaml - service.yaml
  25. 55.

    kustomize base/config.yaml production-ns1/config.yaml kustomize build production apiVersion: v1 kind: ConfigMap

    metadata: name: sample-service-config namespace: ns1 data: SPRING_PROFILES_ACTIVE: "production" apiVersion: v1 kind: ConfigMap metadata: name: sample-service-config namespace: default data: SPRING_PROFILES_ACTIVE: "default" apiVersion: v1 kind: ConfigMap metadata: name: sample-service-config namespace: ns1 data: SPRING_PROFILES_ACTIVE: "production"
  26. 57.

    configMapGenerator production-ns1/kustomization.yaml base/deployment.yaml namespace: ns1 bases: - ../base patches: -

    deployment.yaml - service.yaml configMapGenerator: - name: sample-service-config literals: - SPRING_PROFILES_ACTIVE=production env: - name: SPRING_PROFILES_ACTIVE valueFrom: configMapKeyRef: name: sample-service-config key: SPRING_PROFILES_ACTIVE
  27. 58.

    kustomize kustomize build production ハッシュ値付きのconfigmapが生成される applyするとpod再起動がかかる! apiVersion: v1 kind: ConfigMap

    metadata: name: sample-service-config-tb9f7t5gh8 namespace: ns1 data: SPRING_PROFILES_ACTIVE: "production" --- apiVersion: v1 kind: Deployment # 省略 env: - name: SPRING_PROFILES_ACTIVE valueFrom: configMapKeyRef: name: sample-service-config-tb9f7t5gh8 key: SPRING_PROFILES_ACTIVE
  28. 59.

    kustomize & kubectl on CircleCI CircleCIではビルド実行環境にDockerイメージを指定できる azule-cliのDockerイメージが配布されている https://hub.docker.com/r/microsoft/azure-cli/ kustomize &

    kubectlできるDockerイメージを作ろう! コンテナ上でサービスプリンシパル認証ログインすればOK FROM microsoft/azure-cli:latest RUN az aks install-cli && \ curl -sSL -o /usr/bin/kustomize $(curl -s https://api.github.com/repos/kubernetes-sigs/kustomize/releases/latest | \ jq -r '.assets[] | select(.name | test("linux_amd64")) | .browser_download_url') && \ chmod u+x /usr/bin/kustomize
  29. 60.

    kustomize & kubectl on CircleCI CircleCIからのデプロイ対象判定 ▪前提 • 本番/ステージング/開発で別のAKSクラスタを構築 •

    ネームスペースでサイトを分離(Oisix以外のサイト/ブランドも有り) • リソースグループはクラスタと同名 ▪デプロイ対象判定の仕組み Githubのbranch名からデプロイ対象クラスタを判定 • production-ns1 -> productionクラスタのns1ネームスペース • develop-ns2 -> developクラスタのns2ネームスペース CircleCIの環境変数${CIRCLE_BRANCH}からクラスタ&ネームスペースを取得
  30. 61.

    オペレーションイメージ master feature development-ns1 production-ns1 development-ns2 production-ns2 kustomize build →

    kubectl apply kustomize build HOLD kubectl apply ns1 ns1 ns2 ns2 development production PR PR
  31. 65.

    GradleからAzure ArtifactsにMaven Publish Maven Publish Pluginを使ってPublish build.gradle CircleCIで指定ブランチ時のみpublishMavenJavaPublicationToMavenRepositoryタスクを 実行させればOK apply

    plugin: 'maven-publish' publishing { publications { mavenJava(MavenPublication) { from components.java } } repositories { maven { url 'https://pkgs.dev.azure.com/xxxxxxxx/_packaging/xxxxxxxx/maven/v1' credentials { username "AZURE_ARTIFACTS" password ${AUTH_TOKEN} } } } }
  32. 69.

    Lazybonesによるプロジェクトテンプレート アーカイブの展開 & post-install scriptによるテンプレーティング Groovyによるスクリプトで柔軟な処理が記述可能 lazybones.groovy テンプレートエンジンによる置換処理/必要に応じてファイルのリネーム等を行う 参考:LINE Engineering

    https://engineering.linecorp.com/ja/blog/lazybones-project-generation-tool-for-micro-service/ @Grab(group="uk.co.cacoethes", module="groovy-handlebars-engine", version="0.2") import uk.co.cacoethes.handlebars.HandlebarsTemplateEngine registerDefaultEngine new groovy.text.SimpleTemplateEngine() String serviceName = ask("Input value for Service Name with kebab-case [default: blank-service]: ", "blank-service", "serviceName") def props = [:] props.serviceName = serviceName processTemplates "**/*.yaml", props processTemplates "**/*.gradle", props …
  33. 74.

    まとめ 開発を高速化するためには・・・ • ツール系OSSの積極利用 ◦ IDE/ビルドツール Plugin ◦ テスト系ライブラリ •

    マネージド・サービスの活用 ◦ CIツール ◦ Microsoft Azure!! • 開発者の負担を減らす仕組みづくり ◦ Starter ◦ プロジェクトテンプレート 開発プロセスにおけるボトルネックはどこか? それを改善できるツール/サービスを探そう!
  34. 75.
  35. 77.

    JWT検証による認可制御 既存のECサイトにてJWT(Json Web Token)を払い出してAPIで検証 • API Managementのvalidate-jwtポリシーの利用を検討 ◦ 署名アルゴリズムにRS256を使用する場合、キーを Open

    ID 構成エンドポイントを介して指定する必要がある (≒ OpenID Connectのお作法に従う) ▪ APIの外部公開をしたいわけではない ▪ 大きなコストをかけられない ◦ ECサイトがStatefulすぎる ▪ scopeだけではAPI実行可否が判定できない JWT検証サービスを独自実装!
  36. 78.

    APIの認証認可 Azure API Management Azure Kubernetes Service Inbound processing send-request

    Policy Backend JWT Validation & User State Check Sync User State
  37. 80.