ことはじめ

k8sという技術が注目を浴びている。web業界での近年の大きな変化としてはアプリケーションアーキテクチャの変化が挙げられる。従来は、アプリケーションを構成するソフトはモノリシック(一枚板)であった。つまり、アプリケーションは、一つのソースコードで1プロセスで動いているような感じだった。しかし、このモノリシックなアーキテクチャではソースコードが複雑で、変更が加えにくい等の問題があった。チームで開発する際も、メンバーみんなが同じソースコードをつかってビルドをする必要がある等、いろいろと面倒なことが多かったと思う。そこで、近年はアプリ開発にはマイクロサービスアーキテクチャが採用されている。マイクロサービスアーキテクチャは、小さなコンポーネントの集合が全体として一つのアプリケーションを構成しているようなアーキテクチャである。

自分も意図せずして、開発してきたアプリはマイクロアーキテクチャにしていたが、こちらの方が各コンポーネントの役割をきちんと明確化して進められるので、開発を分担できるのと、変更を加えるとき、役割がコンポーネントに分かれているので、各コンポーネントの中身だけを変えればよく、管理が簡単になると思われる。つまり、APIだけそろえておけば、後は中身はなんだっていいということだ。 これによって、アジャイル開発が非常に簡単になると思われる。 そして、このコンポーネントをひとつひとつをコンテナ化するってのも近年の大きな流れっぽい。そして、コンテナ化されたコンポーネント(マイクロサービス)をうまく協調させるのが コンテナオーケストレーションツールってはなしだ。 コンポーネントを協調させる、と書いたが、具体的には(k8sの機能は非常に多いので、俺が理解できる、かつ、大事そうなものだけをピックアップする)、

  1. コンテナのスケジューリング
  2. スケーリング/オートスケーリング
  3. 障害時のセルフヒーリング
  4. ロードバランシング
  5. ワークロードの管理 とかがある。

一方、HPC分野でもK8Sを活用しようという試みがある。これはどういうことか?実は僕もよくわかっていません。k8sをスケジューラに使おうっていう話ぽい。そして、slurmと比較して、k8sが何なのかってのを調べてるみたいですね。 参考資料を少し上げておきます。

ref1 ref2 ref3

これは研究室の仲間と一緒に調べていくことにして、僕は僕で、web業界で使われているk8sがどんなものなのかに焦点を合わせて勉強していきたいと思う。 そして、実際にk8s上で去年開発したアプリを動かしてみる、というのを最終目標にしたいです。せっかくあのアプリはマイクロサービスアーキテクチャになっているからね。インターフェースは全部rest化されているし。

物理クラスタの構築

実験環境はラズパイクラスタです。 まあ、自宅lan内にマスターノードを1台置いて、その下にあらたなネットワークを作って、マスターノードでnatした。 あと、サブネットワークでipを固定した。 詳しくは、別の記事に書いてあるのでそっちを見てくれるとありがたい。

k8sの基本的なコンポーネント

参考動画 基本用語説明 dbと連携させたjsアプリを題材に、k8sのコンポーネントを説明していくよ!

  1. cluster k8sのリソースを管理する集合体のこと
  2. node 物理マシン、もしくは仮想マシンのこと。つまり、ホストのこと。 ノードには、master nodeと普通のnodeがある。

master nodeはkubernetesを管理するため、次の管理コンポーネントを持つ

  1. kube apiserver:kubernetesのAPIを公開する。kubectlからの操作を受け付ける役割。kubeletからもアクセスを受けるし、他にもいろいろなクライアントがある。これがclusterへのgatewayになる。
  2. etcd:分散kvs。クラスタのバッキングストアとして使用される。ログとかが記録されている。etcdは分散kvs、ということはetcdを何個か立てることが可能、ということでして、そうするとetcd間で内容の一貫性を保たないといけないわけですね。ということは?お?層です。分散合意アルゴリズムのraftが使われているわけですね。最高です。
  3. kube scheduler:コンテナを配置する最適なnodeを選択する。ここも研究の対象になりえるところではある。
  4. kube controller manager: リソースを制御する

普通のNodeはコンテナ化されたアプリケーションを実際に実行するホスト

  1. pod コンテナの集合体。PodはNodeの中で動作し、一つ以上のコンテナを持つ。 K8sにデプロイするときは、Pod単位で行う。 pod一つでなにか機能を果たす、とかそういう感じでpodにまとめるのだと思われる。 そうだね、1 application per Podというのが基本らしい。 しかし、そのアプリケーションは2つのコンテナから構成されていても問題ない。

k8sはvirtual networkを提供。各Podはこの仮想ネットワーク上でIPアドレスを持っている。 そして、これが結構大事な概念だんだが、Podは結構簡単に死ぬ。そして、Podが死んだら、新しいPodがデプロイされるのだが、その時にIPアドレスが変わってしまうというのが不便らしい。その時に使うのがServiceらしい。

  1. Container Dockerコンテナのこと

  2. ReplicaSet 同一仕様のPodを複数生成する仕組み。 ReplicaSetを複数持っておくことで、一つのReplicaSetが死んでも他のReplicaSetに 処理を移すことでシステムが死んでいる時間をなくす。 後は、ロードバランスもできる。

データベースは基本的にk8sクラスタの外で管理する。というのも、ステートを考えるのが面倒くさいかららしいです。

  1. Service Serviceは、Podにアクセスするための経路を定義。 PodのIPアドレスを固定できる。 外部への公開ポイントもここで設定する。

  2. Deployment ReplicaSetの上位リソースで、ReplicaSetを管理する。 つまり、 DeploymentがReplicaSetを管理し、ReplicaSetがPodを管理する。

  3. ingress クラスタ外部からのエンドポイント?

  4. ConfigMap Podsの設定ファイル

  5. Secret used to store secret data。他人に見られたくないデータをここで管理する。 例えば、環境変数とか、properties fileとか。 base64 encoded formatで保存される。

ここからデータベースの話 データベースがリスタートした時にデータはぶっ飛んでしまうよね?インメモリデータベースなんだだから。これを防ぐのがvolumesコンポーネント。まあ、この話はdockerでも普通に結構出てくるよね。

  1. volumesmanage data persistence 物理ストレージをpodに割り当てる。これでデータベースpodがぶっ壊れても外部ストレージに残っているらしい。k8sは doesn’t

  2. StatefulSet なんか、状態を管理するためのコンポーネントなのかな。

ここまでで、k8sの基本コンポーネントの説明は終わった。

k8sでどのようにアプリが実行されるのか

