k8s功能介绍和常用命令

一、Node篇

kubectl get nodes 查看所有node信息
kubectl get nodes -owide 查看所有node的详细信息
kubectl get node -o yaml 查看所有node的yaml文件
kubectl get node master01 -o yaml 查看master01的yaml文件
kubectl get node --show-labels 查看所有node的label信息

kubectl describe node node01 |grep -i taint -A3 查看node01的污点配置
kubectl taint nodes k8s-node01 ssd=true:PreferNoSchedule 给node01配置污点

二、deployment篇

2.1 创建deployment,命名为nginx

kubectl create deployment nginx --image=nginx:1.15.2

2.2 查看deployment,包括IP

kubectl get deploy -owide
kubectl scale deploy {deployment的名称} -n xiyu --replicas=4  缩扩容副本数
kubectl describe -f pod-diff-nodes.yaml  通过查看文件创建deployment的具体信息
备注:
NAME: Deployment名称
READY:Pod的状态,已经Ready的个数
UP-TO-DATE:已经达到期望状态的被更新的副本数
AVAILABLE:已经可以用的副本数
AGE:显示应用程序运行的时间
CONTAINERS:容器名称
IMAGES:容器的镜像
SELECTOR:管理的Pod的标签

2.3 将deployment配置导出yaml格式文件

kubectl create deploy nginx --try-run=client --image=nginx:1.15.2 >nginx_deployment.yaml

2.4 deployment更新,升级pod镜像

kubectl set image deploy nginx nginx=nginx:1.15.3 –record

2.5 deployment回滚

kubectl rollout history deploy nginx

2.6 deployment的暂停和恢复

kubectl rollout pause deployment nginx
kubectl set image deploy nginx nginx=nginx:1.15.3 --record
kubectl set resources deploy nginx -c nginx --limits=cpu=200m,memory=128Mi --requests=cpu=10m,memory=16Mi  //添加内存cpu配置
kubectl get deploy nginx -oyaml
kubectl rollout resume deploy nginx

三、statefulset篇

用statefulset部署pod,会按照顺序创建,如pod名字为nginx,副本数为3,那么pod名称会自动生成nginx-0,nginx-1,nginx-2,并且容器的hostname也为nginx-0,nginx-1,nginx-2
1)创建statefulset前必须要创建service
2)statefulset 按照顺序启动,前一个正常,才会继续下一个,删除的话为倒序
3)用yaml文件创建,一个service和pod

3.1 扩容和缩容

kubectl scale --replicas=2 qingchen nginx  扩容或者缩容
kubectl get pod --show-lables 查看标签
kubectl get pod -A --show-lables 查看标签
kubectl get pod -l app=nginx -w  查看指定的标签,监视资源变化

四、deamonset篇

kubectl get po -owide 
kubectl label node01 node02 ds=ture  //给node打个标签

备注:yaml文件中spec块中 nodeSelector: ds: true 这样创建的deamonset就会自动选择node

kubectl rollout history ds nginx 查看回滚记录   

如果想要一个node中自动部署deamonset,可以直接给node 设置一个标签

kubectl label node03 ds=ture  //给node打个标签
kubectl get pod -owide

五、label篇

kubectl get pod -A --show-labels                查看所有namespace下的所有标签
kubectl get pod -A -l app=busybox               查看所有namespace下的指定的标签
kubectl get pod -n kube-public -l app=busybox   查看指定namespace中的标签
kubectl label pod busybox app=busybox -n kube-public      配置pod的标签为app=busybox
kubectl label pod busybox app- -n kube-public   删除app=busybox的标签,用app-减号 

kubectl get pod -n -A -l 'k8s-app in (metrices-server,kubernetes-dashboard)' 过滤多个标签
kubectl get pod -A -l version!=v1 过滤不等于version=v1的标签

kubectl get node --show-labels  查看所有node节点标签
kubectl label nodes <node-name> <label-key>=<label-value>   给node添加标签
kubectl label nodes <node-name> <node-name ><label-key>=<label-value>   给多个node添加标签
kubectl label nodes <node-name> <label-key>-   删除标签
kubectl label nodes <node-name> <label-key>=<label-value> --overwrite  修改标签

六、volumes篇

6.1 常用命令

  • kubectl get pv
  • kubectl get pvc

6.2 emptyDir

删除pod,emptyDir会随之删除,只是做容器间共享数据用,无法持久化数据

apiVersion: v1
kind: Pod
metadata:
  name:test-pod
spec:
  containers:
  - image: k8s.gcr.io/test/webserver
    name: test-container
    volumeMounts:
    - mountpath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:{}
    

6.3 hostPath

共享pod宿主机的文件或者文件夹,pod迁移后无法正常使用,因此很少被使用

apiVersion: v1
kind: Pod
metadata:
  name:test-pod2
spec:
  containers:
  - image: k8s.gcr.io/test/webserver
    name: test-container2
    volumeMounts:
    - mountpath: /cache2
      name: cache-volume2
  volumes:
  - name: cache-volume2
    hostPath:
      path: /data
      type: Directory

6.4 NFS

需要安装nfs-unils,一般生产环境下NFS共享并无法实现高可用保障,如果是公有云环境下,建议使用阿里云NAS存储,协议与NFS兼容

