关于职业生涯规划的一点思考

在思考职业规划的时候突发奇想,于是记录了下来,这还是第一次在博客上分享自己的思考内容。 很多人对职业规划的理解是一直从事某一个业务方向,成为这个方向上的专家,我觉得没问题,但没有深入本质。 职场能力本质是解决问题的能力,如果只是把目标定在一个方向上,在这个不断变化的世界,如果这个方向不再有价值了,那之前积累的业务经验就作废了。(当然不是说业务知识不重要,除了工作上的需要,了解更多业务知识,对于我们理解这个世界也更有帮助) 回过头来,核心还是要更专注培养自己解决问题的能力,提升自己的认知,尽可能多做尝试,每次尝试除了掌握这个领域的知识,也要去思考更加通用的底层逻辑,融会贯通,最终内化为自己的认知和解决问题的能力。 通俗点就是不能只关注表面,也要关注更深层次的部分。 这样就算这个业务不行了,换一个全新的业务也不至于从头开始,也能利用之前的经验快速解决问题。 视角从职场放大到更广阔的人生也一样,人生也是不断解决问题的一个过程,培养好这种意识,不断提升认知和解决问题的能力,人生也能走向更幸福的道路。 回到职业规划上,找到更有前景、发展、更有挑战的业务,并且投身其中,打磨自身并且创造价值,不断扩大 scope,从实际行动来说,中期目标就是成为一个领域的专家,有自己对这个行业的认知,并且可以迁移到其他领域。 日常工作中有太多事情要做,生活也是,有太多琐碎的事情,还要给自己休息的时间,加起来很难让自己有思考的时间。后面打算在博客开一个板块,给自己设立明确的目标(比如每月输出一篇文章、每天固定时间思考、冥想),记录下自己觉得有价值的思考或者其他内容,养成结构化思考和输出的习惯。

2023-10-15 · 1 min · 10 words · zhenran

Terraform & Pulumi & Crossplane 对比介绍

关于 IaC IaC 的历史 2000 年之后,随着 IT 技术发展,用户的需求越来越复杂,软件系统以及基础设施也变的越来越复杂。最早的运维都是手工式的,面临着几个问题: 交互式变更所引入的人的因素太大,导致了变更的不可控性 基础设施变化越来越快,手工操作成本高且效率低 交互式变更难以管控,且无法实现版本控制 IaC 就是在这个时期出现的想要解决这些问题的概念,维基百科定义的 IaC 指通过 machine-readable 的定义文件,而不是物理硬件配置或交互式配置工具来管理和配置计算机数据中心的过程。该过程管理的 IT 基础设施包括物理设备(如 Bare-metal 或 VM),以及相关的配置资源。定义文件可能在版本控制系统 VCS 中,文件中代码可能使用脚本或者声明式定义,但IaC 通常使用声明式方法管理基础设施。 IaC 有几个核心特征: 最终产物为 machine-readable 的文件,可以是脚本、声明式代码或者配置文件。 基于最终产物,可以利用 VCS(Git、SVN) 实现版本管理。 利用 CI/CD 系统(如 Jenkins、GitLab CI)实现持续集成/持续交付。 基于同样的定义文件,最终表现出来的行为是一致且幂等的。 这个时期出现了一些 IaC 工具,典型的如 Puppet、Chef、Ansible,实际上这些工具,可能设计上各有所取舍(比如 Pull/Push 模型的取舍),但是其核心的特征不会变化: 框架内部提供了常见的比如 SSH 链接管理,多机并行执行,auto retry 等功能。 基于上面描述的这一套基础功能,提供了一套 DSL 封装。让开发者更专注于 IaC 的逻辑,而非基础层面的细节。 其开源开放,并形成了一套完善的插件机制。社区可以基于这一套提供更丰富的生态。比如 SDN 社区基于 Ansible 提供了各种交换机的 playbook;Ansible 官方提供的 AWS playbook 等。 云上资源编排 2006 年 8 月 Amazon 正式发布了 EC2 服务,从这时整个基础设施开始快步向 Cloud 时代迈进。截止目前,各家云厂商提供了各种各样的服务,经过十多年的演进,诞生出了诸如 IaaS,PaaS,DaaS,FaaS 等等各种各样的服务模式。这些服务模式,让我们的基础设施的构建,变得更加的简单,更加的快速。但是这些服务模式,也带来了一些问题:...

