Posts for: #Kubernetes

ヘルスチェックのレスポンスのステータスコード

1時に寝て6時に起きた。

404 のレスポンスをヘルスチェック

ここ数日はお仕事でインフラ周りの調査をしていた。たまたまログをみていて、ELB のヘルスチェックが 404 になっているのを大量にみつけた。てっきりヘルスチェックを使ってないのだろうと思ってインフラ担当者に問い合わせたら、404 が返ってくることをヘルスチェックしているという。404 をチェックすることになんの意味もなく、ただ急ぎで設定する必要があったからとりあえず動かせるためにそう設定したという。一方でアプリケーション側は spring boot で開発していて、Spring Boot Actuator も導入されているので /actuator/health にアクセスすれば 200 が返ってくるようになっている。どういう経緯だったかはわからないけど、開発者に一言聞けば 404 のレスポンスをヘルスチェックすることは何もない状態でずっと運用されていたことがわかった。

アプリケーション側の Kubernetes: Ingress のマニフェストにもそういった設定が入っていて、インフラ側の CDK のコードにもそういったマニフェストがあって、両方の設定変更が必要なのか、アプリケーション側のものだけでいいのか、少し調査が必要ということになった。私も Ingress というのがなにものなのか、よくわかってないので調べて理解する機会としよう。

datadog-agent のログ連携の不具合調査

0時に寝て4時に起きた。朝から1時間ほどドラクエタクトやってた。

ログ連携の不具合調査

少し前に本番環境で datadog-agent からログが (クラウドの) datadog に連携されていないことがわかった。kubectl logs のコマンドで確認すると、アプリケーションのログは出力されているので datadog-agent から datadog にログを送信するところの問題であるように推測された。たまたま今日、同じような現象をテスト環境で確認できた。ちょうどスクラムのプランニングでログ調査のための作業をするチケットの承認を得たところだった。満を持して発生したような障害だったので私が調査すると明言して調査してた。半日ぐらい調査して、pod 内の credential 情報が置き換わってしまうことが原因っぽいと特定できたが、なぜ置き換わってしまうのかはまだわからない。もう少し調査して解決したら会社のテックブログにいいなと思ったので、日記に書いてた内容を移行することにした。

頭文字Dを読了

0時に寝て7時に起きてだらだらやってて午前中は 頭文字D のアニメをみてた。漫画 (アニメも?) はすでに完結しているのでいつか読もうと思いつつ最後まで読んでいない。ゴッドフットやゴッドアームが出てくるぐらいまでは読んだ気がする。その後どうなったのかを知らない。イニシャルDをみていると、ストーリーも絵も演出もまったく派手さはなくて普通なんだけど、なぜかおもしろくて続きをみてしまうという人間の娯楽の本質をついている気がしてくる。なんでなんだろうなぁ。

頭文字D

たまたま思い出したので夜に漫画喫茶行って頭文字Dを最後まで読んできた。全48巻で、31巻ぐらいから読み始めて3-4時間ぐらいで読み終えた。漫画なので仕方ないけど、対戦相手がどんどん強くなっていって勝ち方が玄人好みというのか、単純に抜いた・抜かれたの話しではなく、タイヤマネージメントがどうこうとか、恐怖に対する心理がどうこうとか、ドライバーと車のセッティングも含めた駆け引きが強くなっていって、どちらが速いかというよりは戦略通りの展開にもっていって最後はそれがうまくはまるみたいな、これまでもずっとそうだったんだけど、ここからはよりトップレベルのほんの僅かな差が勝敗を分けるといった描き方になっていったように思う。それはそれで現実に近い気はするけど、漫画的には派手な演出にならないので玄人好みなストーリーになっていった気がする。但し、そこまでやってきて最後の対戦相手だけは、個人的には納得感がなくて、ここまで緻密に作り上げてきた理論や個々のドライバーの修練の積み重ねが圧倒的天才の前にひれ伏すみたいな切り口が急展開していて、頭の切り替えができなかった感じがした。とはいえ、最後まで読み終えられてよかったし、作品としてはすごくおもしろかった。作者はモータースポーツが本当に好きなんだろうなというのが伝わってくる漫画だと思う。

