6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

kubeadmでHAクラスタ構築(参考訳:v1.10)

Posted at

kubeadmでHAクラスタ構築(参考訳:v1.10)

このドキュメントについて

これはv1.10の古いドキュメント Creating HA Clusters with kubeadmに対する参考訳です。正確には先のページの更新版に対する翻訳(6月上旬時点)です。v1.11へのバージョンアップに伴い手順が一部変わりました。現行バージョンとは一部手順が異なるものの、見直すこともあるかと思い、残しておきます。

なお、現行バージョンのドキュメントは v1.11のドキュメント をご覧ください。

Creating HA clusters with kubeadm

このガイドでご案内するのは、 kubeadm を用い、高可用性 Kubernetes クラスタをどのようにインストールしてセットアップするかです。

このドキュメントではセットアップ手順の流れを紹介しますが、 kubeadm 以外のハードウェアのプロビジョニング、複数のシステムの設定、負荷分散は扱いません。

メモ: このガイドは可能性のあるソリューションの1つであり、高可用性クラスタを構成するには他にも多くの方法があります。皆さんにとって適切なソリューションがあれば、そちらをお使いください。まだコミュニティに採用されていない良いソリューションがあれば、どうぞ自由にご提案ください。

準備

  • 3台のマシンでマスタに合致する kubeadm 最小環境 を構成
  • 3台のマシンでワーカーに合致する kubeadm 最小環境 を構成
  • オプション: 少なくとも3台のマシンで kubeadm 最小環境 etcd を稼働するための専用ノードを構築(詳細は後述)
  • マシンごとに 1GB 以上のメモリ (アプリケーションが必要としないなら、少なくとも可)
  • クラスタ内の全てのマシンがネットワーク上で完全に疎通(パブリックか、プライベートネットワークも構わない)

マスタ上にインストールする準備

増す手向けのホストをプロビジョン(作成)したら、 インストール・ガイド に従って kubeadm と依存関係をインストールします。ステップの最後では、各マスタ上に全ての依存関係のインストールが完了しているでしょう。

HA etcd クラスタのセットアップ

高可用性オプションでは、etcd クラスタをどこで動かすか決める必要があります。クラスタを構成するのは、少なくとも3つのメンバです。私たちが推奨するのは以下のモデルです:

  • それぞれの計算ノード(仮想マシン)で etcd クラスタを稼働
  • マスタ・ノード上で etcd クラスタを稼働

より高い性能と優れたハードウェア分離を提供するオプションのためには、より費用がかかり、追加のサポート要素も必要となります。

オプション 1: CoreOS のハードウェア推奨環境 を満たす3つの仮想マシンを作成。簡単に扱うため、それぞれ etcd0etcd1etcd2 と呼ぶ。

オプション 2: こちらは次のステップにスキップできます。マスタ・ノード上で etcd を稼働するため、このガイドは etcd0etcd1etcd2master0master1master2に置き換えます。

etcd CA 証明書を作成

  1. cfsslcfssljson のインストール:

    curl -o /usr/local/bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
    curl -o /usr/local/bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
    chmod +x /usr/local/bin/cfssl*
    
  2. etcd0 に SSH し、以下の通りに実行:

    mkdir -p /etc/kubernetes/pki/etcd
    cd /etc/kubernetes/pki/etcd
    
    cat >ca-config.json <<EOF
    {
      "signing": {
          "default": {
              "expiry": "43800h"
          },
          "profiles": {
              "server": {
                  "expiry": "43800h",
                  "usages": [
                      "signing",
                      "key encipherment",
                      "server auth",
                      "client auth"
                  ]
              },
              "client": {
                  "expiry": "43800h",
                  "usages": [
                      "signing",
                      "key encipherment",
                      "client auth"
                  ]
              },
              "peer": {
                  "expiry": "43800h",
                  "usages": [
                      "signing",
                      "key encipherment",
                      "server auth",
                      "client auth"
                  ]
              }
          }
      }
    }
    EOF
    
    cat >ca-csr.json <<EOF
    {
       "CN": "etcd",
       "key": {
           "algo": "rsa",
           "size": 2048
       }
    }
    EOF
    

    オプション: ca-csr.jsonnames セクションを追加できます。
    例についての詳細は CFSSL wiki をご覧ください。

  3. 次に、CA 証明書を生成します:

    cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
    

etcd クライアントと証明書の生成

クライアント証明書を正視します。 etcd0 であれば、次のように実行します:

