新卒1年目のSREがコンテナをデプロイできるようになるまでの道のり [JAWS DAYS 2019]

Bee9ae4bc9ccb3ca6b01818eb7ad0856?s=47 Daichi Harada
February 23, 2019

新卒1年目のSREがコンテナをデプロイできるようになるまでの道のり [JAWS DAYS 2019]

気づいたらコンテナ環境を運用することになっていた新人SREの原田くんが、Dockerでコンテナイメージをビルドするところから始まり、AWS上で実際にコンテナを動かせるようになるまでの道のりを紹介します。そもそもなぜコンテナなのか?動かしたあとのCICDをどうするかなども取り上げます。またEKSやKubernetesの概念についても合わせて解説します。

補足や当日の様子など書いた登壇レポート記事はこちら ↓
https://medium.com/eureka-engineering/deploy-docker-kubernetes-newgrad-sre-journey-1fb3f017eed7

Bee9ae4bc9ccb3ca6b01818eb7ad0856?s=128

Daichi Harada

February 23, 2019
Tweet

Transcript

  1. Daichi Harada & Jun Sakata JAWS DAYS 2019 2019. 02

    . 23 新卒1年目のSREが コンテナをデプロイできるよう になるまでの道のり
  2. はじめに

  3. Docker やろうぜ お、おす

  4. 急にどうしたんだろう

  5. すべてはここから始まった

  6. Daichi Haradaのクジラ漁

  7. Daichi Haradaのクジラ漁

  8. Daichi Haradaのコンテナとの戦い

  9. この話は実話をもとにした フィクションです

  10. 分量が多く怒涛の勢いで話が進みます が、スライドは後ほど公開予定なので、 合わせてご確認ください。

  11. 50分もあったので調子に乗りました

  12. About Speakers Daichi Harada, eureka Jun Sakata, ex-eureka

  13. DAICHI HARADA - @kai_ten_sushi / @dharada1 - SRE at eureka,

    Inc. - 北海道から遥々上京 - 気づいたら SRE に配属されてしまった! - インフラ経験ゼロからのスタート - Like - #CloudFront - #CostExplorer
  14. JUN SAKATA - @sakajunquality - 別のクラウドのエキスパート - SRE at Ubie

    Inc. - Former SRE at eureka Inc. - Like - #CodeBuild - #Aurora
  15. Agenda - Part 1 - Docker - Kubernetes - Part

    2 - Container Services on AWS - ECR / ECS / EKS / Fargate - EKS を使ってみた - Part 3 - CI/CD
  16. Part 1 Docker and Kubernetes

  17. Docker

  18. Dockerってしってる? ローカルの開発で使ってる、 docker-composeとかいうやつですか? (しらんけど・・・) ggrks

  19. Docker

  20. Dockerとは - コンテナ型の仮想環境を作成、配 布、実行するためのプラットフォーム - ミドルウェアのインストールや各種環 境設定をコード化して管理し、 Docker イメージを作成 -

    Docker さえある環境なら、どこでも同 じイメージを動作させることができる
  21. Build Ship Run

  22. とりあえず触ってみよう なるほど、わからん!

  23. よくあるWebアプリケーションを考えてみよ う

  24. こんな感じのコードですね // main.go package main import ( "fmt" "net/http" )

    func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World") } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8888", nil) }
  25. 8888でhttpリッスンして // main.go package main import ( "fmt" "net/http" )

    func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World") } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8888", nil) }
  26. “Hello, World” と表示する // main.go package main import ( "fmt"

    "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World") } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8888", nil) }
  27. まずは普通に動かしてみよう Docker使わなくていいんですね

  28. (ふつうに go run してみる) $ go run main.go

  29. (ログぐらい出せばよかったな・・・) $ go run main.go

  30. (別のターミナルで curl と...) $ curl localhost:8888

  31. うごいた! $ curl localhost:8888 > Hello, World!

  32. じゃあこれを Docker によう ふむ

  33. ・・・

  34. Dockerfile が必要らしい

  35. // Dockerfile FROM golang:1.11 WORKDIR /go/src/app COPY . . CMD

    ["go", “run”, “main.go”] こんな感じですか?
  36. これでも動くんだけど、 Go って動かすときちゃんとビルドしてるよ ね? たしかに

  37. // Dockerfile FROM golang:1.11 WORKDIR /go/src/app COPY . . RUN

    go get -d -v ./... RUN go install -v ./... CMD ["app"] どや
  38. うごかしてみよう ほい

  39. イメージをビルドする $ docker image build -t my-app .

  40. ビルドしたのを動かす $ docker container run -p 8888:8888 my-app

  41. $ curl localhost:8888 > Hello, World! curl してみる

  42. マルチステージビルドを使うとよいよ // Dockerfile FROM golang:1.11-alpine WORKDIR /go/src/app COPY . .

    RUN go get -d -v ./... RUN go install -v ./... FROM alpine COPY --from=0 /go/src/app /usr/local/bin/app RUN apk --no-cache add ca-certificates CMD ["app"]
  43. イメージのサイズを比べてみよう $ docker images | grep my-app my-app latest 9ba39c3836a9

    38 minutes ago 801MB my-app-alpine latest 3880eef6c224 5 minutes ago 401MB my-app-multistage latest ce94afe10faf 1 second ago 11.6MB
  44. あとこのままだとrootユーザーで動いちゃ うので、ユーザーも指定したほうがベター たしかに

  45. (一旦まとめよう・・・)

  46. Dockerイメージとは・・・ - コンテナを作成するファイルシステムや設 定をまとめたもの - 親のイメージから層のように重なっていく https://nvisium.com/blog/2014/10/15/docker-cache-friend-or-foe.html

  47. Dockerfileとは・・・ - Docker イメージの構成内容を記したもの - 専用の DSL で記述する - FROM

    でベースイメージを指定し - RUN でビルドなどのコマンドを実行
  48. Alpineとは・・・ - 軽量な Linux ディストリビューション - image サイズを小さくできる - glibc

    が入っていないので注意
  49. マルチステージビルドとは・・・ - アプリケーションをビルドするコンテナ / 実行するコンテナ を分離する - 実行するコンテナにはビルドに使うパッケージは入ってなくて OK -

    Docker Image のサイズを小さくできる - Go や Java などビルドしたらバイナリや jar が出力されるものにはピッタリ
  50. Dockerレジストリとは・・・ - DockerHub に代表される、 Docker イメージを管理・共有するしくみ - ソースコードを GitHub などで管理するのに似てる

  51. Docker Hubとは・・・ - Docker 社が運営する Docker レジス トリ - FROM

    golang:1.11 や FROM alpine など書いて Pull される Image は Docker Hub にホストされている https://hub.docker.com/
  52. - official マークのものを選ぶと良い DockerHubでのイメージの探し方

  53. - クラウド - ECR ( AWS ) - GCR (

    Google ) - ACR ( Azure ) - ... - OSS - Harbor - .... DockerHub以外のレジストリ
  54. 今回はローカルで動かしただけだから 使ってないよ。それはまた今度。  そういえば、Dockerレジストリは使わない んですか?

  55. コマンド多くないですか? docker image <list|build|pull|push...> docker container <run...> のように何を操作するかを覚えると良いと 思う

  56. $ docker image --help Usage: docker image COMMAND Manage images

    Commands: build Build an image from a Dockerfile history Show the history of an image import Import the contents from a tarball to create a filesystem image inspect Display detailed information on one or more images load Load an image from a tar archive or STDIN ls List images prune Remove unused images pull Pull an image or a repository from a registry push Push an image or a repository to a registry ... テキトウに--helpすればいいのか
  57. なんとなくわかりました (多分) そういえば、Docker は VM とは何が違うん ですか? なんだとおもう?

  58. (質問に質問で答えられても )

  59. VM vs Container

  60. VM vs Container - VM - ホスト上でハードウェアが仮想化され、その上 でゲスト OS が動作

    - 必要とする以上のリソースを割り当ててしま い、オーバーヘッドが大きい - OS を立ち上げるため起動時間がかかる - Container - コンテナはホスト OS のカーネルを利用 - リソースのオーバーヘッドが小さい - 起動が速い
  61. ざっくりいうと、 「コンテナの方が軽い」 ってことですよね? だいたいそう

  62. Build Ship Run

  63. (テキトウな先輩だな・・・ )

  64. (そういえば、docker-compose.ymlって何者 なんだろう・・・)

  65. docker-compose - 複数のコンテナの立ち上げを yaml で記述 - ローカル開発環境で主に利用 - ミドルウェアのコンテナを docker-compose

    で立ち上げる - MySQL - Elasticsearch - DynamoDB Local - ローカルの go アプリケーションから各コン テナを利用 - いちいち brew install とかしなくていいの で開発者は楽 // docker-compose.yml services: mysql: image: mysql:5.7 environment: MYSQL_USER: datch_datch_go MYSQL_PASSWORD: fake_password ports: - "3306:3306" volumes: - .local/mysql5.7:/var/lib/mysql redis: image: redis:3.2-alpine ports: - "6379:6379" redis-cluster: image: "grokzen/redis-cluster" ports: - "7000-7007:7000-7007" elasticsearch: image: evalphobia/elasticsearch:2.4.0 ports: - "9200:9200"
  66. そうか、Docker のおかげで ローカルの開発でも、 MySQLやDynamoDBが使えてたのか!!

  67. 今はEC2のインスタンスがたくさんいるけ ど、これもコンテナにしたほうがいいんで すか? つぎにその話をしよう

  68. Why Docker in Production? - アプリケーション及び、その依存関係をイメージに固めることができる - 環境依存で動かないことがなくなる - イメージとして本番出す前にステージングで確認したりできる

    - ( The Twelve-Factor App https://12factor.net/ ) - VM を起動するより軽量なので、起動が速い
  69. Docker まとめ - Docker とは ? - コンテナ型の仮想化環境 - Docker

    Image - 構成がまとまったもの - コンテナを作成するファイルシステムや設定をまとめたもの - Dockerfile を書いて build & run - Docker Hub - Docker 社が運営するリポジトリ - 公式の Docker イメージは Docker Hub で探すとよい
  70. Docker 完全熟知 ( ̄^ ̄) ドヤッ !

  71. Kubernetes Google’s Borg

  72. 今日は Kubernetesを触ってみよう 最近よくきくあれですね (またしらんけど・・・)

  73. 少し難しいかもしれないので、 手を動かしながらやっていこう ほーい この前の Docker の続きから

  74. CNCF Phippy and Friends https://www.cncf.io/phippy/ を使って話を進めていく

  75. こんな絵本が・・・

  76. そもそものアプリケーションがあって・・・

  77. コンテナとしてイメージに固める

  78. 本題の Kubernetes

  79. Kubernetes

  80. What is Kubernetes https://speakerdeck.com/sakajunquality/starting-google-kubernetes-engine-2019

  81. つまり、コンテナを動かすのに必要な、 CPU / メモリ / ディスクを管理してくれるや つ、ってことなのかな??? あとはコンテナをどこに配置するかとか、 イメージのデプロイとか。

  82. 養殖漁業で考えると・・・

  83. None
  84. None
  85. Small Ikesu Large Ikesu Medium Ikesu

  86. ...ってことだ!多分

  87. どんな構造になってるんだろう

  88. k8s Components (Master Node & Worker Node) - Master Node

    - API Server - k8s cluster のゲートウェイ - etcd - 共有設定の保持とディスカバリに 使う KVS - controller - API Server を利用してクラスタの 状態を監視 & 操作する - Worker Node - docker - Pod を起動する - kubelet - マスターとの通信 - kube-proxy - プロキシ、ロードバランス https://x-team.com/blog/introduction-kubernetes-architecture/
  89. k8s Components (Master Node & Worker Node) - Master Node

    - API Server - k8s cluster のゲートウェイ - etcd - 共有設定の保持とディスカバリに 使う KVS - controller - API Server を利用してクラスタの 状態を監視 & 操作する - Worker Node - docker - Pod を起動する - kubelet - マスターとの通信 - kube-proxy - プロキシ、ロードバランス https://x-team.com/blog/introduction-kubernetes-architecture/ めっちゃムズカシイ
  90. 一旦内部構造は忘れよう

  91. とりあえず重要なことは コントロールプレーン(マスター)が、リソー スの割当などを管理していて、 データプレーン(ワーカー)に実際のコンテ ナが動いてるってことですね!

  92. ワーカーノードがいけす! Ikesu Node

  93. ワーカーに実際のコンテナがいる Ikesu Node

  94. 次に概念を見てみよう

  95. 再び CNCF Phippy and Friends https://www.cncf.io/phippy/

  96. Kubernetes は内部のリソースをラベルで管 理している e.g. - name: my-app - ver: v1

    そのコンテナをラベルで管理
  97. ラベルと同時に、名前空間でも管理してい る e.g. - production - web - datch-area Namespaces

  98. - コンテナの集合の単位 - 1 つ以上のコンテナを内包する e.g. - nginx - envoy

    - php-fpm - fluent-bit Pod
  99. ReplicaSet - 同じ仕様の Pod の複数集まった Set が ReplicaSet

  100. Service - Pod にアクセスするための経路

  101. - Service に外部からアクセスするための 仕組み - e.g. - GCE LB -

    ALB - annotation でクラウドスペシフィックな 設定を記載 Ingress
  102. - データの永続化する際に仕様 - EC2 に EBS をアタッチするノリ Volumes

  103. ワケワカラン

  104. 思ったより覚えること多い

  105. カエリタイ

  106. 例のアプリケーションを Kubernetes にデプロイしてみよう

  107. これね // main.go package main import ( "fmt" "net/http" )

    func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World") } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8888", nil) }
  108. $ docker image tag my-app gcr.io/sakajunquality-public/my-app:v1 $ docker image push

    gcr.io/sakajunquality-public/my-app:v1 まずはイメージをレジストリに上げる
  109. 今こういう状態っすね boku-no-macbook container my-app (bin) boku-no-cloud container my-app (bin)

  110. チュートリアル用に Kubernetes 作成 $ gcloud container clusters create my-cluster ...

    $ gcloud container clusters get-credentials my-cluster --zone asia-northeast1-c ...
  111. 空っぽの箱を作成 boku-no-cloud Kubernetes Cluster

  112. チュートリアル用にname空間作成 $ kubectl create namespace tutorial

  113. 空っぽの空間を作成 boku-no-cloud Kubernetes Cluster namespace

  114. // deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: app1 namespace:

    tutorial labels: app: app1 spec: replicas: 3 selector: matchLabels: app: app1 Pod/ReplicaSetを定義 // 続き template: metadata: labels: app: app1 spec: containers: - name: app1 Image: gcr.io/sakajunquality-public/my-app:v1 ports: - containerPort : 8888 protocol: TCP
  115. // deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: app1 namespace:

    tutorial labels: app: app1 spec: replicas: 3 selector: matchLabels: app: app1 apps/v1のDeploymentでまとめて定義 // 続き template: metadata: labels: app: app1 spec: containers: - name: app1 Image: gcr.io/sakajunquality-public/my-app:v1 ports: - containerPort : 8888 protocol: TCP
  116. // deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: app1 namespace:

    tutorial labels: app: app1 spec: replicas: 3 selector: matchLabels: app: app1 push下イメージを指定 // 続き template: metadata: labels: app: app1 spec: containers: - name: app1 image: gcr.io/sakajunquality-public/my-app:v1 ports: - containerPort : 8888 protocol: TCP
  117. // deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: app1 namespace:

    tutorial labels: app: app1 spec: replicas: 3 selector: matchLabels: app: app1 replicaの数も指定 // 続き template: metadata: labels: app: app1 spec: containers: - name: app1 Image: gcr.io/sakajunquality-public/my-app:v1 ports: - containerPort : 8888 protocol: TCP
  118. $ kubectl apply -f deployment.yaml デプロイしてみる

  119. 今こういう状態っすね boku-no-cloud Kubernetes Cluster namespace Pods container my-app (bin)

  120. そう! これを外部からアクセスできるようにする

  121. 次にserviceの作成 // service.yaml apiVersion: v1 kind: Service metadata: name: app1-service

    namespace: tutorial annotations: cloud.google.com/neg : '{"ingress": true}' spec: selector: app: app1 ports: - protocol: TCP port: 8081 targetPort: 8888
  122. selectorでdeploymentのラベルを指定 // service.yaml apiVersion: v1 kind: Service metadata: name: app1-service

    namespace: tutorial annotations: cloud.google.com/neg : '{"ingress": true}' spec: selector: app: app1 ports: - protocol: TCP port: 8081 targetPort: 8888
  123. $ kubectl apply -f service.yaml サービスの作成

  124. 多分こんなかんじ boku-no-cloud Kubernetes Cluster namespace Pods container my-app (bin) 8081:8888

    service
  125. // ingress.yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: my-lb namespace:

    tutorial spec: rules: - http: paths: - path: / backend: serviceName: app1-service servicePort: 8081 ingressでロードバランサーを定義
  126. $ kubectl apply -f ingress.yaml ingressを作成

  127. $ kubectl -n tutorial get ingress NAME HOSTS ADDRESS PORTS

    AGE my-app * aa.bb.xxx.yyy 80 3m ロードバランサーのIPを確認
  128. 多分こんなかんじ boku-no-cloud Kubernetes Cluster namespace Pods container my-app (bin) 8081:8888

    service 80/443:8081 ingress
  129. $ curl aa.bb.xxx.yyy > Hello, World! curl してみる

  130. おー いんたーねっつに公開された!!!

  131. Docker熟知した気持ちになってたけど、ど こで動かすかも考える必要があったの か!

  132. なるほど 環境変数はどうやって扱うんですか? configMapやsecretというリソースがあるよ。 今回の場合、my-appがどのポートでリッス ンするか環境変数で指定できても良かっ たかもね

  133. container == pod?

  134. NO さっきの pod Pod container More practical pod Pod container

    my-app my-app container nginx container logger
  135. 理解!

  136. ところで何で急に教育熱心になったんで すか? 恩田さん(上司)に怒られました?

  137. 実は会社やめるんや・・・ えええええええええ (テックリードの座はいただいた)

  138. (冷静に、こんなに技術先行なのは、 引き継ぎってことか・・・)

  139. 困ったらこの本に答えがある https://www.amazon.co.jp/dp/B07HFS7TDT/ https://www.amazon.co.jp/dp/B0721JNVGT/

  140. さらばじゃ

  141. ・・・

  142. とりあえず本ポチるか・・・

  143. ・・・

  144. Part 2 Containers on AWS

  145. いやな先輩消えたし これから、やってくぞい!

  146. う〜ん、パッと見た感じ AWS サービス多くてわからない・・・

  147. とりあえず、 調べてみよう

  148. AWS Container Services

  149. AWS Container Services - Registry - ECR - Orchestration -

    ECS - EKS - Compute - Fargate - EC2 - Auto Scaling Group - Code* - CodeDeploy - CodeBuild - CodePipeline https://aws.amazon.com/jp/containers/services/
  150. ざっくりAWSのコンテナサービス といっても、 何するやつか分類できて その中でも選択肢がある。 って感じなんだな

  151. ECR - ECR = Elastic Container Registry - IAM Policy

    / Role で ECR リソースの利用を細かく制御可能
  152. ECR == AWSのDocker Registry

  153. ECS / EKS - ECS ( Elastic Container Service )

    - 他の AWS サービスとシームレスに連携 - Fargate を使えばサーバの管理が不要 - 起動タイプで EC2 or Fargate を選べる - EKS ( Elastic Container Service for Kubernetes ) - k8s のマネージドサービス - Master のみマネージド - Worker Node は EC2 を立てて運用する - Fargate は未対応 - (AWS のサービスとしては ) ECS より後発
  154. ECSとEKS、 どっちを使うか 悩ましい!

  155. Fargateに 対応してるとかしてないとか う〜ん、Fargateって、なんだろ?

  156. Fargate - Fargate とは - ECS で使えるフルマネージドなコンピューティングエンジン - 課金体系 -

    実際に Task を起動していた vCPU / メモリに対する時間単位の課金 - 最近単価が下がったが、 EC2 との価格比較をすると少し割高ではある
  157. Fargateのメリット - メリット - 管理コストが減る - コンテナのオートスケールに合わせて EC2 もオートスケールさせる手間が ない

    - Worker Node がどの AZ に配置されてるか意識する必要がない - 余剰リソースがなくなる - EC2 を使うときはコンテナ全体が使っているより余剰のリソースを確保する 必要がある
  158. 管理コストも考えると Fargateよさそう!

  159. EKS / ECS / Fargate の関係を整理すると ...

  160. EKSとECSのControl Plane と Data Plane - Control Plane - コンテナを管理する場所

    - どの Node に配置するかなど制御する - AWS のサービスでいうと、 ECS / EKS - Data Plane - コンテナが実行される場所 - Control Plane に各 Node やコンテナの状態をフィードバックする - AWS のサービスでいうと、 Fargate / FC2
  161. Fargate、めっちゃいいやつだな

  162. CodeBuildとかCodeDeployとかは コンテナに対応してるのかな?

  163. Code* (CodeBuild / CodeDeploy / CodePipeline) - CodeBuild - buildspec.yaml

    に ecr push を書いて ECR への push を行う - CodeDeploy - ECS で Blue/Green Deployment のサポート - CodePipeline - ECR 上のイメージをデータソースとして使える - ビルド環境として使うイメージを ECR で管理できるようになった - これまでは CodeBuild で Docker イメージを管理していた - Deploy Target に ECS も対応
  164. コンテナのビルド/デプロイにもちゃんと使 えるんだな

  165. 改めてEKSを さわってみる

  166. Kubernetes 、やりたい

  167. というか前任のあいつが Kubernetesで作ったので、 やらざるを得ない!!

  168. Why EKS ? - Why not ECS ? - 前任者が既に

    GKE で一部サービスを稼働させていた - yaml 使いまわしたい - EKS でも途中まで組んだ形跡があった - Why not GKE ? - 既存のアプリケーションが AWS で稼働しておりデータが AWS にある - また、 AWS でしか使えないデータベースを使いたい - e.g. DynamoDB Aurora
  169. クラスターを立てる - 公式ドキュメント … getting started を読んでみた - https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started.html

  170. VPC / Subnet / Security Group / IAM 設定 ...

    わかるけど、クラスターが立つまでに やることが多いな。。。。
  171. シャッと 簡単にできる方法 ないかな〜

  172. Create k8s cluster by eksctl - Go 製の cli アプリ

    - eksctl create cluster - CloudFormation が裏側で動いてくれる - 一通りよしなにクラスターを作成してくれる - VPC / Subnet - IAM - EKS Cluster - Worker Node (EC2 + ASG) - 検証用途なら最速 - デフォルトだと新規の VPC が作られる - ( 既存の VPC を使うオプションもある ) https://github.com/weaveworks/eksctl
  173. ぽちっとな $ eksctl create cluster

  174. でかいインスタンスたててもたーーーー ※デフォルトだとオレゴンにて m5.large が 2 台立つ

  175. けしけし

  176. $ eksctl create cluster \ --name test-cluster \ --region ap-northeast-1

    \ --nodes 2 \ --nodes-min 1 \ --nodes-max 2 \ --node-type t2.small スペックをしっかり指定するの巻
  177. よし、クラスターができた

  178. Nodeも指定したとおり、 t2.smallが2台できてる $ kubectl get nodes NAME STATUS ROLES AGE

    VERSION ip-192-168-38-92.ap-northeast-1.compute.internal Ready <none> 1s v1.11.5 ip-192-168-74-18.ap-northeast-1.compute.internal Ready <none> 1s v1.11.5 $ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 1s
  179. 他には何が作られているんんだろう。。。 気になる。。。

  180. nodegroupとcluster、2つのCloudFormationス タックができてるみたいだ。

  181. Clusterの方は EKS Clusterと、 それが乗っかる VPC / Subnet / Route Table

    などなどのネット ワーク周りを作って いる。
  182. NodeGroupの方は AsgとLaunch Template を作ってるんだな。 あとは IAM Role / SG /

    Instance Profileとかの 権限周りか。
  183. なにが立てられたか、 ざっくりわかったぞい

  184. では、ECRにDockerイメージを Pushしてみよう

  185. Build > docker image build -t my-app:1.00 . まずはいつものように docker

    buildして、っと
  186. ECR Login > $(aws ecr get-login --no-include-email --region ap-northeast-1) Login

    Succeeded ECR への Login コマンドを 取得 & 実行.
  187. Tag > docker image tag my-app:1.00 \ xxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:1.00 docker tagコマンドで

    ECRの方にタグを切り
  188. Push > docker image push xxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:1.00 ECR へ Push する!

  189. ECRにDocker ImageをPushできたぞい

  190. Makefile化すると便利 NAME=my-app TAG=1.00 CONTAINER_PORT=8888 LOCAL_PORT=8888 AWS_ACCOUNT_NUMBER=1234567890 login: ## generate `docker

    login` command aws ecr get-login --no-include-email --region ap-northeast-1 build: ## docker build docker build -t $(NAME):$(TAG) . run: ## docker run docker run --rm -it -p $(LOCAL_PORT):$(CONTAINER_PORT) $(NAME):$(TAG) tag: ## tag docker tag $(NAME):$(TAG) $(AWS_ACCOUNT_NUMBER).dkr.ecr.ap-northeast-1.amazonaws.com/$(NAME ):$(TAG) push: ## push 事前にAWSコンソールでリポジトリを作っておき、そこへpushする docker push $(AWS_ACCOUNT_NUMBER).dkr.ecr.ap-northeast-1.amazonaws.com/$(NAME ):$(TAG) release: build tag push そういえば、 一連のコマンドは こんな感じで Makefileにしておくと 取り回しやすい
  191. よし、つぎは EKS へデプロイしたい!

  192. まずはdeployment.yamlを書く

  193. ほんで kubectl apply -f deployment.yaml っと $ kubectl apply -f

    deployment.yaml
  194. podが立っている。 $ kubectl get pods NAME READY STATUS RESTARTS AGE

    golang-sample-app-xxxxxxxxxd-dhgj2 1/1 Running 0 1s golang-sample-app-xxxxxxxxxd-q6pls 1/1 Running 0 1s golang-sample-app-xxxxxxxxxd-zlm25 1/1 Running 0 1s
  195. けどこれ、どうやってインターネットからア クセスするんだろう ??

  196. そうだ、Serviceを使うんだった

  197. えいや service.yaml

  198. kubectl apply -f service.yaml $ kubectl apply -f service.yaml

  199. TYPE: LoadBalancerのServiceができた! $ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP

    PORT(S) AGE golang-sample-app LoadBalancer 10.100.17.74 hoge.ap-northeast-1.elb.amazonaws.com 80:30498/TCP 3d kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 4d
  200. EXTERNAL-IP に ELBのDNS名が書かれているぞ $ kubectl get services NAME TYPE CLUSTER-IP

    EXTERNAL-IP PORT(S) AGE golang-sample-app LoadBalancer 10.100.17.74 hoge.ap-northeast-1.elb.amazonaws.com 80:30498/TCP 3d kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 4d
  201. コンソールで確認すると ELB (Classic) が作られている! $ kubectl get services NAME TYPE

    CLUSTER-IP EXTERNAL-IP PORT(S) AGE golang-sample-app LoadBalancer 10.100.17.74 hoge.ap-northeast-1.elb.amazonaws.com 80:30498/TCP 3d kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 4d
  202. いったんブラウザでみると

  203. (Classic LoadBalancerだけど) 動いてる〜!

  204. やったね

  205. でも、あれれ、、、

  206. Ingressってのが必要じゃなかったっけ? Serviceだけでいいの? Service LoadBalancerだとCLBができる IngressでALBができる 時代はALBなのだよ

  207. あと、 セキュリティグループ とか TLS証明書 とかを annotationで指定できるぞい

  208. なるほど〜!ありがとうございます!

  209. (うるさいなあ)

  210. ALBも試しておくか

  211. service.yaml はこんな感じで、 Type: NodePortに書き換える。

  212. apply $ kubectl apply -f manifest/service.yaml

  213. ingress.yaml の annotation で internet-facingなalbをつくる。

  214. これをapplyすると、 ingressができる。 $ kubectl apply -f manifest/ingress.yaml ingress.extensions/golang-sample-app created $

    kubectl get ing NAME HOSTS ADDRESS PORTS AGE golang-sample-app * hoge.ap-northeast-1.elb.amazonaws.com 80 2m
  215. おっ、ALBが Provisioning … になったぞ

  216. しばらく待って... ALBでも動いた!

  217. Ingressのannotationで色々かけば ALBに証明書とかもあてられる (はず...) - alb.ingress.kubernetes.io/certificate-arn - alb.ingress.kubernetes.io/ssl-policy - etc ...

    - https://github.com/kubernetes-sigs/aws-alb-ingre ss-controller/blob/master/docs/guide/ingress/ann otation.md
  218. ここまでをまとめると

  219. まとめ : eksctlでEKS Clusterたててみた - クラスターをたてる - 検証だけなら eksctl でパッと立てられる

    - CloudFormation でもろもろリソースが用意される - Deployment - Kubernetes なので GKE とおなじ - ALB でインターネットからアクセスさせる - Service:NodePort と Ingress でやる - annotation は AWS 固有の設定を書く
  220. 検証はできたので、ちゃんとやるか

  221. Cluster Management

  222. Terraformで、コード管理や!

  223. Create k8s cluster by Terraform - Production Ready in eureka

    - 既存の VPC 上でクラスタ構築したい - リソースは terraform で管理されてる - EKS もなるべく terraform で管理したい
  224. Terraform : VPC & Subnet - # VPC resource "aws_vpc"

    "vpc" { cidr_block = "10.xx.yy.zz/ww" instance_tenancy = "default" enable_dns_support = "true" enable_dns_hostnames = "true" } # Subnet ## Public Subnets resource "aws_subnet" "public_1a" { } resource "aws_subnet" "public_1c" { } ## Private Subnets resource "aws_subnet" "private_1a" { } resource "aws_subnet" "private_1c" { } resource "aws_subnet" "private_1b" { } resource "aws_subnet" "private_1d" { } VPC / Subnet は既存のやつ。
  225. Terraform : EKS Cluster resource "aws_eks_cluster" "quality" { name =

    "cluster-quality" role_arn = "${aws_iam_role.quality-cluster.arn}" vpc_config { security_group_ids = ["${aws_security_group.quality-cluster.id}"] subnet_ids = [ "${aws_subnet.private_1b.id}", "${aws_subnet.private_1d.id}", ] } } EKS Cluster は こんなかんじ だぜ ※ IAM Role / SG を別途書く必要あり
  226. 次にワーカーノードの追加

  227. Terraform : EC2 Auto Scaling Group data "aws_ami" "eks-worker" {

    filter { name = "name" values = ["eks-worker-*"] } most_recent = true owners = ["xxxxxxxxxxxx"] # Amazon Account ID } resource "aws_launch_configuration" "quality" { associate_public_ip_address = true iam_instance_profile = "${aws_iam_instance_profile.quality-node.name}" image_id = "${data.aws_ami.eks-worker.id}" instance_type = "t2.medium" name_prefix = "terraform-eks-quality" security_groups = ["${aws_security_group.quality-node.id}"] user_data_base64 = "${base64encode(local.quality-node-userdata)}" lifecycle { create_before_destroy = true } } resource "aws_autoscaling_group" "quality" { desired_capacity = 2 launch_configuration = "${aws_launch_configuration.quality.id}" max_size = 2 min_size = 1 name = "terraform-eks-quality" vpc_zone_identifier = [ "${aws_subnet.private_1b.id}", "${aws_subnet.private_1d.id}", ] tag { key = "Name" value = "terraform-eks-quality" propagate_at_launch = true } tag { key = "kubernetes.io/cluster/cluster-quality" value = "owned" propagate_at_launch = true } } ※ Instance Profile / SG などなど別途書く必要あり
  228. ちょっと大変。 できるけど、

  229. https://docs.aws.amazon.com/eks/latest/user guide/getting-started.html ノードをマスターに認識させたりする

  230. None
  231. Nodeを認識させるのにまたひと手間

  232. まとめ : Terraformでクラスターを立てる - 既存リソースに組み込むかたちで本番に入れたい - やや分量が増えるが、既存のインフラと同じく terraform でできる -

    それなりに手間はかかる ※Terraformで作ったALBなどをClusterに 認識させるには、タグとかで頑張る必要 があるので注意だよ
  233. ECS

  234. そういえば山本さん(別のSRE)が 最近ECSさわってたな どんな感じか、 聞いてみようっと

  235. None
  236. ふむ ふむ https://qiita.com/marnie_ms4/items/202deb8f587233a17cca

  237. ECS - K8S と似てるけどちょっとちがう概念たち - Cluster / Service / Task

    Definition / etc ... https://qiita.com/marnie_ms4/items/202deb8f587233a17cca
  238. ECSの良さ - AWS のサービスとの密な連携 - CodeDeploy で Blue/Green してくれる -

    Task ( ≒ k8s でいう Pod) ごとに異なる IAM Role を付与できる - Fargate を使えるのがでかい - EC2 の面倒を見なくてすむ - スケールするとき Service のスケールだけ考えれば良い - EC2 の場合 - Service のスケール時に EC2 もスケールさせるので手間かかる - 常にバッファ積むので余分にお金かかる
  239. Fargate いいなあ EKS でも使いたいなー なるほど!ECSは EKSとまた違ったよさがあるんだな

  240. Containers on AWS まとめ - ECR - プライベートなコンテナリポジトリ - EKS

    or ECS - どちらも Control Plane - k8s の生態系に乗りたいか、 AWS の他サービスとなめらかに連携したいか - Fargate - よい
  241. AWS 完全熟知 ( ̄^ ̄) ドヤッ!

  242. Part 3 CI/CD

  243. 熟知・・・ あれ・・・ デプロイまわりはどうしたらええんや

  244. 熟知できてない!! プロダクションに入れるには何かが足りな い!!!

  245. 一旦現状把握

  246. 既存のインフラ in eureka - 主力サービスは EC2 が多くコンテナでは動いていない

  247. 既存のインフラ: CodeBuild - Docker イメージではなく、ビルドの生成物を S3 にアップロード

  248. 開発者視点のOverview - ChatOps 経由でのデプロイ - @nana prepare {env} {region]-{service} -

    差分確認 - 前回 deploy との commit 差分 (GitHub) - 確認して deploy ボタンを押す - デプロイ完了 - Slack 通知
  249. SRE視点の既存のOverview - インターフェイスは ChatOps - Slackbot で CodeBuild がキック -

    ビルド完了後、 bot が CodeDeploy を API 経由で呼び出してデプロイ BotApp RTM API Calls
  250. Why not CodePipeline - 1つのリポジトリで複数のものが内包されており、 - master 等のブランチに単純にフックさせるのが難しい pairs-repo JP

    FE JP BE TW BE KR BE TW FE
  251. つぎに未来を考える

  252. どうしたらいいのか - できるだけ開発者のインターフェイスを変えない - SOX の遵守

  253. せっかくコンテナにするので - ステージングと本番では同じイメージが動く状態にしたい - イメージの脆弱性スキャン - 構成変更の手間を減らしたい

  254. イメージの検証 - ステージングでの検証後本番に出せるようになる

  255. 構成変更の手間 EC2 のゴールデンイメージを作成するのがそれなりに手間

  256. 構成変更の手間 EC2 のゴールデンイメージを作成するのがそれなりに手間 これがコンテナになると

  257. VMとコンテナでの構成管理の違い - Immutable なインフラという思想はそのまま - 構成管理 = Docker Image の変更という世界観になる

    - ミドルウェアの細かい変更など、全て Docker Image の変更で済む
  258. How to Deploy to Kubernetes

  259. 頼りたくないけど、あいつを頼ってみよう

  260. okok Kubernetes ってどうやって、デプロイのフ ロー作ればいいっすか?

  261. コンテナ一般 CI/CD

  262. Container CI/CD https://speakerdeck.com/sakajunquality/starting-google-kubernetes-engine-2019 コンテナ全般 テストは省略...

  263. Container CI/CD https://speakerdeck.com/sakajunquality/starting-google-kubernetes-engine-2019 コンテナ全般

  264. GitOps

  265. GitOps - Operations by Pull Request https://www.weave.works/blog/gitops-operations-by-pull-request

  266. GitOps アプリケーションのリポジトリと、マニフェストのリポジトリを分離 マニフェストリポジトリは常にクラスターの状態と整合性がとれている Application Config

  267. “Declarative” が、ポイントなのか! terraform もそうだよなー

  268. GitOps それぞれのリポジトリに対して、アプリケーションをビルドする CI と Kubernetes に apply する CI を設定する

  269. GitOps on AWS CodeBuild 2つ設定すれば簡単に作れそう 場合によっては CodePipeline も使えそう

  270. CodePipeline

  271. CodePipeline + Lambda https://aws.amazon.com/blogs/devops/continuous-deployment-to-kubernetes-using-aws- codepipeline-aws-codecommit-aws-codebuild-amazon-ecr-and-aws-lambda/

  272. GitOps on AWS? CodePipeline?

  273. CodePipelineでもできそうだし GitOpsも試すのも良さそう

  274. もう少しいろいろ検討してみよう・・・

  275. (今回ここを実装するのは間に合わず)

  276. CI/CD まとめ - Kubernetes では GitOps という考えがある - CodePipelines を使うとシンプルなパイプラインも構築できそう

    - あたらしいワークフローを作りつつも、 - 既存の開発者のインターフェイスはできるだけ変えずにやりたい
  277. What’s Next?

  278. Monitoring - 監視は大事だよね - Kubernetes そのものの監視 - ノードの監視 - コンテナの監視

    - タグとラベルつかう - リソース使用量 - ヘルスチェック - etc ...
  279. Logging - ログ、必要だよね - 既存のログと同じように収集して同じように解析したい

  280. Service Mesh? マイクロサービス間の可視化

  281. Service Mesh? マイクロサービス間の可視化

  282. 気になるRoadmaps

  283. EKS IAM Roles for Pods https://github.com/aws/containers-roadmap/issues/23

  284. EKS IAM Roles for Pods https://github.com/aws/containers-roadmap/issues/23 ECSにはあるやつ GKEでも恩恵うけれる?

  285. Fargate for EKS https://github.com/aws/containers-roadmap/issues/32

  286. Fargate for EKS https://github.com/aws/containers-roadmap/issues/32 Fargate for EKS !!!

  287. Managed worker nodes https://github.com/aws/containers-roadmap/issues/139

  288. Managed worker nodes https://github.com/aws/containers-roadmap/issues/139 Is this different from “EKS Fargate”?

  289. EKS Private Link Support https://github.com/aws/containers-roadmap/issues/22

  290. EKS Private Link Support https://github.com/aws/containers-roadmap/issues/22 他のサービスでは進んでるやつ!

  291. Takeaways

  292. Takeaways - Docker & k8s の基礎 - k8s は覚えること多めだけど -

    焦らず 1 個ずつ確実に理解する - AWS のコンテナ関連サービス - ECR - EKS / ECS - Fargate - CI/CD - GitOps - CodePipeline - What’s Next - 監視 / ロギング などまだまだ考えることある - 今後のロードマップ
  293. ご清聴ありがとうございました!

  294. Appendix

  295. Appendix - https://docs.docker.com/ - https://kubernetes.io/docs/home/ - https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started.html - https://github.com/weaveworks/eksctl -

    https://www.weave.works/blog/gitops-operations-by-pull-request - https://www.slideshare.net/AmazonWebServicesJapan/20180214-aws-black- belt-online-seminar-amazon-container-services