Slide 1

Slide 1 text

コンテナ時代に インフラエンジニアは何をするの か グリー株式会社 開発本部 駒﨑 拓斗

Slide 2

Slide 2 text

2 ●グリー入社前 ○ 組み込みソフト企業 ○ 携帯電話向けプラットフォームの開発 ●2012年より グリーインフラ部門 ○ 開発環境の構築、運用 ○ デプロイツール・フロー改善 ○ 商用サービス部門向き合いのインフラ構築・運用・相談 ○ 最近の主なフィールドは AWS や GCP 2 自己紹介 駒﨑 拓斗

Slide 3

Slide 3 text

3 3 とつぜんですが クイズです

Slide 4

Slide 4 text

1. init オプション付きで起動する 1. pid=host オプション付きで起動する 1. user=1000:1000 オプション付きで起動する 1. sig-proxy=true オプション付きで起動する 4 次のコマンドは Ctrl+C で停止できません run のオプションで停止可能にできます。効果があるものを全て選んでください Q1. Docker クイズ $ docker run --rm busybox sleep 10000 $ docker run --rm --init busybox sleep 10000 $ docker run --rm --pid=host busybox sleep 10000 $ docker run --rm --user=1000:1000 busybox sleep 10000 $ docker run --rm --sig-proxy=true busybox sleep 10000

Slide 5

Slide 5 text

5 5 ⓘ Start presenting to display the poll results on this slide. Ctrl+c で停止可能なのはどれ? (複数選択)

Slide 6

Slide 6 text

1. init オプション付きで起動する 1. pid=host オプション付きで起動する 1. user=1000:1000 オプション付きで起動する 1. sig-proxy=true オプション付きで起動する 6 次のコマンドは Ctrl+C で停止できません run のオプションで停止可能にできます。効果があるものを全て選んでください Q1. 簡易解説 $ docker run --rm busybox sleep 10000 $ docker run --rm --init busybox sleep 10000 $ docker run --rm --pid=host busybox sleep 10000 $ docker run --rm --user=1000:1000 busybox sleep 10000 $ docker run --rm --sig-proxy=true busybox sleep 10000 PID1 のプロセスは明示的にハンドルしない限 り INT や TERM シグナルで停止しない 軽量 init プロセスを PID1 とし、 コマンドをその子として実行するオプション → init 経由でシグナルが伝わり停止する ホストと PID namespace を共有するオプション → PID1 でなくなりシグナルが伝わり停止する uid:gid を指定するオプション → 特に本件では関係ない シグナルの伝搬を指定するオプション → デフォルトで true 、本件では指定しても意味がな い 逆に false にすると Ctrl+C で KILL が送信され停止する

Slide 7

Slide 7 text

1. Service type: ExternalName を作成し Pod から Service 名で参照 $ curl https://greetech/ 2. そのままの名前で参照 $ curl https://greetech.example.com/ 3. そのままの名前 (末尾 . 付き)で参照 $ curl https://greetech.example.com./ 7 Kubernetes の ある Pod から 外部サービス https://greetech.example.com にアクセスします 最も少ない DNS トラフィックが期待できるのは次のうちどれでしょう ※ 一般的な初期設定の Kubernetes クラスタにおいて Pod - クラスタ内 DNS サーバ間 Q2. Kubernetes クイズ apiVersion: v1 kind: Service metadata: name: greetech spec: type: ExternalName externalName: greetech.example.com. ※同一 namespace

Slide 8

Slide 8 text

8 8 ⓘ Start presenting to display the poll results on this slide. DNS トラフィックが少ないのは?

Slide 9

Slide 9 text

1. Service type: ExternalName を作成し Pod から Service 名で参照 $ curl https://greetech/ 2. そのままの名前で参照 $ curl https://greetech.example.com/ 3. そのままの名前 (末尾 . 付き)で参照 $ curl https://greetech.example.com./ 9 Kubernetes の ある Pod から 外部サービス https://greetech.example.com にアクセスします 最も少ない DNS トラフィックが期待できるのは次のうちどれでしょう ※ 一般的な初期設定の Kubernetes クラスタにおいて Pod - クラスタ内 DNS サーバ間 Q2. 簡易解説 apiVersion: v1 kind: Service metadata: name: greetech spec: type: ExternalName externalName: greetech.example.com. ※同一 namespace # 標準的な resolv.conf (EKS) nameserver 10.100.0.10 search default.svc.cluster.local svc.cluster.local cluster.local ec2.internal options ndots:5 search リスト、ndots: 5 が特徴 → 名前に含まれるドットが5より少なければ search リストを順番にためすよ、の意 ドット<5 なので search リストの先頭 greetech.default.svc.cluster.local. に問い合わせ、 返された CNAME greetech.example.com. に問い合わせ ドット<5 なので search リストの先頭から greetech.example.com.default.svc.cluster.local. , greetech.example.com.svc.cluster.local. , greetech.example.com.cluster.local. , greetech.example.com.ec2.internal. , と問い合わせた後、 greetech.example.com. に問い合わせ FQDN なので greetech.example.com. に問い合わせ

