k8s从入门到精通 -- 更适合中国宝宝体质

环境搭建

参考: k8s集群环境的搭建 (yuque.com)

资源管理

k8s中,所有内容都被抽象为 资源

  • k8s本质是一个集群系统,用户在集群中部署各种服务,所谓部署服务,就是在k8s集群中运行一个个容器,并将指定的程序跑在容器中
  • k8s的最小管理单元是 Pod ,只能将容器放在 Pod 中,k8s通过Pod控制器来管理Pod
  • k8s通过Service资源实现对Pod中服务的访问
  • k8s提供存储系统,可对Pod中程序的数据持久化

YAML语言简介

YAML语法

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进不使用tab,只允许空格(低版本限制)
  • 缩进的空格数不重要,只要相同层级的元素左对齐即可
  • 表示注释

YAML支持的数据类型

  • 纯量:单个的、不可再分的值,如:字符串、布尔值、整数、浮点数、Null(使用~表示)、时间、日期
  • 对象:键值对的集合,如:映射、哈希、字典
  • 数组:一组按次序排列的值,如:序列、列表

注意

  • 书写ymal,:后加空格
  • 如果将多个ymal配置在一个文件中,中间使用 --- 分隔

资源管理方式

命令式对象管理

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

  • 语法: kubectl [command] [type] [name] [flags]

    • command 指定要对资源执行的操作,如 create、get、delete
    • type 指定资源类型,如 deployment、pod、service
    • name 资源名称
    • flags 指定额外的可选参数
  • 示例:

bash 复制代码
# 查看所有pod
kubectl get pod

# 查看某个pod
kubectl get pod pod_name

# 查看某个pod,以yaml格式展示结果
kubectl get pod ppod_name -o yaml

command 常见命令

命令分类 命令 翻译 命令作用
基本命令 create 创建 创建一个资源
基本命令 edit 编辑 编辑一个资源
基本命令 get 获取 获取一个资源
基本命令 patch 更新 更新一个资源
基本命令 delete 删除 删除一个资源
基本命令 explain 解释 展示资源文档
运行和调试 run 运行 在集群中运行一个指定的镜像
运行和调试 expose 暴露 暴露资源为Service
运行和调试 describe 描述 显示资源内部信息
运行和调试 logs 日志 输出容器在pod中的日志
运行和调试 attach 连接 进入运行中的容器
运行和调试 exec 执行 执行容器中的一个命令
运行和调试 cp 复制 在Pod内外复制文件
运行和调试 rollout 首次展示 管理资源的发布
运行和调试 scale 规模 扩容或缩容(Pod的数量)
运行和调试 autoscale 自动调整 自动调整Pod的数量
高级命令 apply 通过文件对资源进行配置
高级命令 label 标签 更新资源上的标签
其他命令 cluster-info 集群信息 显示集群信息
其他命令 version 版本 显示当前Server和Client的版本

type 资源类型

k8s中所有内容抽象为资源,可通过下面命令查看:

bash 复制代码
kubectl api-resources

常见资源有:

资源分类 资源名称 缩写 资源作用
集群级别资源 nodes no 集群组成部分
集群级别资源 namespaces ns 隔离Pod
pod资源 pods po 装载容器
pod资源控制器 replicationcontrollers rc 控制pod资源
pod资源控制器 replicasets rs 控制pod资源
pod资源控制器 deployments deploy 控制Pod资源
pod资源控制器 daemonsets ds 控制Pod资源
pod资源控制器 jobs 控制Pod资源
pod资源控制器 cronjobs cj 控制Pod资源
pod资源控制器 horizontalpodautoscalers hpa 控制pod资源
pod资源控制器 statefulsets sts 控制Pod资源
服务发现资源 services svc 统一pod对外接口
服务发现资源 ingress ing 统一pod对外接口
存储资源 volumeattachments 存储
存储资源 persistentvolumes pv 存储
存储资源 persistentvolumeclaims pvc 存储
配置资源 configmaps cm 配置
配置资源 secrets 配置

命令式对象配置

通过命令配置和配置文件去操作k8s资源

kubectl create/patch -f nginx-pod.ymal

命令式对象配置的方式操作资源,可以简单的认为: 命令 + yaml配置文件 (配置文件中是命令需要的各种参数)

声明式对象配置

通过apply命令和配置文件去操作k8s资源、

kubectl apply -f nginx-pod.ymal

声明式对象配置就是使用apply描述一个资源的最终状态(该状态在yaml文件中定义)

使用apply操作资源

  • 如果资源不存在,就创建,相当于 kubectl create
  • 如果资源已存在,就更新,相当于 kubectl patch

扩展:kubectl如何在node节点上运行

kubectl 的运行需要进行配置,配置文件位于 $HOME/.kube,如果想要在node节点运行此命令,需要将master节点上的.kube文件复制到node节点,即在master节点执行下面操作:

scp -r HOME/.kube node1:HOME/

推荐使用的资源管理方式

  • 创建/更新资源:使用声明式对象配置 kubectl apply -f XXX.yaml
  • 删除资源: 使用命令式对象配置 kubectl delete -f XXX.yaml
  • 查询资源: 使用命令式对象管理 kubectl get/describe 资源名称

