部署 Worker 节点

Worker 节点主要安装 kubelet 来管理、运行工作负载 (Master 节点也可以部署为特殊 Worker 节点来部署关键服务)

安装依赖

  1. sudo apt-get update
  2. sudo apt-get -y install socat conntrack ipset

禁用 Swap

默认情况下,如果开启了 swap,kubelet 会启动失败,k8s 节点推荐禁用 swap。

验证一下是否开启:

  1. sudo swapon --show

如果输出不是空的说明开启了 swap,使用下面的命令禁用 swap:

  1. sudo swapoff -a

为了防止开机自动挂载 swap 分区,可以注释 /etc/fstab 中相应的条目:

  1. sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

关闭 SELinux

关闭 SELinux,否则后续 K8S 挂载目录时可能报错 Permission denied:

  1. sudo setenforce 0

修改配置文件,永久生效:

  1. sudo sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

准备目录

  1. sudo mkdir -p \
  2. /etc/cni/net.d \
  3. /opt/cni/bin \
  4. /var/lib/kubelet \
  5. /var/lib/kubernetes \
  6. /var/run/kubernetes

下载安装二进制

下载二进制:

  1. wget -q --show-progress --https-only --timestamping \
  2. https://github.com/opencontainers/runc/releases/download/v1.0.0-rc8/runc.amd64 \
  3. https://github.com/containerd/containerd/releases/download/v1.3.0/containerd-1.3.0.linux-amd64.tar.gz \
  4. https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.16.1/crictl-v1.16.1-linux-amd64.tar.gz \
  5. https://github.com/containernetworking/plugins/releases/download/v0.8.2/cni-plugins-linux-amd64-v0.8.2.tgz \
  6. https://storage.googleapis.com/kubernetes-release/release/v1.16.1/bin/linux/amd64/kubelet
  7. sudo mv runc.amd64 runc

