探索Kubernetes容器编排

写这篇笔记是在已经大体了解 Kubernetes 是什么东西的基础上的,如果不理解我很久之前写过一篇烂尾文可以参考 K8s入门。。。
那么为什么又想起来看 K8s,云原生是趋势,对于小公司和项目也许选择云计算服务商会是个低成本还算好的解决方案,但是一旦做大,这笔账其实就不合算了,最终都会自建云原生平台,作为一个后端,也愈发感觉到 DevOps 的重要性,开发与运维的边界在某些情况下变得模糊,或者说都要懂一点才能更好的适应现在的环境。
这一系列文章记录我学习历程,作为后端并不会在这上面耗费太多精力,力求达到平均水平即可。

学习新东西,对我来说最大的问题是开始阶段,无从下口的感觉,不知道从哪开始,这时候如果能建立一个大体的框架,然后再慢慢去填充这种方式感觉比较合理;但是大体框架的建立也是让人不知所措,我一般从入门书籍或者网上找课程的方式建立,本次依旧是这样,祝我学习顺利。

更新记录

k8s 确实有点过于复杂,搭建过程有很多细节,并且需要非常多的组件来支持,机器性能也是个问题,碍于手头机器配置不够,云主机也不太想购买,目前只能停在纸上谈兵上,等日后再实践踩坑;本阶段先扫盲一下相关的概念。

  • ChatGPT 出来后,对于一些常用命令和资源清单的编写貌似不需要罗列了,让它给你写比看文章更高效,不过记得校验一下,如果不正确还是要进行二次确认。

安装

安装上可以简单分为三类:

  1. Minikube (推荐安装 K3s)
    Minikube 可以实现一种轻量级的 Kubernetes 集群,通过在本地计算机上创建虚拟机并部署只包含单个节点的简单集群。Minikube 适用于 Linux,MacOS 和 Windows 系统。Minikube CLI 提供集群管理的基本操作,包括 start、stop、status、和 delete。
    简单说,就是为了便于开发,开发我门可能没那么多机器和资源,使用它就可以快速的体验 k8s。
  2. 云计算厂商
    安装最简单,master 节点一般由厂商进行托管,通过 UI 选一下机器和配置下一步付钱即可。
  3. 裸机
    就是准备几台物理机,不管是实际的机器还是 VPS,还是虚拟化的机器。

其中裸机上最常见的安装方式,一般分为两种:二进制和 kubeadm 方式 (使用 kubeadm config print init-defaults 查看默认配置),后者官方比较推荐,kubeadm 方式比较简单,适合规模不大的情况,基本都是利用容器的方式来安装,这样也会导致完全启动的时间会比较长;大型生产环境中建议使用二进制方式。

从 Kubernetes 1.24 开始,dockershim 已经从 kubelet 中移除,但因为历史问题 Docker 却不支持 Kubernetes 主推的 CRI(容器运行时接口)标准,所以 Docker 不能再作为 Kubernetes 的容器运行时了,即从Kubernetes v1.24 开始不再使用 Docker了。

但是如果想继续使用 Docker 的话,可以在 Kubelet 和 Docker 之间加上一个中间层 cri-docker。cri-docker 是一个支持 CRI 标准的 shim(垫片)。一头通过 CRI 跟 Kubelet 交互,另一头跟 Docker Api 交互,从而间接的实现了 Kubernetes 以 Docker 作为容器运行时。但是这种架构缺点也很明显,调用链更长,效率更低。

可以考虑将 Containerd 作为 Kubernetes 的容器运行时. 相关内容可以搜一下相关科普文章,或者看我整理的Docker、Containerd、RunC扫盲

具体的安装步骤就不说了,还是挺复杂的,网上也一大把的文档,总结几个关键点;
修改主机名(hostnamectl)、节点信息写入 host、关防火墙和 swap、安装 ntpdate 同步服务器时间、通过一个虚拟 IP(VIP)做负载均衡,入口是在 service,然后访问 pod,master 节点的网段跟 service 不要在一个网段、高可用(主节点安装 HAproxy,keep-alive)、如果使用的是 docker 还需要将 cgroup driver 设置为 systemd(默认是 cgroupfs),配置日志 journald 等等。

集群架构

K8s 必然是跑在集群中的,再来复习一下基本的概念:

  • master
    主节点,控制平台,不需要很高性能,不跑任务,通常一个就行了,也可以开多个主节点来提高集群可用度。

  • worker
    工作节点,可以是虚拟机或物理计算机,任务都在这里跑,机器性能需要好点;通常都有很多个,可以不断加机器扩大集群;每个工作节点由主节点管理

所以正常情况下,使用 k8s 必须有两台机器,一台 master 节点,一台做 worker 节点。

img

对于高可用架构,例如 Master 节点尽量维持在奇数,避免投票机制带来的选举冲突问题。

Node

Node 是 Kubernetes 中的工作节点,最开始被称为 minion。一个 Node 可以是 VM 或物理机。
每个 Node(节点)具有运行 pod 的一些必要服务,并由 Master 组件进行管理,Node 节点上的服务包括 Docker、kubelet 和 kube-proxy。

Node 也算是 K8s 的一个组件,节点组件运行在 Node,提供 Kubernetes 运行时环境,以及维护 Pod。可以说 Node 节点的作用就是来运行应用的工作节点。
处理生产级流量的 Kubernetes 集群至少应具有三个 Node。
Node 使用 Master 暴露的 Kubernetes API 与 Master 通信。终端用户也可以使用 Kubernetes API 与集群交互。

Pod

K8S 调度、管理的最小单位,一个 Pod 可以包含一个或多个容器,每个 Pod 有自己的虚拟 IP。一个工作节点可以有多个 pod,主节点会考量负载自动调度 pod 到哪个节点运行。
同一容器集(Pod)中的所有容器共享同一个 IP 地址、IPC、主机名称及其它资源(存储、网络、以及怎样运行这些容器的声明)。容器集会将网络和存储从底层容器中抽象出来。
注意:自己手动创建的容器无法被管理。

Pod实现共享网络的机制:

Pod 创建时,会先起一个 Pause 容器,或者叫 init 容器、根容器,
之后才会创建一个或多个业务容器,这些业务容器会共用 Pause 网络协议栈(以及存储等),所以业务容器之间的端口不能重复。

在一个 Pod 中起多个容器的情况,多数是他们有互相依赖关系,尤其是 I/O、网络的依赖。