2023-06-11 · 6 min · 1249 words · zhenran

使用 Upjet 生成 Crossplane Provider

简介 Upjet 是一个代码生成框架,支持开发者构建用于生成 Crossplane 控制器的代码生成管道。Upiet主要由三部分组成: 构建代码生成器管道的框架。 所有自动生成 CRD 使用的通用 Reconciler 实现 为所有自动生成 CRD 提取文档的工具。 相关名词: MR: Managed Resource, Crossplane 管理的托管资源 CR: Custom Resource,自定义资源,Kubernetes API的扩展 CRD: Custom Resource Definition: 自定义资源定义。 资源配置 Upjet 使用 Terraform Resource Schema 中的信息尽可能多的生成 Provider 中的相关信息,包括符合XRM 模式的 Resource SchemaController 逻辑、延迟加载、敏感数据处理等。然后仍然有一些信息,需要通过查阅 Terraform 文档后手动输入配置: 外部名称 | External Name 跨资源引用 | Cross Resource Referencing 敏感字段及自定义连接详情 | AdditionalSensitive Fields and Custom Connection Details 延迟初始化行为 | Late lnitialization Behavior 覆盖 | Terraform Resource Schema 初始化器 | Initializers 外部名称 External Name 简介 Crossplane 使⽤ Managed Resource 中的 Annotation 来识别 Crossplane 管理的外部资源, Annotation key 为crossplane....

2023-06-03 · 11 min · 2262 words · zhenran

Pulumi 工作运行原理

简介 Pulumi 是一个基础设施即代码(IaC,Infrastructure as Code)平台,支持使用如 Go、Java、Python、JavaScript、C# 等常见编程语言及相关工具,以实现云基础设施的构建、部署和管理。 使用及基本结构 基本概念 Project:包含 Pulumi.yaml 配置文件的目录。可以通过 pulumi new 使用各个语言的模板创建新的 project。 Stack:每个 Pulumi 程序都部署到一个 Stack。Stack 是 Pulumi 程序的一个相互隔离、可独立配置的实例,Stack 通常用于表示不同的开发阶段(如 dev、staging、production)或功能分支(如 feature-x-dev)。一个 Project 下可以有多个 Stack,当使用 pulumi new 创建 project 时,默认会创建一个 dev Stack。 Program:Project 中包含的资源编排代码以及运行程序的元数据信息。在 project 目录中执行pulumi up命令,pulumi 会创建一个隔离、可配置的 stack 实例,Stack 类似在测试和线上应用程序使用的不同部署环境。 示例 安装 pulumi 插件 brew install pulumi/tap/pulumi 初始化 project,第一次使用会要求登陆 Pulumi Cloud(状态等元数据默认存储在 Pulumi Cloud) mkdir pulumi-example && cd pulumi-example pulumi new go 执行完成后,pulumi 会创建一个 pulumi-example project,同时默认创建一个名为 dev的 stack。...

2023-05-26 · 2 min · 407 words · zhenran

Crossplane 云原生控制平面

简介 Crossplane 是一种开源 Kubernetes 扩展,可将 Kubernetes 集群转换为通用控制平面。借助 Crossplane,平台团队可以利用 Kubernetes 策略、命名空间、基于角色的访问控制等的全部功能创建新的抽象和自定义 API, Crossplane 将所有非 Kubernetes 资源集中管理。 控制平面创建和管理资源的生命周期。控制平面不断检查预期资源是否存在,当预期状态与现实不符时报告并采取行动纠正错误。Crossplane 将 Kubernetes 控制平面扩展为通用控制平面,可以在任何地方检查、报告和处理任何资源。 基本概念 Package:OCI 镜像标准的包,包含 Provider CRDs、Provider 镜像、ServiceAccount 权限等信息。 Provider:云提供商插件,由一组 CRD 和 Controller 组成,CRD 定义了资源信息,Controller 通过 SDK 连接外部云服务,根据资源字段变更,执行相关操作。 Managed Resource:Provider 内部 CRD 定义的资源,创建并由 Crossplane 托管之后,称为 Managed Resource。 Compositions:Managed Resource 集合的模板,用于需要多个资源组合使用的场景,类似 Terraform Module。如 ECS + VPC + EBS。 Composite Resource(XR):使用 Composition 模板创建的一组 Managed Resource。 Claims:开发人员与 Crossplane 交互的主要方式,开发人员通过 Claim 声明由 SRE 团队定义的 XRD 中的自定义字段值,最终在 XR 定义中引用。 和 Terraform 对比,XRD 比较类似 Terraform Module 中的 variables块;Composition 是模块的 HCL 代码的其余部分,它描述了如何使用这些变量来创建一堆资源;XR 和 Claim 类似为模块提供输入的 tfvars 文件。...