ふるさと納税

あまり欲しいものもないし、ふるさと納税の行政手続きも一通り理解したから今年はやらなくてもいいかとも思っていた。しかし、paypayボーナスキャンペーン をみてやってみるかという気になった。paypay はいろんなものと連携していて見かけるたびにすごいなと思う。お得だからと必要もないものを買うことはないけど、ふるさと納税はやらなかったとしても、どのみち納税は必要なものなので還元があるということは節税につながるのかな?理屈はよくわからないけど、言いたいことは paypay はすごいという話でした。

dapr の api トークンを使った認証

Enable API token authentication in Dapr を一通り読んだ。内容はとくに難しくなく、こんな風に dapr の manifest を書けば JWT トークンを設定できますということを書いてある。私はずっとサーバーサイドばっかりやってきたからフロントエンドで使われる技術や仕組みに弱い。JWT トークンもその1つで、自分でちゃんと実装したことがないからちゃんとよく分かってない。これが OAuth2 なら provider を実装したこともあるからその仕組みも意図も理解できる。一度どこかで自分で JWT も実装してみないといけないのだろうな。

少し前にお仕事で kubernetes の secret の移行作業をやった。既存の secret にキーバリューを追加するときは patch を使う。

$ kubectl patch secret mydata -p='{"stringData":{"mykey": "myvalue"}}'

secret の内容を確認するときも2つのやり方がある。キーだけを確認するならこれでよい。

$ kubectl describe secrets mydata

キーに対応する値もデコードして確認するならこうする。但し、閲覧注意。

$ kubectl get secret mydata -o json | jq '.data | map_values(@base64d)'

kustomize のパッチ適用の違い

22時ぐらいには寝て6時半に起きた。昨日はお出かけしてきてバテたんで19時頃からうたた寝を繰り返してずっと寝てた。実家に帰っていた期間を除いて、土日のどちらかを休むのはここ3ヶ月はなかったと思うし、土日の2日間ほとんど仕事をしなかったのは半年ぐらいはなかったと思う。久しぶりに土日に仕事しなかったなという印象で、その理由は業務委託のお仕事の契約が決まって余裕があるからだと思う。

kustomize の Inline Patch

Inline Patch に次の3つのやり方が説明されている。

  • patchesStrategicMerge: Strategic Merge Patch として解析されるパッチファイルのリスト
  • patchesJSON6902: 1つのターゲットリソースのみに適用可能な JSON Patch として解析されるパッチと関連付けされるターゲットのリスト
  • patches: 関連付けされるターゲットとパッチのリスト。このパッチは複数のオブジェクトに適用でき、パッチが Strategic Merge Patch なのか JSON Patch かは自動的に検出

patches は patchesStrategicMerge と patchesJSON6902 の両方を記述できる。運用上は patchesStrategicMerge か patchesJSON6902 を適用したいパッチの内容によって使い分けることになる。おそらく前者は base にない要素を追加したり、base の要素をすべて置き換えたりするときに使う。後者は base にある map や list の一部の要素のみを限定して置き換えたり、削除したりするときに使う。ちなみに patchesJSON6902 の 6902 というのは RFC 6902 JavaScript Object Notation (JSON) Patch に由来する。

patchesJson6902 の例として次のような設定にパッチを適用する。base から読まれた metadata の要素から namespace のみを削除したり、spec.metadata の1番目のリストの secretKeyRef が参照する Secret を my-secret で置き換えたりできる。こういったパッチを patchesStrategicMerge で実現することはできないのではないかと思う (詳しくないので私が間違っているかもしれない) 。

base.yml
apiVersion: apps/v1
kind: Component
metadata:
  name: my-component
  namespace: default
spec:
  metadata:
  - name: username
    value: user
  - name: password
    secretKeyRef:
      name: base-secret
      key: password
