• 部署 Worker 节点
    • 安装依赖
    • 禁用 Swap
    • 关闭 SELinux
    • 准备目录
    • 下载安装二进制
    • 配置
      • 配置 containerd
      • 配置 kubelet
    • 启动
    • 验证
    • 签发 kubelet server 证书

    部署 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 端口