hidemium's blog

日々学んだことをアウトプットする。

KubesprayによるKubernetesのインストール

Kubernetesの環境を触ってみなくなり、Kubernetesのインストール方法でKubesprayが便利そうだったので、KubesprayによるKubernetesのインストールを試してみました。

構成

Kubesprayのダウンロード

Kubesprayをダウンロードします。

git clone https://github.com/kubernetes-sigs/kubespray

Ansibleのインストール

こちらの手順を確認しながら、venvの環境をインストールし、Ansibleをインストールしていきます。

kubespray/ansible.md at master · kubernetes-sigs/kubespray · GitHub

$ VENVDIR=kubespray-venv
$ KUBESPRAYDIR=kubespray
$ ANSIBLE_VERSION=2.12
$ python3 -m venv $VENVDIR
$ source $VENVDIR/bin/activate
$ cd $KUBESPRAYDIR
$ pip install -U -r requirements-$ANSIBLE_VERSION.txt
$ test -f requirements-$ANSIBLE_VERSION.yml && \
  ansible-galaxy role install -r requirements-$ANSIBLE_VERSION.yml && \
  ansible-galaxy collection -r requirements-$ANSIBLE_VERSION.yml

インベントリの作成

インベントリを作成していきます。リポジトリの中のsampleディレクトリをコピーし、自身の環境向けのhostファイルやgroup_varsを用意できます。

cp -r inventory/sample inventory/mycluster
declare -a IPS=(10.0.50.30 10.0.50.31 10.0.50.32 10.0.50.33 10.0.50.34)
CONFIG_FILE=inventory/mycluster/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]}

hosts.ymlファイルが生成されますが、構成を変えたいので、以下のように変更します。

今回はmasterノード3台とworkerノード2台にしています。

$ vi hosts.yml
all:
  hosts:
    kube-master01:
      ansible_host: 10.0.50.30
      ip: 10.0.50.30
      access_ip: 10.0.50.30
    kube-master02:
      ansible_host: 10.0.50.31
      ip: 10.0.50.31
      access_ip: 10.0.50.31
    kube-master03:
      ansible_host: 10.0.50.32
      ip: 10.0.50.32
      access_ip: 10.0.50.32
    kube-worker01:
      ansible_host: 10.0.50.33
      ip: 10.0.50.33
      access_ip: 10.0.50.33
    kube-worker02:
      ansible_host: 10.0.50.34
      ip: 10.0.50.34
      access_ip: 10.0.50.34
  children:
    kube_control_plane:
      hosts:
        kube-master01:
        kube-master02:
        kube-master03:
    kube_node:
      hosts:
        kube-worker01:
        kube-worker02:
    etcd:
      hosts:
        kube-master01:
        kube-master02:
        kube-master03:
    k8s_cluster:
      children:
        kube_control_plane:
        kube_node:
    calico_rr:
      hosts: {}

masterノードとworkerノードのデプロイ

以前、cloud-initを利用した仮想マシンのカスタマイズを書きましたが、Kubernetesの再作成が簡単になるため利用します。

hidemium.hatenablog.com

Ubuntu 22.04のテンプレートを作成し、以下のスペックでテンプレートを用意しておきます。

  • CPU: 1vCPU
  • Memory: 4GB
  • Disk: 100GB

masterノードとworkerノードのスペックはそれぞれの以下の通りになります。

node vCPU Memory Disk
master 1 4GB 100GB
worker 1 4GB 100GB

cloud-initでmasterノードとworkerノードのIPアドレスと公開鍵を設定を行っていきます。

IPアドレスを設定するために、以下のようにmetadataを作成します。こちらは仮想マシンごとにファイルを作成しておきます。

$ vi metadata-kube-master01.yaml
instance-id: kube-master01
local-hostname: kube-master01
hostname: kube-master01
network:
  version: 2
  ethernets:
    ens192:
      dhcp4: false
      addresses:
      - 10.0.50.30/24
      gateway4: 10.0.50.1
      nameservers:
        addresses:
        - 10.0.50.1

公開鍵を設定するために、以下のようにuserdataを作成します。こちらは全体で共通のファイルを作成しておきます。

$ vi userdata-kube.yaml
#cloud-config

users:
  - default
  - name: username
    ssh_authorized_keys:
      - 公開鍵をペースト
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: sudo, wheel
    lock_passwd: true
    shell: /bin/bash

firewallは閉じられているため変更はしていません。

$ sudo ufw status
Status: inactive

govcによるメタデータの追加

govcを利用するための環境変数を設定します。

$ export GOVC_URL=https://<vcenter fqdn>/sdk
$ export GOVC_USERNAME="username"
$ export GOVC_PASSWORD="password"
$ export GOVC_INSECURE="1"

masterノードとworkerノードごとに以下のコマンドを実行し、masterノードとworkerノードの仮想マシンをデプロイします。