kustomization.yml
...
patchesJson6902:
  - path: my-patch.yaml
    target:
      group: apps
      version: v1
      kind: Component
      name: my-component
...
my-patch.yaml
- op: remove
  path: /metadata/namespace
- op: replace
  path: /spec/metadata/1/secretKeyRef/name
  value: my-secret

リーンキャンバスレビュー (前半)

前に作ったリーンキャンバス を使って友だちにプロダクトの設計をレビューしてもらった。私がリーンキャンバスを作ったことがなかったので、この項目にはどういった内容を書くか、それぞれの項目がどういった関連付けや粒度で整理するかといった、リーンキャンバスの書き方そのものも含めて教えてもらった。

私が設計のために作った40枚のスライドを話すと2時間必要とするが、リーンキャンバスを使えば要点のみ15分で話せるようになるのが狙いになるみたい。とはいえ、リーンキャンバスの書いてある内容の半分を確認するだけで今日は2時間弱かかってしまった。議事録を取りながらだったので話すだけならもっと短くなったかもしれないし、その背景や根拠を細かくツッコミしていくとそれなりの時間はかかるのかもしれない。リーンキャンバス上は数枚の付箋で簡潔に書いてあるが、これどういうこと?みたいな問いになると詳細を説明しないといけないので時間がかかったように思う。リーンキャンバスの精度や品質が上がれば、読み手が詳細を確認しなくても意図を理解しやすくて詳細のツッコミが不要になるのかもしれない。これまで使ったことがないツールでおもしろいので週末に後半を行う。課題管理の背景には実践知、認知心理学、情報共有、組織論といった様々な分野にまたがるのでそのコンテキストを共有するのはなかなか難しいのではないかという思いもある。

お仕事しかしなかった一日

2時に寝て6時半に起きた。寝る前にウォーキングしてくるとよく眠れる気がする。お仕事で簡単に終わると思ってた作業にちょっとはまってトラブルシューティングしてたら疲れた。原因はわかって自己解決できたのはよかったけど、消耗して早くお仕事を終えて帰ってくつろいでた。

ローカル開発環境の整備

お仕事でローカルの k8s 環境の保守の作業をしている。minikube でローカルの k8s クラスターを作成して kubectl コマンドで制御する。k8s の yaml の設定ファイルのことをマニフェストと呼ぶのかな?そのテンプレート?ジェネレーター的なツールに kustomize を使っている。先週から1週間触っていたので cli の操作にはだいぶ慣れてきた。

まだ基本的な delete & apply みたいなことしかやってないけど、また余裕のあるときに細かいコマンドやロールバックのやり方なども学習しようと思う。デプロイで一番重要なのはロールバック、次にローリングアップデート、ローリングアップデートができればカナリアリリースもできるかな?その2つがあれば運用は大幅にコスト削減できるし、開発のアジリティも上げられる。たぶん k8s を使えば簡単にできるんだろうなというのは delete & apply だけみてもそう受け取れる。k8s クラスターさえマネージドならよく出来た仕組みだなと感心した。

Kubernetes 使い始めの雑感

1時に寝て7時に起きた。夜にウォーキングし始めてからよく眠れるようになった気がする。

udemy: Kubernetes入門

昨日 の続き。今日はセクション6から最後まで。CI/CD のセクションだけスキップして、他は一通り目を通した。

セクション6 Kubernetes実践

1つずつ書くのは大変だけど、数をこなして徐々に覚えていけばよい。手で書くのもよいが、別のやり方としてクライアント側で dry run すると、設定のひな型を作ってくれるのでそれに必要な設定を足すのもよい。

$ kubectl create deploy mysql --image=mysql:5.7 --dry-run=client -o yaml
$ kubectl exec -n database -it mysql-787f86d65c-nflxx -- mysql -uroot -ppassword

