原文内容:https://gitee.com/dev-99cloud/training-kubernetes ,在此基础上有新增。

Lesson 05: K8S Schedule

5.1 怎么部署多节点的 k8s 集群?

  • 参考资料

  • 步骤

    1. 在 master 节点上取得 token 和 ca_hash

      root@ckamaster003:~# kubeadm token create
      b6k3qj.avofghaucefqe0a8
      
      root@ckamaster003:~# kubeadm token list | grep -v TOKEN | awk '{print $1}' | head -n -1
      b6k3qj.avofghaucefqe0a8
      
      root@ckamaster003:~# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
      d7d0906ebe29f607587e404ef6c393169a51e5f6c81e22a2a48f30ef8702e12a
      
      root@ckamaster003:~# ifconfig | grep eth0 -A 1
      eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
              inet 172.31.43.105  netmask 255.255.240.0  broadcast 172.31.47.255
      
    2. 可以用 kubeadm 命令将新节点加入 k8s cluster,先在 master 节点上生成命令

      kubeadm token create
      master_ip=$(ifconfig | grep eth0 -A 1 | grep inet | awk '{print $2}')
      token=$(kubeadm token list | grep -v TOKEN | awk '{print $1}' | head -n 1)
      ca_hash=$(openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //')
      
      echo kubeadm join $master_ip:6443 --token $token --discovery-token-ca-cert-hash sha256:$ca_hash
      
    3. 然后将生成的命令复制到 worker 节点上执行,执行之前,worker 节点上应该先安装 docker 和 kubeadm - 参考 1.6 节,在 Ubuntu 18.04 上配置 Docker - 参考 2.7 节,安装 kubeadm - 然后将之前在 master 上生成的命令复制到 worker 节点上执行:kubeadm join $master_ip:6443 --token $token --discovery-token-ca-cert-hash sha256:$ca_hash

    4. 在新节点上配置 kubectl

      mkdir -p $HOME/.kube
      scp root@$master_ip:/etc/kubernetes/admin.conf $HOME/.kube/config
      chown $(id -u):$(id -g) $HOME/.kube/config
      
    5. 然后在新节点上用 kubectl 命令可以看到 node 已经 ready

      root@ckaslave003:~# kubectl get nodes
      NAME           STATUS   ROLES    AGE   VERSION
      ckamaster003   Ready    master   20m   v1.18.3
      ckaslave003    Ready    <none>   33s   v1.18.3
      

5.2 怎么把应用部署到指定的 Node?

  • 参考:Labels and Selectors

    apiVersion: v1
    kind: Pod
    metadata:
      name: label-demo
      labels:
        environment: production
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
    
    # 创建一个带 label 的 pod 对象 label-pod.yaml,内容如上
    
    kubectl apply -f label-pod.yaml
    
    root@ckatest:~# kubectl get pods -l environment=production
    NAME         READY   STATUS    RESTARTS   AGE
    label-demo   1/1     Running   0          4m16s
    root@ckatest:~# kubectl get pods -l environment=production,tier=frontend
    No resources found in default namespace.
    
    root@ckatest:~# kubectl get pods -l 'environment in (production),tier in (frontend)'
    No resources found in default namespace.
    root@ckatest:~# kubectl get pods -l 'environment in (production, qa)'
    NAME         READY   STATUS    RESTARTS   AGE
    label-demo   1/1     Running   0          4m42s
    root@ckatest:~# kubectl get pods -l 'environment,environment notin (frontend)'
    NAME         READY   STATUS    RESTARTS   AGE
    label-demo   1/1     Running   0          4m50s
    
  • 参考:Assigning Pods to Nodes

  • 实验:

    1. 如何根据 label 选择 node 启动 pod?(参考上方示例)

    2. 如何根据 node 名称选择 node 启动 pod?

      apiVersion: v1
      kind: Pod
      metadata:
        name: nginx
      spec:
        nodeName: foo-node # schedule pod to specific node
        containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
      

Node Selector 实际是节点亲和,用于将 pod 部署到特定节点

5.3 什么是 Taints & Toleration?

  • 参考: Taints and Tolerations

  • 实验

    为 master 节点打上 taint

    kubectl taint nodes k8s-masterXXX key=value:NoSchedule
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx5
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
      nodeSelector:
        node-role.kubernetes.io/master: ""
      tolerations:
      - key: "key"
        operator: "Equal"
        value: "value"
        effect: "NoSchedule"
    
  • 如果不用 node selector,而是直接用 nodeName,可以无视 NoSchedule Taint,可以被调度。但调度上去之后,会被 NoExecute Taint 驱逐。

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      nodeName: ckamaster003
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
    

Taint 实际上是节点反亲和,不允许 pod 部署到带 taint 的节点。

Toleration 和 Taint 结合,可以让特定节点只允许运行特定 pod,专节点专用。

5.4 什么是 Node Affinity?

思考:

  1. Node Affinity 和 Node Selector 的关系?

5.5 什么是 Pod Affinity?

5.6 实验:Pod 调度