$ export VMNAME="kube-master01"
$ export VM="/Datacenter/vm/path/to/$VMNAME"
$ govc vm.info "${VM}"
$ export METADATA=$(gzip -c9 <metadata-${VMNAME}.yaml | { base64 -w0 2>/dev/null || base64; }) USERDATA=$(gzip -c9 <userdata-kube.yaml | { base64 -w0 2>/dev/null || base64; })
$ govc vm.change -vm "${VM}" -e guestinfo.metadata="${METADATA}" -e guestinfo.metadata.encoding="gzip+base64" -e guestinfo.userdata="${USERDATA}" -e guestinfo.userdata.encoding="gzip+base64"
$ govc vm.power -on "${VM}"

以下のようにコマンドを実行すれば、まとめて仮想マシンをデプロイできます。

$ for VMNAME in kube-master0{1..3}; do
  echo ${VMNAME}
  export VM="/Datacenter/vm/path/to/$VMNAME"
  govc vm.clone -vm template-vm -on=false -folder="/Datacenter/vm/k8s" $VMNAME
  export METADATA=$(gzip -c9 <metadata-${VMNAME}.yaml | { base64 -w0 2>/dev/null || base64; }) USERDATA=$(gzip -c9 <userdata-kube.yaml | { base64 -w0 2>/dev/null || base64; })
  govc vm.change -vm "${VM}" -e guestinfo.metadata="${METADATA}" -e guestinfo.metadata.encoding="gzip+base64" -e guestinfo.userdata="${USERDATA}" -e guestinfo.userdata.encoding="gzip+base64"
  govc vm.power -on "${VM}"
done
$ for VMNAME in kube-worker0{1..2}; do
  echo ${VMNAME}
  export VM="/Datacenter/vm/path/to/$VMNAME"
  govc vm.clone -vm template-vm -on=false -folder="/Datacenter/vm/k8s" $VMNAME
  export METADATA=$(gzip -c9 <metadata-${VMNAME}.yaml | { base64 -w0 2>/dev/null || base64; }) USERDATA=$(gzip -c9 <userdata-kube.yaml | { base64 -w0 2>/dev/null || base64; })
  govc vm.change -vm "${VM}" -e guestinfo.metadata="${METADATA}" -e guestinfo.metadata.encoding="gzip+base64" -e guestinfo.userdata="${USERDATA}" -e guestinfo.userdata.encoding="gzip+base64"
  govc vm.power -on "${VM}"
done

Kubesprayによるクラスタ構築

以下のコマンドでKubernetesクラスタを構築することができます。

$ ansible-playbook -i inventory/mycluster/hosts.yml  --become --become-user=root cluster.yml

以下のようにログが出力され無事構築が完了します。30分程度で構築が完了します。

TASK [network_plugin/calico : Check if inventory match current cluster configuration] **************************************
ok: [kube-master01] => {
    "changed": false,
    "msg": "All assertions passed"
}
Thursday 22 December 2022  07:56:58 +0900 (0:00:00.101)       0:33:20.265 ***** 
Thursday 22 December 2022  07:56:58 +0900 (0:00:00.060)       0:33:20.325 ***** 
Thursday 22 December 2022  07:56:58 +0900 (0:00:00.060)       0:33:20.386 ***** 

PLAY RECAP *****************************************************************************************************************
kube-master01              : ok=744  changed=146  unreachable=0    failed=0    skipped=1270 rescued=0    ignored=9   
kube-master02              : ok=652  changed=135  unreachable=0    failed=0    skipped=1110 rescued=0    ignored=4   
kube-master03              : ok=654  changed=136  unreachable=0    failed=0    skipped=1108 rescued=0    ignored=4   
kube-worker01              : ok=507  changed=93   unreachable=0    failed=0    skipped=775  rescued=0    ignored=2   
kube-worker02              : ok=507  changed=93   unreachable=0    failed=0    skipped=775  rescued=0    ignored=2   
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Thursday 22 December 2022  07:56:58 +0900 (0:00:00.189)       0:33:20.576 ***** 
=============================================================================== 
download : download_container | Download image if required --------------------------------------------------------- 55.77s
download : download_file | Download item --------------------------------------------------------------------------- 51.95s
download : download_container | Download image if required --------------------------------------------------------- 51.70s
network_plugin/calico : Wait for calico kubeconfig to be created --------------------------------------------------- 47.02s
kubernetes/control-plane : Joining control plane node to the cluster. ---------------------------------------------- 46.59s
container-engine/containerd : download_file | Download item -------------------------------------------------------- 28.89s
download : download_file | Validate mirrors ------------------------------------------------------------------------ 28.20s
download : download_file | Download item --------------------------------------------------------------------------- 27.57s
download : download_container | Download image if required --------------------------------------------------------- 26.08s
kubernetes/control-plane : kubeadm | Initialize first master ------------------------------------------------------- 25.96s
kubernetes/preinstall : Preinstall | wait for the apiserver to be running ------------------------------------------ 24.94s
kubernetes/preinstall : Install packages requirements -------------------------------------------------------------- 24.79s
kubernetes/preinstall : Update package management cache (APT) ------------------------------------------------------ 24.47s
etcd : reload etcd ------------------------------------------------------------------------------------------------- 23.30s
download : download_file | Download item --------------------------------------------------------------------------- 23.14s
kubernetes/kubeadm : Join to cluster ------------------------------------------------------------------------------- 21.30s
download : download_container | Download image if required --------------------------------------------------------- 20.24s
container-engine/crictl : download_file | Download item ------------------------------------------------------------ 20.20s
download : download_container | Download image if required --------------------------------------------------------- 20.11s
download : download_container | Download image if required --------------------------------------------------------- 17.82s

