1、k8s架构
kubernetes整体架构
etcd介绍
kube-apiserver
kube-scheduler
kube-controller
kubelet
kube-proxy
kubectl get pod -n {namespace} {pod-name} -o yaml
容器的自动化部署
微服务架构
扩缩容
1.1、kubernetes基本概念
pod 实列
replicaSet 创建副本数量,添加了label标签功能
1.2、kubernetes核心组件
kubelet : 负责pod的整个生命周期
kube-proxy : 负责接收来自k8s-api请求,负责把请求的数据通过api写入到etcd中存储
kube-controller-manager: 控制器负责控制pod创建的请求
kube-apiserver: 负责收集客户请求,转发请求到kube-proxy和etcd
kube-scheduler: 负责调度实列到具体的node节点
etcd : 负责接手API发送的请求并保存对应集群数据
容器运行时: 提供容器运行时的环境,常用的有docker
master节点: 提供整个k8s平台的管理中心
node节点: 为k8s的工作节点,负责接收master的工作指令,并用指定的命令创建与销毁pod实列
1.3、etcd
etcd : 一个分布式的 可靠的key-value存储系统
1.4、api server
api server : 提供集群管理的接口
提供资源配置控制的入口
提供一定的集群安全机制
提供其他模块之间数据交互和通信的枢纽
认证(Authentication) :
APIServer需要认证发送请求的客户端的身份是否合法。一个集群可以同时配置多种认证方式,只要其中任意一个方式认证通过即可。
api server 认证流程:
base认证
token认证
证书认证
1.4.1、api server http base认证
Base认证:把用户名和密码信息用BASE64算法进行编码后的字符串放在HTTP Request中的Authorization头里发送给服务器,服务端在收到后进行解码,获取用户名和密码,然后进行用户身份鉴权。
基本认证: basic-auth
--basic-auth-file=/path/to/basic-auth.csv
在basic-auth.csv中拥有以列为单位的认证信息,格式为password,username,uid
列:
passwd, kinderao,1
password2, test, 2
1.4.2、token认证:
Token认证:每个Token对应一个用户名,存储在APIServer能访问的一个文件中。当客户端发起API调用请求时,需要在HTTP Header里放入Token,这样一来,APl Server就能识别合法用户和非法用户了。
Token认证: token-auth
--token-auth-file=/path/to/token-auth.csv
在token-auth.csv中拥有以列为单位的认证信息,格式为token,username,uid
token,kinderao,1
token2,kinderao2,2
1.4.3、api -server证书认证
在使用证书认证之前首先需要申请证书,证书可以通过权威CA来申请,也可以通过自签证书,不过部署kubernetes的大多数环境都是内网环境,所以更多的还是使用的是自签证书。
在Kubernetes的组件之间进行通信时,数字证书的验证是在协议层面通过TLS完成的, Kubernetes采用双向TLS认证方式进行认证,除了客户端需要验证服务器的证书,服务器也要通过客户端证书验证客户端的身份。
k8s : 自签证书
TLS : 客户端和服务端都需要有证书
1.4.4、api -server授权
授权(Authorization)就是授予不同用户不同的访问权限,通过授权策略来决定一个API调用是否合法。APIServer目前支持以下几种授权策略,通过APIServer的启动参数“-authorization-mode”设置,常用的主要有以下几种授权方式:
AlwaysDeny: 表示拒绝所有的请求,该配置一般用于测试
AlwaysAllow: 表示接收所有请求,如果集群不需要授权,则可以采取这个策略。
ABAC: 基于属性的访问控制,表示基于配置的授权规则去匹配用户请求,判断是否有权限。
api server本地需要要有一个json格式的文件,文件内记录了用户的权限,apiserver基于文件查看是否有授权的权限
RBAC: 基于角色的访问控制,允许管理员通过api动态配置授权策略。
设定一个角色,用户和角色关联在一起,授权检查
当配置多个授权模块时,会按顺序检查每个模块,如果有任何授权模块验证通过,则继续执行下一步的请求。如果所有模块拒绝,则该请求授权失败。
可以选择多个授权模块。如果其中一种模式是AlwaysAllow,则覆盖其他模式,并允许所有的API请求。
1.4.5、api server准入
准入控制(Admission Control)在授权后对请求做进一步的验证或添加默认参数。不同于授权和认证只关心请求的用户和操作,准入控制还处理请求的内容,并且仅对创建、更新、删除或连接(如代理)等有效,而对读操作无效。
在kubernetes APIServer中有一个参数: admission_control它的值为一串用逗号连接的有序的准入模块列表,设置后,就可在对象被操作前执行一定顺序的准入模块调用。请求需要通过所有准入模块的校验才算通过。
admission_control :可以接入多个准入模块,多个模块校验后才能准入
AlwaysPulllmages: 总是拉取最新镜像。要求系统每次启动容器前都要用密钥去重新下载镜像。增强node上下载的镜像的安全性。
ResourceQuota:限制Pod的请求以确保Namespace上的资源配额不会超标,作用于Namespace。
LimitRanger:需要在namespace中创建一个LimitRange对象,确保请求符合LimitRange对象里的资源限制,也可以会为没有设置资源请求的Pod设置默认的资源请求。
NamespaceLifecycle:当尝试在一个不存在namespace中创建资源对象时,拒绝该请求,并拒绝删除kube-system、default和kube-public这三个命名空间
1.4.6、api-5个顶层元素
Kubernetes APl是集群系统中的重要组成部分,Kubernetes中各种资源(对象)的数据通过该API接口被提交到后端的持久化存储(etcd)中,Kubernetes集群中的各部件之间通过该API接口实现解耦合,同时Kubernetes集群中一个重要且便捷的管理工具kubectl也是通过访问该API接口实现其强大的管理功能的。
API举例: /api/v1/namespaces/{namespace}/pods
Kubernetes API的顶层元素主要有以下五类:
1) kind:表明资源的类别
2) apiVersion: apiVersion表明API的版本号。
3) Metadata是资源对象的元数据定义,是集合类的元素类型,包含一组由不同名称定义的属性,主要包含namespace、name等字段。
4) spec: spec是集合类的元素类型,用户对需要管理的对象进行详细描述的主体部分都在spec里给出,它会被Kubernetes持久化到etcd中保存,系统通过spec的描述来创建或更新对象,以达到用户期望的对象运行状态。spec的内容既包括用户提供的配置设置、默认值、属性的初始化值,也包括在对象创建过程中由其他相关组件。
5) Status用于记录对象在系统中的当前状态信息
1.4.7、访问kubernetes api
kubectl 直接调用api
kubectl proxy
curl 命令直接调用api
列:
创建接口:
curl -u "admin:Harbor12345" -X POST -H "Content-Type: application/json" " http://10.188.3.217:1121/api/v2.0/projects" -d @createproject.json
createproject.json
--------------------
{"project_name": "kube_system",: {"public": "true"}}
{"project_name": "google_containers",: {"public": "true"}}
{"project_name": "paas-monitor",: {"public": "true"}}
{"project_name": "paas-middleware",: {"public": "true"}}
1.4.7、api server list-watch机制
APIServer除了提供GET/POST等基本类型的请求接口外,还提供了WATCH方法以供其他组件监听etcd中数据的变化,从而执行各组件的职能。
APIServer除了接收api请求、对请求进行准入控制验证、跟etcd交互和通知客户端有变更的工作外,并没有做其他的工作,即使收到了一个创建pod的请求,也不是由APIServer来执行具体的调度、创建pod的流程。其他组件根据自己的需要来订阅、监控不同资源变更时的通知,这样组件就能在集群元数据变化时做任何需要做的任务。
1、用户 ---> get /../pods?/watch=true ---> api
2、kubectl ---> post /.../pods/pod-xyz ---> api
3、api ---> 更新etcd中的对象 >> etcd
4、etcd >> 通知修改 >> api
5、api >> 向所有监听者发送更新后的对象 >> 用户
1.5、调度器scheduller
调度器决定了将pod调度到哪个集群节点上。利用APIServer的监听机制等待新创建的pod信息,给pod分配节点,所谓的「调度到某个节点」其实也只是往etcd 里写入数据。调度器会把给pod分配的节点的信息通过APIServer更新在etcd中,各个节点上的kubelet会通过监听机制从APIServer获得信息,如果得知新创建的pod要被调度到自己的节点上,kubelet就会实际的去创建并运行pod。
Scheduler提供的调度流程分三步:
1. 预选策略(predicate):遍历nodelist,选择出符合要求的候选节点
2.优选策略(priority):在选择出符合要求的候选节点中,采用优选规则计算出每个节点的积分,
最后选择得分最高的
3.选定(select):如果最高得分有好几个node,select机制就会从中随机选择一个节点,将pod调度
上去
1.5.1、亲和性调度
亲和性调度(Affinity)
默认调度器考虑的是资源足够,并且负载尽量平均,但是有的时候我们需要能够更加细粒度的去控制pod的调度。这就需要用到Kubernetes里面的一个概念:亲和性调度。基于亲和性调度机制,我们能够控制pod调度到某个节点、某个名称空间。
硬亲和性: 必须满足亲和性,可选:匹配表达式、匹配字段
软亲和性: 能满足最好,不满足也没关系。可选;优先级、权重
nodeselector: 定向调度,将pod调度到标签指定的node上
nodeaffinity: 节点亲和性,可以分为硬亲和性和软亲和性
硬亲和性:必须满足亲和性,可选:匹配表达式、匹配字段
软亲和性:能满足最好,不满足也没关系。可选;优先级、权重
podaffinity: Pod亲和性,可以分为硬亲和性和软亲和性。
匹配字段: labelSelector选择跟哪组Pod亲和
适用场景: k8s集群的节点分布在不同的区域或者不同的机房,当应用A和应用B要求部署在同一个区域或者同一机房的时候,需要用到pod亲和性调度
列:
nodeaffinity
-----------------
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
nodeScheduller
-----------------
kind: Deployment
apiVersion: apps/v1
metadata:
name: kubia-gpu
spec:
nodeSelector:
gpu: "true"
1.5.2、podaffinity亲和性与反亲和性
pod-nginx.yaml
---------------
apiVersion: v1
kind: Pod
metadata:
name: pod-flag
labels:
security: "S1"
app: "nginx"
spec:
containers:
- name: nginx
image: 172.31.4.103:1121/kube_system/alpine-nginx:v1.18.0
亲和性:
pod-affinity.yaml
------------------
apiVersion: v1
kind: Pod
metadata:
name: pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: failure-domain.beta.kubernetes.io/zone
containers:
- name: pod-affinity
image: 172.31.4.103:1121/kube_system/alpine-nginx:v1.18.0
反亲和性:
pod-affinity-failure.yaml
--------------------------
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: failure-domain.beta.kubernetes.io/zone
containers:
- name: pod-affinity
image: 172.31.4.103:1121/kube_system/alpine-nginx:v1.18.0
1.5.3、污点容忍调度(taint和toleration)
污点调度是node选择的pod,污点就是定义在节点上的键值属性数据,主要作用是让节点拒绝不合法规则的pod。Toleration(容忍)是在负载里面配置的,主要是为了避开污点。Taint(污点)和Toleration(容忍)是相互配合的,可以用来避免pod被分配到不合适的节点上,每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的pod,是不会被该节点接受的。
taint(node) : Key:定义一个key
value:定义一个值
effect: pod不能容忍这个污点时,它的响应策略可分为三种:
noSchedule、preferNoSchedule和noExecute
noSchedule:仅影响调度过程,对现存的pod不影响。
preferNoSchedule:仅影响调度过程,系统将尽量避免放置不容忍节点上污点的pod,但这不是必需的。就是软版的NoSchedule
noExecute:既影响调度过程,也影响现存的pod,不满足的pod将被驱逐。
列: kubectl taint nodes node1 key1=value1:NoSchedule
tolerations(pod): Key:被容忍的key
value被容忍key的值
tolerationSecond:被驱逐的宽限时间,默认是0就是立即被驱逐
Operator:如果operator是 Exists(此时容忍度不能指定value),或者如果operator是Equal ,则它们的value应该相等
effect:节点调度后的操作
tolerations: - key. "key1" operator. "Equal" value: "value1" effect ""NoSchedule"
1.6、控制器controller
Controller Manager包含多种控制器,每种控制器都负责一种特定资源的控制流程。
Replication Controller(副本控制器): 核心作用是保持在任何时候集群中某个RC(资源对象)关联的Pod副本数都保持预设值,利用RC包含的Pod模板创建新的Pod、删除多余的Pod,也可以通过修改RC中的Pod模板实现系统的升级、弹性伸缩。
Node Controller: 通过APIServer实时获取node的8相关信息,保存节点的最新状态,实现管理和监控集群中各个node的相关控制功能,如果节点故障,则删除etcd中的节点信息,并删除和该节点相关的pod等资源的信息。
Namespace Controller: 读取namespace的信息,如果命名空间被标记为删除,则删除该namespace下的资源
1.7、 endpoint controller
Endpoints表示了一个Service对应的所有Pod副本的访问地址,而Endpoints Controller负责生成和维护所有Endpoints对象的控制器。它负责监听Service和对应的Pod副本的变化。
如果监测到Service被删除,则删除和该Service同名的Endpoints对象;
如果监测到新的Service被创建或修改,则根据该Service信息获得相关的Pod列表,然后创建或更新Service对应的Endpoints对象。
如果监测到Pod的事件,则更新它对应的Service的Endpoints对象。
kube-proxy进程监听Service的Endpoints资源的信息,实现Service的负载均衡功能。
1.8、Kubelet
Kubelet
每个工作节点上都会有一个kubelet进程,用以处理从master节点下发到本节点的任务,管理和监控Pod。
职责一: 向APIServer注册kubelet所在node节点的信息,将新的节点扩容进k8s集群
职责二: 持续监听APIServer,查看是否有pod被分配到了自己的节点上,并和节点上已有的pod的信息做对比,通知docker进行创建、删除pod等操作
职责三: 周期性检查容器的探针,检测容器是否存活,并重启异常容器
职责四: 监控节点和容器的资源信息,并向APIServer上报Node和Pod的信息、
1.9、静态pod
Kubelet一般会和APIServer进行通信来获取应该运行在该节点上的pod清单,但kubelet也可以基于本地pod目录下的pod清单来运行容器,这类直接由kubelet在本地进行管理的pod就叫做静态pod。
静态pod直接由某个节点上的kubelet程序进行管理,不需要api server介入,静态pod也不需要关联Deployment等控制器,完全是由kubelet程序来监控,无法用APIServer来进行直接管理。
[root@vm-paasyy4-102 ~]
● kubelet.service - Kubernetes Kubelet Server
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
[root@vm-paasyy4-102 ~]
[Service]
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true"
[root@vm-paasyy4-102 ~]
[root@ node01 ~] $ cat <<EOF >/etc/kubernetes/manifest/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
app: static
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
EOF
[root@node01 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6d05272b57e nginx:latest "nginx" 8 minutes ago Up 8 minutes k8s_web.6f802af4_static-web-fk-node1_default_67e24ed9466ba55986d120c867395f3c_378e5f3c
现在我们通过kubectl工具可以看到这里创建了一个新的镜像 Pod:
[root@node01 ~] $ kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node01 1/1 Running 0 2m
静态 pod 的标签会传递给镜像 Pod,可以用来过滤或筛选。 需要注意的是,我们不能通过 API 服务器来删除静态 pod(例如,通过kubectl命令),kebelet 不会删除它。
[root@node01 ~] $ kubectl delete pod static-web-my-node01
[root@node01 ~] $ kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node01 1/1 Running 0 12s
我们尝试手动终止容器,可以看到kubelet很快就会自动重启容器。
[root@node01 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
5b920cbaf8b1 nginx:latest "nginx -g 'daemon of 2 seconds ago ...
静态pods的动态增加和删除#
运行中的kubelet周期扫描配置的目录(我们这个例子中就是/etc/kubernetes/manifests)下文件的变化,当这个目录中有文件出现或消失时创建或删除pods.
[root@node01 ~] $ mv /etc/kubernetes/manifests/static-web.yaml /tmp
[root@node01 ~] $ sleep 20
[root@node01 ~] $ docker ps
// no nginx container is running
[root@node01 ~] $ sleep 20
[root@node01 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
e7a62e3427f1 nginx:latest "nginx -g 'daemon of 27 seconds ago
2.0、kube-proxy
Kube-proxy运行在每个node节点上,它监听APl server中 service和endpoint的变化情况,并通过配置iptables等规则来为实现流量转发功能。Kube-proxy通过维护节点上的网络规则,实现了kubernetes Service概念的一部分。它的作用是使发往Service的流量负载均衡到正确的后端Pod。
目前linux下的Kube-proxy主要支持以下三种代理模式:
userSpace
iptables
ipvs
userSpace:
该模式下kube-proxy会为每一个Service创建一个监听端口。发向Cluster IP的请求被iptables规则重定向到Kube-proxy监听的端口上,Kube-proxy根据LB算法选择一个提供服务的Pod并和其建立连接,以将请求转发到Pod上。该模式下,Kube-proxy充当了一个四层Load balancer的角色,但效率较另外两种模式低一些。
iptables:
提高转发效率,kube-proxy提供了iptables模式。在该模式下,Kube-proxy为service后端的每个Pod创建对应的iptables规则,直接将发向Cluster lP的请求重定向到一个Pod lP。该模式下Kube-proxy不承担四层代理的角色,只负责创建iptables规则。该模式的优点是较userspace模式效率更高,但不能提供灵活的LB策略。
ipvs:
ipvs模式和iptables类似,kube-proxy监控Pod的变化并创建相应的ipvs规则。ipvs也是在kernel模式下通过netfilter实现的,但采用了hash table来存储规则,因此在规则较多的情况下,Ipvs相对iptables转发效率更高。除此以外,ipvs支持更多的LB算法。
2.1、deployment的全流程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!