涅槃を目指す in はてな

人生に迷う様を書きます

Kubernetes The Hard Way On VirtualBox 8日目

Kubernetesを雰囲気で使わないための修行Kubernetes The Hard Way On VirtualBoxの8日目。

今日はKubernetes のWorker NodeのTLS Bootstrapping。だいぶ来てますね。

更新がやたら遅いのは忙しいわけでも体調が悪いわけでもなく、怠惰です。

7つの大罪を順調に犯してます。

TLS Bootstrapping Worker Nodes

前回までは以下のことを行ってきました

  • ワーカーノード用の鍵ペアのセットを自分で作成する
  • 自分でCAに署名してもらう
  • この証明書を使用したkube-configファイルを自分で作成する
  • 証明書の有効期限が切れるたびに、同じ手順で証明書を更新しなければならない

これは数千のノードがあり、動的に追加削除されるような環境を運用する場合には実用的ではありません

TLS boostrapping を使うことで

  • ノードは鍵ペアを自分で作成できる
  • ノードはCSRを作成できる
  • ノードはAPIを使ってCSRをKubernetesCAに送信できる
  • ノードはKubernetesCAの署名付き証明書を取得できる
  • ノードはその証明書を使った kube-config ファイルを自分で作成できる
  • ノードはクラスタの起動や参加を自分で出来る
  • ノードは新しい証明書のCSRを作成できるが、クラスタの管理者が手動で承認する必要がある

Kubernetes 1.11では、セキュリティ上の理由から、ノードがCSRを発行する際に管理者またはコントローラの承認を必要とするパッチがマージされました。

参考:https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#certificate-rotation

What is required for TLS Bootstrapping

証明書APIは(先程説明したように)、証明書の管理(CSRの作成、CAによって署名された証明書の取得、署名された証明書の取得など)に役立つAPIのセットをKubernetes上で提供します。ワーカーノード(kubelets)は、このAPIを使用してKubernetes CAによって署名された証明書を取得する機能を持っています。

Pre-Requisite

kube-apiserver

kube-apiserver の /etc/systemd/system/kube-apiserver.service で、以下の設定がされているか確認しましょう。

bootstrap token認証が有効になっているかの設定です。

--enable-bootstrap-token-auth=true

kube-controller-manager

証明書要求は、最終的にkube-controller-managerによって署名されます。

kube-controller-managerは、これらの操作を実行するためにCA証明書とキーを必要とします。

kube-controller-manager.service で、以下の設定が有効になっているか確認します。

  --cluster-signing-cert-file=/var/lib/kubernetes/ca.crt \\
  --cluster-signing-key-file=/var/lib/kubernetes/ca.key

master-1 の証明書をworker-2もコピーします

vagrant@master-1:~$ scp ./ca.crt 192.168.5.22:/home/vagrant/
ca.crt                                      100% 1001     2.8MB/s   00:00 

Configure the Binaries on the Worker node

この作業はworker-2で行います。

ワーカのバイナリをダンロードしてインストールします。

worker-2$ wget -q --show-progress --https-only --timestamping \
  https://storage.googleapis.com/kubernetes-release/release/v1.22.0/bin/linux/amd64/kubectl \
  https://storage.googleapis.com/kubernetes-release/release/v1.22.0/bin/linux/amd64/kube-proxy \
  https://storage.googleapis.com/kubernetes-release/release/v1.22.0/bin/linux/amd64/kubelet

インストール用のディレクトリ作成

worker-2$ sudo mkdir -p \
  /etc/cni/net.d \
  /opt/cni/bin \
  /var/lib/kubelet \
  /var/lib/kube-proxy \
  /var/lib/kubernetes \
  /var/run/kubernetes

バイナリをインストール

{
  chmod +x kubectl kube-proxy kubelet
  sudo mv kubectl kube-proxy kubelet /usr/local/bin/
}

証明書を移動

worker-2$ sudo mv ca.crt /var/lib/kubernetes/

Step 1 Create the Boostrap Token to be used by Nodes(Kubelets) to invoke Certificate API

証明書APIにアクセスするworkerノード(kubelet)にとって、まず kubernetes api-server への認証が必要です。ここではkubeletが使う Bootstrap Tokens を作成します。

Bootstrap Tokens は、6文字のトークンIDと、ドットで区切られた16文字のトークン・シークレットで構成されています。(例:abcdef.0123456789abcdef.)

master-1で行います。

$ cat > bootstrap-token-07401b.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
  # Name MUST be of form "bootstrap-token-<token id>"
  name: bootstrap-token-07401b
  namespace: kube-system

# Type MUST be 'bootstrap.kubernetes.io/token'
type: bootstrap.kubernetes.io/token
stringData:
  # Human readable description. Optional.
  description: "The default bootstrap token generated by 'kubeadm init'."

  # Token ID and secret. Required.
  token-id: 07401b
  token-secret: f395accd246ae52d

  # Expiration. Optional.
  expiration: 2031-03-10T03:22:11Z

  # Allowed usages.
  usage-bootstrap-authentication: "true"
  usage-bootstrap-signing: "true"

  # Extra groups to authenticate the token as. Must start with "system:bootstrappers:"
  auth-extra-groups: system:bootstrappers:worker
EOF

作成時の注意として

  • expiration が未来の日付になっていること
  • auth-extra-groups が "system:bootstrappers:" で始まる必要があること。このグループは今は存在していないけど、ワーカーノードが所属するグループ。このグループは、このトークンに関連付けられています。