kubectlのインストール

Ansibleの実行ノードにkubectlをインストールしていきます。

$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add
OK
$ sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
$ sudo apt update
$ sudo apt install kubectl

masterノードから /etc/kubernetes/admin.conf を取得します。

admin.confを取得するために、masterノードにログインし、ファイルの権限を変更しておきます。

$ ssh $USERNAME@$IP_CONTROLLER_0
$ USERNAME=$(whoami)
$ sudo chown -R $USERNAME:$USERNAME /etc/kubernetes/admin.conf
$ exit

masterノードから /etc/kubernetes/admin.conf を取得します。

scp -v $USERNAME@$IP_CONTROLLER_0:/etc/kubernetes/admin.conf kubespray-do.conf

serverのIPアドレスをmasterノードのIPアドレスに書き換えを行います。

$ vi kubespray-do.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: XXX
    server: https://10.0.50.30:6443  # 書き換え
  name: cluster.local
...

設定をロードして、接続ができることを確認します。

$ export KUBECONFIG=$PWD/kubespray-do.conf
$ kubectl get nodes
NAME            STATUS   ROLES           AGE   VERSION
kube-master01   Ready    control-plane   23h   v1.25.5
kube-master02   Ready    control-plane   23h   v1.25.5
kube-master03   Ready    control-plane   23h   v1.25.5
kube-worker01   Ready    <none>          23h   v1.25.5
kube-worker02   Ready    <none>          23h   v1.25.5

スモークテスト

動作確認を行います。

テスト用のpodを2台作成し、pod間で疎通が取れるか確認します。

$ kubectl run myshell1 -it --rm --image busybox -- sh
/ # hostname -i
10.233.68.2
/ # ping 10.233.92.3
PING 10.233.92.3 (10.233.92.3): 56 data bytes
64 bytes from 10.233.92.3: seq=0 ttl=62 time=0.659 ms
64 bytes from 10.233.92.3: seq=1 ttl=62 time=0.419 ms
^C
--- 10.233.92.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.419/0.539/0.659 ms
kubectl run myshell2 -it --rm --image busybox -- sh
/ # hostname -i
10.233.92.3

/ # ping 10.233.68.2
PING 10.233.68.2 (10.233.68.2): 56 data bytes
64 bytes from 10.233.68.2: seq=0 ttl=62 time=1.144 ms
64 bytes from 10.233.68.2: seq=1 ttl=62 time=0.489 ms
64 bytes from 10.233.68.2: seq=2 ttl=62 time=0.402 ms
^C
--- 10.233.68.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.402/0.678/1.144 ms

podの状態は以下の通りです。

$ kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE     IP            NODE            NOMINATED NODE   READINESS GATES
myshell1   1/1     Running   0          4m34s   10.233.68.2   kube-worker01   <none>           <none>
myshell2   1/1     Running   0          7s      10.233.92.3   kube-worker02   <none>           <none>

デプロイメント

nginxのdeploymentを作成します。

port-forwardを行い、nginxへcurlでアクセスができることを確認します。

$ kubectl create deployment nginx --image=nginx
$ kubectl get pods -l app=nginx
NAME                    READY   STATUS      RESTARTS   AGE
nginx-76d6c9b8c-kt6td   1/1     Running     0          13m
$ POD_NAME=$(kubectl get pods -l app=nginx -o jsonpath="{.items[0].metadata.name}")
$ kubectl port-forward $POD_NAME 8080:80
$ curl --head http://127.0.0.1:8080

動作確認ができため、deploymentを削除しておきます。

$ kubectl delete deployment nginx

リセット

以下のコマンドでKubernetesクラスタをリセットすることができます。

$ ansible-playbook -i inventory/mycluster/hosts.yml --become --become-user=root reset.yml

リセット後にKubesprayで再構築を行いましたが、再構築に失敗したため、仮想マシンごと削除して、govcで仮想マシンの再作成を行う行うことで、Kubernetesクラスタを何度も構築することができます。

$ govc vm.destroy "${VM}"

参考