kubeadmでKubernetesクラスタを構築する
- 構築してからしばらく利用してきたKubernetesクラスタが壊れてしまい、再起不能となったため作り直す
- 今後のメモとして構築方法をまとめておく
今回作成するクラスタ
今回は、以下の環境のクラスタを構築する。
- 3台構成 (Master1台、Worker2台)
- Cent OS7
- minikubeは使わない (kubeadmを使って構築)
- 使用するkubectl / kubeadm / kubeletのバージョンは1.18.2
Masterの構築
各種パッケージのインストール
Masterを構築するサーバにログイン。
$ ssh k8s.master.kazono.co.jp
以下のコマンドを実行してkubernetes.repo
を/etc/yum.repos.d
に配置。
$ sudo tee /etc/yum.repos.d/kubernetes.repo <<EOF [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF
SELinuxを一時的に無効化。
$ sudo setenforce 0 $ sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
dockerをインストールして、サービスをstartさせておく。
$ sudo yum install -y docker $ sudo systemctl enable docker && sudo systemctl start docker
v1.6.0以降、KubernetesはデフォルトでCRI(Container Runtime Interface)の使用を有効にしており、kubeadmは既知のドメインソケットのリストをスキャンして、Linuxノード上のコンテナランタイムを自動的に検出しようするため。
検出可能なランタイムとソケットパスは、以下のとおり。
ランタイム ドメインソケット Docker /var/run/docker.sock conteinerd /run/containerd/containerd.sock CRI-O /var/run/crio/crio.sock
Dockerとcontainerdの両方が同時に検出された場合、Dockerが優先される。これはDocker 18.09にはcontainerdが同梱されており、両方が検出されてしまうため。他の2つ以上のランタイムが検出された場合、kubeadmはエラーを出力して終了する。
なお、もしコンテナランタイムとしてDockerを選択した場合、
kebelet
内に組み込まれたdockershim
CRIが使用される。
dockerのインストールと起動が正常に完了したら、kubelet
、kubeadm
、kubectl
をインストールして、kubelet
の自動起動を有効化。
$ sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes $ sudo systemctl enable --now kubelet
初期化と設定ファイルの準備
以下のコマンドでkubeadm
の初期化を実施。
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16
Your Kubernetes control-plane has initialized successfully! と表示されたらOK。kubeadm join ...
は今後Slaveを登録する際に必要な情報のため、どこかにメモしておく。
Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join <IP Addr>:6443 --token XXXXX \ --discovery-token-ca-cert-hash YYYYYY
初期化が完了すると/etc/kubernetes
ディレクトリ配下に設定ファイルが生成されるので、適切なファイルをホームディレクトリにcpする。
$ mkdir -p $HOME/.kube $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config
コンテナ間通信の準備
続いて、コンテナ間の通信を行うための仮想ネットワークに関する設定を行う。今回はcalico
を使って設定を行なっていく。
- flannelでもいいけど、開発が停滞している印象 (個人的主観)
- flannelでも上層部分でcalicoのネットワークポリシーを使ってそう
$ kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
正常に完了したら、以下のコマンドでcalicoがRunningになっていることを確認。
$ kubectl get pods -n kube-system
Masterの状態確認
ここまできたらkubectl get nodes
でクラスタにサービスインしているノードの情報が取れるはず。
$ kubectl get nodes ... k8s.master.kazono.co.jp Ready master 13m v1.18.2
Workerの追加
Masterが構築できたので、Workerをサービスインしていく。
各種パッケージのインストール
Masterを構築した時と同様にdocker
やkubelet
などをインストールしていく。
# repoファイルの準備 $ sudo tee /etc/yum.repos.d/kubernetes.repo <<EOF [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF #SELinuxの停止 $ sudo setenforce 0 $ sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config # dockerのインストール $ sudo yum install -y docker $ sudo systemctl enable docker && sudo systemctl start docker # kubelet, kubeadm, kubectlのインストール & kubeletの自動起動有効化 $ sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes $ sudo systemctl enable --now kubelet
インストールが完了したらMaster構築時 (kubeadm init
した時) に表示された kubeadm join
コマンドを実行。
「Then you can join any number of worker nodes by running the following on each as root」と書いてあるように、rootで実行すること。
$ sudo kubeadm join <IP Addr>:6443 --token XXXXX \ --discovery-token-ca-cert-hash YYYYYY
実行が正常に完了すると、「This node has joined the cluster」と表示されるので、Master側でkubectl get nodes
を実行してみる。
$ kubectl get nodes ... k8s.master.kazono.co.jp Ready master 27m v1.18.2 k8s.worker01.kazono.co.jp Ready <none> 2m55s v1.18.2 k8s.worker02.kazono.co.jp NotReady <none> 12s v1.18.2
想定通り、3台のノードが表示されたのでOK。
ROLEの設定
kubeadm
で追加したノードのROLEは基本的に設定されておらず<none>
になっている。このままでもいいが、nodeSelectorなどで特定のノードにpodを起動したいという場面もあるかもしれないので、設定しておく。
コマンド自体は↓のような感じ。
# Node: k8s.worker01.kazono.co.jp に workerというROLEを付与 $ kubectl label node k8s.worker01.kazono.co.jp node-role.kubernetes.io/worker=k8s.worker01.kazono.co.jp $ kubectl get nodes ... k8s.master.kazono.co.jp Ready master 38m v1.18.2 k8s.worker01.kazono.co.jp Ready worker 14m v1.18.2 k8s.worker02.kazono.co.jp Ready <none> 11m v1.18.2
ちなみにコマンドの構文としては以下のようになっている。
# 追加 $ kubectl label node <node name> node-role.kubernetes.io/<role name>=<key - (any name)> # 削除 $ kubectl label node <node name> node-role.kubernetes.io/<role name>-
Kubernetes Dashboardのデプロイ
詳細は別記事で。今回はv2を使っていく。
yamlをダウンロードして、NodePortを使用するようにyamlを修正して、kubectl apply
を実行。
$ wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml # NodePortを使うように修正 $ vi recommended.yaml $ kubectl apply -f recommended.yaml
namespaceにkubenetes-dashboard
を指定して、podが稼働していることを確認。
$ kubectl get service -n kubernetes-dashboard NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE dashboard-metrics-scraper ClusterIP 10.96.15.35 <none> 8000/TCP 6m42s kubernetes-dashboard NodePort 10.107.230.202 <none> 443:30843/TCP 6m43s
https://k8s.worker01.kazono.co.jp:30843/
へアクセス。
サインインを求められる画面にリダイレクトされるので、認証用のサービスアカウントを作成して、認証情報を取得してサインイン。
$ tee ~/admin-user.yaml <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboard EOF $ kubectl apply -f admin-user.yaml $ ADMIN=`kubectl get secret -n kubernetes-dashboard | grep admin | awk '{ print $1 }'` $ kubectl describe secret $ADMIN -n kubernetes-dashboard | grep token: | awk '{ print $2 }' # トークンが出力されるので、それをコピーしてサインイン