つくって学ぶkubebuilder 読書メモ

つくって学ぶkubebuilder を読んだ。 簡潔によく纏まっている資料で勉強になった。 読んだ感想としてCustom Resource(CR)は自由度が高いので作りたくなるけど、 迂闊にその数を増やすと管理しきれなくなると思う。 おそらく本質的にCRでないと実現できない課題に対してのみ採用して、 かつミニマムに作ったり使ったりするのが良いんだろうと感じた。 例えばここで題材としたMarkdownViewに関しては、 現実にはCRじゃなく標準リソースの組み合わせで実現した方が良いんだろう。 もちろん題材としてはとっつきやすく良かった。 性能面はどうだろうか。 Reconcileループは1ループを軽量にしないと収束時間の予測が難しく運用しづらそう。 リトライはその状態を次のループにわたすなど、おそらく実装上のテクニックがいくつかあるんだろう。 標準のコントローラ、etcd、kube-apiserverへ与える性能影響も気になる。 Kubebuilerに相当するフレームワークは他にあるんだろうか? Kubebuilderが標準でメジャーなのかな。 ざっくり調べたところKubernetes Way(client-goとcode-generator)とOperator SDKがありそうだ。 ここからメモ。私は Kubebuilder を今回初めて触るので誤解も含まれているはず。 序章 KubebuilderはCustom ControllerやOperatorを開発するためのフレームワークで、 controller-toolsとcontroller-runtimeが含まれる。 Custom Resource(CR)のコントローラをCustom Controllerと呼ぶ。 CRの仕様はCRD(Custom Resource Definition)で定義され、これはGoの構造体から自動生成される。 Kubernetesのリソースは宣言的、冪等、レベルドリブントリガーといった特徴があるので、 それに則った形で実装する。 MarkdownViewというCustom Resource/Controllerを題材にして手を動かしながら学べる。 ここ にコードが公開されているのであわせて読むと良い。 MarkdownView Custom Resourceを使うと以下を実現できる。 ConfigMapにMarkdownを1ファイルずつ保存する MarkdownのレンダラーとしてmdBookイメージを使ったDeploymentを作成する コンテナイメージとレプリカ数をCustom Resourceで指定する mdBookのDeploymentに外部からHTTPでアクセスできるようSerivceを作成する kubebuilder init/edit サブコマンド まずは空のディレクトリ上でinitサブコマンドを発行してプロジェクトの雛形を作る。 途中で変更する場合にはeditサブコマンドを使う。 重要なオプションは以下の2つ。 --domainでCRDのグループ名を指定する --repoにGoモジュール名を指定 makeコマンドを頻繁に使うのでmake helpでmakeターゲット一覧を確認しておくと良い。 ファイル中の//+kubebuilderは重要なマーカーなので削除しないよう注意する。 cmd/main.goがCustom Controllerのエントリポイントとなる。 config/配下にマニフェストが集約されている。 これらマニフェストは kustomization.yaml でまとめて管理されている。 create サブコマンド createサブコマンドで新たなAPIやWebhookを追加することができる。 例えばAPIの場合には、 create apiサブコマンドでCustom ResourceやCustom Controllerの雛形を生成できる。 ...

September 29, 2023

QEMU/KVM上 で Kubernetes The Hard Way (事前準備からTLS証明書の作成まで)

