一、k8s概念和架构

1、k8s概述

  • k8s是谷歌在2014年开源的容器化集群管理系统
  • 使用k8s进行容器化应用部署
  • 使用k8s利于应用扩展
  • k8s目标实施让容器化应用程序更加简洁高效

2、特性

(1)自动装箱
(2)自我修复(自愈能力)
(3)水平扩展
(3)服务发现
(4)滚动更新
(5)版本回退
(6)密钥和配置管理
(7)存储编排
(8)批处理
在这里插入图片描述

3、k8s 集群架构节点角色功能

1、Master Node

k8s 集群控制节点,对集群进行调度管理,接受集群外用户去集群操作请求; Master Node 由
API Server:集群统一入口,以restfull方式交给etcd存储
Scheduler:节点调度,选择node节点应用部署
ClusterState Store(ETCD 数据库): 存储系统,用于保存集群数据
Controller MangerServer :处理集群中常规后台任务,一个资源对应一个控制器

2、Worker Node

集群工作节点,运行用户业务应用容器; Worker Node 包含
kubelet:master派到node节点的代表,管理本机容器如生命周期,容器的创建,容器的各种操作。
kube proxy :提供网络代理,可以实现负载均衡等
和 ContainerRuntime;
在这里插入图片描述

4、概念

1、pod

  • 部署的最小单元
  • 一组容器的集合
  • 共享网络
  • 生命周期是短暂的

2、controller

  • 确保pod中预期的副本数量
  • 无状态应用部署
  • 有状态应用部署
  • 确保所有的node都运行同一个pod
  • 一次性任务和定时任务
ReplicaSet:确保预期的Pod副本数量

Deployment:无状态应用(例如:web、nignx、apache、tomcat)

StatefulSet:有状态应用部署(例如:mysql)

有状态:该应用独一无二,无法重新创建进行完美替代,例如mysql、Oracle数据库
DaemonSet:确保所有的Node运行同一个Pod(把所有的Node设置为同一个命名空间)

Job:一次性任务(类似linux:at)

Cronjob:定时任务(类似linux:crontab)

3、service

  • 定义一组pod访问规则
    在这里插入图片描述
    在这里插入图片描述

二、从零搭建k8s集群

在这里插入图片描述

1、基于客户端工具kubeadm

一、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 get po -owide 
kubectl label node01 node02 ds=ture  //给node打个标签

四、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 的部分。

对于名称为 alice@example.com 的用户:

subjects:
- kind: User
  name: "alice@example.com"
  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

1、使用的命令

  • kubectl get nodes 查看所有的节点
  • kubectl get pod -n kube-system 查看是否runing状态
  • kubectl create deployment nginx --image=nginx 创建一个pod
  • kubectl get pod 查看是否runing状态
  • kubectl expose deployment nginx --port=80 --type=NodePort 暴露端口
  • kubectl get pod,svc 查看pod
  • kubectl get cs 检查状态
  • kubectl apply -f a.yaml 部署yaml文件
  • kubectl get csr 查看申请
  • kubectl logs --tail=200 --all-containers=true -f -n sip -lapp=contractmg
  • kubectl get pods -o wide 可以看到pod的ip等完整信息
kubectl get deploy 查看部署的资源
kubect get nodes  查看所有的节点
kubectl get pod -n kube-system 查看是否runing状态
kubectl get pods -o wide
kubectl create deployment nginx --image=nginx     创建一个pod
kubectl  get pod 查看是否runing状态
kubectl expose deployment nginx --port=80 --type=NodePort 暴露端口
kubectl expose deployment nginx --port=80 --target-port=80 --type=NodePort 暴露端口
kubectl expose deployment web --port=80 --type=NodePort --traget-port=80 --name=web1 -o yaml  > web1.yaml

kubectl get pod,svc 查看pod
kubectl get cs 检查状态
kubectl apply -f  a.yaml     部署yaml文件
kubectl get csr  查看申请
kubectl logs --tail=200 --all-containers=true -f -n sip  -lapp=contractmg  查看日志 
kubectl logs 

