Kubernetes the hard way を初学者目線で解説する ~ #6 Control Plane コンポーネントを設定する


はじめに

30代未経験からエンジニアを目指して勉強中のYNと申します。
インフラ初学者の私ですが、Kubernetes the hard wayを進めるにあたって、インフラに関する基本的な知識を体系的に学ぶことができました。
そこで、初学者目線での学びなどを本記事にまとめておきたいと思います。

目次

こちらをご覧ください

Control Planeコンポーネントの設定

それぞれのmastetrノードにAPI ServerSchedulerおよびController Managerをインストールします。

インストール

kube-apiservekube-controller-managerkube-schedulerkubectlバイナリをインストールして展開します。

master-1.node/master-2.node
sudo mkdir -p /etc/kubernetes/config
master-1.node/master-2.node
wget -q --show-progress --https-only --timestamping \
  "https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kube-apiserver" \
  "https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kube-controller-manager" \
  "https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kube-scheduler" \
  "https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kubectl"

実行権限を付与してバイナルフォルダに移動します↓

master-1.node/master-2.node
{
  chmod +x kube-apiserver kube-controller-manager kube-scheduler kubectl
  sudo mv kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/local/bin/
}

etcdの暗号化の設定を行う

Kubernetesクラスタの情報は全てetcdデータベースに保存されていますが、公式でも述べられているとおり、クラスター内で保持されるデータの暗号化を行う必要があります。

etcdデータベースには、Kubernetes APIを介してアクセス可能なあらゆる情報が含まれています。このため、暗号化ソリューションを活用してetcdのデータのバックアップを暗号化することや、EncryptionConfigurationを利用してデータを暗号化することが可能です。
参照

暗号化のための適当なkeyを発行する

次のようにしてランダムなkeyを生成します。

master-1.node
ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)

head -c 32はファイルの頭から32バイトの情報を取得します。
/devは擬似デバイスファイルで、/dev/udrandomは乱数を永遠に吐き続けるファイルです。
つまり、32バイトの乱数を取り出してbase64にエンコードしたものをkeyに設定します。

暗号化設定ファイルを生成する

ファイルを生成してmasterノードで共有します。
encryption-config.yamlはこの後のAPI-serverの設定で使います。

master-1.node
cat > encryption-config.yaml <<EOF
kind: EncryptionConfig
apiVersion: v1
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: ${ENCRYPTION_KEY}
      - identity: {}
EOF
master-1.node
for instance in master-1 master-2; do
  scp encryption-config.yaml ${instance}:~/
done

APIサーバーの設定

etcdサーバーのときと基本的に同じです。設定の全体像を示します。

事前準備

master-1.node/master-2.node
{
  sudo mkdir -p /var/lib/kubernetes/

  sudo cp ca.crt ca.key kube-apiserver.crt kube-apiserver.key \
    service-account.key service-account.crt \
    etcd-server.key etcd-server.crt \
    encryption-config.yaml /var/lib/kubernetes/
}

masterノードのinternal IPを取得(してshell変数に格納)します↓

master-1.node/master-2.node
INTERNAL_IP=$(ip addr show enp0s8 | grep "inet " | awk '{print $2}' | cut -d / -f 1)

kube-apiserver.serviceファイルを設定する

systemdのserviceをファイルを設定します。

master-1.node/master-2.node
cat <<EOF | sudo tee /etc/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-apiserver \\
  --advertise-address=${INTERNAL_IP} \\
  --allow-privileged=true \\
  --apiserver-count=3 \\
  --audit-log-maxage=30 \\
  --audit-log-maxbackup=3 \\
  --audit-log-maxsize=100 \\
  --audit-log-path=/var/log/audit.log \\
  --authorization-mode=Node,RBAC \\
  --bind-address=0.0.0.0 \\
  --client-ca-file=/var/lib/kubernetes/ca.crt \\
  --enable-admission-plugins=NodeRestriction,ServiceAccount \\
  --enable-swagger-ui=true \\
  --enable-bootstrap-token-auth=true \\
  --etcd-cafile=/var/lib/kubernetes/ca.crt \\
  --etcd-certfile=/var/lib/kubernetes/etcd-server.crt \\
  --etcd-keyfile=/var/lib/kubernetes/etcd-server.key \\
  --etcd-servers=https://192.168.5.11:2379,https://192.168.5.12:2379 \\
  --event-ttl=1h \\
  --encryption-provider-config=/var/lib/kubernetes/encryption-config.yaml \\
  --kubelet-certificate-authority=/var/lib/kubernetes/ca.crt \\
  --kubelet-client-certificate=/var/lib/kubernetes/kube-apiserver.crt \\
  --kubelet-client-key=/var/lib/kubernetes/kube-apiserver.key \\
  --kubelet-https=true \\
  --runtime-config=api/all \\
  --service-account-key-file=/var/lib/kubernetes/service-account.crt \\
  --service-cluster-ip-range=10.96.0.0/24 \\
  --service-node-port-range=30000-32767 \\
  --tls-cert-file=/var/lib/kubernetes/kube-apiserver.crt \\
  --tls-private-key-file=/var/lib/kubernetes/kube-apiserver.key \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

