K8s零散小知识

Saturday, December 4, 2021

概述

这篇文章是记录k8s的一些小知识点,涵盖一些操作配置等等,是对平时问题的一些小记录。

1. 命名空间与 Node 绑定

实际部署中,有时候会希望将某一个特定的命名空间下的 pod 都部署在指定的同一个节点,这里就涉及到了 PodNodeSelector,它 允许 Pod 强制在特定标签的节点上运行,它的控制器行为如下:

  1. 如果 Namespace 的注解带有键 scheduler.alpha.kubernetes.io/node-selector, 则将其值用作节点选择算符。
  2. 如果名字空间缺少此类注解,则使用 PodNodeSelector 插件配置文件中定义的 clusterDefaultNodeSelector 作为节点选择算符。
  3. 评估 Pod 节点选择算符和名字空间节点选择算符是否存在冲突。存在冲突将导致拒绝。
  4. 评估 Pod 节点选择算符和特定于名字空间的被允许的选择算符所定义的插件配置文件是否存在冲突。 存在冲突将导致拒绝。

如果我们希望将 pod 部署到某个节点,我们可以给该 pod 增加 nodeSelector 配置,值可以是节点名称,也可以是 label,同样,如果希望某个命名空间下的所有 pod 都部署到某个节点,我们只需要让 pod 创建的时候自动带上配置 nodeSelector 即可。

操作
  1. 修改 kubeapi 配置文件 /etc/kubernetes/manifests/kube-apiserver.yaml--enable-admission-plugins 增加 PodNodeSelector,如下:

    --enable-admission-plugins=NodeRestriction,PodNodeSelector
    

    重启 kubelet

    systemctl daemon-reload
    systemctl restart kubelet
    
  2. 编辑命名空间,增加 scheduler.alpha.kubernetes.io/node-selector 注解,值可以是指定节点的名称,也可以是 label,如下:

    • 编辑命名空间

      kubectl edit namespace devops
      
    • 增加注解,此处我加了一个 label usefulness=devops

      # Please edit the object below. Lines beginning with a '#' will be ignored,
      # and an empty file will abort the edit. If an error occurs while saving this file will be
      # reopened with the relevant failures.
      #
      apiVersion: v1
      kind: Namespace
      metadata:
        annotations:
          scheduler.alpha.kubernetes.io/node-selector: usefulness=devops
        creationTimestamp: "2021-12-04T09:39:36Z"
        finalizers:
        - finalizers.kubesphere.io/namespaces
        labels:
          kubernetes.io/metadata.name: devops
          kubesphere.io/namespace: devops
        name: devops
        resourceVersion: "69106"
        uid: 1c1c6f06-a491-49b9-9dcc-7458e1d590f1
      spec:
        finalizers:
        - kubernetes
      status:
        phase: Active
      
  3. 为节点增加指定的label,如下:

    root@master:~/k8s# kubectl label node node1 usefulness=devops
    node/node1 labeled
    root@master:~/k8s# kubectl describe node node1
    Name:               node1
    Roles:              worker
    Labels:             beta.kubernetes.io/arch=amd64
                        beta.kubernetes.io/os=linux
                        kubernetes.io/arch=amd64
                        kubernetes.io/hostname=node1
                        kubernetes.io/os=linux
                        node-role.kubernetes.io/worker=
                        usefulness=devops
    Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
                        node.alpha.kubernetes.io/ttl: 0
    
    ..........
    

经过上面三个步骤,现在该命名空间下新创建的 pod 都会自动带上 nodeSelector 配置了。

测试

这里我们测试在该命名空间下创建一个 nginx 应用,yaml 文件如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: devops
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

创建 deployment

root@master:~/k8s# kubectl apply -f nginx.yaml
deployment.apps/nginx-deployment created

这个时候我们观察下对应的 pod 的信息:

root@master:~/k8s# kubectl get pod -n devops -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
nginx-deployment-66b6c48dd5-b8qhd   1/1     Running   0          84s   10.233.90.10   node1   <none>           <none>
nginx-deployment-66b6c48dd5-ll7pl   1/1     Running   0          84s   10.233.90.9    node1   <none>           <none>
root@master:~/k8s# kubectl describe pod nginx-deployment-66b6c48dd5-b8qhd -n devops
Name:         nginx-deployment-66b6c48dd5-b8qhd
Namespace:    devops
Priority:     0
Node:         node1/192.168.1.101
.....
QoS Class:                   BestEffort
Node-Selectors:              usefulness=devops
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
.....

注意看该 pod 已经部署在了节点 node1 上,并且 pod 的信息中有这么一栏,这就是创建 pod 时自动带上的注解:

Node-Selectors:              usefulness=devops

这个时候我们查看 pod 的 yaml 配置,可以看到该 yaml 文件 spec 下自动多了一个配置,如下:

root@master:~/k8s# kubectl get pod nginx-deployment-66b6c48dd5-b8qhd -n devops -o yaml
apiVersion: v1
kind: Pod
metadata:
  .....
spec:
  .....
  nodeSelector:
    usefulness: devops
  .....

至此,该命名空间下的所有 pod 都会自动部署到 节点 node1 上。

2. 修改 NodePort 端口范围

默认情况下,NodePort 的端口范围是 30000-32767,但是有时候我们希望使用范围之外的节点端口,比如 80 和 443,这个时候我们仅需要修改 kube-apiserver 的对应配置 --service-node-port-range 即可,如果没有该项,手动添加一个即可,如下:

root@master:~/k8s# cat /etc/kubernetes/manifests/kube-apiserver.yaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 192.168.1.100:6443
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=192.168.1.100
    - --allow-privileged=true
    - --audit-log-maxage=30
    - --audit-log-maxbackup=10
    - --audit-log-maxsize=100
    - --authorization-mode=Node,RBAC
    - --bind-address=0.0.0.0
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction,PodNodeSelector
    .....
    - --service-node-port-range=1-32767
    .....

之后重启 kubelet

systemctl daemon-reload
systemctl restart kubelet

这里需要注意两点:

  • 对于已经创建的NodePort类型的Service,需要删除重新创建
  • 如果集群有多个 Master 节点,需要逐个修改每个节点上的 /etc/kubernetes/manifests/kube-apiserver.yaml 文件,并重启 kubelet。
Kubernetes Kubernetes

Kubekey搭建多节点k8s集群k8s搭配traefik