kubectlコマンドで作成します。

master-1$ kubectl create -f bootstrap-token-07401b.yaml

Step 2 Authorize workers(kubelets) to create CSR

次に、先ほど作成したグループをsystem:node-bootstrapper ClusterRoleに紐づけます。このClusterRoleはグループに、kubeletを起動するのに十分な権限を与えます。

まずはCSRを作成します。

master-1で行います。

$ kubectl create clusterrolebinding create-csrs-for-bootstrapping --clusterrole=system:node-bootstrapper --group=system:bootstrappers

Step 3 Authorize workers(kubelets) to approve CSR

先程作ったCSRを承認します。

master-1で行います。

$ kubectl create clusterrolebinding auto-approve-csrs-for-group --clusterrole=system:certificates.k8s.io:certificatesigningrequests:nodeclient --group=system:bootstrappers

Step 3 Authorize workers(kubelets) to Auto Renew Certificates on expiration

次は、Cluster Role Binding を作成します。これは証明書の期限を自動的に更新するのにノードに必要なものです。 注意として、system:bootstrappersグループは使いません。なぜなら更新期間までにはノードは起動していて既にクラスタの一部になっているからです。 全てのノードは system:nodesグループです。

master-1で行います。

$ kubectl create clusterrolebinding auto-approve-renewals-for-nodes --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeclient --group=system:nodes

Step 4 Configure Kubelet to TLS Bootstrap

ここでは2つ目のワーカーノードに作成したtokrnを使ってTLS bootstrapの設定をします。

worker-1では、手動で作成したTLS証明書を使ってkubeconfigを作成するところから始めました。 しかしここでは、まだ証明書を持っていませんのでkubecobfigを作成できません。 代わりに、作成したtokenの情報をもとにbootstrap-kubeconfigを作成します。

これはworker-2で行います。

sudo kubectl config --kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig set-cluster bootstrap --server='https://192.168.5.30:6443' --certificate-authority=/var/lib/kubernetes/ca.crt
sudo kubectl config --kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig set-credentials kubelet-bootstrap --token=07401b.f395accd246ae52d
sudo kubectl config --kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig set-context bootstrap --user=kubelet-bootstrap --cluster=bootstrap
sudo kubectl config --kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig use-context bootstrap

Step 5 Create Kubelet Config File

kubelet-config.yamlを作成します。

これはworker-2で行います。

$ cat <<EOF | sudo tee /var/lib/kubelet/kubelet-config.yaml
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous:
    enabled: false
  webhook:
    enabled: true
  x509:
    clientCAFile: "/var/lib/kubernetes/ca.crt"
authorization:
  mode: Webhook
clusterDomain: "cluster.local"
clusterDNS:
  - "10.96.0.10"
resolvConf: "/run/systemd/resolve/resolv.conf"
runtimeRequestTimeout: "15m"
EOF

Step 6 Configure Kubelet Service

kubelet.serviceというsystemdのunitファイルを作成します。

これはworker-2で行います。

$ cat <<EOF | sudo tee /etc/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=docker.service
Requires=docker.service

[Service]
ExecStart=/usr/local/bin/kubelet \\
  --bootstrap-kubeconfig="/var/lib/kubelet/bootstrap-kubeconfig" \\
  --config=/var/lib/kubelet/kubelet-config.yaml \\
  --image-pull-progress-deadline=2m \\
  --kubeconfig=/var/lib/kubelet/kubeconfig \\
  --cert-dir=/var/lib/kubelet/pki/ \\
  --rotate-certificates=true \\
  --network-plugin=cni \\
  --register-node=true \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Step 7 Configure the Kubernetes Proxy

以前作成したkube-proxy.kubeconfigファイルを移動します。

これはworker-2で行います。

$ sudo mv kube-proxy.kubeconfig /var/lib/kube-proxy/kubeconfig

kube-proxy-config.yamlファイルを作成します。

$ cat <<EOF | sudo tee /var/lib/kube-proxy/kube-proxy-config.yaml
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
clientConnection:
  kubeconfig: "/var/lib/kube-proxy/kubeconfig"
mode: "iptables"
clusterCIDR: "192.168.5.0/24"
EOF

kube-proxy.serviceというsystemdのunitファイルを作成します。

$ cat <<EOF | sudo tee /etc/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-proxy \\
  --config=/var/lib/kube-proxy/kube-proxy-config.yaml
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Step 8 Start the Worker Services

サービスを起動します。

これはworker-2で行います。

{
  sudo systemctl daemon-reload
  sudo systemctl enable kubelet kube-proxy
  sudo systemctl start kubelet kube-proxy
}

Step 9 Approve Server CSR

master-1CSRを確認します。

vagrant@master-1:~$ kubectl get csr
NAME        AGE   SIGNERNAME                                    REQUESTOR                 REQUESTEDDURATION   CONDITION
csr-bf8xb   40s   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:07401b   <none>              Approved,Issued

承認します。(CONDITIONが既にApprovedになってるような。。。)

$ kubectl certificate approve csr-bf8xb

Verification

master-1で登録されたnodeの確認をします。

vagrant@master-1:~$ kubectl get nodes --kubeconfig admin.kubeconfig
NAME       STATUS     ROLES    AGE     VERSION
worker-1   NotReady   <none>   35d     v1.22.0
worker-2   NotReady   <none>   3m56s   v1.22.0

ネットワークの設定が終わってないのでNotReadyで大丈夫です。

最後までお読み頂き有難うございました!

さすがにペースを上げよう。。。