Willson Chen

Stay Hungry, Stay Foolish.

k8s 基础

k8s 基础

简介

K8S(Kubernetes缩写)是容器编排引擎,用于实现自动化运维管理容器。
核心功能:

  • 自动调度:根据容器消耗情况与节点负载情况,自动分配容器到节点上。
  • 自动修复:通过健康检查发现节点问题,自动转移到其他节点完成修复。
  • 自动扩容收缩:预定义负载指标,自动动态扩容与收缩。
  • 服务发现与负载均衡:容器是动态创建,故需要有名字服务和负载均衡。

概念

  • Pod(容器组)
    • 是调度的基本单元,用于存放一组容器及容器的共享资源。
    • 共享资源包括:存储、网络(主机名、IP地址)等。
    • Pod 单词是豌豆荚,形象表达了容器组的概念。
  • ReplicaSet(复制集):
    • 用于确保 Pod 的副本数量和状态稳定性。
    • 只有两个信息,副本数和 Pod 模板。
    • 一般通过 Deployment 来创建 ReplicaSet。
  • Deployment(部署):
    • 是对应用部署的抽象,在 ReplicaSet 基础上增加滚动升级和回滚。
    • 其定义中比 ReplicaSet 增加了滚动更新策略。
    • 当用户修改副本数(Scale)时,会与 ReplicaSet 交互,实现扩容。
    • 当用户修改 Pod 模版时就会触发滚动更新。
    • 滚动更新时会创建一个新的 ReplicaSet,周期性创建新Pod和删除旧Pod。
    • Deployment下,所有Pod是完全一样的,也没有顺序。
  • StatefulSet(有状态集):
    • StatefulSet 是有状态的 Pod 集合。
    • 可确保 Pod 的有序创建和更新。
    • 可确保每一个 Pod 有稳定的DNS名称。
    • 可为每一个 Pod 创建单独的 PVC。
    • 适合部署数据库、队列等有主从节点和持久化存储的服务。
  • Service(服务):
    • Pod 是动态创建且副本数不定,通过 Service 为其提供稳定的访问方式。
    • 其定义中包含具体的外部访问方式及其关联的 Pod 选择器。
    • 当关联到多组 Pod 时,负载均衡算法默认是轮询,只支持 4 层负载均衡。
    • K8S 内置了DNS 服务器,在集群中可以通过 DNS 来访问服务。
    • 可以将 Service 映射到外部服务上,通过 DNS。
  • Namespace(命名空间):
    • 集群内实现逻辑隔离,在同一个物理集群内实现多个虚拟集群。
    • 每个资源必须属于一个Namespace,并且在其内部唯一。
  • Label(标签):
    • 是附加在资源对象上的键值对。
    • 对资源进行命名和分类,便于管理和查找。
    • 用于引用和筛选资源,如 service 中用来筛选 Pod。
  • Ingress(入口):
    • 是集群的外部服务入口,用于将外部请求转发到内部服务上。
    • 是 7 层的负载均衡器,是对反向代理的抽象,类似 nginx。
  • PersistentVolume(PV,持久卷):
    • 是对实际物理存储系统的抽象。
    • 是物理集群层面的资源,不属于任何命名空间。
    • PV 有多种存储方式,如临时目录、主机目录、共享目录。
  • PersistentVolumeClaim(PVC,持久卷声明):
    • 是用户对存储请求的抽象。
    • PVC 与 PV 的关系类似于接口与实现类的关系。
    • 请求信息包含存储大小、访问模式等。
    • PVC 会绑定和消耗 PV。
    • PVC 必须与 Pod 在同一命名空间下才可以被指定使用。
  • DaemonSet
    • 确保在每一个节点上都运行一个 Pod。
    • 用于部署守护进程,如监控或日志收集器。
    • 集群本身的 kube-proxy 就是一个 DaemonSet 部署。
  • ConfigMap
    • 是一种资源,用于存储 KV 配置信息。
    • 可以作为环境变量、命令行参数或挂载到容器中使用。
  • Secret
    • 是一种资源,用于存储敏感信息,如密码、API 密钥等。
    • 可以作为环境变量、命令行参数或挂载到容器中使用。

