kubeasz/docs/07-安装kube-node节点.md

9.4 KiB
Raw Blame History

07-安装kube-node节点.md

node 是集群中承载应用的节点前置条件需要先部署好master节点(因为需要操作用户角色绑定批准kubelet TLS 证书请求等),它需要部署如下组件:

  • docker运行容器
  • calico 配置容器网络
  • kubelet node上最主要的组件
  • kube-proxy 发布应用服务与负载均衡
roles/kube-node
├── files
│   └── rbac.yaml
├── tasks
│   └── main.yml
└── templates
    ├── calico-kube-controllers.yaml.j2
    ├── kubelet.service.j2
    ├── kube-proxy-csr.json.j2
    └── kube-proxy.service.j2

请在另外窗口打开roles/kube-node/tasks/main.yml 文件,对照看以下讲解内容。

创建角色绑定

kubelet 启动时向 kube-apiserver 发送 TLS bootstrapping 请求,需要先将 bootstrap token 文件中的 kubelet-bootstrap 用户赋予 system:node-bootstrapper 角色,然后 kubelet 才有权限创建认证请求

# 增加15秒延时是为了等待上一步kube-master 启动完全
"sleep 15 && {{ bin_dir }}/kubectl create clusterrolebinding kubelet-bootstrap \
        --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap"

创建 bootstrapping kubeconfig 文件

#设置集群参数
  shell: "{{ bin_dir }}/kubectl config set-cluster kubernetes \
        --certificate-authority={{ ca_dir }}/ca.pem \
        --embed-certs=true \
        --server={{ KUBE_APISERVER }} \
        --kubeconfig=bootstrap.kubeconfig"
#设置客户端认证参数
  shell: "{{ bin_dir }}/kubectl config set-credentials kubelet-bootstrap \
        --token={{ BOOTSTRAP_TOKEN }} \
        --kubeconfig=bootstrap.kubeconfig"
#设置上下文参数
  shell: "{{ bin_dir }}/kubectl config set-context default \
        --cluster=kubernetes \
        --user=kubelet-bootstrap \
        --kubeconfig=bootstrap.kubeconfig"
#选择默认上下文
  shell: "{{ bin_dir }}/kubectl config use-context default --kubeconfig=bootstrap.kubeconfig"
  • 注意 kubelet bootstrapping认证时是靠 token的后续由 master为其生成证书和私钥
  • 以上生成的bootstrap.kubeconfig配置文件需要移动到/etc/kubernetes/目录下后续在kubelet启动参数中指定该目录下的 bootstrap.kubeconfig

创建 kubelet 的服务文件

  • 必须先创建工作目录 /var/lib/kubelet
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service

[Service]
WorkingDirectory=/var/lib/kubelet
#--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest
ExecStart={{ bin_dir }}/kubelet \
  --address={{ NODE_IP }} \
  --hostname-override={{ NODE_IP }} \
  --pod-infra-container-image=mirrorgooglecontainers/pause-amd64:3.0 \
  --experimental-bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig \
  --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \
  --cert-dir={{ ca_dir }} \
  --network-plugin=cni \
  --cni-conf-dir=/etc/cni/net.d \
  --cni-bin-dir={{ bin_dir }} \
  --cluster-dns={{ CLUSTER_DNS_SVC_IP }} \
  --cluster-domain={{ CLUSTER_DNS_DOMAIN }} \
  --hairpin-mode hairpin-veth \
  --allow-privileged=true \
  --fail-swap-on=false \
  --logtostderr=true \
  --v=2
#kubelet cAdvisor 默认在所有接口监听 4194 端口的请求, 以下iptables限制内网访问
ExecStartPost=/sbin/iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -s 172.16.0.0/12 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -s 192.168.0.0/16 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -p tcp --dport 4194 -j DROP
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
  • --pod-infra-container-image 指定基础容器的镜像负责创建Pod 内部共享的网络、文件系统等,这个基础容器非常重要:K8S每一个运行的 POD里面必然包含这个基础容器如果它没有运行起来那么你的POD 肯定创建不了kubelet日志里面会看到类似 FailedCreatePodSandBox 错误,本项目集群常见 SandBox 容器起不来有两个原因a. pause镜像没有下载到 b. calico/node 容器还没有正常运行,可用docker ps -a 验证
  • --experimental-bootstrap-kubeconfig 指向 bootstrap kubeconfig 文件kubelet 使用该文件中的用户名和 token 向 kube-apiserver 发送 TLS Bootstrapping 请求
  • --cluster-dns 指定 kubedns 的 Service IP(可以先分配,后续创建 kubedns 服务时指定该 IP)--cluster-domain 指定域名后缀,这两个参数同时指定后才会生效;
  • --network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir={{ bin_dir }} 为使用cni 网络并调用calico管理网络所需的配置
  • --fail-swap-on=false K8S 1.8需显示禁用这个,否则服务不能启动