cat >client.json <<EOF
{
  "CN": "client",
  "key": {
      "algo": "ecdsa",
      "size": 256
  }
}
EOF
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client

client.pemclient-key.pem の両方が作成されます。

SSH アクセスの作成

マシン間に証明書をコピーするため、 scp での SSH 接続を有効化する必要があります。

  1. まず、 etcd1etcd2 のための新しいタブをシェルで開きます。3つのマシンに SSH したのを確認し、それから以下のコマンドを実行します(tmux 動機を使えばより素早く行えます。iTerm で cmd+shift+i を入力します)
    :

    export PEER_NAME=$(hostname)
    export PRIVATE_IP=$(ip addr show eth1 | grep -Po 'inet \K[\d.]+')
    

    eth1 にはプライベート・ネットワーク用の IPv4 アドレス向けネットワーク・インターフェースを割り当てます。ここはネットワークのセットアップに依存して様々に変わるため、この先に進む前に echo $PRIVATE_IP を実行してご確認ください。

  2. 次は、box に対する SSH 鍵を生成します:

    ssh-keygen -t rsa -b 4096 -C "<email>"
    

    <email> の部分は自分のメールアドレスに置き換えるか、何か他のものを書くか、空白文字にします。ここに入力した内容が ~/.ssh のファイルに書かれます。

  3. etcd1etcd2 向け公開鍵の内容を表示します:

    cat ~/.ssh/id_rsa.pub
    
  4. 最後に、それぞれの出力内用を etcd0~/.ssh/authorized_keys ファイルに追加します。これにより、対象マシンに etcd1etcd2 から SSH を可能にします。

etcd サーバとピア証明書の生成

  1. 証明書を生成するために、 etcd0 で生成された root CA が各 etcd マシンで必要になります。 etcd1etcd2 で以下のように実行します:

    mkdir -p /etc/kubernetes/pki/etcd
    cd /etc/kubernetes/pki/etcd
    scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/ca.pem .
    scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/ca-key.pem .
    scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/client.pem .
    scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/client-key.pem .
    scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/ca-config.json .
    

    <etcd0-ip-address> の場所には etcd0 に対する適切なパブリックあるいはプライベート IPv4 アドレスを書きます。

  2. これが完了したら、全ての etcd マシン上で以下のコマンドを実行します:

    cfssl print-defaults csr > config.json
    sed -i '0,/CN/{s/example\.net/'"$PEER_NAME"'/}' config.json
    sed -i 's/www\.example\.net/'"$PRIVATE_IP"'/' config.json
    sed -i 's/example\.net/'"$PEER_NAME"'/' config.json
    
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server config.json | cfssljson -bare server
    cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer config.json | cfssljson -bare peer
    

    こちらのデフォルト設定は、ピア名としてのマシンのホスト名や IP アドレスに応じて置き換えます。証明書は適切に作成しているか確認します。エラーがあれば、 config.json を再調整し、再び cfssl コマンドを実行します。

以上の結果、次のファイルが作成されます: peer.pempeer-key.pemserver.pemserver-key.pem.

etcd_mode

etcd を適切に動かすために、対象となる手順のタブをクリックします。

systemd

  1. まず、etcd バイナリをインストールします:

    ETCD_VERSION="v3.1.12" curl -sSL https://github.com/coreos/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz | tar -xzv --strip-components=1 -C /usr/local/bin/
    

    Kubernetes v1.10 では適切な etcd のバージョンが v3.1.12 なのでご注意ください。Kubernetes の他のバージョンの場合は、changelog をご覧ください。

    また、多くの Linux ディストリビューションでは既に etcd がインストールされている場合もあるためご注意ください。その場合はシステムのデフォルトを置き換えます。

  2. 次に、systemd が使う環境ファイルを生成:

    touch /etc/etcd.env
    echo "PEER_NAME=${PEER_NAME}" >> /etc/etcd.env
    echo "PRIVATE_IP=${PRIVATE_IP}" >> /etc/etcd.env
    
  3. それから systemd unit ファイルをコピー:

    cat >/etc/systemd/system/etcd.service <<EOF
    [Unit]
    Description=etcd
    Documentation=https://github.com/coreos/etcd
    Conflicts=etcd.service
    Conflicts=etcd2.service
    
    [Service]
    EnvironmentFile=/etc/etcd.env
    Type=notify
    Restart=always
    RestartSec=5s
    LimitNOFILE=40000
    TimeoutStartSec=0
    
    ExecStart=/usr/local/bin/etcd --name <name> --data-dir /var/lib/etcd --listen-client-urls http://localhost:2379 --advertise-client-urls http://localhost:2379 --listen-peer-urls http://localhost:2380 --initial-advertise-peer-urls http://localhost:2380 --cert-file=/etc/kubernetes/pki/etcd/server.pem --key-file=/etc/kubernetes/pki/etcd/server-key.pem --client-cert-auth --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem --peer-cert-file=/etc/kubernetes/pki/etcd/peer.pem --peer-key-file=/etc/kubernetes/pki/etcd/peer-key.pem --peer-client-cert-auth --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem --initial-cluster <etcd0>=https://<etcd0-ip-address>:2380,<etcd1>=https://<etcd1-ip-address>:2380,<etcd2>=https://<etcd2-ip-address>:2380 --initial-cluster-token my-etcd-token --initial-cluster-state new
    
    [Install]
    WantedBy=multi-user.target
    EOF
    

    <etcd0-ip-address><etcd1-ip-address><etcd2-ip-address> を適切な IPv4 アドレスに置き換えてください。 <name> は適切な etcd メンバ名に置き換えます。実際の各マシンのホスト名にあわせ、必要に応じて --listen-client-urls--advertise-client-urls--listen-peer-urls--initial-advertise-peer-urls を置き換えます。各マシンの実際のホスト名にあわせて <etcd0><etcd1><etcd2> を置き換えます。各マシン間は DNS を用いて接続できるようにする必要があるため、 /etc/hosts にレコードを追加します。

  4. 最後に etcd を起動:

    systemctl daemon-reload
    systemctl start etcd
    
  5. 起動が成功しているかどうかを確認:

    systemctl status etcd
    

Static Pods(静的な Pod)

メモ: サポートしているのは kubelet のインストールに必要な、全ての依存関係が入っているノードのみです。マスタ・ノード上に etcd を動かす場合、このセットアップは既に完了しています。専用ノードで etcd を動かす場合は、systemd を用いるか、あるいは専用 etcd マシン向けの インストール・ガイド をご覧ください。

マニフェスト・ファイルを生成するため、以下の手順を実行します:

  cat >/etc/kubernetes/manifests/etcd.yaml <<EOF
  apiVersion: v1
  kind: Pod
  metadata:
    labels:
      component: etcd
      tier: control-plane
    name: <podname>
    namespace: kube-system
  spec:
    containers:
    - command:
      - etcd --name <name> 
      - --data-dir /var/lib/etcd 
      - --listen-client-urls http://localhost:2379 
      - --advertise-client-urls http://localhost:2379 
      - --listen-peer-urls http://localhost:2380 
      - --initial-advertise-peer-urls http://localhost:2380 
      - --cert-file=/certs/server.pem 
      - --key-file=/certs/server-key.pem 
      - --client-cert-auth 
      - --trusted-ca-file=/certs/ca.pem 
      - --peer-cert-file=/certs/peer.pem 
      - --peer-key-file=/certs/peer-key.pem 
      - --peer-client-cert-auth 
      - --peer-trusted-ca-file=/certs/ca.pem 
      - --initial-cluster etcd0=https://<etcd0-ip-address>:2380,etcd1=https://<etcd1-ip-address>:2380,etcd2=https://<etcd2-ip-address>:2380 
      - --initial-cluster-token my-etcd-token 
      - --initial-cluster-state new
      image: k8s.gcr.io/etcd-amd64:3.1.10
      livenessProbe:
        httpGet:
          path: /health
          port: 2379
          scheme: HTTP
        initialDelaySeconds: 15
        timeoutSeconds: 15
      name: etcd
      env:
      - name: PUBLIC_IP
        valueFrom:
          fieldRef:
          fieldPath: status.hostIP
      - name: PRIVATE_IP
        valueFrom:
          fieldRef:
            fieldPath: status.podIP
      - name: PEER_NAME
        valueFrom:
          fieldRef:
            fieldPath: metadata.name
      volumeMounts:
      - mountPath: /var/lib/etcd
        name: etcd
      - mountPath: /certs
        name: certs
  hostNetwork: true
  volumes:
  - hostPath:
      path: /var/lib/etcd
      type: DirectoryOrCreate
    name: etcd
  - hostPath:
      path: /etc/kubernetes/pki/etcd
    name: certs
  EOF

置き換えを確認します:

  • <podname> は実行するノード名です(例: etcd0etcd1etcd2)
  • <etcd0-ip-address><etcd1-ip-address><etcd2-ip-address> は etcd を稼働するホストのパブリック IPv4 です

lb_mode