架构原理

架构图及解析

image

  • K8S集群:一组虚拟机或物理机,运行了 K8S 的集群。
  • Master(主节点):负责集群的管理和调度。
  • Worker(工作节点):部署用户容器,提供计算资源。
  • ETCD:所有资源及状态数据存储的位置。
  • APIServer:
    • 提供 RESTFul API,是集群控制的入口。
    • 接口基本是对资源的增删改查和变化监听。
  • Scheduler(调度器):
    • 监听 APIServer 变化。
    • 负责决定将 Pod 放在哪个节点上运行。
    • 会充分考虑集群的拓扑结构、节点负载和亲和性。
  • Controller Manager(控制器):
    • 管理资源,确保集群处于预期状态。
    • 每种资源都有对应的控制器。
  • kubelet:
    • 在 Worker 上负责 Pod 的全生命周期管理,同时上报状态到 APIServer。
    • CRI:容器运行时接口,cri-dockerd是 docker 的CRI实现。
    • CNI:容器网络接口,Flannel是其实现。
    • CSI:容器存储接口。
  • kube-proxy:
    • 负责服务转发和负载均衡的实现,对应 service 的功能。
    • 以 DaemonSet 方式运行在每个 Worker 上。
    • 默认使用 iptables 模式,利用iptables实现转发和四层负载均衡。
    • 新版本支持 ipvs,解决iptables线性查找规则的问哦。
    • 如果内核版本不够,会降级到 userspace 模式,固定端口进 proxy 进行转发。
  • kubectl
    • 提供命令行工具,调用 APIserver 接口。

网络模型

  • K8S 的网络原则:
    • 提供简单一致的网络视图和使用体验,屏蔽宿主机环境和网络拓扑的复杂度。
  • K8S 的网络特征:
    • 每个 Pod 有一个独立 IP。
    • 所有 Pod 通过 IP 直接访问其他 Pod,不管是不是在同一节点上。
    • Pod 看自己的 IP 和任意 Pod 或节点看自己的 IP 是一样的。
    • Pod 内的容器通过 localhost 访问其他容器。
  • K8S 网络模型的实现要求:
    • Pod 与任意节点的 Pod 通信无需 NAT。
    • Node 与 Pod 相互通信无需 NAT。
  • K8S 网络模型的实现原理:
    • Pod 内容器共享同个网络命名空间,通过回环虚拟网卡访问内部容器。
    • 相同 Node 的 Pod 之间通过 cni0 网桥进行通信。
    • 不同 Node 的 Pod 之间通过网络插件进行通信。
    • flannel 插件实现了一个覆盖网络,将 TCP数据包装在另外一网络包里进行路由转发和通信。

image

