Kubernetesバイナリデプロイと高可用性構成ガイド

Kubernetesの基本アーキテクチャ

Kubernetesクラスターは主にマスターノードとワーカーノードの2種類のノードで構成されます。

マスターノードのコンポーネント

  • APIサーバー: 全てのサービスリクエストの統一アクセスポイント
  • コントローラーマネージャー: K8Sリソースオブジェクトのコントローラーを管理し、リソース状態を監視
  • スケジューラー: Podリソースのスケジューリングを担当し、最適なノードを選択
  • etcd: K8Sクラスターのデータベース。キー値ペア構造の分散データベース

ワーカーノードのコンポーネント

  • kubelet: APIサーバーからのリクエストを受信し、Podとコンテナを管理
  • kube-proxy: Serviceリソースの実体として、Podのネットワークプロキシを実現
  • コンテナランタイム: コンテナを実行(Docker、containerdなど)

Podリソース作成のワークフロー

  1. クライアントがPod作成リクエストをAPIサーバーに送信
  2. APIサーバーがリクエスト情報をetcdに保存し、コントローラーマネージャーにPod作成を依頼
  3. コントローラーマネージャーがスケジューラーを呼び出し、新規Podのスケジューリングを実行
  4. スケジューラーがスケジューリングアルゴリズムを使用して最適なノードを選択
  5. APIサーバーが対象ノードのkubeletにPod作成を指示
  6. kubeletがコンテナランタイムと連携してPodおよびコンテナのライフサイクルを管理
  7. ユーザーがAPIサーバー経由でkube-proxyにネットワークルールを書き込み、Serviceを作成

K8Sリソースオブジェクトと設定情報

主要なリソースオブジェクト

  • Pod: K8Sが作成・管理できる最小単位。1つのPodに複数のコンテナを含めることが可能
  • Podコントローラー:
    • Deployment: ステートレスアプリケーションのデプロイ
    • StatefulSet: ステートフルアプリケーションのデプロイ
    • DaemonSet: 全ノードに同一タイプのPodをデプロイ
    • Job/CronJob: 一時的または周期的なタスクの実行
  • Service: クラスター内でPodグループに統一アクセスポイントを提供
  • Ingress: クラスター外部アクセス層として、7層プロキシ転送をサポート

リソース設定情報

  • apiVersion: リソースオブジェクトが使用するAPIインターフェースのバージョン
  • kind: リソースオブジェクトのタイプ
  • metadata: リソースオブジェクトのメタデータ(名前、アノテーション、名前空間、ラベル)
  • spec: リソースオブジェクトの設定プロパティ(レプリカ数、イメージ、ボリュームなど)
  • status: リソースオブジェクトの現在の実行状態情報

K8Sの3種類のネットワークとインターフェース

3種類のネットワーク

  • ノードネットワーク: nodeIP
  • Podネットワーク: podIP
  • Serviceネットワーク: clusterIP

3種類のインターフェース

CRIコンテナランタイムインターフェースdocker, containerd, podman, cri-o
CNIコンテナネットワークインターフェースflannel, calico, cilium
CSIコンテナストレージインターフェースceph, nfs, gfs, oss, s3

etcdクラスター

etcdはCoreOSチームによって開発されたオープンソースの分散キー値データベースです。Go言語で記述され、Raftアルゴリズムを使用して一貫性を確保します。

etcdの特徴

  • シンプルさ: インストールと設定が簡単で、HTTP APIを提供
  • セキュリティ: SSL証明書認証をサポート
  • 高速性: シングルインスタンスで毎秒2k以上の読み取り操作をサポート
  • 信頼性: Raftアルゴリズムにより、分散システムデータの可用性と一貫性を実現

etcdはデフォルトでポート2379を使用してHTTP APIサービスを提供し、ポート2380でピア通信を行います。本番環境では通常、クラスター方式でのデプロイが推奨されます。リーダー選挙メカニズムのため、少なくとも3台以上の奇数台が必要です。

Flannelネットワーク

Flannelの基本概念

Flannelは各ノード上でコンテナ宛のデータパケットをカプセル化し、トンネル経由で対象Podが実行されているノードに送信します。対象ノードはカプセル化を解除し、元のデータパケットを対象Podに転送します。この方法ではデータ通信のパフォーマンスに影響が出ます。