Pod控制器

下面来说说 Pod 控制器,RC(ReplicationController)、RS(ReplicaSet),RC 用于确保在集群中运行指定数量的 Pod 副本,并在 Pod 发生故障时进行自动替换,我们称之为自愈能力。在新版本中官方更推荐使用 RC 的升级版 RS。

RC 和 RS 是实现 Pod 副本控制的核心控制器,而 Deployment 是在它们的基础上构建的更高级别的控制器。Deployment 可以看作是 RC 和 RS 的上层抽象,它使用 RS 来确保 Pod 副本数量的正确性,并实现了滚动升级和回滚等功能

Deployment 不直接参与 Pod 创建,是通过 RS 来实现的,Deployment 实现回滚和滚动升级的原理是通过管理多个 RS 版本来实现的;每次更新 Deployment 时,它会创建一个新的 RS;回滚时,Deployment 会找到上一个版本的 RS,并将其 Pod 数量恢复到原来的状态。
如何判断是否满足数量其实是根据标签 label 来匹配的。在更新和回滚的时候,默认是按 25% 来进行操作,例如先创建 25% 新的 Pod,然后删除 25% 的旧的,通过对应的 RS 操作完成。
有一种特殊情况是:当需要创建 5 个,创建到 3 个也就是没有完全创建完成时,突然更新了版本,那么 RS 会立即杀掉创建好的 3 个,然后开始建新版本,并不会等到旧版本全部创建完毕后再进行。同时默认保存所有历史版本。

HPA

HPA 是 Horizontal Pod Autoscaler 的缩写,它是 Kubernetes 提供的一种自动扩展 Pod 数量的机制
HPA 可以根据 CPU 使用率、内存使用率等指标自动调整 Pod 的数量,从而实现自动扩缩容。HPA 的工作原理是通过定期检查 Pod 的 CPU 使用率、内存使用率等指标,然后根据指标的变化情况来调整 Pod 的数量。
HPA 支持 ReplicaSet、StatefulSet 和 Deployment 部署。

DaemonSet

DaemonSet 通常用于在每个节点上运行集群守护进程、日志收集守护进程、监控守护进程等。
DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。 当有节点加入集群时,也会为他们新增一个 Pod。当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。

关于 apiVersion 的选择,在 Kubernetes 1.9 及更早期版本中,DaemonSet 只能通过 extensions/v1beta1 API 进行管理,而在 Kubernetes 1.10 及之后的版本中,DaemonSet 已经被调整为 apps/v1 API,并逐步废弃了 extensions/v1beta1 API。
v1 是最基本的 API 版本,一般情况下足够用。

Job与CronJob

Job 用于管理短暂任务,会创建一个或者多个 Pod,如果非正常终止,将继续重试 Pod 的执行,直到指定数量的 Pod 成功终止。 随着 Pod 成功结束,Job 跟踪记录成功完成的 Pod 个数。当数量达到指定的成功个数阈值时,任务(即 Job)结束。 删除 Job 的操作会清除所创建的全部 Pod。 挂起 Job 的操作会删除 Job 的所有活跃 Pod,直到 Job 被再次恢复执行。
当一个 Job 执行完毕,会保留在 API 中,以便观察是否成功以及执行过程,当然也可以配置自动清理。

CronJob 用于创建基于时隔重复调度的 Job,CronJob 用于执行排期操作,例如备份、生成报告等。 一个 CronJob 对象就像 Unix 系统上的 crontab(cron table)文件中的一行。 它用 Cron 格式进行编写, 并周期性地在给定的调度时间执行 Job。

Pod生命周期

任何技术中的生命周期都非常重要,了解生命周期可以更方便的进行排查问题、扩展等。

  • init 容器
    如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。
    它们用于在启动应用程序之前执行一些必要的操作或者检查,并确保所需的资源可用。例如,可能需要等待某个服务启动完毕、加载配置文件、运行数据库迁移脚本等操作。如果这些操作失败,则 Pod 不会进入 Running 状态,所以可以作为一种延迟主容器启动的方案。
    如果有多个,Init Container 将按照定义的顺序逐个运行。每个容器都必须成功完成后,才能执行下一个容器,执行完毕后就会退出,不会一直存在,也就是只存在于初始阶段。

    在 Kubernetes 中,Secret 是一种用于存储敏感信息的机制,例如密码、API 密钥或其他机密数据,Secret 可以加密存储,并且只能通过授权的 Pod 访问。
    Init Container 可以访问和使用 Secret 存储的敏感信息。这对于需要在容器启动之前加载密码或其他机密信息的应用程序非常有用。
    在 Pod 启动时,Kubernetes 将加载该 Secret,并将其作为环境变量传递给容器,所以也可以用环境变量的方式来获取,不过对于机密文件,可能就需要 init c 了。

    一个 Pod 里可能有多个容器,每一个容器都有一套完整的以上 init 过程。

  • Pending 挂起
    Pod 已经被创建,但是它的容器还没有被调度到一个节点上。例如需要的镜像还没有下载完成。

  • Running
    Pod 中的容器已经被调度到了一个节点上,并且正在运行中(包括正处于启动和重启中)。如果配置了 postStart 回调,那么该回调已经执行且已完成。
    处于该状态时,并不代表你的服务可以正常访问(就绪 Ready 才是表示可以对外服务)。

  • Succeeded
    Pod 中的所有容器都已经成功地执行完任务并退出了。

  • Failed
    Pod 中的某个容器因为错误而终止了执行。

  • Unknown
    Kubernetes 无法确定 Pod 的状态。这通常是由于与 Pod 相关的信息丢失或不可访问导致的。

在 init 后主容器运行时,可以在开始与结尾进行一个回调,做一下准备和收尾工作,这个就不展开了很简单。
与生命周期密切相关的,还有两种探测(由 kubelet 执行):

  1. 生存探测(Liveness Probe)
    用于检查容器是否在运行中,如果容器无法响应,则 Kubernetes 会将其标记为失败,并尝试重启该容器。例如,可以通过执行某个特定的命令或者发送一个 HTTP 请求来进行生存探测。
    一般会一直伴随主容器的运行,支持的方式可以是 TCP、HTTP、命令等。
  2. 就绪探测(Readiness Probe)
    用于检查容器是否已经准备好接受流量,如果容器还没有完全启动或者正在加载数据,则 Kubernetes 不会将流量路由到该容器。这有助于确保应用程序不会接收到无法处理的请求。例如,可以通过监视某个特定的端口或者等待某个文件创建完成来进行就绪探测。
    一般发生在 init 后主容器的开始阶段。