安装二进制:

  1. chmod +x crictl kubelet runc
  2. tar -xvf crictl-v1.16.1-linux-amd64.tar.gz
  3. mkdir containerd
  4. tar -xvf containerd-1.3.0.linux-amd64.tar.gz -C containerd
  5. sudo cp crictl kubelet runc /usr/local/bin/
  6. sudo cp containerd/bin/* /bin/
  7. sudo tar -xvf cni-plugins-linux-amd64-v0.8.2.tgz -C /opt/cni/bin/

配置

配置 containerd

创建 containerd 启动配置 config.toml:

  1. sudo mkdir -p /etc/containerd/
  2. cat << EOF | sudo tee /etc/containerd/config.toml
  3. [plugins]
  4. [plugins.cri.containerd]
  5. snapshotter = "overlayfs"
  6. [plugins.cri.containerd.default_runtime]
  7. runtime_type = "io.containerd.runtime.v1.linux"
  8. runtime_engine = "/usr/local/bin/runc"
  9. runtime_root = ""
  10. EOF

创建 systemd 配置 containerd.service:

  1. cat <<EOF | sudo tee /etc/systemd/system/containerd.service
  2. [Unit]
  3. Description=containerd container runtime
  4. Documentation=https://containerd.io
  5. After=network.target
  6. [Service]
  7. ExecStartPre=/sbin/modprobe overlay
  8. ExecStart=/bin/containerd
  9. Restart=always
  10. RestartSec=5
  11. Delegate=yes
  12. KillMode=process
  13. OOMScoreAdjust=-999
  14. LimitNOFILE=1048576
  15. LimitNPROC=infinity
  16. LimitCORE=infinity
  17. [Install]
  18. WantedBy=multi-user.target
  19. EOF

配置 kubelet

放入 这里 创建好的 CA 证书与 这里 创建好的 bootstrap-kubeconfig:

  1. sudo cp ca.pem /var/lib/kubernetes/
  2. sudo cp bootstrap-kubeconfig /var/lib/kubelet/

事先确定好集群 DNS 的 CLUSTER IP 地址,通常可以用 service 网段的最后一个可用 IP 地址:

  1. DNS=10.32.0.255

创建 kubelet 启动配置 config.yaml:

  1. cat <<EOF | sudo tee /var/lib/kubelet/config.yaml
  2. kind: KubeletConfiguration
  3. apiVersion: kubelet.config.k8s.io/v1beta1
  4. authentication:
  5. anonymous:
  6. enabled: false
  7. webhook:
  8. enabled: true
  9. x509:
  10. clientCAFile: "/var/lib/kubernetes/ca.pem"
  11. authorization:
  12. mode: Webhook
  13. clusterDomain: "cluster.local"
  14. clusterDNS:
  15. - "${DNS}"
  16. resolvConf: "/run/systemd/resolve/resolv.conf"
  17. runtimeRequestTimeout: "15m"
  18. rotateCertificates: true
  19. serverTLSBootstrap: true
  20. EOF

NODE 变量表示节点名称,kube-apiserver 所在节点需要能够通过这个名称访问到节点,这里推荐直接使用节点内网 IP,不需要配 hosts 就能访问:

  1. NODE="10.200.16.79"

创建 systemd 配置 kubelet.service:

  1. cat <<EOF | sudo tee /etc/systemd/system/kubelet.service
  2. [Unit]
  3. Description=Kubernetes Kubelet
  4. Documentation=https://github.com/kubernetes/kubernetes
  5. After=containerd.service
  6. Requires=containerd.service
  7. [Service]
  8. ExecStart=/usr/local/bin/kubelet \\
  9. --config=/var/lib/kubelet/config.yaml \\
  10. --container-runtime=remote \\
  11. --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \\
  12. --image-pull-progress-deadline=2m \\
  13. --bootstrap-kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig \\
  14. --kubeconfig=/var/lib/kubelet/kubeconfig \\
  15. --network-plugin=cni \\
  16. --register-node=true \\
  17. --hostname-override=${NODE} \\
  18. --v=2
  19. Restart=on-failure
  20. RestartSec=5
  21. [Install]
  22. WantedBy=multi-user.target
  23. EOF

启动

  1. sudo systemctl daemon-reload
  2. sudo systemctl enable containerd kubelet
  3. sudo systemctl start containerd kubelet

验证

配置好 kubectl,执行下 kubectl:

  1. $ kubectl get node
  2. NAME STATUS ROLES AGE VERSION
  3. 10.200.16.79 NotReady <none> 11m v1.16.1

没有装网络插件,节点状态会是 NotReady,带 node.kubernetes.io/not-ready:NoSchedule 这个污点,默认是无法调度普通 Pod,这个是正常的。后面会装网络插件,通常以 Daemonset 部署,使用 hostNetwork,并且容忍这个污点。

签发 kubelet server 证书

由于之前做过 RBAC 授权 kubelet 创建 CSR 与自动签发和更新证书,kubelet 启动时可以发起 client 与 server 证书的 CSR 请求,并自动审批通过 client 证书的 CSR 请求,kube-controller-manager 在自动执行证书签发,最后 kubelet 可以获取到 client 证书并加入集群,我们可以在 /var/lib/kubelet/pki 下面看到签发出来的 client 证书:

  1. ls -l /var/lib/kubelet/pki
  2. total 4
  3. -rw------- 1 root root 1277 Oct 10 20:46 kubelet-client-2019-10-10-20-46-23.pem
  4. lrwxrwxrwx 1 root root 59 Oct 10 20:46 kubelet-client-current.pem -> /var/lib/kubelet/pki/kubelet-client-2019-10-10-20-46-23.pem

kubeconfig 中引用这里的 kubelet-client-current.pem 这个证书,是一个指向证书 bundle 的软连接,包含证书公钥与私钥

但 server 证书默认无法自动审批,需要管理员人工审批,下面是审批方法,首先看下未审批的 CSR:

  1. $ kubectl get csr
  2. NAME AGE REQUESTOR CONDITION
  3. csr-6gkn6 2m4s system:bootstrap:360483 Approved,Issued
  4. csr-vf285 103s system:node:10.200.17.6 Pending

可以看到 system:bootstrap 开头的用户的 CSR 请求已经自动 approve 并签发证书了,这就是因为 kubelet 使用 bootstrap token 认证后在 system:bootstrappers 用户组,而我们创建了对应 RBAC 为此用户组授权自动 approve CSR 的权限。下面 system:node 开头的用户的 CSR 请求状态是 Pending,需要管理员来 approve。

  1. $ kubectl certificate approve csr-vf285
  2. certificatesigningrequest.certificates.k8s.io/csr-vf285 approved
  3. $ ls -l /var/lib/kubelet/pki
  4. total 8
  5. -rw------- 1 root root 1277 Oct 10 20:46 kubelet-client-2019-10-10-20-46-23.pem
  6. lrwxrwxrwx 1 root root 59 Oct 10 20:46 kubelet-client-current.pem -> /var/lib/kubelet/pki/kubelet-client-2019-10-10-20-46-23.pem
  7. -rw------- 1 root root 1301 Oct 10 21:09 kubelet-server-2019-10-10-21-09-15.pem
  8. lrwxrwxrwx 1 root root 59 Oct 10 21:09 kubelet-server-current.pem -> /var/lib/kubelet/pki/kubelet-server-2019-10-10-21-09-15.pem

和 client 证书一样,kubelet-server-current.pem 也是一个指向证书 bundle 的软连接,包含证书公钥与私钥,用与 kubelet 监听 10250 端口