AWS EC2でkubeadmを用いたKubernetesクラスターを作ってみたのでメモ
この記事はなむゆの個人ブログにもマルチポストしています。
はじめに
Kubernetesって動かすと楽しいじゃないですか。
でも、Kubernetesで遊ぼうと思ったら普段はローカルでRancher Desktopからシングルノードのクラスターをワンボタンで作ったりEKSやAKSでマネージドなクラスターを作ったりするのですが、それではちょっと物足りないこともあります。
例えば最新のバージョンのKubernetesを使ってみようとしたら、前述の方法だとどれもすぐには対応していなくて、最新バージョンに対応するのを待つ必要があります。
そのためいつでも最新のバージョンのKubernetesを試せるように、ついでにマルチノードの構成で立ち上げるようにするためにAWS EC2の中にkubeadmでKubernetesを立ち上げ、クラスターを構成する方法を確立しておこうと試みたので今のところ確立できている方法をメモしておきます。
そのうちもっといい方法が確立できるかもしれないのでその時はその時で別途記事にしようと思います。
今回の構成
今回作成した構成は以下のような形です。
Control Plane Nodeが1台、Worker Nodeの数は2台にしましたが実際はお好みで。
コンテナランタイム: runc
CNI: Cilium
作成したリソース
EC2
- name: kubernetestest-dev-app-controlplane
image: Canonical, Ubuntu, 24.04 LTS, amd64 noble image build on 2024-04-23
instanceType: t3.small
keyPair: 新規作成
VPC: kubernetestest-dev-pvc
サブネット: kubernetes-dev-subnet
NSG: kubernetestest-dev-nsg
パブリックIPの自動割り当て: 有効化
- name: kubernetestest-dev-app-worker
image: Canonical, Ubuntu, 24.04 LTS, amd64 noble image build on 2024-04-23
instanceType: t3.micro
keyPair: 新規作成
VPC: kubernetestest-dev-pvc
サブネット: kubernetes-dev-subnet
NSG: kubernetestest-dev-nsg
パブリックIPの自動割り当て: 有効化
インスタンスサイズは、Control Plane用のインスタンスではメモリとCPUがそれぞれ2GiBと2v必要なためt3.smallとしています。
Worker Node用では最低限で構わないのでt3.microにしています。
また、今回は学習用リソースとして作成しているため、インスタンスにローカルから直接sshするためにパブリックIPの自動割り当てを有効にいています。
VPC
- name: kubernetestest-dev-vpc
IPv4 CIDR: 10.0.0.0/16
Subnet
- name:
VPC: kubernetestest-dev-vpc
IPv4 Subnet CIDR: 10.0.0.0/16
Route Table
- name: kubernetes-dev-rtb
VPC: kubernetestest-dev-vpc
routes:
- to: 10.0.0.0/16
target: local
- to: 0.0.0.0/16
target: kubernetestest-dev-igw
IGW
- name: kubernetestest-dev-igw
VPC: kubernetestest-dev-vpc
NSG
- type: ssh
source: 0.0.0.0/0
- type: customTCP
source: 0.0.0.0/0
port: 6443
- type: customTCP
source: 10.0.0.0/16
port: 10250
NSGではこちらを参考に許可する通信を規定しています。
本当はControl PlaneとWorker Nodeで要件は異なりますが、今回はひとまとめにしています。
ssh用の22番、API Serverへのアクセス用の6443番、Kubernetes Nodeのkubelet間のやりとりのための10250番ポートを開放してあります。
特に10250番はクラスター内部の通信であるため、通信元は同じVPC内部に限定しています。
実行したコマンド
リソースが一通り作成できれば、EC2 Instance Connect等を用いてインスタンスにssh接続します。
Control Plane NodeとなるEC2インスタンスでは起動後に以下のコマンドを実行してコンテナランタイム、Kubernetes、CNIをインストールしています。
実行時は先にControl Plane Nodeのコマンドから実行してください。
# Dockerのインストール
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
sudo apt-get update
sudo apt-get install -y docker.io
# Dockerの開始
sudo systemctl start docker
sudo systemctl enable docker
# Kubernetesのインストール
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/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
# Kubernetesの起動
sudo kubeadm init --pod-network-cidr=10.0.0.0/16
# kubeconfigのコピー
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# CNIのインストール
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
cilium install
Worker NodeとなるEC2インスタンスでは以下のコマンドを実行しています。KubernetesのインストールコマンドまではControl Plane Nodeと同様です。
クラスターに加入するコマンドは、Control Plane Nodeの立ち上げ時に最後のほうで
kubeadm join ~~~
といった形で表示されるのでそれをそのままWorker Nodeで打ち込んでください。# Dockerのインストール
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
sudo apt-get update
sudo apt-get install -y docker.io
# Dockerの開始
sudo systemctl start docker
sudo systemctl enable docker
# Kubernetesのインストール
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/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
# Kubernetesクラスターに加入
sudo kubeadm join <Control PlaneノードのプライベートIP>:6443 --token <トークン> --discovery-token-ca-cert-hash sha256:<hash値>
# 動作確認
各ノードでコマンドを実行し、成功していれば以下のような出力が得られるかと思います。
Control Plane Nodeで
kubectl get node
を実行どこのノードでも
sudo docker info
コマンドを実行すると現在使用しているDockerのバージョンやコンテナランタイムが表示されるかと思います。Todo
このクラスターではまだメトリクスサーバーがインストールされていません。
そのため`kubectl top`コマンドやHPAが使えません。
スケーリングの動きを確かめようと思ったらこのあたりの機能が使える必要があるので、また今度インストールも試してみます。
今回動作確認が取れたコンテナランタイムはruncで、しかもそのためにインストールしたパッケージは少し古めの
docker.io
でした。推奨されるコンテナランタイムはcotainerdかcri-oなのですが、今回は動作確認が取れなかったので今度動作することを確認したいと思います。
また、今回はEC2やネットワーク系のリソース、Kubernetesのインストール等を手動で行っていますが、1コマンドでできたほうが楽なので今度Terraform化を試してみます。
おわりに
今回は勉強がてらEC2でKubernetesクラスターをkubeadmベースで作成してみました。
この方法が確立できていれば後でいろいろ検証するのに役立ちそうに思います。
ただ、今回はそれなりに苦労した割に妥協した点も多くあるので、これからもっと構成を洗練させていければと考えています。
自分と同様にKubernetesクラスターをkubeadmベースで作ってみたいという方の助けになれば幸いです。