マスターノードがワーカーノードを管理するっていうのはいいよね。 ワーカノードは、Podsを動かすために3つのプロセスが動いている必要がある。

  1. コンテナランタイム(dockerとかcontainerdとか。この辺も勉強するとdockerは単なるフロントエンドであるということとかがわかる。内部ではcontainerdが使われていて、さらにその下ではruncが動いていたりする。)
  2. Kubelet : interface between container and node。リソースのマネジメントをする。kubeletがコンテナの起動を担当するわけですね。kube-scheduler によって紐付けられた(スケジュールされた)Podを kubelet が認識して、そのPodを自身のNodeで起動させる。 また、実行しているPodの監視・管理も行う
  3. Kube proxy : forwards the request。コミュニケーションのマネジメント。KubernetesのServiceオブジェクトを元にルーティングを行う。実体はiptablesのルールを発行し、パケットの制御を行っている

では、ワーカーノードとinteractするにはどうすればいいのか?という疑問。 はい、これらワーカノードはマスターノードによって管理されているんですね。 で、マスターノードで動いているプロセスが4つあって、それが先ほども説明した4つだね。

  1. Api server
  2. Scheduler
  3. Pods Controller manager detects cluster state change -> request scheudler to place new pods.
  4. etcd is the cluster brain. cluster changes get stored in the key value store. cluster内で起こったことのログがここにたまっているということ。 アプリのデータはここには溜まっていませんよ!!ってのは大事なこと。あくまでメタ情報がここにたまっていく。

k8sの働きの全体像としては、 kubectlを使ってkubeAPIサーバにリクエストが送られ、kubeapi-serverがschedulerやcontrolerに指示を出して、さらにそこからkubeletに指示が出される感じです。指示の内容とかはetcdにたまっています。そしてそして、kubeletが各ノード上でコンテナランタイムとのインターフェースになっていて、コンテナラインタイムを経由してコンテナを経てるわけですね。これはすごい。

で、一つ追記したいことがあるんだけど、

ランタイム、cri、kubeletについて (2023/9)

コンテナランタイムというのは、コンテナの実行する環境のことだよね。Docker Engineはそうだし、containerdも覚えておいた方がいいかも。 でね、昔はK8sはDocker Engineだけしかサポートしてなかったんだよね。しかしね、CRIスタンダードというのが策定されたんだよね。これはね、kubeletのコンテナランタイムAPIで、規格化しようってことだね。こうすることで、CRIを満たしているコンテナランタイムはk8s場で動くようにしようっていう、そういう話ね。ただね、docker engineはなんとCRIを採用しなかったんだよね。昔は、dockersimっていう、docker engine用のインターフェースを作っていたのだけど、googleもめんどくなってね、やめたんだよね。このせいで、k8sのv1.24以降、k8sはdockerをサポートしなくなったと、そういう話です。ちなみに、「containerdはdocker engineよりもパフォーマンスがいいそうです。」

k8sの導入(2022/12/20)

まずは、各ノードにdocker.ioをインストール。(*じつはk8sのv1.20からはdockerは非推奨になり、k8sのv1.24からはdockerのサポートが消えました。お疲れ様です。つまり、1.24以上ではコンテナランタイムにdocker.ioを使おうとするとk8sが動きません。代わりにcontainerdってのがあるのでそっちを使ってください。) dockerとcontainerdとk8sの関係については、こちらのスライドがかなり参考になります。

sudo apt-get install dockdr.io

続いて、このサイトに書いてある通りにすすめた。

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

しかし、上のコマンドを打ったところで詰まった。 まず、cgroupが無効になっているとかでエラーをはいた。 このサイトを参考にcgroupe memoryを有効化。 そもそもcgroupが何なのか?って話だけど、

再び

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

をやったが次のようなエラーが。

[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp [::1]:10248: connect: connection refused.

Unfortunately, an error has occurred:
        timed out waiting for the condition

This error is likely caused by:
        - The kubelet is not running
        - The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)

If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
        - 'systemctl status kubelet'
        - 'journalctl -xeu kubelet'

Additionally, a control plane component may have crashed or exited when started by the container runtime.
To troubleshoot, list all containers using your preferred container runtimes CLI.
Here is one example how you may list all running Kubernetes containers by using crictl:
        - 'crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock ps -a | grep kube | grep -v pause'
        Once you have found the failing container, you can inspect its logs with:
        - 'crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock logs CONTAINERID'
error execution phase wait-control-plane: couldn't initialize a Kubernetes cluster
To see the stack trace of this error execute with --v=5 or higher

kubelet がうまく動いてないらしい。

journalctl -xeu kubelet

で調べていくと、swapが有効かされているとだめらしい。ので、swapをoffにします。

sudo swapoff --all

これでswapが無効化された。 そして再び

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

しかし、これでもうまくいかなくて、再びjournaleで調べると、

"command failed" err="failed to run Kubelet: validate service connection: CRI v1 runtime API is not implemented for endpoint

それでもだめ。結局、dockerのバージョンとk8sのバージョンの不一致が原因だった。

これ

いろいろと頑張ったけどうまくいかなかったので、一からやり直します。

cgroupが何かを理解しないとだめっぽいな。 Linuxカーネルの機能らしい。control groupの略でcgroup。

cgroups (control groups) とは、プロセスグループのリソース(CPU、メモリ、ディスクI/Oなど)の利用を制限・隔離するLinuxカーネルの機能。“process containers” という名称で Rohit Seth が2006年9月から開発を開始し[1]、2007年に cgroups と名称変更され、2008年1月に Linux カーネル 2.6.24 にマージされた[2]。それ以来、多くの機能とコントローラが追加された。

プロセスグループがなにか?という話だけど、プロセスのグループのことです。 じゃあどうやってこのグループが形成されるのか?だけど、元となる親プロセスから生まれた子プロセスは一つのプロセスグループになる。なるほど。なるほどなるほど。 そのプロセスグループのリソースの利用を制限するのが、cgroupesというLinuxカーネルの機能なんですね。つまり、コンテナランタイムから生まれた子プロセスはコンテナランタイムとおなじプロセスグループに属すことになる。

はいはい、それはOKです。 ここで気になるのが、dockerのcgroupがv2担っていることなんですよね。

なぜうまくいかないのかが少しわかってきたかもしれない。 kubenetes v1.23まではノード上でDockerをコンテナランタイムを利用可能だが、v1.24以降はdockerのサポートを削除予定らしい。

sudo apt-get install docker.io

でインストールしたので、コンテナランタイムがdockerdになっていたっぽいんですよ。 もうdocker.ioはアンインストールしました。 しかし、ノードでDockerが稼働していればcontainerdもすでに稼働しているっぽいんですよ。なので、kubeadmでどのランタイムを使うかを決めるときに、containerdを指定してあげたらもしかしたら上の問題は解決したかもしれません。 –>そんなことできないと思いますが、、、