```bash
kubectl get deploy 查看部署的资源
-- 生成yaml文件
kubectl create demployment web --image=nginx  -o yaml --dry-run > my1.yaml
kubectl get deploy  nginx -o=yaml --export > my2.yaml

-- 标签属于pod属性,污点taint属于node节点属性

kubectl label node node1 env_role=prod 添加标签  
kubectl label node node1 env_role- 删除标签

kubectl taint node [node] key=value:污点三个值  添加污点
kubectl taint node k8snode1 key:NoSchedule-   删除污点

-- pod升级
kubectl set image deployment web  nginx=nginx:1.15 
-- 查看升级状态
kubectl rollout status deployment web
-- 查看历史版本
kubectl rollout history deployment web
-- 回滚
kubectl rollout undo deployment web

-- 回滚指定版本
kubectl rollout undo deployment web --to-revision=2
-- 弹性伸缩扩容
kubectl scale deployment web --replicas=5


--删除
kubectl delete statefullset --all  删除controller
kubectl delete svc nginx 删除service
kubectl delete pod --all
kubectl delete node --all
kubectl delete -f job.yaml
kubectl delete -f cronJob.yaml 

-- 进入具体的pod
kubectl exec -it aaa  bash 

一次任务
kubectl create -f job.yaml
查看
kubectl get pods
kubectl get jobs 可以查看

echo -n 'admin'| base64

kubectl get ns 获取命名空间
kubectl create ns roletest  创建一个命名空间

kubectl run  nginx --image=nginx -n roletest 运行一个pod,
kubect get pods -n roletest

kubectl get role -n roletest  查看创建的角色

kubectl get role.rolebinding -n roletest 查看角色绑定
生成证书
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

生成证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes lucy-csr.json | cfssljson -bare lucy


helm repo list 
helm repo add stable http://mirror.azure.cn/kubernetes/charts/
helm repo remove stable
helm repo update

helm search repo weave
helm install ui stable/weave-scope
helm list
helm status ui

kubectl edit  svc ui-weave-scope

kubectl create deployment nginxchart --image=nginx -o yaml --dry-run 

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2、kubeadm部署

在这里插入图片描述

1、前置知识点

目前生产部署 Kubernetes 集群主要有两种方式:

  • (1)kubeadm Kubeadm 是一个 K8s 部署工具,提供 kubeadm init 和 kubeadm join,用于快速部 署 Kubernetes 集群。 官方地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/
  • (2)二进制包 从 github 下载发行版的二进制包,手动部署每个组件,组成 Kubernetes 集群。 Kubeadm 降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。如果想更容易可 控,推荐使用二进制包部署 Kubernetes 集群,虽然手动部署麻烦点,期间可以学习很 多工作原理,也利于后期维护。
2、kubeadm 部署方式介绍

kubeadm 是官方社区推出的一个用于快速部署 kubernetes 集群的工具,这个工具能通 过两条指令完成一个 kubernetes 集群的部署: 第一、创建一个 Master 节点 kubeadm init 第二, 将 Node 节点加入到当前集群中 $ kubeadm join <Master 节点的 IP 和端口 >

3、安装要求

在开始之前,部署 Kubernetes 集群机器需要满足以下几个条件:

  • 一台或多台机器,操作系统 CentOS7.x-86_x64
  • 硬件配置:2GB 或更多 RAM,2 个 CPU 或更多 CPU,硬盘 30GB 或更多
  • 集群中所有机器之间网络互通 - 可以访问外网,需要拉取镜像
  • 禁止 swap 分区
4、最终目标
  • (1) 在所有节点上安装 Docker 和 kubeadm
  • (2)部署 Kubernetes Master
  • (3)部署容器网络插件
  • (4)部署 Kubernetes Node,将节点加入 Kubernetes 集群中
  • (5)部署 Dashboard Web 页面,可视化查看 Kubernetes 资源
5、准备环境

在这里插入图片描述
角色 IP
k8smaster 192.168.163.133
k8snode1 192.168.163.134
k8snode2 192.168.163.135

6、系统初始化
6.1 关闭防火墙:
$ systemctl stop firewalld 
$ systemctl disable firewalld
6.2 关闭 selinux:
$ sed -i 's/enforcing/disabled/' /etc/selinux/config # 永久 
$ setenforce 0 # 临时
6.3 关闭 swap:
$ swapoff -a # 临时 
$ vim /etc/fstab # 永久
6.4 主机名:
$ hostnamectl set-hostname <hostname>
  • hostnamectl set-hostname k8smaster
  • hostnamectl set-hostname k8snode1
  • hostnamectl set-hostname k8snode2
6.5 在 master 添加 hosts:
$ cat >> /etc/hosts << EOF 
192.168.163.133 k8smaster 
192.168.163.134 k8snode1 
192.168.163.135 k8snode2 
EOF
6.6 将桥接的 IPv4 流量传递到 iptables 的链
$ cat > /etc/sysctl.d/k8s.conf << EOF 
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1 
EOF 

$ sysctl --system # 生效
6.7 时间同步
$ yum install ntpdate -y 
$ ntpdate time.windows.com
7、所有节点安装 Docker/kubeadm/kubelet

Kubernetes 默认 CRI(容器运行时)为 Docker,因此先安装 Docker。

(1)安装 Docker
$ wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
 
$ yum -y install docker-ce-18.06.1.ce-3.el7 

$ systemctl enable docker && systemctl start docker

$ docker --version
(2)添加阿里云 YUM 软件源

设置仓库地址

# cat > /etc/docker/daemon.json << EOF 
{ "registry-mirrors": ["https://xxx.mirror.aliyuncs.com"] }
EOF

添加 yum 源

$ cat > /etc/yum.repos.d/kubernetes.repo << EOF [kubernetes] 
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 
enabled=1 
gpgcheck=0 
repo_gpgcheck=0 
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg 
EOF
(3)安装 kubeadm,kubelet 和 kubectl

由于版本更新频繁,这里指定版本号部署:

$ yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0
$ systemctl enable kubelet
8、部署 Kubernetes Master
(1)在 192.168.163.133(Master)执行

提供了一种在拉去镜像时指定镜像仓库的方法

kubeadm init --apiserver-advertise-address=192.168.163.133 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.22.3 --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16

由于默认拉取镜像地址 k8s.gcr.io 国内无法访问,这里指定阿里云镜像仓库地址。

(2)使用 kubectl 工具:

如果kubeadm reset后需要删除这个目录重新弄

mkdir -p $HOME/.kube 
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config 

$ kubectl get nodes
9、安装 Pod 网络插件(CNI)
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

确保能够访问到 quay.io 这个 registery。如果 Pod 镜像下载失败,可以改这个镜像地址

10、加入 Kubernetes Node

在 192.168.163.134/135(Node)执行
向集群添加新节点,执行在 kubeadm init 输出的 kubeadm join 命令:

$ kubeadm join 192.168.31.61:6443 --token esce21.q6hetwm8si29qxwn \ 
--discovery-token-ca-cert-hash sha256:00603a05805807501d7181c3d60b478788408cfe6cedefedb1f97569708be9c5
11、测试 kubernetes 集群

在 Kubernetes 集群中创建一个 pod,验证是否正常运行:

$ kubectl create deployment nginx --image=nginx 
$ kubectl expose deployment nginx --port=80 --type=NodePort 
$ kubectl get pod,svc

访问地址:http://NodeIP:Port。比如这里访问的http://192.168.163.134:30521

2、基于二进制包安装k8s

三、k8s核心概念

1、kubernetes 集群命令行工具 kubectl

1、kubectl 概述

kubectl 是 Kubernetes 集群的命令行工具,通过 kubectl 能够对集群本身进行管理,并能 够在集群上进行容器化应用的安装部署。

2、kubectl 命令的语法

在这里插入图片描述

  • comand:指定要对资源执行的操作,例如 create、get、describe 和 delete
  • TYPE:指定资源类型,资源类型是大小写敏感的,开发者能够以单数、复数和缩略的 形式。例如:
    在这里插入图片描述
  • NAME:指定资源的名称,名称也大小写敏感的。如果省略名称,则会显示所有的资源, 例如:
    在这里插入图片描述
  • flags:指定可选的参数。例如,可用-s 或者–server 参数指定 Kubernetes API server 的地址和端口。

3、kubectl help 获取更多信息

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、kubectl 子命令使用分类

(1)基础命令

在这里插入图片描述

(2)部署和集群管理命令

在这里插入图片描述

(3)故障和调试命令

在这里插图片描述

(4)其他命令

在这里插入图片描述

2、kubernetes 集群 YAML 文件详解

1、YAML 文件概述

k8s 集群中对资源管理和资源对象编排部署都可以通过声明样式(YAML)文件来解决,也 就是可以把需要对资源对象操作编辑到 YAML 格式文件中,我们把这种文件叫做资源清单文 件,通过 kubectl 命令直接使用资源清单文件就可以实现对大量的资源对象进行编排部署 了。

2、YAML 文件书写格式

(1)YAML 介绍 YAML :仍是一种标记语言。为了强调这种语言以数据做为中心,而不是以标记语言为重点。 YAML 是一个可读性高,用来表达数据序列的格式。
(2)YAML 基本语法

  • 使用空格做为缩进
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • 低版本缩进时不允许使用 Tab 键,只允许使用空格
  • 使用#标识注释,从这个字符一直到行尾,都会被解释器忽略

(3)YAML 支持的数据结构

  • 对象
    键值对的集合,又称为映射(mapping) / 哈希(hashes) / 字典(dictionary)
    在这里插入图片描述
  • 数组
    一组按次序排列的值,又称为序列(sequence) / 列表 (list)
    在这里插入图片描述
  • 纯量(scalars)
    单个的、不可再分的值
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

3、资源清单描述方法

在这里插入图片描述

  • (1)在 k8s 中,一般使用 YAML 格式的文件来创建符合我们预期期望的 pod,这样的 YAML 文件称为资源清单。
  • (2)常用字段
    必须存在的属性
    在这里插入图片描述

spec 主要对象
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
额外的参数
在这里插入图片描述

4、创建yaml方式

1、kubectl create

适合还没有部署的资源
将创建的过程写入my1.yaml
如果写错deployment就会报unknown flags --image 有坑

kubectl create demployment web --image=nginx  -o yaml --dry-run > my1.yaml
2、kubectl get

适合已经部署过的资源,从已经有的导出成yaml编排清单

kubectl get deploy  nginx -o=yaml --export > my2.yaml

3 、pod

在这里插入图片描述

1、Pod 概述

Pod 是 k8s 系统中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最 小资源对象模型,也是在 k8s 上运行容器化应用的资源对象,其他的资源对象都是用来支 撑或者扩展 Pod 对象功能的,比如控制器对象是用来管控 Pod 对象的,Service 或者 Ingress 资源对象是用来暴露 Pod 引用对象的,PersistentVolume 资源对象是用来为 Pod 提供存储等等,k8s 不会直接处理容器,而是 Pod,Pod 是由一个或多个 container 组成 Pod 是 Kubernetes 的最重要概念,每一个 Pod 都有一个特殊的被称为”根容器“的 Pause 容器。Pause 容器对应的镜 像属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 还包含一个或多个紧密相关的用户业务容器

  • (1) 最小的部署单元
  • (2)包含多个容器(一组容器的集合)
  • (3)一个pod容器共享网络命名空间
  • (4)pod是短暂的

2、存在的意义

  • (1)创建容器使用docker,一个docker对应一个容器,一个容器一个进程,是单进程设计,一个容器运行一个应用
  • (2)pod是多线程设计,运行多个应用程序,一个pod有多个容器,是容器的集合体
  • (3)pod是为了亲密性应用,两个应用之间交互, 网络之间调用,两个容器需要频繁调用

3、pod实现机制

在这里插入图片描述

  • (1)共享网络
    通过pause容器,把其他业务容器加入到pause容器里面,让所有的业务容器在一个名称空间中,可以实现网络共享
  • (2)共享存储
    引入数据卷概念volumn,使用数据卷进行持久化存储
    在这里插入图片描述
    在这里插入图片描述

4、Pod 特性

(1)资源共享
一个 Pod 里的多个容器可以***共享存储和网络***,可以看作一个逻辑的主机。共享的如 namespace,cgroups 或者其他的隔离资源。
 多个容器共享同一 network namespace,由此在一个 Pod 里的多个容器共享 Pod 的 IP 和 端口 namespace,所以一个 Pod 内的多个容器之间可以通过 localhost 来进行通信,所需要 注意的是不同容器要注意不要有端口冲突即可。不同的 Pod 有不同的 IP,不同 Pod 内的多 个容器之前通信,不可以使用 IPC(如果没有特殊指定的话)通信,通常情况下使用 Pod 的 IP 进行通信。 
 一个 Pod 里的多个容器可以**共享存储卷**,这个存储卷会被定义为 Pod 的一部分,并且可 以挂载到该 Pod 里的所有容器的文件系统上。
(2)生命周期短暂

Pod 属于生命周期比较短暂的组件,比如,当 Pod 所在节点发生故障,那么该节点上的 Pod 会被调度到其他节点,但需要注意的是,被重新调度的 Pod 是一个全新的 Pod,跟之前的 Pod 没有半毛钱关系。

(3)平坦的网络

K8s 集群中的所有 Pod 都在同一个共享网络地址空间中,也就是说每个 Pod 都可以通过其 他 Pod 的 IP 地址来实现访问

5、pod镜像拉取策略

在这里插入图片描述
imagesPullPolicy: [ Always| Never| IfNotPresent]
获取镜像的策略,默认值为 IfNotPresent 在宿主机不存在时拉取

6、pod资源限制

在这里插入图片描述

resources: 
	limits: //资源限制,容器的最大可用资源数量 
		cpu: Srting
		memory: string 
	requeste: //资源限制,容器启动的初始可用资源数量
		cpu: string 
		memory: string

7、pod重启策略

restartPolicy: [ Always| Never| OnFailure]
//重启策略,默认值为 Always

8、pod容器检查

在这里插入图片描述

1、 存活检查 livenessProbe

如果检查失败,将杀死容器,根据pod的restartPolicy来操作

2、就绪检查 readinessProbe

如果检查失败,kubernetes会把pod从service endpoints剔除

3、probe支持三种检查方法
1、httpGet

发送http请求,返回200-400范围状态码为成功

2、exec

执行shell命令返回状态码0位成功

3、tcpSocket

发起tcp Socket建立连接

9、pod调度策略

1、创建pod的流程

在这里插入图片描述

2、影响调度的属性
  • pod的资源限制
  • 节点选择器标签
    在这里插入图片描述
spec:
	ndoeSelector:
		env_role=dev
	containers:
		- name: neginx
		 image: nginx:1.15
		
对节点创建标签,master上面设置
kubectl label node node1 env_role=prod

删除节点标签:后面的-表示将该标签删除
kubectl label node node1 env_role-
  • 节点亲和性
spec:
	affinity:
		nodeAffinity:
			requiredDruingSchedulingIgnoredDuringExecution:
				nodeSelectorTerms:
					- matchExpression:
						- key: env_role
						  operator: In
						  values:
						  	- dev
						  	- test
			preferredDuringSchedulingIgnoreDuringExecution:
				- weight: 1
				  preference:
				  	matchExpression:
				  		- key: group
				  		  operator: In
				  		  values:
				  		  	- otherprod
	containers:
		- name: webdemo
		  image: nginx

节点亲和性nodeAffinity和之前的nodeSelector基本一样,根据节点上标签约束来决定pod调度到哪个节点上,
硬亲和性:约束条件必须满足
软亲和性:尝试满足,不保证
支持的常用操作符:

In   NotIn  Exists   Gt   Lt   DoesNotExists

在这里插入图片描述

  • 污点和污点容忍性
    污点是节点属性,不是pod属性,不做普通的分配调度,
    使用场景比如专用节点,配置特点硬件节点,基于Taint驱逐
    污点的三个值:
    NoSchedule:一定不会被调度
    PreferSchedule : 尽量不被调度
    NoExecute:不会被调度,并且还会驱逐Nde已有的pod
(1)为节点添加污点
	kubectl taint node [node] key=value:污点三个值
(2)删除污点
例如:	kubectl taint node k8snode1 key:NoSchedule-  


污点容忍:就是配置内容

spec:
	tolerations:
		- kye: "key"
		  operator: "Equal"
		  value: "value"
		  effect: "NoSchedule"

在这里插入图片描述

4 、Conttroller

在这里插入图片描述
在这里插入图片描述

1、什么是controller

在集群上管理和运行容器的对象

2、Pod和Controller的关系

Pod是通过Controller实现应用的运维,比如弹性伸缩,滚动升级等

3、Pod和Controller是通过label建立关系的

4、deployment应用场景

  • 部署无状态应用
  • 管理pod和ReplicaSet
  • 部署,滚动升级等功能
  • 应用场景:web服务,微服务

5、使用deployment部署引用(yaml)

在这里插入图片描述

1、导出yaml文件
kubectl create deployment web --image=nginx --dry-run -o yaml > web.yaml
2、使用yaml部署应用
kubectl apply -f web.yaml
3、对外发布(暴露对外端口号)
kubectl expose deployment web --port=80 --type=NodePort --traget-port=80 --name=web1 -o yaml  > web1.yaml
4、查看应用运行状态
kubectl get pod,svc

6、deployment升级回滚和弹性伸缩

1、升级应用deployment 类型的controller nginx版本为1.15

在这里插入图片描述

kubectl set image deployment web  nginx=nginx:1.15   

在这里插入图片描述

2、查看升级的状态
kubectl rollout status deployment web

在这里插入图片描述

3、查看升级的历史版本
kubectl rollout history deployment web

在这里插入图片描述

4、回滚版本
1、回滚到上一个版本
kubectl rollout undo deployment web
2、回滚到指定版本
kubectl rollout undo deployment web --to-revision=2

在这里插入图片描述

5、弹性伸缩

kubectl scale deployment web --replicas=5

5、Service

在这里插入图片描述

在这里插入图片描述

1、存在的意义

  • 1、防止pod失联(服务发现)
  • 2、定义一组pod的访问规则(负载均衡)
    *在这里插入图片描述

2、pod和service的关系

根据label和selector标签建立关联的
在这里插入图片描述

3、service常见的三中类型

  • ClusterIP 默认,集群内部使用
  • NodePort 对外访问应用使用
  • LoadBalancer 对外访问应用使用,公有云
    在这里插入图片描述
    node内网部署应用,外网一般不能访问到,
    方法:
    1 找到一台可以进行外网访问机器,安装nginx,反向代理,手动把可以访问的节点添加上

2 loadBalancer公有云,把负载均衡,控制器

4、无状态,有状态部署

(1) 无状态:
认为pod都是一样的 ,使用kubectl get pods -o wide 查看pod的ip地址,ip是不一样的,每个pod内统一用一个ip
没有顺序要求
不用考虑哪个node运行
随意伸缩和扩展
(2)有状态
上面因素都需要考虑
让每个pod独立 ,保持pod启动顺序和唯一性
(唯一性网络标识符,持久存储
有序,比如mysql主从)

5、部署有状态应用

1、无头service 就是ClusterIp为None

在这里插入图片描述
在这里插入图片描述

2、SatefullSet部署有状态应用

在这里插入图片描述

3、查看pod有三个副本,没有名次不一样

deployment和satefullSet区别:有身份(唯一标识),根据主机名+按照一定规则生成域名

域名规则:
主机名称.service名称.名称空间.svc.cluster.local
在这里插入图片描述

在这里插入图片描述

4、查看创建无头的service

在这里插入图片描述

5、sts.yaml文件内容
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-statefulset
  namespace: default
spec:
  serviceName: nginx
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

6、部署守护进程,确保所有node在一个pod运行,DamonSet

在每个node上运行一个pod,新加入的node也同时运行在一个pod里面
例子:

为每个mode节点安装数据采集工具
在这里插入图片描述

7、一次任务job

1、job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

2、部署
kubectl apply -f job.yaml

在这里插入图片描述

3、删除:job

在这里插入图片描述

在这里插入图片描述

8、定时任务

1、cronjob.yaml
apiVersion: batch/v1beta1
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


2、部署
kubectl apply -f cronjob.yaml

在这里插入图片描述

3、查看
kubectl get pods -o wide

在这里插入图片描述

4、查看日志
kubectl logs 容器名称

在这里插入图片描述

5、删除
kubectl delete -f cronjob.yaml

在这里插入图片描述

6、secret

加密: echo -n ‘admin’ | base64
解密:echo -n ‘fewfewf’ | base64 -d
在这里插入图片描述

作用:加密数据存储在etcd里面,让pod容器以挂载volmn方式进行访问
场景:凭证

1、创建secret数据secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

在这里插入图片描述

2、以变量形式挂载到pod中

secret-var.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: nginx
    image: nginx
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password

在这里插入图片描述
在这里插入图片描述

3、以volumn形式挂载pod容器中

secret-vol.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret

部署应用:记得删除之前的变量的形式,因为都叫mypod名称的,会报错部署的时候

kubectl apply -f kubectl-vol.yaml

在这里插入图片描述
检查是否挂载上
在这里插入图片描述

7、ConfigMap

在这里插入图片描述

作用:存储不加密数据到etcd,让pod以变量或者volumn挂载到容器中
场景:配置文件

1、创建配置文件

redis.properties

redis.host=127.0.0.1
redis.port=6379
redis.password=123456

2、创建configMap

kubectl create configmap redis-config --from-file=redis.properties

在这里插入图片描述
在这里插入图片描述

3、以volumn形式挂载到pod中config-vo.yaml

创建pod,挂载volumn

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: busybox
      image: busybox
      command: [ "/bin/sh","-c","cat /etc/config/redis.properties" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: redis-config
  restartPolicy: Never


在这里插入图片描述
在这里插入图片描述

4、以变量的形式挂载到pod容器中

(1)创建yaml,声明变量信息configMap创建
(2)以变量挂载pod

vi mycm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: myconfig
  namespace: default
data:
  special.level: info
  special.type: hello

创建pod:(config-var.yaml)

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: busybox
      image: busybox
      command: [ "/bin/sh", "-c", "echo $(LEVEL) $(TYPE)" ]
      env:
        - name: LEVEL
          valueFrom:
            configMapKeyRef:
              name: myconfig
              key: special.level
        - name: TYPE
          valueFrom:
            configMapKeyRef:
              name: myconfig
              key: special.type
  restartPolicy: Never

部署pod并将变量挂载到pod上

kubectl apply -f config-var.yaml

在这里插入图片描述
在这里插入图片描述

8、RABC k8s安全机制

在这里插入图片描述
在这里插入图片描述

1、概述

访问k8s集群时候,需要经过三个步骤完成具体操作:认证,授权,准入控制
进行访问的时候,过程中都需要经过apiserver,apiserver作为统一协调,比如门卫
访问过程中需要证书,token,或者用户名密码,如果访问pod,需要serviceAccount

2、第一步 传输安全

传输安全:对外不暴露8080端口,只能内部访问,对外使用端口6443
  • 认证:客户端身份常用方式
  • https证书认证,基于CA证书
  • http token 认证通过token识别用户
  • http基本认证,用户名+密码

3、第二步 鉴权(授权)

基于RBAC进行鉴权操作
基于角色访问控制

4、准入控制

就是准入控制器的列表,如果列表里有请求内容,通过,没有就拒绝

5、RBAC:基于角色的访问控制

角色:
role:特定命名空间访问权限
clusterRole:所有命名空间访问权限
角色绑定
roleBinding:角色绑定到主体
ClusterRoleBinding:集群角色绑定到主体
主体:
user:用户
group:用户组
serviceAccount:服务账号

1、创建命名空间
kubectl create ns roletest
2、查看命名空间
kubectl get ns
3、在新创建的命名空间创建pod
-- 运行pod
kubectl run  nginx --image=nginx -n roletest
-- 查看创建的pod
kubect get pods -n roletest
4、创建角色

rbac-role.yaml

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

部署yaml文件创建角色:

kubectl apply -f rbac-role.yaml

查看创建的角色

kubectl get role -n roletest
5、创建角色绑定

rbac-rolebinding.yaml

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: roletest
subjects:
- kind: User
  name: lucy # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role #this must be Role or ClusterRole
  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io

kubectl apply -f rbac-rolebinding.yaml
kubect get role.rolebinding -n roletest
6、使用证书识别证书

rabc-user.sh

cat > lucy-csr.json <<EOF
{
  "CN": "lucy",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "BeiJing",
      "ST": "BeiJing"
    }
  ]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes lucy-csr.json | cfssljson -bare lucy

kubectl config set-cluster kubernetes \
  --certificate-authority=ca.pem \
  --embed-certs=true \
  --server=https://192.168.163.133:6443 \
  --kubeconfig=lucy-kubeconfig
  
kubectl config set-credentials lucy \
  --client-key=lucy-key.pem \
  --client-certificate=lucy.pem \
  --embed-certs=true \
  --kubeconfig=lucy-kubeconfig

kubectl config set-context default \
  --cluster=kubernetes \
  --user=lucy \
  --kubeconfig=lucy-kubeconfig

kubectl config use-context default --kubeconfig=lucy-kubeconfig

证书复制进来ca开头的 cp /root/TLS/k8s/ca* ./
在这里插入图片描述
这个证书没有用,所以自己生成一个ca证书
ca-config.json

cat>ca-config.json<< EOF
{
	"signing": {
		"default": {
			"expiry": "87600h"
		},
		"profiles": {
			"kubernetes": {
				"expiry": "87600h",
				"usages": ["signing", "key encipherment", "server auth", "client auth"]
			}
		}
	}
}
EOF

ca-csr.json

cat > ca-csr.json<< EOF
{
	"CN": "etcd CA",
	"key": {
		"algo": "rsa",
		"size": 2048
	},
	"names": [{
		"C": "CN",
		"L": "Beijing",
		"ST": "Beijing"
	}]
}
EOF
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

生成ca.csr,ca.pem ,ca-key.pem 三个文件

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes lucy-csr.json | cfssljson -bare lucy

即是rbac-user.sh里面的前两个命令拿出来执行了

kubectl config set-cluster kubernetes \
  --certificate-authority=ca.pem \
  --embed-certs=true \
  --server=https://192.168.31.63:6443 \
  --kubeconfig=mary-kubeconfig
kubectl config set-credentials mary \
  --client-key=mary-key.pem \
  --client-certificate=mary.pem \
  --embed-certs=true \
  --kubeconfig=mary-kubeconfig

kubectl config set-context default \
  --cluster=kubernetes \
  --user=mary \
  --kubeconfig=mary-kubeconfig

kubectl config use-context default --kubeconfig=mary-kubeconfig

在这里插入图片描述

在这里插入图片描述

kubectl  get pods  -n roletest

在这里插入图片描述

9、ingress

在这里插入图片描述
在这里插入图片描述
查看pod详细部署在哪个节点上然后修改window的hosts域名映射
在这里插入图片描述

在这里插入图片描述

1、把端口号对外暴露,通过ip+端口号进行访问

使用service里面的NodePort实现

2、NodePort缺陷

在每个节点都会起到端口,在访问的时候通过任意节点,通过节点ip+端口号实现访问

  • 意味着每个端口只能使用一次,一个端口对应一个应用
  • 实际访问中跳转到不同端口服务中都是用域名,根据不同的域名

3、Ingress和pod的关系

pod和ingress通过service关联的,ingress作为统一的入口,由service关联一组pod

4、ingress工作流程

在这里插入图片描述
ongoing

5、使用ingress

第一步 部署ingress Controller
第二步 创建ingress规则
我们这里选择官方维护nginx控制器,实现部署

6、使用ingress对外暴露应用

  1. 创建nginx应用,对外暴露端口使用NodePort
kubect create deployment web --image=nginx

kubectl expose deployment web --port=80 --target-port=80 --type=NodePort
  • 部署ingress Controller
    ingress-controller.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: udp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-ingress-serviceaccount
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: nginx-ingress-clusterrole
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses/status
    verbs:
      - update

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: nginx-ingress-role
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - pods
      - secrets
      - namespaces
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - configmaps
    resourceNames:
      # Defaults to "<election-id>-<ingress-class>"
      # Here: "<ingress-controller-leader>-<nginx>"
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - "ingress-controller-leader-nginx"
    verbs:
      - get
      - update
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - get

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: nginx-ingress-role-nisa-binding
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nginx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: nginx-ingress-clusterrole-nisa-binding
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nginx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      hostNetwork: true
      # wait up to five minutes for the drain of connections
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: nginx-ingress-controller
          image: lizhenliang/nginx-ingress-controller:0.30.0
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --annotations-prefix=nginx.ingress.kubernetes.io
          securityContext:
            allowPrivilegeEscalation: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 101
            runAsUser: 101
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
            - name: https
              containerPort: 443
              protocol: TCP
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown

---

apiVersion: v1
kind: LimitRange
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  limits:
  - min:
      memory: 90Mi
      cpu: 100m
    type: Container

kubectl apply -f ingress-controller.yaml
  1. 查询ingress状态
kubectl get pods -n ingress-nginx
  1. 创建ingress规则
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - host: example.ingredemo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web
          servicePort: 80

ingress01.yaml

---
# http
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - host: example.ctnrs.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web
          servicePort: 80


ingress02.yaml


---
# https
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: tls-example-ingress
spec:
  tls:
  - hosts:
    - sslexample.ctnrs.com
    secretName: secret-tls
  rules:
    - host: sslexample.ctnrs.com
      http:
        paths:
        - path: /
          backend:
            serviceName: web
            servicePort: 80
  1. 在window系统hosts文件中添加域名访问规则
    hosts地址:C:\Windows\System32\drivers\etc
    在这里插入图片描述

10、Helm

1、helm的引入

之前方式部署应用的基本过程

  1. 编写yaml文件(deployment,service,ingress)
  2. 如果使用之前方式部署单一应用,少数服务的应用,比较合适
  3. 比如微服务项目,可能有几十个服务,每个服务都有yaml文件。需要维护大量的yaml,版本管理特别不合适。

2、使用helm可以解决哪些问题

  1. 使用heml可以把这些yaml作为一个整体管理
  2. 实现yaml高效复用
  3. 使用helm应用级别的版本管理

3、helm介绍

helm是一个Kubernetes包管理工具,就想linux包管理器,如yum、apt,可以很方便将之前打包好的yaml文件部署到kubernetes上

4 、Helm的三个重要概念

  • Helm 是一个命令行客户端工具
  • Chart 把yaml打包,是yaml的集合
  • Release 基于Chart部署实体,应用级别的版本管理

5、helm在2019年发布V3版本,和之前版本相比有变化

  • V3版本删除Tiller架构变化
  • release可以在不同命名空间重用
  • 将Chart推送到docker仓库中
    在这里插入图片描述
    在这里插入图片描述

6、helm安装(V3版本以后)

下载helm安装压缩文件,上传到linux,解压helm压缩文件,把解压后helm目录复制到/usr/bin目录下

1、配置helm仓库
1、添加仓库
helm repo add 仓库名称  仓库地址
比如
helm repo add stable http://mirror.azure.cn/kubernetes/charts/

在这里插入图片描述

2、查看仓库地址
helm repo list

在这里插入图片描述

3、删除仓库
kubectl repo remove  aliyun

在这里插入图片描述

4、更新仓库地址
helm repo update

在这里插入图片描述

7、使用helm快速部署应用
1、搜索weave应用
helm search repo weave

在这里插入图片描述

2、安装weave应用
helm install ui stable/weave-scope

在这里插入图片描述

3、查看安装列表
helm list

在这里插入图片描述

4、查看安装状态
helm status ui

在这里插入图片描述

8、如何自己创建chart

1、使用命令创建chart

在这里插入图片描述
在这里插入图片描述

2、在templates文件夹创建两个yaml文件

在这里插入图片描述

nginxchart.yaml

kubectl create deployment nginxchart --image=nginx -o yaml --dry-run >nginxchartweb.yaml

nginxchartsvc.yaml

kubectl expose deployment nginxchart --port=80 --target-port=80 --name=nginxhcart --type=NodePort -o yaml --dry-run >nginxchartsvc.yaml

进入templates目录,并删除生成的文件
在这里插入图片描述

3、安装mychart
helm install nginxchart mychart/

在这里插入图片描述

4、应用升级
helm upgrade ngingxchart mychart/

在这里插入图片描述

9、实现yaml高效复用

通过传递参数,动态渲染模板,yaml内容动态传入参数生成

1、values.yaml定义变量

在chart有values.yaml文件,定义yaml文件局变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
deployment.yaml文件替换变量
在这里插入图片描述

service.yaml 替换变量
在这里插入图片描述

2、在templates的yaml文件使用values.yaml定义的变量

在这里插入图片描述

3、可以检查变量替换是否成功 --dry-run

在这里插入图片描述

10、持久化存储nfs

1、nfs网络存储 pod重启数据化存在

第一步找一台服务器nfs服务器
安装nfs

yum install -y nfs-utils

设置挂载路径

vi /etc/exports

添加/data/nfs *(rw,no_root_squash)
挂载路径需要创建出来 /data/nfs

第二步:在k8s集群node节点安装nfs: yum install -y nfs-utils
第三步:在nfs服务器启动nfs服务

system start nfs
查看
ps -ef | grep nfs

第四步:在k8s集群部署应用使用nfs持久网络存储

kubectl apply -f nfs-nginx.yaml

kubectl exec -it nginx-dept1-xxx bash 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dep1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: wwwroot
          mountPath: /usr/share/nginx/html
        ports:
        - containerPort: 80
      volumes:
        - name: wwwroot
          nfs:
            server: 192.168.63.133
            path: /data/nfs

在这里插入图片描述
暴露端口后使用ip访问首页
在这里插入图片描述
在这里插入图片描述

2、PV和PVC

在这里插入图片描述
pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /k8s/nfs
    server: 192.168.63.163

pvc.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dep1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: wwwroot
          mountPath: /usr/share/nginx/html
        ports:
        - containerPort: 80
      volumes:
      - name: wwwroot
        persistentVolumeClaim:
          claimName: my-pvc

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

四、搭建集群监控平台系统

1、监控指标

集群监控:资源资源利用率,节点数,运行pods
pod监控:容器指标,应用指标

2、监控平台搭建方案 prometheus+Grafana接入即可

prometheus:开源的,监控报警,数据库,以http协议周期性抓取被监控组件状态,不需要复杂的集成过程,使用http接口即可
grafana:开源的数据分析和可视化工具,支持多种数据源
在这里插入图片描述

1、node-exporter.yaml 守护进程

---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: kube-system
  labels:
    k8s-app: node-exporter
spec:
  selector:
    matchLabels:
     k8s-app: node-exporter
  template:
    metadata:
      labels:
        k8s-app: node-exporter
    spec:
      containers:
      - image: prom/node-exporter
        name: node-exporter
        ports:
        - containerPort: 9100
          protocol: TCP
          name: http
---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: node-exporter
  name: node-exporter
  namespace: kube-system
spec:
  ports:
  - name: http
    port: 9100
    nodePort: 31672
    protocol: TCP
  type: NodePort
  selector:
    k8s-app: node-exporter

2、prometheus

1、rbac-setup.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/proxy
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups:
  - extensions
  resources:
  - ingresses
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: kube-system

2、configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: kube-system
data:
  prometheus.yml: |
    global:
      scrape_interval:     15s
      evaluation_interval: 15s
    scrape_configs:

    - job_name: 'kubernetes-apiservers'
      kubernetes_sd_configs:
      - role: endpoints
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
        action: keep
        regex: default;kubernetes;https

    - job_name: 'kubernetes-nodes'
      kubernetes_sd_configs:
      - role: node
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
      - target_label: __address__
        replacement: kubernetes.default.svc:443
      - source_labels: [__meta_kubernetes_node_name]
        regex: (.+)
        target_label: __metrics_path__
        replacement: /api/v1/nodes/${1}/proxy/metrics

    - job_name: 'kubernetes-cadvisor'
      kubernetes_sd_configs:
      - role: node
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
      - target_label: __address__
        replacement: kubernetes.default.svc:443
      - source_labels: [__meta_kubernetes_node_name]
        regex: (.+)
        target_label: __metrics_path__
        replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor

    - job_name: 'kubernetes-service-endpoints'
      kubernetes_sd_configs:
      - role: endpoints
      relabel_configs:
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
        action: replace
        target_label: __scheme__
        regex: (https?)
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
        action: replace
        target_label: __address__
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
      - action: labelmap
        regex: __meta_kubernetes_service_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_service_name]
        action: replace
        target_label: kubernetes_name

    - job_name: 'kubernetes-services'
      kubernetes_sd_configs:
      - role: service
      metrics_path: /probe
      params:
        module: [http_2xx]
      relabel_configs:
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe]
        action: keep
        regex: true
      - source_labels: [__address__]
        target_label: __param_target
      - target_label: __address__
        replacement: blackbox-exporter.example.com:9115
      - source_labels: [__param_target]
        target_label: instance
      - action: labelmap
        regex: __meta_kubernetes_service_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_service_name]
        target_label: kubernetes_name

    - job_name: 'kubernetes-ingresses'
      kubernetes_sd_configs:
      - role: ingress
      relabel_configs:
      - source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_probe]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
        regex: (.+);(.+);(.+)
        replacement: ${1}://${2}${3}
        target_label: __param_target
      - target_label: __address__
        replacement: blackbox-exporter.example.com:9115
      - source_labels: [__param_target]
        target_label: instance
      - action: labelmap
        regex: __meta_kubernetes_ingress_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_ingress_name]
        target_label: kubernetes_name

    - job_name: 'kubernetes-pods'
      kubernetes_sd_configs:
      - role: pod
      relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
        target_label: __address__
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: kubernetes_pod_name

3、prometheus.deploy.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    name: prometheus-deployment
  name: prometheus
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      containers:
      - image: prom/prometheus:v2.0.0
        name: prometheus
        command:
        - "/bin/prometheus"
        args:
        - "--config.file=/etc/prometheus/prometheus.yml"
        - "--storage.tsdb.path=/prometheus"
        - "--storage.tsdb.retention=24h"
        ports:
        - containerPort: 9090
          protocol: TCP
        volumeMounts:
        - mountPath: "/prometheus"
          name: data
        - mountPath: "/etc/prometheus"
          name: config-volume
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
          limits:
            cpu: 500m
            memory: 2500Mi
      serviceAccountName: prometheus    
      volumes:
      - name: data
        emptyDir: {}
      - name: config-volume
        configMap:
          name: prometheus-config   

4、prometheus.svc.yml
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: prometheus
  name: prometheus
  namespace: kube-system
spec:
  type: NodePort
  ports:
  - port: 9090
    targetPort: 9090
    nodePort: 30003
  selector:
    app: prometheus

3、grafana

1、grafana-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana-core
  namespace: kube-system
  labels:
    app: grafana
    component: core
spec:
  selector:
    matchLabels:
     app: grafana
     component: core
  replicas: 1
  template:
    metadata:
      labels:
        app: grafana
        component: core
    spec:
      containers:
      - image: grafana/grafana:4.2.0
        name: grafana-core
        imagePullPolicy: IfNotPresent
        # env:
        resources:
          # keep request = limit to keep this container in guaranteed class
          limits:
            cpu: 100m
            memory: 100Mi
          requests:
            cpu: 100m
            memory: 100Mi
        env:
          # The following env variables set up basic auth twith the default admin user and admin password.
          - name: GF_AUTH_BASIC_ENABLED
            value: "true"
          - name: GF_AUTH_ANONYMOUS_ENABLED
            value: "false"
          # - name: GF_AUTH_ANONYMOUS_ORG_ROLE
          #   value: Admin
          # does not really work, because of template variables in exported dashboards:
          # - name: GF_DASHBOARDS_JSON_ENABLED
          #   value: "true"
        readinessProbe:
          httpGet:
            path: /login
            port: 3000
          # initialDelaySeconds: 30
          # timeoutSeconds: 1
        volumeMounts:
        - name: grafana-persistent-storage
          mountPath: /var
      volumes:
      - name: grafana-persistent-storage
        emptyDir: {}

2、grafana-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: grafana
  namespace: kube-system
  labels:
    app: grafana
    component: core
spec:
  type: NodePort
  ports:
    - port: 3000
  selector:
    app: grafana
    component: core

3、grafana-ing.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
   name: grafana
   namespace: kube-system
spec:
   rules:
   - host: k8s.grafana
     http:
       paths:
       - path: /
         backend:
          serviceName: grafana
          servicePort: 3000

3、部署prometheus

先部署守护进程
kubectl create -f xxx.yaml
kubectl apply -f xxx.yaml

kubectl appply -f node-exporter.yaml
kubectl appply -f rbac-setup.yaml
kubectl appply -f configmap.yaml
kubectl appply -f prometheus.deploy.yml
kubectl appply -f prometheus.svc.yml

4、部署grafana

kubectl apply -f grafana-deploy.yaml
kubectl apply -f grafana-svc.yaml
kubectl apply -f grafana-ing.yaml

5、打开grafana配置数据源导入显示模板315

用户名密码都是admin
在这里插入图片描述

五、从零搭建高可用k8s集群

在这里插入图片描述
在这里插入图片描述

1、搭建高可用步骤

kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。

这个工具能通过两条指令完成一个kubernetes集群的部署:

### 创建一个 Master 节点
$ kubeadm init

# 将一个 Node 节点加入到当前集群中
$ kubeadm join <Master节点的IP和端口 >

1. 安装要求

在开始之前,部署Kubernetes集群机器需要满足以下几个条件:

  • 一台或多台机器,操作系统 CentOS7.x-86_x64
  • 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多
  • 可以访问外网,需要拉取镜像,如果服务器不能上网,需要提前下载镜像并导入节点
  • 禁止swap分区

2. 准备环境

角色IP
master1192.168.44.155
master2192.168.44.156
node1192.168.44.157
VIP(虚拟ip)192.168.44.158
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld

# 关闭selinux
sed -i 's/enforcing/disabled/' /etc/selinux/config  # 永久
setenforce 0  # 临时

# 关闭swap
swapoff -a  # 临时
sed -ri 's/.*swap.*/#&/' /etc/fstab    # 永久

# 根据规划设置主机名
hostnamectl set-hostname <hostname>

# 在master添加hosts
cat >> /etc/hosts << EOF
192.168.44.158    master.k8s.io   k8s-vip
192.168.44.155    master01.k8s.io master1
192.168.44.156    master02.k8s.io master2
192.168.44.157    node01.k8s.io   node1
EOF

# 将桥接的IPv4流量传递到iptables的链
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system  # 生效

# 时间同步
yum install ntpdate -y
ntpdate time.windows.com

3. 所有master节点部署keepalived

3.1 安装相关包和keepalived

yum install -y conntrack-tools libseccomp libtool-ltdl

yum install -y keepalived

3.2配置master节点

master1节点配置

cat > /etc/keepalived/keepalived.conf <<EOF 
! Configuration File for keepalived

global_defs {
   router_id k8s
}

vrrp_script check_haproxy {
    script "killall -0 haproxy"
    interval 3
    weight -2
    fall 10
    rise 2
}

vrrp_instance VI_1 {
    state MASTER 
    interface ens33 
    virtual_router_id 51
    priority 250
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ceb1b3ec013d66163d6ab
    }
    virtual_ipaddress {
        192.168.44.158
    }
    track_script {
        check_haproxy
    }

}
EOF

master2节点配置

cat > /etc/keepalived/keepalived.conf <<EOF 
! Configuration File for keepalived

global_defs {
   router_id k8s
}

vrrp_script check_haproxy {
    script "killall -0 haproxy"
    interval 3
    weight -2
    fall 10
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP 
    interface ens33 
    virtual_router_id 51
    priority 200
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ceb1b3ec013d66163d6ab
    }
    virtual_ipaddress {
        192.168.44.158
    }
    track_script {
        check_haproxy
    }

}
EOF

3.3 启动和检查

在两台master节点都执行

# 启动keepalived
$ systemctl start keepalived.service
设置开机启动
$ systemctl enable keepalived.service
# 查看启动状态
$ systemctl status keepalived.service

启动后查看master1的网卡信息

ip a s ens33

4. 部署haproxy

4.1 安装

yum install -y haproxy

4.2 配置

两台master节点的配置均相同,配置中声明了后端代理的两个master节点服务器,指定了haproxy运行的端口为16443等,因此16443端口为集群的入口

cat > /etc/haproxy/haproxy.cfg << EOF
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    #
    log         127.0.0.1 local2
    
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon 
       
    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------  
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
#---------------------------------------------------------------------
# kubernetes apiserver frontend which proxys to the backends
#--------------------------------------------------------------------- 
frontend kubernetes-apiserver
    mode                 tcp
    bind                 *:16443
    option               tcplog
    default_backend      kubernetes-apiserver    
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend kubernetes-apiserver
    mode        tcp
    balance     roundrobin
    server      master01.k8s.io   192.168.44.155:6443 check
    server      master02.k8s.io   192.168.44.156:6443 check
#---------------------------------------------------------------------
# collection haproxy statistics message
#---------------------------------------------------------------------
listen stats
    bind                 *:1080
    stats auth           admin:awesomePassword
    stats refresh        5s
    stats realm          HAProxy\ Statistics
    stats uri            /admin?stats
EOF

4.3 启动和检查

两台master都启动

# 设置开机启动
$ systemctl enable haproxy
# 开启haproxy
$ systemctl start haproxy
# 查看启动状态
$ systemctl status haproxy

检查端口

netstat -lntup|grep haproxy

5. 所有节点安装Docker/kubeadm/kubelet

Kubernetes默认CRI(容器运行时)为Docker,因此先安装Docker。

5.1 安装Docker

$ wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
$ yum -y install docker-ce-18.06.1.ce-3.el7
$ systemctl enable docker && systemctl start docker
$ docker --version
Docker version 18.06.1-ce, build e68fc7a
$ cat > /etc/docker/daemon.json << EOF
{
  "registry-mirrors": ["https://xxx.mirror.aliyuncs.com"]
}
EOF

5.2 添加阿里云YUM软件源

$ cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

5.3 安装kubeadm,kubelet和kubectl

由于版本更新频繁,这里指定版本号部署:

$ yum install -y kubelet-1.16.3 kubeadm-1.16.3 kubectl-1.16.3
$ systemctl enable kubelet

6. 部署Kubernetes Master

6.1 创建kubeadm配置文件

在具有vip的master上操作,这里为master1

$ mkdir /usr/local/kubernetes/manifests -p

$ cd /usr/local/kubernetes/manifests/

$ vi kubeadm-config.yaml

apiServer:
  certSANs:
    - master1
    - master2
    - master.k8s.io
    - 192.168.44.158
    - 192.168.44.155
    - 192.168.44.156
    - 127.0.0.1
  extraArgs:
    authorization-mode: Node,RBAC
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta1
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: "master.k8s.io:16443"
controllerManager: {}
dns: 
  type: CoreDNS
etcd:
  local:    
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.16.3
networking: 
  dnsDomain: cluster.local  
  podSubnet: 10.244.0.0/16
  serviceSubnet: 10.1.0.0/16
scheduler: {}

6.2 在master1节点执行

$ kubeadm init --config kubeadm-config.yaml

按照提示配置环境变量,使用kubectl工具:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
$ kubectl get nodes
$ kubectl get pods -n kube-system

按照提示保存以下内容,一会要使用:

kubeadm join master.k8s.io:16443 --token jv5z7n.3y1zi95p952y9p65 \
    --discovery-token-ca-cert-hash sha256:403bca185c2f3a4791685013499e7ce58f9848e2213e27194b75a2e3293d8812 \
    --control-plane 

查看集群状态

kubectl get cs

kubectl get pods -n kube-system

7.安装集群网络

从官方地址获取到flannel的yaml,在master1上执行

mkdir flannel
cd flannel
wget -c https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

安装flannel网络

kubectl apply -f kube-flannel.yml 

检查

kubectl get pods -n kube-system

8、master2节点加入集群

8.1 复制密钥及相关文件

从master1复制密钥及相关文件到master2

# ssh root@192.168.44.156 mkdir -p /etc/kubernetes/pki/etcd

# scp /etc/kubernetes/admin.conf root@192.168.44.156:/etc/kubernetes
   
# scp /etc/kubernetes/pki/{ca.*,sa.*,front-proxy-ca.*} root@192.168.44.156:/etc/kubernetes/pki
   
# scp /etc/kubernetes/pki/etcd/ca.* root@192.168.44.156:/etc/kubernetes/pki/etcd

8.2 master2加入集群

执行在master1上init后输出的join命令,需要带上参数--control-plane表示把master控制节点加入集群

kubeadm join master.k8s.io:16443 --token ckf7bs.30576l0okocepg8b     --discovery-token-ca-cert-hash sha256:19afac8b11182f61073e254fb57b9f19ab4d798b70501036fc69ebef46094aba --control-plane

检查状态

kubectl get node

kubectl get pods --all-namespaces

5. 加入Kubernetes Node

在node1上执行

向集群添加新节点,执行在kubeadm init输出的kubeadm join命令:

kubeadm join master.k8s.io:16443 --token ckf7bs.30576l0okocepg8b     --discovery-token-ca-cert-hash sha256:19afac8b11182f61073e254fb57b9f19ab4d798b70501036fc69ebef46094aba

集群网络重新安装,因为添加了新的node节点

检查状态

kubectl get node

kubectl get pods --all-namespaces

7. 测试kubernetes集群

在Kubernetes集群中创建一个pod,验证是否正常运行:

$ kubectl create deployment nginx --image=nginx
$ kubectl expose deployment nginx --port=80 --type=NodePort
$ kubectl get pod,svc

访问地址:http://NodeIP:Port

六、在集群环境部署项目

在这里插入图片描述

在这里插入图片描述

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