有些时候容器虽然 Running 但是可能进程还没准备好对外服务,或者进程出现了假死;这种情况探测技术就变的非常有用。

StatefulSet

StatefulSet 主要用于部署有状态服务,需要搭配 HeadLess 和 PVC 使用,可能需要先了解一下这两部分知识:

  • 稳定的持久化存储,PVC 实现
    举例来说,当 StatefulSet 中的一个 Pod 被删除后,根据副本数量会重新创建,新的 Pod 的 IP 与被删的肯定是不一致的,但是由于 Pod 仍然具有相同的网络标识符,因此会尝试重用之前分配给该 Pod 的 PVC,所以新 Pod 与 PVC 的绑定关系不会丢失(每一个副本都有自己的 PVC)。
  • 稳定的网络标识,HeadLess(SVC 的一种)实现(clusterIP: None),在下面 SVC 中理解。
    DNS 规则一般是:<pod-name>.<headless-service-name>.<namespace>.svc.cluster.local,当服务处于相同的命名空间下时,可以省略写为:<pod-name>.<headless-service-name>
    如果查询 <headless-service-name>.<namespace>.svc.cluster.local 的 DNS 记录,将会返回所有副本 Pod 节点的 IP。
  • 有序部署和回收,基于 Pause(init c),例如先启动 MySQL 再 Java

在 StatefulSet 中,由于每个 Pod 都有自己独立的名称(例如 web-0、web-1 等),因此也需要为每个 Pod 分配一个唯一的 PVC。这样才能保证每个 Pod 都有自己独立的存储卷,并且可以在重启或迁移时保留其之前的数据。
通过 Headless Service 则可以将每个 Pod 映射到一个唯一的 DNS 记录中。这样,在调用应用程序时,就可以通过 DNS 解析来直接访问特定的 Pod,从而实现数据的有序访问。
在应用程序中,使用 Headless Service 的名称加上 Pod 的名称或索引编号等信息作为域名,来直接访问特定的 Pod。

在创建 StatefulSet 资源清单时,可以直接使用模板(volumeClaimTemplate)来创建 PVC,当副本先被创建时,如果 PVC 还不存在, Kubernetes 控制面会为该副本自动创建一个 PVC。
当资源被删除时,可以使用 StatefulSetAutoDeletePVC 特性来自动删除 PVC,它有几种策略可选,默认与之前策略一致,删除时 PVC 不受影响。

但是目前来说,总有一些有状态服务不方便使用 StatefulSet 部署,甚至说不方便使用 K8s 部署,例如 MySQL,这里说的不方便不是不能,而是没有想象中的那么稳定;也不是说数据库服务就不行,例如 MongoDB 就可以很稳定的部署;这个具体分情况。

K8s组件与工具

控制相关:

  • kube-apiserver API 服务器
    公开了 Kubernetes API
  • etcd 键值数据库
    可以作为保存 Kubernetes 所有集群数据的后台数据库,分布式、高可用。
    相比 Redis,etcd 更适合分布式、强一致性、高可靠性的场景。例如服务发现、集群协调等场景。
  • kube-scheduler
    调度 Pod 到哪个节点运行
  • kube-controller
    集群控制器
  • cloud-controller
    与云服务商交互

Node 相关(节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行环境):

  • kubelet
    在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中,并确保处于运行的健康状态;kubelet 不会管理不是由 Kubernetes 创建的容器(自主式与控制器管理的)。
  • kube-proxy
    是 Node 上的运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。它维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。
    如果操作系统提供了可用的数据包过滤层,则 kube-proxy 会通过它来实现网络规则。 否则,kube-proxy 仅做流量转发。
  • Container Runtime
    Kubernetes 支持许多容器运行环境,例如 containerd、 CRI-O 以及 Kubernetes CRI (容器运行环境接口) 的其他任何实现。

其他工具:

  • kubectl
    Kubernetes 命令行工具 kubectl, 让你可以对 Kubernetes 集群运行命令。 你可以使用 kubectl 来部署应用、监测和管理集群资源以及查看日志。
  • CoreDNS
    可以让集群内(SVC)使用自定义域名来访问
  • Ingress
    官方默认 4 层负载均衡,它可以实现 7 层。
  • Prometheus
    集群监控能力
  • ELK
    日志接入、分析平台
  • Federation
    跨集群统一管理支持

在命令行界面使用 Kubectl 创建和管理 Deployment。Kubectl 是使用 Kubernetes API 与集群进行交互的。

Service/SVC

Service 是将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法(或者说是用于暴露应用程序网络服务的对象类型)。Kubernetes 服务代理会自动将服务请求分发到正确的容器集,无论这个容器集会移到集群中的哪个位置,甚至可以被替换掉(Pod 销毁重建后 IP 会改变)。具有的特性:

  • Service 通过 label 关联对应的 Pod
  • Servcie 生命周期不跟 Pod 绑定,不会因为 Pod 重创改变 IP
  • 提供了负载均衡功能,自动转发流量到不同 Pod
  • 可对集群外部提供访问端口
  • 集群内部可通过服务名字访问

Service 可以将应用程序的一个或多个副本绑定在一个虚拟 IP(ClusterIP)上,并为集群中的其他对象提供一个固定的 DNS 名称。Service 可以用来实现应用程序的负载均衡、服务发现和内部通信等功能。
Kubernetes 支持以下几种类型的 Service:

  1. ClusterIP:将 Service 暴露在集群内部,只能通过集群内部的 IP 地址访问,仅在集群内部可用(默认)。
    适用于服务间通信,通常用于微服务架构中,例如 Web 后端和数据库之间的通信。可以避免服务重启后的 IP 变动的影响;
  2. NodePort:将 Service 暴露在每个节点上的固定端口上,可以通过节点的 IP 地址和端口号访问,内部也可以使用该 Service 的 DNS 名称来访问集群内的服务,有一定的 LB 效果。
    适用于需要将 Service 暴露给集群外部的情况。
  3. LoadBalancer:将 Service 暴露在外部负载均衡器上,可以通过负载均衡器的 IP 地址和端口号访问,一般需要花钱购买云服务商提供的 LB 服务。
  4. ExternalName:将 Service 作为一个 DNS 名称暴露出去,可以通过该名称访问 Service,相当于是一条内部的 CNAME 记录。
    如果正在使用外部系统作为后端服务,并希望在 Kubernetes 中将其命名为 Service,可以使用 ExternalName 来实现。