实战入门

namespace

作用: 实现多套环境的资源隔离多租户的资源隔离

ns常用命令

  • 查看所有ns kubectl get ns
  • 查看指定ns kubectl get ns ns名称
  • 指定输出格式 kubectl get ns ns名称 -o 格式参数
    • 常见格式参数:wide json yaml
  • 查看ns详情 kubectl describe ns ns命令
  • 创建ns kubectl create ns ns名称
  • 删除ns kubectl delete ns ns名称

pod

pod是k8s集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于pod中。pod可认为是容器的封装,一个pod中可以存在一个或多个容器

pod常用命令

  • 创建并运行pod kubectl run pod名称 [参数]
    • 参数包括:
    • --image 指定pod镜像
    • --port 指定端口
    • --namespace 指定ns
  • 查看pod基本信息 kubectl get pods -n pod名称
  • 查看pod详细信息 kubectl describe pod pod名称 -n ns名称
  • 访问pod
    • 获取podIP kubectl get pods -n ns名称 -o wide
    • 访问pod curl http://ip:暴露的端口号
  • 删除pod kubectl delete pod pod名称 -n ns名称
    • 如果当前pod是由pod控制器创建的,则若要删除pod,必须删除pod控制器:
      • 查询当前ns下的pod控制器: kubectl get deployment -n ns名称
      • 删除pod控制器: kubectl delete deployment pod控制器名称 -n ns名称

label

Label的作用就是在资源上添加标识,用来对资源进行区分和选择

Label特点:

  • 一个Label会以key:value键值对的形式添加到各种资源上,如:node pod service等
  • 一个资源可以定义任意数量的label,同一个label可可以添加到任意数量的资源上
  • label通常在资源对象定义时确定,也可以在资源创建后动态添加或删除
  • label用于给某个资源对象定义标识
  • label selector用于查询和筛选拥有某些标签的资源对象
    • 基于等式的label selector

      • name = slave: 选择所有label中key="name" 且 value="slave"的资源
      • env != prod:选择所有包含label中的key="env" 且 value不等于"prod"的资源
    • 基于集合的label selector

      • name in (master,slave): 选择所有label中key="name" 且 value="master"或"slave"的资源
      • name not in(frontend): 选择所有label中key="name" 且 value 不等于"frontend"的资源
    • 标签的选择条件可以使用多个,使用 "," 进行分隔即可

      • name=slave, env!=prod

label常用命令

  • 为pod资源打标签
    • kubectl label pod nginx-pod(pod名称) version=1.0(具体标签) -n dev(ns名称)
  • 为pod资源更新标签
    • kubectl label pod nginx-pod(pod名称) version=1.0(具体标签) -n dev(ns名称) --overwrite
  • 查看标签
    • kubectl get pod nginx-pod(pod名称) -n dev(ns名称) --show-labels
  • 筛选标签
    • kubectl get pod -n dev(ns名称) -l version=2.0(筛选条件) --show-labels
  • 删除标签
    • kubectl label pod nginx-pod(pod名称) version-(标签的key-) -n dev(ns名称)

deployment

在k8s中,pod是最小控制单元,但是k8s很少直接控制pod,一般都是通过pod控制器完成。pod控制器用于pod的管理,确保pod资源符合预期状态,当pod资源出现故障时,会尝试进行重启或重建pod。pod控制器有多种,此处以deployment为例。

deployment常见命令

  • 通过pod控制器创建pod
    • kubectl run nginx --image=nginx --port=80 --replicas=3 -n dev (新版本已不支持)
      • --image 指定pod镜像
      • --port 指定端口
      • --replicas 指定创建pod数量
      • -n 指定ns
新版本执行下列命令 复制代码
[root@Master ~]# kubectl create deploy nginx --image=nginx:1.17.2 -n dev
deployment.apps/nginx created
[root@Master ~]# kubectl get pod -n dev
NAME                     READY   STATUS    RESTARTS   AGE
nginx-56c8664f6b-jdbxd   1/1     Running   0          16s
[root@Master ~]# kubectl scale deploy nginx --replicas=3 -n dev
deployment.apps/nginx scaled
[root@Master ~]# kubectl get pod -n dev
NAME                     READY   STATUS    RESTARTS   AGE
nginx-56c8664f6b-dzkk8   1/1     Running   0          5s
nginx-56c8664f6b-jdbxd   1/1     Running   0          73s
nginx-56c8664f6b-vt8cz   1/1     Running   0          5s
  • 查看创建的pod

    • kubectl get pods -n dev(ns名称)
  • 查看deployment信息

    • kubectl get deploy(deployment简写) -n dev(ns名称)
  • 查看deployment详细信息

    • kubectl describe deploy(deployment简写) nginx(pod控制器名称) -n dev(ns名称)
  • 删除pod控制器

    • kubectl delete deploy nginx(pod控制器名称) -n dev(ns名称)

service

每个pod都会分配一个单独的pod IP,但是存在如下问题:

  • pod IP会随着pod重建产生变化
  • pod IP仅是集群内可见的虚拟IP,外部无法访问

Service可以看作一组同类pod对外的访问接口,借助service,应用可以方便的实现服务发现和负载均衡

service基本操作

集群内部可以访问的service