NFS服务端:yum install nfs* rpcbind -y
NFS客户端:yum install nfs-utils -y 
NFS服务端创建共享目录 mkdir /data/k8s/ -p
NFS服务端配置 vim /etc/exports 添加一下内容
/data/k8s. *(rw,sync,no_subtree_check,no_root_squash)
NFS服务端配置加载 exportfs -r
NFS服务端服务重启 systemctl restart nfs rpcbind
NFS服务端口号查看 netstat -anlp |grep nfs
客户端挂载:mount -fs nfs 10.1.1.1:/data/k8s /mnt/ 
10.1.1.1是nfs服务端的IP

https://blog.csdn.net/m0_46327721/article/details/108006037
先配置好nfs共享服务后,再配置pod

apiVersion: v1
kind: Pod
metadata:
  name:test-pod3
spec:
  containers:
  - image: k8s.gcr.io/test/webserver
    name: test-container3
    volumeMounts:
    - mountpath: /mnt
      name: nfs-volume
  volumes:
  - name: nfs-volume
    nfs:
      server:192.168.1.100
      path: /data/nfs/test-dp

6.5 k8s持久化存储 PV & PVC

有些问题使用volume是无法解决的,比如
1)数据卷不再被挂载了,数据如何处理?
2)只读挂载?
3)只能一个pod挂载
4)限制某个pod使用10G空间

PersistentVolume:简称PV,由k8s管理员设置的存储,可以配置ceph, NFS, GlusterFS等常用存储配置,相对于volume,它提供了更多功能,比如生命周期管理,大小限制,PV分为静态和动态,PV是没有命名空间限制

PersistentVolumeClaim:简称PVC,是对存储PV的请求,配置需要什么类型的PV,PV无法直接使用,需要配置成PVC才可以,PVC是有命名空间限制

6.6 PV的访问策略和回收策略

1)ReadWriteOnce:可以被单个节点以读写模式挂载,命令行中可缩写为RWO
2)ReadOnlyMany:可以被多个节点以只读模式挂载,命令行中可缩写为ROX
3)ReadWriteMany:可以被多个节点以读写模式挂载,命令行中可缩写为RWX

1)Retain:保留,允许手动回收,当删除pvc时,pv仍保留,可以手动回收
2)Recycle:回收,如果Volume插件支持,Recycle策略对卷支持rm -rf清理PV,为创建新的pvc做准备,但该策略将来被废弃,目前只有NFS HostPath支持
3)Delete:删除,如果Volume插件支持,删除pvc会同时删除pv,动态卷默认delete模式,目前支持delete的存储后端包括AWS EBS ,GCE PD ,Azure Disk 等

  • 可以通过persistentVolumeReclaimPolicy:Recyle 字段配置

6.7 PV的yaml案例

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server:172.17.0.2
备注: volumeMode:卷的模式,目前支持Filesystem(文件系统)和block(块),其中block需要后端存储支持,默认为文件系统 accessModes:该PV的访问模式 storageClassName:PV的类,一个特定类型的PV只能绑定到特定类别的PVC,用来绑定PVC使用的名字 mountOptions:非必须,新版本中已废弃 nfs:NFS服务配置,包括两个选项,path:nfs上的共享目录,server:nfs的IP地址
  • 文件存储:一些数据被多个节点使用,实现方式:NFS NAS FTP等(生产环境中不建议使用NFS,建议使用有高可用的功能的NAS Ceph等)
  • 块存储:一些数据只能被一个节点使用,或者将一块裸盘整个挂载使用,比如数据库 redis等,实现方式:Ceph, GlusterFS 公有云等
  • 对象存储:由程序代码直接实现的一种存储方式,云原生应用无状态常用的实现方式,实现方式:一般是复核S3协议的云存储,比如AWS的S3存储,Minio等

6.8 创建NAS或者NFS类型的PV

1、先创建NFS服务端和客户端(已完成,请忽略)
2、创建yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server:172.17.0.2

pv的几种status

Available:可用,还未被PVC绑定资源
Bound:已绑定,被PVC绑定
Released:已释放,pvc被删除,但资源还未被重新使用
Faild:失败,自动回收失败(Recycle策略中存在的一种)

6.9 创建hostPath类型的PV

2、创建yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
  labels:
    type:local
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: hostpath
  hostPath:
    path:"/mnt/data"

备注:path是指宿主机上的目录路径,与nas和nfs的唯一不同的地方就是后端存储的地方

  hostPath:
    path:"/mnt/data"

6.10 创建PVC,绑定到PV

  • 单独创建PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-test  //随便写
spec:
  storageClassName: slow   //与PV一致
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage:3Gi

注意:slow为pv的storageClassName的名称,accessModes要跟pv的模式一致,容量要小于pv的大小

  • 常用命令
    kubectl create -f pvc-nfs.yaml
    kubectl get -f pvc-nfs.yaml
    kubect get pv pv-nfs

6.11 创建POD中绑定PVC

创建yaml为pvc-nfs-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pvc-pod
spec:
  volumes:
    - name:pvc-storage    #volumes的名称
      persistentVolumeClaim:
        claimName:nfs-pvc-claim  #pvc的名称
  containers:
    - name: pvc-container
      image: nginx
      ports:
        - containerPort: 80
          name:"http-server"
      volumeMounts:
        - mountPath:"/usr/share/nginx/html"
          name: pvc-storage
  • 常用命令
    kubectl create -f pvc-nfs-pod.yaml
    kubectl get pod
    kubectl get pvc
    进入pod中执行
    df -Th

  • 测试
    1)写入数据,查看宿主机和pod中是否同步
    2)删除pod,查看数据是否还在

