ラベル Kubernetes の投稿を表示しています。 すべての投稿を表示
ラベル Kubernetes の投稿を表示しています。 すべての投稿を表示
2024年9月4日水曜日

Fluentdを使ってKubernetesのログをsyslogで送信する

KubernetesのPodのログはファイルに出力はされているが、1台のサーバーにログ集約を行い一元管理をしたい場合がある。そのような用途で利用されるソフトウェアとしてFluentdがある。

本記事では、Fluentdを使ってKubernetesのログをsyslogで送信する手順を記載する。

環境

今回の環境の構成概要図を以下に記載する。赤枠個所が本記事の設定個所となる。

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6
  • Docker : 24.0.6
  • cri-dockerd: 0.3.4
  • Kubernetes: v1.29.4

Fluentd導入

1. fluentd-kubernetes-daemonsetのマニフェストファイルをダウンロード

FluentdをKubernetesで動作させるため、fluentd-kubernetes-daemonsetを導入する。マニフェストファイルは以下からダウンロードできる。

今回はsyslogによるログ送信をしたいことから、fluentd-daemonset-syslog.yamlをダウンロードする。ダウンロード方法は任意となるが、curlを使う場合は以下の通り行う。

# curl -LO https://raw.githubusercontent.com/fluent/fluentd-kubernetes-daemonset/master/fluentd-daemonset-syslog.yaml

2. マニフェストファイルを修正

マニフェストファイルそのままではsyslogファイルを正常に送ることができないため、以下の★箇所の修正を行う。

fluentd-daemonset-syslog.yaml

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: fluentd
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
    version: v1

~(中略)~

---
apiVersion: apps/v1
kind: DaemonSet

~(中略)~

      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1-debian-syslog
        env:
          - name: K8S_NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name:  SYSLOG_HOST
            value: "192.168.1.1" # ★ログ送信先のsyslogサーバーを指定
          - name:  SYSLOG_PORT
            value: "514" # ★ポート番号を変更する場合は修正
          - name:  SYSLOG_PROTOCOL
            value: "tcp" # ★udpまたはtcpを指定
          - name:  FLUENTD_SYSTEMD_CONF
            value: "disable" # ★"No such file or directory retrying in 1s"のエラーログ抑止のため指定
          - name:  TZ
            value: "Asia/Tokyo" # ★Fluentdのログのタイムゾーンを指定(デフォルトはUTC)
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        # When actual pod logs in /var/lib/docker/containers, the following lines should be used.
        - name: dockercontainerlogdirectory     # ★アンコメント
          mountPath: /var/lib/docker/containers # ★アンコメント
          readOnly: true                        # ★アンコメント
        # When actual pod logs in /var/log/pods, the following lines should be used.
        #- name: dockercontainerlogdirectory    # ★コメントアウト
        #  mountPath: /var/log/pods             # ★コメントアウト
        #  readOnly: true                       # ★コメントアウト
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      # When actual pod logs in /var/lib/docker/containers, the following lines should be used.
      - name: dockercontainerlogdirectory  # ★アンコメント
        hostPath:                          # ★アンコメント
          path: /var/lib/docker/containers # ★アンコメント
      # When actual pod logs in /var/log/pods, the following lines should be used.
      #- name: dockercontainerlogdirectory # ★コメントアウト
      #  hostPath:                         # ★コメントアウト
      #    path: /var/log/pods             # ★コメントアウト

3. マニフェストファイルをapply

修正したマニフェストファイルapplyする。

# kubectl apply -f fluentd-daemonset-syslog.yaml
serviceaccount/fluentd created
clusterrole.rbac.authorization.k8s.io/fluentd created
clusterrolebinding.rbac.authorization.k8s.io/fluentd created
daemonset.apps/fluentd created

成功すると、fluentdのPodが各KubernetesノードでRunningとなるはずだ。

# kubectl get pod -n=kube-system
NAME                                READY   STATUS    RESTARTS      AGE
coredns-76f75df574-dntsp            1/1     Running   1 (51d ago)   105d
coredns-76f75df574-lswd4            1/1     Running   1 (51d ago)   105d
etcd-t1051kube                      1/1     Running   1 (51d ago)   105d
etcd-t1052kube                      1/1     Running   1 (51d ago)   105d
etcd-t1053kube                      1/1     Running   1 (51d ago)   105d
fluentd-k98t7                       1/1     Running   0             18s
fluentd-pn55s                       1/1     Running   0             18s
fluentd-xq6rb                       1/1     Running   0             18s
kube-apiserver-t1051kube            1/1     Running   1 (51d ago)   105d
kube-apiserver-t1052kube            1/1     Running   1 (51d ago)   105d
kube-apiserver-t1053kube            1/1     Running   1 (51d ago)   105d
kube-controller-manager-t1051kube   1/1     Running   3 (20d ago)   105d
kube-controller-manager-t1052kube   1/1     Running   2 (51d ago)   105d
kube-controller-manager-t1053kube   1/1     Running   2 (19d ago)   105d
kube-proxy-7lhj5                    1/1     Running   1 (51d ago)   105d
kube-proxy-gx8rj                    1/1     Running   1 (51d ago)   105d
kube-proxy-krjfz                    1/1     Running   1 (51d ago)   105d
kube-scheduler-t1051kube            1/1     Running   3 (51d ago)   105d
kube-scheduler-t1052kube            1/1     Running   1 (51d ago)   105d
kube-scheduler-t1053kube            1/1     Running   3 (19d ago)   105d

4. 動作確認

ログ送信先となるsyslogサーバーにてログの受信状況を確認する。以下は私の環境の例となる。Fluentd経由でSquidのPodの標準出力に対して出力された接続ログが出力されている。
※Podのログを収集する場合、標準出力に対して出力させるようコンテナを構成する必要があるため注意する。

Aug 31 18:07:00 fluentd-72t29 fluentd: log:1725095215.225  83353 10.244.1.0 TCP_TUNNEL/200 6767 CONNECT www.googleapis.com:443 - HIER_DIRECT/172.217.175.234 -
Aug 31 18:07:00 fluentd-72t29 fluentd: log:1725095215.225  63309 10.244.3.0 TCP_TUNNEL/200 2408 CONNECT play.google.com:443 - HIER_DIRECT/142.251.222.14 -
Aug 31 18:07:00 fluentd-72t29 fluentd: log:1725095215.225 138131 10.244.0.1 TCP_TUNNEL/200 28279 CONNECT apis.google.com:443 - HIER_DIRECT/172.217.175.238 -
Aug 31 18:07:00 fluentd-72t29 fluentd: log:1725095215.226  63194 10.244.0.1 TCP_TUNNEL/200 4006 CONNECT play.google.com:443 - HIER_DIRECT/142.251.222.14 -
Aug 31 18:07:00 fluentd-72t29 fluentd: log:1725095215.224  56514 10.244.1.0 TCP_TUNNEL/200 2491 CONNECT ogs.google.com:443 - HIER_DIRECT/142.250.196.110 -

以上で、Fluentdを使ってKubernetesのログをsyslogで送信する手順は完了となる。

2024年2月24日土曜日

Raspberry Pi 4上のUbuntuにKubernetesを構築する

本ブログでは、数回に分けてKubernetesの構築手順を記載してきた。

今回は、Raspberry Pi 4上のUbuntuに対してKubernetesを構築する手順を記載する。

環境

今回の手順を検証した環境は以下となる。

  • HW: Raspberry Pi 4 Model B(RAM 4GB)
  • OS: Ubuntu 22.04.4 LTS
  • コンテナランタイム: Docker : 24.0.1
  • CRI: cri-dockerd: 0.3.10-dev
  • Kubernetes: v1.28.5

手順

1. Dockerのインストール

Dockerのインストールはaptを使って実施するが、その際に利用する前提パッケージを先にインストールする。

sudo apt install apt-transport-https ca-certificates curl software-properties-common

Dockerのリポジトリを登録する。以前はapt-keyコマンドでも同様の登録ができてが、現在は非推奨となっていることから、curlでキー情報を入手し、登録する手順を実施する。

sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

Docker CEやその他必要となるパッケージをインストールする。

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Dockerの初期設定として、daemon.jsonを作成する。

$ sudo vi /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "insecure-registries": [
    "192.168.11.50"
  ]
}

Dockerのサービスを起動する。

sudo systemctl daemon-reload
sudo systemctl enable docker
sudo systemctl restart docker

2. Kubernetesインストール

Dockerと同様、Kubernetesもaptでインストールするため、リポジトリを登録する。

Kubernetes 1.28.xを使用する場合

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring_1.28.gpg
echo \
  'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | \
  sudo tee /etc/apt/sources.list.d/kubernetes_1.28.list
sudo apt update

Kubernetes 1.29.xを使用する場合

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/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.29/deb/ /' | \
  sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update

kubelet、kubeadm、kubectlをインストールする。今回は既存のKubernetesクラスターに追加するため、バージョンを1.28.5に固定している。さらにapt-mark holdをすることで、インストールしたパッケージが想定されないタイミングでバージョンアップされないようにしている。

sudo apt-get install kubelet=1.28.5-1.1 kubeadm=1.28.5-1.1 kubectl=1.28.5-1.1
sudo apt-mark hold kubelet kubeadm kubectl

kubeletのサービスを起動する。

sudo systemctl daemon-reload
sudo systemctl enable kubelet
sudo systemctl restart kubelet

3. Swap無効化

Kubernetesの前提条件として、Swapを無効化する必要がある。Raspberry PiのUbuntuの場合は、そもそもSwapが設定されておらず、totalの値が0になっているため、このまま作業を続行する。

$ free
               total        used        free      shared  buff/cache   available
Mem:         3880992      226264     2100932        3552     1553796     3472052
Swap:              0           0           0

4. cri-dockerdインストール

cri-dokerdはGo言語でコンパイルする必要があるため、まずはGoのインストールを行う。なお、Ubuntuの標準リポジトリのGoはバージョンが古いため、PPA (Personal Package Archives)のリポジトリ追加を行ったうえでインストールを行う。

sudo add-apt-repository ppa:longsleep/golang-backports
sudo apt update
sudo apt install golang-go

なお、今回のインストールされたGoのバージョンは、1.21.7となる。

$ go version
go version go1.21.7 linux/arm64

cri-dockerdのビルドと配置を行う。