xml 复制代码
[root@Master ~]# kubectl get pod -n dev
NAME                     READY   STATUS    RESTARTS   AGE
nginx-56c8664f6b-8c9kz   1/1     Running   0          14s
nginx-56c8664f6b-r64ng   1/1     Running   0          14s
nginx-56c8664f6b-zvl72   1/1     Running   0          24s
// 暴露service(svc)
[root@Master ~]# kubectl expose deploy nginx --name=svc-nginx --type=ClusterIP --port=80 --target-port=80 -n dev
service/svc-nginx exposed
// 查看service
[root@Master ~]# kubectl get svc svc-nginx -n dev -o wide
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE   SELECTOR
svc-nginx   ClusterIP   10.111.178.16   <none>        80/TCP    54s   app=nginx
// 通过ClusterIP访问pod
[root@Master ~]# curl 10.111.178.16:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

创建集群外部也可访问的service

scss 复制代码
// 将type修改为NodePort
[root@Master ~]# kubectl expose deploy nginx --name=svc-nginx1 --type=NodePort --port=80 --target-port=80 -n dev
service/svc-nginx1 exposed
// 查看service,会看到一对port
[root@Master ~]# kubectl get svc svc-nginx1 -n dev -o wide
NAME         TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE   SELECTOR
svc-nginx1   NodePort   10.109.135.207   <none>        80:30129/TCP   58s   app=nginx
// 此时可通过集群外的主机访问 节点IP(不是ClusterIP):30129 访问服务

删除service

perl 复制代码
[root@Master ~]# kubectl delete svc svc-nginx1 -n dev
service "svc-nginx1" deleted

Pod详解(yaml)

pod结构

pod定义

可以通过下列命令查看每种资源的可配置项

  • kubectl explain 资源类型 查看某种资源可配置的一级属性
  • kubectl explain 资源类型.属性 查看属性的子属性

一级属性简介

  • apiVersion (string) 版本,由k8s内部定义,可用 kubectl api-versions 查询
  • kind (string)类型,由k8s内部定义,可用 kubectl api-resources 查询
  • metadata(Object)元数据,资源标识和说明,常用的有name,namespace,labels等
  • spec (Object)描述,配置中最重要的部分,里面是对各种资源的详细描述
  • status (Object)状态信息,由k8s自动生成

spec常见子属性

  • containers ([]Object), 容器列表,定义容器详细信息
  • nodeName (string), 根据nodeName的值将pod调度到指定的Node节点上
  • nodeSelector (map[]), 根据NodeSelector中定义的信息,选择将该pod调度到包含这些label的Node上
  • hostNetwork (boolean), 是否使用主机网络模式,默认为false,如为true,表示使用宿主主机网络
  • volumes ([]Object), 存储卷,用于定义pod上挂载的存储信息
  • restartPolicy (string), 重启策略,表示pod在遇到故障时的处理策略

pod配置

基本配置

镜像拉取策略 imagePullPolicy

  • Always 总是从远程仓库拉取镜像
  • ifNotPresent 本地有就本地,本地没有就远程
  • Never 一直使用本地,本地没有就报错

启动命令 command & args

单独command就可以完成启动命令和传递参数的功能

  • 如果command和args均没有写,则使用dockerfile的配置
  • 如果command写了,但是args没有写,则dockerfile默认配置会被忽略,执行输入的command
  • 如果command没写,但是args写了,则dockerfile中配置的ENTRYPOINT命令会被执行,但使用当前args的参数
  • 如果command和args都写了,则dockerfile配置会被忽略,会执行command并追加args参数

环境变量 env

用于在pod中的容器设置环境变量,但不推荐,更推荐将配置单独存储在配置文件中

端口设置 ports

kubectl explain pod.spec.containers.ports 访问容器中的程序需要使用的是 PodIP:containerPort

资源配额 resources

k8s使用resources对容器占用的内存、cpu资源进行配额

  • limits:限制运行时容器的最大占用资源,当容器占用资源超过limits时会被终止,并进行重启
  • requests:设置容器需要的最小资源,如果环境资源不够,容器无法启动

示例pod-resources.yaml

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
    name: pod-resources
    namespace: dev
spec:
    containers:
    - name: nginx
      image: nginx:1.17.1
      resources: # 资源配额
          limit: # 上限
              cpu: "2"
              memory: "10Gi"
          requests: # 下限
              cpu: "1"
              memory: "10Mi"
  • cpu: core数,可以为整数或者小数
  • memory: 内存大小,单位可为Gi,Mi,G,M等形式

pod生命周期

在整个生命周期中,Pod会出现的5种状态(相位):

  • 挂起(Pending):apiServer已经创建了pod资源对象,但它尚未被调度完成或仍处于下载镜像过程
  • 运行中(Running):pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成
  • 成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启
  • 失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态
  • 未知(Unknown):apiServer无法正常获取到pod对象的状态信息,通常由网络通信失败所导致

创建和终止

