GitOps 实践理论:Kubernetes 部署策略深入解析

今天我们来看看 kubernetes 和 gitops 的理论实践 命令介绍 首先我们来看看 kubectl 支持的子命名,方便我们使用: kubectl apply - 应用一个或多个资源的定义。通常用于部署应用程序或更新资源。 kubectl get - 显示一个或多个资源的信息。这是查看 Kubernetes 集群中资源状态的常用命令。 kubectl describe - 显示一个或多个资源的详细信息,如事件、状态和配置。 kubectl delete - 删除 Kubernetes 集群中的资源。 kubectl exec - 在集群中的容器里执行命令。 kubectl logs - 打印容器的日志。 kubectl create - 从文件或标准输入中创建一个或多个资源。 kubectl edit - 编辑集群中的资源。这将打开一个编辑器来修改资源的配置。 kubectl port-forward - 将本地端口转发到集群中的 Pod。 kubectl run - 在集群中运行一个指定的镜像。 kubectl scale - 调整资源(如 Deployment、ReplicaSet)的副本数量。 kubectl rollout - 管理资源的部署,如查看状态、暂停、恢复或回滚更新。 除了上面的命令,Kubernetes 中的 kubectl 还支持注解: kubectl annotate 命令用于给 Kubernetes 集群中的资源添加或更新注解(annotations)。注解是一种附加信息,可以用于存储非识别性的元数据。它们通常用于管理工具、库和客户端以存储辅助信息,例如描述、版本信息等。...

November 25, 2023 · 10 分钟 · 2034 字 · Xinwei Xiong, Me

Hugo 的高级教程

136: Hugo 进阶 来到进阶部分,就需要深度学习一些 Hugo 的高级技巧。 模块 Hugo 模块是 Hugo 的核心构建块。模块可以是您的主项目或较小的模块,提供 Hugo 中定义的 7种组件类型中的一种或多种:static、content、layouts、data、assets、i18n和archetypes。 您可以按照您喜欢的任何组合来组合模块,甚至可以挂载非 Hugo 项目的目录,形成一个大型的虚拟联合文件系统。 Hugo 模块由 Go 模块提供支持。有关 Go 模块的更多信息,请参阅: https://github.com/golang/go/wiki/Modules https://go.dev/blog/using-go-modules 一些示例项目: https://github.com/bep/docuapi是一个在测试此功能时已移植到 Hugo Modules 的主题。这是将非 Hugo 项目安装到 Hugo 文件夹结构中的一个很好的示例。它甚至展示了常规 Go 模板中的 JS Bundler 实现。 https://github.com/bep/my-modular-site是一个非常简单的用于测试的网站。 模块配置: top level 💡简单的一个案例如下: module:noProxy:nonenoVendor:""private:'*.*'proxy:directreplacements:""workspace:"off"noVendor 一个可选的Glob模式匹配模块路径,当自动售货时跳过,例如 github.com/** vendorClosest 启用后,我们将选择与使用它的模块最近的供应商模块。默认行为是选择第一个。请注意,给定的模块路径仍然只能有一个依赖项,因此一旦使用它,就不能重新定义它。 proxy 定义用于下载远程模块的代理服务器。默认值是 direct ,意思是“git clone”或类似的。 noproxy 逗号分隔的glob列表匹配不应使用上面配置的代理的路径。 private 逗号分隔的glob列表匹配应被视为私有的路径。 workspaces 要使用的工作区文件。这将启用Go工作区模式。请注意,这也可以通过OS env设置,例如 export HUGO_MODULE_WORKSPACE=/my/hugo.work 这只适用于Go 1.18+。在Hugo v0.109.0 中,我们将默认值更改为 off ,现在我们可以解析相对于工作目录的任何相对工作文件名。...

November 6, 2023 · 15 分钟 · 3098 字 · 熊鑫伟, Me

OpenIM 使用 Harbor 构建企业镜像仓库

需求 OpenIM 提供了多种公共的镜像注册地址,比如说 aliyun, github, Docker hub ~ 阅读 https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/images.md 获取更多的镜像构建指南。 大部分企业都会选择自己做镜像仓库,使用 Harbor 来搭建企业级的镜像仓库,将它集成 CICD Pipeline 流程中,最终替换 Docker Hub,进一步降低镜像存储的成本。 此外,在生产环境下,Harbor 一般都会开启 TLS,所以你还需要准备一个可用的域名。 中国的服务器使用域名,需要对域名进行备案 安装 Helm Helm,以及 集群的部署参考 https://github.com/openimsdk/open-im-server/tree/main/deployments 安装 Cert-manager 接下来我们安装 Cert-manager,它会为我们自动签发免费的 Let’s Encrypt HTTPS 证书,并在过期前自动续期。 首先,运行 helm repo add 命令添加官方 Helm 仓库。 $ helm repo add jetstack https://charts.jetstack.io 然后,运行 helm repo update 更新本地缓存。 $ helm repo update 接下来,运行 helm install 来安装 Cert-manager。 $ helm install cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --version v1....

