二進位制搭建kubernetes多master叢集【四、配置k8s node】
上一篇我們部署了kubernetes的master叢集,參考:二進位制搭建kubernetes多master叢集【三、配置k8s master及高可用】
本文在以下主機上操作部署k8s node
k8s-node1:192.168.80.10
k8s-node2:192.168.80.11
k8s-node3:192.168.80.12
以下kubeadm和kubectl命令操作都是在k8s-master1上執行的。
kubernetes work 節點執行如下元件:
- docker
- kubelet
- kube-proxy
- flannel
docker和flannel部署參考:
一、安裝依賴包
yum install -y epel-release wget conntrack ipvsadm ipset jq iptables curl sysstat libseccomp && /usr/sbin/modprobe ip_vs
二、部署kubelet元件
kublet 執行在每個 worker 節點上,接收 kube-apiserver 傳送的請求,管理 Pod 容器,執行互動式命令,如 exec、run、logs 等。
kublet 啟動時自動向 kube-apiserver 註冊節點資訊,內建的 cadvisor 統計和監控節點的資源使用情況。
為確保安全,本文件只開啟接收 https 請求的安全埠,對請求進行認證和授權,拒絕未授權的訪問(如 apiserver、heapster)。
1、下載和分發kubelet二進位制檔案
wget https://dl.k8s.io/v1.12.3/kubernetes-server-linux-amd64.tar.gz tar -xzvf kubernetes-server-linux-amd64.tar.gz cp kubernetes/server/bin/ cp kubelet kube-proxy /usr/local/bin scp kubelet kube-proxy k8s-node2:/usr/local/bin scp kubelet kube-proxy k8s-node3:/usr/local/bin
2、建立kubelet bootstrap kubeconfig檔案 (k8s-master1上執行)
#建立 token export BOOTSTRAP_TOKEN=$(kubeadm token create \ --description kubelet-bootstrap-token \ --groups system:bootstrappers:k8s-master1 \ --kubeconfig ~/.kube/config) # 設定叢集引數 kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/cert/ca.pem \ --embed-certs=true \ --server=https://114.67.81.105:8443 \ --kubeconfig=kubelet-bootstrap-k8s-master1.kubeconfig # 設定客戶端認證引數 kubectl config set-credentials kubelet-bootstrap \ --token=${BOOTSTRAP_TOKEN} \ --kubeconfig=kubelet-bootstrap-k8s-master1.kubeconfig # 設定上下文引數 kubectl config set-context default \ --cluster=kubernetes \ --user=kubelet-bootstrap \ --kubeconfig=kubelet-bootstrap-k8s-master1.kubeconfig # 設定預設上下文 kubectl config use-context default --kubeconfig=kubelet-bootstrap-k8s-master1.kubeconfig
- kubelet bootstrap kubeconfig檔案建立三次,分別把k8s-master1改成k8s-master2、k8s-master3。
- 證書中寫入 Token 而非證書,證書後續由 controller-manager 建立。
3、檢視 kubeadm 為各節點建立的 token:
[[email protected] ~]# kubeadm token list --kubeconfig ~/.kube/config TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS 8w6j3n.ruh4ne95icbae4ie 23h 2018-12-21T20:42:29+08:00 authentication,signing kubelet-bootstrap-token system:bootstrappers:k8s-master3 e7n0o5.1y8sjblh43z8ftz1 23h 2018-12-21T20:41:53+08:00 authentication,signing kubelet-bootstrap-token system:bootstrappers:k8s-master2 ydbwyk.yz8e97df5d5u2o70 22h 2018-12-21T19:28:43+08:00 authentication,signing kubelet-bootstrap-token system:bootstrappers:k8s-master1
- 建立的 token 有效期為 1 天,超期後將不能再被使用,且會被 kube-controller-manager 的 tokencleaner 清理(如果啟用該 controller 的話);
- kube-apiserver 接收 kubelet 的 bootstrap token 後,將請求的 user 設定為 system:bootstrap:,group 設定為 system:bootstrappers;
檢視各 token 關聯的 Secret:(紅色的為建立生成的token)
[[email protected] ~]# kubectl get secrets -n kube-system NAME TYPE DATA AGE attachdetach-controller-token-z2w72 kubernetes.io/service-account-token 3 119m bootstrap-signer-token-hz8dr kubernetes.io/service-account-token 3 119m bootstrap-token-8w6j3n bootstrap.kubernetes.io/token 7 20m bootstrap-token-e7n0o5 bootstrap.kubernetes.io/token 7 20m bootstrap-token-ydbwyk bootstrap.kubernetes.io/token 7 93m certificate-controller-token-bjhbq kubernetes.io/service-account-token 3 119m clusterrole-aggregation-controller-token-qkqxg kubernetes.io/service-account-token 3 119m cronjob-controller-token-v7vz5 kubernetes.io/service-account-token 3 119m daemon-set-controller-token-7khdh kubernetes.io/service-account-token 3 119m default-token-nwqsr kubernetes.io/service-account-token 3 119m
4、分發bootstrap kubeconfig檔案
[[email protected] ~]# scp kubelet-bootstrap-k8s-master1.kubeconfig k8s-node1:/etc/kubernetes/cert/kubelet-bootstrap.kubeconfig [[email protected]-master1 ~]# scp kubelet-bootstrap-k8s-master2.kubeconfig k8s-node2:/etc/kubernetes/cert/kubelet-bootstrap.kubeconfig [[email protected]-master1 ~]# scp kubelet-bootstrap-k8s-master3.kubeconfig k8s-node3:/etc/kubernetes/cert/kubelet-bootstrap.kubeconfig
5、建立和分發kubelet引數配置檔案
從 v1.10 開始,kubelet 部分引數需在配置檔案中配置,kubelet --help
會提示:
DEPRECATED: This parameter should be set via the config file specified by the Kubelet's --config flag
建立 kubelet 引數配置模板檔案:(紅色字型改成對應node主機ip)
cat > kubelet.config.json <<EOF { "kind": "KubeletConfiguration", "apiVersion": "kubelet.config.k8s.io/v1beta1", "authentication": { "x509": { "clientCAFile": "/etc/kubernetes/cert/ca.pem" }, "webhook": { "enabled": true, "cacheTTL": "2m0s" }, "anonymous": { "enabled": false } }, "authorization": { "mode": "Webhook", "webhook": { "cacheAuthorizedTTL": "5m0s", "cacheUnauthorizedTTL": "30s" } }, "address": "192.168.80.10", "port": 10250, "readOnlyPort": 0, "cgroupDriver": "cgroupfs", "hairpinMode": "promiscuous-bridge", "serializeImagePulls": false, "featureGates": { "RotateKubeletClientCertificate": true, "RotateKubeletServerCertificate": true }, "clusterDomain": "cluster.local."", "clusterDNS": ["10.254.0.2"] } EOF
- address:API 監聽地址,不能為 127.0.0.1,否則 kube-apiserver、heapster 等不能呼叫 kubelet 的 API;
- readOnlyPort=0:關閉只讀埠(預設 10255),等效為未指定;
- authentication.anonymous.enabled:設定為 false,不允許匿名�訪問 10250 埠;
- authentication.x509.clientCAFile:指定簽名客戶端證書的 CA 證書,開啟 HTTP 證書認證;
- authentication.webhook.enabled=true:開啟 HTTPs bearer token 認證;
- 對於未通過 x509 證書和 webhook 認證的請求(kube-apiserver 或其他客戶端),將被拒絕,提示 Unauthorized;
- authroization.mode=Webhook:kubelet 使用 SubjectAccessReview API 查詢 kube-apiserver 某 user、group 是否具有操作資源的許可權(RBAC);
- featureGates.RotateKubeletClientCertificate、featureGates.RotateKubeletServerCertificate:自動 rotate 證書,證書的有效期取決於 kube-controller-manager 的 --experimental-cluster-signing-duration 引數;
- 需要 root 賬戶執行;
為各節點建立和分發 kubelet 配置檔案:
scp kubelet.config.json k8s-node1:/etc/kubernetes/cert/kubelet.config.json scp kubelet.config.json k8s-node2:/etc/kubernetes/cert/kubelet.config.json scp kubelet.config.json k8s-node3:/etc/kubernetes/cert/kubelet.config.json
6、建立和分發kubelet systemd unit檔案 (紅色字型改成對應node主機ip)
[[email protected] ~]# cat /etc/systemd/system/kubelet.service [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=docker.service Requires=docker.service [Service] WorkingDirectory=/var/lib/kubelet ExecStart=/usr/local/bin/kubelet \ --bootstrap-kubeconfig=/etc/kubernetes/cert/kubelet-bootstrap.kubeconfig \ --cert-dir=/etc/kubernetes/cert \ --kubeconfig=/etc/kubernetes/cert/kubelet.kubeconfig \ --config=/etc/kubernetes/cert/kubelet.config.json \ --hostname-override=192.168.80.10 \ --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.1 \ --allow-privileged=true \ --alsologtostderr=true \ --logtostderr=false \ --log-dir=/var/log/kubernetes \ --v=2 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
- 如果設定了
--hostname-override
選項,則kube-proxy
也需要設定該選項,否則會出現找不到 Node 的情況; --bootstrap-kubeconfig
:指向 bootstrap kubeconfig 檔案,kubelet 使用該檔案中的使用者名稱和 token 向 kube-apiserver 傳送 TLS Bootstrapping 請求;- K8S approve kubelet 的 csr 請求後,在
--cert-dir
目錄建立證書和私鑰檔案,然後寫入--kubeconfig
檔案;
為各節點建立和分發 kubelet systemd unit 檔案:
scp /etc/systemd/system/kubelet.service k8s-node2:/etc/systemd/system/kubelet.service
scp /etc/systemd/system/kubelet.service k8s-node3:/etc/systemd/system/kubelet.service
7、Bootstrap Token Auth和授予許可權
kublet 啟動時查詢配置的 --kubeletconfig 檔案是否存在,如果不存在則使用 --bootstrap-kubeconfig 向 kube-apiserver 傳送證書籤名請求 (CSR)。
kube-apiserver 收到 CSR 請求後,對其中的 Token 進行認證(事先使用 kubeadm 建立的 token),認證通過後將請求的 user 設定為 system:bootstrap:,group 設定為 system:bootstrappers,這一過程稱為 Bootstrap Token Auth。
預設情況下,這個 user 和 group 沒有建立 CSR 的許可權,kubelet 啟動失敗,錯誤日誌如下:
sudo journalctl -u kubelet -a |grep -A 2 'certificatesigningrequests' May 06 06:42:36 kube-node1 kubelet[26986]: F0506 06:42:36.314378 26986 server.go:233] failed to run Kubelet: cannot create certificate signing request: certificatesigningrequests.certificates.k8s.io is forbidden: User "system:bootstrap:lemy40" cannot create certificatesigningrequests.certificates.k8s.io at the cluster scope May 06 06:42:36 kube-node1 systemd[1]: kubelet.service: Main process exited, code=exited, status=255/n/a May 06 06:42:36 kube-node1 systemd[1]: kubelet.service: Failed with result 'exit-code'.
解決辦法是:建立一個 clusterrolebinding,將 group system:bootstrappers 和 clusterrole system:node-bootstrapper 繫結:
[[email protected] ~]# kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --group=system:bootstrappers
8、啟動kubelet服務
mkdir -p /var/log/kubernetes && mkdir -p /var/lib/kubelet systemctl daemon-reload systemctl enable kubelet systemctl restart kubelet
- 關閉 swap 分割槽,否則 kubelet 會啟動失敗;
- 必須先建立工作和日誌目錄;
kubelet 啟動後使用 --bootstrap-kubeconfig 向 kube-apiserver 傳送 CSR 請求,當這個 CSR 被 approve 後,kube-controller-manager 為 kubelet 建立 TLS 客戶端證書、私鑰和 --kubeletconfig 檔案。
注意:kube-controller-manager 需要配置 --cluster-signing-cert-file
和 --cluster-signing-key-file
引數,才會為 TLS Bootstrap 建立證書和私鑰。
- 三個 work 節點的 csr 均處於 pending 狀態;
此時kubelet的程序有,但是監聽埠還未啟動,需要進行下面步驟!
9、approve kubelet csr請求
可以手動或自動 approve CSR 請求。推薦使用自動的方式,因為從 v1.8 版本開始,可以自動輪轉approve csr 後生成的證書。
手動approve csr請求
檢視 CSR 列表:
[[email protected] ~]# kubectl get csr NAME AGE REQUESTOR CONDITION node-csr-P7XcQAc2yNlXn1pUmQFxXNCdGyyt8ccVuW3bmoUZiK4 30m system:bootstrap:e7n0o5 Pending node-csr-gD18nmcyPUNWNyDQvCo2BMYiiA4K59BNkclFRWv1SAM 79m system:bootstrap:ydbwyk Pending node-csr-u2sVzVkFYnMxPIYWjXHbqRJROtTZBYzA1s2vATPLzyo 30m system:bootstrap:8w6j3n Pending
approve CSR
[[email protected] ~]# kubectl certificate approve node-csr-gD18nmcyPUNWNyDQvCo2BMYiiA4K59BNkclFRWv1SAM certificatesigningrequest.certificates.k8s.io "node-csr gD18nmcyPUNWNyDQvCo2BMYiiA4K59BNkclFRWv1SAM" approved
檢視 Approve 結果:
[[email protected] ~]# kubectl describe csr node-csr-gD18nmcyPUNWNyDQvCo2BMYiiA4K59BNkclFRWv1SAM Name: node-csr-gD18nmcyPUNWNyDQvCo2BMYiiA4K59BNkclFRWv1SAM Labels: <none> Annotations: <none> CreationTimestamp: Thu, 20 Dec 2018 19:55:39 +0800 Requesting User: system:bootstrap:ydbwyk Status: Approved,Issued Subject: Common Name: system:node:192.168.80.10 Serial Number: Organization: system:nodes Events: <none>
Requesting User
:請求 CSR 的使用者,kube-apiserver 對它進行認證和授權;Subject
:請求籤名的證書資訊;- 證書的 CN 是 system:node:kube-node2, Organization 是 system:nodes,kube-apiserver 的 Node 授權模式會授予該證書的相關許可權;
自動approve csr請求
建立三個 ClusterRoleBinding,分別用於自動 approve client、renew client、renew server 證書:
[[email protected] ~]# cat > csr-crb.yaml <<EOF # Approve all CSRs for the group "system:bootstrappers" kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: auto-approve-csrs-for-group subjects: - kind: Group name: system:bootstrappers apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: system:certificates.k8s.io:certificatesigningrequests:nodeclient apiGroup: rbac.authorization.k8s.io --- # To let a node of the group "system:nodes" renew its own credentials kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: node-client-cert-renewal subjects: - kind: Group name: system:nodes apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient apiGroup: rbac.authorization.k8s.io --- # A ClusterRole which instructs the CSR approver to approve a node requesting a # serving cert matching its client cert. kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: approve-node-server-renewal-csr rules: - apiGroups: ["certificates.k8s.io"] resources: ["certificatesigningrequests/selfnodeserver"] verbs: ["create"] --- # To let a node of the group "system:nodes" renew its own server credentials kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: node-server-cert-renewal subjects: - kind: Group name: system:nodes apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: approve-node-server-renewal-csr apiGroup: rbac.authorization.k8s.io EOF
- auto-approve-csrs-for-group:自動 approve node 的第一次 CSR; 注意第一次 CSR 時,請求的 Group 為 system:bootstrappers;
- node-client-cert-renewal:自動 approve node 後續過期的 client 證書,自動生成的證書 Group 為 system:nodes;
- node-server-cert-renewal:自動 approve node 後續過期的 server 證書,自動生成的證書 Group 為 system:nodes;
生效配置:
[[email protected] ~]# kubectl apply -f csr-crb.yaml
檢視kubelet情況
等待一段時間(1-10 分鐘),三個節點的 CSR 都被自動 approve:
[[email protected] ~]# kubectl get csr NAME AGE REQUESTOR CONDITION node-csr-P7XcQAc2yNlXn1pUmQFxXNCdGyyt8ccVuW3bmoUZiK4 35m system:bootstrap:e7n0o5 Approved,Issued node-csr-gD18nmcyPUNWNyDQvCo2BMYiiA4K59BNkclFRWv1SAM 84m system:bootstrap:ydbwyk Approved,Issued node-csr-u2sVzVkFYnMxPIYWjXHbqRJROtTZBYzA1s2vATPLzyo 35m system:bootstrap:8w6j3n Approved,Issued
所有節點均 ready:
[[email protected] ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION 192.168.80.10 Ready <none> 69m v1.12.3 192.168.80.11 Ready <none> 36m v1.12.3 192.168.80.12 Ready <none> 36m v1.12.3