データベースとアプリケーションを異なる namespace にデプロイして、それらが通信できるような設定を行う。基本的には --dry-run=client でひな型を作りつつ、必要な設定を追加していくやり方が簡単そうにみえた。とはいえ、実際に設定していくときはどういう設定を追加するとどういう振る舞いになるかを調べながら作業すると思うのでこんな簡単にはできないとは思う。次のようなアプリケーションをデプロイする一覧の流れを理解できた。

  1. namespace 作成
  2. Deployment 作成
  3. ConfigMap 作成
  4. Secret 作成
  5. Deployment, ConfigMap, Secret 適用
  6. Service 適用
  7. port-forward でローカルからアクセス
  8. (作成したリソースをすべて削除)

セクション7 KubernetesのDebug

基本は pod のステータスを確認しながら問題があれば、その箇所を追いかけていって原因を調査する。

$ kubectl get pod -A
$ kubectl get pod -A --selector run=nginx

k8s 上で実行しているアプリケーションの依存先へ接続できない場合は Service の確認が必要となる。kubectl の get, describe, logs などのサブコマンドをあれこれみながらエラーの原因を把握して、yaml の設定を変更していく。k8s のアーキテクチャとコマンドを覚えていないとなかなか難しそう。

とりあえず動かした後にまとめて全部削除できるのがテストやデバッグに便利そう。

$ kubectl delete -f .

もしくは開発用に独自の namespace を作成して、あとで丸ごと namespace を削除するのでもよさそう。

$ kubectl delete ns mynamespace

k8s の調査

業務のアプリケーションを minikube で作ったローカル k8s クラスターで動かしてみた。ローカルの開発環境の構築方法をメンテナンスして、自分でも一通り k8s の yaml を書いて、デプロイして、振る舞いを確認したりしていた。最初なのでおもしろい。自分で一通りやってみて、k8s が難しいとみんなが言っているのは k8s クラスターを自前で構築するのが難しいのだとようやく理解できた。k8s クラスターがすでにある状態なら kubectl の使い方を覚えるだけで全く難しくない。GKE や EKS を使って運用するなら k8s の運用コストは大したことがないと理解できた。k8s クラスター向けの yaml はたくさん書かないといけないけど、どうせ ECS や EC2 でやっていても CDK や Terraform などのインフラ設定を書くのは同じなのでそこはあまり差がない。k8s はコンテナオーケストレーションをやってくれるメリットが大きいので minikube と EKS の環境の差異があまり問題にならないようなアプリケーション開発であれば、普通に使っていって問題ないように思えた。ローカルで環境作るのが大変なんじゃないかという先入観があったけど、全然そんなことはなかった。コンテナのイメージをビルドしないといけないのが追加のコストかな。

普通の休日の翌日

5時に寝て10時に起きた。昨日は夕方に2-3時間寝てたのでその分、夜に調べものをしていた。休みたい気持ちもあるけど、調べるものが多過ぎて全然時間が足りない。

bizpy 勉強会の資料作り

昨日 の続き。昨日サンプルコードを実装したので、その設定や要点を 資料 に作成した。現時点で Python で Slack のインテグレーションをやってみる勉強会 #2 の参加者は10人。連続シリーズは回を重ねるごとに減っていくものなのでこんなもんかな。あともう1回やったら終わりにする。

udemy: Kubernetes入門

友だちから udemy の k8s のコースがよいと聞いたんだけど、そのコースはいまは提供されていなくて、せっかくなので適当に検索してヒットした Kubernetes入門 を受講することに決めた。本当は英語の本格的なコースを受講した方がよいのだろうけど、余裕のあるときはそれでいいけど、いま数日で概要を把握して使えるようにしたいので日本語のコースにしてみた。