docker.ioをremoveしてもcontainerdが消えなかったので、さらに以下のコマンドでいらないものを削除。

sudo apt auto-remove

removeとpurgeとautoremoveの違いもここで軽く説明したいと思います。 removeは

パッケージを削除しますが、環境設定は削除されません。 purgeは パッケージとそのパッケージの環境設定をすべて削除します。 autoremoveは 以前に他のパッケージの依存関係のために設置されたが、今は使用されていないパッケージを削除します。

今回のdocker.ioのインストールを例に説明したいと思います。 docker.ioというpackageは様々なpackageの元にできているパッケージです。つまり、他のパッケージに依存しているということですね。実は、その依存関係を調べることもできるんですね。次のコマンドで。

sudo apt-chache depends docker.io

はい。次のようなのが出てきます。

 PreDepends: init-system-helpers
  Depends: libc6
  Depends: libdevmapper1.02.1
  Depends: libsystemd0
    libelogind0
  Depends: adduser
  Depends: containerd
  Depends: iptables
    iptables:armhf
  Depends: lsb-base
  Depends: runc
  Depends: tini
  Conflicts: <docker-ce>
  Conflicts: <docker-ce-cli>
  Conflicts: <docker-ce-rootless-extras>
  Recommends: apparmor
  Recommends: ca-certificates
  Recommends: cgroupfs-mount
  Recommends: git
    git:armhf
  Recommends: needrestart
  Recommends: xz-utils
    xz-utils:armhf
  Suggests: docker-doc
  Suggests: <aufs-tools>
  Suggests: btrfs-progs
    btrfs-progs:armhf
  Suggests: debootstrap
  Suggests: e2fsprogs
    e2fsprogs:armhf
  Suggests: rinse
  Suggests: rootlesskit
  Suggests: xfsprogs
 |Suggests: <zfs-fuse>
  Suggests: zfsutils-linux

長いですね。 docker.ioがcontainerdにも依存しているのがわかりますね。

apt-get purge docker.io

では、docker.ioしか消えません。 で、

apt autoremove

でdocker.ioに使われなくなったpackageも削除される、という感じです。 ちなみに、この依存関係を調べるのにかの有名なトポロジカルソートが使われている、というのは知っておいて損はなさそうですね。

じっさい、purge docker.ioの後、htopすると、 dockerdは消えて、containerdはまだ動いている感じでしたが、 autoremove purgeをすると、containerdも消えてくれました。いいですねー。

けいち先生も言っていたけど、やっぱりこういうのは公式documentが一番いいですね。

ということで、k8sの公式documentを参考に、k8sクラスタを構築します。 その前に、今一度リポジトリについて、軽くおさらいしておくのがいいでしょうね。ソフトをダウンロードしたいときは、リポジトリからダウンロードしてくるんですね。リポジトリの場所っていうのも実はあったりするんですね。うん、リポジトリからダウンロードされるのは、基本的にバイナリだと思います。なので、cpuアーキテクチャとかを考えてリポジトリを設定する必要がある、ということです。

ちなみに、めちゃめちゃ紛らわしいのですが、ラズパイのcpuアーキテクチャは

arch = aarch64

って出るんだよね。これは、何なの?って思うかもしれないけど、arm64のことなんだよね。まぎらわしい!! aarch64について。

公式リポジトリと3rdパーティ製のリポジトリ。PPAについて PPA = Personal Package Archive この辺をまとめると、 外部リポジトリは、

/etc/apt/sources.list

に書いてあるんですね。

新たに追加するには

add-apt-repository url

削除する場合には、

add-apt-repository --remove url

って感じです。

さらに、リポジトリの追加や削除をしたあと、実際に反映させるには、

sudo apt update

を実行する必要があります。

apt系のコマンドも見てみましょう。

以上を踏まえて、いろいろとインストールしていきますね

1.criのインストール dockerのインストールに関してはここを見てください

まった、すべての原因が、zetaっていう名前が引けなかったところにあった説が濃厚になってきた。 /etc/hostsの

127.0.0.1       zeta

担ってないといけないところが、

127.0.1.1       zeta

になっていた。これはだめだろうとね。

いやーこれがもんだいなのかね?おれにはわからなくなってきた。

sudo modprobe overlay
sudo modprobe br_netfilter

カーネルモジュールのロードとアンロードを行うコマンド。ちなみに、カーネルモジュールとは、カーネルの機能を拡張するためのバイナリファイルです。代表的なものにはデバイスドライバがあるんだけど、他に何があるのか?

以下のコマンドをちゃんと実行してからでないと、kubeadmで起動できないんですよね。

cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

sudo sysctl --system

いやマジでなぜうまくいかんのかがわからんですわ。 これも見てみてくれ

こいつが俺と全く同じ問題を抱えているのだがね 原因がガチで不明。マジでどうすればいいんだい。おれにはわからんわ。

屋っと解決しました。 いろいろと問題があったみたいだけど、 結局は、containerdとkubeletが使うcgorup driverが違かったのが問題でした。 ここ に書いてある通りに、

sudo vim /etc/containerd/config.toml
======
'plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options' の下に、SystemdCgroup = true を追加する

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true
=====
sudo sed -i -e "/^cgroupDriver:/c cgroupDriver: systemd" /var/lib/kubelet/config.yaml

この二つを変更したら、無限に動くようになりました。

あとは、kube-proxyを破壊するっていうんで、ipatablesを従来のやつに変えたりもした。 この辺も忘れないで下さい。 ここのiptalbesがnftableをバックエンドとして使用しないようにするってところを見てください。

結局の所、k8sを入れるための流れ。詳細は上に書いてある。

  1. swappoff –all
  2. cgroupの設定。 /boot/cmdline.txt
  3. containerdとkubeletが同じcgroupドライバーを使うように変更
  4. kube-proxyが破壊されないように、iptablesがnftableをバックエンドとして使用しないようにする
  5. sudo apt-install kubectl kubeadm=1.25,kubelet=1.25
  6. sudo apt-get insall containerd
  7. 上をやるときに、バージョンは気を付ける。これを参考にね。
  8. sudo kubeadm init –で新しく作る。kubeadmが最近できたツールらしくて、コミュニケーションのための鍵を自動で生成し、k8sの基本コンポーネントである、kube-apiserverと、kube-controller-managerと、kube-scheudelrとkube-procyとcorednsを立ち上げてくれる。
  9. kubectl get nodesでちゃんと出てくれれば成功です。
  10. ただ、実はここまでやってもcorednsが起動してくれていないんですね。なんでやねん!と。