6.12 创建deployment绑定PVC

  • 创建文件pvc-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name:nginx
  namespace: default
spec:
  replicas: 2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      volumes:
        - name:pvc-storage    #volumes的名称
          persistentVolumeClaim:
            claimName:nfs-pvc-claim  #pvc的名称
      containers:
      - name:nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath:"/usr/share/nginx/html
          name: task-pv-storage
               
  • 常用命令
    kubectl get po
    kubectl exec -it nginx-xxxxx-xx – bash 进入pod内

6.13 pvc创建和报错分析

  • PVC一直pending
    1)PVC的空间大小大于PV的大小
    2)PVC的storageClassName没有与PV一致
    3)PVC的accessModes与PV不一致

  • 挂载PVC的pod一直处于pending
    1)PVC没有创建成功
    2)PVC和pod不在同一个Namespace

七、Job篇

7.1 Job

  • 常用命令
    kubectl create -f job.yaml
    kubectl delete -f job.yaml
    kubectl get pod
    kubectl get job
    kubectl logs -f echo-xxxx 查看执行日志

创建job.yaml

apiVersion: batch/v1
kind: Job
metadata:
  labels:
    job-name: echo
  name: echo
  namespace: default
spec:
  backoffLimit: 4
  completions: 1
  parallelism: 1
  template:
    spec:
      containers:
      - command:
        - echo
        - Hello,job
        image: registry.cn-beijing.aliyuncs.com/dotbalo/busybox
        imagePullPolicy: Always
        name: echo

备注:
backoofLimit: 如果任务失败,多少次不再执行
completions: 多少个pod执行成功,认为任务是成功的
parallelism: 并行执行任务的数量(如果大于未完成的数,会多次创建)
ttlSecondsAfterFinishe:job结束后自动清理,0表示结束后立即删除,不设置则不会清除

7.2 CronJob

CronJob用于以时间为基准周期性地执行任务,这些自动化任务和运行在Linux或UNIX系统上的CronJob一样。CronJob对于创建定期和重复任务非常有用,例如执行备份任务、周期性调度程序接口、发送电子邮件等。

对于Kubernetes 1.8以前的版本,需要添加–runtime-config=batch/v2alpha1=true参数至APIServer中,然后重启APIServer和Controller Manager用于启用API,对于1.8以后的版本无须修改任何参数,可以直接使用,本节的示例基于1.8以上的版本。

  • 创建CronJob有两种方式,一种是直接使用kubectl创建,一种是使用yaml文件创建。

  • 使用kubectl创建CronJob的命令如下:

kubectl run hello --schedule="*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster"

对应的yaml文件如下:

apiVersion: batch/v1beta1  #1.21版本以上  改为batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
  • 创建一个每分钟执行一次、打印当前时间和Hello from the Kubernetes cluster的计划任务。
    查看创建的CronJob:
kubectl get cj
NAME    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
hello   */1 * * * *   False     0        <none>          5s
  • 等待1分钟可以查看执行的任务(Jobs):
$ kubectl get jobs
NAME               COMPLETIONS   DURATION   AGE
hello-1558779360   1/1           23s        32s
  • CronJob每次调用任务的时候会创建一个Pod执行命令,执行完任务后,Pod状态就会变成Completed,如下所示:
$ kubectl get po 
NAME                          READY   STATUS      RESTARTS   AGE
hello-1558779360-jcp4r        0/1     Completed   0          37s
  • 可以通过logs查看Pod的执行日志:
$ kubectl logs -f hello-1558779360-jcp4r 
Sat May 25 10:16:23 UTC 2019
Hello from the Kubernetes cluster
  • 如果要删除CronJob,直接使用delete即可:
kubectl delete cronjob hello
  • 定义一个CronJob的yaml文件如下:
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  labels:
    run: hello
  name: hello
  namespace: default
spec:
  concurrencyPolicy: Allow
  failedJobsHistoryLimit: 1
  jobTemplate:
    metadata:
    spec:
      template:
        metadata:
          labels:
            run: hello
        spec:
          containers:
          - args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
            image: registry.cn-beijing.aliyuncs.com/dotbalo/busybox
            imagePullPolicy: Always
            name: hello
            resources: {}
          restartPolicy: OnFailure
          securityContext: {}
  schedule: '*/1 * * * *'
  successfulJobsHistoryLimit: 3
  suspend: false
  • 参数说明:

apiVersion: batch/v1beta1 #1.21+ batch/v1
schedule:调度周期,和Linux一致,分别是分时日月周。
restartPolicy:重启策略,和Pod一致。
concurrencyPolicy:并发调度策略。可选参数如下:
– Allow:允许同时运行多个任务。
– Forbid:不允许并发运行,如果之前的任务尚未完成,新的任务不会被创建。
– Replace:如果之前的任务尚未完成,新的任务会替换的之前的任务。
suspend:如果设置为true,则暂停后续的任务,默认为false。
successfulJobsHistoryLimit:保留多少已完成的任务,按需配置。
failedJobsHistoryLimit:保留多少失败的任务。