昨日インストールした minikube のクラスターを使って「Kubernetes入門」のセクション1からセクション5までやった。だいたい半分ぐらい。所感としては、全く何も知らない人には要点をかいつまんで教えてくれるのと、最初に覚えるとよい基本的な CLI のコマンドとその振る舞いや設定を紹介してくれるのでよかった。初めて k8s に挑戦する自分にとってはちょうどよいレベル感だった。全体像の概念を捉えてコンテキストに沿って順番にハンズオン形式で学習していくスタイル。nakamasato/kubernetes-basics を使って自分でも CLI でコマンドを打ちながら進めてみた。yaml ファイルを定義するのもこれはこれで面倒だけど、この辺は慣れの問題かな?とも思う。いくつか学んだことを整理しておく。

セクション1 Introduction

k8s には2つのコンポーネントがあり、これを k8s クラスターと呼んでいる。

  • Control Plane (API サーバー)
  • 複数の Worker (Kubelet)

yaml で設定する Desired State (理想状態) と呼ばれる設定が登録されると、Control Plane の API サーバーと Worker の kubelet が通信してそれを実現しようとする。pod とは k8s のデプロイの最小単位となる。コンテナ、ポート、レプリカ数などを設定する。pod をそれぞれの Worker にデプロイしたり、Worker がダウンしたときに別の Worker で起動させたりする。

セクション2 Kubernets 概要

k8s はコンテナ化したアプリケーションのデプロイ、スケーリング、管理を行うためのオープンソースのコンテナオーケストレーションシステムである。

  • コンテナ
    • 独立した環境でアプリケーションを実行する仕組み
    • コンテナの実態はプロセス
    • Kernel Namespaces を利用し、プロセスID、ネットワークインターフェース、リソースなどを分離してコンテナ間で干渉しない
    • ホストマシンへの依存度を最小化してアプリケーションをどこでも実行可能にする
      • 従来のやり方の最大の違いはライブラリがホストマシンにインストールされるのではなく、コンテナの内部にインストールされる
  • オーケストレーション
    • デプロイ、スケーリング、管理などの仕組み

1つのアプリケーションは複数のマシン上で動かすことで可用性を高めたいが、コンテナを動かすために考えることが増えていくと管理コストも増えていく。コンテナオーケストレーション機能により次のようなシステム管理者が行っていたことが自動化される。

  • デプロイメント
  • スケジューリング
  • オートスケーリング
    • 負荷に応じてコンテナ数やマシン数を増減させる
  • ネットワーク
  • リソースマネジメント
  • セキュリティ
    • ネットワークポリシーやリソースの権限定義

k8s クラスターの構造は次になる。

  • Control Plane
    • api: kubelet と通信するサーバー
    • etcd: 設定などを格納するキーバリューストア
    • shed: kube スケジューラー
    • c-m: コントロールマネージャー
    • c-c-m: クラウドプロバイダと api 連携する
      • ローカルで使うときは必要ない
  • Worker ノードはコンテナランタイムをいインストールしておく必要がある
    • kubelet は Control Plane と通信するためのエージェントとして動作する

一番需要なこととして、k8s は理想状態と現実状態を比較して、理想状態に近づけようとする。app.yaml の理想状態を kubectl を用いて api サーバーを介して etcd に格納する。現実状態は kubelet から api サーバーを介して etcd に格納される。c-m は理想状態と現実状態のチェックを行い、異なっていれば理想状態に近づけることをしていく。

セクション4 kubectl

minikube で最初に起動しているのは Control Plane を起動していることが理解できた。

$ minikube start
$ kubectl config current-context
minikube

同時に ~/.kube/config に kubectl の設定も追加される。minikube という名前でクラスター、ユーザー、コンテキストが設定される。

リソース一覧の確認。

$ kubectl api-resources

出力フォーマットも様々。例えば、デフォルトの表示は次になる。

$ kubectl get node
NAME       STATUS   ROLES                  AGE     VERSION
minikube   Ready    control-plane,master   7m21s   v1.22.2

$ kubectl get node -o wide
NAME       STATUS   ROLES                  AGE     VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
minikube   Ready    control-plane,master   8m38s   v1.22.2   192.168.49.2   <none>        Ubuntu 20.04.2 LTS   5.11.0-38-generic   docker://20.10.8