pod创建过程

  1. 用户通过kubectl或其它api客户端提交需要创建的pod信息给apiServer
  2. apiServer开始生成pod对象信息,并将信息存入etcd,然后返回确认信息至客户端
  3. apiServer开始反映etcd中的pod对象的变化,其他组件使用watch机制来跟踪检查apiServer上的变动
  4. scheduler发现有新的pod对象要创建,开始为pod分配主机并将结果信息更新至apiServer
  5. node节点上的kubelet发现有pod调度过来,尝试调用docker启动容器,并将结果回送至apiServer
  6. apiServer将接收到的pod状态信息存入etcd中

pod终止过程

  1. 用户向apiServer发送删除pod对象的命令
  2. apiServer中的pod对象信息会随着时间的推移而更新,在宽限期内(默认30s),pod被视为dead
  3. 将对象标记为terminating状态([terminating不是pod阶段之一](Pod 的生命周期 | Kubernetes))
  4. kubelet在监控到pod对象转为terminating状态的同时启动pod关闭过程
  5. 端点控制器监控到pod对象的关闭行为时将其从所有匹配到此端点的service资源的端点列表中移除
  6. 如果当前pod对象定义了perStop钩子处理器,则在其标记为terminating后即会以同步的方式启动执行
  7. pod对象中的容器进程收到停止信号
  8. 宽限期结束后,若pod中还存在仍在运行的进程,则pod对象会收到立即终止的信号
  9. kubelet请求apiServer将此pod资源的宽限期设置为0从而完成删除操作,此时pod对用户已不可见

初始化容器

初始化容器是在pod的主容器启动之前要运行的容器,主要做一些主容器的前置工作,具有两大特征:

  1. 初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernates需要重启它直至成功完成
  2. 初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面一个才能运行

钩子函数

k8s在主容器启动之后和停止之前提供两个钩子函数

  • post start 容器创建之后执行,如果失败了重启容器
  • pre stop 容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作

钩子处理器支持使用下面三种方式定义动作

  • exec命令:在容器内执行一次命令
  • tcpSocket:在当前容器尝试访问指定的socket
  • httpGet:
  • 在当前容器中向某url发起http请求

容器探测

容器探测用于检测容器中的应用实例是否正常工作,k8s提供两种探针来实现容器探测

  • liveness probes:存活性探针,检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器
  • readiness probes:就绪性探针,检测应用实例当前是否可以接收请求,如果不能,k8s不会转发流量

上述探针支持的探测方式

  • exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常
yaml 复制代码
......
    livenessProbe:
        exec:
         command:
         - cat
         - /temp/healthy
......
  • tcpSocket:尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常
yaml 复制代码
......
    livenessProbe:
        tcpSocket:
            port: 8080
......
  • httpGet:调用容器内Web应用的url,如果返回状态码在200到399之间,则认为程序正常,否则不正常
yaml 复制代码
......
    livenessProbe:
        httpGet:
            path: / # URI地址
            port: 80 
            host: 127.0.0.1 # 主机地址
            scheme: HTTP # 支持的协议,http/https
......

kubectl explain pod.spec.containers.livenessProbe

重启策略 restartPolicy

一旦容器探测出现问题,k8s会对容器所在的pod进行重启,pod的重启策略有3种:

  • Always:默认值,容器失效时,自动重启该容器
  • OnFailure: 容器终止运行且退出码不为0时(异常终止)重启
  • Never: 不论什么状态,都不重启

Pod调度

k8s提供四大类调度方式:

  • 自动调度:运行在哪个节点完全由Scheduler经过一系列的算法计算得出
  • 定向调度:NodeName、NodeSelector
  • 亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity
  • 污点-容忍调度:Taints、Toleration

定向调度

利用在pod上声明nodeName或者nodeSelector,以此将pod调度到期望的node节点上。定向调度是强制的,即使要调度的目标node不存在,也会向上面进行调度,只不过pod运行失败

  • nodeName:强制约束将pod调度到指定name的node节点上
  • nodeSelector:强制约束将pod调度到添加了指定标签的node节点上

亲和性调度

亲和性调度是在NodeSelector的基础之上进行的扩展,可通过配置的形式,实现优先选择满足条件的node进行调度,如果没有,也可以调度到不满足条件的节点上。 Affinity主要分为3类:

  • nodeAffinity(node亲和性):以node为目标,解决pod可调度到哪些node的问题
  • podAffinity(pod亲和性):以pod为目标,解决pod可以和哪些pod部署在同一个拓扑域的问题
  • podAntiAffinity(pod反亲和性):以pod为目标,解决pod不能和哪些pod部署在同一个拓扑域的问题

污点和容忍

污点 taint

站在node角度,通过在node上添加污点属性,来决定是否允许pod调度过来

污点的格式为:key=value:effect,其中,key和value是污点的标签,自定义即可, effect描述污点的作用,支持如下三个选项:

  • PreferNoSchedule:k8s将尽量避免把pod调度到具有该污点的node上,除非没有其他节点可调度
  • NoSchedule:k8s将不会把pod调度到具有该污点的Node上,但不会影响当前Node上已经存在的Pod
  • NoExecute:k8s将不会把Pod调度到具有该污点的Node上,同时也将Node上已存在的Pod驱离

使用k8s设置和去除污点的命令示例

  • 设置污点:kubectl taint nodes node1(节点名称) key=value:effect
  • 去除污点:kubectl taint nodes node1 key:effect-
  • 去除所有污点:kubectl taint nodes node1 key-