相对于Linux上的计划任务,Kubernetes的CronJob更具有可配置性,并且对于执行计划任务的环境只需启动相对应的镜像即可。比如,如果需要Go或者PHP环境执行任务,就只需要更改任务的镜像为Go或者PHP即可,而对于Linux上的计划任务,则需要安装相对应的执行环境。此外,Kubernetes的CronJob是创建Pod来执行,更加清晰明了,查看日志也比较方便。可见,Kubernetes的CronJob更加方便和简单。

7.3 初始化容器

7.3.1 初始化容器介绍
在这里插入图片描述

  • 初始化容器和poststart区别,PostStart:依赖主应用的环境,而且并不一定先于Command运行,InitContainer:不依赖主应用的环境,可以有更高的权限和更多的工具,一定会在主应用启动之前完成

  • 另外,初始化容器和普通容器区别,Init 容器与普通的容器非常像,除了如下几点:
    它们总是运行到完成;上一个运行完成才会运行下一个;
    如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止,但是Pod 对应的 restartPolicy 值为 Never,Kubernetes 不会重新启动 Pod。
    Init 容器不支持 lifecycle、livenessProbe、readinessProbe 和 startupProbe

7.3.2 创建初始化容器

创建init.yaml文件,用来测试初始化容器的整个工作过程,使用deployment部署pod,定义三个pod副本,定义两个初始化容器init-touch和echo,并且为了演示效果,将echo加入for循环和sleep100秒,

kubectl create -f init.yaml
kubectl get pod -n kube-public
kubectl describe pod test-init-xxxxx -c echo -n kube-public 查看指定容器目前执行的命令
kubectl logs -f init.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: test-init
  name: test-init
  namespace: kube-public
spec:
  replicas: 3
  selector:
    matchLabels:
      app: test-init
  template:
    metadata:
      labels:
        app: test-init
    spec:
      volumes:
      - name: data
        emptyDir: {}
      initContainers:
      - command:
        - sh
        - -c
        - touch /mnt/test-init.txt
        image: nginx
        imagePullPolicy: IfNotPresent
        name: init-touch
        volumeMounts:
        - name: data
          mountPath: /mnt
      - command:
        - sh
        - -c
        - for i in `seq 1 100`; do echo $i; sleep 1; done
        image: nginx
        imagePullPolicy: IfNotPresent
        name: echo
      containers:
      - image: nginx
        imagePullPolicy: IfNotPresent
        name: test-init
        volumeMounts:
        - name: data
          mountPath: /mnt

7.4 临时容器

什么是临时容器?
临时容器:一种特殊的容器,该容器在现有 Pod 中临时运行,以便完成用户发起的操作,例如故障排查。 你会使用临时容器来检查服务,而不是用它来构建应用程序。
临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启, 因此不适用于构建应用程序。 临时容器使用与常规容器相同的 ContainerSpec 节来描述,但许多字段是不兼容和不允许的。

Pod 是 Kubernetes 应用程序的基本构建块。 由于 Pod 是一次性且可替换的,因此一旦 Pod 创建,就无法将容器加入到 Pod 中。 取而代之的是,通常使用 Deployment 以受控的方式来删除并替换 Pod。

有时有必要检查现有 Pod 的状态。例如,对于难以复现的故障进行排查。 在这些场景中,可以在现有 Pod 中运行临时容器来检查其状态并运行任意命令。

临时容器没有端口配置,因此像 ports,livenessProbe,readinessProbe 这样的字段是不允许的。
Pod 资源分配是不可变的,因此 resources 配置是不允许的。
有关允许字段的完整列表,请参见 EphemeralContainer 参考文档。
临时容器是使用 API 中的一种特殊的 ephemeralcontainers 处理器进行创建的, 而不是直接添加到 pod.spec 段,因此无法使用 kubectl edit 来添加一个临时容器。

与常规容器一样,将临时容器添加到 Pod 后,将不能更改或删除临时容器。

临时容器的用途
当由于容器崩溃或容器镜像不包含调试工具而导致 kubectl exec 无用时, 临时容器对于交互式故障排查很有用。

尤其是,Distroless 镜像 允许用户部署最小的容器镜像,从而减少攻击面并减少故障和漏洞的暴露。 由于 distroless 镜像不包含 Shell 或任何的调试工具,因此很难单独使用 kubectl exec 命令进行故障排查。

使用临时容器时,启用 进程名字空间共享很有帮助,可以查看其他容器中的进程。

八、污点和容忍篇(Taint和Toleration)

设计理念:Taint在一类服务器上打上污点,让不能容忍这个污点的Pod不能部署在打了污点的服务器上。Toleration是让Pod容忍节点上配置的污点,可以让一些需要特殊配置的Pod能够调用到具有污点和特殊配置的节点上。
官方文档:https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/

污点:作用在节点上(相当于锁)
容忍:作用在pod上(相当于钥匙)

注意:若是想要pod落到指定的某一个node中,需要在pod的yaml中配置nodeSelector,并且pod必须与nodes的label一致,然后还需要pod配置可以容忍node的污点。 如果单纯的只配置了容忍,未配置label,那么pod的容忍未必会起到作用。

8.1 taint污点

创建一个污点(一个节点可以有多个污点):
kubectl taint nodes NODE_NAME TAINT_KEY=TAINT_VALUE:EFFECT

	kubectl taint nodes k8s-node01 ssd=true:PreferNoSchedule
	kubectl taint nodes k8s-node01 ssd=true:NoExecute(此时会驱逐没有容忍该污点的Pod)
	kubectl taint nodes k8s-node01 ssd=true:NoSchedule
	kubectl label node k8s-node01 ssd=true

NoSchedule:禁止调度到该节点,已经在该节点上的Pod不受影响
NoExecute:禁止调度到该节点,如果不符合这个污点,会立马被驱逐(或在一段时间后,配置tolerationSeconds: 6000)
PreferNoSchedule:尽量避免将Pod调度到指定的节点上,如果没有更合适的节点,可以部署到该节点

  • 说明,配置6000秒后驱使pod
tolerations:
- key: "taintKey"
  operator: "Exists"
  effect: "NoExecute"   
  tolerationSeconds: 6000

8.2 Toleration容忍

创建一个pod的 toleration.yaml,Toleration是配置在pod中的,与taint不一样,taint是定义在node中的

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    ssd: "true"
  tolerations:
  - key: "ssd"
    operator: "Exists"

另外,toleration有四种模式

  • 第一种:完全匹配
tolerations:
- key: "taintKey"
  operator: "Equal"
  value: "taintValue"
  effect: "NoSchedule"
  • 第二种:不完全匹配(这种模式下,只配置key,不配置value)
tolerations:
- key: "taintKey"
  operator: "Exists"
  effect: "NoSchedule"
  • 第三种:大范围匹配(这种模式下,不推荐key为内置Taint)
tolerations:
- key: "taintKey"
  operator: "Exists"
  • 第四种:匹配所有(不推荐)
tolerations:
- operator: "Exists"

8.3 常用命令

1)创建一个污点(一个节点可以有多个污点):
#kubectl taint nodes NODE_NAME TAINT_KEY=TAINT_VALUE:EFFECT
比如:
kubectl taint nodes k8s-node01 ssd=true:PreferNoSchedule
2)查看一个节点的污点:
kubectl get node k8s-node01 -o go-template --template {{.spec.taints}}
kubectl describe node k8s-node01 | grep Taints -A 10
3)删除污点(和label类似):
基于Key删除: kubectl taint nodes k8s-node01 ssd-
基于Key+Effect删除: kubectl taint nodes k8s-node01 ssd:PreferNoSchedule-
4)修改污点(Key和Effect相同):
kubectl taint nodes k8s-node01 ssd=true:PreferNoSchedule --overwrite

8.4 内置污点

内置污点为pod创建成功后,自动生成的tolerations,是为了在机器宕机或者网络不可达后,节点自动采取迁移或者其他动作来规避故障
使用以下命令可以查看:

kubectl get pod nginx -o yaml

node.kubernetes.io/not-ready:节点未准备好,相当于节点状态Ready的值为False。
node.kubernetes.io/unreachable:Node Controller访问不到节点,相当于节点状态Ready的值为Unknown。node.kubernetes.io/out-of-disk:节点磁盘耗尽。
node.kubernetes.io/memory-pressure:节点存在内存压力。
node.kubernetes.io/disk-pressure:节点存在磁盘压力。
node.kubernetes.io/network-unavailable:节点网络不可达。
node.kubernetes.io/unschedulable:节点不可调度。
node.cloudprovider.kubernetes.io/uninitialized:如果Kubelet启动时指定了一个外部的cloudprovider,它将给当前节点添加一个Taint将其标记为不可用。在cloud-controller-manager的一个controller初始化这个节点后,Kubelet将删除这个Taint。

九、亲和力篇(Affinity)

9.1 使用背景

  • 部署pod时,优先选择对应的标签,如果不存在,则部署到其他节点
  • 部署pod时,部署到标签一和标签二的节点上,但需要优先部署到标签一的节点上
  • 同一个pod多个副本,尽量或者必须部署到同一个节点上
  • 相互有关联的pod,必须部署到同一个节点上,降低网络延迟
  • 同一个项目的应用,尽量部署到不同的节点上,保证业务的高可用性

9.2 亲和力分类

NodeAffinity:节点亲和力 / 反亲和力
1)分为硬亲和力-required(必须满足)和软亲和力-preferred(尽量满足)
2)作用:

PodAffinity:Pod亲和力
1)分为硬亲和力-required(必须满足)和软亲和力-preferred(尽量满足)
2)作用:

PodAntiAffinity:Pod反亲和力
1)分为硬亲和力-required(必须满足)和软亲和力-preferred(尽量满足)
2)作用:为了规避所有的pod副本都部署到同一个节点,尽可能按照不同node均衡打散,或者按照机房和可用区打散

9.3 节点亲和力配置

创建nodeAffinity.yaml文件

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: ipaddress
            operator: In
            values:
            - 172-16-27-35
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: nginx

注意:

nodeSelectorTerms 下的配置其一满足就可以 
matchExpressions下的配置项都要符合才可以 
requiredDuringSchedulingIgnoredDuringExecution:硬亲和力配置
nodeSelectorTerms:节点选择器配置,可以配置多个matchExpressions(满足其一),每个matchExpressions下可以配置多个key、value类型的选择器(都需要满足),其中values可以配置多个(满足其一)