Slide 10

Slide 10 text

10 10 お付き合いありがとうございました

Slide 11

Slide 11 text

11 11 本題 コンテナ時代のインフラ

Slide 12

Slide 12 text

●アプリケーション担当者/チーム (アプリチーム) ○ あるサービスのビジネスロジックを担当する ○ カスタマーに対し サービスを開発、運用する ○ 典型的には、サーバアプリケーション開発者チーム ●インフラストラクチャ担当者/チーム (インフラチーム) ○ アプリチームに対し基盤を提供、開発、運用する ○ 複数のサービスを受け持ち、共通課題を横串で担当する ■ 横串で受け持つことで、コスト・リソースの最適化を狙う ●理想的にはワンチームでプロダクトが作れたらよい、が ○ 複数事業をさばくため 12 アプリチームとインフラチーム 背景: 本日の "インフラエンジニア" について

Slide 13

Slide 13 text

●サービスを提供するインフラは絶えず変化 ●ベアメタルから VM、コンテナへ ●2020 現在グリーでは ○ オンプレミス・パブリッククラウド併用中 ○ さらにパブリッククラウドへ移行中 13 グリーグループのインフラの歩み 背景: Web サービスインフラの移り変わり ベアメタル オンプレ VM パブリッククラウド VM サーバレス コンテナ

Slide 14

Slide 14 text

●ベアメタル時代 ○ サーバ調達、インベントリ管理、OS 設定、プロビジョニング、... ○ 監視・アラートシステム 内製 ●VM 時代 初期 ○ プロビジョニングツールの導入 ○ Infrastructure as Code による自動化 ○ 構造はそのまま クラウドへの "リフト" が行われた ●VM 時代 後期 ○ パブリッククラウドの活用 ■ プログラマブル / 宣言的な構築 により自動化がさらに進む ■ クラウドに合わせた設計の浸透 ■ スケーリング操作など一部運用がアプリチーム側へ 14 インフラのデリバリー・運用の変化 これまでの変化 (ホストベース時代)

Slide 15

Slide 15 text

●実用的なコンテナ基盤の普及 ○ アプリチームからもコンテナが身近なものに ■ docker-compose ■ Cloud Run ■ AWS copilot (ecs-cli) ■ Kubernetes ●マネージド Kubernetes の大きなインパクト 15 コンテナ時代へ

Slide 16

Slide 16 text

16 消えるインフラ業務、残る生まれるインフラ業務 マネージド Kubernetes の出現 ランタイム / Lib 更新したい VM イメージ作り直してもらえます か サーバにつなげる 最小限の E2E 環境がほしい 構築とデプロイお願いします デプロイツールの改修を … Dockerfile をちょいと FROM php:7.4-apache 、と クラスタぽちぽち、 Deployment に Service に Ingress 書いて、apply 、と

Slide 17

Slide 17 text

●たしかに 一部の既存業務は ほぼなくなった ○ VM イメージ管理 ○ デプロイツール ○ オートスケーリング設定 ●引き続きやってくモノ・新しく生まれるモノ ○ サイト信頼性エンジニアリング (SRE) 関連 ■ 可観測性の面でより重要度が高まる ○ データストアやネットワーク、CDN などの専門知識 ○ 本番運用に耐えるための Kubernetes 自体の知識 ○ これまでも VM やパブリッククラウドの登場による変化はあったが Kubernetes による変化はそれよりかなり大きい 17 消えるインフラ業務、残る生まれるインフラ業務 マネージド Kubernetes の出現

Slide 18

Slide 18 text

●(少なくとも今のとこは) まだまだ ●例. 冒頭のクイズの領域 ○ Q1. Docker クイズ (The PID1 Problem) ■ Dockerfile の書き方を気をつける問題、nodejs で遭遇しがち ○ Q2. Kubernetes クイズ (dnsPolicy ClusterFirst の設定) ■ 名前解決のお作法に気をつける問題 ○ しかし全くビジネスロジックには関係無い ■ アプリチームが頑張るところだろうか? ■ 組織として横串で共有すべきノウハウの類 ●"アプリチームに基盤を提供する" 仕事の本質は同じ ○ が、どこまでが基盤なの? 18 Kubernetes でインフラの業務範囲はどんどん縮小する? これから仕事減りそう?

Slide 19

Slide 19 text