kube-flannel           kube-flannel-ds-kbl4q                        0/1     CrashLoopBackOff    399 (2m52s ago)   33h
kube-system            coredns-565d847f94-ncdvm                     0/1     ContainerCreating   0                 34h
kube-system            coredns-565d847f94-wvzkr                     0/1     ContainerCreating   0                 34h
kube-system            etcd-zeta                                    1/1     Running             144 (34h ago)     34h
kube-system            kube-apiserver-zeta                          1/1     Running             59 (34h ago)      34h
kube-system            kube-controller-manager-zeta                 1/1     Running             68 (34h ago)      34h
kube-system            kube-proxy-7sqxm                             1/1     Running             6 (34h ago)       34h
kube-system            kube-scheduler-zeta                          1/1     Running             63 (34h ago)      34h
kubernetes-dashboard   dashboard-metrics-scraper-74cb589b78-nqpb9   0/1     Pending             0                 34h
kubernetes-dashboard   kubernetes-dashboard-5958dcc96-glgxv         0/1     Pending             0                 34h
tigera-operator        tigera-operator-6bb5985474-rfxls             1/1     Running             7 (34h ago)       34h

その他

kubeadmについて

podsのステータスの見方 kubectl describe pods -n namespace pods_name

いつまでも続けているのはきついから、ここまで行ったらおしまいっていうのを決めておこう

  • podsを削除する
  • kube-proxyを稼働させる
  • dash-boardを入れて稼働させる -> これなんだけど、何かアプリをデプロイしてから出ないとだめっぽいな。サービスをデプロイしましょうってことですよ。
  • slave1をネットワークにjoinする。

上のを達成するための奮闘日記。 なぜかわからんが、

kubectl delete pods <pods_name>

では削除できなかったんですよ。まったく、面倒くさい。

kubectl get deploy -A

で結構出てきました。

うん、削除の仕方は、 ここ に書いてある。namespaceって概念が登場してから、扱うのがかなりめんどくなっているね。これは。はい、削除の仕方はわかって、しかもdeploment単位で削除すると、 完全に削除できるってこともわかった。pod単位での削除だと、元に戻ろうとして再起動するんだけど。 ということで、

kubectl delete -n kube-system deployments coredns

これで、corednsを削除できました。でも動きませんでしたね。まあそうれはそうか。 こいつがいないとだめっぽいので、

kubeadm reset

で最初からにしました。

はい。でもやっぱり、corednsはContainerCreatingのままなんですよね。 この原因を探ります。

リセットしてもcorednsは動かない。

kubectl describe -n kube-flannel pods kube-flanne-ds-

で見てみると、 flannelがなんとかってはなし。なんだ?

flannelがひつようなのか? ともって、

kubectl apply -f https://flannel

からやったけど前のやつに前戻り。 今度はflannelを見てみると、

もうすでにflannelはあるよ

って怒られた。 たしかに、flannelを入れる前にifconfigでflannelのインターフェースがあったのがなんでだって思ったけど、そういうことなのかもしれないね。

ということで、再びresetして、initして、

なんかね、resetしただけじゃあ前の設定が残ってしまうらしいのよね。 完全にresetするには、 まず、

/etc/kubenetes

の消去。

/etc/cni/

の消去。とくにcniの消去が大事っぽい。 なぜかというと、

cniは、コンテナが作成または破棄されたときにユーザーがコンテナネットワークをより簡単に構成できるようにするためのコンテナネットワークのAPIインターフェース なので、これが残ってしまうからなんですね。 さっき、describe flannelを見た時に怒られたのも、これが原因だったっぽい。

うん、fannelは入れないといけないみたい。 ただ、flannelはデフォルトでのネットワークが決まっていて、 kubeadm initで

--pod-network-cidr=10.244.0.0/16

を渡さないとだめなんです。

おけ、これを渡したら、flannelは動き始めた。ただ、corednsはまだ動かないんだよね。

kubectl describe -n ...

で見てみると、なんか、まだノードが動ける状況じゃないとかなんとか。

うーん、どうやら、flannelがあまりサポートされていないのが問題みたいだね。 かわりに、calicoを持ってこようかな。 うん、この時は、あの参考サイトに書いてある通りに–pod-network-cidrを決めないとだめっぽいですね。

ただね、この時に最悪なことが起こってしまったのですよ。設定の途中で起こってしまったことだと思うんだけど、slaveたちがいるサブネットから、名前解決ができなくなってしまったんだよね。これによって、updateとかもできなくなった。最悪。 ということで、 zetaをリブートした。 今度は無事google.comが通るようになっていた。

たぶん、レガシーバージョンを使うっていう設定にすると、nat周辺でうまくいかないことがあるんだろうね。気を付けましょう。

なんかね、slave1をネットワークにjoinすると、pending状態になっていたpodたちが次々と稼働し始めた。

NAMESPACE         NAME                                       READY   STATUS             RESTARTS         AGE
calico-system     calico-kube-controllers-6b57db7fd6-67884   0/1     CrashLoopBackOff   9 (54s ago)      27m
calico-system     calico-node-6lqhk                          0/1     Init:1/2           10               27m
calico-system     calico-node-lpblm                          0/1     Running            0                27m
calico-system     calico-typha-784f9d547-c2gtf               1/1     Running            10 (4m49s ago)   27m
kube-system       coredns-565d847f94-4d5lw                   0/1     CrashLoopBackOff   10 (88s ago)     31m
kube-system       coredns-565d847f94-7s9h5                   0/1     CrashLoopBackOff   12 (3m21s ago)   31m
kube-system       etcd-zeta                                  1/1     Running            155              32m
kube-system       kube-apiserver-zeta                        1/1     Running            70               32m
kube-system       kube-controller-manager-zeta               1/1     Running            4                32m
kube-system       kube-proxy-gfcd4                           0/1     CrashLoopBackOff   10 (21s ago)     29m
kube-system       kube-proxy-rf9ml                           1/1     Running            0                31m
kube-system       kube-scheduler-zeta                        1/1     Running            75               32m
tigera-operator   tigera-operator-6bb5985474-8jcl6           1/1     Running            0                28m

こんな感じで。ただ、これでもまだ問題があってね。見てもらうと、まだ安定しないのよね。理由はわからないけど、再起動を繰り返すわけですね。

はい、今度はこれが出るようになりました。

calico/node is not ready: BIRD is not ready

まじでなぞやね。

でも、これが出ててもなんかだいじょぶっぽくて、 dashboardを外部にプロキシするコマンドが次のやつ