使用k8s搭建的集群,默认会给Master节点添加污点标记(NoExecute),所以pod不会调度到master节点

容忍 tolerations

如果需要将一个pod调度到一个有污点的node上去,需要使用容忍

污点是拒绝,容忍是忽略,Node通过污点拒绝pod调度上去,Pod通过容忍忽略拒绝

kubectl explain pod.spec.tolerations

Pod控制器详解

Pod控制器介绍

Pod控制器是管理pod的中间层,使用pod控制器后,只需告诉pod控制器想要的pod数量和类型,pod控制器会创建出满足条件的pod并确保每一个pod处于用户期望的状态,如果pod在运行中出现故障,控制器会基于指定策略重启或重建pod。

ReplicaSet(RS)

RS的主要作用:

  • 保证一定数量的pod能够正常运行:它会持续监听这些pod的运行状态,一旦pod发生故障,就会重启或重建
  • 对pod数量扩缩容
  • 版本镜像的升降级

yaml文件示例:

扩缩容

  • 编辑rs的副本数量,修改spec:replicas:x(数量)
    • kubectl edit rs rs名称 -n ns名称
  • 使用scale命令实现
    • kubectl scale rs rs名称 --replicas=副本数量 -n ns名称

镜像升降级

  • 编辑rs的容器镜像,修改image:镜像名称及版本 如:- image:nginx:1.17.2
    • kubectl edit rs rs名称 -n ns名称
  • 使用set image命令
    • kubectl set image rs rs名称 容器=镜像版本 -n ns名称

删除rs

  • 使用kubectl delete命令删除rs以及它管理的pod
    • kubectl delete rs rs名称 -n ns名称
  • 如果希望仅删除rs,但是保留pod,可以在使用kubectl delete命令时添加--cascade=false选项(不推荐)
    • kubectl delete rs rs名称 -n ns名称 --cascade=false
  • 使用yaml直接删除(推荐)
    • kubectl delete -f yaml文件名称

Deployment(deploy)

Deployment通过管理Rs来间接管理Pod

deoloy主要功能

  • 支持rs所有功能
  • 支持发布的停止、继续
  • 支持版本滚动更新和版本回退

yaml文件示例

扩缩容

参考rs扩缩容

镜像更新

deploy支持两种镜像更新策略:重建更新Recreate滚动更新RollingUpdate(默认) ,可以通过strategy选项配置

版本回退

deploy支持版本升级过程中的暂停、继续以及版本回退功能 版本升级相关命令kubectl rollout 支持选项:

  • status 显示当前升级状态
  • history 显示升级历史记录
  • pause 暂停版本升级过程
  • resume 继续已暂停的版本升级过程
  • restart 重启版本升级过程
  • undo 回滚到上一级版本(使用--to-revision=版本号 回滚到指定版本)

金丝雀发布

概念:一批新的pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧版本。然后再筛选一小部分的用户请求路由到新版本的pod应用,继续观察能够按照期望的方式运行。确定没问题后再继续完成余下的pod资源的滚动更新,否则,立即回滚更新操作。

命令示例: kubectl set image deploy pc-deployment nginx=nginx:1.17.2 -n dev && kubectl rollout pause deploy pc-deployment -n dev

删除deploy

kubectl delete -f deploy的yaml文件名称

Horizontal Pod Autoscaler(HPA)

HPA可以获取每个pod利用率,然后和HPA中定义的指标进行对比,同时计算出需要伸缩的具体值,最后实现pod数量的调整。HPA也属于k8s资源对象,它通过追踪分析目标pod的负载变化情况,来确定是否需要针对性地调整pod的副本数

示例pc-hpa.yaml:

DaemonSet(DS)

DS类型的控制器可以保证集群中的每一台(或者指定)节点上都运行一个副本,一般用于日志收集、节点监控等场景。也就是说,如果一个pod提供的功能是节点级别的(每个节点都需要且只需要一个),那么这类pod就适合用DS类型的控制器创建

DS控制器特点

  • 每当向集群中添加一个节点时,指定的pod副本也将添加到该节点上
  • 当节点从集群中移除时,pod也就被垃圾回收了

Job

job主要用于负责批量处理 短暂的一次性任务

Job特点

  • 当Job创建的pod执行成功结束时,job将记录成功结束的pod数量
  • 当成功结束的pod达到指定的数量时,job将完成执行

job资源清单文件:

Cronjob(CJ)

Cj控制器以job控制器资源为其管控对象,并借助Job控制器管理pod资源对象,job控制器定义的作业任务在其控制器资源创建之后便会立即执行,Cj可以在特定的时间点(反复的)去运行job任务

CJ资源清单文件:

  • 并发执行策略aoncurrencyPolicy选项(结合schedule)
    • Allow(默认):允许jobs并发运行
    • Forbid:禁止并发运行,如果上一次运行尚未完成,则跳过下一次运行
    • Replace:替换,取消当前正在运行的作业并用新作业替换

StatefulSet(sts)

待补充....

Service详解

kubernetes流量负载组件:

  • Service:四层路由的负载
  • Ingress:七层路由的负载

Service介绍

k8s提供的Service资源,会对提供同一个服务的多个pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务