19 ホストベースのころ 19 PHP : アプリチーム CI : アプリチーム Deploy : インフラチーム apache : インフラチーム VM : インフラチーム LB : インフラチーム ︙ チーム担当範囲の境界はどこだ これから Dockerfile : アプリチーム...? ちょっとインフラ? CI/CD : アプリ?インフラ? K8s : インフラチーム...? とアプリチーム...? ︙ 従来型分担とのアンマッチ

Slide 20

Slide 20 text

●ソフトの構造と組織の構造に相関がある、として ●従来のチーム分け ○ VM時代以前(ホストベース) の構造に最適化されたもの ●インフラの新しいレイヤが積まれ構造が変化 ○ 一段上のプラットフォームができた ○ 抽象化・ソフトの構造が変化した ○ 従来の組織でアンマッチを感じるのは自然 20 ソフトウェアの変化、変化前の組織とのアンマッチ なぜアンマッチが発生するか

Slide 21

Slide 21 text

●現状は双方からコミット ●コミュニケーションを大事に ●サービスの時期によって柔軟に ○ 弊社ケース ■ 初期はインフラチーム率高め ■ 安定運用 & K8s 習熟度向上してくるとアプリチーム率高め ■ 境界のあいまいさは許容 21 インフラチーム / アプリチームの壁を越えてコミュニケーション 現時点の状況 Dockerfile インフラチーム アプリチーム K8s manifest K8s Cluster Config Dockerfile インフラチーム アプリチーム K8s manifest K8s Cluster Config Dockerfile インフラチーム アプリチーム K8s manifest K8s Cluster Config CI/CD CI/CD CI/CD むしろ、従来の構造のチームにキッチリ 合わせようとしてしまうと Kubernetes 的/クラウドネイティブ的 なソフトを活かせなくなる可能性も

Slide 22

Slide 22 text

●グリーでは現状 ホストベース環境が主流 ○ コンテナ/Kubernetes に向けて即組織刷新とかはない ●いま 2020 年、両方やらなくちゃいけない ●Kubernetes との向き合い方には気をつける ○ コンテナ管理ツール ではなく プラットフォームとして ○ 今までのやり方を延長するより、段を登ってみる ○ さらにプラットフォームのためのプラットフォームでもある ○ プラットフォームの意図を汲む 22 従来のホストベース環境も両方見ていく 現時点の状況

Slide 23

Slide 23 text

● Dokcer も Kubernetes も関係無しに 実現するとしたら? ○ 環境ごとに VPC を分ける VPC ごとの DNS サーバを使って レコードを切り替える ○ AWS Route53 など 23 例. 23 DNS 管理者の帽子 「自前 DNS サーバでコントロールしよう」 アプリから外部サービス API を参照する。 Production / QA / Develop の 環境ごとに参照先を切りかえたい… どうやって実現しようか

Slide 24

Slide 24 text

● Dokcer コンテナ的なお作法で 実現するとしたら? ○ コンテナ内で環境変数を参照させ 実行環境で環境変数に参照先ドメインを流し込む ○ コンテナ内に全パターンの config を埋めておき、 環境変数で config パスを切り替える 24 例. 24 Docker の帽子 「APP_PORT_TCP_ADDR 環境変数を 参照させよう」 DNS 管理者の帽子 「自前 DNS サーバでコントロールしよう」 アプリから外部サービス API を参照する。 Production / QA / Develop の 環境ごとに参照先を切りかえたい… どうやって実現しようか

Slide 25

Slide 25 text

● Kubernetes のお作法で 実現するとしたら? ○ コンテナ内の名前は固定してよい Service リソースで流し込む ○ または Docker のとこで挙げたパターンもよい 25 例. 25 Kubernetes の帽子 「Service リソース名を参照させよう」 「もしくは環境変数でもよい」 Docker の帽子 「APP_PORT_TCP_ADDR 環境変数を 参照させよう」 DNS 管理者の帽子 「自前 DNS サーバでコントロールしよう」 アプリから外部サービス API を参照する。 Production / QA / Develop の 環境ごとに参照先を切りかえたい… どうやって実現しようか

Slide 26

Slide 26 text

●帽子のかぶりわけ ○ 範囲を明確に認識出来ている状態 ●まずは一番上の帽子をかぶる ○ だめなら下の帽子をかぶりなおす ○ どの帽子をかぶっているかを忘れない ●柔軟なプラットフォームほど 帽子を見失いがち ●作る側に回るときにも必要 26 このプラットフォームはどう使われることを想定しているのか プラットフォームの意図を汲む Kubernetes の帽子 「Service リソース名を参照させよう」 「もしくは環境変数でもよい」 Docker の帽子 「APP_PORT_TCP_ADDR 環境変数を 参照させよう」 外部サービスの参照先を 環境ごとに切りかえたい … DNS 管理者の帽子 「自前 DNS サーバでコントロールしよう」

Slide 27

Slide 27 text