kubectl proxy --address 0.0.0.0 --accept-hosts '.*'

これは、外部へのアドレスを192.168.3.4とか特定のに限定するのではなく、出ている穴に来るアクセスには答える感じですね。 –accept-hosts ‘.*‘アクセス制限がないってことですね。これでokですよ、これで。

ちなみに、cniにcalicoをインストールするときは、 calico のホームページを参考にやるのが一番いいですよ。よろしくお願いしますね。

ただ、次の問題があってね。アクセスするのにパスワード的なのが必要なんですね。 まじでだるいわーーーー!!って感じですが。

今後の予定

  • dockerとかdockerdとか、kubeletとか、containerdとか、その関係を明らかにしたいですね。というのも、dockerdはバックエンドにcontainerdを使っていて、昔はk8sでもdockerをコンテナのランタイムに使えたのに今はcontainerdじゃ野にとだめとかね。

  • kubeadmを使ってコントロールプレーンのコンポーネントとか、kubeletを入れたけど、手動でやるのがいいかもね。というのも、使う側からではなくて、開発側からの始点で見たいからね。

  • slurmのプラグインとかについても学んだ方がいいのかもしれないね。

2/10:再びk8sに戻ってきた。

前回からの差分だけど、slurmクラスタを作れるようになった。はい。 で、slurmとk8sの違いだけど、どちらもクラスタのリソース管理をするためのミドルウェアであることはに変わりない。しかし、管理するジョブの種類が全く違う。slurmはまさに様々なユーザからスクリプトとしてサブミットされるジョブを効率よく実行するための管理を担うミドルウェアである。一方、k8sってのはユーザがスクリプトでサブミットするようなジョブを管理するものではない。webアプリのような、長期間にわたって安定稼働が求められるプロセス群の管理を担うのがk8s。ユーザはwebアプリを通してリソースを使っていく感じだ。

で、k8sとHPCとの接点だけれども、そうだね、WEB業界のどんなところでスパコンを使う需要があるのか?っていう所を調べていかないといけないな。しかし、batchジョブとかだとあまりk8sを使う需要はないと思うんだがね。なぜかというと、ユーザからのアクセス要求に応じて自動的にリソースをスケーリングしたりする必要がないからね。バッチジョブだとね。しかし、やはりweb業界はリアルタイム性が求められるアプリが多いと思うからな。となるとやはりk8sになって、その先にどうやってHPCとの接点を作る?っていう話になる。そうなのよ。画像生成モデル、stable diffusionとかはGPUをたくさん使うけどね。そうだね、やっぱりGPUってのが入ってくるとHPCっぽくなってくる。冒頭の方でも書いたけど、以下の記事がやはり参考になりそう。k8sのノードの資源割り当てを予測するっていのは面白そうだね。しかし、これを研究に持っていくってなるとすごく難しそう。

ref1 ref2 ref3

まあ、かなり話がそれたが、手動でk8sを構築したいと思う。 で、構築の流れなんですけど、なるべく失敗したくないので、一旦完成までのステップを思い浮かべてやってみましょうか。

  1. まずはバージョンのコンパチが一番大事。ラズパイだから、アーキテクチャはarm64。で、k8sのバージョンとランタイムのバージョンのコンパチを合わせないとだめ。っていうのと、あと、cgroupのこともチョット考えないとな。

k8sの1.23までdockerの利用が可能。しかし、今後containerdが主流になってくるのであればcontainerdを使っていきたい。が1.23以前でもcontainerd普通に使えるやろ? k8sは1.25で行きたいと思う。で、そうなると、1.64が一番いいらしい。 で、containerdを使うことにして、containerdのバージョンでarm64に対応しているのは、

containerd=1.6.4 を使って、k8sは1.25を使う。ok?

で、使うノードだけど、mst0をマスターにします。とりあえず。で、mst2もマスターになる予定なので、開けておく。で、slave1をとりあえずjoinさせますよ。

で、ネットワークの設定だけど、

Node用サブネット。

これはzetaの下にあるサブネットのことだけど、 172.20.2.0/24ですね。 で、 mst0:172.20.2.2 slave1:172.20.2.3

Pod用サブネット

10.10.0.0/16にしましょう。これはpod同士が通信するときの仮想的なネットワークです。で、 mst0:10.10.1.0/16 slave1:10.10.2.0/16

ClusterIP用サブネット

10.32.0.0/24 これが何を言っているのか俺にはわかりませんが、まあ良しとしましょう。 これを参考に。

  1. swappoff –all
  2. cgroupの設定。 このサイトを参考にcgroupe memoryを有効化。 /boot/cmdline.txtに
cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory

を追記。

  1. containerdとkubeletが同じcgroupドライバーを使うように変更
sudo vim /etc/containerd/config.toml
======
'plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options' の下に、SystemdCgroup = true を追加する

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true
=====
  1. kube-proxyが破壊されないように、iptablesがnftableをバックエンドとして使用しないようにする
sudo sed -i -e "/^cgroupDriver:/c cgroupDriver: systemd" /var/lib/kubelet/config.yaml
  1. sudo apt-install kubectl kubeadm=1.25,kubelet=1.25

  2. sudo apt-get insall containerd

  3. 上をやるときに、バージョンは気を付ける。これを参考にね。 しかし、raspiのpackageでは1.4しかないので、直接binaryを持ってくる必要がある、ということで、

  4. overlayとbr_netfilterカーネルモジュールを設定する。

cat > /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF

modprobe overlay
modprobe br_netfilter

# 必要なカーネルパラメータの設定をします。これらの設定値は再起動後も永続化されます。
cat > /etc/sysctl.d/99-kubernetes-cri.conf <<EOF
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

sysctl --system
  1. sudo kubeadm init –で新しく作る。kubeadmが最近できたツールらしくて、コミュニケーションのための鍵を自動で生成し、k8sの基本コンポーネントである、kube-apiserverと、kube-controller-managerと、kube-scheudelrとkube-procyとcorednsを立ち上げてくれる。
  2. kubectl get nodesでちゃんと出てくれれば成功です。
  3. ただ、実はここまでやってもcorednsが起動してくれていないんですね。なんでやねん!と。
  4. cniをインストールする。

ちなみに、cniにcalicoをインストールするときは、 calico のホームページを参考にやるのが一番いいですよ。よろしくお願いしますね。

いや、やっぱりkubeadmを使う方がいい気がしてきた。すみません。