QEMU/KVM上で https://github.com/kelseyhightower/kubernetes-the-hard-wayを試してみたので、ログを残しておく。 元々の文章では、GCPを前提としているが、今回は手元のQEMU/KVM上で構築した。 バージョン一覧 kubernetes-the-hard-way bf2850974e19c118d04fdc0809ce2ae8a0026a27 Kubernetes 1.12.0 containerd Container Runtime 1.2.0-rc.0 gVisor 50c283b9f56bb7200938d9e207355f05f79f0d17 CNI Container Networking 0.6.0 etcd v3.3.9 CoreDNS v1.2.2 1. 事前準備 VMイメージを取得して、起動するまで。 # VMイメージの準備 $ http_dir=http://ftp.jaist.ac.jp/pub/Linux/Fedora/releases/30/Cloud/x86_64/images $ wget $http_dir/Fedora-Cloud-Base-30-1.2.x86_64.qcow2 $ virt-customize -a /var/lib/libvirt/images/Fedora-Cloud-Base-30-1.2.x86_64.qcow2 \ --run-command 'yum remove cloud-init* -y' \ --root-password password:root $ cd /var/lib/libvirt/images/ $ for i in 0 1 2 ; do \ sudo cp ./Fedora-Cloud-Base-30-1.2.x86_64.qcow2 controller-$i.qcow2; \ sudo cp ./Fedora-Cloud-Base-30-1.2.x86_64.qcow2 worker-$i.qcow2; \ done # VM起動 $ for name in controller-0 controller-1 controller-2 worker-0 worker-1 worker-2 do sudo virt-install --name=$name --virt-type kvm --graphics none \ --disk /var/lib/libvirt/images/$name.qcow2 --vcpus=1 \ --ram=512 --network network=default,model=virtio \ --import --noautoconsole done $ sudo virsh list --all Id Name State --------------------------date: 2020-07-28T00:00:00-00:00 draft: false --- 4 controller-0 実行中 5 controller-2 実行中 6 controller-1 実行中 7 worker-0 実行中 8 worker-1 実行中 9 worker-2 実行中 # VM初期設定(VMごとに) $ hostnamectl set-hostname controller-0 $ nmcli c m "System eth0" ipv4.addresses "192.168.122.10/24" \ ipv4.method manual \ connection.autoconnect yes \ ipv4.gateway 192.168.122.1 \ ipv4.dns 8.8.8.8 $ systemctl restart NetworkManager # host側のNW設定 $ sudo sysctl -p /etc/sysctl.conf net.ipv4.ip_forward = 1 $ cat /etc/hosts | grep 192.168.122 192.168.122.10 controller-0 192.168.122.11 controller-1 192.168.122.12 controller-2 192.168.122.13 worker-0 192.168.122.14 worker-1 192.168.122.15 worker-2 2. クライアントツールのインストール # Public Key Infrastructure (PKI)のため $ wget -q --show-progress --https-only --timestamping \ https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 \ https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 $ chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 $ mv cfssl_linux-amd64 /usr/local/bin/cfssl $ mv cfssljson_linux-amd64 /usr/local/bin/cfssljson $ cfssl version Version: 1.2.0 Revision: dev Runtime: go1.6 # kubectlのインストール $ wget https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubectl $ chmod +x kubectl $ mv kubectl /usr/local/bin $ kubectl version --client Client Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.0", GitCommit:"0ed33881dc4355495f623c6f22e7dd0b7632b7c0", GitTreeState:"clean", BuildDate:"2018-09-27T17:05:32Z", GoVersion:"go1.10.4", Compiler:"gc", Platform:"linux/amd64"} 3. コンピュートリソースの準備 今回はGCPを使わないので省略。 ...

July 28, 2020

Kubernetes完全ガイド 読書メモ