●アンラーニングで新しい帽子を手に入れる ○ 既存知識との境界を認識する、引きずらない ■ 既存知識の活用・応用はあとからでいい ●多くの場合、高次の帽子が "筋がいい" が ○ ときには帽子をかぶりわける ○ プラットフォームの機能が十分でないとき ○ あえて違う作法を選ぶとき ●帽子を混ぜない!どっちつかずは運用混乱を招く ○ どっちつかずの例. ■ ingress-controller で LB を作成したが、別の方法で設定追加 ■ external-dns で作成したレコードと手動作成したレコード混在して参照させる 27 新しい帽子を手に入れる・帽子をかぶりわける どっちつかずの帽子

Slide 28

Slide 28 text

●コンテナ・クラウドネイティブ時代も変わらないもの ○ アプリチームがビジネスに集中できる基盤を提供する ○ 横串でノウハウ・サービスを展開する ●ホストベース時代とコンテナ時代の構造の違いを認識 ○ どちらにもマッチするチームは難しい ○ (気持ちは) チームの柵を越えていく ●インフラの階層ごとに頭を切り替える ○ インフラ領域も確実に抽象化層が増えた ○ 帽子をかぶりわけるように ○ どの階層の話なのか? をはっきり 28 移行期のインフラエンジニアとして ホストベース時代からコンテナ時代へ

Slide 29

Slide 29 text

29 29 ⓘ Start presenting to display the poll results on this slide. よろしければ教えて下さい皆様の担当領域は?

Slide 30

Slide 30 text

30

Slide 31

Slide 31 text

31 Q1. Docker クイズ (The PID1 Problem) 資料 参考リンク ● "Docker/Kubernetes で PID 1 問題を回避する" https://text.superbrothers.dev/200328-how-to-avoid-pid-1- problem-in-kubernetes/ ● "PID1 は、カーネルから特別扱いされてるって本当ですか?" https://speakerdeck.com/superbrothers/pid1-ha- kanerukara-te-bie-xi-isareterututeben-dang-desuka ● "Docker and Node.js Best Practices" > Node.js was not designed to run as PID 1 which leads to unexpected behaviour … https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md#handling-kernel-signals ● Google Cloud "PID 1、シグナル処理、ゾンビプロセスの適切な処理" https://cloud.google.com/solutions/best- practices-for-building-containers?hl=ja#signal-handling ● docker アプリが適切な signal handling をしていない場合に、アプリの適切な終了処理ができなかったり、実行環境・ア プリによっては fork したプロセスが回収されずゾンビ大量発生などの問題を招く ● 現実的には nodejs や LL の簡易サーバ、crond などで遭遇しがち ● 自分のアプリが適切に handling できているかについては、クイズのように docker run してみて Ctrl+C や docker stop / docker kill --signal="TERM" のようにしてみると簡単に確認できる ● 対応については、alpine ベースであれば apk で tini (軽量 init プロセス) を入れてしまうのが便利 $ docker run --rm busybox sleep 10000

Slide 32

Slide 32 text

32 Q2. Kubernetes クイズ (dnsPolicy ClusterFirst の設定) 資 料 参考リンク ● "RESOLV.CONF(5)" https://linuxjm.osdn.jp/html/LDP_man-pages/man5/resolv.conf.5.html ● "Kubernetes Documentation >..> DNS for Services and Pods" https://kubernetes.io/docs/concepts/services- networking/dns-pod-service/#srv-records ● GitHub "update docker's resolv.conf file with options ndots:5" https://github.com/kubernetes/kubernetes/pull/10266 ● GREE Engineer's blog "スマホゲームの API サーバにおける EKS の運用事例 > DNS の名前解決に失敗する" https://labs.gree.jp/blog/2020/01/20271/#anker612 ● "Amazon EKS での DNS 障害のトラブルシューティング" https://aws.amazon.com/jp/premiumsupport/knowledge- center/eks-dns-failure/ ● まずは resolv.conf(5) man の options ndots 項を参照のこと ● Kubernetes 固有の問題。ふつうの(?) Linux 環境であれば ndots: 5 が入っていることはそうそう無いので、 curl https://greetech.example.com/ で何も問題ない ● Kubernetes では、SRV レコードによるサービスディスカバリの利便性のためにこういう設定になっている (下記 github の kubernetes/kubernetes リンクも参照) ● クイズで問題のある例として挙げた方法では、IPv6 が有効な場合 AAAA レコードにも問い合わせを行い、1つの名前解決 だけで 10 以上のクエリが発生する場合がある # 標準的な resolv.conf (EKS) nameserver 10.100.0.10 search default.svc.cluster.local svc.cluster.local cluster.local ec2.internal options ndots:5 search リスト、ndots: 5 が特徴 → 名前に含まれるドットが5より少なければ search リストを順番にためすよ、の意