Service 可以与 Deployment、StatefulSet、DaemonSet 等控制器对象类型配合使用,以实现应用程序的水平扩展和负载均衡等功能。

Service 的 ClusterIP 地址是由 kube-proxy 组件负责维护和更新的。kube-proxy 主要有三种模式:userspace、iptables 和 ipvs。不同的模式实现方式不同,但其基本原理都相同,都是通过监听 Kubernetes API Server 发送的事件来实现 Service IP 地址的自动更新。
主要用到的就是两种,目前最新版本都推荐使用 IPVS;

  • iptables
    kube-proxy 组件使用 iptables 规则来实现 Service 的负载均衡和 IP 地址转发。在该模式下,kube-proxy 会监控 Kubernetes API Server 发送的事件,并根据事件信息生成或更新相应的 iptables 规则。这些规则可以将请求转发到正确的后端 Pod,并保证源 IP 地址不变。
    客户端访问 SVC,通过 iptables 路由到具体 pod。
  • ipvs
    kube-proxy 组件使用 Linux 内核中的 IPVS(IP Virtual Server)模块来实现 Service 的负载均衡和 IP 地址转发。与 iptables 不同,ipvs 可以快速处理大量的网络连接,并支持多种负载均衡算法和自动故障检测与恢复机制。在该模式下,kube-proxy 会监控 Kubernetes API Server 发送的事件,并根据事件信息生成或更新相应的 ipvs 规则。

总之就是它们原理上差不多,但是 ipvs 具有更好的性能。这里有个点可能不太好理解,就是 SVC 也要使用 Node 节点的 IP 访问,我直接暴露 pod 的端口不就行了吗?

首先,集群内部的情况下,更普遍地会使用 Service 名称来访问 Service,而不是直接使用其 IP 地址。当创建一个 Service 后,Kubernetes 会自动为该 Service 分配一个 DNS 名称,并将该名称与 Service 的 ClusterIP 绑定。
例如使用 NodePort 方式时,会在每个节点上分配一个端口,并将该端口映射到 Service 的 ClusterIP 上。ClusterIP 是一个虚拟 IP 地址,这个 ClusterIP 不属于任何一个节点,而是由 Kubernetes 控制平面管理。
外部客户端也可以使用任何的节点 IP 和暴露的端口进行访问,请求会根据其端口对应的 Service 配置找到与该服务关联的 ClusterIP 地址,并将客户端的请求路由到该地址。
一旦请求到达 Service 后,Kubernetes 将使用负载均衡算法(例如 Round Robin),将请求路由到后面运行的一组 Pod 上。这些 Pod 可以运行任何位置,包括不同节点上的多个 Pod。


Headless Service 是一种特殊的 Service 类型,它不会为 Service 分配 Cluster IP(clusterIP: None),而是直接返回后端 Pod 的 IP 地址列表。换句话说,Headless Service 不会负责转发请求到具体的 Pod。一个非常有用的作用是 StatefulSet。
它主要用于 DNS 解析和集群内服务的发现。例如,当用户使用 DNS 名称来访问 Service 时,Kubernetes 可以通过 Headless Service 将 DNS 请求解析成与 Service 相关联的所有 Pod 的 IP 地址列表,并返回给用户。这样,用户就可以直接与 Pod 进行通信,而无需经过 Service 和其背后的负载均衡器
由于 Headless Service 不涉及负载均衡和 IP 地址转发,因此它的性能和稳定性通常比普通 Service 更高。此外,Headless Service 还支持 Kubernetes 中的服务发现机制,能够自动监测和更新后端 Pod 的状态变化,确保始终返回最新的 IP 地址列表。因为如果直接暴露了 Pod 的 IP 地址,因此必须提前考虑好网络安全和访问控制等问题。

Ingress

Ingress 是一种 API 对象,用于将外部流量路由到集群内的 Service 上。它提供了一种灵活、统一和扩展性强的方式来管理 HTTP 和 HTTPS 流量,并支持多种负载均衡算法、路径匹配规则和 TLS 加密等功能。

使用 Ingress 能够方便地管理集群中的多个 Service,并将其暴露给外部客户端。Ingress 可以实现以下功能:

  1. 路径匹配:可以根据请求的 URL 路径将流量路由到不同的后端 Service 上。
  2. 主机名匹配:可以根据请求的主机名(即域名)将流量路由到不同的后端 Service 上。
  3. TLS 加密:可以对 Ingress 进行 TLS 加密,保护客户端与服务端之间的通信安全。
  4. 多种负载均衡算法:可以根据需求选择不同的负载均衡算法,如轮询、最小连接数等。

需要注意的是,要使用 Ingress 需要满足以下条件:

  1. 集群中必须存在一个符合规范的 Ingress Controller(如 Nginx、Traefik、Haproxy 等),用于监听 Ingress 对象的变化并更新对应的负载均衡器或反向代理。
  2. 需要为每个 Ingress 配置一个规则,指定其路径、主机名、后端 Service (其类型设置为 NodePortLoadBalancer)等相关信息。
  3. 如果需要对 Ingress 进行 TLS 加密,则需要先创建一个 Kubernetes Secret,用于存储证书和私钥等敏感信息,并将其与 Ingress 绑定。

使用最多的还是 Ingress-Nginx,本质来说其实就是启动了一个 Nginx,只不过不需要我们去写 NG 的配置文件而使用 k8s yml 自动完成了。
Ingress 可以帮我们实现七层代理,原本只支持到四层代理。

七层代理和四层代理都是计算机网络中常用的代理类型,它们在不同的 OSI 模型层次上工作并提供了不同的功能。

  • 四层代理(传输层代理):工作在 OSI 模型的传输层,主要负责对网络连接进行管理和控制。四层代理能够根据源 IP 地址、目标 IP 地址、源端口号和目标端口号等信息来对传输的数据进行转发,以达到负载均衡、流量控制和安全过滤等目的。
  • 七层代理(应用层代理):工作在 OSI 模型的应用层,具有更高的可扩展性和灵活性。七层代理能够深入了解应用程序的协议、数据格式和语义,并对传输的数据进行精细化处理。七层代理可以根据应用程序的特殊需求,对数据进行修改、重写和过滤,以实现更高级别的功能,如内容缓存、反向代理、Web 加速和应用层防火墙等。