2023-05-12 · 4 min · 649 words · zhenran

Golang 业务代码单元测试实践

背景 什么是单测 单元测试是一项由开发人员或测试人员对程序模块的正确性进行检验测试的工作,用于检查被测试代码的功能是否正确。单元测试是软件工程中降低开发成本,提高软件质量常用方式之一。 正确性:同一单元,在给定的输入下,总能得到预期的输出。 为什么要写单测 在业务快速迭代过程中,单元测试能够保证业务逻辑的一致性。(如修改业务逻辑、或者引入缺陷导致业务逻辑变更,单测会发现问题并报错,前提是测试用例能够覆盖到改动的场景) 利于未来的代码重构,保证基本的业务功能不变,不会出现严重的基本功能不可用的情况。 复杂的代码块单测十分复杂,有助于开发者将复杂逻辑拆分为多个内聚的小模块,降低了代码耦合度,提升了代码质量,内聚的小模块也更方便测试。 整体单测覆盖率达到一定程度后,能够保证项目的基本质量。 更有信心修改代码,自动化的单测能够确保基本业务逻辑没有问题,还能节省开发者自测的时间。 推动测试驱动开发(TDD,Test-Driven Development),让开发者在开发前优先设计接口,考虑各种输入输出场景,提升代码质量,覆盖更多边界用例。 …… 为什么都不想写单测 需要花费更多时间写单测,修改一行代码,要写300行单测。(从👆🏻能看出来,在未来可以节省很多时间,还能提升质量,减少故障) 代码太复杂,不够内聚,一个方法几百行,依赖了各种模块,调用满天飞。(需要重构代码,拆分为内聚的模块,不仅方便写单测,还能提升代码质量,方便未来迭代) 写单测很复杂,不清楚怎么写好单测。(模块设计合理的前提下,大部分单测都不复杂,👇🏻也会有一些最佳实践) 什么是好的单测实践 简短、粒度小:只有一个测试目的,不应该包含过多计算逻辑,尽量只有输入、输出和断言。 独立性:保证单元测试稳定可靠且便于维护,单测用例之间不能互相调用,也不能依赖执行的先后次序。 可重复:单元测试通常会被放到持续集成中,每次有集成时单元测试都会被执行。如果单测对外部环境(网络、服务、中间件等)有依赖,容易导致持续集成机制的不可用。 自动化:单元测试应该是全自动执行的,并且非交互式的。 实践 Go Mockito 使用字节开源的 mockey 库可以很方便的实现函数 mock,解耦依赖调用,专注测试方法内部的业务逻辑。 Mockey 是一款简单易用的 Golang 打桩工具库,能够快速方便地进行函数、变量的 mock,目前在字节跳动各业务的单元测试编写中应用较为广泛,其底层是通过**运行时改写函数指令**实现的猴子补丁(Monkey Patch)。 // 示例代码 package main import ( "syscall" "unsafe" ) func a() int { return 1 } func b() int { return 2 } func rawMemoryAccess(b uintptr) []byte { return (*(*[0xFF]byte)(unsafe.Pointer(b)))[:] } func assembleJump(f func() int) []byte { funcVal := *(*uintptr)(unsafe....

2023-03-26 · 2 min · 363 words · zhenran

Kubernetes Cluster Autoscaler 原理 & 对接介绍

