大学時代はTOEIC300点代だった僕が、人生で初めて洋書を読み終わったのでその記録です。

『Cloud Native DevOps with Kubernetes』という本を読みました。

せっかくなので、洋書を読み終わるまでにやったことと工夫したポイントと、読書メモを記録しておきます。

工夫ポイント

専門外ではなくて、少しは内容を知っている本を読む

あまりに専門外の本だと単語の意味とか全くわからないし、興味もわかないと思ったので、内容を多少は知っている本を選びました。 今年の夏からKubernetesの勉強を初めて10月にCKAを取得したので、k8s関連であまり難しくなさそうな本ということで選定しました。

毎日コツコツ読む

英語できないマンは一日に読める英語の量に限界があります(多分) 一気にやろうとすると間違いなく途中で挫折するので、「1日10Pを毎日続けて30日で読み終わる」という計画を立てて実行しました。 家だと集中できないので、毎朝ちょっと早めに会社に来てリフレッシュエリアで読んでしました。

躊躇なく読み飛ばす

英語できないマンなので、普通にわからない単語めちゃくちゃあります。長い文章は意味を捉えきれないところもあります。 毎回立ち止まっていたら進まないので、なんとなく雰囲気で理解できる所はそのまま読んで、全く意味がわからない時だけ立ち止まって単語の意味を調べたりするようにしました。

『Cloud Native DevOps with Kubernetes』の読書メモ

以下、読書メモです。