preferredDuringSchedulingIgnoredDuringExecution:软亲和力配置
weight:	软亲和力的权重,权重越高优先级越大,范围1-100
preference:软亲和力配置项,和weight同级,可以配置多个,matchExpressions和硬亲和力一致
operator:标签匹配的方式 In:相当于key = value的形式 NotIn:相当于key != value的形式
Exists:节点存在label的key为指定的值即可,不能配置values字段
DoesNotExist:节点不存在label的key为指定的值即可,不能配置values字段 
Gt:大于value指定的值
Lt:小于value指定的值
说明:可同时配置硬亲和力和软亲和力

9.4 Pod亲和力和反亲和力配置

创建pod-affinity.yaml

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: failure-domain.beta.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          namespaces:
          - default
          topologyKey: failure-domain.beta.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: nginx

注意:

labelSelector:Pod选择器配置,可以配置多个,匹配的是pod的标签,非node的标签 
matchExpressions:和节点亲和力配置一致,pod中只能配置一个
operator:配置和节点亲和力一致,但是没有Gt和Lt   
topologyKey:匹配的拓扑域的key,也就是节点上label的key,key和value相同的为同一个域,可以用于标注不同的机房和地区
Namespaces: 和哪个命名空间的Pod进行匹配,为空为当前命名空间
说明:可同时配置node亲和pod亲和力以及pod反亲和力

9.5 案例实践

  • 案例一

同一个业务的pod副本,部署到不同的node中
创建一个deployment,vim pod-diff-nodes.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: must-be-diff-nodes
  name: must-be-diff-nodes
  namespace: kube-public
spec:
  replicas: 3
  selector:
    matchLabels:
      app: must-be-diff-nodes
  template:
    metadata:
      labels:
        app: must-be-diff-nodes
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - must-be-diff-nodes
            topologyKey: kubernetes.io/hostname
      containers:
      - image: nginx
        imagePullPolicy: IfNotPresent
        name: must-be-diff-nodes
  • 案例二

将pod调度到符合标签ssd=true的node节点上,并且不调度到gpu=true的node节点上,如果两者都不满足,则调度到type=physical节点上。preferredDuringSchedulingIgnoredDuringExecution代表尽可能,不强制

1、首先,对master和node节点打上对应的标签

#kubectl label node master01 master02 master03 ssd=true
#kubectl label node master01 master02 master03 gpu=true
#kubectl label node node01 ssd=true
#kubectl label node node02 type=physical
#kubectl get nodes --show-labels |grep ssd  //检查配置

2、创建pod-affinity-ssd.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: prefer-ssd
  name: prefer-ssd
  namespace: kube-public
spec:
  replicas: 3
  selector:
    matchLabels:
      app: prefer-ssd
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: prefer-ssd
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - preference:
              matchExpressions:
              - key: ssd
                operator: In
                values:
                - "true"
              - key: gpu
                operator: NotIn
                values:
                - "true"
            weight: 100
          - preference:
              matchExpressions:
              - key: type
                operator: In
                values:
                - physical
            weight: 10
      containers:
      - env:
        - name: TZ
          value: Asia/Shanghai
        - name: LANG
          value: C.UTF-8
        image: nginx
        imagePullPolicy: IfNotPresent
        name: prefer-ssd


说明:node中有一个label满足条件,便可以调度上去

3、将node01的ssd=true标签删除,重新创建pod,观察pod会被调度到哪个节点中(正常应该会是node02)

9.6 拓扑域(TopologyKey)

  • 什么时拓扑域

pod亲和性调度需要各个相关的pod对象运行于"同一位置", 而反亲和性调度则要求他们不能运行于"同一位置",

这里指定“同一位置” 是通过 topologyKey 来定义的,topologyKey 对应的值是 node 上的一个标签名称,比如各别节点zone=A标签,各别节点有zone=B标签,pod affinity topologyKey定义为zone,那么调度pod的时候就会围绕着A拓扑,B拓扑来调度,而相同拓扑下的node就为“同一位置”。

可以理解成,它主要针对宿主机,相当于对宿主机进行区域的划分。用label进行判断,不同的key和不同的value是属于不同的拓扑域

实验目的,将5个节点分为三个拓扑域,分别是beijing、shanghai、hangzhou
master01、master02 为region=beijing
master03、node01 为region=shanghai
node02 为region=hangzhou
然后创建3个副本的pod,观察是否分别位于三个region上

1、首先为节点打标签

#kubectl label node master01 master02 region=beijing
#kubectl label node master03 node01 region=shanghai
#kubectl label node node03 region=hangzhou

2、创建pod ,vim diff-zone.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: must-be-diff-zone
  name: must-be-diff-zone
  namespace: kube-public
spec:
  replicas: 3
  selector:
    matchLabels:
      app: must-be-diff-zone
  template:
    metadata:
      labels:
        app: must-be-diff-zone
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - must-be-diff-zone
            topologyKey: region
      containers:
      - image: nginx
        imagePullPolicy: IfNotPresent
        name: must-be-diff-zone

3、上面yaml中,是通过region来定义区分不同的拓扑域

注意:如果副本数超过域的数量,就会一直pending,解决该问题需要按照条件调整域的逻辑定义

十、资源配额

十一、RBAC

https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/

11.1 使用 RBAC 鉴权

基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对 计算机或网络资源的访问的方法。

RBAC 鉴权机制使用 rbac.authorization.k8s.io API 组 来驱动鉴权决定,允许你通过 Kubernetes API 动态配置策略。

要启用 RBAC,在启动 API 服务器 时将 --authorization-mode 参数设置为一个逗号分隔的列表并确保其中包含 RBAC。