四层代理更依赖于基本的网络传输协议,而七层代理则更加注重应用程序的细节和语义。
简单说就是四层代理更加底层,速度快延迟低,占用资源也少,而七层具有更高的灵活性。

Ingress 与 SVC 之间可能会有点难以理解,尤其是跟 SVC 的 NodePort 对比,简单说 Ingress 是已经暴露了一个 IP 和端口,终端用户可以直接通过 Ingress 暴露的 IP 进行访问。此时,后面运行的 Service 的 type 类型是否为 ClusterIP 或 NodePort 在某种程度上已经不再重要了。

不过在同等条件下,NodePort 类型的 Service 可能会比 ClusterIP 类型的 Service 略微快一些;
NodePort 类型的 Service 可能会更加不可靠一些,因为它需要暴露节点上的端口,可能会遇到端口号冲突、网络分区等问题。

存储

ConfigMap

ConfigMap 是一种用于存储配置数据的 API 对象,它可以将配置数据从 Pod 代码中分离出来,实现了配置和代码的分离,提高了应用程序的可移植性和可维护性。
ConfigMap 可以是一个文件或者文件夹,或者是硬编码到 YAML 中;使用上可以通过环境变量或者挂载 Volume 的方式;
需要注意的是,ConfigMap 存储的数据为纯文本格式,因此不适合存储大型二进制文件。

Secret

Secret 是一种用于存储敏感信息的 API 对象,例如密码、证书等。Secret 可以对数据进行加密处理,并提供各种不同类型的加密方式和安全性保障。
Kubernetes 中的 Secret 存储常用的三种类型:

  1. Opaque:Opaque 类型的 Secret 是最通用的类型,它可以存储任意格式的数据。Opaque Secret 中的数据将会被编码为 base64 格式,但并未进行加密
  2. Service Account:Service Account 类型的 Secret 主要用于身份验证和授权,包含了一个或多个令牌,用于验证 Pod 中的容器是否具有访问其他资源的权限。
  3. docker-registry:用来存储 Docker 仓库的认证信息和配置信息,并在容器中使用该 Secret 来进行身份验证和授权操作。
    在资源清单中使用 imagePullSecrets 来在 pull 镜像时进行认证。

Kubernetes 中的 Service Account 只能用于访问 Kubernetes API 或其他与 Kubernetes 集群相关的资源和对象,并且不适用于外部服务或资源的访问。
Service Account 通常由应用程序自动使用,并由 Kubernetes 自动处理。如果声明了 Service Account 会自动挂载到 /run/secrets/kubernetes.io/serviceaccount,部分发行版或者老的 Linux 会在 /var/run 下。

Opaque 在使用时,不管是环境变量还是挂载,都会自动解码,当然存储的时候也要求值必须是 base64.

Volume

Volume 是一种用于持久化和共享数据的抽象概念。Volume 可以将不同类型的存储介质(例如本地磁盘、网络存储或云存储等)封装为统一的接口,并在 Pod 中使用。
Volume 一些常见的类型:

  • emptyDir
    emptyDir 是一种临时性的 Volume,用于在单个 Pod 的多个容器之间共享数据。emptyDir 将数据存储在 Pod 所在的节点上,并在 Pod 被删除或重新调度时自动清理
    需要注意的是,当 Pod 中的容器崩溃尝试重启/新建时 Volume 不会清除数据。
  • hostPath
    hostPath 是一种将主机节点上的文件或目录作为 Volume 挂载到 Pod 中的方法。hostPath 可以让 Pod 访问主机节点上的文件系统(或者主机访问 Pod 中的文件),但也可能导致安全性问题和资源争用。

其他的还有很多类型,因为用的不多就不贴了。

PV/PVC

PersistentVolume(PV)是一种用于持久化存储数据的资源对象。PV 可以将不同类型和容量的存储介质(例如本地磁盘、网络存储或云存储等)封装为统一的接口,并在整个 Kubernetes 集群中使用。
区别与 Volume 的几个特点:

  • 范围
    Volume 是一个容器级别的概念,用于将数据持久化到 Pod 中。而 PV 是一个集群级别的概念,用于将数据持久化到整个 Kubernetes 集群中。
  • 生命周期
    Volume 的生命周期与 Pod 相关联,当 Pod 被删除或重启时,相关的 Volume 也会被删除或重新创建。而 PV 则独立于 Pod 存在,并且可以在多个 Pod 之间共享和复用。
  • 管理方式
    Volume 可以在 Pod 中直接定义和管理,而 PV 则需要通过 PersistentVolume 和 PersistentVolumeClaim 对象进行定义和管理。
  • 耦合性
    PV 将存储介质与 Pod 解耦,使得 Pod 可以从实际存储细节中隔离出来。这使得存储介质可以轻松地更换和升级,而无需对 Pod 进行修改。
    同理,当 Pod 删除时,PVC 并不会被删除,依然可以为其他 Pod 提供服务。

而 PersistentVolumeClaim(PVC)则可以理解为存储资源的使用者,它定义了对 PV 的访问要求,例如存储类型、访问模式和容量等信息。PVC 可以请求 Kubernetes 动态分配或静态绑定一个 PV,并将其挂载到 Pod 中,以实现数据的持久化和共享。

PVC 概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源(CPU 和内存);同样 PVC 申领也可以请求特定的大小和访问模式 (例如,可以要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载)。

当 PVC 请求一个 PV 时,Kubernetes 会根据 PVC 的要求,在可用的 PV 池中寻找匹配的 PV。如果找到多个匹配的 PV,则 Kubernetes 会按照一定的策略进行选择和绑定。一旦绑定成功,PVC 和 PV 就形成了一种类似于 “占位符” 的关系。当 PVC 被删除时,它会释放与之关联的 PV。
一个 PV 可以被多个 PVC 绑定和使用,但每个 PVC 只能绑定一个 PV。如果多个 PVC 请求同一个 PV,则 Kubernetes 会按照先来先服务的原则进行分配,直到 PV 的容量用尽为止。


