环境搭建
资源管理
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:暴露的端口号
- 获取podIP
- 删除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名称
- 查询当前ns下的pod控制器:
- 如果当前pod是由pod控制器创建的,则若要删除pod,必须删除pod控制器:
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创建过程
- 用户通过kubectl或其它api客户端提交需要创建的pod信息给apiServer
- apiServer开始生成pod对象信息,并将信息存入etcd,然后返回确认信息至客户端
- apiServer开始反映etcd中的pod对象的变化,其他组件使用watch机制来跟踪检查apiServer上的变动
- scheduler发现有新的pod对象要创建,开始为pod分配主机并将结果信息更新至apiServer
- node节点上的kubelet发现有pod调度过来,尝试调用docker启动容器,并将结果回送至apiServer
- apiServer将接收到的pod状态信息存入etcd中
pod终止过程
- 用户向apiServer发送删除pod对象的命令
- apiServer中的pod对象信息会随着时间的推移而更新,在宽限期内(默认30s),pod被视为dead
- 将对象标记为terminating状态([terminating不是pod阶段之一](Pod 的生命周期 | Kubernetes))
- kubelet在监控到pod对象转为terminating状态的同时启动pod关闭过程
- 端点控制器监控到pod对象的关闭行为时将其从所有匹配到此端点的service资源的端点列表中移除
- 如果当前pod对象定义了perStop钩子处理器,则在其标记为terminating后即会以同步的方式启动执行
- pod对象中的容器进程收到停止信号
- 宽限期结束后,若pod中还存在仍在运行的进程,则pod对象会收到立即终止的信号
- kubelet请求apiServer将此pod资源的宽限期设置为0从而完成删除操作,此时pod对用户已不可见
初始化容器
初始化容器是在pod的主容器启动之前要运行的容器,主要做一些主容器的前置工作,具有两大特征:
- 初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernates需要重启它直至成功完成
- 初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面一个才能运行
钩子函数
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为例)
- 用户编写Ingress规则,说明哪个域名对应k8s集群中的哪个Servcice
- Ingress Controller动态感知Ingress服务规则的变化,然后生成一段对应的Nginx配置
- Ingress Controller会将生成的Nginx配置写入一个运行着的Nginx服务中,并动态更新
- 到此刻,真正工作的是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中的各种资源。