go build -o bin/cri-dockerd
sudo install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
sudo cp -a packaging/systemd/* /etc/systemd/system
sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service

cri-dockerdのサービスを起動する。

sudo systemctl daemon-reload
sudo systemctl enable cri-docker.service
sudo systemctl start cri-docker.socket

5. Kubernetes起動

最後にKubernetesを起動するが、初めてKubernetesクラスターを構成する場合はkubeadm initを、既存のクラスターに参加する場合はkubeadm joinを行う。

それぞれ、過去記事を参考に対応をいただきたい。

新規にKubernetesクラスターを構成する場合

既存のKubernetesクラスターに参加する場合

今回は既存のクラスターに参加した。結果、以下の通りUbuntu 22.04.4 LTSのノードがKubernetesに登録できた。

$ kubectl get node -o=wide
NAME        STATUS   ROLES           AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                    KERNEL-VERSION              CONTAINER-RUNTIME
t1015rasp   Ready    control-plane   26h    v1.28.5   192.168.3.5   <none>        Ubuntu 22.04.4 LTS          5.15.0-1046-raspi           docker://25.0.3
t3051kube   Ready    control-plane   276d   v1.28.5   192.168.3.1   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6
t3052kube   Ready    control-plane   276d   v1.28.5   192.168.3.2   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6

以上で、Raspberry Pi 4上のUbuntuに対してKubernetesを構築する手順は完了となる。

2024年2月19日月曜日

Kubernetes構築手順① (cri-dockerdを使ってコントロールプレーンを構築)

今までminikubeを使ってKubernetes環境を手軽に構築をしてきたが、とうとう本家Kubernetesの構築を行うことにした。

Kubernetes構築は数回に分けて説明する。

本記事では、Kubernetesの管理機能であるコントールプレーンの構築手順を記載する。

なお、Kubernetesを利用する際は、CRI (Container Runtime Interface)と呼ばれるコンテナを操作するためのインタフェースを指定する必要がある。CRIにはcontainerd、CRI-O、Dockerなど選択できるが、今回はDocker用のCRIである「cri-dockerd」を利用する。

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6
  • Docker : 23.0.1
  • cri-dockerd: 0.3.1-dev
  • Kubernetes: v1.26.2

なお、私の環境ではインターネット接続時にプロキシ接続が必要となるため、プロキシ経由で接続するための設定も併せて行っている。

今回の構成の概要図を以下に記載する。

Dockerインストール

1. プロキシ設定 (必要な場合のみ)

私の環境ではプロキシ経由でなければインターネット接続ができないため、以下の通り環境変数を設定する。プロキシの環境変数について小文字と大文字の両方を設定している理由は、本環境変数はソフトウェアによっては小文字と大文字の区別をすることがあるため、念のため両方を設定している。

また、no_proxyの設定は、コントロールプレーンとなるホストのIPアドレスも指定している(今回であれば、192.168.11.51)。

export http_proxy=http://192.168.33.23:8080
export https_proxy=http://192.168.33.23:8080
export no_proxy=localhost,127.0.0.1,192.168.11.51,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
export HTTP_PROXY=http://192.168.33.23:8080
export HTTPS_PROXY=http://192.168.33.23:8080
export NO_PROXY=localhost,127.0.0.1,192.168.11.51,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

2. Dockerインストール前の競合パッケージの削除

Kubernetesが利用するコンテナエンジンはDockerを用いることにする。まずは、Dockerをインストールする。

ただし、GUI環境をインストールしたAlmaLinuxの場合、以下の通りpodmanとcontainers-commonのパッケージが競合する旨のエラーでインストールに失敗する。

# dnf install docker-ce docker-ce-cli containerd.io -y
メタデータの期限切れの最終確認: 0:05:01 時間前の 2022年11月26日 12時46分04秒 に 実施しました。
エラー:
 問題 1: インストール済パッケージの問題 podman-2:4.0.2-6.module_el8.6.0+2878+e681bc44.x86_64
  - パッケージ podman-2:4.0.2-6.module_el8.6.0+2878+e681bc44.x86_64 には runc >= 1.0.0-57 が必要ですが、どのプロバイダーからもインストールできません
  - パッケージ podman-3:4.2.0-4.module_el8.7.0+3344+484dae7b.x86_64 には runc >= 1.0.0-57 が必要ですが、どのプロバイダーからもインストールできません

~(中略)~

 問題 2: インストール済パッケージの問題 containers-common-2:1-27.module_el8.6.0+2878+e681bc44.x86_64
  - パッケージ containers-common-2:1-27.module_el8.6.0+2878+e681bc44.x86_64 には runc が必要ですが、どのプロバイダーからもインストールできません
  - パッケージ containers-common-2:1-43.module_el8.7.0+3344+484dae7b.x86_64 には runc が必要ですが、どのプロバイダーからもインストールできません

~(中略)~

このような場合は、一度podmanとcontainers-commonのパッケージを削除したうえで、Dockerをインストールしよう。

# dnf remove podman containers-common

3. Dockerをインストール

Dockerのインストールは以下の通りコマンドを実行すればよい。

# dnf install yum-utils -y
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# dnf install docker-ce docker-ce-cli containerd.io -y

4. Docker起動時の設定

プロキシ環境の場合は、外部からコンテナのダウンロードができるよう、systemctlの起動設定に環境変数の設定をしておくこと。

# sed -ie '/\[Service\]/a Environment="http_proxy=http://192.168.33.23:8080" "https_proxy=http://192.168.33.23:8080" "no_proxy=localhost,127.0.0.1,192.168.11.51,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"' /usr/lib/systemd/system/docker.service

また、Dockerのサービス起動時の設定ファイルであるdaemon.jsonを以下の通り作成する。Kubernetesを利用する場合は、以下2点を設定する必要がある。

  • cgroupdrivercgroupfssystemdに変更
  • insecure-registriesに必要に応じてプライベートのDockerコンテナレジストリを設定
# cat << EOF > /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ],
  "insecure-registries": [
    "192.168.11.54"
  ]
}
EOF

5. Dockerサービスを起動

最後に、Dockerのサービスを起動しておく。

# systemctl daemon-reload
# systemctl start docker
# systemctl enable docker

Kubernetesインストール

1. Kubernetesパッケージのリポジトリ設定

Kubernetesのリポジトリとして、以下の通りファイルを作成する。

# cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/repodata/repomd.xml.key
#exclude=kubelet kubeadm kubectl
EOF

2. Kubernetesパッケージインストール

Kubernetesのインストールに必要なパッケージとして、kubeletkubeadmkubectlをインストールする。また、関連して必要なパッケージであるiproute-tcも併せてインストールする。

パッケージ 説明
kubelet Kubernetesの各ノードにインストールされるエージェントとなり、Podの起動などを制御するサービス。
kubeadm Kubernetesの構築を行うためのツール。コントロールプレーンの構築や、
kubectl Kubernetesの管理を行うためのツール。
iproute-tc Linux Traffic Control utilityのパッケージ。
# dnf install kubelet kubeadm kubectl --disableexcludes=kubernetes -y
# dnf install iproute-tc -y

3. kubelet起動

インストールしたkubeletのサービスを起動させておく。

# systemctl start kubelet
# systemctl enable kubelet

4. swapの無効化

Kubernetesでは前提としてswapの無効化が必要となるため、無効化のコマンドを実行し、/etc/fstabにてswap領域をマウントしないよう設定する。

# swapoff -a
# sed -ie 's|\(^/dev/.* swap .*\)|#\1|' /etc/fstab

cri-dockerdインストール

1. 前提パッケージインストール

cri-dockerdは、GitHubに公開されているソースを用いてビルドしインストールする。そのため、gitwgetのパッケージをインストールする。

# dnf install git wget -y

2. cri-dockrdをビルド及び配置

cri-dockerdはgo言語を用いているため、goコマンドをインストールする。

goコマンドをインストールするためのツールが用意されているので、ダウンロードしてインストールする。rootでコマンドを実行した場合は、/root/.go/bin/goにインストールされ、~/.bash_profileにもパスが追記される。

# mkdir /tmp/cri-dockerd
# cd /tmp/cri-dockerd
# wget https://storage.googleapis.com/golang/getgo/installer_linux
# chmod +x ./installer_linux
# ./installer_linux
# source ~/.bash_profile

次に、cri-dockerdのソースをgit cloneしダウンロードする。

# git clone https://github.com/Mirantis/cri-dockerd.git

ダウンロードしたソースをビルドし、systemdのディレクトリに配置する。

# cd cri-dockerd
# mkdir -p bin
# go build -o bin/cri-dockerd
# install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
# cp -a packaging/systemd/* /etc/systemd/system
# sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service

3. cri-dockrdを起動

cri-dockerdをサービスとして起動する。

# systemctl daemon-reload
# systemctl enable cri-docker.service
# systemctl enable --now cri-docker.socket

kubeadmコマンドを用いてKubernetesクラスター作成

1. kubeadmコマンド実行

kubeadmコマンドを用いて、Kubernetesクラスターの作成を行う。クラスターの作成はkubeadm initコマンドにて実施する。「Your Kubernetes control-plane has initialized successfully!」が表示されれば成功となる。

オプションの説明を以下に記載する。

オプション 説明
--pod-network-cidr=10.244.0.0/16 ネットワークアドオンとしてflannelを追加する際に必要となる設定となる。Pod用のクラスターネットワークのネットワークアドレスを指定する。
--cri-socket=unix:///var/run/cri-dockerd.sock CRIとしてcri-dockerdを使うことを明示的に指定するために指定する。指定しない場合、containerdとcri-dockerdの2つがインストールされていることにより、「Found multiple CRI endpoints on the host」のエラーにてクラスターの作成に失敗するので注意しよう。
# kubeadm init --pod-network-cidr=10.244.0.0/16 --cri-socket=unix:///var/run/cri-dockerd.sock
[init] Using Kubernetes version: v1.26.2
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'

~(中略)~

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

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 192.168.11.51:6443 --token bexxee.xx866gxx91sxxa69 \
        --discovery-token-ca-cert-hash sha256:06d8e3077c71a3f7af2xx8d6b389d43673xx9a8axxa5d003ed8dccb356a42f80

2. Kubernetesクラスター状態確認

Kubernetesの管理はkubectlコマンドを使って実施するが、そのままでは使用できないので、環境変数で設定ファイルのパスを指定しておく。

# export KUBECONFIG=/etc/kubernetes/admin.conf

それでは、kubectlコマンドを使って、PodとNodeの状態を確認してみよう。以下の通り、各種コントロールプレーン用のPodと1台のNodeが表示される。

# kubectl get pod -A
NAMESPACE     NAME                                READY   STATUS    RESTARTS   AGE
kube-system   coredns-787d4945fb-cf2sf            0/1     Pending   0          45s
kube-system   coredns-787d4945fb-wkp86            0/1     Pending   0          45s
kube-system   etcd-t1051kube                      1/1     Running   0          59s
kube-system   kube-apiserver-t1051kube            1/1     Running   0          60s
kube-system   kube-controller-manager-t1051kube   1/1     Running   0          60s
kube-system   kube-proxy-lscpc                    1/1     Running   0          46s
kube-system   kube-scheduler-t1051kube            1/1     Running   0          60s

# kubectl get node
NAME        STATUS     ROLES           AGE   VERSION
t1051kube   NotReady   control-plane   83s   v1.26.2

上記を見ると、corednsがPendingのステータスとなっており、NodeのステータスもNotReadyとなっている。これはPod用のネットワークアドオンがインストールされていないために発生しており、後続の手順にてflannelをインストールするとステータスがRunningになるため、現時点では気にしなくて問題ない

ネットワークアドオンインストール (flannelインストール)

1. flannelインストール

Kubernetesのネットワークアドオンはいくつか選択肢があるようだが、今回はflannnelを利用する。flannelはインストール用のマニフェストファイルが公開されており、Kubernetes環境に適用するだけでインストールできる。

# cd ~
# curl -LO https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

# kubectl apply -f kube-flannel.yml
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

2. インストール後のPodとNodeの状態確認

インストール後、1分ほど待ってから再度PodとNodeの状態を確認してみよう。PendingステータスだったcorednsがRunningになり、NodeのステータスもReadyになっているはずだ。

# kubectl get pod -A
NAMESPACE      NAME                                READY   STATUS    RESTARTS   AGE
kube-flannel   kube-flannel-ds-8s4cq               1/1     Running   0          41s
kube-system    coredns-787d4945fb-cf2sf            1/1     Running   0          2m43s
kube-system    coredns-787d4945fb-wkp86            1/1     Running   0          2m43s
kube-system    etcd-t1051kube                      1/1     Running   0          2m57s
kube-system    kube-apiserver-t1051kube            1/1     Running   0          2m58s
kube-system    kube-controller-manager-t1051kube   1/1     Running   0          2m58s
kube-system    kube-proxy-lscpc                    1/1     Running   0          2m44s
kube-system    kube-scheduler-t1051kube            1/1     Running   0          2m58s

# kubectl get node
NAME        STATUS   ROLES           AGE     VERSION
t1051kube   Ready    control-plane   3m17s   v1.26.2

以上で、Kubernetesの管理機能であるコントールプレーンの構築手順は完了となる。とはいえ、これだけでは実際にコンテナを起動させることもできないため、次回以降でワーカーノードを追加していく。

更新履歴

  • 2023/3/11 新規作成
  • 2024/2/19 リポジトリのURLを最新情報に更新

2023年12月16日土曜日

Kubernetesにてノードの削除・追加を行う

Kubernetesでノードの調子が悪くなったりした際に、一度ノードを削除して同じ名前で再度追加をさせたい場合がある。

簡単にノードを削除・追加するだけであればよいが、Kubernetesの場合、少し追加で必要な作業がある。本記事では、Kubernetesにてノードの削除・追加を行うために必要な手順を記載する。

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6
  • Kubernetes : v1.28.2
  • Docker : 24.0.6
  • CRI : cri-dockerd 0.3.4
  • CNI : flannel v0.22.0

今回の構成の概要図を以下に記載する。

作業前のKubernetesのノードの状態は以下の通り。3台目に存在する「t1053kube」のノードを削除したのち、追加する手順を説明する。

# kubectl get node -o=wide
NAME        STATUS   ROLES           AGE    VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                    KERNEL-VERSION              CONTAINER-RUNTIME
t1051kube   Ready    control-plane   202d   v1.28.2   192.168.11.51   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6
t1052kube   Ready    control-plane   202d   v1.28.2   192.168.11.52   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6
t1053kube   Ready    control-plane   174d   v1.28.2   192.168.11.53   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6

ノード削除手順

1. Kubernetesクラスタからノードを削除

Kubernetesクラスタからノードを削除する際は、kubectl delete node [ノード名]で行う。処理はすぐに完了する。

# kubectl delete node t1053kube
node "t1053kube" deleted

3台存在したノードが2台になったことが確認できる。

# kubectl get node -o=wide
NAME        STATUS   ROLES           AGE    VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                    KERNEL-VERSION              CONTAINER-RUNTIME
t1051kube   Ready    control-plane   202d   v1.28.2   192.168.11.51   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6
t1052kube   Ready    control-plane   202d   v1.28.2   192.168.11.52   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6

2. ノードをリセット

削除した対象のOSにログインし、kubeadm resetを用いて、一度ノードをリセットする。なお、複数のCRIがインストールされている環境の場合は、--cri-socketオプションにて使用するCRIを明記する必要がある(オプションを指定しない場合、Found multiple CRI endpoints on the host.というエラーが表示されコマンドが失敗する)。

# kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock
[reset] Reading configuration from the cluster...
[reset] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
W1210 07:53:07.866239  247333 reset.go:120] [reset] Unable to fetch the kubeadm-config ConfigMap from cluster: failed to get node registration: failed to get node name from kubelet config: open /etc/kubernetes/kubelet.conf: no such file or directory
W1210 07:53:07.866312  247333 preflight.go:56] [reset] WARNING: Changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.
[reset] Are you sure you want to proceed? [y/N]: y ★"y"を入力
[preflight] Running pre-flight checks
W1210 07:53:09.421805  247333 removeetcdmember.go:106] [reset] No kubeadm config, using etcd pod spec to get data directory
[reset] Deleted contents of the etcd data directory: /var/lib/etcd
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Deleting contents of directories: [/etc/kubernetes/manifests /var/lib/kubelet /etc/kubernetes/pki]
[reset] Deleting files: [/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/bootstrap-kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf]

The reset process does not clean CNI configuration. To do so, you must remove /etc/cni/net.d

The reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually by using the "iptables" command.

If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.

The reset process does not clean your kubeconfig files and you must remove them manually.
Please, check the contents of the $HOME/.kube/config file.

3. etcdからNode情報を削除

Kubernetesクラスタから削除しても、etcdからは情報が削除されない。そこで、直接etcdのPodにログインし削除作業を行う。etcdにログインすると、プロンプトがsh-5.1#に変わる。

# kubectl exec -it -n kube-system etcd-t1051kube -- sh
sh-5.1#

etcdの操作はetcdctlコマンドで実行する。オプションが多いため超絶コマンドが長いが、以下の通りetcdctl member listを実行すると、現在etcdに登録されている情報を確認することができる。先ほどKubernetesクラスタから削除した「t1053kube」のノードの情報が残っていることがわかる。

sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 member list
391db64cfd0b76da, started, t1052kube, https://192.168.11.52:2380, https://192.168.11.52:2379, false
40f1e9f856640698, started, t1051kube, https://192.168.11.51:2380, https://192.168.11.51:2379, false
a642d0757a50ab59, started, t1053kube, https://192.168.11.53:2380, https://192.168.11.53:2379, false

テーブル形式でもう少し見やすくする場合は、etcdctl -w table member listを実行する。

sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 -w table member list
+------------------+---------+-----------+----------------------------+----------------------------+------------+
|        ID        | STATUS  |   NAME    |         PEER ADDRS         |        CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-----------+----------------------------+----------------------------+------------+
| 391db64cfd0b76da | started | t1052kube | https://192.168.11.52:2380 | https://192.168.11.52:2379 |      false |
| 40f1e9f856640698 | started | t1051kube | https://192.168.11.51:2380 | https://192.168.11.51:2379 |      false |
| a642d0757a50ab59 | started | t1053kube | https://192.168.11.53:2380 | https://192.168.11.53:2379 |      false |
+------------------+---------+-----------+----------------------------+----------------------------+------------+

削除対象の「t1053kube」のIDを引数として、etcdctl member remove [ID]を実行する。

sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 member remove a642d0757a50ab59
Member a642d0757a50ab59 removed from cluster 786da9e9c378caa1

再度登録状況を確認すると、「t1053kube」が削除されていることが確認できる。

sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 -w table member list
+------------------+---------+-----------+----------------------------+----------------------------+------------+
|        ID        | STATUS  |   NAME    |         PEER ADDRS         |        CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-----------+----------------------------+----------------------------+------------+
| 391db64cfd0b76da | started | t1052kube | https://192.168.11.52:2380 | https://192.168.11.52:2379 |      false |
| 40f1e9f856640698 | started | t1051kube | https://192.168.11.51:2380 | https://192.168.11.51:2379 |      false |
+------------------+---------+-----------+----------------------------+----------------------------+------------+

最後にexitでetcdから抜けておく。

sh-5.1# exit

ノード参加手順

1. 参加するためのtoken作成

ノード参加のためには、tokenを作成する必要がある。現在作成されているtokenは以下コマンドで確認できる。何も表示されない場合は、未登録であることを意味する。

# kubeadm token list

tokenを作成しつつノード追加のコマンドを表示させるため、以下コマンドを実行する。

# kubeadm token create --print-join-command
kubeadm join t1041kube.intrat.local:6443 --token hqrq5b.lmlys2u5vsqmza06 --discovery-token-ca-cert-hash sha256:cd21077ae8389da3990d28424f3e8aa1fcbf5394094bcb849803b8664d700b55

また、ノード追加時に必要となる証明書の更新も実施する。

# kubeadm init phase upload-certs --upload-certs
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
36568d37aa84232e623cd8df34c1704c2fb16e7846e7df92b55f13072ce262f0

再度tokenを確認すると、tokenと証明書の2行が表示されていることが確認できる。

# kubeadm token list
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
hqrq5b.lmlys2u5vsqmza06   23h         2023-12-10T22:41:01Z   authentication,signing   <none>                                                     system:bootstrappers:kubeadm:default-node-token
x87o7b.ya73txnsszqsx8x5   1h          2023-12-10T00:58:59Z   <none>                   Proxy for managing TTL for the kubeadm-certs secret        <none>

2. kubectl joinコマンド実行

token作成時に生成したkubeadm joinコマンドを実行し、ノードを再参加させる。なお、コントロールプレーンとして追加する場合は、--control-plane--certificate-keyのオプション指定が追加で必要となる。--cri-socketは前述したとおり、複数のCRIがインストールされている環境の場合に必要となる。

今回の場合はコントロールプレーンとしてノードを参加させるため、コマンドは以下のようになった。

kubeadm join t1041kube.intrat.local:6443 --token hqrq5b.lmlys2u5vsqmza06 \
--discovery-token-ca-cert-hash sha256:cd21077ae8389da3990d28424f3e8aa1fcbf5394094bcb849803b8664d700b55 \
--control-plane \
--certificate-key 36568d37aa84232e623cd8df34c1704c2fb16e7846e7df92b55f13072ce262f0 \
--cri-socket=unix:///var/run/cri-dockerd.sock

実際の実行結果は以下となる。

# kubeadm join t1041kube.intrat.local:6443 --token hqrq5b.lmlys2u5vsqmza06 \
> --discovery-token-ca-cert-hash sha256:cd21077ae8389da3990d28424f3e8aa1fcbf5394094bcb849803b8664d700b55 \
> --control-plane \
> --certificate-key 36568d37aa84232e623cd8df34c1704c2fb16e7846e7df92b55f13072ce262f0 \
> --cri-socket=unix:///var/run/cri-dockerd.sock
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[preflight] Running pre-flight checks before initializing the new control plane instance
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
W1210 08:16:25.328679  250776 checks.go:835] detected that the sandbox image "registry.k8s.io/pause:3.6" of the container runtime is inconsistent with that used by kubeadm. It is recommended that using "registry.k8s.io/pause:3.9" as the CRI sandbox image.
[download-certs] Downloading the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[download-certs] Saving the certificates to the folder: "/etc/kubernetes/pki"
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost t1053kube] and IPs [192.168.11.53 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost t1053kube] and IPs [192.168.11.53 127.0.0.1 ::1]
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local t1041kube.intrat.local t1053kube] and IPs [10.96.0.1 192.168.11.53]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
[kubeconfig] Generating kubeconfig files
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[check-etcd] Checking that the etcd cluster is healthy
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
[etcd] Announced new etcd member joining to the existing etcd cluster
[etcd] Creating static Pod manifest for "etcd"
[etcd] Waiting for the new etcd member to join the cluster. This can take up to 40s
The 'update-status' phase is deprecated and will be removed in a future release. Currently it performs no operation
[mark-control-plane] Marking the node t1053kube as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node t1053kube as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]

This node has joined the cluster and a new control plane instance was created:

* Certificate signing request was sent to apiserver and approval was received.
* The Kubelet was informed of the new secure connection details.
* Control plane label and taint were applied to the new node.
* The Kubernetes control plane instances scaled up.
* A new etcd member was added to the local/stacked etcd cluster.

To start administering your cluster from this node, 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

Run 'kubectl get nodes' to see this node join the cluster.

最後にノードの状態を確認すると「t1053kube」が正常に登録されステータスがReadyになっていることがわかる。

# kubectl get node -o=wide
NAME        STATUS   ROLES           AGE    VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                    KERNEL-VERSION              CONTAINER-RUNTIME
t1051kube   Ready    control-plane   202d   v1.28.2   192.168.11.51   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6
t1052kube   Ready    control-plane   202d   v1.28.2   192.168.11.52   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6
t1053kube   Ready    control-plane   17s    v1.28.2   192.168.11.53   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6

以上で、Kubernetesにてノードの削除・追加を行うために必要な手順は完了となる。

2023年10月21日土曜日

KubernetesのCNI「flannel」をバージョンアップする手順

先日Kubernetes環境をバージョンアップする手順を記載した。

前回はKubernetes本体のバージョンアップ手順を記載したが、関連コンポーネントであるCRI (Container Runtime Interface)やCNI (Container Network Interface)のバージョンアップについては言及していなかった。

私の自宅Kubernetes環境ではCNIとしてflannelを用いている。本記事ではKubernetesのCNI「flannel」をバージョンアップする手順を記載する。

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6
  • Kubernetes : v1.27.3
  • Docker : 23.0.5
  • CRI : cri-dockerd 0.3.4
  • CNI : flannel v0.21.5 -> v0.22.0

今回の構成の概要図を以下に記載する。

flannelバージョンアップ手順

1, 事前バージョン確認

flannelのバージョンアップ前のバージョン確認をしておく。Dockerのコンテナイメージの情報から、今回のバージョンアップ前のバージョンは、v0.21.5となっていることがわかる。

# docker images | grep flannel
flannel/flannel                             v0.21.5   a6c0cb5dbd21   2 months ago    68.9MB
flannel/flannel-cni-plugin                  v1.1.2    7a2dcab94698   7 months ago    7.97MB

2. 最新のマニフェストファイルを適用

flannelの最新のマニフェストファイルをダウンロードする。

# curl -LO https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

kubectl applyにて更新する。最下行のdaemonset.apps/kube-flannel-dsconfiguredとなっていれば、更新処理が実行される。

# kubectl apply -f kube-flannel.yml
namespace/kube-flannel unchanged
serviceaccount/flannel unchanged
clusterrole.rbac.authorization.k8s.io/flannel unchanged
clusterrolebinding.rbac.authorization.k8s.io/flannel unchanged
configmap/kube-flannel-cfg unchanged
daemonset.apps/kube-flannel-ds configured

3. バージョンアップ完了まで待機

マニフェストファイルを更新すると、ノード単位で順番にPodの再作成がされ自動的にローリングアップデートがされる。最終的に各ノードで動作していたkube-flannel-dsのPodは、新しいバージョンのPodとして起動する。

# kubectl get pod -n=kube-flannel -w
NAME                    READY   STATUS        RESTARTS      AGE
kube-flannel-ds-5bqnn   1/1     Terminating   4 (8d ago)    60d
kube-flannel-ds-mghhs   1/1     Running       2 (35d ago)   60d
kube-flannel-ds-x9mzn   1/1     Running       2 (35d ago)   60d
kube-flannel-ds-5bqnn   0/1     Terminating   4 (8d ago)    60d
kube-flannel-ds-5bqnn   0/1     Terminating   4 (8d ago)    60d
kube-flannel-ds-5bqnn   0/1     Terminating   4 (8d ago)    60d
kube-flannel-ds-fgg2w   0/1     Pending       0             0s
kube-flannel-ds-fgg2w   0/1     Pending       0             0s
kube-flannel-ds-fgg2w   0/1     Init:0/2      0             0s
kube-flannel-ds-fgg2w   0/1     Init:1/2      0             1s
kube-flannel-ds-fgg2w   0/1     PodInitializing   0             7s
kube-flannel-ds-fgg2w   1/1     Running           0             8s
kube-flannel-ds-mghhs   1/1     Terminating       2 (35d ago)   60d
kube-flannel-ds-mghhs   0/1     Terminating       2 (35d ago)   60d
kube-flannel-ds-mghhs   0/1     Terminating       2 (35d ago)   60d
kube-flannel-ds-mghhs   0/1     Terminating       2 (35d ago)   60d
kube-flannel-ds-ztdg7   0/1     Pending           0             0s
kube-flannel-ds-ztdg7   0/1     Pending           0             0s
kube-flannel-ds-ztdg7   0/1     Init:0/2          0             0s
kube-flannel-ds-ztdg7   0/1     Init:1/2          0             1s
kube-flannel-ds-ztdg7   0/1     PodInitializing   0             6s
kube-flannel-ds-ztdg7   1/1     Running           0             7s
kube-flannel-ds-x9mzn   1/1     Terminating       2 (35d ago)   60d
kube-flannel-ds-x9mzn   0/1     Terminating       2 (35d ago)   60d
kube-flannel-ds-x9mzn   0/1     Terminating       2 (35d ago)   60d
kube-flannel-ds-x9mzn   0/1     Terminating       2 (35d ago)   60d
kube-flannel-ds-cz2q4   0/1     Pending           0             0s
kube-flannel-ds-cz2q4   0/1     Pending           0             0s
kube-flannel-ds-cz2q4   0/1     Init:0/2          0             0s
kube-flannel-ds-cz2q4   0/1     Init:1/2          0             1s
kube-flannel-ds-cz2q4   0/1     PodInitializing   0             7s
kube-flannel-ds-cz2q4   1/1     Running           0             9s

4. 事後バージョン確認

flannelのバージョンアップ後のバージョン確認する。事前の確認においてv0.21.5だけだったコンテナイメージにv0.22.0が追加されている。

# docker images | grep flannel
flannel/flannel                                 v0.22.0   38c11b8f4aa1   7 weeks ago     69.8MB
flannel/flannel                                 v0.21.5   a6c0cb5dbd21   2 months ago    68.9MB
flannel/flannel-cni-plugin                      v1.1.2    7a2dcab94698   7 months ago    7.97MB

さらに、Podの詳細情報を確認すると、v0.22.0のコンテナイメージで起動していることが確認できる。

# kubectl describe pod kube-flannel-ds-cz2q4 -n=kube-flannel
Name:                 kube-flannel-ds-cz2q4
Namespace:            kube-flannel

~(中略)~

Containers:
  kube-flannel:
    Container ID:  docker://fcd1857a182c3622a9ba4bed91101e443d384705dcee03c97d0bf179704cec6d
    Image:         docker.io/flannel/flannel:v0.22.0 ★
    Image ID:      docker-pullable://flannel/flannel@sha256:5f83f1243057458e27249157394e3859cf31cc075354af150d497f2ebc8b54db

~(以下略)~

以上で、KubernetesのCNI「flannel」をバージョンアップする手順は完了となる。

2023年10月14日土曜日

KubernetesのCRI「cri-dockerd」をバージョンアップする手順

先日Kubernetes環境をバージョンアップする手順を記載した。

前回はKubernetes本体のバージョンアップ手順を記載したが、関連コンポーネントであるCRI (Container Runtime Interface)やCNI (Container Network Interface)のバージョンアップについては言及していなかった。

私の自宅Kubernetes環境ではCRIとしてcri-dockerdを用いている。本記事ではKubernetesのCRI「cri-dockerd」をバージョンアップする手順を記載する。

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6
  • Kubernetes : v1.27.3
  • Docker : 23.0.5
  • CRI : cri-dockerd 0.3.2 -> 0.3.4
  • CNI : flannel v0.22.0

今回の構成の概要図を以下に記載する。

cri-dockerdバージョンアップ手順

1. 事前バージョン確認

cri-dockerdのバージョンアップ前のバージョン確認をしておく。今回のバージョンアップ前のバージョンは、0.3.2となっていることがわかる。

# cri-dockerd --buildinfo
Program: cri-dockerd
Version: 0.3.2 (HEAD)
GitCommit: HEAD
Go version: go1.20.4

2. drain実行 (Podの退避・Podの配置の禁止)

一時的にcri-dockerdのサービス再起動が発生することから、念のためバージョンアップ対象ノードからPodを退避(drain)したのち、Podの配置を禁止(cordon)する。

# kubectl drain t1051kube --ignore-daemonsets
node/t1051kube cordoned
~(以下略)~

drainされると、ノードのステータスがSchedulingDisabledとなる。

# kubectl get node
NAME        STATUS                     ROLES           AGE   VERSION
t1051kube   Ready,SchedulingDisabled   control-plane   62d   v1.27.3
t1052kube   Ready                      control-plane   62d   v1.27.3
t1053kube   Ready                      control-plane   34d   v1.27.3

3. cri-dockerdのバージョンアップ

git cloneにてcri-dockerdのリポジトリから必要なファイルを入手する。

# git clone https://github.com/Mirantis/cri-dockerd.git

cri-dockerdはGo言語にてビルドする必要があるため、そちらに必要となるファイルも入手する。

# wget https://storage.googleapis.com/golang/getgo/installer_linux
# chmod +x ./installer_linux
# ./installer_linux

cri-dockerdの公式手順に従い、再インストールを行う。

# cd cri-dockerd/
# mkdir -p bin
# /root/.go/bin/go build -o bin/cri-dockerd
# install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
# cp -af packaging/systemd/* /etc/systemd/system
# sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service

最後にcri-dockerdのサービスを再起動する。

# systemctl daemon-reload
# systemctl restart cri-docker.service

4. uncordon実行

バージョンアップが完了したので、対象ノードのcordon状態を解消するため、uncordonを実行する。

# kubectl uncordon t1051kube

最終的にノードがバージョンアップされた状態でReadyとなった。

# kubectl get node
NAME        STATUS   ROLES           AGE   VERSION
t1051kube   Ready    control-plane   62d   v1.27.3
t1052kube   Ready    control-plane   62d   v1.27.3
t1053kube   Ready    control-plane   34d   v1.27.3

5. 事後バージョン確認

cri-dockerdのバージョンアップ後のバージョン確認する。事前の確認において0.3.2だったものが0.3.4となっていることがわかる。

# cri-dockerd --buildinfo
Program: cri-dockerd
Version: 0.3.4 (HEAD)
GitCommit: HEAD
Go version: go1.20.6

6. 手順1~5を残りのノードに対して繰り返す

残りのノードに対してもdrain、バージョンアップ、uncordonを繰り返しながらローリングアップデートを実行する。

以上で、KubernetesのCRI「cri-dockerd」をバージョンアップする手順は完了となる。

2023年9月30日土曜日

Kubernetes Metrics Server導入手順 (kubectl topコマンドを使えるようにする)

Kubernetes環境のCPUやメモリリソースの使用率をKubernetes API経由で確認するための機能として、「Kubernetes Metrics Server」がある。

Kubernetes Metrics Serverは、標準ではインストールされておらず使用できない。そのため、kubectl topコマンドでリソース情報を取得しようとしても、以下の通り"Metrics API not available"のエラーで失敗する。

# kubectl top node
error: Metrics API not available

# kubectl top pod -A
error: Metrics API not available

Kubernetes Metrics Serverは、マニフェストファイルをApplyすることで簡単に導入することができる。本記事では、Kubernetes Metrics Serverの導入手順を記載する。導入することでkubectl topコマンドを利用できるようにする。

環境

環境は以下の通り。

  • ホストOS : AlmaLinux 8.6
  • Kubernetes: v1.27.3
  • Kubernetes Metrics Server: v0.6.3 (2023/7/16導入)

Kubernetes Metrics Server導入手順

1. インストール用マニフェストファイルのダウンロード

Kubernetes Metrics Serverはマニフェストファイルを用いることでインストールできる。公式手順は直接kubectl apply [URL]コマンドを実行しているが、今回は次の手順で一部マニフェストファイルを編集をするため、先にcurlコマンドでダウンロードを行う。

#curl -LO https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# ls -l
-rw-r--r-- 1 root root 4186  7月 16 17:20 components.yaml

2. マニフェストファイルを編集

Kubernetes Metrics ServerへはHTTPSによる通信にて接続を行うが、その際にSSL証明書の検証が動作し、検証に失敗すると正常にリソース情報を取得することができない。

そこで、--kubelet-insecure-tlsのオプションを追加し、証明書の検証を行わないよう設定する。

components.yaml

~(中略)~

  strategy:
    rollingUpdate:
      maxUnavailable: 0
  template:
    metadata:
      labels:
        k8s-app: metrics-server
    spec:
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        - --kubelet-use-node-status-port
        - --metric-resolution=15s
        - --kubelet-insecure-tls    # <-★追加

~(以下略)~

3. マニフェストファイルをapply

修正したマニフェストファイルをapplyする。

# kubectl apply -f components.yaml
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created

4. Pod及びサービスリソースの起動確認

10秒ほど経過してから確認すると、Podとサービスリソースが正常に展開されているはずだ。

# kubectl get pod -n=kube-system
NAME                                READY   STATUS    RESTARTS      AGE
~(中略)~
metrics-server-7db4fb59f9-skc7s     1/1     Running   0             144m

# kubectl get service -n=kube-system
NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
kube-dns         ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP,9153/TCP   53d
metrics-server   ClusterIP   10.107.188.51   <none>        443/TCP                  3h2m

もし、PodのREADYが0/1などになっている場合は正常にコンテナが起動していない可能性があるため、Podのログを確認して原因調査が必要となる。例えば、--kubelet-insecure-tlsオプションを付与しておらず証明書の検証に失敗した場合は、以下のような"statuscode: 500"のエラーが表示される。

# kubectl describe pod metrics-server-7b4c4d4bfd-tbctq -n=kube-system
Name:                 metrics-server-7b4c4d4bfd-tbctq
Namespace:            kube-system

~(中略)~

Events:
  Type     Reason     Age                   From               Message
  ----     ------     ----                  ----               -------
  Normal   Scheduled  5m48s                 default-scheduler  Successfully assigned kube-system/metrics-server-7b4c4d4bfd-tbctq to t3052kube
  Normal   Pulled     5m48s                 kubelet            Container image "registry.k8s.io/metrics-server/metrics-server:v0.6.3" already present on machine
  Normal   Created    5m48s                 kubelet            Created container metrics-server
  Normal   Started    5m48s                 kubelet            Started container metrics-server
  Warning  Unhealthy  38s (x33 over 5m28s)  kubelet            Readiness probe failed: HTTP probe failed with statuscode: 500
  ↑★"statuscode: 500"のエラー

5. kubectl topコマンドで動作確認

kubectl topコマンドでノードとPodのリソース取得ができることの確認をしてみよう。

ノードの場合

# kubectl top node
NAME        CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
t3051kube   121m         3%     2459Mi          67%
t3052kube   90m          2%     1076Mi          29%
t3053kube   105m         2%     2470Mi          68%

Podの場合

[root@t3051kube metrics-server]# kubectl top pod -A
NAMESPACE      NAME                                 CPU(cores)   MEMORY(bytes)
~(中略)~
mynamespace    almalinux-postfix-7b4577c6bc-fq578   1m           36Mi
mynamespace    almalinux-postfix-7b4577c6bc-hds6v   1m           43Mi
mynamespace    almalinux-postfix-7b4577c6bc-mtrnp   1m           42Mi
mynamespace    almalinux-squid-d66588dbb-g6tn6      1m           200Mi
mynamespace    almalinux-squid-d66588dbb-m5fff      1m           279Mi
mynamespace    almalinux-squid-d66588dbb-t9lg6      1m           266Mi
mynamespace    almalinux-unbound-66c9746bff-92htn   0m           42Mi
mynamespace    almalinux-unbound-66c9746bff-f5gmk   0m           37Mi
mynamespace    almalinux-unbound-66c9746bff-rnw8m   0m           40Mi

以上で、Kubernetes Metrics Serverの導入手順は終了となる。

2023年7月22日土曜日

kubectl versionコマンド実行時に"deprecated"の警告メッセージを出力させない方法

Kubernetes環境のバージョンは、kubectl versionコマンドを用いることで確認することができる。しかし、Kubernetes v1.27.3の環境で試したところ、以下の通りWARNING: This version information is deprecatedの警告メッセージが表示される。

# kubectl version
WARNING: This version information is deprecated and will be replaced with the output from kubectl version --short.  Use --output=yaml|json to get the full version.
Client Version: version.Info{Major:"1", Minor:"27", GitVersion:"v1.27.3", GitCommit:"25b4e43193bcda6c7328a6d147b1fb73a33f1598", GitTreeState:"clean", BuildDate:"2023-06-14T09:53:42Z", GoVersion:"go1.20.5", Compiler:"gc", Platform:"linux/amd64"}
Kustomize Version: v5.0.1
Server Version: version.Info{Major:"1", Minor:"27", GitVersion:"v1.27.3", GitCommit:"25b4e43193bcda6c7328a6d147b1fb73a33f1598", GitTreeState:"clean", BuildDate:"2023-06-14T09:47:40Z", GoVersion:"go1.20.5", Compiler:"gc", Platform:"linux/amd64"}

警告メッセージにkubectl version --shortとあるので、ためしにそれを実行すると、今度はFlag --short has been deprecatedという警告が出てきた。このメッセージは、将来的にオプションを付けなくてもデフォルト表示になる旨を示しており無視しても問題なさそうだが、気にはなってしまう。。

# kubectl version --short
Flag --short has been deprecated, and will be removed in the future. The --short output will become the default.
Client Version: v1.27.3
Kustomize Version: v5.0.1
Server Version: v1.27.3

本記事では、kubectl versionコマンドを実行する際にdeprecatedの警告メッセージを表示させないようにする方法を記載する。

環境

  • Kubernetes v1.27.3

解決方法

警告メッセージを表示させないようにするには、以下の通りkubectl versionコマンドに--output=yamlまたは--output=jsonのオプションを付与すればよい。それぞれ、出力形式をYAMLまたはJSONに整形し、詳細情報を表示するオプションとなる(オプションは-o=yamlのように省略して記載可能)。

以下に出力例を記載する。

YAML形式

# kubectl version --output=yaml
clientVersion:
  buildDate: "2023-06-14T09:53:42Z"
  compiler: gc
  gitCommit: 25b4e43193bcda6c7328a6d147b1fb73a33f1598
  gitTreeState: clean
  gitVersion: v1.27.3
  goVersion: go1.20.5
  major: "1"
  minor: "27"
  platform: linux/amd64
kustomizeVersion: v5.0.1
serverVersion:
  buildDate: "2023-06-14T09:47:40Z"
  compiler: gc
  gitCommit: 25b4e43193bcda6c7328a6d147b1fb73a33f1598
  gitTreeState: clean
  gitVersion: v1.27.3
  goVersion: go1.20.5
  major: "1"
  minor: "27"
  platform: linux/amd64

JSON形式

# kubectl version --output=json
{
  "clientVersion": {
    "major": "1",
    "minor": "27",
    "gitVersion": "v1.27.3",
    "gitCommit": "25b4e43193bcda6c7328a6d147b1fb73a33f1598",
    "gitTreeState": "clean",
    "buildDate": "2023-06-14T09:53:42Z",
    "goVersion": "go1.20.5",
    "compiler": "gc",
    "platform": "linux/amd64"
  },
  "kustomizeVersion": "v5.0.1",
  "serverVersion": {
    "major": "1",
    "minor": "27",
    "gitVersion": "v1.27.3",
    "gitCommit": "25b4e43193bcda6c7328a6d147b1fb73a33f1598",
    "gitTreeState": "clean",
    "buildDate": "2023-06-14T09:47:40Z",
    "goVersion": "go1.20.5",
    "compiler": "gc",
    "platform": "linux/amd64"
  }
}

以上。

2023年7月8日土曜日

Kubernetesバージョンアップ手順

Kubernetesはバージョンアップ頻度が高く、おおよそ4か月に1回のペースで新しいマイナーバージョンがリリースされている。

バージョン リリース日
1.27 2023-04-11
1.26 2022-12-09
1.25 2022-08-23

サポートが有効なバージョンは最新の3世代となることから、結果として12ヶ月に1回はバージョンアップし、サポートされる状態を維持する必要がある。

Kubernetesのバージョンアップは決められた手順に従い実施すればそこまで難しいものではない。本記事では、Kubernetesのバージョンアップ手順を記載する。

環境

以下に各種ソフトウェアのバージョンを記載する。今回はバージョン1.27のパッチバージョンのバージョンアップとなるが、おそらくマイナーバージョン(例えば、1.27 -> 1.28)などでも同様の手順で実施できると想定している。

  • ホストOS : AlmaLinux 8.6
  • Kubernetes:
    • バージョンアップ前 : v1.27.1
    • バージョンアップ後 : v1.27.3

クラスターは3台で構成し、すべてコントロールプレーンのノードとなる。冗長化されたコントロールプレーンのKubernetesクラスターの構築手順は以下記事を参照いただきたい。

以下に、本記事で用いるKubernetes環境の構成概要図と、バージョンアップ手順の概要を記載する。

Kubernetesバージョンアップ手順

1. kubeadmバージョンアップ

バージョンアップ前のバージョン確認をしておく。kubeadmやノードのバージョンは、v1.27.1となっていることがわかる。

# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"27", GitVersion:"v1.27.1", GitCommit:"4c9411232e10168d7b050c49a1b59f6df9d7ea4b", GitTreeState:"clean", BuildDate:"2023-04-14T13:20:04Z", GoVersion:"go1.20.3", Compiler:"gc", Platform:"linux/amd64"}

# kubectl get node
NAME        STATUS   ROLES           AGE   VERSION
t3051kube   Ready    control-plane   25d   v1.27.1
t3052kube   Ready    control-plane   25d   v1.27.1
t3053kube   Ready    control-plane   25d   v1.27.1

kubeadmdnfコマンドでバージョンを指定することで、特定のバージョンへバージョンアップすることができる。

# dnf install kubeadm-1.27.3-0 --disableexcludes=kubernetes -y
メタデータの期限切れの最終確認: 0:01:42 時間前の 2023年06月18日 07時33分08秒 に実施しました。
依存関係が解決しました。
====================================================================================================================================================
 パッケージ                        アーキテクチャー                 バージョン                           リポジトリー                         サイズ
====================================================================================================================================================
アップグレード:
 kubeadm                           x86_64                           1.27.3-0                             kubernetes                            11 M

トランザクションの概要
====================================================================================================================================================
アップグレード  1 パッケージ

ダウンロードサイズの合計: 11 M

~(以下略)~

バージョンアップ後、kubeadmがバージョンアップされていることを確認しよう。今回であれば、v1.27.1 -> v1.27.3になっていることが確認できる。

# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"27", GitVersion:"v1.27.3", GitCommit:"25b4e43193bcda6c7328a6d147b1fb73a33f1598", GitTreeState:"clean", BuildDate:"2023-06-14T09:52:26Z", GoVersion:"go1.20.5", Compiler:"gc", Platform:"linux/amd64"}

2. アップグレードプランの確認

アップグレードプランを確認する。ここで、現在のKubernetesクラスターの状態が確認され、最終的にバージョンアップに必要なコマンドが表示される。

# kubeadm upgrade plan
[upgrade/config] Making sure the configuration is correct:
[upgrade/config] Reading configuration from the cluster...
[upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[preflight] Running pre-flight checks.
[upgrade] Running cluster health checks
[upgrade] Fetching available versions to upgrade to
[upgrade/versions] Cluster version: v1.27.2
[upgrade/versions] kubeadm version: v1.27.3
[upgrade/versions] Target version: v1.27.3
[upgrade/versions] Latest version in the v1.27 series: v1.27.3

Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
COMPONENT   CURRENT       TARGET
kubelet     3 x v1.27.1   v1.27.3

Upgrade to the latest version in the v1.27 series:

COMPONENT                 CURRENT   TARGET
kube-apiserver            v1.27.2   v1.27.3
kube-controller-manager   v1.27.2   v1.27.3
kube-scheduler            v1.27.2   v1.27.3
kube-proxy                v1.27.2   v1.27.3
CoreDNS                   v1.10.1   v1.10.1
etcd                      3.5.7-0   3.5.7-0

You can now apply the upgrade by executing the following command:

        kubeadm upgrade apply v1.27.3

_____________________________________________________________________


The table below shows the current state of component configs as understood by this version of kubeadm.
Configs that have a "yes" mark in the "MANUAL UPGRADE REQUIRED" column require manual config upgrade or
resetting to kubeadm defaults before a successful upgrade can be performed. The version to manually
upgrade to is denoted in the "PREFERRED VERSION" column.

API GROUP                 CURRENT VERSION   PREFERRED VERSION   MANUAL UPGRADE REQUIRED
kubeproxy.config.k8s.io   v1alpha1          v1alpha1            no
kubelet.config.k8s.io     v1beta1           v1beta1             no
_____________________________________________________________________

3. Kubernetesクラスターのバージョンアップ (1台目)

アップグレードプランの確認で出力されたkubeadm upgrade apply [ターゲットバージョン]コマンドを用いてKubernetesクラスターのバージョンアップを行う。この作業はコントロールプレーンの1台で実行する。

# kubeadm upgrade apply v1.27.3
[upgrade/config] Making sure the configuration is correct:
[upgrade/config] Reading configuration from the cluster...

~(中略)~

[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.27.3". Enjoy!

[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.

4. Kubernetesクラスターのバージョンアップ (2台目以降)

コントロールプレーンが冗長化されている場合は、2台目以降のすべてのコントロールプレーンのノードにて、kubeadm upgrade nodeコマンドを実行する。

# kubeadm upgrade node
[upgrade] Reading configuration from the cluster...
[upgrade] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
W0618 07:46:01.123220 3723323 images.go:80] could not find officially supported version of etcd for Kubernetes v1.27.3, falling back to the nearest etcd version (3.5.7-0)
W0618 07:46:27.546881 3723323 checks.go:835] detected that the sandbox image "registry.k8s.io/pause:3.6" of the container runtime is inconsistent with that used by kubeadm. It is recommended that using "registry.k8s.io/pause:3.9" as the CRI sandbox image.
[upgrade] Upgrading your Static Pod-hosted control plane instance to version "v1.27.3"...

~(中略)~

[upgrade] The configuration for this node was successfully updated!
[upgrade] Now you should go ahead and upgrade the kubelet package using your package manager.

5. drain実行 (Podの退避・Podの配置の禁止)

Kubernetesクラスターのバージョンアップが完了したら、各ノードのkubelet及びkubectlのバージョンアップを行う。

一時的にkubeletの再起動が発生することから、バージョンアップ対象ノードからPodを退避(drain)したのち、Podの配置を禁止(cordon)する。

# kubectl drain t3051kube --ignore-daemonsets
node/t3051kube cordoned
Warning: ignoring DaemonSet-managed Pods: kube-flannel/kube-flannel-ds-x9mzn, kube-system/kube-proxy-6q4qn

~(中略)~

node/t3051kube drained

drainされると、ノードのステータスがSchedulingDisabledとなる。

# kubectl get node
NAME        STATUS                     ROLES           AGE   VERSION
t3051kube   Ready,SchedulingDisabled   control-plane   25d   v1.27.1
t3052kube   Ready                      control-plane   25d   v1.27.1
t3053kube   Ready                      control-plane   25d   v1.27.1

6. kubelet及びkubectlのバージョンアップ

kubelet及びkubectldnfコマンドでバージョンを指定することで、特定のバージョンへバージョンアップすることができる。

# dnf install kubelet-1.27.3-0 kubectl-1.27.3-0 --disableexcludes=kubernetes -y
メタデータの期限切れの最終確認: 0:28:16 時間前の 2023年06月18日 07時33分08秒 に実施しました。
依存関係が解決しました。
====================================================================================================================================================
 パッケージ                        アーキテクチャー                 バージョン                           リポジトリー                         サイズ
====================================================================================================================================================
アップグレード:
 kubectl                           x86_64                           1.27.3-0                             kubernetes                            11 M
 kubelet                           x86_64                           1.27.3-0                             kubernetes                            20 M

トランザクションの概要
====================================================================================================================================================
アップグレード  2 パッケージ

ダウンロードサイズの合計: 31 M

~(以下略)~

7. kubelet再起動

kubeletのバージョンアップ後、再起動を行う。

# systemctl daemon-reload
# systemctl restart kubelet

ノードの状態を確認すると、バージョンがv1.27.1 -> v1.27.3となっていることがわかる。

# kubectl get node
NAME        STATUS                     ROLES           AGE   VERSION
t3051kube   Ready,SchedulingDisabled   control-plane   25d   v1.27.3
t3052kube   Ready                      control-plane   25d   v1.27.1
t3053kube   Ready                      control-plane   25d   v1.27.1

8. uncordon実行

バージョンアップが完了したので、対象ノードのcordon状態を解消するため、uncordonを実行する。

# kubectl uncordon t3051kube

最終的にノードがバージョンアップされた状態でReadyとなった。

# kubectl get node
NAME        STATUS   ROLES           AGE   VERSION
t3051kube   Ready    control-plane   25d   v1.27.3
t3052kube   Ready    control-plane   25d   v1.27.1
t3053kube   Ready    control-plane   25d   v1.27.1

9. 手順5~8を残りのノードに対して繰り返す

残りのノードに対してもdrain、kubeletバージョンアップ、uncordonを繰り返しながらローリングアップデートを実行する。

以下は2台目の実行例となる。

# kubectl drain t3052kube --ignore-daemonsets
node/t3051kube cordoned

# dnf install kubelet-1.27.3-0 kubectl-1.27.3-0 --disableexcludes=kubernetes -y
# systemctl daemon-reload
# systemctl restart kubelet

# kubectl uncordon t3052kube

# kubectl get node
NAME        STATUS     ROLES           AGE   VERSION
t3051kube   Ready      control-plane   25d   v1.27.3
t3052kube   NotReady   control-plane   25d   v1.27.3
t3053kube   Ready      control-plane   25d   v1.27.1

以上で、Kubernetesのバージョンアップ手順は完了となる。

参考

2023年6月24日土曜日

AnsibleでKubernetesを操作する

自宅ではAnsibleを導入してから、以下OSやソフトウェアに対して作業のコード化や自動化を行ってきた。導入手順などは以下記事を参照。

OS/ソフトウェア URL
Linux AnsibleでLinuxサーバの初期設定と単体テストを行う
Windows Server AnsibleからWindows Serverに接続するための事前作業
vSphere ESXi AnsibleでESXi上に仮想マシンを構築する

今回は、Ansibleを使ってKubernetesを操作する手順を記載する。Kubernetesは、Ansibleに標準で導入されているkubernetes.coreというモジュールで操作可能となる。

# ansible-galaxy collection list

Collection                    Version
----------------------------- -------
~(中略)~
kubernetes.core               2.3.1  
~(以下略)~

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • Ansible: 2.13.1
  • Kubernetes: v1.27.1

Ansibleコントロールノード構築やLinuxサーバの事前準備の手順は、以下記事を参照いただきたい。

Kubernetesコントロールプレーンに対する準備

AnsibleでKubernetesを操作する際は、コントロールプレーンを経由してKubernetes APIにアクセスする。その際に、コントロールプレーンのノードに対して追加のPythonモジュールが必要となる。

1. pipをインストール

Dockerを利用する際はPythonパッケージのインストールが必要となるため、pipをインストールしておく。

# dnf install python3-pip

2. pipを用いてPythonモジュールをインストール

pipを用いて、以下の通りkubernetesのPythonモジュールをインストールする。

# python3 -m pip install kubernetes

3. Ansible実行ユーザーにKubernetesクラスタの環境設定ファイルを配置

Kubernetesのコントロールプレーン構築時に、Kubernetes APIへアクセスするために環境設定ファイルをホームディレクトリに配置する作業をするが、Ansible実行ユーザーに対しても同様に実施が必要となる。

私の環境ではansibleuserとなるため、以下の通り配置作業を実施した。

# su - ansibleuser
> mkdir -p $HOME/.kube
> sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
> sudo chown $(id -u):$(id -g) $HOME/.kube/config

実際にAnsibleでKubernetesを操作してみる

動作確認として、AnsibleでKubernetesにNamespaceを作成してみよう。Kubernetesのリソース操作は、kubernetes.core.k8sというモジュールで実現できる。

以下のシンプルなPlaybookを実行する。

---
- name: Create K8s namespace
  gather_facts: true
  hosts: t3051kube

  vars:
    ansible_user: ansibleuser

  tasks:
    # Namespace作成
    - name: Create namespace
      kubernetes.core.k8s:
        name: test-namespace
        api_version: v1
        kind: Namespace
        state: present

実行結果は以下の通り。

# ansible-playbook -i hosts k8s/create_k8s_namespace.yml 

PLAY [Create K8s namespace] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [t3051kube]

TASK [Create namespace] ********************************************************************************************
changed: [t3051kube]

PLAY RECAP *********************************************************************************************************
t3051kube                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

kubectlコマンドで確認すると、以下の通りNamespaceが作成されている。

# kubectl get namespace
NAME              STATUS   AGE
default           Active   18d
kube-flannel      Active   18d
kube-node-lease   Active   18d
kube-public       Active   18d
kube-system       Active   18d
mynamespace       Active   18d
test-namespace    Active   2m5s ★Ansibleで作成されたNamespace

以上で、Ansibleを使ってKubernetesを操作する手順は完了となる。今回はNamespaceの作成を例として記載したが、kubernetes.core.k8sモジュールを使うことで、kubectlコマンドを用いて行う各種リソースの作成や、マニフェストファイルからのリソースなども実現することができる。

2023年6月10日土曜日

Kubernetes構築手順④ (コントロールプレーンを冗長構成にする)

本ブログでは、数回に分けてKubernetesの構築手順を記載してきた。

今まではコントロールプレーンをシングル構成にて構築していたが、コントロールプレーン停止時にコンテナ間の通信ができなくなり、影響が発生するという問題がある。

そこで、本記事では、Kubernetesの管理機能であるコントールプレーンを冗長構成にて構築する手順を記載する。

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6
  • Docker : 23.0.1
  • cri-dockerd: 0.3.1-dev
  • Kubernetes: v1.27.1

なお、私の環境ではインターネット接続時にプロキシ接続が必要となるため、プロキシ経由で接続するための設定も併せて行っている。

今回の構成の概要図を以下に記載する。負荷分散装置にてkube-apiserverへのアクセスを冗長化する点が、大きな差異となる。

NGINXによる負荷分散装置作成

負荷分散装置は何を用いてもよいが、NGINXにて簡単に作成できる。NGINXを用いた負荷分散装置の構成手順は以下を参照いただきたい。

NGINXでロードバランサを設定する際に、 /etc/nginx/stream.conf.d/servers.stream.confという設定ファイルを作成する。kube-apiserverは待ち受けポートとなる6443となることから、負荷分散設定としては以下のとおり設定すればよい。

# kube-apiserver
upstream kube-apiserver {
    least_conn;
    server 192.168.3.51:6443;
    server 192.168.3.52:6443;
    server 192.168.3.53:6443;
}

server {
    listen       192.168.3.43:6443;
    proxy_pass   kube-apiserver;
}

Dockerインストール

今回はcri-dockerdを使ってKubernetes環境を構築する。本手順については、過去記事の手順を参照いただきたい。

Kubernetesインストール

こちらも手順については、過去記事の手順を参照いただきたい。

kubeadmコマンドを用いてKubernetesクラスター作成

1. kubeadmコマンド実行

kubeadmコマンドを用いて、Kubernetesクラスターの作成を行う。クラスターの作成はkubeadm initコマンドにて実施する。「Your Kubernetes control-plane has initialized successfully!」が表示されれば成功となる。

コントロールプレーンを冗長化する場合は、--control-plane-endpoint--upload-certsのオプションが追加となる。オプションの説明を以下に記載する。

オプション 説明
--pod-network-cidr=10.244.0.0/16 ネットワークアドオンとしてflannelを追加する際に必要となる設定となる。Pod用のクラスターネットワークのネットワークアドレスを指定する。
--cri-socket=unix:///var/run/cri-dockerd.sock CRIとしてcri-dockerdを使うことを明示的に指定するために指定する。指定しない場合、containerdとcri-dockerdの2つがインストールされていることにより、「Found multiple CRI endpoints on the host」のエラーにてクラスターの作成に失敗するので注意しよう。
--control-plane-endpoint コントロールプレーンへアクセスするためのKubernetes APIのDNS名やIPアドレスを指定する。すべてのコントロールプレーンで共通のアクセス先を指定する必要があることから、kube-apiserverへ振り分けを行う負荷分散装置のDNS名やIPアドレスを指定する。
--upload-certs 新たにコントロールプレーンが参加する際に、自動的に必要な証明書の登録を行うための設定。本オプションを省略した場合、手動による証明書のコピーが必要となる。

以下に実行結果を記載する。

# kubeadm init --pod-network-cidr=10.244.0.0/16 --cri-socket=unix:///var/run/cri-dockerd.sock \
>         --control-plane-endpoint "t3043kube.test.local:6443" --upload-certs
[init] Using Kubernetes version: v1.27.2
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster

~(中略)~

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

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/

You can now join any number of the control-plane node running the following command on each as root:

  kubeadm join t3043kube.test.local:6443 --token jf1wss.euqu6slbvc1c4kry \
        --discovery-token-ca-cert-hash sha256:abcdefgh5a4463ce8dc2761a89187036b1719abbb7a907aed96650ca8162d3d9 \
        --control-plane --certificate-key abcdefgh89a9c0d36e026014d9c9885119cd8c336e45420be92578832456a85a

Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join t3043kube.test.local:6443 --token jf1wss.euqu6slbvc1c4kry \
        --discovery-token-ca-cert-hash sha256:abcdefgh5a4463ce8dc2761a89187036b1719abbb7a907aed96650ca8162d3d9

2. Kubernetesクラスター状態確認

Kubernetesの管理はkubectlコマンドを使って実施するが、そのままでは使用できない。以下の通り設定ファイルをコピーすることでkubectlによるコマンドが使えるようになる。

# mkdir -p $HOME/.kube
# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# sudo chown $(id -u):$(id -g) $HOME/.kube/config

それでは、kubectlコマンドを使って、ノードとPodの状態を確認してみよう。以下の通り、各種コントロールプレーン用のPodと1台のノードが表示される。

# kubectl get node
NAME        STATUS     ROLES           AGE   VERSION
t3051kube   NotReady   control-plane   83s   v1.27.1

# kubectl get pod -A
NAMESPACE      NAME                                READY   STATUS    RESTARTS   AGE
kube-flannel   kube-flannel-ds-zjw8w               1/1     Running   0          42s
kube-system    coredns-5d78c9869d-2lcjq            1/1     Running   0          6m55s
kube-system    coredns-5d78c9869d-fqbw9            1/1     Running   0          6m55s
kube-system    etcd-t3053kube                      1/1     Running   0          7m4s
kube-system    kube-apiserver-t3053kube            1/1     Running   0          7m4s
kube-system    kube-controller-manager-t3053kube   1/1     Running   0          7m4s
kube-system    kube-proxy-nhl5c                    1/1     Running   0          6m55s
kube-system    kube-scheduler-t3053kube            1/1     Running   0          7m4s

上記を見ると、corednsがPendingのステータスとなっており、NodeのステータスもNotReadyとなっている。これはPod用のネットワークアドオンがインストールされていないために発生しており、後続の手順にてflannelをインストールするとステータスがRunningになるため、現時点では気にしなくて問題ない

ネットワークアドオンインストール (flannelインストール)

こちらも手順については、過去記事の手順を参照いただきたい。

flannelインストールが完了すると、ノードのステータスがReadyに変化する。

# kubectl get node
NAME        STATUS   ROLES           AGE     VERSION
t3053kube   Ready    control-plane   7m16s   v1.27.1

# kubectl get pod -A
NAMESPACE      NAME                                READY   STATUS    RESTARTS   AGE
kube-flannel   kube-flannel-ds-zjw8w               1/1     Running   0          42s
kube-system    coredns-5d78c9869d-2lcjq            1/1     Running   0          6m55s
kube-system    coredns-5d78c9869d-fqbw9            1/1     Running   0          6m55s
kube-system    etcd-t3053kube                      1/1     Running   0          7m4s
kube-system    kube-apiserver-t3053kube            1/1     Running   0          7m4s
kube-system    kube-controller-manager-t3053kube   1/1     Running   0          7m4s
kube-system    kube-proxy-nhl5c                    1/1     Running   0          6m55s
kube-system    kube-scheduler-t3053kube            1/1     Running   0          7m4s

2台目のコントロールプレーンの追加

1. kubeadm joinコマンドにてコントロールプレーンを追加

CRIとしてcri-dockerdを用いる場合は、--cri-socketのオプション追加が必要となるため注意すること。

# kubeadm join t3043kube.test.local:6443 --token jf1wss.euqu6slbvc1c4kry \
        --discovery-token-ca-cert-hash sha256:abcdefgh5a4463ce8dc2761a89187036b1719abbb7a907aed96650ca8162d3d9 \
        --control-plane --certificate-key abcdefgh89a9c0d36e026014d9c9885119cd8c336e45420be92578832456a85a \
        --cri-socket=unix:///var/run/cri-dockerd.sock
# kubeadm join t3043kube.test.local:6443 --token jf1wss.euqu6slbvc1c4kry \
        --discovery-token-ca-cert-hash sha256:abcdefgh5a4463ce8dc2761a89187036b1719abbb7a907aed96650ca8162d3d9 \
        --cri-socket=unix:///var/run/cri-dockerd.sock

2. Kubernetesクラスター状態確認

1台目のコントロールプレーンと同様、以下の通り設定ファイルをコピーすることで、2台目のコントロールプレーンにおいてもkubectlによるコマンドが使えるようになる

# mkdir -p $HOME/.kube
# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# sudo chown $(id -u):$(id -g) $HOME/.kube/config

ノードとPodの状態を確認すると、ノードのROLESがcontorol-planeとなっており、各ノードにて、etcd、kube-apiserver、kube-controller-manager、kube-schedulerが起動していることが確認できる(kube-proxyはワーカーノードにおいても起動する)。

# kubectl get node
NAME        STATUS   ROLES           AGE   VERSION
t3052kube   Ready    control-plane   47s   v1.27.1
t3053kube   Ready    control-plane   15m   v1.27.1

# kubectl get pod -A
NAMESPACE      NAME                                READY   STATUS    RESTARTS      AGE
kube-flannel   kube-flannel-ds-xtq5b               1/1     Running   0             59s
kube-flannel   kube-flannel-ds-zjw8w               1/1     Running   0             9m27s
kube-system    coredns-5d78c9869d-2lcjq            1/1     Running   0             15m
kube-system    coredns-5d78c9869d-fqbw9            1/1     Running   0             15m
kube-system    etcd-t3052kube                      1/1     Running   0             58s
kube-system    etcd-t3053kube                      1/1     Running   0             15m
kube-system    kube-apiserver-t3052kube            1/1     Running   0             59s
kube-system    kube-apiserver-t3053kube            1/1     Running   0             15m
kube-system    kube-controller-manager-t3052kube   1/1     Running   0             59s
kube-system    kube-controller-manager-t3053kube   1/1     Running   1 (48s ago)   15m
kube-system    kube-proxy-nhl5c                    1/1     Running   0             15m
kube-system    kube-proxy-zq88d                    1/1     Running   0             59s
kube-system    kube-scheduler-t3052kube            1/1     Running   0             59s
kube-system    kube-scheduler-t3053kube            1/1     Running   1 (44s ago)   15m

参考:コントロールプレーンにおいても管理用Pod「以外」を起動させる設定 (taintの解除)

初期設定時は、コントロールプレーンにおいては管理用Podのみ起動できる設定が入っている。これは「taint (汚れ、汚染という意味)」と呼ばれる設定において制御されている。

検証用途などにおいては、コントロールプレーンにおいても管理用Pod「以外」を起動したい場合は、以下コマンドでtaintを解除する。
※今回は説明しないが、Pod側の設定で「toleration (耐える、黙認という意味)」という対となる設定をすることでも対処できる。

# kubectl taint node t3051kube node-role.kubernetes.io/control-plane:NoSchedule-
# kubectl taint node t3052kube node-role.kubernetes.io/control-plane:NoSchedule-

taintの設定を戻す場合は、以下の通り行う(解除コマンドの最後の-を取る)。

# kubectl taint node t3051kube node-role.kubernetes.io/control-plane:NoSchedule
# kubectl taint node t3052kube node-role.kubernetes.io/control-plane:NoSchedule

以上で、Kubernetesの管理機能であるコントールプレーンを冗長構成にて構築する手順は完了となる。

2023年3月25日土曜日

Kubernetes構築手順③ (マニフェストファイルを使ってDockerコンテナをデプロイ)

前回、前々回において、Kubernetesのコントロールプレーンの構築とワーカーノードを追加する手順を記載した。

本記事では、構築したKubernetes環境にマニフェストファイルを使ってDockerコンテナをデプロイする手順を記載する。

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6
  • Docker : 23.0.1
  • cri-dockerd: 0.3.1-dev
  • Kubernetes: v1.26.2

今回の構成の概要図を以下に記載する。

マニフェストファイルの準備

マニフェストファイルは、Pod用とサービスリソース用の2種類を作成する。マニフェストファイルの記載方法の説明は、過去minikubeで検証した際に説明をしているので、参考にしていただきたい。

1. Pod用マニフェストファイル

検証用のPodのコンテナイメージは、minikubeでも確認用途で使用していたkicbase/echo-serverを使用する。コントロールプレーン含め、3台のノードにPodが配置されることを確認するため、replicas: 3を設定した。

deployment-hello.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-k8s-deployment
  labels:
    app: hello-k8s-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-k8s
  template:
    metadata:
      labels:
        app: hello-k8s
    spec:
      containers:
      - name: hello-k8s
        image: kicbase/echo-server:1.0
        imagePullPolicy: Always

2. サービスリソース用マニフェストファイル

サービスリソースのタイプはNodePortを選択し、各ノードのIPアドレスにアクセスした際に、Podに接続を振り分けるよう設定する。

service-hello.yml

apiVersion: v1
kind: Service
metadata:
  name: hello-k8s-service
  labels:
    app: hello-k8s-service
spec:
  selector:
    app: hello-k8s
  ports:
    - port: 8080
  type: NodePort

Dockerコンテナをデプロイ

1. Podをデプロイ

作成したマニフェストファイルをkubectl applyコマンドで展開する。

# kubectl apply -f deployment-hello.yml
deployment.apps/hello-k8s-deployment created

問題なければ、以下のように3台のPodが展開される。NODEの項目を確認すると、各Podは別々のノードで起動していることがわかる。

# kubectl get pod -o=wide
NAME                                    READY   STATUS    RESTARTS   AGE   IP           NODE        NOMINATED NODE   READINESS GATES
hello-k8s-deployment-6c69965bcb-24qkv   1/1     Running   0          12s   10.244.0.6   t1051kube   <none>           <none>
hello-k8s-deployment-6c69965bcb-4bp74   1/1     Running   0          12s   10.244.2.4   t1053kube   <none>           <none>
hello-k8s-deployment-6c69965bcb-fkbpr   1/1     Running   0          12s   10.244.1.4   t1052kube   <none>           <none>

2. サービスリソースをデプロイ

サービスリソースも同様にkubectl applyコマンドで展開する。

# kubectl apply -f service-hello.yml
service/hello-k8s-service created

問題なければ、サービスリソースは以下の通り表示される。今回はPORTの項目 に記載されている31595ポートが接続用のポート番号となる。

# kubectl get service
NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-k8s-service   NodePort    10.102.109.11   <none>        8080:31595/TCP   31s
kubernetes          ClusterIP   10.96.0.1       <none>        443/TCP          24h

3. デプロイしたPodへ接続確認

それでは実際にサービスリソース経由でPodにアクセスをしてみよう。

接続先URLは以下の通り。今回はNodePortの設定となるため、接続先は任意のノードの物理IPアドレスとなる。ポート番号は、先ほど確認した31595ポートとなる。

  • http://[任意のノードの物理IPアドレス]:31595

試しにブラウザからノード#3に接続すると以下の通り表示された。

最上部にアクセス先のPodが表示されるており、hello-k8s-deployment-6c69965bcb-4bp74となっている。このことから、ノード#2で起動しているPodであり、たとえノード#3の物理IPアドレスにアクセスしたとしても、実際にアクセスするPodは同一ノードのものとは限らず、任意のPodが選ばれていることがわかる。

以上で、Kubernetes環境にマニフェストファイルを使ってDockerコンテナをデプロイする手順は完了となる。

人気の投稿