根据 PV 的创建方式可分为两种:

  1. 静态PV
    手动分配的方式,它要求管理员提前创建好一定数量的 PV,并将其存储属性和访问模式等信息进行配置。
    静态 PV 的优点是稳定可靠,但缺点是不够灵活,难以应对动态变化的需求。
  2. 动态PV
    自动分配的方式,它利用 Kubernetes 动态资源管理特性,根据 PVC 对 PV 的请求,动态地创建、绑定和管理 PV。
    动态 PV 的优点是灵活方便,可以动态适应不同的需求,但缺点是可能会产生较大的管理负担。

动态 PV 一般是配合云计算服务来使用的,主要是价格昂贵。


每个 PersistentVolume(PV)都有一个访问模式(Access Mode),用于定义 Pod 如何访问 PV 中的数据。Kubernetes 支持以下三种访问模式:

  1. ReadWriteOnce(RWO):
    只允许单个节点以读写方式挂载 PV。这意味着同一时间内只能有一个 Pod 访问该 PV,并且只能将其挂载到同一个节点上。
  2. ReadOnlyMany(ROX):
    允许多个节点以只读方式挂载 PV。这意味着多个 Pod 可以同时访问该 PV,并且可以将其挂载到多个节点上,但不能进行写操作。
  3. ReadWriteMany(RWX):
    允许多个节点以读写方式挂载 PV。这意味着多个 Pod 可以同时访问该 PV,并且可以将其挂载到多个节点上,也可以进行读写操作。

当 PersistentVolume(PV)上的数据不再需要时(当其被从申领中释放时如何处理该数据卷),可以使用回收策略对 PV 进行清理和释放。Kubernetes 提供了以下三种回收策略:

  1. Retain(保留):
    指定在被释放后保留其数据。这意味着 PV 中的数据不会被删除,并且管理员需要手动清理它们。通常用于需要手动备份或迁移数据的场景。
    例如当 PVC 被删除时,由于卷上仍然存在这前一申领人的数据,该卷还不能用于其他申领。
  2. Delete(删除):
    删除 PVC 时也会将 PV 对象从 Kubernetes 中移除,同时也会从外部基础设施(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)中移除所关联的存储资产。
  3. Recycle(回收):
    在被释放后重新格式化存储介质并清除所有数据。
    在新版本中,回收策略 Recycle 已被废弃。取而代之的建议方案是使用动态制备。

PV 的回收策略是在 PersistentVolumeClaim(PVC)被删除后触发的。具体而言,当一个 PVC 被删除时,Kubernetes 会检查其绑定的 PV 是否仍然被其他 PVC 使用,如果没有,则会按照该 PV 的回收策略进行清理和释放。


使用 PV 时,每个卷会处于以下阶段(Phase)之一:

  • Available(可用)– 卷是一个空闲资源,尚未绑定到任何申领;
  • Bound(已绑定)– 该卷已经绑定到某申领(PVC);
  • Released(已释放)– 所绑定的申领已被删除,但是资源尚未被集群回收;也就是对应的 PVC 被删除。
  • Failed(失败)– 卷的自动回收操作失败。

区别于 PVC 的状态,当查看 PVC 状态时,也会列出绑定的 PV 的状态,而 PVC 的状态一般是:Pending/Bound/Lost。

对于 StatefulSet 当 Pod 重建后依然有相同的网络标识符,可以绑定之前的 PVC 保证数据不会丢失(每一个副本会有单独的 PVC);对于在 Deployment 资源清单中配置的副本和 PVC,所有 Pod 会共享 PVC,也不需要考虑新建还是更新的了(猜测,未证实)。

网络策略

在 Kubernetes 中,有两种主要的网络模型:Overlay 网络和基于主机的网络。

  1. Overlay 网络:Overlay 网络是一种虚拟网络,它在物理网络之上创建一个逻辑网络,用于容器之间的通信。Overlay 网络通常使用隧道技术(如 VXLAN、GRE、IPsec 等)将容器数据包封装在物理网络的数据包中传输。Kubernetes 中的 Flannel、Calico(更推荐吧)、Weave Net 等网络插件都是基于 Overlay 网络实现的。
  2. 基于主机的网络:基于主机的网络是一种直接将容器连接到主机网络上的网络模型,容器与主机之间共享同一个网络命名空间。这种网络模型通常使用 Linux Bridge 或者直接使用主机网络接口来实现。Kubernetes 中的 kube-proxy 就是基于主机的网络模型实现的。

Flannel 是一个用于容器网络的开源项目,旨在为 Kubernetes 集群提供简单、快速、可靠的网络连接。Flannel 的主要作用是将容器连接到同一网络中,并允许它们之间进行通信。Flannel 通过在每个节点上创建一个虚拟网络(VXLAN 或 UDP),将容器的 IP 地址映射到集群中的其他节点上。这种方式可以实现跨节点的容器通信,同时保证容器的 IP 地址在整个集群中唯一
对于实现的原理,简单说就是维护一个路由表(使用 ETCD),因为每个 Node 都有 Flanneld,利用路由表可以共享 IP 对应信息,在进行集群初始化的时候需要安装一下,可以在 kubeadm 的默认模板中事先配置好。

1
2
3
4
5
6
7
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 修改配置文件,例如 - --iface=eth0

# 安装
kubectl apply -f kube-flannel.yml
# 查看 pod
kubectl get pods --all-namespaces

以上,可以在 kubeadm 初始化完成后使用 kubectl 快速安装。

集群调度

在 Kubernetes 中,调度 是指将 Pod 放置到合适的节点上,以便对应节点上的 Kubelet 能够运行这些 Pod。默认的调度器就是 kube-scheduler。
调度过程一般可划分为两个阶段,过滤和打分;
过滤阶段会将所有满足 Pod 调度需求的节点选出来。 例如,PodFitsResources 过滤函数会检查候选节点的可用资源能否满足 Pod 的资源请求。
在打分阶段,调度器会为 Pod 从所有可调度节点中选取一个最合适的节点。 根据当前启用的打分规则,调度器会给每一个可调度节点进行打分。最后会将 Pod 调度到得分最高的节点上。如果存在多个得分最高的节点,kube-scheduler 会从中随机选取一个。
这里会有一些可选的调度策略,例如 CPU 或者 内存占用最低的优先。

podspec.nodename 是 PodSpec 的另一个属性,用于指定 Pod 所部署的节点名称。当 Pod 的 podspec.nodename 属性被设置时,Kubernetes 调度器将不会再考虑其他节点来调度该 Pod,并且会直接将该 Pod 分配给指定的节点上运行;这种方式称为静态 Pod 调度,当然也可以使用标签选择。