kube-apiserver --authorization-mode=Example,RBAC --<其他选项> --<其他选项>

11.2 API 对象

RBAC API 声明了四种 Kubernetes 对象:

Role
ClusterRole
RoleBinding
ClusterRoleBinding。

11.3 Role 和 ClusterRole

RBAC 的 Role 或 ClusterRole 中包含一组代表相关权限的规则。 这些权限是纯粹累加的(不存在拒绝某操作的规则)。

Role 总是用来在某个名字空间内设置访问权限;在你创建Role时,你必须指定该Role所属的名字空间。

与之相对,ClusterRole则是一个集群作用域的资源。这两种资源的名字不同(Role 和 ClusterRole)是因为 Kubernetes 对象要么是名字空间作用域的,要么是集群作用域的, 不可两者兼具。

ClusterRole的用法

  • 定义对某名字空间域对象的访问权限,并将在各个名字空间内完成授权;
  • 为名字空间作用域的对象设置访问权限,并跨所有名字空间执行授权;
  • 为集群作用域的资源定义访问权限。

如果你希望在名字空间内定义角色,应该使用 Role; 如果你希望定义集群范围的角色,应该使用 ClusterRole

Role 示例
下面是一个位于 “default” 名字空间的 Role 的示例,可用来授予对 pods 的读访问权限:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" 标明 core API 组
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

ClusterRole 示例
ClusterRole 可以和 Role 相同完成授权。 因为 ClusterRole 属于集群范围,所以它也可以为以下资源授予访问权限:

  • 集群范围资源(比如 节点(Node))
  • 非资源端点(比如 /healthz)
  • 跨名字空间访问的名字空间作用域的资源(如 Pods)

比如,你可以使用 ClusterRole 来允许某特定用户执行 kubectl get pods --all-namespaces
下面是一个 ClusterRole 的示例,可用来为任一特定名字空间中的 Secret 授予读访问权限, 或者跨名字空间的访问权限(取决于该角色是如何绑定的):

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" 被忽略,因为 ClusterRoles 不受名字空间限制
  name: secret-reader
rules:
- apiGroups: [""]
  # 在 HTTP 层面,用来访问 Secret 对象的资源的名称为 "secrets"
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

11.4 RoleBinding 和 ClusterRoleBinding

角色绑定(Role Binding)是将角色中定义的权限赋予一个或者一组用户。 它包含若干 主体(用户、组或服务账户)的列表和对这些主体所获得的角色的引用。 RoleBinding 在指定的名字空间中执行授权,而 ClusterRoleBinding 在集群范围执行授权。

一个 RoleBinding 可以引用同一的名字空间中的任何 Role。 或者,一个 RoleBinding 可以引用某 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 所在的名字空间。 如果你希望将某 ClusterRole 绑定到集群中所有名字空间,你要使用 ClusterRoleBinding。

RoleBinding 或 ClusterRoleBinding 对象的名称必须是合法的 路径区段名称。

RoleBinding 示例
下面的例子中的 RoleBinding 将 “pod-reader” Role 授予在 “default” 名字空间中的用户 “jane”。 这样,用户 “jane” 就具有了读取 “default” 名字空间中 pods 的权限。

apiVersion: rbac.authorization.k8s.io/v1
#此角色绑定允许 "jane" 读取 "default" 名字空间中的 Pods
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
#你可以指定不止一个“subject(主体)”
- kind: User
  name: jane # "name" 是区分大小写的
  apiGroup: rbac.authorization.k8s.io
roleRef:
  # "roleRef" 指定与某 Role 或 ClusterRole 的绑定关系
  kind: Role # 此字段必须是 Role 或 ClusterRole
  name: pod-reader     # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配
  apiGroup: rbac.authorization.k8s.io

RoleBinding 也可以引用 ClusterRole,以将对应 ClusterRole 中定义的访问权限授予 RoleBinding 所在名字空间的资源。这种引用使得你可以跨整个集群定义一组通用的角色, 之后在多个名字空间中复用。

例如,尽管下面的 RoleBinding 引用的是一个 ClusterRole,“dave”(这里的主体, 区分大小写)只能访问 “development” 名字空间中的 Secrets 对象,因为 RoleBinding 所在的名字空间(由其 metadata 决定)是 “development”。

apiVersion: rbac.authorization.k8s.io/v1
#此角色绑定使得用户 "dave" 能够读取 "development" 名字空间中的 Secrets
#你需要一个名为 "secret-reader" 的 ClusterRole
kind: RoleBinding
metadata:
  name: read-secrets
  # RoleBinding 的名字空间决定了访问权限的授予范围。
  # 这里隐含授权仅在 "development" 名字空间内的访问权限。
  namespace: development
subjects:
- kind: User
  name: dave # 'name' 是区分大小写的
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding 示例
要跨整个集群完成访问权限的授予,你可以使用一个 ClusterRoleBinding。 下面的 ClusterRoleBinding 允许 “manager” 组内的所有用户访问任何名字空间中的 Secrets。

apiVersion: rbac.authorization.k8s.io/v1
#此集群角色绑定允许 “manager” 组中的任何人访问任何名字空间中的 secrets
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager # 'name' 是区分大小写的
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

