Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CA 1day Youth Bootcamp CIU Kubernetes

Bo0km4n
November 25, 2021

CA 1day Youth Bootcamp CIU Kubernetes

CA 1day Youth Bootcamp CIU 編という CyberAgent, Inc. が主催するインターンで発表した資料になります

Bo0km4n

November 25, 2021
Tweet

More Decks by Bo0km4n

Other Decks in Programming

Transcript

  1. 2021新卒研修 Kubernetes の 基礎編 CA 1Day Youth Boot Camp Version

    CyberAgent group Infrastructure Unit / Katsuya Kawabe
  2. Katsuya Kawabe •CyberAgent group Infrastructure Unit インフラ基盤を開発するソフトウェアエンジニアです AKE, OpenStack, ML

    Platform などの開発、運用をしています •趣味 漫画 最近は「ブルーロック」「左利きのエレン」が熱い 音楽 なんでも聴きます。BUMP OF CHICKEN が一番好き
  3. さくっと理解する Kubernetes の需要 •コンテナベースのアプリケーションを運用するために考えることは? 1. アプリケーションをどの VM or 物理マシン に配備するか

    2. リソースが足りなくなった時の マシン のスケールアウトはどうするか 3. 逆にリソース過多でスケールインさせたい場合はどうするか? 4. コンテナに割り振る IP アドレスはどうやって管理するか 5. コンテナ間のサービスディスカバリはどうするか 6. 複数のコンテナへのロードバランシングはどうするか 7. コンテナに依存しない永続化したデータはどうやって管理するか などなど、人類は欲深いのでこれらを解決できるソリューションを求めていました
  4. 余談: VMは必要なくなったのか? •そんなことは全然ない そもそも GKE や EKS といった、パブリッククラウドにおける Kubernetes as

    a Service も 結局は GCE や EC2 といった仮想化基盤の上で動いている •VM時代に比べてバックエンドエンジニアが知るべき領域は減ったのか? 抽象化が進み確実に「バックエンドエンジニアでもOS、ネットワーク、ミドルウェアの知識も必要」という場 面は減ってきている(気がする) •「とりあえず Kubernetes でアプリを運用してみる」ってどう? 2, 3年前なら批判されていたかもしれないが、今は GKE Autopilot などの登場により、Kubernetes 自体の 運用もかなり楽になってきている。後述する魅力的な機能やエコシステムに楽に乗っかれるようになって きたので今なら全然ありだと思う
  5. 宣言的なコードによる管理 • Kubernetes で管理するリソースは全て宣言的な YAML で定 義されます • 「Desired State」:

    こうあるべきという状態を宣言するもの (ex: Nginx の Pod が3つ立って欲しい • 宣言された状態に遷移させるのは Kubernetes のコンポー ネントが責務を持ちます • 基本的に Kubernetes で軽くアプリを動かすだけならよく使う リソースの YAML の書き方を知っておけば大丈夫なはず
  6. 宣言的なコードによる管理 Developer or SRE or Program ... kubectl apply *

    Nginx Nginx Nginx 様々なリソースをマニフェストとして Kubernetes に登録する Node Node Node
  7. Kubernetes のリソース - Workloads リソース - コンテナ実行に関わるリソース - この研修で主に触れます。Pod, Deployment,

    ReplicaSet 等が含まれます - Discovery & LB リソース - コンテナを外部公開するためのリソース - Service, Ingress リソース等が含まれます - Config & Storage リソース - 設定情報、機密情報、永続化するようなデータに関するリソースです - Cluster リソース - クラスタで共通なセキュリティやクォータに関するリソースです - Metadata リソース - Kubernetes のリソースを操作するためのリソースです - CustomResourceDefinition のような拡張機能も含まれます
  8. Namespace による分離 Pod Pod Pod Service Service Pod Pod Service

    Service “Staging” Namespace Pod Pod Service “Decvelopment” Namespace アプリ開発者 Namespace という分離機能があり、リソースの分離や Namespace 単位でのア クセス許可といったことができます。 今回は default Namespace 内での操作しかしませんが、重要な概念です “Production” Namespace SRE
  9. 宣言的なコードによる管理 • 今日はこの Infrastructure as a Code をサンプルや課題のコードを実際に動かして体感してもら います •

    とはいってもやることはシンプル • ファイルを編集 -> kubectl apply -f *.yaml -> 修正したかったらファイルを修正 -> 再度 kubectl apply -f *.yaml
  10. 使用する環境: GCP, GCE, Kind • GCP は Google が提供するパブリッククラウド •

    Kind on GCE: GCE 上で Kind (Kubernetes in Docker) を動かして Kubernetes を体験してもらい ます • Kind: Docker 上に Kubernetes のコンポーネントを動作させて、お手軽に Kubernetes を試すこ とができるツールです。類似ツールに Minikube があります • GKE でない理由はこのインターンの後皆さんの手元の PC でも簡単に環境を再現できるように するためです
  11. 使用する環境: 1人1クラスタ Pod Pod Pod Service Service “User A” Cluster

    User A User B VM に SSH してもらい、kubectl コマンドでクラスタを操作してもらいます。 他人のクラスタは SSH しないと操作できませんが、間違えないように注意してくださ い。 Pod Pod Pod Service Service “User B” Cluster
  12. リポジトリの構造 $ tree ├── examples │ ├── deployment.yaml │ ├──

    ingress.yaml │ ├── pod.yaml │ ├── replicaset.yaml │ └── service.yaml ├── exercises │ ├── deployment │ │ └── answer.md │ ├── ingress │ │ ├── answer.md │ │ ├── gencert.sh │ │ ├── ingress.yaml │ │ ├── server.crt │ │ ├── server.key │ │ └── ssl.conf │ └── pod │ ├── advance_answer.md │ └── basic_answer.md
  13. Pod とは Container Container NIC Container Container NIC NIC Pod

    は一つ以上のコンテナから構成される、Kubernetes におけるコンテナ実行に関する最小単位のリソースです。 アプリケーションをコンテナ化して動かしたい場合は最終的には Pod が作成されることになるはず。 IP アドレスは Pod 単位で割り当てられます => ネットワークの名前空間を共有 つまり、内部のコンテナで同じポート番号でサーバをリッスンしようとするとどちらかは失敗します
  14. Pod のアプライ $ kubectl apply -f examples/pod.yaml # Pod が動いているか確認してみよう

    $ kubectl get po NAME READY STATUS RESTARTS AGE echo-pod 1/1 Running 0 3d3h
  15. Pod のマニフェストについて • kind: Kubernetes のリソースの種類 • apiVersion: kind のバージョン

    • metadata: 管理用の付加情報 • name: コンテナを識別するための名前。他のと重 複できない • command: コンテナのエントリーポイント • image: コンテナ のイメージとタグ • imagePullPolicy: image を pull する際、キャッシュ したものを使うのか( IfNotPresent )、常にリモート から取得するのか( Always ) • ports.ContainerPort : Pod の IP から Expose するコ ンテナの ポート番号を指定 • args: command に対する引数
  16. Pod にリクエストを投げてみよう # Pod の IP を確認しよう $ kubectl get

    pod -owide # kubectl run でデバッグ用の Pod を建てて echo-pod にアクセスしてみる # foo と出力されれば成功 $ kubectl run busybox -it --rm --image=busybox --restart=Never -- /bin/sh -c "wget -q -O- <Pod IP>:8080"
  17. # Tips - kubectl apply -f <file name> - 一番お世話になるであろうコマンド。マニフェストを適用する

    - http のアドレスを指定してもいいので GitHub 上の生マニフェストも適用できます - create もあるが、こちらは既にリソースがあるとエラーになる - apply は作成も更新も可能 - kubectl get resource_kind - 恐らく一番お世話になるであろうコマンド第二弾。リソースの一覧を取得します - kubectl get -oyaml で生のリソースを yaml 形式で確認できます。-ojson とかだと json になる - -owide を Pod や Node に使うと IP をぱっと確認できて便利 - kubectl run - 実運用で使うことはあまりないが、Pod 間の疎通を確認するのに便利 - --it は --stdin と --tty オプションを同時に指定しており Pod の標準入出力を取得しています - --rm は実行後 Pod を削除します - busybox イメージ - busybox という unix のユーティリティを詰め合わせたバイナリのコンテナイメージ - 軽量なので立ち上がるのが早いです。とりあえず Pod 建てるなら busybox でいいんじゃないかな - sh 自体も busybox に含まれる - curl とか dig はないので注意 (ping はある)
  18. 問題 1 • busybox イメージのコンテナ2つを含む Pod を建ててみよう。 ◦ 1つ目のコンテナの name

    は foo、2つ目のコンテナの name は bar で作成してみよう ◦ foo, bar コンテナで実行するコマンドは sh -c “echo bootcamp; sleep infinity” にしてみよう ◦ busybox のイメージは image: busybox で使用できます • 上級者向け: nginx の Pod を建て、init container に busyboxy のコンテナを作成して echo -n “Hello, World!” > /work-dir/index.html を実行しよう。 ◦ 作成するとき、emptyDir をinit container の /work-dir、nginx の /usr/share/nginx/html にマウントしよう ◦ nginx のポート番号などはお任せします。 ◦ kubectl run busybox -it --rm --image=busybox --restart=Never -- /bin/sh -c "wget -q -O- $POD_IP" で Hello, World! と出力されるか確認してみよう • 解説は exercises/pod 以下の Markdown に書いてあります
  19. ReplicaSet で複数の Pod を管理 • Pod のレプリカを作成して指定した数の Pod を稼働させるリソース •

    冗長性、スケールインやスケールアウトを実現するリソースの一つ • 後述する Deployment と合わせて Pod -> ReplicaSet -> Deployment という親子構造がある Pod Pod Pod Pod Pod ReplicaSet (Replica 数 = 5) 図引用: Kubernetes 完全ガイド 第一版
  20. ReplicaSet で複数の Pod を管理 • オートヒーリングも ReplicaSet で実現可能 Pod Pod

    Pod Pod Pod ReplicaSet (Replica 数 = 5) Pod Pod 図引用: Kubernetes 完全ガイド 第一版
  21. ReplicaSet で複数の Pod を管理 • Pod のラベルで数を調節 ReplicaSet (Replica 数

    = 3) metadata.labels で該当する app: nginx ラベルがついた Pod を探 す Pod app: echo Pod app: test Pod app: nginx Pod app: nginx Pod app: nginx 図引用: Kubernetes 完全ガイド 第一版
  22. ReplicaSet のデプロイ $ kubectl apply -f examples/replicaset.yaml # Pod が作成されているか確認

    $ kubectl get po -l app=echoserver # spec.replicas を 5 に変更してみよう $ kubectl apply -f examples/replicaset.yaml # 動作確認ができたら削除しておこう $ kubectl delete -f examples/replicaset.yaml
  23. # Tips - kubectl edit - Kubernetes 上のリソースを直接操作できます - しかし、手元に修正後のマニフェストが残らないので本番環境とかではやらないほうがいい

    - edit 時に開かれるエディタは EDITOR 環境変数で変更できます - kubectl label - 対象リソースにラベルの付与、更新、削除ができます - 付与: kubectl label pod/test app=test - 削除: kubectl label pod/test app- - 更新: kubectl label --overwrite pod/test app=test2
  24. ReplicaSet マニフェストの解説 • spec.replicas: Pod の数 • selector.matchLabels: 管理する Pod

    のラベル • spec.template: Pod のテンプレートを書きます。中身 は pod.yaml のものと一緒 selector には他にも matchExpressions という複雑な条 件をもとに Pod を管理する方法もあるがここでは割愛 します
  25. Deployment で ReplicaSet を管理 • Deployment は複数の ReplicaSet を管理することで、ローリングアップデートやロールバックと いった、実運用においてアプリケーションの稼働状態を保ちながら変更する仕組みを実現して

    います Pod Pod Pod Old ReplicaSet (Replicas = 3) New ReplicaSet (Replicas = 0) Pod Pod Pod Old ReplicaSet (Replicas = 3) New ReplicaSet (Replicas = 1) Pod Pod Pod Pod Old ReplicaSet (Replicas = 2) New ReplicaSet (Replicas = 2) Pod Pod Pod Old ReplicaSet (Replicas = 0) New ReplicaSet (Replicas = 3) Pod 図引用: Kubernetes 完全ガイド 第一版
  26. Deployment で ReplicaSet を管理 • 新しい ReplicaSet の Pod がちゃんと立ち上がったかを

    HealthCheck しながら切り替えてくれる • Rolling Update の際の許容される不足 Pod 数や超過 Pod 数なども設定可能 • ロールバックするための、Pod の Revision などをどれだけ保持するかなどの設定も可能 • Kubernetes でコンテナを起動する際に、最も推奨されている方法
  27. Deployment のデプロイ $ kubectl apply -f examples/deployment.yaml # Pod が作成されているか確認

    $ kubectl get po -l app=echoserver # Pod Template の imagePullPolicy を IfNotPresent に変更してみよう $ kubectl apply -f examples/deployment.yaml # ReplicaSet が二つできているはず $ kubectl get rs # ReplicaSet を一つ目の Revision に戻してみる $ kubectl rollout undo deployment echoserver --to-revision=1 # 動作確認ができたら削除しておこう $ kubectl delete -f examples/deployment.yaml
  28. # Tips - kubectl rollout - kubectl rollout restart deploy

    <deployment_name> で一台ずつ安全にリスタートできます
  29. 問題 2 • nginx:1.18.0 の Deployment を作成しよう ◦ Replica は

    3 ◦ Port は 80 を expose していること ◦ command と args は指定しなくて大丈夫です • 上級者向け問題 • Deployment に対して Horizontal Pod Autoscaler を設定しよう ◦ 最小 Replica = 5, 最大 Replica = 10, メトリクスは CPU 使用率 80 %
  30. Service: Kubernetes のネットワーク • Service は Pod 宛のトラフィックをロードバランシングするリソースです • サービスディスカバリとクラスタ内

    DNS で利用 • 外部からのリクエストもロードバランシングできる NIC Pod Pod NIC Pod NIC Pod Pod Node Network Pod Network 図引用: Kubernetes 完全ガイド 第一版
  31. Service: Kubernetes のネットワーク NIC Pod In Cluster VIP NIC Pod

    Pod NIC Endpoint (LB VIP) Pod Pod Pod kube-proxy kube-proxy kube-proxy 図引用: Kubernetes 完全ガイド 第一版 Node Network Pod Network • 外部のロードバランサが払い出す IP やクラスタ内でのみ使用可能な IP などを提供するリソース • それぞれの外部のロードバランサを利用する場合、プロバイダごとに実装が異なります • Pod への通信は kube-proxy によってノードから Pod の仮想 NIC にルーティングされます
  32. Kubernetes でのサービスディスカバリ NIC Pod In Cluster VIP NIC Pod Pod

    NIC Pod Pod Pod kube-proxy kube-proxy kube-proxy 図引用: Kubernetes 完全ガイド 第一版 Node Network Pod Network • クラスタ内でのみ有効な DNS を利用してサービス間の通信を実現できる • Pod, Service に対して固有のレコードがクラスタ上の DNS に追加される • Pod から透過的に、別サービスの Pod へリクエストを送信することができる To: service-b.default.svc.cluster.local
  33. Service の種類 • Cluster IP : クラスタ内部でのみ使用可能な仮想 IP を持つ Service

    • NodePort : <全ての Node の IP アドレス>: Port の組みでトラフィックを受ける Service • LoadBalancer : Kubernetes クラスタ外のロードバランサを利用して、トラフィックを受ける Service。L4 のロードバランシング実現するためのリソース
  34. Cluster IP のルーティング NIC Pod Pod Pod Network app: echo

    10.0.0.10:80 NIC Pod app: echo 10.0.1.20:80 NIC Pod Pod app: echo 10.0.2.30:80 ClusterIP Service (10.100.100.100:8080) kube-proxy 図引用: Kubernetes 完全ガイド 第一版
  35. Cluster IP Service のデプロイ # 受け付ける Pod が必要なので Deployment を用意

    $ kubectl apply -f examples/deployment.yaml # Pod が作成されているか確認 $ kubectl get po -l app=echoserver # Service をデプロイ $ kubectl apply -f examples/service.yaml # 割り振られた IP を確認。kubectl get svc でも可 $ kubectl describe svc echoserver # クラスタ内に適当に Pod を建ててアクセスしてみる $ kubectl run --image=centos:6 --restart=Never --rm -i testpo -- curl -s http://<svc-ip>:80 # 今度はクラスタ内DNS経由でアクセスしてみる $ kubectl run --image=centos:6 --restart=Never --rm -i testpo -- curl -s http://echoserver.default.svc.cluster.local:80
  36. # Tips - kubectl describe - リソースの詳細を知ることができます - 綺麗に整形されて表示されるので見やすいです -

    kubectl get <resource> <resource_name> -oyaml では生のマニフェストを見れますが整形されてないので 慣れてないとわかりづらい - kubectl get -oyaml だと describe で表示されない情報も確認できるのでトラブルシュートの時はこちらを 使うことが多いかも
  37. NodePort のルーティング NIC Pod Pod Pod Network app: echo 10.0.0.10:80

    NIC Pod app: echo 10.0.1.20:80 NIC Pod Pod app: echo 10.0.2.30:80 NodePort Service (*:30010) • 全ての Node の特定の Port でリクエストを受け付けるサービスを作成する • Kubernetes 外部からも 30010 にアクセスするとバックエンドの Pod にリクエストが送信できる • 外部との疎通性を確立する手法の1つ • ポート番号は指定できるが、指定しない場合は Kubernetes が使用していないポート番号をあらかじめ指定したレンジ から割り振ります
  38. NodePort Service のデプロイ # 受け付ける Pod が必要なので Deployment を用意 $

    kubectl apply -f examples/deployment.yaml # Pod が作成されているか確認 $ kubectl get po -l app=echoserver # Service をデプロイ $ kubectl apply -f manifests/service-node-port.yaml # Service に割り振られた Port を確認 $ kubectl get svc -owide # 割り振られた Node の IP を確認 $ kubectl get node -owide # クラスタ内に適当に Pod を建ててアクセスしてみる $ kubectl run busybox -it --rm --image=busybox --restart=Never -- /bin/sh -c "wget -q -O- <Node IP>:<Node Port>"
  39. Ingress のルーティング NIC Pod Service A Service B NIC Pod

    Pod NIC Pod Ingress /foo: Service A, /bar: Service B Pod Pod 図引用: Kubernetes 完全ガイド 第一版
  40. Ingress のデプロイ # Ingress をデプロイ。マニフェストに Deployment と Service も含まれています。 $

    kubectl apply -f examples/ingress.yaml # Ingress にアクセス可能なアドレスが付与されたか確認 $ kubectl get ingress NAME CLASS HOSTS ADDRESS PORTS AGE example-ingress <none> echo.info localhost 80 105m # Ingress 経由でアクセス $ curl -XGET -H “Host: echo.info” http://localhost/foo # cleanup $ kubectl delete -f examples/ingress.yaml
  41. Ingress のマニフェスト • spec.rules[].host: リクエストを受け付ける Host 名 • spec.rules[].http.paths: HTTP

    のパスに対するルーティング ルールを記述する • pathType: Prefix は前方一致。 ◦ Exact を指定した場合は完全一致 ◦ ImplementationSpecific というプロバイダごとに異なるマッ チ条件も指定可能 • path: リクエストをルーティングするパス • backend: ◦ リクエストを流す Service を指定しているが、その他のリ ソースも指定可能 ◦ GCS のストレージなども指定可能だったりする
  42. # Tips - 複数マニフェストを同一ファイルに記述 - “---” で区切ることによって複数のマニフェストを同一ファイルに書ける - Ingress のホストは

    * を指定できる - あらゆるホストへのリクエストをバックエンドの Pod に流せるが、あまり使わない - Ingress の作成時間 - 裏でクラウドごとに LB やファイヤウォールのリソースを作成していたりするので意外と時間がかかる。気 長に待ちましょう
  43. 問題 3 • Examples の Ingress で /bar でアクセスしたとき `bar`

    を返すようにしてみよう • 超上級者向け • Examples の Ingress で TLS 終端してみよう 自己署名証明書で終端してください (Let’s encrypt やその他正式な認証局による証明書はなし) cert-manager を使わずに openssl コマンドで証明書を作成してみよう curl --cacert ./ca.crt https://echo.info/foo --resolve echo.info:443:127.0.0.1 が通ればOK
  44. 今回説明できなかったリソース • Secret : その名の通り秘密情報をもつリソース • ConfigMap : 何らかの設定情報をもつリソース •

    Job & CronJob : 周期的、または何かを起点にした OneShot なコンテナの起動を行うリソース • DaemonSet : ノード単位で Pod をデプロイするリソース • PersistentVolume : コンテナのライフサイクルとは独立した永続化ボリュームを表現するリソー ス • Role & RoleBinding & ServiceAccount : Kubernetes のリソースに対しての認証認可を司るリ ソース
  45. 今回説明できなかった仕組み • requests & limits Pod 単位で CPU や Memory

    の割り当てについて指定できる • コンテナライフサイクル preStop, preStart : コンテナの起動、終了に任意の処理を挟み込む仕組み livenessProbe, readinessProbe : コンテナが起動しているか、準備完了かをチェックする仕組み
  46. Kubernetes 内部の仕組み • 知らなくてもそこまで困らないけど、やはり知っておくと色々トラブルシューティングする時楽な ので軽く触れます • 詳しくコアコンポーネントの仕様とか動きを知りたい人は「Kubernetes The Hard Way」とググっ

    て一から Kubernetes を構築してみよう! • ちなみに弊社でも 「おうちk8sインターン」というので Raspberry Pi4 にベアメタルK8sを構築する というのをやっていて手順も公開されているのでよかったらZehi
  47. Kubernetes 内部の仕組み Kubernetes Nodes kubelet + kube-proxy kube-apiserver LoadBalancer データストアとして利用

    kube-scheduler Pod のスケジューリング 自ノードに割り当てられてる Pod があれば起動 kube-controller-manager Deployment などのリソースの 制御 kube-dns 名前解決 サービスディスカバリ 図引用: Kubernetes 完全ガイド 第一版
  48. kube-apiserver • Kubernetes の API を提供するコンポーネントです • kubectl コマンドは kube-apiserver

    に対してリクエストを送っています • 受け付けたリクエストを etcd に書き込んだり、読み込んだりする • kube-scheduler や kubelet といったコンポーネントも kube-apiserver にリクエストを送り、処理 を行っている • kube-apiserver が死ぬとクラスタが操作不能になるのでこれも冗長化必須
  49. kube-controller-manager • リソースの状態を Desired State を持っていくために様々な処理を行うコントローラ • 例えば Pod が

    3つ動いて欲しいが2つしかないとき、Pod の情報を etcd に追加したりする • 組み込みのリソースのコントローラは全て kube-controller-manager で処理される • 運用者独自のリソースとコントローラを導入したい場合は「CustomResourceDefinition」と 「Custom Controller」という仕組みを使います
  50. kubelet • kubelet は各ノード上で稼働するコンポーネントです • Docker などのコンテナランタイムを呼び出して、実際にコンテナの起動や停止などを行います • kube-scheduler によって

    Pod が起動されるノードが決定すると、それを検知して自身で起動す べきコンテナを起動します • Docker 以外でも OCI というコンテナランタイムのインタフェースに則ったランタイムであれば利 用可能です(e.g. Containerd, CRI-O, gVisor) • ちなみに Docker は kubelet のランタイムとしては v1.24 で使用できなくなるので注意
  51. kube-proxy • kube-proxy もノード上で動作するコンポーネントです • Service リソースを作成した際に、仮想的な IP 宛のトラフィックを対象の Pod

    へ転送されるよう にします • 実際にはノードの iptables や IPVS のような Linux カーネルに組み込まれてるネットワークトラ フィックを制御する仕組みをラップして、トラフィックの転送を実現しています
  52. kube-dns • Kubernetes クラスタ内部の名前解決やサービスディスカバリに利用される DNS です • Pod からのリクエストを解決する際は、まず kube-dns

    に問合せが行われ、それでも解決できな い場合は上流の DNS で解決を試みます • 最初から kube-dns ではなく、自前で建てた DNS に解決させたい場合も Pod 側で個別に設定 可能
  53. Argo CD • GitOps な CI/CD を構築可能 • Argo Rollouts

    を使って Blue/Green や Canary といった高度なデプロイも可能 • 手動のマニフェストデプロイが必要なくなるのでかなり便利
  54. Istio • Service Mesh の代表格 • サイドカーでサーキットブレイクや HTTPS 終端、認証といった処理を担うことができる •

    Kubernetes 上で一貫したネットワークポリシーやロギングなどが可能 • 大規模な分散システムでは役立つ