节点亲和性(Node Affinity)是指将 Pod 调度到与其相关的节点上的能力。通俗来说,它可以让我们通过一些限制条件(如硬件配置、软件环境等)来控制 Pod 应该部署在哪些节点上;其中又分为软策略和硬策略,也就是尽量满足和必须满足。

污点(Taint)是一种标记,用于指示节点上存在特定的限制条件,这些条件会影响 Pod 在该节点上的调度。与节点亲和性(Node Affinity)相反,污点可以使节点更具有选择性,以便根据实际需求来控制 Pod 不能被调度到某些节点上。
容忍度(Toleration) 是应用于 Pod 上的。容忍度允许调度器调度带有对应污点的 Pod。 容忍度允许调度但并不保证调度:作为其功能的一部分, 调度器也会评估其他参数。
污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod, 是不会被该节点接受的。
我们建立的 Pod 不会运行在 Master 节点就是使用了这个特性打了一个 NoSchedule。

K3s

Rancher Labs 是业界领先的容器软件提供商,其旗舰产品 Rancher 是一款开源的企业级 Kubernetes 管理平台,极为出色地管理和安装 Kubernetes 集群。

k3s 将安装 Kubernetes 所需的一切打包进仅有 60MB 大小的二进制文件中,并且完全实现了 Kubernetes API。为了减少运行 Kubernetes 所需的内存,Rancher 删除了很多不必要的驱动程序,并用附加组件对其进行替换。K3s 仅需要 kernel 和 cgroup 挂载。
k3s 是一款完全通过 CNCF 认证的 Kubernetes 发行版,这意味着你可以编写 YAML 来对完整版的 Kubernetes 进行操作,并且它们也将适用于 k3s 集群。
由于它只需要极低的资源就可以运行,因此它能够在任何 512MB RAM 以上的设备上运行集群,换言之,我们可以让 pod 在 master 和节点上运行。专为物联网及边缘计算设计。

所以,对于日常开发用,K3s 是个比 Minikube 更好的选择,介于 Minikube 和 K8s 之间的最优解。如果你处于边缘计算等小型部署的场景或仅仅需要部署一些非核心集群进行开发/测试,那么选择 k3s 则是性价比更高的选择。

与 K8s 对比:

  • 移除过时的功能、Alpha 功能、非默认功能,这些功能在大多数 Kubernetes 集群中已不可用。
  • 删除内置插件(比如云供应商插件和存储插件),可用外部插件程序替换。K3s 在默认状态下只会启动除自身进程之外的两个应用:coredns 和 traefik。

  • 添加 SQLite3 作为默认的数据存储。etcd3 仍然可用,但并非默认项。

  • 默认执行容器从 docker 换成了 containerd。

  • 封装在简单的启动程序中,该启动程序处理很多复杂的 TLS 和选项。

  • 内置了 local storage provider、service load balancer、helm controller、Traefik ingress controller,开箱即用。
  • 所有 Kubernetes 控制平面组件如 api-server、scheduler 等封装成为一个精简二进制程序,控制平面只需要一个进程即可运行。

综上,一般来说,K3s 基本也满足大部分需求了。k3s 官方准备了一键安装脚步,部署非常方便:

1
2
3
4
5
# 主/Server 节点
curl -sfL https://get.k3s.io | sh -

# node/Agent 节点
curl -sfL https://get.k3s.io | K3S_URL=https://myserver:6443 K3S_TOKEN=mynodetoken sh -

接着就可以部署 Rancher 进行多集群管理了,最好找一台独立的机器,支持 Helm 或者 Docker 的方式进行部署,操作也非常简单,一行命令搞定,然后根据引导界面选择新建集群还是导入已有集群,也就是执行几行命令的事,因为 K8s 已经不支持 dockershim,之前都是用 docker 作为容器运行时,目前新版的 k3s 已经切换到 containerd,当然也可以通过 cri-dockerd 继续使用 Docker。

而另一个 Rancher 出品的 k8s 集群部署工具 RKE 也挺不错的,功能类似 kubeadm 都主要用来快速初始化集群。

RKE(Rancher Kubernetes Engine)是经过认证的 Kubernetes 发行版,也是用于创建和管理 Kubernetes 集群的 CLI 工具和库。
RKE 是一款经过 CNCF 认证的开源 Kubernetes 发行版,可以在 Docker 容器内运行。它通过删除大部分主机依赖项,并为部署、升级和回滚提供一个稳定的路径,从而解决了 Kubernetes 最常见的安装复杂性问题。

RKE2,也称为 RKE Government,是 Rancher 的下一代 Kubernetes 发行版。RKE2 完美结合了 1.x 版本的 RKE(以下简称 RKE1)和 K3s。
重要的是,RKE2 不像 RKE1 一样依赖 Docker。RKE1 使用 Docker 来部署和管理 control plane 组件以及 Kubernetes 的容器运行时。RKE2 将 control plane 组件作为由 kubelet 管理的静态 pod 启动。嵌入式容器运行时是 containerd。

无论安装哪一个,安装的时候一定要注意版本对应,可以从这里查阅版本的支持范围。

不得不说,Rancher 真是把 k8s 弄到了开箱即用,生产环境下也完全不是问题,并且文档有中文,赞。
爱折腾的可以尝试使用 Rancher Desktop 来代替开发机的 Docker,它内置 k3s 应该表现还是可以的。

常用命令整理

minikube

1
2
3
4
5
6
7
8
9
10
# 启动集群
minikube start
# 查看节点。kubectl 是一个用来跟 K8S 集群进行交互的命令行工具
kubectl get node
# 停止集群
minikube stop
# 清空集群
minikube delete --all
# 安装集群可视化 Web UI 控制台
minikube dashboard