创建了绑定之后,你不能再修改绑定对象所引用的 Role 或 ClusterRole。 试图改变绑定对象的 roleRef 将导致合法性检查错误。 如果你想要改变现有绑定对象中 roleRef 字段的内容,必须删除重新创建绑定对象。

这种限制有两个主要原因:
针对不同角色的绑定是完全不一样的绑定。要求通过删除/重建绑定来更改 roleRef, 这样可以确保要赋予绑定的所有主体会被授予新的角色(而不是在允许或者不小心修改 了 roleRef 的情况下导致所有现有主体未经验证即被授予新角色对应的权限)。
将 roleRef 设置为不可以改变,这使得可以为用户授予对现有绑定对象的 update 权限, 这样可以让他们管理主体列表,同时不能更改被授予这些主体的角色。

11.5 对资源的引用

在 Kubernetes API 中,大多数资源都是使用对象名称的字符串表示来呈现与访问的。 例如,对于 Pod 应使用 “pods”。 RBAC 使用对应 API 端点的 URL 中呈现的名字来引用资源。 有一些 Kubernetes API 涉及 子资源(subresource),例如 Pod 的日志。 对 Pod 日志的请求看起来像这样:

GET /api/v1/namespaces/{namespace}/pods/{name}/log

在这里,pods 对应名字空间作用域的 Pod 资源,而 log 是 pods 的子资源。 在 RBAC 角色表达子资源时,使用斜线(/)来分隔资源和子资源。 要允许某主体读取 pods 同时访问这些 Pod 的 log 子资源,你可以这么写:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

对于某些请求,也可以通过 resourceNames 列表按名称引用资源。 在指定时,可以将请求限定为资源的单个实例。 下面的例子中限制可以 “get” 和 “update” 一个名为 my-configmap 的 ConfigMap:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  # 在 HTTP 层面,用来访问 ConfigMap 的资源的名称为 "configmaps"
  resources: ["configmaps"]   
  resourceNames: ["my-configmap"]   #要指定名称,不指定的话对所有的cm都又权限
  verbs: ["update", "get"]

说明:
你不能使用资源名字来限制 create 或者 deletecollection 请求。 对于 create 请求而言,这是因为在鉴权时可能还不知道新对象的名字。 如果你使用 resourceName 来限制 list 或者 watch 请求, 客户端必须在它们的 list 或者 watch 请求里包含一个与指定的 resourceName 匹配的 metadata.name 字段选择器。 例如,kubectl get configmaps --field-selector=metadata.name=my-configmap

11.6 Role案例

以下示例均为从 Role 或 ClusterRole 对象中截取出来,我们仅展示其 rules 部分。

允许读取在核心 API 组下的 “Pods”:

rules:
- apiGroups: [""]
  # 在 HTTP 层面,用来访问 Pod 的资源的名称为 "pods"
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

允许读/写在 “extensions” 和 “apps” API 组中的 Deployment(在 HTTP 层面,对应 URL 中资源部分为 “deployments”):

rules:
- apiGroups: ["extensions", "apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允许读取核心 API 组中的 “pods” 和读/写 “batch” 或 “extensions” API 组中的 “jobs”:

rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["batch", "extensions"]
  resources: ["jobs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

允许读取名称为 “my-config” 的 ConfigMap(需要通过 RoleBinding 绑定以 限制为某名字空间中特定的 ConfigMap):

rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["my-config"]
  verbs: ["get"]

允许读取在核心组中的 “nodes” 资源(因为 Node 是集群作用域的,所以需要 ClusterRole 绑定到 ClusterRoleBinding 才生效):

rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]

允许针对非资源端点 /healthz 和其子路径上发起 GET 和 POST 请求 (必须在 ClusterRole 绑定 ClusterRoleBinding 才生效):

rules:
  - nonResourceURLs: ["/healthz", "/healthz/*"] # nonResourceURL 中的 '*' 是一个全局通配符
    verbs: ["get", "post"]

11.7 RoleBinding 示例

下面示例是 RoleBinding 中的片段,仅展示其 subjects 的部分。

对于名称为 [email protected] 的用户:

subjects:
- kind: User
  name: "[email protected]"
  apiGroup: rbac.authorization.k8s.io

对于名称为 frontend-admins 的用户组:

subjects:
- kind: Group
  name: "frontend-admins"
  apiGroup: rbac.authorization.k8s.io

对于 kube-system 名字空间中的默认服务账户:

subjects:
- kind: ServiceAccount
  name: default
  namespace: kube-system

对于任何名称空间中的 “qa” 组中所有的服务账户:

subjects:
- kind: Group
  name: system:serviceaccounts:qa
  apiGroup: rbac.authorization.k8s.io

对于 “development” 名称空间中 “dev” 组中的所有服务帐户:

subjects:
- kind: Group
  name: system:serviceaccounts:dev
  apiGroup: rbac.authorization.k8s.io
  namespace: development

对于在任何名字空间中的服务账户:

subjects:
- kind: Group
  name: system:serviceaccounts
  apiGroup: rbac.authorization.k8s.io

对于所有已经过认证的用户:

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io

对于所有未通过认证的用户:

subjects:
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

对于所有用户:

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

二十、账号相关

kubectl get sa //serviceaccount
创建角色-绑定角色-授权-创建账号-测试
https://blog.csdn.net/cr7258/article/details/114274628

你可能感兴趣的:(kubernetes,nginx,kubernetes,docker)