October 25, 2023 · 2 分钟 · 350 字 · 熊鑫伟, Me

自动化测试的学习(一)

云原生领域中GitHub开源Go项目的自动化测试实践与策略 介绍 作为 Github 上的 热门项目 OpenIM,如何在云原生时代中创造出价值,这是非常重要的,OpenIM 是一个优质的小团队,我们在自动化中并没有特别深入的见解。 使用 GitHub Actions 进行持续集成和持续交付 (CI/CD): GitHub Actions 提供了一个平台,可以自动构建和测试 Go 语言项目。通过配置 GitHub Actions 工作流,你可以在代码更改时自动运行测试,确保代码的质量和功能。 KubeVela 项目实践: KubeVela 是一个 Go 语言的云原生和开源项目,它展示了如何在云原生环境中组织 CI/CD 过程,包括自动化测试。KubeVela 使用声明性工作流来协调 CI/CD 过程,你可以参考 KubeVela 的 GitHub 仓库来理解和应用这些实践34[5](https://github.com/kubevela/workflow#:~:text=KubeVela Workflow is an open,engine in your own repository)。 云原生测试框架与工具: 在云原生开发中,合约测试(Contract Testing)是一种常见的测试实践,它确保服务间的通信符合预定义的 API 协议。例如,Cloud-Native Toolkit 中使用 Pact 进行合约测试。通过编写和集成测试,你可以验证服务间的通信是否符合预期6。 代码覆盖率检查: 在进行自动化测试时,检查代码覆盖率是一个好的实践。许多测试框架内置了代码覆盖率检查功能,可以配置它们来报告测试的代码覆盖率。例如,使用 SonarQube 工具来读取和报告代码覆盖率信息6。 利用开源工具和框架: 你可以利用开源工具和框架来进行测试,例如使用 Cypress 进行云原生应用的测试[7](https://dev....

October 14, 2023 · 17 分钟 · 3593 字 · 熊鑫伟, Me

Kubernetes 控制平面 - Kubectl

Kubelet组件解析 理解 kubelet Kubelet组件运行在Node节点上,维持运行中的Pods以及提供kuberntes运行时环境,主要完成以下使命: 1.监视分配给该Node节点的pods 2.挂载pod所需要的volumes 3.下载pod的secret 4.通过docker/rkt来运行pod中的容器 5.周期的执行pod中为容器定义的liveness探针 6.上报pod的状态给系统的其他组件 7.上报Node的状态 kubelet 管理Pod的核心流程主要包括三个步骤。首先,kubelet获取Pod清单,可以通过文件、HTTP endpoint、API Server和HTTP server等方式获取。其次,节点管理主要是节点自注册和节点状态更新,Kubelet在启动时通过API Server注册节点信息,并定时向API Server发送节点新消息,API Server在接收到新消息后,将信息写入etcd。最后,Pod启动流程主要包括镜像拉取、容器启动、探针监控以及状态汇报等步骤。 kubelet是Kubernetes中的一个节点代理程序,负责维护本节点上Pod的生命周期。kubelet是Kubernetes中非常重要的组件之一,它在Kubernetes集群中扮演着非常重要的角色。kubelet可以在每个节点上运行,它监视分配给该Node节点的pods,并执行各种管理容器的操作,如挂载pod所需要的volumes、下载pod的secret等。 kubelet的核心流程主要包括获取Pod清单、节点管理和Pod启动流程。其中,获取Pod清单的方式包括文件、HTTP endpoint、API Server和HTTP server等方式。节点管理主要包括节点自注册和节点状态更新,而Pod启动流程主要包括镜像拉取、容器启动、探针监控以及状态汇报等步骤。 在节点管理方面,kubelet可以通过设置启动参数-register-node来确定是否向API Server注册自己。如果kubelet没有选择自注册模式,则需要用户自己配置Node资源信息,同时需要告知kubelet集群上的API Server的位置。在启动时,kubelet会通过API Server注册节点信息,并定时向API Server发送节点新消息,API Server在接收到新消息后,将信息写入etcd。 在Pod管理方面,kubelet可以通过文件、HTTP endpoint、API Server和HTTP server等方式获取Pod清单。文件方式主要用于static pod,而HTTP和API Server方式则是Kubernetes中常用的方式。HTTP server主要用于kubelet侦听HTTP请求,并响应简单的API以提交新的Pod清单。 在Pod启动流程方面,kubelet会执行各种管理容器的操作,包括镜像拉取、容器启动、探针监控以及状态汇报等步骤。镜像拉取是Pod启动过程中的一项重要工作,kubelet可以通过imageManager模块来管理镜像。容器启动是Pod启动过程的下一步,kubelet通过container runtime来启动容器。探针监控是Pod启动过程中一项非常重要的工作,kubelet会周期性地执行pod中为容器定义的liveness探针,并将结果上报给系统的其他组件。状态汇报是kubelet的一个重要功能,它会上报pod和Node的状态给系统的其他组件,以及上报节点自身的状态和资源使用情况给API Server。 总之,kubelet是Kubernetes中非常重要的组件之一,它负责维护本节点上Pod的生命周期,并执行各种管理容器的操作。kubelet的核心流程包括获取Pod清单、节点管理和Pod启动流程。在节点管理方面,kubelet通过设置启动参数-register-node来确定是否向API Server注册自己。在Pod管理方面,kubelet可以通过文件、HTTP endpoint、API Server和HTTP server等方式获取Pod清单。在Pod启动流程方面,kubelet会执行各种管理容器的操作,包括镜像拉取、容器启动、探针监控以及状态汇报等步骤。 kubelet 架构 每个节点上都运行一一个 kubelet 服务进程,默认监听 10250 端口。 接收并执行 master 发来的指令; 管理 Pod 及 Pod 中的容器; 每个 kubelet 进程会在 API Server上注册节点自身信息,定期向 master 节点汇报节点的资源使用情况,并通过 cAdvisor 监控节点和容器的资源。 kubelet 架构如下图所示:...

September 28, 2023 · 2 分钟 · 421 字 · Xinwei Xiong, Me

Kubernetes 控制平面 - 调度器

调度器 kube-scheduler 负责分配调度 Pod 到集群内的节点上,它监听 kube-apiserver,查询还未分配 Node 的 Pod,然后根据调度策略为这些 Pod 分配节点(更新 Pod 的 NodeName 字段)。 调度器需要充分考虑诸多的因素: 公平调度; 资源高效利用; QoS; affinity 和 anti-affinity; 数据本地化(data locality) ; 内部负载干扰(inter-workload interference) ; deadlines。 kube-scheduler 调度分为两个阶段, predicate 和 priority: predicate: 过滤不符合条件的节点; priority:优先级排序,选择优先级最高的节点。. predicate 策略 PodFitsHostPorts:检查是否有 Host Ports 冲突。 PodFitsPorts:同P odFitsHostPorts。 PodFitsResources:检查 Node 的资源是否充足,包括允许的Pod数量、CPU、内存、GPU个数以及其他的OpaqueIntResources。 HostName:检查 pod.Spec.NodeName 是否与候选节点一致。 MatchNodeSelector:检查候选节点的 pod.Spec.NodeSelector 是否匹配 NoVolumeZoneConflict:检查 volume zone 是否冲突。 MatchInterPodAffinity:检查是否匹配 Pod 的亲和性要求。 NoDiskConflict:检查是否存在 Volume 冲突,仅限于 GCE PD、AWS EBS、Ceph RBD以及 iSCSI。 PodToleratesNodeTaints:检查 Pod 是否容忍 Node Taints。 CheckNodeMemoryPressure:检查 Pod 是否可以调度到 MemoryPressure 的节点上。 CheckNodeDiskPressure:检查 Pod 是否可以调度到 DiskPressure 的节点上。 NoVolumeNodeConflict:检查节点是否满足 Pod 所引用的 Volume 的条件。 priority 策略 SelectorSpreadPriority:优先减少节点上属于同一个 Service 或 Replication Controller 的 Pod 数量。 尽量将同一个 rc 下的多个副本分散到不同节点,增加可用性 InterPodAffinityPriority:优先将Pod调度到相同的拓扑上(如同一个节点、Rack、Zone等)。 LeastRequestedPriority:优先调度到请求资源少的节点上。 BalancedResourceAllocation:优先平衡各节点的资源使用。 NodePreferAvoidPodsPriority:alpha....

September 28, 2023 · 4 分钟 · 668 字 · Xinwei Xiong, Me

Kubernetes 的 CNI,CRI,CSI 详解

容器运行时 容器运行时(Container Runtime),运行于Kubernetes (k8s)集群的每个节点中,负责容器的整 个生命周期。其中Docker是目前应用最广的。随着容器云的发展,越来越多的容器运行时涌现。为了 解决这些容器运行时和Kubernetes的集成问题,在Kubernetes 1.5版本中,社区推出了CRI ( Container Runtime Interface,容器运行时接口)以支持更多的容器运行时。 什么是 CRI CRI 是 Kubernetes 定义的一组 gRPC 服务。 kubelet 作为客户端,基于 gRPC 框架,通过 Socket 和容器运行时通信。它包括两类服务: 镜像服务(Image Service):提供下载、检查和删除镜像的远程程序调用; 运行时服务(Runtime Service):包含用于管理容器生命周期,以及与容器交互的调用(exec/ attach / port-forward)的远程程序调用。 运行时的层级 容器运行时可以分为高层和低层的运行时: Dockershime,containerd 和 CRI-O 都是遵循 CRI 的容器运行时,我们称之为 高级运行时。 OCI 定义了创建容器的格式和运行时的开源行业标准,包括 镜像规范(Image Specification) 和 容器运行时规范 (runtime specification) 镜像规范定义了 OCI 镜像标准,高层级运行时 将会下载一个 OCI 镜像,并且将它解压为 OCI 运行时文件系统包(file system bundle) 运行时规范描述了如何从 OCI 运行时文件系统包运行容器程序。并且定义它的配置,运行环境和生命周期。如何为新的容器设置命名空间(namespace)和控制组(cgroup) ,以及挂载根文件系统(rootfs)等等操作,都是在这里定义的。它的一个参考实现是 runc,我们称其为 低层级运行时(Low-level Runtime) 高层级运行时(High-level Runtime):主要包括 Docker,containerd 和 CRI-O 低层级运行时(Low-level Runtime):包含了 runc, kata,以及 gVisor。 低层运行时 kata 和 gVisor 都还处于小规模落地或者实验阶段,其生态成熟度和使用案例都比较欠缺,所以除非有特殊的需求,否则 runc 几乎是必然的选择。因此在对容器运行时的选择上,主要是聚焦于上层运行时的选择。...

September 28, 2023 · 11 分钟 · 2200 字 · Xinwei Xiong, Me

深入了解Kubernetes Kube apisserver的组件

深入理解Kube-APIServer kube-apiserver是Kubernetes最重要的核心组件之一,主要提供以下的功能 提供集群管理的REST API接口,包括认证授权、数据校验以及集群状态变更等 提供其他模块之间的数据交互和通信的枢纽(其他模块通过API Server查询或修改数据,只有API Server才直接操作etcd) apiserver 主要功能: 认证:使用集群判断身份。 鉴权:使用操作 CRUD,需要权限。 准入: 对于Kubernetes来说,需要一些额外的 actions,例如写入的值不规范,需要对其进行修改,修改后需要 校验。最后需要 限流,以防止恶意或者漏洞导致拥堵 Mutating Validating Admission 限流 APIServer对象的实现 访问控制 API Server 是所有组件交互的 中间枢纽。 Kubernetes API的每个请求都会经过多阶段的访问控制之后才会被接受,这包括认证、授权以及准入控制(Admission Control)等。 前面的是 Mutating Webhook,可以改一个对象的值,而 Validating Webhook 是不可以修改对象的值,不生效的。 更加详细的请求处理流程: 📜 对上面的解释: 如何处理API请求:API源码存在于kubernetes/pkg/api路径中,会处理集群内以及集群外客户端的请求。 那么,当HTTP请求到达Kubernetes API时,具体会发现什么呢?从上层看,会发现以下交互: HTTP请求由一串过滤器(filters)进行处理,这些过滤器注册在DefaultBuildHandlerChain()(参阅源码:https://github.com/kubernetes/apiserver中的config.go)中,并执行相应的处理。过滤器要么会将信息传递并附加到ctx.RequestInfo上(例如通过了身份认证的用户),要么返回适当的HTTP响应代码。 第二步,复用器(multiplexer,参阅源码:https://github.com/kubernetes/apiserver中的container.go)会根据HTTP路径,将HTTP请求路由到相应的处理程序(handler)。 第三步,routes(在routes/*中定义)会将处理程序(handler)与HTTP路径进行连接。 第四步,按照API Group进行注册的处理程序(参阅源码:https://github.com/kubernetes/apiserver中的groupversion.go和installer.go),会处理HTTP请求和上下文(context,如user、rights等),并将请求的对象从存储中传送出来。 注意,为了简洁,在上图中我们省略了HTTP路径中的$NAMESPACE字段。 现在我们进一步深入的对前文中提到的DefaultBuildHandlerChain()中建立的过滤器(filters)进行介绍: **WithRequestInfo():**在requestinfo.go中定义,将RequestInfo附加到上下文中。...

September 28, 2023 · 7 分钟 · 1326 字 · Xinwei Xiong, Me

深入了解Kubernetes等组件之ETCD

开始前 ETCD 是 Kubernetes 中所有组件中最难的,因为 ETCD 是有状态的,而不是无状态的。 我在之前做 k3s runtime 设计的时候,了解了一些关于 ETCD 和 Raft 算法相关的概念,作为前奏知识,请分别前往 ETCD 以及 Raft算法 进行前奏学习。 这一篇来深入并且贯穿的讲解 ETCD 和 Raft。并且站在 Kubernetes 的角度来深入 剖析 ETCD。 ETCD 介绍 Etcd是CoreOS基于Raft开发的分布式key-value存储,可用于服务发现、共享配置以及一致性保障(如数据库选主、分布式锁等)。 包含的功能以及特性 前奏 都有学过,看下 Kubernetes 最关心的 存储: 主要功能 基本的key-value存储 监听机制 key的过期及续约机制,用于监控和服务发现 原子Compare And Swap和Compare And Delete,用于分布式锁和leader选举 使用场景 可以用于键值对存储,应用程序可以读取和写入 etcd 中的数据 etcd 比较多的应用场景是用于服务注册与发现 基于监听机制的分布式异步系统 etcd 是一个键值存储的组件,其他的应用都是基于其键值存储的功能展开。 采用kv型数据存储,一般情况下比关系型数据库快。 支持动态存储(内存)以及静态存储(磁盘)。 分布式存储,可集成为多节点集群。 存储方式,采用类似目录结构。(B+tree) 只有叶子节点才能真正存储数据,相当于文件。 叶子节点的父节点一定是目录,目录不能存储数据。 服务注册与发现:...

September 26, 2023 · 6 分钟 · 1264 字 · Xinwei Xiong, Me

设计建议:通过配置文件简化Kubernetes部署的端口配置

介绍 当前模块的执行中,直接传递了众多端口(ws、api、rpc、Prometheus)。 这种方法可能很麻烦,并且不符合 Kubernetes 的最佳实践,即 pod 通常只公开一个端口(80 或 443)。 该提案建议过渡到以配置文件为中心的方法,同时仍然保留在需要时直接传递端口的功能。 目标 简化Kubernetes部署的端口配置。 作为参数传递的端口值优先于配置文件值。 为希望使用传统的基于端口或基于环境变量的部署的用户提供灵活性。 建议的解决方案 1.配置文件 不会直接传递多个端口,而是引入一个配置文件。 默认情况下,该文件将包含预定义的端口。 可以使用 Kubernetes 的“ConfigMap”将该配置文件传递给模块。 配置文件示例: ws_端口:3000 api_端口:3001 rpc_端口:3002 普罗米修斯端口:9090 2. 直接传递端口 虽然 Kubernetes 部署建议使用配置文件方式,但用户仍然可以直接传递端口。 如果端口作为参数传递,这些值将覆盖配置文件中的值。 3.基于环境变量的部署 对于喜欢使用环境变量进行源代码部署的用户,该模块可以设计为读取 Linux 系统上设置为环境变量的端口值。 如果设置了这些环境变量,它们将覆盖配置文件值,但优先级低于直接作为参数传递的端口值。 示例:如果WS_PORT环境变量设置为3005,它将覆盖配置文件中的ws_port值,除非ws_port作为参数传递。 实施步骤 更新模块以读取配置文件:修改模块以从提供的配置文件中读取端口值。 基于参数的覆盖:实现逻辑以覆盖配置文件端口值(如果它们作为参数提供)。 基于环境变量的覆盖:实现逻辑来检查环境变量并使用这些值(如果设置)。 确保直接参数值具有最高优先级。 文档:更新文档以提供有关设置端口值的三种方法的清晰说明:配置文件、直接参数和环境变量。 测试:在不同场景下彻底测试模块: 仅使用配置文件。 将端口作为参数传递。 设置环境变量。 结论 采用配置文件方法可以简化部署过程,尤其是在 Kubernetes 环境中。 虽然配置文件优先考虑简单性,但直接传递端口或使用环境变量的灵活性确保了向后兼容性并满足各种用户偏好。

September 18, 2023 · 1 分钟 · 53 字 · Xinwei Xiong, Me