K8S内のPodネットワーク通信

  • 同一Pod内のコンテナ間通信: 同じネットワーク名前空間を共有するため、localhostアドレスで直接通信可能
  • 同一ノード内のPod間通信: 各Podはグローバルに一意なIPアドレスを持ち、同じdocker0ブリッジに接続されているため直接通信可能
  • 異なるノード上のPod間通信: 物理NICを介した通信が必要で、PodのIPが衝突しないこと、PodのIPとノードIPを関連付ける必要がある

Flannelの動作モードと原理

UDPモードの動作原理

  1. 元のデータパケットがソースホストのPodコンテナからcni0ブリッジインターフェースへ送信され、flannel0仮想インターフェースへ転送
  2. flanneldプロセスがflannel0インターフェースで受信したデータを監視し、元のデータパケットをUDPパケットにカプセル化
  3. flanneldプロセスがetcdで維持されているルーティングテーブルに基づき対象PodのあるノードIPを検索し、UDPパケットを物理NIC経由で対象ノードに送信
  4. UDPパケットがポート8285で対象ノードのflanneldプロセスに到達し、復号化された後、flannel0インターフェースからcni0ブリッジへ転送され、最終的に対象Podコンテナへ

VXLANモードの動作原理

  1. 元のデータフレームがソースホストのPodコンテナからcni0ブリッジインターフェースへ送信され、flannel.1仮想インターフェースへ転送
  2. flannel.1インターフェースがデータフレームを受信後、VXLANヘッダーを追加し、カーネル内で元のデータフレームをUDPパケットにカプセル化
  3. flanneldプロセスがetcdで維持されているルーティングテーブルに基づきUDPパケットを物理NIC経由で対象ノードに送信
  4. UDPパケットがポート8472で対象ノードのflannel.1インターフェースに到達し、カーネル内で復号化された後、flannel.1インターフェースからcni0ブリッジへ転送され、最終的に対象Podコンテナへ

Calicoネットワーク

Calicoの基本概念

CalicoはトンネルやNATを使用せずに転送を実現し、ホストをインターネット上のルーターとして扱い、BGPでルートを同期し、iptablesを使用してセキュリティアクセスポリシーを実装します。

Calicoの主要コンポーネント

  • Calico CNIプラグイン: Kubernetesとの連携を担当
  • Felix: ホスト上のルーティングルールやFIB転送情報ベースの維持を担当
  • BIRD: ルーティングルールの配信を担当(ルーターに類似)
  • Confd: 設定管理コンポーネント

Calicoの動作原理

Calicoはルーティングテーブルを使用して各Podの通信を維持します。CalicoのCNIプラグインは各コンテナにveth pairデバイスを設定し、もう一方の端をホストのネットワーク名前空間に接続します。ブリッジがないため、CNIプラグインはホスト上で各コンテナのveth pairデバイスに受信用のルーティングルールを設定する必要があります。

IPIPモードとBGPモードの動作原理

IPIPモードの動作原理

  1. 元のデータパケットがソースホストのPodコンテナからtunl0インターフェースへ送信され、カーネルのIPIPドライバによってノードネットワークのIPパケットにカプセル化
  2. tunl0インターフェースのルートに従い、物理NIC経由で対象ノードに送信
  3. IPデータパケットが対象ノードに到達後、カーネルのIPIPドライバによって復号化され元のIPデータパケットを取得
  4. ローカルのルーティングルールに従い、veth pairデバイス経由で対象Podコンテナに送達

BGPモードの動作原理

  1. ソースホストのPodコンテナから送信された元のIPデータパケットがveth pairデバイス経由でノードネットワーク空間に送達
  2. 元のIPデータパケットの宛先IPとノードのルーティングルールに基づき対象ノードのIPを検索し、物理NIC経由で対象ノードに送信
  3. IPデータパケットが対象ノードに到達後、ローカルのルーティングルールに従いveth pairデバイス経由で対象Podコンテナに送達

FlannelとCalicoの比較

Flannel

  • 動作モード: UDP、VXLAN、HOST-GW
  • デフォルトネットワーク: 10.244.0.0/16
  • 特徴: 通常VXLANモードを使用し、オーバーレイネットワーク、IPトンネル方式でデータを転送。設定が簡単で管理が容易ですが、複雑なネットワークポリシー設定能力はありません

