Kubernetes笔记_0
架构
一个Kubernetes
集群至少包含一个控制平面,以及一个或多个工作节点
控制平面
- 负责管理工作节点和维护集群状态,所有任务的分配都来自控制平面
- 为集群做出去全局决策,比如资源的调度、检测和响应集群事件
kube-apiserver
- 如果与
Kubernetes
集群进行交互,需要通过API apiserver
是Kubernetes
控制平面的前端,用于处理内部和外部请求
kube-scheduler
- 集群状态是否良好,如果需要创建新的容器,需要将他们放在哪里,由调度程序关注
scheduler
调度程序考虑容器集的资源需求,比如CPU
或者内存,以及集群的运行状态,然后将容器集安排到适当的计算节点
kube-controller-manager
- 控制器负责实际运行集群,
controller-manager
控制器管理器将多个控制器功能合并,降低了程序的复杂性
controller-manager
包含以下控制器:
- 节点控制器(
Node Controller
): 负责在节点出现故障时进行通知和响应 - 任务控制器(
Job Controller
): 检测代表一次性任务的Job
对象,然后创建Pods
来运行这些任务直到完成 - 端点控制器(
Endpoints Controller
): 填充端点Endpoints
对象,即加入Service
和Pod
- 服务账户和令牌控制器(
Service Account & Token Controllers
): 为新的命名空间创建默认账户和API
访问令牌
etcd
- 键值对数据库,存储配置数据和集群状态信息
可选组件cloud-controller-manager
- 云控制管理器,允许将集群了解到云提供商的
API
之上,将该云平台交互的组件与自己的集群交互组件分离开。如果在自己的环境中运行Kubernetes
或者在本地计算机中运行学习环境,则所部署的集群不需要有云控制管理器
各组件之间的关系
工作节点
- 负责执行由控制平面分配的请求任务,运行实际的应用和工作负载
Node
组件
- 节点组件会在每个工作节点上运行,负责维护运行的
Pod
并提供Kubernetes
运行环境
Pod
Pod
是包含一个或者多个容器的容器组,是Kubernetes
中创建和管理的最小对象
特点
- 是
Kubernetes
的最小调度单位(原子单元),Kubernetes
直接管理Pod
而不是容器 - 同一个
Pod
中的容器总是会被自动安排到集群中的同一个节点(物理机或者虚拟机上),并且一起调度 Pod
可以理解为运行特定应用的逻辑主机,容器共享存储、网络和配置声明(比如资源限制)- 每个
Pod
有唯一的IP
地址,IP
地址分配给Pod
,在同一个Pod
内,所有容器共享一个IP
地址和端口空间,Pod
内的容器可以使用localhost
相互通信
创建和管理
- 创建
Pod
:kubectl run <Pod名称> --imgae=<容器镜像>
- 执行一次性任务,退出
Pod
时自动删除容器:kubectl run <Pod名称> --image=<容器镜像> -it --rm
- 执行一次性任务,退出
- 查看容器状态:
kubectl get pod
- 显示详细
Pod
信息:kubectl get pod -owide
- 显示详细
- 查看
Pod
运行日志:kubectl logs -f <Pod名称>
- 查看
Pod
的一些信息:kubesctl describe pod <Pod名称>
- 创建分为四个步骤
- 分配节点
Successfully assigned default/Pod名称 to k8s-worker2
- 拉取镜像
Container image "容器镜像" already present on machine
- 创建容器
Created container Pod名称
- 启动容器
Started container Pod名称
- 分配节点
- 创建分为四个步骤
- 进入
Pod
容器:kubectl exec -it Pod名称 -- /bin/bash
- 删除容器:
kubectl delete pod Pod名称
Deployment
部署和ReplicaSet
副本集
Deployment
是对ReplicaSet
和Pod
的更高级别的抽象,使Pod
拥有多副本,自愈,扩缩容,滚动升级等能力ReplicaSet
副本集是一个Pod
的集合,设置运行Pod
的数量,确保任何时间都有指定数量的Pod
副本在运行。
- 通常,我们不直接使用
ReplicaSet
,而是在Deployment
中声明
- 创建
Deployment
:kubectl create deployment <部署名称> --imgae=<镜像名称> --replicas=<副本数量>
Deployment
通过副本集控制Pod
的数量- 如果手动删除一个
Pod
,副本集会自动生成一个新的Pod
,维持副本数量不变。这就是自愈
- 查看
Deployment
状态:kubectl get deploy
缩放
- 查看副本集:
kubectl get replicaSet
- 查看副本集缩放过程:
kubectl get replicaSet --watch
- 查看副本集缩放过程:
手动缩放
- 手动修改
Deployment
中的副本集数量:kubectl scale deploy <部署名称> --replicas=<新的副本数量>
自动缩放
kubectl autoscale deployment/<部署名称> --min=<最小副本数> --max=<最大副本数> --cpu-percent=75
--cpu-percent=75
是使得自动缩放保持所有的Pod
的平均cpu占用维持在75%以下
- 查看自动缩放:
kubectl get hpa
- 删除自动缩放:
kubectl delete hpa <部署名称>
滚动更新
- 滚动更新部署版本:
kubectl set image deploy/部署名称 容器名=镜像版本
- 如果一个
Deployment
中有三个Pod
,运行滚动更新命令时,会创建一个新的副本集。- 当新的副本集有一个
Pod
就绪了,就会下线旧副本集中的一个Pod
,直到旧副本集中所有的Pod
均下线
- 当新的副本集有一个
- 版本回滚:
- 查看历史版本:
kubectl rollout history deploy/部署名称
- 查看历史版本详情:
kubectl rollout history deploy/部署名称 --revision=版本号
- 回滚到指定的版本:
kubectl rollout undo deploy/部署名称 --to-revision=版本号
- 查看历史版本:
Service
- 将一组
Pods
上的应用程序公开为网路服务的抽象方法 - 将一组
Pod
提供相同的DNS
名,并进行负载均衡 Kubernetes
为Pod
提供分配了IP
地址,但是IP
地址可能发生变化,集群内的容器可以通过service
名称访问服务,不需要担心Pod
的IP
发生变化
Service
定义的抽象:
- 逻辑上一组可以互相替换的
Pod
,通常称为微服务 Service
对应的Pod
集合通过选择符关联- 在一个
Service
上运行了三个Nginx
副本,副本之间可以相互替换,我们不需要关心它调用了哪一个Nginx
,也不需要关注Pod
的运行装填,只需要调用这个服务就可以了
- 将部署公开为服务:
kubectl expose deploy/部署名称 --name=服务名称 --port=服务端口 --target-port=对应pod端口
ServiceType
ClusterIP
(默认)
- 将服务公开在集群内部,
Kubernetes
会给服务分配一个集群内部的IP
,集群内的所有主机都可以通过这个Cluster-IP
访问服务。集群内部的Pod
可以通过Service
名称访问服务。
NodePort
- 通过每个节点的主机和静态端口(
NodePort
)暴露服务,集群外部的主机可以使用节点IP
和NodePort
访问服务
ExternalName
- 将集群外部的网络引入集群内部
LoadBalancer
- 使用云提供商的负载均衡器向外部暴露服务
使用--type=NodePort
即可,本地集群不需要使用LoadBalancer
命名空间
- 一种资源隔离机制,将同一个集群中的资源划分为互相隔离的组。命名空间可以在多个用户之间划分集群资源(通过资源配额)
- 比如可以设置开发、测试、生产多个命名空间
- 同一个命名空间内资源名称唯一,跨命名空间时没有这个要求
- 命名空间作用域仅仅针对带有名字空间的对象,比如
Deployment、Service
等 - 作用域对集群访问对象不适用,比如
StorageClass、Node、PersistentVolume
等 - 查看命名空间:
kubectl get namespace
Kubernetes
默认创建四个命名空间:default
: 默认命名空间,不可删除,没有指定命名空间的对象都会分配到这里kube-system
: 系统对象(控制平面和Node
组件)使用的命名空间kube-public
: 自动创建的公共命名空间,所有用户(包括没有身份验证的用户)都可以读取,将集群中公用的可见和可读的资源放在这个空间中kube-node-lease
: 租约(Lease
)对象使用的命名空间。每个节点都有一个关联的Lease
对象,Lease
是一种轻量级的资源,通过发送心跳,检测集群中的每个节点是否发生故障- 查看
lease
对象:kubectl get lease -A
- 查看
- 查看指定命名空间的
Pod
:kubectl get pod -n=命名空间名称
- 创建命名空间:
kubectl create ns 命名空间名称
- 运行容器指定命名空间:
kubectl run pod名称 --image=镜像名称 -n=命名空间名称
- 修改默认命名空间的名称(
default
):kubectl config set-context $(kubectl config current-context) --namespace=新的名称
- 删除命名空间:
kubectl delete ns 命名空间名称
- 删除命名空间会删除其中所有内容,如果有些对象无法被删除(对象处于错误状态,或者对象资源被占用),则命名空间也无法被删除。需要手动删除对象以后才能删除命名空间
管理对象
命令行指令
- 使用
kubectl
创建和管理Kubernetes
对象。简单高效,但是功能有限,不适合复杂场景,不容易追溯操作,用于开发和调试。
声明式配置
Kubernetes
使用yaml
文件描述Kubernetes
对象,学习难度大并且配置麻烦,但是操作留痕,适合操作复杂的对象,多用于生产。- 使用命令行指令,无法指定
NodePort
端口,是随机生成的。但是yaml
文件中可以指定NodePort
常用命令缩写
名称 | 缩写 | Kind |
---|---|---|
namespace | ns | Namespace |
nodes | no | Node |
pods | po | Pod |
services | svc | Service |
deployment | deploy | Deployment |
replicasets | rs | ReplicaSet |
statefulsets | sts | StatefulSet |
使用yaml
文件配置KUbernetes
对象
apiVersion
:Kubernetes API
版本kind
: 对象类别,比如Pod、Deployment、Service、ReplicaSet
等metadata
: 描述对象的元数据,包括一个name
字符串,UID
(系统自动生成)和可选的namespace
spec
: 对象的配置
yaml
内容在官网都可以找到
- 使
yaml
文件生效:kubectl apply -f xxx.yaml
- 删除
yaml
文件:kubectl delete -f xxx.yaml
标签
- 附加在对象
Pod
上的键值对,用于补充对象的描述信息。标签使用户可以以松散的方式管理对象映射,不需要客户端存储这些映射。 - 格式
- 键:
- 前缀(可选) / 名称(必须)
- 有效的名称和值:
- 字符数量小于等于63
- 如果不为空,以字母和数字字符开头结尾
- 包含破折号-,下划线_,点和字母或者数字
- 键:
- 查看所有
Pod
的标签:kubectl get pod --show-labels
- 查看指定
Pod
的标签:kubectl get pod -l "指定的Pod描述"
- 查看指定
选择器
- 标签通常配合选择器使用,标签选择器可以识别一组对象,标签不支持唯一性
- 标签选择器最常见的用法是为
Service
选择一组Pod
作为后端 - 标签选择运算,基于等值的和基于集合的
- 多个条件使用逗号分割,相当于
AND
- 基于等值的直接使用键值对即可
- 基于集合的可以使用
IN, NOT IN
- 多个条件使用逗号分割,相当于
容器运行时接口(CRI
)
Kubelet
运行在每个节点上,用于管理和维护Pod
和容器的状态- 容器运行时接口是
Kubelet
和容器运行时之间通信的主要协议,将Kubelet
于容器运行时解耦,实现了CRI
接口的容器引擎,都可以所谓Kubernetes
的容器运行时。 Docker
没有实现CRI
接口,Kubernetes
使用dockershim
来兼容docker
crictl
是一个兼容CRI
的容器运行时命令,跟docker
命令一个样,可以用来检查和调试底层的运行时容器- 比
docker
命令稍微少一些,比如无法实现导入导出 - 因此导入导出使用
ctr
命令,也只用来导入导出,因为ctr
也不是很好用1
2
3
4
5docker pull alpine:3.15
docker save apline:3.15 > alpine-3.15.tar # 保存成tar
ctr -n k8s.io images import alpine-3.15.tar --platform linux/amd64 # 导入镜像
kubernetes 中所有的镜像都在k8s.io这个命名空间中
ctr -n k8s.io images export alpine.tar docker.io/library/alpine:3.15 --platform linux/amd64 # 导出镜像
- 比
金丝雀发布(canary deployment
)
- 生产环境中小范围部署新的应用代码,一旦应用签署发布,只有少数用户被路由到他,最大限度降低影响。如果没有错误发生,则将新版本逐渐推广到整个基础设施
- 默认的金丝雀发布有一定的局限
- 不能根据用户的注册时间、地区等请求中的内容属性进行流量分配
- 同一个用户如果多次调用该
Service
,可能第一次请求到了旧版本的Pod
,第二次请求到了新版本的Pod
- 因为
Kubernetes Service
只在TCP
层面解决负载均衡问题,不对请求响应的消息内容做任何解析和识别,如果更完善的实现金丝雀日发布,可以考虑Istio
灰度发布
搭建MySQL
创建mysql-pod.yaml
1 | apiVersion: v1 |
挂载数据卷
hostPath
卷: 将主机节点上的文件或目录挂在到Pod
中
type | 含义 |
---|---|
DirectoryOrCreate | 目录不存在则自动创建 |
Directory | 挂载已经存在的目录,不存在会报错 |
FileOrCreate | 文件不存在则自动创建,不会自动创建文件的父目录,必须确保文件路径存在 |
File | 挂载已经存在的文件,不存在会报错 |
Socket | 挂在UNIX套接字,比如挂载/var/run/docker.sock 进程 |
ConfigMap
Docker
中可以使用绑定挂载的方式将配置文件挂载到容器里,但是在Kubernetes
集群中,容器可能被调度到任意的节点中,配置文件需要能在集群的任意节点上访问、分发和更新ConfigMap
用来在etcd中保存非加密的数据,一般用来保存配置文件- 可以用作环境变量,命令行参数或者存储卷
- 将配置信息与容器镜像解耦,便于配置的修改
- 在设计上不是用来保存大量数据的
- 保存的数据不能超过1MB
- 超出这个限制,需要考虑存储卷或者访问文件存储服务
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Sangs Blog!