この設定は、全体像におけるAPI-serverとその他のコンポーネントの関係についてを記述していることが見て取れます。その他特記すべき部分としては下記が挙げられます。

  • --etcd-servers=https://192.168.5.11:2379,https://192.168.5.12:2379

etcdサーバーの冗長化について設定しています

  • --enable-admission-plugins=NodeRestriction,ServiceAccount

API-serverに届くリクエストのvaidation方法について設定しています。

Admission controllers limit requests to create, delete, modify or connect to (proxy). They do not support read requests.
The admission control process proceeds in two phases. In the first phase, mutating admission controllers are run. In the second phase, validating admission controllers are run. Note again that some of the controllers are both.
If any of the controllers in either phase reject the request, the entire request is rejected immediately and an error is returned to the end-user.
参考

  • --authorization-mode=Node,RBAC

APi-serverがKubernetesコンポーネントにどういった権限を認めるかを設定します。参考

Controller Managerの設定

API-serverと大体一緒です。

事前準備

master-1.node/master-2.node
sudo cp kube-controller-manager.kubeconfig /var/lib/kubernetes/

kube-controller-manager.serviceファイルを設定する

master-1.node/master-2.node
cat <<EOF | sudo tee /etc/systemd/system/kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-controller-manager \\
  --address=0.0.0.0 \\
  --cluster-cidr=192.168.5.0/24 \\
  --cluster-name=kubernetes \\
  --cluster-signing-cert-file=/var/lib/kubernetes/ca.crt \\
  --cluster-signing-key-file=/var/lib/kubernetes/ca.key \\
  --kubeconfig=/var/lib/kubernetes/kube-controller-manager.kubeconfig \\
  --leader-elect=true \\
  --root-ca-file=/var/lib/kubernetes/ca.crt \\
  --service-account-private-key-file=/var/lib/kubernetes/service-account.key \\
  --service-cluster-ip-range=10.96.0.0/24 \\
  --use-service-account-credentials=true \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

この設定を見ても、全体像におけるcontroller-managerとその他のコンポーネントの関係についてほどんと記述していることが分かります。
また、--leader-elect=trueの部分に着目すると、master-1もしくはmaster-2ノードのどちらかでLeaderが起動していることが分かります。

Schedulerの設定

これも上記とだいたい一緒です。

事前準備

master-1.node/master-2.node
sudo cp kube-scheduler.kubeconfig /var/lib/kubernetes/

kube-scheduler.serviceファイルを設定する

master-1.node/master-2.node
cat <<EOF | sudo tee /etc/systemd/system/kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-scheduler \\
  --kubeconfig=/var/lib/kubernetes/kube-scheduler.kubeconfig \\
  --address=127.0.0.1 \\
  --leader-elect=true \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

control planeの起動

起動

master-1.node/master-2.node
{
  sudo systemctl daemon-reload
  sudo systemctl enable kube-apiserver kube-controller-manager kube-scheduler
  sudo systemctl start kube-apiserver kube-controller-manager kube-scheduler
}

動作確認

master-1.node/master-2.node
kubectl get componentstatuses --kubeconfig admin.kubeconfig
#もしくは kubectl get componentstatuses
master-1.node/master-2.node
NAME                 STATUS    MESSAGE              ERROR
controller-manager   Healthy   ok
scheduler            Healthy   ok
etcd-0               Healthy   {"health": "true"}
etcd-1               Healthy   {"health": "true"}

Frontend Load Balancerを設定する

外部からAPIサーバーへのアクセスに対するLBを設置します。

Network Load Balancerを配置する

local.pc
vagrant ssh loadbalancer
loadbalancer.node
#Install HAProxy
sudo apt-get update && sudo apt-get install -y haproxy
loadbalancer.node
cat <<EOF | sudo tee /etc/haproxy/haproxy.cfg 
frontend kubernetes
    bind 192.168.5.30:6443
    option tcplog
    mode tcp
    default_backend kubernetes-master-nodes

backend kubernetes-master-nodes
    mode tcp
    balance roundrobin
    option tcp-check
    server master-1 192.168.5.11:6443 check fall 3 rise 2
    server master-2 192.168.5.12:6443 check fall 3 rise 2
EOF

HAproxyの設定については公式を参照ください。

  • frontend => 192.168.5.30:6443をlisten.後述のkubernetes-master-nodesバックエンドにセッションを接続させる
  • backend => kubernetes-master-nodesバックエンドについて規定する。master-1/master-2にラウンドロビンでスケジューリング。ヘルスチェックは3回連続OKで健全、2回連続失敗でfailと判定。
loadbalancer.node
sudo service haproxy restart

動作確認

local.pc
# vagrantクラスタ外のターミナルからアクセス
curl  https://192.168.5.30:6443/version -k
{
  "major": "1",
  "minor": "13",
  "gitVersion": "v1.13.0",
  "gitCommit": "ddf47ac13c1a9483ea035a79cd7c10005ff21a6d",
  "gitTreeState": "clean",
  "buildDate": "2018-12-03T20:56:12Z",
  "goVersion": "go1.11.2",
  "compiler": "gc",
  "platform": "linux/amd64"
}