etcd を適切に動かすために、対象となる手順のタブをクリックします。

クラウド"

クラウド事業者のソリューション例:

ロードバランサから master0 の port 6443 に対して径路があるかを確認します。これは kubeadm がロードバランサの IP アドレスでヘルスチェックを行うためです。そのため master0 のセットアップを個別に第一に行う必要があり、他のマスタで apiserver を実行しなければ、 kubeadm が継続して応答しない場合もああります。

可能であれば、「最小コネクション」(least connections)のような小さな負荷分散アルゴリズムを用い、ヘルスチェックを使って応答しないノードは振り分け先からは除外します。ほとんどの事業者ではこの機能を提供しています。

オンサイト

オンサイト環境では、物理ロードバランサを利用できない場合があります。そのかわりに、仮想 IP で正常なマスタ・ノードを示せられます。そのためには、ロードバランサを使うもの、使わないものを含め、 Keepalived、Pacemaker などを含む多くのソリューションがあります。

ここでは例として keepalived をベースとした簡単なセットアップを紹介します。環境への依存や必要とするものにより、異なったソリューションがあります。以下の設定は負荷分散を使わない アクティブ/パッシブ のフェイルオーバです。必要であれば、HAProxy 、 Nginx などをマスタ・ノード上でセットアップし、簡単に負荷分散も追加できます(本ガイドでは扱いません)。

  1. keepalived のインストールは、ディストリビューションのパッケージ・マネージャを使うなどします。以下の設定はバージョン 1.3.5 が対象ですが、おそらく他のバージョンでも動作するでしょう。対象ノードが起動時に自動的に起動するよう、設定が有効かどうか(chkconfig、systemd 等)ご確認ください。

  2. 全てのマスタ・ノード上で設定ファイル /etc/keepalived/keepalived.conf を作成し、以下の内容にします:

    ! keepalived用設定ファイル
    global_defs {
     router_id LVS_DEVEL
    }
    
    vrrp_script check_apiserver {
     script "/etc/keepalived/check_apiserver.sh"
     interval 3
     weight -2
     fall 10
     rise 2
    }
    
    vrrp_instance VI_1 {
       state <STATE>
       interface <INTERFACE>
       virtual_router_id 51
       priority <PRIORITY>
       authentication {
           auth_type PASS
           auth_pass 4be37dc3b4c90194d1600c483e10ad1d
       }
       virtual_ipaddress {
           <VIRTUAL-IP>
       }
       track_script {
           check_apiserver
       }
    }
    

    セクション中の vrrp_instance VI_1 は、皆さんの環境にあわせて数行を書き換えます:

    • stateMASTER (1つめのマスタ・ノード上) か BACKUP (その他のマスタ・ノード上) のどちらかです。
    • interface は仮想 IP を割り当てる既存のパブリック/インターフェースです(通常は1番目のインターフェース)。
    • priority には1つめのマスタ・ノードが他より高くなるべきです。例:101 であれば、他のノードは 100 など低い値に。
    • auth_pass には何らかのランダムな文字列を入れます。
    • virtual_ipaddresses にはマスタ・ノード用の仮想 IP を含めるべきです。
  3. 全てのマスタ・ノード上にヘルスチェック用のスクリプト /etc/keepalived/check_apiserver.sh_ をインストールします:

    #!/bin/sh
    
    errorExit() {
       echo "*** $*" 1>&2
       exit 1
    }
    
    curl --silent --max-time 2 --insecure https://localhost:6443/ -o /dev/null || errorExit "Error GET https://localhost:6443/"
    if ip addr | grep -q <VIRTUAL-IP>; then
       curl --silent --max-time 2 --insecure https://<VIRTUAL-IP>:6443/ -o /dev/null || errorExit "Error GET https://<VIRTUAL-IP>:6443/"
    fi
    

    <VIRTUAL-IP> は皆さんの仮想 IP から選んで置き換えます。

  4. Keepalived を再起動します。Kubernetes サービスをまだ起動していなければ、全てのマスタ・ノード上でのヘルスチェック失敗がログに記録されます。1つめのマスタ・ノードが立ち上がれば、間もなく止まります。

etcd 証明書の取得