Service只是一个概念,真正起作用的是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程,当创建Service的时候会通过api-server向etcd写入创建的service信息,而kube-proxy会基于监听的机制发现这种service的变动,然后它将最新的Service信息转换成对应的访问规则

kube-proxy目前支持三种工作模式

  • userspace模式
    • kube-proxy会为每一个Service创建一个监听端口,发向Cluster IP的请求被iptables规则重定向到kube-proxy监听的端口上,kube-proxy根据LB算法(Load Balance 负载均衡)选择一个提供服务的pod并和其建立链接,将请求转发到pod上
    • 该模式下,kube-proxy充当一个四层负载均衡器,由于kube-proxy运行在userspace中,在进行转发处理时会增加内核和用户空间之间的数据拷贝,虽然比较稳定,但效率较低
  • iptables模式
    • kube-proxy为service后端的每个pod创建对应的iptables规则,直接将发向ClusterIP的请求重定向到一个PodIP
    • 该模式下kube-proxy不承担四层负载均衡器的角色,只负责创建iptables规则。该模式的优点是较userspace模式效率更高,但是不能提供灵活LB策略,当后端pod不可用时也无法进行重试。
  • ipvs模式
    • kube-proxy监控pod的变化并创建相应的ipvs规则,ipvs相对iptables转发效率更高,且支持更多LB算法

Service类型

Service的资源清单文件

  • clusterIP 就是Service的ip地址
  • type:Service类型
    • ClusterIP:默认值,它是k8s系统自动分配的虚拟ip,只能在集群内部访问
    • NodePort:将Service通过指定的Node上的端口暴露给外部,可以在集群外部访问服务
    • LoadBalancer:使用外接负载均衡器完成到服务的负载分发,此模式需要外部云环境支持
    • ExternalName:将集群外部的服务引入集群内部,直接使用

Service使用

ClusterIP类型的Service

  • Endpoint

    • Endpoint是k8s中的一个资源对象,存储在etcd中,用来记录一个service对应的所有pod的访问地址,它是根据service配置文件中selector描述产生的
    • 一个service由一组pod组成,这些pod通过endpoints暴露出来,Endpoint是实现实际服务的端点集合,即:service和pod之间的联系是通过Endpoint实现的
  • 负载分发策略 对service的访问被分发到后端的pod,目前k8s提供两种负载分发策略

    • 默认使用kube-proxy策略,如:轮询(rr)
    • 基于客户端地址的会话保持模式,即来自同一个客户端发起的所有请求都会转发到固定的一个pod上,此模式需要在spec中添加 sessionAffinity: ClientIP 选项

HeadLiness类型的Service(无头服务)

在某些场景中,开发人员不希望使用Service提供的负载均衡策略,希望自己来控制,针对这种情况,k8s提供了Headliness Service,这类service不会分配ClusterIP,如果想要访问service,只能通过service的域名进行查询

  • 将yaml文件中的clusterIp设置为None,即可创建headliness service
  • 默认域名(可自定义配置):service名称.ns名称.svc.cluster.local

NodePort类型的Service

NodePort类型的Service能够将service暴露给集群外部使用,工作原理是将service的端口映射到Node的一个端口上,然后可通过NodeIP:NodePort来访问service

LoadBalancer类型的Service

LoadBalancer也是向外部暴露一个端口,在集群外部再做一个负载均衡设备,这个设备需要外部环境支持,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中

ExternalName类型的Service

ExternalName类型的Service用于引入集群外部的服务,通过 externalName 属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务

Ingress介绍

Service对集群之外暴露服务的主要方式有两种:NodePort和LoadBalancer,但这两种方式都有一定缺点:

  • NodePort方式会占用很多集群机器的端口,当集群服务变多时,这个缺点越发明显
  • LB方式的每个Service都需要一个LB,浪费、麻烦并且需要k8s之外的设备支持

k8s提供的Ingress资源对象,只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求。Ingress相当于一个7层的负载均衡器,是k8s反向代理的抽象,工作原理类似于Nginx,可以理解成在Ingress里建立了诸多映射规则,Ingress Controller通过监听这些配置规则并转换成Nginx的配置,然后对外部提供服务。

核心概念:

  • Ingress:k8s中的一个资源对象,作用是定义请求如何转发到Service的规则
  • Ingress Controller:具体实现反向代理及负载均衡的程序,对Ingress定义的规则进行解析,根据配置的规则实现请求转发,实现的方式有Nginx、Haproxy等

Ingress的工作原理(以Nginx为例)

  1. 用户编写Ingress规则,说明哪个域名对应k8s集群中的哪个Servcice
  2. Ingress Controller动态感知Ingress服务规则的变化,然后生成一段对应的Nginx配置
  3. Ingress Controller会将生成的Nginx配置写入一个运行着的Nginx服务中,并动态更新
  4. 到此刻,真正工作的是Nginx,内部配置了用户定义的请求转发规则

数据存储

Volume(存储卷)是Pod中能够被多个容器访问的共享目录。它被定义在Pod上,然后被一个Pod里的多个容器挂载到具体的文件目录下。k8s通过Volume实现同一个Pod中不同容器之间的数据共享 以及数据的持久化存储。Volume的生命周期不与Pod中单个容器的生命周期相关,当容器终止或者重启时,Volume中的数据不会丢失。