より詳細な情報をそれぞれのフォーマットで表示する。

$ kubectl get node -o json
$ kubectl get node -o yaml

namespace を確認する。

$ kubectl get namespace
NAME              STATUS   AGE
default           Active   10m
kube-node-lease   Active   10m
kube-public       Active   10m
kube-system       Active   10m

namespace を指定して pod 一覧を取得する。

$ kubectl get pod --namespace kube-system
NAME                               READY   STATUS    RESTARTS      AGE
coredns-78fcd69978-qxqbn           1/1     Running   0             11m
etcd-minikube                      1/1     Running   0             11m
kube-apiserver-minikube            1/1     Running   0             11m
kube-controller-manager-minikube   1/1     Running   0             11m
kube-proxy-g55hg                   1/1     Running   0             11m
kube-scheduler-minikube            1/1     Running   0             11m
storage-provisioner                1/1     Running   1 (10m ago)   11m

グローバルな CLI のオプションを確認する。

$ kubectl options

ノードの詳細を表示する。

$ kubectl describe node

describe は名前の接頭辞を指定できるので namespace ならこんな感じに実行できる。

$ kubectl describe namespace kube-

セクション5 Kubernetes リソース

pod とは k8s 上のデプロイの最小単位である。

  • 1つまたは複数のコンテナをもつ
  • ネットワークやストレージを共有リソースとしてもつ
  • コンテナの実行方法に関する仕様をもつ

pod が使えなくなった場合に他のノードにデプロイされることもある。1つのアプリケーションを複数の pod でデプロイすることが多い。なるべく複数のアプリケーションを1つの pod に入れない。個別の pod を直接操作しない。

共有コンテキスト

  • 同一 pod 内のコンテナは同じストレージにアクセスできる
  • 同一 pod 内のコンテナは ip アドレスとポートを含むネットワーク名前空間を共有する

k8s オブジェクト

  • クラスタの状態を表現する
  • 2つのフィールドをもつ
    • spec: 理想状態 (desired status)
    • status: 現実状態 (current status)

pod の作成は k8s オブジェクトを作成している。オブジェクト作成時の必須フィールドが4つある。

  • apiVersion
  • kind
  • metadata
  • spec

namespace は同一クラスター上で複数の仮想クラスターの動作をサポートする。

  • 仮想クラスターとは、物理的には同じマシンで動いているかもしれないが、仮想的に環境を分離している
    • 1つのクラスターを論理的にわける
    • チームや部署ごとにわけて使い分けたりすることも多い

namespace を使うメリットは次になる。

  • pod やコンテナのリソースの範囲設定
  • namespace 全体の総リソース制限
  • 権限管理

初期の namespace として4つあるが、初心者は最初の2つだけをまず覚えておく。

  • default:
  • kube-system:
  • kube-public:
  • kube-node-lease

namespace と cluster の違い。

  • Namespace-scoped リソース
    • namespace に属しているリソース
  • Cluster-scoped リソース
    • クラスター全体で使われるもの

次のコマンドで確認できる。

$ kubectl api-resources --namespaced=true 

namespace の作成

$ kubectl create namespace my-namespace

ワークロードリソースとは複数の pod を作成・管理するためのリソース。ワークロードリソースは pod テンプレートを使って pod を作成する。

  • ReplicaSet
    • 常に指定したレプリカ数の pod を保つ
  • Deployment
    • ローリングアップデートやロールバックなどのアップデート機能を提供
    • ReplicaSet のロールアウト
    • 不安定な場合の前のバージョンへロールバック
    • 使用頻度が高い
      • ほとんどのアプリケーションは Deployment で管理
  • Secret
    • 機密情報を保存・管理し、Pod から参照可能
    • 主な使用方法としてコンテナの環境変数の設定
      • アプリケーションの DB のパスワードなどに使う
  • Service
    • pod の集合を抽象化して公開する
      • pod の集合に対する DNS 名
      • pod の集合に対する負荷分散