Calico

  • 動作モード: IPIP、BGP、混合モード(CrossSubnet)
  • デフォルトネットワーク: 192.168.0.0/16
  • 特徴:
    • IPIPモード: サブネットを超えた転送が可能ですが、追加のカプセル化・復号化プロセスが必要
    • BGPモード: 各ノードをルーターとして扱い、FelixとBIRDコンポーネントでルーティングルールを維持・配信。BGPプロトコルによる直接ルーティング転送を実現し、パフォーマンスが良いが同一サブネット内のみ使用可能
  • 利点: cni0ブリッジを使用せず、ルーティングルールでデータパケットを直接宛先NICに送信するため高性能。豊富なネットワークポリシー設定管理能力を持つ

小規模でネットワーク要件がシンプルなK8SクラスターにはFlannelを、大規模でより多くのネットワークポリシー設定が必要な場合はCalicoを採用することをお勧めします。

バイナリによるデプロイ手順

1. etcdのデプロイ

cfsslツールを使用して証明書と秘密鍵を発行し、etcdソフトウェアパッケージを解凍してバイナリファイルを取得します。etcdクラスター設定ファイルを準備し、etcdサービスプロセスを起動してetcdクラスターに参加させます。

# etcdクラスターの健全性状態を確認
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://etcd01IP:2379,https://etcd02IP:2379,https://etcd03IP:2379" --cacert=CA証明書 --cert=クライアント証明書 --key=クライアント秘密鍵 endpoint health -wtable

# etcdクラスター状態情報を確認
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://etcd01IP:2379,https://etcd02IP:2379,https://etcd03IP:2379" --cacert=CA証明書 --cert=クライアント証明書 --key=クライアント秘密鍵 endpoint status -wtable

# etcdクラスターメンバーリストを確認
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://etcd01IP:2379" --cacert=CA証明書 --cert=クライアント証明書 --key=クライアント秘密鍵 member list -wtable

2. マスターコンポーネントのデプロイ

cfsslツールを使用して証明書と秘密鍵を発行し、K8Sサーバーソフトウェアパッケージを解凍してバイナリファイルを取得します。kube-apiserver起動時に呼び出されるbootstrap-token認証ファイルを準備し、各コンポーネントのサービスプロセス起動パラメータ設定ファイルを準備します。

# マスターコンポーネントの健全性状態を確認
kubectl get cs

3. ノードコンポーネントのデプロイ

kubeletとkube-proxyのkubeconfigクラスター誘導設定ファイルを準備し、サービスプロセス起動パラメータ設定ファイルを準備します。kubeletサービスプロセスを起動し、APIサーバーにCSRリクエストを送信して証明書を発行してもらいます。ipvsモジュールをロードし、kube-proxyサービスプロセスを起動します。

# ノードの状態を確認
kubectl get nodes

K8Sバイナリデプロイの実践

# クラスターノード構成例
k8sクラスターmaster01: 192.168.30.100(kube-apiserver、kube-controller-manager、kube-scheduler、etcd)
k8sクラスターmaster02: 192.168.30.105
k8sクラスターmaster03: 192.168.30.203

etcdクラスターnode1: 192.168.30.100
etcdクラスターnode2: 192.168.30.200
etcdクラスターnode3: 192.168.30.104

k8sクラスターnode01: 192.168.30.200(kubelet、kube-proxy、docker)
k8sクラスターnode02: 192.168.30.104

ロードバランサーnginx+keepalive01(master): 192.168.30.14
ロードバランサーnginx+keepalive02(backup): 192.168.30.15

シングルマスター構成

オペレーティングシステムの初期設定

全ノードでファイアウォール、SELinux、スワップを無効化し、ホストファイルを設定し、カーネルパラメータを調整します。

# ファイアウォールの無効化(全ノード)
systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

# SELinuxの無効化(全ノード)
setenforce 0
sed -i 's/enforcing/disabled/' /etc/selinux/config

# スワップの無効化(全ノード)
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab

# 全ノードにhostsを追加
cat >> /etc/hosts << EOF
192.168.80.10 master01
192.168.80.11 node01
192.168.80.12 node02
EOF

# カーネルパラメータの調整(全ノード)
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv6.conf.all.disable_ipv6=1
net.ipv4.ip_forward=1
EOF

sysctl --system