基本存储

EmptyDir

EmptyDir是最基础的Volume类型,一个EmptyDir就是Host上的一个空目录

EmptyDir是在Pod被分配到Node时创建的,初始内容为空,并且无须指定宿主机上对应的目录文件,因为k8s会自动分配一个目录,当Pod销毁时,EmptyDir中的数据也会被永久删除。

EmptyDir用途:

  • 临时空间,例如用于某些应用程序运行时所需的临时目录,且无须永久保留
  • 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)

HostPath

Hostpath是将Node主机中一个实际目录挂载到Pod中,供容器使用,即使Pod销毁了,但是数据依旧可以存在Node主机上

NFS

NFS是一个网络文件存储系统,可以搭建一台NFS服务器,然后将Pod中的存储直接连接到NFS系统上,这样的话,无论Pod在节点上怎么转移,只要Node跟NFS的对接没有问题,数据就可成功访问

高级存储

pv和pvc

PV(Persistent Volume)持久化卷,是对底层的共享存储的一种抽象。一般情况下PV由k8s管理员进行创建和配置,它与底层集体具体的共享存储技术有关,并通过插件完成与共享存储的对接

PVC(Persistent Volume Claim)持久卷声明,是用户对于存储需求的一种声明。PVC其实就是用户向k8s系统发出的一种资源需求申请。

pv

PV是存储资源的抽象,资源清单文件:

参数说明

  • 存储类型
    • 底层实际存储的类型,k8s支持多种存储类型,每种存储类型的配置有所差异
  • 存储能力(capacity)
    • 目前只支持存储空间的设置(storage = 1Gi),未来可能会加入IOPS、吞吐量等指标的配置
  • 访问模式(accessModes)
    • ReadWriteOnce(RWO):读写权限,但是只能被单节点挂载
    • ReadOnlyMany(ROX):只读权限,可以被多个节点挂载
    • ReadWriteMany(RWX):读写权限,可以被多个节点挂载
  • 回收策略(persistentVolumeReclaimPolicy)
    • Retain(保留) 保留数据,需要管理员手工清理
    • Recycle(回收)清除PV中的数据,效果相当于执行 rm -rf /the volume/
    • Delete(删除) 与PV相连的后端存储完成volume的删除操作,常见于云服务商的存储服务
  • 存储类别(storageClassName)
    • 具有特定类别的pv只能与请求了该类比额的PVC进行绑定
    • 未设定类别的PV则只能与不请求任何类别的PVC进行绑定
  • 状态:PV的生命周期可能处于4种不同阶段
    • Available(可用):表示可用状态,还未被任何PVC绑定
    • Bound(已绑定):表示PV已经被PVC绑定
    • Released(已释放):表示PVC被删除,但是资源还未被集群重新声明
    • Failed(失败):表示该PV的自动回收失败

pvc

PVC是资源的申请,用来声明对存储空间、访客模式、存储类别需求信息,资源清单文件如下

参数说明:

  • 访问模式 accessModes:描述用户应用对存储资源的访问权限
  • 选择条件 selector:通过Label Selector的设置,可使PVC对于系统中已存在的PV进行筛选
  • 存储类别 storageClassName:PVC在定义时可以设定需要的后端存储的类别,只有设置了该class的pv才能被系统选出
  • 资源请求 resources:描述对存储资源的请求

生命周期

PVC和PV是一一对应的,PVC和PV之间的相互作用遵循以下生命周期:

  • 资源供应:管理员手动创建底层存储和PV

  • 资源绑定:用户创建PVC,k8s负责根据PVC的声明(主要是对存储资源的请求)去寻找PV,并绑定

    • 一旦找到,就将该pv与用户定义的PVC进行绑定,用户的应用就可以使用这个pvc
    • 如果找不到,pvc就会无限处于Pending状态,直到等到系统管理员创建了一个符合其要求的PV
    • pv一旦绑定到某个pvc,就会被这个pvc独占,不能再与其它pvc进行绑定
  • 资源使用:用户可在pod中像volume一样使用pvc

    • pod使用volume的定义,将pvc挂载到容器内的某个路径进行使用
  • 资源释放:用户删除pvc来释放pv

    • 当存储资源使用完毕后,用户可以删除pvc,与该pvc绑定的pv将会被标记为"已释放",但还不能立刻与其它pvc进行绑定。通过之前pvc写入的数据可能还被留在存储设备上,只有清除之后该pv才能再次使用。
  • 资源回收:k8s根据pv设置的回收策略进行资源回收

    • 对于pv,管理员可以设定回收策略,用于设置与之绑定的pvc释放资源之后如何处理遗留数据的问题。只有pv的存储空间完成回收,才能供新的pvc绑定和使用。

配置存储

ConfigMap

configmap是一种比较特殊的存储卷,主要用来存储配置信息

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
    name: configmap
    namespace: dev
data:
    info: |
      username: admin
      password: 123456

使用时,每个configmap都映射成一个目录,key(示例中的info)映射为文件,value映射为文件中的内容。如果更新configmap的内容,容器中的值也会动态更新

Secret