CHAPTER1 Revolution in the Cloud

  • The operating system for this world is called Kubernetes
  • Cloud(pay-per use access to computing resource)は新しい考え方ではない。世界の革命は"circilar movement”(円運動)であり、揺り戻しがある。
    • メインフレームのタイムシェアリングも似たような考え方である
  • DevOpsの夜明けにより、Developerはシステムがどのように動くかを理解し、Operatorはソフトウェアがどのように動き、失敗するかを理解する必要がある世界になってきた
  • 「NoOpsが運用をCloud Providerや他のthird-partyサービスに全てアウトソースできるという考え」は誤解である
  • 「巨大かつ複雑でネットワークの異なるシステムに、どうシステムをデプロイするか」「複数の環境にどのようにデプロイするか」コンテナ(とオーケストレータ)を使おう
  • VMとコンテナの違い
    • サイズが小さい、余計なものが入ってない、仮想ではないのでオーバーヘッドが少ない、`
  • GoogleのBorgに端を発したOSSのKubernetesは2017年にはデファクトスタンダードになった
  • Kubernetes is provider-agnostic(プロバイダに依存しない)
  • Kubernetes Doesn’t Do It All
    • Kubernetesに合わないものもある
    • もちろんDBとかも動かせるが、コストとかを考えればマネージドサービスを使ったほうがいいケースもある
    • FaaSを使ったほうがいい場合もある
  • FaaSはコンテナより便利な点もある(サーバ管理コストがかからない)が、実行時間が短かったり巨大なファイルをデプロイできないなどの制約も多い
  • Cloud Nativeの特徴
    • Automatable
    • Ubiquitous and Flexible
    • Resilient(弾力性) and Scalable
    • Dynamic
    • Observable
    • Distributed(分散)
  • microserviceは万能薬ではなく、複雑性が増すというデメリットもある
  • 「モノリスなアプリケーションをコンテナ化してクラウド上で動かすこと」は。徐々にモノリスをマイクロサービスに移行すること及びCliudNativeなシステムにre-designする最初の一歩となりうる
  • 今までのように簡単なシェルスクリプトだけ書けばよかった時代ではなく、ソフトウェアを理解し、維持し、コードを書くスキルが必要とされる
    • より新しいことを学ばなければならない
  • ops teamではなくdeveloper productivity engineering(DPE) と呼びたい!

CHAPTER2 First Steps with Kubernetes

  • This makes Go a good choice for developing cloud native applications.
    • Cloud Native関連のOSSはgolangで書かれているケースが多い
  • multi stage buildのよいところ
    • image sizeの削減
    • attack surfaceの削減
  • kubectlはimperative(命令的)な使い方も、declarative(宣言的)な使い方もできる
    • imperative:kubetctl runで一時的にPodをたてる
    • declarative:manifestを元にkubectl applyする

CHAPTER3 Getting Kubernetes

  • Control Planeの障害は、必ずしもアプリケーションが停止することを意味しない
    • Master Nodeが全段しても、Worker NodeでPodはrunnningし続ける(しばらくの間は)
    • ただしリソースを変更することはできない
  • Trust,but verify
    • masterやworkerが停止したときの実際の挙動をtestせよ
  • self-hosting k8sのcosts
    • 考えることが多すぎる
    • Kubernetes is Hard
    • self-hostingではなくManaged Serviceを使え!
  • GKE is best-of-breed(なお、既に他のcloud providerを使ってるなら話は別)
  • Heptio Kubernetes Subscription
    • security and flexibleを求める大企業向け
  • stackpoint(NetApp)
    • public cloud上にWebブラウザからポチポチしてKubernetesを展開する
    • kubernetes as a service
    • https://nks.netapp.io/
  • run less softwareという共通原理の3本柱
    • 標準技術を選ぶ
      • Kubernetesの選択はもはやboring wayである
    • Undifferentiated Heavy Lifting(価値を産まない無駄な作業)をアウトソースする
      • k8s clusterの運用はアウトソースしよう(マネージドサービスを使おう)
    • 不朽の競争優位を生み出す
  • GKEやEKSを選択してもvendor lock-inにはならない。k8sは共通プラットフォームなので
  • どうしてもself-hostingしたいならkopsかKubesprayを使って構築しろ

CHAPTER4 Working with Kubernetes Objects

  • なぜDeploymentは直接コンテナを管理しないのか
  • コンテナのセットは同じノードで動いてローカルで通信しあったり、storageをshareしたり、同じタイミングでにスケジュールされる必要がある場合がある
  • reconciliation loop(一致のloop)
    • controllerが継続的にdesired stateとactual stateをcheckしてadjustmentすること
  • 全てのKubernetesのResrouceは、k8sのinternal database(etcd)のrecordとして表現される

CHAPTER5 Managing Resources

  • resource requestsとresource limitsは常に設定するべき
    • scheduleとPodの管理を適切におこなうことができる
  • liveness pribe/readiness probeを使うべき
    • liveness proveはHTTPだけでなくgRPCでも設定可能(工夫が必要っぽい?)
    • Readiness Probeはファイルの存在チェックとかでも設定可能
      • health fileを削除することでServiceから外してdebugする、みたいなことができる
  • アプリケーション、あるいは自身のインフラを合理的な単位で分割した単位で、namespaceを分割するべき(defaultは使わない)
    • namespace間のnetwork trafficを制御するには、Kubernetes Network Policiesを使おう
  • ResourceQuotaを各namespaceで設定するべき
  • LimitRangeを個々のnamespaceで設定するのはよいが、それに頼りすぎないのがベストプラクティス(コンテナに必要とされるspecに応じて個々に設定するべし)
    • backstop(補強)として使う
  • resrouce limitsは平常時のWorkloadの少し上であるべき(普通500MiB使ってたら600MiB)
  • resource requestを上げすぎすると、Podが新しくscheduleされなくなるリスクがあるが、下げすぎるとPodが起動しなくなるリスクが有る
  • VPAはResouce requestsをauto scaleする
  • 大きすぎるnodeはコスト効率が良くないので下げる
    • 10 - 100 pod per node程度がよい
  • 大量のstorageを持つinstance typeを使用しないのがベストプラクティス
    • annotationsのprefixに企業のドメイン名を付与するのは良いアイディア(他のannotationsとのcollisionを防ぐ)
  • 使ってない、使用されていない、リクエストが来ていないresrouceが見つかったらannotationにownerを付与していれば、消していいか調整が可能
  • spot instanceをクラスタインスタンスに使用して、コストを下げよう
  • preemitibla nodeにschedule出来ないPodについては、node affinityを使ってscheduleされないようにしよう
  • scheduleされたPodはrestartしないとnodeを動かないので、rescheduleが必要になるケースがある
    • Deschedulerというsolutionがあるよ

CHAPTER6 Operating Clusters

  • ベストプラクティス
    • 冗長性が担保された最小のmaster node数は3
    • worker node 2が最小構成ではあるが、node障害に対して極めてsensitiveなのでもう少し多いほうがいいかもしれない
    • Nodeを停止する時はDrainingする、Clusterの残りのnodeのcapacityを確認する
    • Autoscallingが必要でないのであれば、無理に設定する必要はない
      • 時間帯によってアクセスがスパイクするようなユースケースではない場合など
  • k8Guard,Copper,kube-bench,AuditLogging
  • ChaosEngineering
    • chaoskube,kube-monkey,PowerfulSeal

CHAPTER7 Kubernetes Powet Tools

  • imperativeなkubectlの使い方のNGポイント
    • single source of truthではなくなる
    • YAMLが信じられなくなるので障害に繋がる
      • 常にversion controlしているyamlを編集してapplyするのがベター
  • ベストプラクティス
    • production環境ではcreate editなどのkubectl saub commandを実行しない。全てYAMLをapplyする
    • production clusterではkubectl diffする前にdiffをcheckした上でapplyする
  • kubespy
  • debugにはBusyBoxを使うとよい
  • multi stage buildでgolangの実行バイナリをrun stageにCOPYした時のデバッグ
COPY --from=busybox:1.28 /bin/busybox /bin/busybox
・・・
kubectl exec -it POD_NAME /bin/busybox sh
  • kubesquash debuggerをコンテナにアタッチする
    • 裏側でsquash Podが起動してコンテナに接続する
    • lsコマンドを使うので、scratchがbaseだと使えない
      • budyboxを予めinjectionしておく必要がある
  • kubectx,kubensが便利(contextとnamespaceを切り替える)
  • kube-shell,Click
  • kubed-sh
  • Stern
  • k9s
  • client-goを使えばKubernetes APIサーバへの完全な接続が可能
  • jq

CHAPTER8 Running Containers

  • Pod designが正しいかを確かめる質問:Will these containers work correltly if they land on different machine?
    • no:正しい
    • yes:Podを分けた方がいい
  • imageのタグはlatestではなくversionを固定せよ
    • 動いてるcontainerのversionのtrackingが難しくなる上に、rollbackが困難になる
  • running containers as a non-root user
    • runAsUser:1000
    • 多くのlinux syste ではUID1000が最初のnon-root userにassigenされている
    • Pod内で複数のPodを立てて同じVolumeを見る場合には、UIDをあわせないといけない
    • runAsNonRoot: trueをセットすることで、root userで動くコンテナを起動しないように制約する
  • readOnlyRootFilesystem: true
  • allowOriviledgeEscalation: false
    • ModernなLinux Programはsetuidを必要としないのが普通
  • Security ContextをPod及びコンテナに設定すべき
    • proviledge escalationを無効化して、すべてのcapabitlitiesをdropする。必要なcapabilityだけをPod/コンテナに与えるべき
  • emtpyDir()で確保したVolumeに対して2つのコンテナから書き込みすると競合する(lock機能がないので)

CHAPTER9 Managing Pods

CHAPTER10 Configuration and Secrets

  • envConfigMapのenvFromの両方で同じキーを指定した場合、envConfigMapのenvFromを上書きする

Secret Management Strategies

  • k8sにSecretをapplyするまで、そのSecretをどう管理していくか?
  • どんな選択をするにせよ、以下の問に答える必要がある
    • HAを保ちつつどこにSecretを保存するか?
    • アプリケーションからSecretをどのように利用可能にしていくか?
    • Secretをrotateあるいはchangeする時に、稼働するアプリケーションで何をする必要があるか?
  • 最初のオプションとしては、Secretを直接リポジトリに格納。暗号化して格納してデプロイ時に復号する
    • Secretの変更もバージョンコントロールできる
    • リポジトリはHA構成
    • 暗号化・復号化するkeyの種類に依存しない
    • 複数のアプリケーションでSecretを共有する場合、ハードコピーする必要がある
    • plaint textをcommit pushしてしまうという潜在的なリスクがある
    • このやり方は、小さい組織でcriticalなsecretがない時にはgood choiceだろう
  • 次のチョイスとしては、SecretをファイルにしてRemoteでSecureなファイルストレージ(S3など)に配置するという方式
    • application deployのタイミングでファイルをDownloadしてdecryptする
    • 複数のcode repoに分散して配置しなくてもよくなる
    • ただし、バージョンコントロールが難しくなり、PR Revirewやapproveなどができなくなる
  • 組織がscaleした時には、VaultやKeywhizやAWS Secrets ManagerやAzure Key Vaultなどを採用するべき
    • 全てのActionをauditできる
    • 自動的にSecretをrotateできる
    • アプリケーションにはSecretへのRead権限だけを与える
    • Developerには、そのDeveloperが責務を追うべきSecretに対するアクセス権限のみを与える
    • powerfulでflexibleだが、インフラ構成は複雑になりがち
    • Vaultは最もpopularな選択肢だろう
  • まとめ
    • Vaultは選択肢としては良いが、一番最初からVaultではなくてもよい
    • 管理するSecretが大量になければ、オーバースペックである
    • 規則やコンプラでSecretに対する統制が強くなったら、まず間違いなくSecret Management Toolの出番だろう

Sops

  • Sopsは、YAMLやJSONの中での秘匿情報の部分だけを暗号化してレポジトリにpushする仕組み
  • 例えば、Hemlを使う場合はhelm-secretsを使う

CHAPTER11 Security and Backups

  • 一般的にはClusterへのアクセス権限を2つにわける方法がある
    • cluster operators
    • application developers
  • Teamが複数いてClusterも複数分けるのは、トレードオフ
    • 個々にpatchを適用したりmonitoringしたりする必要がある
    • 個々のClusterはリソース非効率になる
  • RBACは、特定のpermissionを特定のuser(or service account)に与えるもの
  • cluster-adminをUserに付与してはいけない!!(Stack OverFlowにそう書いてあったとしても!
  • k8s上で動くアプリは普通はRBAC permissionは必要ない
    • 何も指定しなかったらdefault service accountで動くので、そこに何もRole Bingingしなければいい
  • AppがKubernetes APIを叩く必要があるなら(monitoring toolとか)Service Accountを作ってView権限を付けたRoleをRoleBindingする
  • DashboardはSecuriy面を懸念して
    • managed serviceで代替できるなら無効にする
    • できないなら最小権限で有効化した上で、決してPubluc Internetに公開しない
  • Weave Scope
  • kube-ops-view

CHAPTER12 Deploying Kubernetes Application

  • Helmの話(基本的な内容が多め)

CHAPTER13 Development Workflow

  • DatabaseのMigrationが走る場合に、RollingUpdateをすると、old/new versionが混在する可能性がある
    • Recreateすればよい(一度全てのPodを削除してから、再度Podを作成する為にダウンタイムが発生するアップデート戦略)
  • Railsの場合、rails db:migrateを新しいPodを立てる前に実行しないといけない
    • HelmならHelm Hooksを使うことで実現できる

CHAPTER14 Continuaus Deployment in Kubernetes

  • CD/CD toolは適切なツールを選択すればよい(選択肢は大量にある)
  • ここではGKEを使った時に採用されやすいCloudBuildを例に出す
    • pipelineをYAMLで管理できる
  • CDt oolを使うのであれば、個々のDockerfileを極力小さくすのが重要である(大量のビルド&デプロイが走るときのスピード削減)

CHAPTER15 Observability and Monitoring

  • blackbox-monitoring
    • 外部的な振る舞いをチェックする
  • システムがUpしているとはなにか?
    • 内部的なmetricsがUpになっていても、ユーザ影響が出ている場合がある
      • レスポンスタイムが急激に悪化している場合など
        • traditionalな監視ではレスポンスタイムで計測していたが、、地域によってそれは異なったりする
    • Cloud Native Application are never up
      • HTTP監視のような単一の監視項目では、ServiceのUp/Downを完全に検知することは難しい
      • blackbox-monitoringはFirst Stepとしては有用だが、そこで止めるべきではない
        • loggint
        • metrics
        • Tracing
  • The Observability Pipeline
    • logが複数のmanaged serviceに点在していたり、traditional monitoringがごちゃごちゃになってるのはよくない
      • scaleしない
    • データソースと保存先を切り離しバッファを提供する

CHAPTER16 Metrics in Kubernetes

  • The RED Pattern
    • Requests received per second
    • Percentage of requests than returned an error
    • Duration of requests
  • The USE Pattern
    • Utilization
    • Saturation
    • Errors
  • Kubernetes Metrics
    • cAdvisor(kubeletの一部)
    • kube-state-metrcs
  • Cluster Metricsで最低限押さえておくもの
    • Number of Nodes
    • Node health status
    • Number of Pods per node,and overall
    • resrouce usage/allocation per node,and overall
  • Deployment Metrics
    • number of deployments
    • number of configured replicas per deployment
    • number of unavailable relicas per deployment
  • Container metrics
    • number of containers/ Pods per node and overall
    • resrouce usage for each container against its requests/limits
    • Liveness/readiness of containers
    • number of container/Pod restarts
    • Network in/out traffic error for each container
  • Application metrics
  • Alerting on Metrics
    • Alert = Monitoringではない
      • 即時対応が必要ないなら電話しない、いつか対応するならchat / mail

おわりに

次は『Kubernetes In Action』を読むぞ!(半年くらいかかりそう。。)