Pod 原理

  • Pod 状态:
    • Pending:APIServer 已经创建,Pod 内还有至少一个容器没有创建,包括下载镜像的过程。
    • Running:Pod 内所有容器均已创建,至少有一个处于运行中。
    • Succeeded:Pod 内所有容器均已成功退出,且不会重启。
    • Failed:Pod 内所有容器均已退出,但至少有一个容器退出时状态非 0。
    • Unknown:无法取得该 Pod 状态,可能由于网络原因。
  • Pod 重启策略:
    • Always:默认策略,当容器退出后总是重启。
    • OnFailure:退出状态码非 0 时才重启。
    • Never:只要退出就不重启。
  • Pod 的镜像拉取策略:
    • IfNotPresent:默认值,如果本地有镜像,则直接使用,否则从仓库拉取。
    • Always:总是重新拉取,每次创建 Pod 都会重新拉取。
    • Never:永远不自动拉取,如果 Node 不存在则启动失败。
  • Pod 的探针方式:
    • httpGet:发 HTTP 请求返回 200-400 为成功
    • exec:在容器内执行 shell 命令,根据命令退出状态 0 为健康。
    • TCPSocket:与容器的 IP 端口建立TCP 连接,能建立为成功。
  • Pod 的探针类型:
    • 存活探针(LivenessProbe),用于检测容器健康情况,如果失败 kubelet 会杀掉容器根据容器重启策略决定是否重启。
    • 就绪探针(ReadinessProbe),用于检测容器是否准备好接受流量,可以用于确保程序启动后的数据加载,如果失败 service 不会转发请求。
    • 启动探针(StartupProbe),适用于初始化时间较长的程序,一旦满足条件后不再执行。存在目的是暂时屏蔽其他探针。
  • 直接创建 Pod 的过程:
    • 用户通过kubectl或api提交 Pod 信息到 APIServer。
    • APIServer验证用户权限,创建 Pod 信息到 ETCD 则返回确认。
    • APIServer反馈 ETCD 中Pod的变化,其他组件监听变化。
    • 调度器发现了未分配节点的 Pod,为其分配最佳的节点,结果更新到 APIServer。
    • Node 上的 kubelet 监听到变化,检查是否存在,不存在则创建。
    • 如果需要挂载外部存储,则通过 CSI挂载外部存储。
    • 通过 CNI 配置网络,然后启动容器,完成后反馈 APIServer。
  • 通过 Deployment 创建Pod 过程:
    • kubectl apply 一个 Deployment。
    • APIServer验证用户权限,创建Deployment 信息到 ETCD 则 返回确认。
    • Deployment 控制器监听到变化会创建ReplicaSet。
    • ReplicaSet 控制器监听到变化则会按照其模板创建 Pod。
    • 未分配节点的 Pod,后续过程与直接创建 Pod 的过程一样。
    • Deployment 创建的Pod,ReplicaSet 控制器会持续关注确保数量。
  • Pod 的 容器类型:
    • 应用容器:运行业务引用程序,多个时并行启动。
    • Init 容器:可以有多个,在应用容器启动前串行启动。
    • Pause 容器:在 pod 内第一个启动,用于设置网络,生命周期与 Pod 相同。
    • SideCar 容器:只是一种设计模式,把业务无关的功能剥离出来通过辅助容器实现。
  • Pod 的亲和性调度:
    • 确保 Pod 运行在特定类型的节点上,如 SSD存储节点或 GPU 节点。

命令行

#查看帮助,中文文档: http://docs.kubernetes.org.cn/683.html
kubectl --help

#查看k8s版本
kubectl version

#查看资源清单及简写
kubectl api-resources

#查看集群信息
kubeclt cluster-info

#通过 yaml 创建资源如果存在会返回错误,不建议使用
kubectl create -f xx.yaml

#通过 yaml 创建或更新资源,如果存在则更新
kubectl apply -f xx.yaml

# 查看资源信息,格式:
# kubectl get <resource> [-o wide|json|yaml] [-n namespace]
kubectl get nodes #查看节点
kubectl get cs #查看各组件状态
kubectl get all -A #查看所有命名空间下的所有资源
kubectl get pod -A -w -o wide #查看所有命名空间下的Pod,实时更新,显示详细信息
kubectl get all -n kubernetes-dashboard #查看命名空间下所有的资源
kubectl get svc -n kubernetes-dashboard #查看命名空间下的服务
kubectl get deploy nginx -o=yaml --export > nginx.yaml #将 deployment 输出到文件


# 描述资源的详细信息
kubectl describe deploy kubernetes-dashboard -n kubernetes-dashboard


helm

helm是一个包管理工具,可以用来管理kubernetes应用。
helm是舵轮的意思,kubernetes 是舵手。
文档:https://helm.sh/zh/docs/

helm 安装

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh