はじめに
この記事では kubespray を使用してKubernetes クラスターをインストールする方法について説明します.
仮想マシンを使用するため,Vagrant および VirtualBox を使います.
注意:泥臭い作業やコードが多く含まれます.
環境
- Ubuntu 20.04
- Kubespray v2.15.1
- Ansible v2.9.20
- VirtualBox v6.1.16
- Vagrant v2.2.6
0. 準備
Vagrantがない場合はインストールします.Vagrant以前にVirtualBoxもない場合はインストールしてください.
0.1 VirtualBoxのインストール
sudo apt install virtualbox
0.2 Vagrantのインストール
sudo apt install vagrant
バージョンを確認
vagrant --version
vagrantの使い方については例えば以下を参照してください.
1. プロビジョニング
大量の物理マシンがあれば使いたいところですが,無いのでVM(仮想マシン)を使ってクラスターを構築します.
以下では7つのVM(仮想マシン)をセットアップします.
IP | CPU | メモリ | |
---|---|---|---|
Ansibleマスターノード(amaster) | 100.0.0.1 | 1 | 2GB |
Kubernetesマスターノード(kmaster1〜3) | 100.0.0.2, 100.0.0.3, 100.0.0.4 | 1 | 2GB |
Kubernetesワーカーノード(kworker1〜3) | 100.0.0.5, 100.0.0.6, 100.0.0.7 | 1 | 2GB |
もしリソースに余裕があれば,CPUを2以上にしたり,メモリを増やすことも可能です.
1.1 Vagrantfileの作成
適当な作業ディレクトリを作成し,その中に以下のVagratnfileを作成します.(for文で書くともっと短く書けます)
Vagrant.configure("2") do |config|
config.vm.define "amaster" do |amaster|
amaster.vm.box_download_insecure = true
amaster.vm.box = "hashicorp/bionic64"
amaster.vm.network "private_network", ip: "100.0.0.1"
amaster.vm.hostname = "amaster"
amaster.vm.provider "virtualbox" do |v|
v.name = "amaster"
v.memory = 2048
v.cpus = 1
end
end
config.vm.define "kmaster1" do |kmaster|
kmaster.vm.box_download_insecure = true
kmaster.vm.box = "hashicorp/bionic64"
kmaster.vm.network "private_network", ip: "100.0.0.2"
kmaster.vm.hostname = "kmaster1"
kmaster.vm.provider "virtualbox" do |v|
v.name = "kmaster1"
v.memory = 2048
v.cpus = 1
end
end
config.vm.define "kmaster2" do |kmaster|
kmaster.vm.box_download_insecure = true
kmaster.vm.box = "hashicorp/bionic64"
kmaster.vm.network "private_network", ip: "100.0.0.3"
kmaster.vm.hostname = "kmaster2"
kmaster.vm.provider "virtualbox" do |v|
v.name = "kmaster2"
v.memory = 2048
v.cpus = 1
end
end
config.vm.define "kmaster3" do |kmaster|
kmaster.vm.box_download_insecure = true
kmaster.vm.box = "hashicorp/bionic64"
kmaster.vm.network "private_network", ip: "100.0.0.4"
kmaster.vm.hostname = "kmaster3"
kmaster.vm.provider "virtualbox" do |v|
v.name = "kmaster3"
v.memory = 2048
v.cpus = 1
end
end
config.vm.define "kworker1" do |kworker|
kworker.vm.box_download_insecure = true
kworker.vm.box = "hashicorp/bionic64"
kworker.vm.network "private_network", ip: "100.0.0.5"
kworker.vm.hostname = "kworker1"
kworker.vm.provider "virtualbox" do |v|
v.name = "kworker1"
v.memory = 2048
v.cpus = 1
end
end
config.vm.define "kworker2" do |kworker|
kworker.vm.box_download_insecure = true
kworker.vm.box = "hashicorp/bionic64"
kworker.vm.network "private_network", ip: "100.0.0.6"
kworker.vm.hostname = "kworker2"
kworker.vm.provider "virtualbox" do |v|
v.name = "kworker2"
v.memory = 2048
v.cpus = 1
end
end
config.vm.define "kworker3" do |kworker|
kworker.vm.box_download_insecure = true
kworker.vm.box = "hashicorp/bionic64"
kworker.vm.network "private_network", ip: "100.0.0.7"
kworker.vm.hostname = "kworker3"
kworker.vm.provider "virtualbox" do |v|
v.name = "kworker3"
v.memory = 2048
v.cpus = 1
end
end
end
コマンド vagrant up
でVMインスタンスを作成します.
vagrant up
数分かかります.
1.2 hostsファイルの編集
VMインスタンスの数ぶんのターミナルを開いて,すべてのVMインスタンスにssh接続しておきます.
vagrant ssh amaster
vagrant ssh kmaster1
vagrant ssh kmaster2
vagrant ssh kmaster3
vagrant ssh kworker1
vagrant ssh kworker2
vagrant ssh kworker3
次に,すべてのVMインスタンスで次のコマンドを実行します.
sudo cat <<EOF | sudo tee -a /etc/hosts
100.0.0.1 amaster
100.0.0.2 kmaster1
100.0.0.3 kmaster2
100.0.0.4 kmaster3
100.0.0.5 kworker1
100.0.0.6 kworker2
100.0.0.7 kworker3
EOF
これが何をやっているかというと,/etc/hosts
ファイルに以下の内容を追記しているだけです.
100.0.0.1 amaster
100.0.0.2 kmaster1
100.0.0.3 kmaster2
100.0.0.4 kmaster3
100.0.0.5 kworker1
100.0.0.6 kworker2
100.0.0.7 kworker3
例えば,amaster
ノードでのhostsファイルは以下のようになります.
$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 amaster amaster
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
100.0.0.1 amaster
100.0.0.2 kmaster1
100.0.0.3 kmaster2
100.0.0.4 kmaster3
100.0.0.5 kworker1
100.0.0.6 kworker2
100.0.0.7 kworker3
1.3 Ansibleを使えるようにするためのSSHまわりの準備(amasterでのみ実行)
鍵認証によるログインが必要ですので,公開鍵と秘密鍵を作成します(パスフレーズ等はセキュリティ等の理由がなければ空のままでよいです).
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Generating public/private rsa key pair.
Enter file in which to save the key (/home/vagrant/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/vagrant/.ssh/id_rsa.
Your public key has been saved in /home/vagrant/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:5U39LgrybQyluHATriD5LzgAZ57qJnSDz1g1O0CnETY vagrant@amaster
The key's randomart image is:
+---[RSA 2048]----+
| E. |
| .o.. . |
| . + . . . |
|. oo o .o o. . |
|.+.oo o.So.o. .|
|.o=+.o. = o . |
|.o*+...+.o.o . .|
|ooooo . .o oo. . |
|+. . o. ..o |
+----[SHA256]-----+
vagrant@amaster:~$
公開鍵の登録
生成した公開鍵(id_rsa.pub
)を他のノードにコピーします.
例えば,kmaster1
へコピーするときは以下のようにします.
$ ssh-copy-id 100.0.0.2
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/vagrant/.ssh/id_rsa.pub"
The authenticity of host '100.0.0.2 (100.0.0.2)' can't be established.
ECDSA key fingerprint is SHA256:uY6GIjFdI9qTC4QYb980QRk+WblJF9cd5glr3SmmL+w.
Are you sure you want to continue connecting (yes/no)?
接続を続けますか?と聞かれるので,yes
と入力.
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
vagrant@100.0.0.2's password:
ユーザー名vagrant
に対するパスワードを聞かれます.パスワードはvagrant
です.
Number of key(s) added: 1
Now try logging into the machine, with: "ssh '100.0.0.2'"
and check to make sure that only the key(s) you wanted were added.
公開鍵のコピー完了です.
他のノードに対しても同様の作業を行ってください:
ssh-copy-id 100.0.0.3
ssh-copy-id 100.0.0.4
ssh-copy-id 100.0.0.5
ssh-copy-id 100.0.0.6
ssh-copy-id 100.0.0.7
ssh-copy-id
が面倒な場合
Ansibleのauthorized_key
というモジュールで公開鍵を配布することができます.
例えば次のplaybook.ymlのようなplaybookを実行すると配れます。
- hosts: all
tasks:
- name: add authorized_key
authorized_key:
user: "{{ user }}"
key: "{{ lookup('file', '/home/{{user}}/.ssh/id_rsa.pub') }}"
ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i <inventory> playbook.yml -k
環境変数ANSIBLE_HOST_KEY_CHECKING
はsshで新規ホスト接続時に出る,ホスト鍵追加のプロンプトを抑制するためのものです.
参考
2. Kubesprayによるkubernetesクラスターのセットアップ
2.1 kubespray 実行に必要なパッケージのインストール(amasterでのみ実行)
年のため,次のコマンドを実行します(すべてのノードで実行)
sudo apt-get update
python3-pipをインストールします(amasterでのみ実行)
sudo apt install -y python3-pip
インストールされたか確認します.
$ pip3 -V
pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.6)
kubespray のリポジトリのクローン(amasterでのみ実行)
git clone https://github.com/kubernetes-sigs/kubespray.git
requirement.txt
パッケージをインストール(amasterでのみ実行)
「kubespray」ディレクトリに移動
cd kubespray
sudo pip3 install -r requirements.txt
インベントリファイルのコピー(amasterでのみ実行)
次のコマンドを使用してインベントリファイルをコピーします.
cp -rfp inventory/sample inventory/mycluster
host.yml
の準備(amasterでのみ実行)
他のノードのIPアドレスを格納するための変数IPS
を宣言します.
declare -a IPS=(100.0.0.2 100.0.0.3 100.0.0.4 100.0.0.5 100.0.0.6 100.0.0.7)
CONFIG_FILE=inventory/mycluster/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]}
上記のコマンドを実行後,hosts.yml
を確認すると,次のようになっています.
$ cat inventory/mycluster/hosts.yml
all:
hosts:
node1:
ansible_host: 100.0.0.2
ip: 100.0.0.2
access_ip: 100.0.0.2
node2:
ansible_host: 100.0.0.3
ip: 100.0.0.3
access_ip: 100.0.0.3
node3:
ansible_host: 100.0.0.4
ip: 100.0.0.4
access_ip: 100.0.0.4
node4:
ansible_host: 100.0.0.5
ip: 100.0.0.5
access_ip: 100.0.0.5
node5:
ansible_host: 100.0.0.6
ip: 100.0.0.6
access_ip: 100.0.0.6
node6:
ansible_host: 100.0.0.7
ip: 100.0.0.7
access_ip: 100.0.0.7
children:
kube_control_plane:
hosts:
node1:
node2:
kube_node:
hosts:
node1:
node2:
node3:
node4:
node5:
node6:
etcd:
hosts:
node1:
node2:
node3:
k8s_cluster:
children:
kube_control_plane:
kube_node:
calico_rr:
hosts: {}
このファイルはKubernetesのインストールで使用することになります.このまま使用しても良いのですが,欲しい構成と異なるため,編集しておきます.
編集の前に,yamlの構成を見ておきます.階層構造を見やすくすると,以下のようになっていることがわかります.
all:
hosts:
node1:
node2:
node3:
node4:
node5:
node6:
children:
kube_control_plane:
kube-node:
etcd:
k8s-cluster:
children:
kube-master:
kube-node:
calico-rr:
各項目を簡単に解説します.
-
hosts
: kubernetesクラスタに含まれるマシンを列挙します -
children
: Kubernetesのマスター・ワーカーノードなどの設定を行います-
kube_control_plane
: マスターとなるマシンを列挙します -
kube-node
: ワーカーとなるマシンを列挙します -
etcd
: etcdをインストールするマシンを列挙します -
k8s-cluster
:children
としてKubernetesを構成するkube-master
,kube-node
を記述します.ここは編集しなくても大丈夫です. -
calico-rr
はcalicoの使用に関する設定です.Kubernetesのネットワークポリシーの実装に使用されるらしいのですが,詳しくは存じません.この記事の範疇では編集しなくて大丈夫です.
-
host.yml
の編集(amasterでのみ実行)
いま,我々はマスターノードが3つ欲しいので,kube_control_plane
にnode3
を追加してください:
...
children:
kube_control_plane:
hosts:
node1:
node2:
node3: # here!
kube_node:
hosts:
...
2.2 ansible-playbookの実行(amasterでのみ実行)
以上で準備完了です.
以下のコマンドでKubesprayによるkubernetesのインストールを実行します.
ansible-playbook -i inventory/mycluster/hosts.yml --become --become-user=root cluster.yml
時間がかかるのでしばらくお待ちください.(ネットワーク帯域幅にも依存しますが,概ね15〜30分前後かかりました)
2.3 kubectl
のインストール(kmasterでのみ実行)
kubernetes公式にしたがうならば,どのインストール方法でもよいと思われますが,私の環境でうまくいったコマンド例を掲載します.
kmaster1~3で以下を実行します.
curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
次にadmin.conf
ファイルを.kube
にコピーします.
sudo cp /etc/kubernetes/admin.conf /home/vagrant/config
mkdir .kube
mv config .kube/
sudo chown $(id -u):$(id -g ) $HOME/.kube/config
インストール後にkubectlのバージョンを確認してください
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:31:21Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.6", GitCommit:"8a62859e515889f07e3e3be6a1080413f17cf2c3", GitTreeState:"clean", BuildDate:"2021-04-15T03:19:55Z", GoVersion:"go1.15.10", Compiler:"gc", Platform:"linux/amd64"}
以上でkubesprayによるkubernetesのインストールは完了です.(超簡単ですね!)
3 kubernetesの動作確認
この章ではkubesprayとは関係なく,kubernetesの基本的な動作確認を行います.
まずはノードを確認(kmaster1~3で実行)
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready control-plane,master 9m10s v1.20.6
node2 Ready control-plane,master 8m23s v1.20.6
node3 Ready <none> 7m21s v1.20.6
node4 Ready <none> 7m21s v1.20.6
node5 Ready <none> 7m21s v1.20.6
node6 Ready <none> 7m21s v1.20.6
Deploymentも試してみましょう.deployment.yaml
を作成します.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.17
deploymentを作成して挙動を確認します.
$ kubectl apply -f deployment.yaml
deployment.apps/nginx-deployment created
$ kubectl get deployment,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 3/3 3 3 21s
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-db749865c-h4zpd 1/1 Running 0 21s
pod/nginx-deployment-db749865c-rxk72 1/1 Running 0 21s
pod/nginx-deployment-db749865c-s7wmn 1/1 Running 0 21s
Deploymentは3つのPodが稼働している状態を保とうとするはずです.試しに1つ削除してみましょう.
$ kubectl delete pod nginx-deployment-db749865c-h4zpd
pod "nginx-deployment-db749865c-h4zpd" deleted
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-db749865c-bkpnf 1/1 Running 0 12s
nginx-deployment-db749865c-rxk72 1/1 Running 0 67s
nginx-deployment-db749865c-s7wmn 1/1 Running 0 67s
完璧ですね!うまく動いているようです.
4. kubesprayによるクラスターの操作
ここではクラスターの基本的な操作をメモします.
詳細は公式のGetting startedを参照してください.
4.1 ノードの追加
hosts.yml
に書かれているノードのうち,足りないものが自動的に追加される
ansible-playbook -i inventory/mycluster/hosts.yml scale.yml -b -v
4.2 ノードの削除
-
node5
のようにノード名を指定する.(kworker2
のようにansibleにとっての識別名ではないので注意) - 公式では
--private-key=~/.ssh/private_key
のように秘密鍵を指定していたけど,なくても実行できてしまった.なぜだか理解できていない
ansible-playbook -i inventory/mycluster/hosts.yml remove-node.yml -b -v \
--extra-vars "node=node5"
5. 発展的な作業
metalLBの導入
クラウドでのkubernetesのマネージドサービスだと,気軽にtype:LoadBalancer Service
などを使ってしまうのですが,オンプレだとロードバランサを作らないと使えません.
ベアメタル上にk8s環境を構築している場合は MetalLB を導入することで,service や ingress でtype:LoadBalancer
を使えるようになります.
導入に成功し次第,この記事にまとめます.
導入方法について解説されているページは以下があるようです.