Autoscaler 简介 Autoscaler 是 Kubernetes 弹性伸缩的一个组件集合,主要包含三个组件: Cluster Autoscaler / CA:用于自动调整 Kubernetes 集群大小,以便所有 Pod 都能被调度到 Node 上运行,且没有多余的无负载 Node。GA 版本已随 Kubernetes 1.8 版本发布。 Vertical Pod Autoscaler / VPA:用于自动调整在 Kubernetes 中运行的 Pod 请求的 CPU 和内存量的一组组件。目前处于 beta 版本,主要由 3 个部分组成: Recommender:监控 Pod 的当前和过去的资源消耗,根据监控数据计算推荐的 CPU 和内存建议值。 Updater:检查 Pod 是否使用 Recommender 推荐的资源建议值,如果 Pod 没有使用推荐值,Updater 会尝试驱逐该 Pod。 Admission Plugin:在新的 Pod 上设置 Recommender 推荐的资源建议值。 Addon Resizer:VPA 的简化版,根据集群中 Node 数量修改资源请求。 CA 工作原理 工作流程 CA 顶层工作流程: 每 10s 检查集群是否存在无法被调度的 Pod 集群中没有足够资源分配给这些 Pod,CA 会触发云厂商 Provider 执行扩容流程 云厂商支持新节点加入集群 Pod 调度至新加入集群的 Node 核心控制循环 CA 是一个 CLI 应用程序。启动时,它会触发无限控制循环逻辑,每 10 秒执行一次。它会检查集群状态,以决定是否执行扩容或缩容操作。...

2023-02-26 · 2 min · 247 words · zhenran

Flannel VXLAN 模式

背景 Flannel 是专为 Kubernetes 设计的一种用于容器的网络结构插件,用于在 Kubernetes 集群中构建 3 层网络,实现跨宿主机 Pod 之间在 3 层网络相互通信。 Flannel 支持的三种模式: UDP:通过 TUN + 用户空间 Flannel 进程实现,由于存在多次用户空间和内核空间之间的 COPY,性能比较差,基本不再使用。 HOST-GW:纯三层解决方案,把 HOST 作为网关,需要宿主机二层互通,性能比较好,但是存在一定局限。 VXLAN:在 VLAN 基础上进行扩展,通过构建 Tunnel 实现二层互通。 名词 VXLAN(Virtual Extensible LAN 虚拟可扩展局域网) VTEP(VXLAN Tunnel Endpoints,VXLAN 隧道端点) VNI(VXLAN Network Identifier,VXLAN 网络标识符) 原理 同 Pod 通信 Pod 内部容器通过 pause 容器共享一个网络。 同 Node 跨 Pod 通过 veth pair 设备和 cni0(docker0) 网桥实现通信。 跨 Node 首先数据包从pod1内的eth0出来到达cni0网桥,cni0网桥接收到数据包后发现目的IP跟自己不在一个网段,那么自然需要转发出去,而Linux Bridge有个特殊规则: 网桥不会将这个数据包转发给任何设备,而是直接转交给主机的三层协议栈进行处理, 因此通过本机的route得知,目的地址为10.224.1.0段的数据包都将转到flannel.1。 [node1]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 10....

2022-12-24 · 2 min · 243 words · zhenran

Java线程池的使用及原理分析

概述 线程池是管理一组同构工作线程的资源池。合理利用线程池能够带来三个好处。第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。但是要做到合理的利用线程池,必须对其原理了如指掌。 Java中线程池的基础架构 线程池的使用及原理分析 由于在JDK中内部提供的许多线程池都是基于ThreadPoolExecutor的,因此下面先介绍ThreadPoolExecutor的相关原理。 ThreadPoolExecutor 使用ThreadPoolExecutor Java中可以通过ThreadPoolExecutor来创建一个线程池: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler); 参数介绍: corePoolSize:核心线程数量。 maximumPoolSize:最大线程数,线程池允许创建的最大线程数。 keepAliveTime:超出corePoolSize后创建的线程的存活时间。 unit:keepAliveTime的时间单位。 workQueue:任务队列,用于保存待执行的任务。 threadFactory:线程池内部创建线程所用的工厂。 handler:任务无法执行时的处理器。 使用ThreadPoolExecutor+单例模式实现一个简单的线程池: import java.util.List; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; public class MyThreadPool { private final String THREAD_TAG = this.getClass().getSimpleName(); /** * 定义ThreadPoolExecutor需要的必要参数 */ private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2; private static final int MAX_POOL_SIZE = 64; private static final int KEEP_ALIVE_TIME = 1; /** * 工作队列,使用LinkedBlockingQueue */ private final BlockingQueue<Runnable> mWorkQueue = new LinkedBlockingQueue<>(); /** * 定义创建线程的工厂 */ private final ThreadFactory mThreadFactory = new ThreadFactory() { private final AtomicInteger threadCount = new AtomicInteger(0); @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r, THREAD_TAG + "#" + threadCount....

2019-04-30 · 9 min · 1907 words · zhenran