# 時刻同期(全ノード)
yum install ntpdate -y
ntpdate ntp.aliyun.com

etcdクラスターのデプロイ

master01ノードでCFSSL証明書生成ツールを準備し、Etcd証明書を生成します。etcdバイナリファイルを配置し、サービスを起動します。設定ファイルと証明書を他のetcdノードにコピーし、各ノードでサービスを起動します。

Dockerエンジンのデプロイ

全ノードでDockerエンジンをインストールし、設定ファイルをカスタマイズしてサービスを起動します。

# Dockerエンジンのインストール(全ノード)
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io

# Docker設定ファイルのカスタマイズ
cat > /etc/docker/daemon.json << EOF
{
  "registry-mirrors": ["https://6na95ym4.mirror.aliyuncs.com"],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "500m", 
    "max-file": "3"
  }
}
EOF

systemctl start docker.service
systemctl enable docker.service

マスターコンポーネントのデプロイ

master01ノードでK8Sコンポーネントの証明書を生成し、バイナリファイルを配置してサービスを起動します。kubectlのkubeconfigファイルを生成し、クラスターの状態を確認します。

ワーカーノードコンポーネントのデプロイ

全ノードでkubeletとkube-proxyを設定し、サービスを起動します。マスターノードでCSRリクエストを承認し、ノードの状態を確認します。

CNIネットワークコンポーネントのデプロイ

全ノードでCNIプラグインをインストールし、FlannelまたはCalicoをデプロイします。CoreDNSをデプロイしてDNS解決をテストします。

マルチマスター高可用性構成

追加マスターノードの設定

master02とmaster03ノードでオペレーティングシステムの初期設定を行い、master01ノードから証明書ファイルと設定ファイルをコピーします。各ノードのIPアドレスを設定ファイルに反映し、サービスを起動します。

ロードバランサーのデプロイ

lb01とlb02ノードでNginxとKeepalivedをインストールし、設定を行います。Nginxで4層リバースプロキシ負荷分散を設定し、Keepalivedで双機ホットスタンバイを実現します。

# Nginx設定例
stream {
    upstream k8s-apiserver {
        server 192.168.30.100:6443;
        server 192.168.30.203:6443;
        server 192.168.30.105:6443;
    }
    server {
        listen 6443;
        proxy_pass k8s-apiserver;
    }
}

# Keepalived設定例
vrrp_script check_nginx {
    script "/etc/nginx/check_nginx.sh"
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.80.100/24
    }
    track_script {
        check_nginx
    }
}

ノード設定の更新

全ノードでbootstrap.kubeconfig、kubelet.kubeconfig、kube-proxy.kubeconfigファイルを更新し、VIPを指すように設定します。kubeletとkube-proxyサービスを再起動します。

まとめ

etcdデータベース

  • 分散キー値型データベース、サービスディスカバリシステム
  • Go言語で開発、Raft一貫性アルゴリズムを使用
  • クラスター展開時は3台以上の奇数台が必要
  • 2379ポート:外部(クライアント)通信用
  • 2380ポート:内部(クラスター内ノード間)通信用

マスターコンポーネントのインストール手順

  1. APIサーバーのインストール:
    • コンポーネント関連の証明書と秘密鍵ファイルを準備
    • bootstrap token認証ファイルを準備(kubelet起動時の証明書発行用)
    • コンポーネントの起動設定ファイルを準備
    • APIサーバーサービスを起動(ポート6443、HTTPS)
  2. コントローラーマネージャーとスケジューラーの起動:
    • 起動設定ファイルを準備
    • 証明書と秘密鍵ファイルを使用してkubeconfigファイルを生成
    • サービスを起動
  3. クラスターコンポーネント状態の確認:
    • kubeconfigファイルを準備し、kubectlをクラスターに追加
    • kubectl get csで状態を確認

マルチマスター展開手順

  1. 他のマスターノード(master02など)を展開
  2. Nginx/Haproxy + Keepalived高可用性負荷分散を構築
  3. マスターノードクラスターを設定
  4. ノード上のkubeletとkube-proxyのkubeconfig設定ファイルをVIPに接続するよう更新
  5. kubectlの設定ファイルもVIPまたは現在のノードIPに接続するよう更新

タグ: Kubernetes etcd flannel calico バイナリデプロイ

6月15日 19:44 投稿