マスター側

  1. swapoff –all
  2. cgroupの設定
  3. containerdのインストール。バージョンをチェックしながら。 githubからこれ をとってくる。systemdファイル(unitfile)や、runc、など、必要なソフトが入っているpackage担っています。マジでありがとう。インストールしてください。
  4. sudo systemctl start containerd
  5. nerdctlのインストール。 githubからだね nerdctl を/usr/local/binに移動。
  6. kubeletとkubectlとkubeadmのインストール
sudo apt install kubeadm=1.24 kubelet=1.24 kubectl=1.24

この手順通りにやりました

  1. swapoff –all
  2. cgroupの設定

むりだ!!おつ!!今日はもうおしまいです!!

再び頑張ってみる。k8s the hard wayは難しいと思うので、まずはkubeadmを使って簡単化する。

まず、ノード構成だが、次のような感じで行きたいと思う。

mrlee : 192.168.3.7 (worker) mrkee : 192.168.3.6 (worker) jhonny : 192.168.3.14 (worker) firelily : 192.168.3.5 (master)

で、インストールするバージョンですが、

k8s : 1.28 1.6.24にも対応しています。

containerd : 1.7 -> 1.6.24に変更 これで行きたい。せ、CRIはv1らしいね。これは container runtime interfaceがv1ってことなのかな。まあ俺には関係ないが。 で、参考にするサイトだけど、やっぱり公式がいいということで、

kubernetes.io。ここを参考にやりたいですね。チョット書いてあるのが、kubelet以外のコンポーネントは全部コンテナの中で動かせると。たしかに、kubeletはコンテナとやり取りするためのインターフェースだからね。

まずは、containerdのインストールからだね。いや、1.6.24をインストールすることにする。まずは、公式サイト で、公開されているbinaryを見てみよう。 sha256sumってのがあるよね。これはね、その実父ファイルがsha256でハッシュされた値が入っててね、autheniticityを保証するものになる。

openssl sha256 hogehoge.tar.gz > sha256ed_file

とかにして、

diff sha256ed_file hogehoge.sha256sum

して比較してみようじゃない。これが同じだったら本物ってことよ。で同じなわけね。

だから、解凍して、ソフトとして使ってもいいってことね。安全性が保障されている。 でね、解凍すると、以下のディレクトリが出てくるわけよ。

cri-containerd.DEPRECATED.txt
etc/
etc/cni/
etc/cni/net.d/
<!-- etc/cni/net.d/10-containerd-net.conflist --> こいつはいらないですね、おそらく。
etc/crictl.yaml
etc/systemd/
etc/systemd/system/
etc/systemd/system/containerd.service
usr/
usr/local/
usr/local/sbin/
usr/local/sbin/runc
usr/local/bin/
usr/local/bin/ctd-decoder
usr/local/bin/critest
usr/local/bin/containerd-shim-runc-v1
usr/local/bin/containerd-stress
usr/local/bin/containerd-shim-runc-v2
usr/local/bin/containerd
usr/local/bin/containerd-shim
usr/local/bin/ctr
usr/local/bin/crictl
opt/
opt/cni/
opt/cni/bin/
opt/cni/bin/host-device
opt/cni/bin/macvlan
opt/cni/bin/host-local
opt/cni/bin/vlan
opt/cni/bin/bandwidth
opt/cni/bin/tuning
opt/cni/bin/dhcp
opt/cni/bin/ptp
opt/cni/bin/portmap
opt/cni/bin/vrf
opt/cni/bin/loopback
opt/cni/bin/static
opt/cni/bin/ipvlan
opt/cni/bin/firewall
opt/cni/bin/bridge
opt/cni/bin/sbr
opt/containerd/
opt/containerd/cluster/
opt/containerd/cluster/gce/
opt/containerd/cluster/gce/env
opt/containerd/cluster/gce/cloud-init/
opt/containerd/cluster/gce/cloud-init/master.yaml
opt/containerd/cluster/gce/cloud-init/node.yaml
opt/containerd/cluster/gce/cni.template
opt/containerd/cluster/gce/configure.sh
opt/containerd/cluster/version

手動で全部コピーするのは面倒くさいので、次のシェルスクリプトで一括でやります。

#!/bin/bash

# Define the paths to your installation directories
CONTAINERD_BIN_DIR="/usr/local/bin"
CONTAINERD_SBIN_DIR="/usr/local/sbin"
CONTAINERD_ETC_DIR="/etc/containerd"
CONTAINERD_SYSTEMD_DIR="/etc/systemd/system"

# Define the source directory where you extracted ƒtainerd files
SOURCE_DIR="/home/ray/"

# Move binary files to /usr/local/bin
cp -r "$SOURCE_DIR/usr/local/bin/"* "$CONTAINERD_BIN_DIR/"

# Move sbin files to /usr/local/sbin
cp -r "$SOURCE_DIR/usr/local/sbin/"* "$CONTAINERD_SBIN_DIR/"

# Move etc files to /etc/containerd
cp -r "$SOURCE_DIR/etc/"* "$CONTAINERD_ETC_DIR/"

# Move systemd service file to /etc/systemd/system
cp "$SOURCE_DIR/etc/systemd/system/containerd.service" "$CONTAINERD_SYSTEMD_DIR/"

# Reload systemd to recognize the new service
systemctl daemon-reload
echo "Containerd installed successfully."

chmod 777 install.shして、sudo ./install.sh をすれば一発だな。で、sudo systemctl start containerdだね。 一応動いている感じです。いい感じね。 次。docker コマンドコンパチのnerdctlをインストールしないとだめですね。 はい、ちゃんと動きます。完全にdockerコマンドと互換性があります。これには驚きです。素晴らしい。 で、docker imageも問題なくう号とか言ってるので、本当か確認するために実験します。

sudo docker save -o my_image.tar jc_data_checker_comp

で、イメージ化。これをcontainerdが動いているサーバに転送。で、

sudo nerdctl load -i ./my_image.tar

で、ちゃんと復元されます。すごいね。マジで互換性があるのか。これは感動。

ただ、すぐ止まってしまうね。これは、実行ファイルを設定していないからだと思うんだけど。

でね、 nerdctl execはあくまで、動いているコンテナの中でコマンドを打つコマンドなんですよ。だから、/bin/bashってやって、 しかも、-itってやると中で打てているように見えるだけなんですね。つまり、泊ってはいけないのです。 うーんやっぱり駄目だね。

dockerでは、

sudo docker container create --name=test -i image

で、

sudo docker container start test

すると、フツーに泊まらずに行ってくれるんだよね。 なのにさ、containerdだと、難化泊ってしまうのよね。まじで。これどうすんねんと。まあ、中に入っていろいろするために作られてはいないってのはわかるんだけどさ、そういう使い方をしたい人だっているわけじゃないですか。まじで。 まあ、何かしらのプログラムが動いてくれていないと止まってしまうということ。

