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を発行する際に管理者またはコントローラの承認を必要とするパッチがマージされました。
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-1
でCSRを確認します。
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
で大丈夫です。
最後までお読み頂き有難うございました!
さすがにペースを上げよう。。。