kubectl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 部署应用,使用 create 创建如果存在会返回失败
kubectl apply -f app.yaml
# 快速创建一个 pod,1.18 后是使用 Deployment 来创建的
kubectl run mypod --image=myimage
# 查看 deployment,rs 也一样
# get 可以跟 pod/deployment/svc/rs
kubectl get deployment
# 查看 pod 详细信息
kubectl get pod -o wide
# 查看系统命名空间的 pod,默认是 default
kubectl get pod -n kube-system
# 查看 pod 详情
kubectl describe pod pod-name
# 查看 log
kubectl logs pod-name
# 进入 Pod 容器终端, -c container-name 可以指定进入哪个容器。
kubectl exec -it pod-name -- bash
# 伸缩扩展副本
kubectl scale deployment test-k8s --replicas=5
# 把集群内端口映射到节点
kubectl port-forward pod-name 8090:8080
# 查看历史
kubectl rollout history deployment test-k8s
# 回到上个版本
kubectl rollout undo deployment test-k8s
# 回到指定版本
kubectl rollout undo deployment test-k8s --to-revision=2
# 删除部署
kubectl delete deployment test-k8s

# 查看全部
kubectl get all
# 重新部署
kubectl rollout restart deployment test-k8s
# 命令修改镜像,--record 表示把这个命令记录到操作历史中
kubectl set image deployment test-k8s test-k8s=ccr.ccs.tencentyun.com/k8s-tutorial/test-k8s:v2-with-error --record
# 暂停运行,暂停后,对 deployment 的修改不会立刻生效,恢复后才应用设置
kubectl rollout pause deployment test-k8s
# 恢复
kubectl rollout resume deployment test-k8s
# 输出到文件
kubectl get deployment test-k8s -o yaml >> app2.yaml
# 删除全部资源
kubectl delete all --all


# 将一个已有的 Kubernetes 资源对象暴露为一个新的 Service
# 将名为 myapp 的 Deployment 暴露为一个新的 LoadBalancer 类型的 Service
kubectl expose deployment myapp --type=LoadBalancer --port=80 --target-port=8080
kubectl get svc

# 修改 SVC 网络类型
kubectl edit svc xxxx

更多可以直接问 ChatGPT。

资源清单

在 Kubernetes 中,资源清单(Resource Manifest)是一个包含 Kubernetes 对象定义的 YAML 文件。它描述了在 Kubernetes 集群中创建、配置或管理的任何一种对象,例如 Pod、Service、Deployment、ConfigMap 等。通常可以与 Kubectl 命令一起使用,例如:kubectl apply -f deployment.yaml

资源分类:

  • 命名空间级别
    即:只在当前的命名空间有效,
  • 集群级别
    全集群可用,可跨命名空间
  • 元数据型
    类似 HPA 这种通过指标来进行操作。也可归属于上面两种

资源清单中有一些属性属于必选:

  1. apiVersion
    Kubernetes API 的版本号。可通过 kubectl api-versions 查询
  2. kind
    资源对象的类型,例如 Pod、Service 或 Deployment。
  3. metadata
    元数据,包括资源对象的名称和标签等信息。
  4. spec
    资源对象的规格,包括容器设置、网络设置、存储设置以及其他相关信息。具体内容取决于资源对象的类型。

对于 metadata 和 spec,下面细分了很多项,下面展示一个最简单的清单文件:

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Pod
metadata:
name: mypod
# 标签易于管理
labels:
app: myapp
version: v1
spec:
containers:
- name: mycontainer
image: nginx

后续生成资源清单可以使用 Helm,然后配合 ChatGPT 进行微调。

补充:Cgroup

Cgroup,全称 Control Group(控制组),是 Linux 系统内核提供的一个特性(Linux 2.6.24内核开始将 Cgroup 加入主线),主要用于限制和隔离一组进程对系统资源的使用,也就是做资源 QoS。可控制的资源主要包括 CPU、内存、block I/O、网络带宽等等。

Cgroup 提供了一个原生接口并通过 cgroupfs 提供(从这句话我们可以知道 cgroupfs 就是 Cgroup 的一个接口的封装)。类似于 procfs 和 sysfs,是一种虚拟文件系统。并且 cgroupfs 是可以挂载的,默认情况下挂载在 /sys/fs/cgroup 目录。

Systemd 也是对于 Cgroup 接口的一个封装。systemd 以 PID 的形式在系统启动的时候运行,并提供了一套系统管理守护程序、库和实用程序,用来控制、管理 Linux 计算机操作系统资源。

相对来说 Systemd 更加简单,而且目前已经被主流 Linux 发行版所支持(Red Hat 系列、Debian 系列等),而且经过几个版本的迭代已经很成熟了,所以不管是 Docker 本身还是在 K8S 中建议使用 Systemd 来进行资源控制与管理。

cgroupfs 是文件驱动修改,内核功能没有提供任何的系统调用接口,而是对 linux vfs 的一个实现,因此可以用类似文件系统的方式进行操作。

systemd 封装了 cgroups 的软件也能让你通过它们定义的接口控制 cgroups 的内容,因此是通过接口调用驱动修改。

相关工具

对于一些场景,我们需要使用代码来控制 K8s,这方面可以使用 Kubernetes API 来实现,官方提供了 REST API 的接口,也可以使用相关语言的 SDK 来实现。

文档参考:https://kubernetes.io/zh-cn/docs/concepts/overview/kubernetes-api/

集群之间都是通过证书来进行认证的,证书由 Master 进行签发,而 Pod 因为会频繁新建和销毁,签发证书的方式就不太合适,使用的是 Service Accounts 它被用于为 Pod 提供访问 Kubernetes API 和其他 Kubernetes 资源的标准方式。每个 Service Account 都会分配一个唯一的名称和一个对应的 Token,该 Token 可以被应用程序用来进行身份验证和授权。每个 Pod 都有一个默认的 Service Account,上面 Secret 中介绍过。

关于鉴权,则推荐使用 RBAC 方式,它声明了四种 Kubernetes 对象:RoleClusterRoleRoleBindingClusterRoleBinding。带有 Cluster 的则表示是集群级别的权限,否则需要指定是那个命名空间下的权限。
Role 通常与 Role Binding 结合使用,用于将指定的角色分配给特定的用户或服务账户。而 ClusterRole 则通常与 ClusterRoleBinding 结合使用,用于将角色分配给整个集群的用户或服务账户。
K8s 不提供用户管理,在证书签发时已经包含了这部分信息。

可视化可以使用 kubernetes-dashboard
监控可以用 Prometheus、Grafana

参考

K8s入门
Docker、Containerd、RunC扫盲
kubectl命令表
Kubernetes组件
k3s vs k8s vs k9s
鉴权

喜欢就请我吃包辣条吧!

评论框加载失败,无法访问 Disqus

你可能需要魔法上网~~