sudo nerdctl container create --name=jc2 -i jc_data_checker_comp node /root/JC_mobile_data_viewer/server/main.js

上のコマンどでクリエイトして、startさせれば、フツーに無限に動いてくれる。 htopをすると

Error opening terminal: unknown.

こんなエラーが出ることもあったが。 コンテナの中で、

export TERM=xterm

をすると、htopも受け付けるようになった。なぜかはわからん。 で、createするときに稼働させるプロセスは、/bin/bashだと、なぜかすぐ止まってしまう。これマジでなんでやねん!って思ってしまうんだが。 しかし、ここで解決策を見つけた。次のコマンドでコンテナを作成することで、/bin/bashを永遠に動かし続けることが可能です。

sudo nerdctl (container) create --name=test -it image_name /bin/bash

ポイントは、-itですね。ここで、tオプションを付けるのがポイントでした。さらに、/bin/bashを起動すると。これで問題が解決します。

Dockerfileをビルドするためのツールは別でインストールする必要がありますよと。はい。BuildKitってものらしいですね。これは標準ではdockerについてるものみたいなんですけど、nerdctlには標準ではついていませんよと。まあ、いいか。別にdockerで作ったイメージ、containerdで使えるし。はい。

ということで、k8sが規定するcniに準拠するインターフェースを持つcontainerd + 周辺のソフト、(runc + CNI)をインストールしてローカルで使えるようにするまででした。一括でやってくれちゃうshellスクリプト、載せておきます。(nerdctlも一緒についてくるバージョンがあったので、そっちも。)

#!/bin/bash

download binaries nerdctl

wget https://github.com/containerd/nerdctl/releases/download/v1.5.0/nerdctl-1.5.0-linux-amd64.tar.gz

wget https://github.com/containerd/containerd/releases/download/v1.6.24/cri-containerd-cni-1.6.24-linux-amd64.tar.gz

tar -zxvf nerdctl-1.5.0-linux-amd64.tar.gz

tar -zxvf cri-containerd-cni-1.6.24-linux-amd64.tar.gz

mv nerdctl /usr/local/bin

mkdir /etc/containerd

Define the paths to your installation directories

CONTAINERD_BIN_DIR="/usr/local/bin" CONTAINERD_SBIN_DIR="/usr/local/sbin" CONTAINERD_ETC_DIR="/etc/containerd" CONTAINERD_SYSTEMD_DIR="/etc/systemd/system" CONTAINERD_OPT_DIR="/opt/"

Define the source directory where you extracted the Containerd files

SOURCE_DIR="/home/ray"

Move binary files to /usr/local/bin

cp -r “$SOURCE_DIR/usr/local/bin/”* “$CONTAINERD_BIN_DIR/”

Move sbin files to /usr/local/sbin

cp -r “$SOURCE_DIR/usr/local/sbin/”* “$CONTAINERD_SBIN_DIR/”

Move etc files to /etc/containerd

cp -r “$SOURCE_DIR/etc/”* “$CONTAINERD_ETC_DIR/”

Move systemd service file to /etc/systemd/system

cp “$SOURCE_DIR/etc/systemd/system/containerd.service” “$CONTAINERD_SYSTEMD_DIR/”

Move opt files to opt

cp -r “$SOURCE_DIR/opt/”* “$CONTAINERD_OPT_DIR”

Reload systemd to recognize the new service

systemctl daemon-reload

echo “Containerd installed successfully.”


# システムの設定。

## swap off -a

sudo swapoff -a

## /etc/containerd/config.tomlを作る

以下のコマンドでconfig.tomlが作られる。

containerd config default > /etc/containerd/config.toml


## Forwarding IPv4 and letting iptables see bridged traffic

cat «EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF

sudo modprobe overlay sudo modprobe br_netfilter

sysctl params required by setup, params persist across reboots

cat «EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF

Apply sysctl params without reboot

sudo sysctl –system


To verify that everything goes well run following command

lsmod | grep br_netfilter lsmod | grep overlay


check if the variables below are set to 1

sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward


## cgoup drivers
On Linux, control groups are used to constrain resources that are allocated to processes.

Both the kubelet and the underlying container runtime need to interface with control groups to enforce resource management for pods and containers and set resources such as cpu/memory requests and limits. To interface with control groups, the kubelet and the container runtime need to use a cgroup driver. It's critical that the kubelet and the container runtime use the same cgroup driver and are configured the same.
とのことです。で、

cgroupfsとsystemdの2つのcgroup driverがあると。で、systemd cgroup driverが推奨されています。で、コンテナランタイムも、kubeletもどっちも同じcgroup driverを使わないといけないと。
To use the systemd cgroup driver in /etc/containerd/config.toml with runc, set