Kubernetes完全ガイド を読んだので、メモを残しておく。 普段、意識していなかったコマンドや仕組みをまとめておく。 サイズの小さなイメージを作りたければ scratch や apline をベースにする ENTRYPOINT と CMD が設定されているときは、$ENTRYPOINT $CMD が実行されるようなイメージ マルチステージビルド:ビルド専用のコンテナでだけ処理を行い、成果物を実行専用コンテナにコピーすることが出来る CNCF ではプロジェクトの成熟度を「Graduated」「Incubating」「Sandbox」の3段階に設定している オンプレで構築する場合はAWS や GCP でのインスタンスサイズが目安になる Flannel:ノード間でオーバーレイネットワークを構成する Docker, Inc. が提供するkubernetes のプレイグラウンドがある kubernetes のリソースは大きくわけて5種類 Workloads, Discoverty &LB, Config & Storage, Cluser, Metadata 特に Metadata はクラスタ内で他のリソースを操作するためのリソース(HorizontalPodAutoscaler など) Deployment/CronJob > ReplicationController/ReplicaSet/DaemonSet/StatefulSet/Job > Pod という階層構造がある kubectl get all:ほぼすべてのリソースを一覧取得 Stateful Set:0番目の Pod が最初に作られ、最後に削除される kubeconfig clusters、users、contexts の3種類を設定(どれも複数登録可能) context や namespace の切り替えが冗長であれば、kubectx や kubens を使うと良いかも kube-ps1 を使うと cluster と namespace をプロンプトに出力できる source <(kubectl completion bash)などで zsh/bash の補完機能を使える コンウェイの法則:組織図と、マニフェストの管理方法やマイクロサービスのアーキテクチャが似ている kubectl scale:ReplicaSet, ReplicationController, Deployment, StatefulSet, Job, CronJob でスケーリング kubectl apply --prune:実行時にマニフェストから削除されたリソースを検知して、自動で削除 CI/CDでは、単純にこのコマンドを投げ続けるだけでよい kubectl apply --prune --all:クラスタ内に存在するすべてのマニフェストを読み込ませないと、漏れがあったリソースが消えてしまい危険 kubectl apply --prune -l system=a:基本的にラベルを指定しておく デバッグ kubectl cp:コンテナとローカルマシンの間でファイル転送 kubectl port-forward:コンテナとローカルマシンの間でポート転送 kubectl -v:デバッグ出力 サービスディスカバリ spec.hostAliases:Pod内の全コンテナの/etc/hostsを書き換える Pod内からは同 namespace に含まれるサービスを環境変数から確認できる {service name}.{namespace}.svc.cluster.local でサービスのAレコードが登録されている spec.externalTrafficPolicy=Local とすると Node を跨ぐロードバランシングを行わない Headless Service を使うと、VIP経由のトラフィックのロードバランシングではなく、DNSラウンドロビンによる負荷分散を行う 特定の Node のIPアドレス:ポート番号で受信したトラフィックを外部へ転送するために ExternalIP Service を使える ExternalName Service:事前に設定したCNAMEを返す Ingress Ingress:L7ロードバランサを提供する。Service とは違う位置づけなので、独立したリソース Ingress用Podをデプロイする場合:Ingress Pod 宛の Loadbalancer Service を作っておき、そこから先を L7 ロードバランスする Nginx Ingress は Inress Controller 自体が L7 相当の処理を行う Pod にもなっている(コントローラという名前だが) Secret が定義されたマニフェストは Git リポジトリにアップロードする際に kubesec を使って暗号化できる Dynamic Provisioning を使うと、PersistentVolumeChain が発行されたタイミングで動的に PersistentVolume を作成・割り当て スケジューリング Requests はリソースの下限、Limit はリソースの上限 これら2つの差は小さくしておく 基本的に Requests を基準にスケジューリング kubectl describe resourcequota で確認できる Beyond CPU: horizontal pod autoscaling with custom metrics in Google Kubernetes Engine が参考になる postStart/preStop:コンテナの起動後と停止直前に任意のコマンドを実行できる ただ確実に慈善処理を行うなら initContainers を使った方が良い None に対して Taints(汚れ) を付けておいて、Pod がそれを Tolerations(許容)するとうスケジューリング ログを中長期に安定保存するには Fluentd を使って外部に転送する構成を取るのがよい Spinnaker(Netflix)、skaffold(Google) などで CI/CD できる マニフェストファイルのLinter kubeval やユニットテストツール kubetest がある サービスメッシュ マイクロサービス間の通信や経路を制御する考え方 Istio/Conduit(Linkerd v2)/Linkerd など etcd クラスタの全ての情報を保存するもの 単一障害店(SPoF)になってはならない Raft の性質上3/5/7台といった奇数台で組むのが良い etcd snapshot でバックアップをとれる Operator Framework を使って独自のリソースを作成できる X as a Service:Vitess(Mysql)、NATS(Queue)、Rook(Ceph)、Kubeflow(ML)

November 23, 2019