K8S
2021-06-09 11:49:48 8 举报
AI智能生成
K8S 各功能及其原理的思维导图
作者其他创作
大纲/内容
K8S
Master
kube-apiserver
kube-scheduler
kube-controller-manager
控制器
控制循环
实际状态
期望状态
两个状态对比根据对比的结果来做操作
yaml
控制器定义
podTemplate
Node
kubelet
CRI
container runtime
OCI
docker
Device Plugin
CNI
依赖 kubernetes-cni 包
第一类,Main 插件,它是用来创建具体网络设备的二进制文件
第二类,IPAM(IP Address Management)插件,它是负责分配 IP 地址的二进制文件
第三类,由 CNI 社区维护的内置 CNI 插件
CSI
容器
容器镜像
容器运行时
namespace
network namespace
pid namespce
mount namespace
Cgroup
CPU
Mem
IO
rootfs
kubeadm非生产环境
kubelet 部署到宿主机
其他的 K8S 组件用容器部署
kubeadm init
Preflight Checks
生成其他组件访问 apiserver 的配置文件路径 /etc/kubernetes/xxx.conf
为 Master 组件生成 Pod 配置文件
为集群生成一个 bootstrap token
将 ca.crt 等 Master 节点的重要信息,通过 ConfigMap 的方式保存在 Etcd 当中,供后续部署 Node 节点使用
安装默认插件
kubeadm join
拿到保存在 ConfigMap 中的 cluster-info
kubelet 以“安全模式”连接到 apiserver 上
kubeadm init --config kubeadm.yaml
编排和作业管理
容器对象
Pod
第一个容器 Infra:k8s.gcr.io/pause
其他容器-net=k8s.gcr.io/pause
同一个 network namespace
同一个 Volume
探针 probe
Pod 生命周期的变化Pod API 对象 status 部分
pod.status.phasePod 的当前状态
Pending
Running
Succeeded
Failed
Unknown
Conditions
PodScheduled
Ready
Initialized
Unschedulable
yaml 配置
Pod 重要字段
NodeSelector
NodeName
HostAliases
shareProcessNamespace
namespace 级别的参数都是 pod 级别
restartPolicy
Always
OnFailure
Never
Container 重要字段
ImagePullPolicy
Lifecycle
控制器对象
Deployment
操作逻辑
从 ETCD 获取携带指定标签的 Pod 的数量
Deployment 对象 Replicas 的值
根据两个值对比的结果新增更新或者删除 Pod
操作对象:ReplicaSet 控制器
管理的 Pod 的 ownerReference 是 ReplicaSet
n 副本是 Pod 副本个数为 n 的 ReplicaSet 控制器
创建的 ReplicaSet Pod 的名称是deployment 名称 + 随机字符串(pod-template-hash)
创建的 ReplicaSet 管理的 Pod 名称带有随机字符串(pod-template-hash)
可配置的多版本方便回滚
滚动更新(rolling update)
修改 Pod 模板触发更新
kubectl edit 指令编辑 Etcd 里的 API 对象
修改 Pod 使用的镜像kubectl set image
vim 修改 yaml,然后 kubectl replace -f xxx.yaml
vim 修改 yaml,然后 kubectl apply -f xxx.yaml
...
策略 RollingUpdateStrategy
滚动更新过程
成功的滚动更新
修改 Pod 模板
保存更改
中间状态
创建新的 ReplicaSet A
A 新增一个新的 Pod
旧的 ReplicaSet 删除一个副本
最终状态
ReplicaSet A 副本数为 n
旧的 ReplicaSet 的副本数为 0
失败的滚动更新
修改 Pod 信息
新增了 ReplicaSet 和允许个数的 Pod
原 ReplicaSet 删除了允许个数的 Pod
新增的 ReplicaSet 中的 Pod 没有 ready旧的 ReplicaSet 中的 Pod 已经少了更新失败,自动停止更新
回滚kubectl rollout undo
命令
水平扩展kubectl scale deployment nginx-deployment --replicas=4
查看状态kubectl get deployments
实时查看状态kubectl rollout status deployment/nginx-deployment
记录状态--record
重要参数
保留 ReplicaSet 的“历史版本”个数spec.revisionHistoryLimit
restartPolicy 只允许被设置为 Always
ReplicaSet
查看 ReplicaSet 列表kubectl get rs
DaemonSet
工作原理
从 ECTD 获取 Node 列表
遍历所有 Node 查看是否有指定标签的 Pod
根据每个 Node 上的结果做相应操作
没有对应的 Pod,去创建
Pod 数量大于 1,删除多余 Pod
有且只有一个对应的 Pod,正常
特点
运行时机可能比 k8s 集群早
与 Deployment 相似,只是没有副本
使用 selector 管理带指定标签的 pod
可以进行版本管理
管理对象是 Pod
如何在指定 Node 上创建新的 Pod
nodeSelector(将要废弃)
nodeAffinity
DaemonSet 在向 k8s 发起请求之前修改模板生成的 pod 对象
自动在对象里加上 nodeAffinity 定义绑定的 node 就是正在遍历的 node
tolerations
实例
创建 DaemonSet 对象
查看状态
查看 ds 的版本
更新容器镜像的版本
查看滚动更新的过程
回滚到指定版本
StatefulSet
拓扑状态
部署
代理 Service - Nginx
应用 StatefulSet - Nginx
多副本应用按 0-n 的顺序启动
验证
DNS 验证
创建一个客户端的 Pod
在客户端 Pod 中查看 DNS
删除应用再次验证
执行删除操作
观察多副本 Pod 的变化
再次 DNS 验证
存储状态
部署 StatefulSet - Nginx
在 Pod 的 Volume 目录中写入数据
请求 web 查看信息
删除 Pod
自动恢复 Pod
再次请求 web 查看信息
数据库主从
依赖 Headless Service
当使用存储时,自动为每个 Pod 创建同样编号的 PVC
状态管理
存储状态持久化的原理
Pod 删除之后,PVC 和 PV 仍然存在
StatefulSet 创建新的 Pod,名称不变
绑定 PVC 时,会发现有已经存在的 PVC,就会直接绑定原来的 PVC
拓扑状态在整个生命周期不变
滚动更新
修改模板触发更新
kubectl patch
kubectl edit
与编号相反的顺序逐一更新
更新控制
spec.updateStrategy.rollingUpdate 的 partition 字段
有状态应用
可多副本
CronJob
concurrencyPolicy
Allow
Forbid
Replace
spec.startingDeadlineSeconds
Job
参数
spec.selector非必须,会自动生成
spec.restartPolicy 只能定义为 Never 和 OnFailure
spec.backoffLimit新建 Pod 的次数限制
spec.activeDeadlineSeconds限制 Pod 运行时间
spec.parallelism并发数
spec.completions至少要完成的 Pod 数目
无并发实例
编辑 yaml
创建 Job
查看 job 对象
查看 Pod 状态
查看 Pod 日志获得计算结果
多并发实例
编译 yaml
创建 Job 对象
查看 Job 状态
控制对象是 Pod
调谐
在 Running 状态 Pod 的数目
成功退出的 Pod 的数目
parallelism 参数的值
completions 参数的值
三种常用使用姿势
外部管理器 + Job 模板
Job 模板
外部管理器
创建 job
固定任务数目的并行 Job
指定并行度(parallelism)
内置控制器 Volume Controller运行在 master 节点
PersistentVolumeController
AttachDetachController
VolumeManagerReconcilerkubelet 的一部分
Operator
其他控制器 API 对象
ControllerRevision
查看某个 controller 对应的 ControllerRevision
查看 ControllerRevision 对象
CRD
添加 Network 的 API 资源类型
名为 Network 的 CR 对象的 yaml 文件example-network.yaml
编写 CRD 使得 k8s 认识 Network 对象network.yaml
编写代码使 k8s 认识 Network 中的 cidr 和 gateway
代码
我要在 GOPATH 下创建一个结构如下的项目
pkg/apis/samplecrd 下创建 register.go 文件放置后面要用到的全局变量
pkg/apis/samplecrd 目录下添加 doc.go 文件Golang 的文档源文件
需要添加 types.go 文件
编写 pkg/apis/samplecrd/v1/register.go 文件
使用 k8s 代码生成工具为定义的 Network 资源类型生成 clientset、informer 和 lister
clientset
informer 原理
lister
使用 network.yaml 创建 Network 对象的 CRD
使用 example-network.yaml 创建 Network 对象
自定义控制器
编写 Network 自定义控制器
编写自定义控制器的 main 函数
创建 client
kubeClient
networkClient
创建 InformerFactory(即:networkInformerFactory)的工厂使用它生成一个 Network 对象的 Informer,传递给控制器
main 函数启动上述的 Informer然后执行 controller.Run 启动自定义控制器
编写控制器的定义
编写这个自定义控制器的业务逻辑
运行自定义控制器
编译并启动这个项目
创建 Network 对象的 CRD
Network 对象的增删改查操作
创建一个 Network 对象
修改 Network 对象
删掉 Network 对象
自定义控制器工作原理
初始化 API 对象自动在 API 对象中添加定义的信息
InitializerDynamic Admission Control
示例
应用 Pod
Initializer
通过 ConfigMap 定义初始化新增的配置
编写 Initializer 代码并部署 Pod
伪代码
操作代码示例
指定对什么资源进行初始化
Pod 中指定使用哪个 Initializer
PodPreset
声明式 API
声明式 API 命令
kubectl apply
kubectl set
非声明式 API命令式操作
kubectl create
kubectl replace
声明式 API 和非声明式的区别
API 对象
非声明式 API 是直接修改替换原 API 对象
声明式 API 是执行的对原 API 对象的 PATCH 操作
在响应命令式请求时,一次只能处理一个写请求,不然可能会产生冲突
在处理声明式请求时,一次能处理多个写操作,并且具备 Merge 功能
k8s 对 API 对象的解析
Kubernetes 会匹配 API 对象的组
Kubernetes 进一步匹配到 API 对象的版本号
Kubernetes 匹配 API 对象的资源类型
解析和处理示例
发起创建 CronJob 的 POST 请求YAML 的信息被提交给 APIServer
API server 过滤请求完成前置性工作
授权
超时处理
审计
进入 MUX 和 Routes 流程
根据这个 CronJob 类型定义使用用户提交的 YAML 文件里的字段创建 CronJob 对象
APIServer 会先后进行 Admission() 和 Validation()
Admission 初始化添加一些写好的配置信息
Validation 验证 API 对象被验证过的对象保存到 Register 数据结构中
APIServer 把验证过的 API 对象转换成用户最初提交的版本进行序列化操作调用 Etcd 的 API 把它保存起来。
访问控制 RBAC
用户权限
外部用户权限
Namespaced 对象
Role
Subject
RoleBinding
非 Namespaced 对象(Non-namespaced)
ClusterRole
ClusterRoleBinding
内置用户权限:ServiceAccount 分配权限
ServiceAccount
创建实例
用户组
外部用户组
内置用户组
作用于 namespace
作用于整个系统
内置 role
system:kube-scheduler
cluster-admin
admin
edit
view
持久化存储
Projected Volume
Secret
ConfigMap
Downward API
ServiceAccountToken
Persistent Volume Claim(PVC)
声明 PVC
在应用中使用声明的 PVC
指定 storageClassName
Pod 中使用已创建的 PVC
Persistent Volume(PV)Static Provisioning
CEPH RBD
NFS
storageClassDynamic Provisioning
Local Persistent Volume
一个 PV 一块盘
在调度的时候考虑 Volume 分布
删除本地 PV
手动删除
删除使用这个 PV 的 Pod
从宿主机移除本地磁盘(比如,umount 它)
删除 PVC
删除 PV
Static Provisioner
持久化 Volume 原理
挂载两阶段处理
第一阶段 Attach: AttachDetachController
为当前 Pod 创建 Volume 目录
挂载远程存储
第二阶段 Mount:VolumeManagerReconciler
格式化磁盘
挂载到 Volume
kubelet 把 volume 传递给 docker
卸载两阶段处理
第一阶段 Unmount
第二阶段 Dettach
controller
动态和静态 PV 使用
Volume Controller运行在 master 节点
本地 PV 使用
VolumeBindingChecker
静态存储
声明 NFS PV
声明使用上述 NFS PV 的 PVC
创建使用上述 PVC 的 Pod
动态存储
声明 StorageClass 对象
创建 sc 对象
PVC 中指定 sc
本地存储
声明本地 PV
创建本地 PV
创建 StorageClass 对象
声明 PVC 对象
创建 PVC 对象
声明一个 Pod 对象
创建 Pod 对象
Pod 中创建测试文件
物理机上查看目录下内容
重新创建这个 Pod
网络
容器网络
网桥
docker 网桥docker0交换机作用
k8s 网桥通过 CNI 接口维护设备名为 cni0 的 CNI 网桥
虚拟设备 Veth Pair
一端在 docker 内部,作为 eth0 网卡
另一端在宿主机上,作为一个插在 docker0 或其他网桥上的虚拟网卡
K8SOverlay Network(覆盖网络)
插件
Flannel
三种模式
UDP
VXLAN
VTEP
host-gw
K8S 上使用 Flannel 插件
宿主机上安装 flanneld配置文件路径 /etc/cni/net.d/10-flannel.conflist
Docker 的 dockershim 加载 CNI 配置
Pod 是怎么使用 CNI 插件的(网桥方式)
dockershim 调用 docker api 创建 infra 容器
执行 SetUpPod 操作
为 CNI 插件准备参数分两部分
由 dockershim 设置的一组 CNI 环境变量
dockershim 从 CNI 配置文件里加载到的、默认插件的配置信息
配置信息
调用 CNI 插件为 Infra 容器配置网络
Flannel CNI 对 dockershim 传来的 Network Configuration 进行补充
Flannel CNI 调用 CNI bridge 插件,即执行:/opt/cni/bin/bridge
将容器加入到 CNI 网络里
CNI bridge 插件会在宿主机上检查 CNI 网桥是否存在
CNI bridge 通过 Network Namespace 文件,进入到 Network Namespace 里面,创建一对 Veth Pair 设备
另一端是 容器中的 eth0
把 Veth Pair 的其中一端 vethb4963f3,“移动”到宿主机上
CNI bridge 把 vethb4963f3 设备连接在 CNI 网桥上
CNI bridge 还会为 vethb4963f3 设置 Hairpin Mode(发夹模式)
CNI bridge 调用 CNI ipam 插件,从 ipam.subnet 字段规定的网段为容器分配一个可用的 IP 地址
CNI bridge 把这个 IP 地址添加在容器的 eth0 网卡上,同时为容器设置默认路由
CNI bridge 为 CNI 网桥添加 IP 地址
CNI 插件把容器的 IP 地址等信息返回给 dockershim,被 kubelet 添加到 Pod 的 Status 字段
Calico CNI
注意事项
k8s 处理网络的逻辑不在 kubelet,而是在 CRI
K8S 不支持多个 CNI 混用如果配置目录中有多个,会按字母顺序加载第一个插件
网络隔离
NetworkPolicy 对象
NetworkPolicy Controller
实现原理
被请求
FORWARD负责“拦截”对被隔离 Pod 的访问请求
FORWARD将拦截的请求转到其他规则上KUBE-POD-SPECIFIC-FW-CHAIN
KUBE-POD-SPECIFIC-FW-CHAIN
将请求转发到 KUBE-NWPLCY-CHAIN来判断是否被允许
第二条规则将上述不匹配的请求拒绝
请求
实现网络隔离的插件
Calico
Weave
kube-router
没有实现网络隔离的插件
服务发现/代理Service
纯 iptables 的 kube-proxy
K8S 内
通过 VIP 访问
通过 DNS 访问
ClusterIP 模式/ Normal Service访问 DNS 解析到 VIP
Service 的 Endpoints
访问 service
Headless Service
Headless Service访问 DNS 直接解析到后端 Pod 的地址
指定 hostname 的 Pod
原理以 ClusterIP 模式为例
提交 Service 对象到 apiserverService 的 informer 感知到新增的 Service 对象
Informer 在宿主机创建 iptables 规则 KUBE-SERVICES该规则会把匹配的请求转到 KUBE-SVC-NWV5X2332I4OT4T3 链
KUBE-SVC-NWV5X2332I4OT4T3 链规则
规则 1,将请求转发到 KUBE-SEP-WNBA2IHDGP2BOBGZ 链,对应第一个 Pod
规则 2,将请求转发到 KUBE-SEP-X3P2623AGDH6CDF3 链,对应第二个 Pod
规则 3,将请求转发到 KUBE-SEP-57KPRZ3JQVENLNBR 链,对应第三个 Pod
从集群外访问 K8S 内服务
NodePort
从外部访问
原理
在 IP 包离开宿主机发往目的 Pod 时,对这个 IP 包做一次 SNAT 操作
与 ClusterIP 模式类似在宿主机添加一条 iptables 规则 KUBE-NODEPORTS改规则将匹配的请求转发到 KUBE-SVC-67RL4FN6JRUPOJYM 链
span style=\
ExternalName
externalIPs
使用 IPVS 的 kube-proxy
创建 Service 会创建一个虚拟网卡并分配 IP 地址
通过 IPVS 为三个后端的 Pod 设置转发和负载均衡
问题排查
集群的 DNS 异常
检查 Kubernetes Master 节点 Service DNS
Service 本身的配置问题
Service 是否有 Endpoints
确认 kube-proxy 是否在正确运行
查看宿主机上的 iptables
Pod 没办法通过 Service 访问到自己
负载均衡Ingress
场景
Ingress 对象
资源管理
管理对象 Pod
资源类型
内存
资源配置
limits
requests
cpuset
QoS 模型
级别
Guaranteed
Burstable
BestEffort
应用场景
模式
Soft
Hard
Eviction
到了阈值进入 MemoryPressure 或者 DiskPressure 状态,从而避免新的 Pod 被调度到这台宿主机上
挑选 Pod 删除
收藏
收藏
0 条评论
回复 删除
下一页