[plugins.“io.containerd.grpc.v1.cri”.containerd.runtimes.runc] … [plugins.“io.containerd.grpc.v1.cri”.containerd.runtimes.runc.options] SystemdCgroup = true ```

で、この辺から、kubeadmをつかってインストール!に従っていくわけですね。3つのコンポーネントをインストールするわけですね。kubeadm,kubelet,kubectl

sudo apt-get update
# apt-transport-https may be a dummy package; if so, you can skip that package
sudo apt-get install -y apt-transport-https ca-certificates curl

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

インストールが終わったら、コントロールプレーン、つまりマスターノードで、

sudo kubeadm init –pod-network-cidr=10.244.0.0/16

をする。そうすると、ワーカからマスターにjoinするのにどんなコマンドが必要が教えてくれる。下のようなコマンドになると思う。ので、それに従ってやってみてくれって感じ。

sudo kubeadm join : –token –discovery-token-ca-cert-hash sha256:




で、ジョインが完了すると思う。
ポッド同士が通信しあうためには特別なアドオンが必要。ポッドネットワークというものだね。これは、下のコマンドで実行可能。

ー->これは、applyだから、一回セットすると全部に適用されるんだよね?

kubectl apply -f “https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d ‘\n’)”


これでポッドどおしが通信できるようになりました。最後。
kubeapi-serverと通信するため設定。

大事なのが、$KUBECONFIGをkubectlは見に行くから、ここにちゃんと設定ファイルを入れるってこと。元の場所は、
/etc/kubernetes/admin.conf
で、ここから任意の場所に移して、そこにパスを通してあげれば桶。

# 最後、kubectl get nodesで意外と手間取った。からここだけまとめておきたい。

mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config export KUBECONFIG=$HOME/.kube/config


いやだめっぽいな。普通に

export KUBECONFIG=$HOME/admin.conf


でお願いします。これで動いているのが確認できる。

結局まとめるとこんな感じになりますと。

# オーバレイネットワークとは

a virtual network that spans multiple nodes in a cluster and provides connectivity between Pods running on different nodes

[https://www.netstars.co.jp/kubestarblog/k8s-3/](詳しく書いてあります)


# k8sを導入するまとめ

## 1. containerdを導入。
k8sのv1.25以降は、コンテナエンジンにdockerエンジンを使えません。(理由は、dockerがcriを満たしていないから)。criを満たしてるcontainerdをインストールする必要があります。
containerdのインストールは、githubのリポジトリからできます。同時に、runcとcniもインストールしてださい。
ちなみに、cniは、container network interfaceで、まあ、コンテナのネットワークを操るためのapiですね。
で、そのapiを操るのが、cniプラグイン。で、cniプラグインには、calicoだったり、flannelだったりがあるわけですね。で、プラグインには、3種類のモードがあって、オーバーレイと、ルーティングと、アンダーレイですね。オーバレイを使うことで、別のホスト上にいるコンテナ同士が同じセグメントにいるようになります。

で、だけど、/etc/cni/net.dにはデフォルトのやつ、おかなくて結構です。まったく問題ありませんので、お気になさらず。ということで。

## 2. ホストの設定
### swapのoff

大事なこと忘れてました!!!!!!!!!!!!!
worker nodesはport 10250 を開けてください。


### /etc/containerd/config.tomlを作る

containerd config default > /etc/containerd/config.toml


### Forwarding IPv4 and letting iptables see bridged traffic

cat «EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF

sudo modprobe overlay sudo modprobe br_netfilter

sysctl params required by setup, params persist across reboots

cat «EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF

Apply sysctl params without reboot

sudo sysctl –system


To verify that everything goes well run following command

lsmod | grep br_netfilter lsmod | grep overlay


check if the variables below are set to 1

sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward


### cgoup drivers
On Linux, control groups are used to constrain resources that are allocated to processes.

Both the kubelet and the underlying container runtime need to interface with control groups to enforce resource management for pods and containers and set resources such as cpu/memory requests and limits. To interface with control groups, the kubelet and the container runtime need to use a cgroup driver. It's critical that the kubelet and the container runtime use the same cgroup driver and are configured the same.
とのことです。で、

cgroupfsとsystemdの2つのcgroup driverがあると。で、systemd cgroup driverが推奨されています。で、コンテナランタイムも、kubeletもどっちも同じcgroup driverを使わないといけないと。
To use the systemd cgroup driver in /etc/containerd/config.toml with runc, set

[plugins.“io.containerd.grpc.v1.cri”.containerd.runtimes.runc] … [plugins.“io.containerd.grpc.v1.cri”.containerd.runtimes.runc.options] SystemdCgroup = true



これを変更した後に、containerdを再起動しないとマジでバグります。よろしくおねげーします。まじd。

sudo systemctl restart containerd


## 3. kubeadm, kubelet, kubectlのインストール

sudo apt-get update

apt-transport-https may be a dummy package; if so, you can skip that package

sudo apt-get install -y apt-transport-https ca-certificates curl

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg –dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list

echo ‘deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /’ | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl

sudo systemctl start kubelet sudo systemctl enable kubelet

でkubeletを起動

##### ここまでがワーカ、マスターに限らず必要な操作になります。

## 4. マスター上で、kubeadmを使って、各コンポーネントを起動させる

sudo kubeadm init –pod-network-cidr=10.244.0.0/16



トークンの再発行

kubeadm token create –print-join-command

--print-join-commandをつけると、kubeadmのjoinに必要なコマンドとかも全部出してくれる。


## 5. ワーカ上で、4を実行後に得られるトークンを使って、マスターと接続する

sudo kubeadm join : –token –discovery-token-ca-cert-hash sha256:






## 6. cniプラグインをインストールする

kubectl apply -f “https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d ‘\n’)”


By default, tokens expire after 24 hours. If you are joining a node to the cluster after the current token has expired, you can create a new token by running the following command on the control-plane node:

kubeadm token create


でもちょっと待てよ。これってもしかして既にインストールされているのではないかという話。
いや、わからん。/etc/cni/net.d/bridgeってのは何だね。わからんねー-。

The file you’ve shown, nerdctl-bridge.conflist, is a configuration file for a CNI (Container Network Interface) plugin called “bridge.” This CNI plugin is typically used for container runtimes like Docker or containerd to set up network connectivity for containers. It may not be directly related to Kubernetes networking, but it can be used by container runtimes on a Kubernetes node to manage networking for pods.

Let’s break down the contents of the file:

ってことらしいのよね。つまり、k8sのネットワークとは関係ないってことなんですよね。マジで。
ってことでやっぱりcniプラグインをインストールする必要があるんですね。
はい、必ずインストールしてください。でないとpod間で通信ができません。ので必ず入れてください。よろしくおねがいします。flannelを入れてください。で、入れたらその設定が、全部のノードの/etc/cni/net.d/の中に書き込まれます。これは、kubeadmでノードを停止させたあとも残ります。ので、気をつけてください。もし違うプラグインをインストールしたいのであれば、必ず/etc/cni/net.dに入ってるものを一度消してください。よろしくおねがいします。

というのも、calicoを入れたあと、flannelを入れて、マジでうまく行かなかかった。これで結構時間も食ってしまった。。。

## 7. kubectlで、apiserverにアクセスするための設定ファイルをホームディレクトリに移動させる。

mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config

って書いてあるんだけど、これではうまくいかなくてね。
ふつーに、

sudo cp -i /etc/kubernetes/admin.conf $HOME/ export KUBECONFIG=$HOME/admin.conf

して、設定ファイルにパスを通す感じ。
これで、

kubectl get nodes

ができる。

kubectl –kubeconfig ./admin.conf get nodes

でもおけ。設定ファイルを各ワーカに配置すれば、ワーカからも上のコマンドで確認ができるようになる。


## 8. remove the node

kubectl drain –delete-emptydir-data –force –ignore-daemonsets


## その他、必要なtips

By default, your cluster will not schedule Pods on the control plane nodes for security reasons. If you want to be able to schedule Pods on the control plane nodes, for example for a single machine Kubernetes cluster, run:

kubectl taint nodes –all node-role.kubernetes.io/control-plane-



## なんか、dash-boardをデプロイしようとしてるんだけど、なかなかうまくいかんですなー。いいところまではいっていると思ってるのだが。。。まあ、あとは、地道に学んでいくしかないんだろうな。いきなりは無理や。
環境を構築しただけでもえらい。