3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Kubespray を使った Kubernetes クラスターの作り方

Last updated at Posted at 2021-05-10

はじめに

この記事では 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文で書くともっと短く書けます)

Vagratnfile
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を実行すると配れます。

playbook.yml
- 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-rrcalicoの使用に関する設定です.Kubernetesのネットワークポリシーの実装に使用されるらしいのですが,詳しくは存じません.この記事の範疇では編集しなくて大丈夫です.

host.ymlの編集(amasterでのみ実行)

いま,我々はマスターノードが3つ欲しいので,kube_control_planenode3を追加してください:

...
  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を作成します.

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を使えるようになります.

導入に成功し次第,この記事にまとめます.

導入方法について解説されているページは以下があるようです.

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?