etcd を専用ノード上で動かす場合は、オプション1 の手順に従ってください。etcd をマスタ上で動かす場合は オプション2 の手順に従いますが、マスタ上で etcd 証明書を既に生成済みの場合は省略できます。

  1. SSH アクセスの作成 セクションの手順に従い、各マスタ・ノード用の SSH 鍵を生成します。この作業が終われば、各マスタでは SSH 鍵が ~/.ssh/id_rsa.pub に置かれ、 etcd0~/.ssh/authorized_keys ファイルにそれぞれ登録されます。

  2. 次の通りに実行します:

    mkdir -p /etc/kubernetes/pki/etcd
    scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/ca.pem /etc/kubernetes/pki/etcd
    scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/client.pem /etc/kubernetes/pki/etcd
    scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/client-key.pem /etc/kubernetes/pki/etcd
    

kubeadm initmaster0 で実行 {#kubeadm-init-master0}

  1. kubeadm を実行できるようにするため、まず設定ファイルを書く必要があります:

cat >config.yaml <<EOF
apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
api:
advertiseAddress:
etcd:
endpoints:
- https://:2379
- https://:2379
- https://:2379
caFile: /etc/kubernetes/pki/etcd/ca.pem
certFile: /etc/kubernetes/pki/etcd/client.pem
keyFile: /etc/kubernetes/pki/etcd/client-key.pem
networking:
podSubnet:
apiServerCertSANs:
-
apiServerExtraArgs:
apiserver-count: "3"
EOF
```
以下の該当箇所は書き換えます:

  • <private-ip> はマスタ・サーバのプライベート IP アドレスです。

  • <etcd0-ip><etcd1-ip><etcd2-ip> は3つの etcd ノードの IP アドレスです。

  • <podCIDR> にはポッドの CIDER です。詳細については CNI ネットワークのセクション にあるドキュメントをご覧ください。CNI プロバイダによっては設定が不要な場合もあります。

  • <load-balancer-ip> はロードバランサで設定する仮想 IP です。詳細については マスタ・ロードバランサのセットアップ のセクションをご覧ください。

    メモ: Kubernetes 1.9 以上を使っている場合は、 apiserver-count: 3 を特別な引数 endpoint-reconciler-type: lease に書き換えられます。より詳しい情報は ドキュメント をご覧ください。

  1. これが終われば、kubeadm を実行します:

kubeadm init --config=config.yaml
```

master1master2上で kubeadm init を実行

他のマスタ上で kubeadm を実行する前に、 master0 から K8s の CA 証明書をコピーする必要があります。そのためには2つの選択肢があります:

オプション1:scp でコピー

  1. SSH アクセスの作成 セクションにある手順に従いますが、etcd0 ではなく master0authorized_keys ファイルに追加します。

  2. それから、こちらを実行します:

    scp root@<master0-ip-address>:/etc/kubernetes/pki/* /etc/kubernetes/pki
    rm apiserver.*
    

オプション 2: コピー&ペースト

/etc/kubernetes/pki/ca.crt/etc/kubernetes/pki/ca.key/etc/kubernetes/pki/sa.key/etc/kubernetes/pki/sa.pub の各ファイルの内容をコピーし、 master1master2 上で各ファイルを手動作成します。

こちらが終われば、前の手順 に従い、kubeadm でコントロール・プレーンをインストールします。

master1master2 をロードバランサに追加

kubeadm を他のマスタにプロビジョンしたら、それぞれロードバランサ・プールに追加できます。

CNI ネットワークのインストール

こちら にある手順に従い、ポッド・ネットワークをインストールします。マスタの設定ファイルで指定した pod CIDR のいずれかを適切に設定します。

ワーカーのインストール

次はワーカー・ノードのプロビジョンとセットアップをします。そのためには、少なくとも3台の仮想マシンのプロビジョンが必要です。

  1. ワーカー・ノードを設定するには、HA ワークロードを行わない こちらと同じ手順に従い に従います。

ワーカーの設定変更

  1. kube-apiserver にロードバランサを経由して接続できるよう、kube-proxy を再設定します:

    kubectl get configmap -n kube-system kube-proxy -o yaml > kube-proxy-cm.yaml
    sed -i 's#server:.*#server: https://<masterLoadBalancerFQDN>:6443#g' kube-proxy-cm.yaml
    kubectl apply -f kube-proxy-cm.yaml --force
    # restart all kube-proxy pods to ensure that they load the new configmap
    kubectl delete pod -n kube-system -l k8s-app=kube-proxy
    
  2. kube-apiserver にロードバランサを経由して接続できるよう、kubelet を再設定します:

    sudo sed -i 's#server:.*#server: https://<masterLoadBalancerFQDN>:6443#g' /etc/kubernetes/kubelet.conf
    sudo systemctl restart kubelet
    
6
2
0

Register as a new user and use Qiita more conveniently

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?