Secret和ConfigMap类似,但是主要用于存储敏感信息,比如密码、密钥、证书等

安全认证

访问控制概述

k8s是一个分布式集群管理工具,保证集群的安全性需要保证对k8s的各种客户端进行认证鉴权操作

客户端

在k8s集群中,客户端分为两类:

  • User Account:独立于k8s之外的其它服务管理的用户账号
  • Service Account:k8s管理的账号,用于Pod中的服务进程在访问k8s时提供身份标识

认证、授权与准入控制

ApiServicer是访问及管理资源对象的唯一入口。任何一个请求访问ApiServer,都经过下面三个流程:

  • Authentication(认证):身份鉴别,只有正确的账号才能通过认证
  • Authorization(授权):判断用户是否有权限对访问的资源执行特定的动作
  • Admission Control(准入控制):用于补充授权机制以实现更加精细的访问控制功能

认证管理

识别并认证客户端身份,主要有3种客户端身份认证方式:

  • HTTP Base认证: 通过用户名+密码方式认证(安全性最低)
  • HTTP Token认证:通过一个Token来识别合法用户
  • HTTPS证书认证:基于CA根证书签名的双向数字证书认证方式(安全性最高)

授权管理

认证成功之后会进行授权,APIServer支持的授权策略有:

  • AlwaysDeny:拒绝所有请求,一般用于测试
  • AlwaysAllow:允许接收所有请求,相当于集群不需要授权流程(k8s默认策略)
  • ABAC: 基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制
  • Webhook:通过调用外部REST服务对用户进行授权
  • Node:专用模式,对k8s发出的请求进行访问控制
  • RBAC (Role-Based Access Control):基于角色的访问控制(kubeadm安装方式下的默认项)
    • 即:给哪些对象授予了哪些权限 ,涉及内容:
      • 对象:User、Groups、ServiceAccount
      • 角色:代表一组定义在资源上的可操作动作(权限)的集合
      • 绑定:将定义好的角色跟用户绑定在一起

RBAC引入4个顶级资源对象:

  • Role、ClusterRole:角色,用于指定一组权限
  • RoleBinding、ClusterRoleBinding:角色绑定,用于将角色(权限)赋给对象

Role、ClusterRole

  • 一个角色就是一组权限的集合,这里的权限都是许可形式(白名单,不会拥有未许可的权限)

rules中的参数:

  • apiGroups:支持的api组列表

"","apps","autoscaling","batch"

  • resources: 支持的资源对象列表

"services","endpoints","pods","secrets","configmaps","crontabs","deployments","jobs","nodes","rolebindings","clusterroles","daemonsets","replicasets","statefulsets","horizontalpodautoscalers","replicationcontrollers","cronjobs"

  • verbs:对资源对象的操作方法列表

"get","list","watch","create","update","patch","delete","exec"

RoleBinding、ClusterRoleBinding

  • 角色绑定用来把一个角色绑定到一个目标对象上,绑定目标可以是User、Group或者ServiceAccount

特殊用法:RoleBinding引用ClusterRole进行授权

  • RoleBinding引用ClusterRole,对属于统一命名空间内ClusterRole定义的资源主体进行授权

集群管理员为集群范围预定义好一组角色(clusterRole),然后在多个命名空间中重复使用这些clusterRole。这样可以大幅提高授权工作效率,同时使得各命名空间下的基础性授权规则与使用体验保持一致

准入控制

  • 通过认证和授权之后,还需通过准入控制处理通过之后,apiserver才会处理这个请求
  • 准入控制是一个可配置的控制器列表,可以通过在Api-server上通过命令行设置选择执行哪些准入控制器
bash 复制代码
--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount

只有当所有准入控制器都检查通过以后,apiserver才执行请求,否则返回拒绝。可配置的admission Control准入控制在此不再展开

DashBoard

DashBoard是k8s开发的一个基于web的用户页面,用户可以使用Dashboard部署容器化应用、监控应用状态、执行故障排查以及管理k8s中的各种资源。

相关推荐
wenyue11215 小时前
Enhancing K8s Gateway API with Easegress Without Changing a Single Line of Code
容器·kubernetes·gateway
sxy1993sxy201813 小时前
k8s rainbond centos7/win10 -20241124
云原生·容器·kubernetes
Python私教16 小时前
Python 使用 Token 认证方案连接 Kubernetes (k8s) 的详细过程
开发语言·python·kubernetes
风霜不见闲沉月17 小时前
k8s网络服务
linux·容器·kubernetes
夏沫的梦1 天前
kubernetes起源与介绍
kubernetes
胡八一2 天前
解决k8s拉取私有镜像401 Unauthorized 问题
云原生·容器·kubernetes
筑梦之路2 天前
银河麒麟v10 x86架构二进制方式kubeadm+docker+cri-docker搭建k8s集群(证书有效期100年) —— 筑梦之路
docker·容器·kubernetes
it噩梦2 天前
使用EFK收集k8s日志
容器·kubernetes
条纹布鲁斯2 天前
dockerdsktop修改安装路径/k8s部署wordpress和ubuntu
docker·kubernetes
登云时刻2 天前
Kubernetes集群外连接redis集群和使用redis-shake工具迁移数据(一)
redis·kubernetes·bootstrap