批准kubelet 的 TLS 证书请求

sleep 15 && {{ bin_dir }}/kubectl get csr|grep 'Pending' | awk 'NR>0{print $1}'| xargs {{ bin_dir }}/kubectl certificate approve
  • 增加15秒延时等待kubelet启动
  • kubectl get csr |grep 'Pending' 找出待批准的 TLS请求
  • kubectl certificate approve 批准请求

创建 kube-proxy 证书请求

{
  "CN": "system:kube-proxy",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "HangZhou",
      "L": "XS",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
  • CN 指定该证书的 User 为 system:kube-proxy预定义的 ClusterRoleBinding system:node-proxier 将User system:kube-proxy 与 Role system:node-proxier 绑定,授予了调用 kube-apiserver Proxy 相关 API 的权限;
  • kube-proxy 使用客户端证书可以不指定hosts 字段

创建 kube-proxy kubeconfig 文件

#设置集群参数
  shell: "{{ bin_dir }}/kubectl config set-cluster kubernetes \
        --certificate-authority={{ ca_dir }}/ca.pem \
        --embed-certs=true \
        --server={{ KUBE_APISERVER }} \
        --kubeconfig=kube-proxy.kubeconfig"
#设置客户端认证参数
  shell: "{{ bin_dir }}/kubectl config set-credentials kube-proxy \
        --client-certificate={{ ca_dir }}/kube-proxy.pem \
        --client-key={{ ca_dir }}/kube-proxy-key.pem \
        --embed-certs=true \
        --kubeconfig=kube-proxy.kubeconfig"
#设置上下文参数
  shell: "{{ bin_dir }}/kubectl config set-context default \
        --cluster=kubernetes \
        --user=kube-proxy \
        --kubeconfig=kube-proxy.kubeconfig"
#选择默认上下文
  shell: "{{ bin_dir }}/kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig"
  • 生成的kube-proxy.kubeconfig 配置文件需要移动到/etc/kubernetes/目录后续kube-proxy服务启动参数里面需要指定

创建 kube-proxy服务文件

[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
WorkingDirectory=/var/lib/kube-proxy
ExecStart={{ bin_dir }}/kube-proxy \
  --bind-address={{ NODE_IP }} \
  --hostname-override={{ NODE_IP }} \
  --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig \
  --logtostderr=true \
  --v=2
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
  • --hostname-override 参数值必须与 kubelet 的值一致,否则 kube-proxy 启动后会找不到该 Node从而不会创建任何 iptables 规则
  • 特别注意kube-proxy 根据 --cluster-cidr 判断集群内部和外部流量,指定 --cluster-cidr 或 --masquerade-all 选项后 kube-proxy 才会对访问 Service IP 的请求做 SNAT但是这个特性与calico 实现 network policy冲突所以如果要用 network policy这两个选项都不要指定。

部署calico-kube-controllers

calico networkpolicy正常工作需要3个组件

  • master/node 节点需要运行的 docker 容器 calico/node
  • cni-plugin 所需的插件二进制和配置文件
  • calico kubernetes controllers 负责监听Network Policy的变化并将Policy应用到相应的网络接口

准备RBAC和calico-kube-controllers.yaml 文件

  • RBAC
    • 最小化权限使用
  • Controllers
    • 注意只能跑一个 controller实例
    • 注意该 controller实例需要使用宿主机网络 hostNetwork: true

创建calico-kube-controllers

"sleep 15 && {{ bin_dir }}/kubectl create -f /root/local/kube-system/calico/rbac.yaml && \ 
        {{ bin_dir }}/kubectl create -f /root/local/kube-system/calico/calico-kube-controllers.yaml"
  • 增加15s等待集群node ready

验证 node 状态

systemctl status kubelet	# 查看状态
systemctl status kube-proxy
journalctl -u kubelet		# 查看日志
journalctl -u kube-proxy 

运行 kubectl get node 可以看到类似

NAME           STATUS    ROLES     AGE       VERSION
192.168.1.42   Ready     <none>    2d        v1.8.4
192.168.1.43   Ready     <none>    2d        v1.8.4
192.168.1.44   Ready     <none>    2d        v1.8.4

并且稍等一会,kubectl get pod -n kube-system -o wide 可以看到有个calico controller 的POD运行且使用了host 网络

kubectl get pod -n kube-system -o wide
NAME                                      READY     STATUS    RESTARTS   AGE       IP              NODE
calico-kube-controllers-69bcb79c6-b444q   1/1       Running   0          2d        192.168.1.44    192.168.1.44