ch04 函数

concept [1] 函数 (function) 是执行任务的语句块。 函数的作用: 提高代码的可重用性并减少冗余 代码模块化 代码易读性 使代码模块化 函数的分类 C语言中有两种类型的函数: 标准库函数:C中的内置函数,在头文件中定义 #include <stdio.h> 用户自定义函数:用户自定义的函数 #include "stdio.h" 函数三部曲 C语言中函数分为三个方面,声明(declaration),定义(defining),调用(calling) 声明 声明是让编译器知道函数的名称、参数信息、参数的返回值的类型。 c 1 (type) function_name({type args...}); 隐式声明(implicit) :当在main之后定义的函数而未声明,默认编译器会做隐式声明。 ISO/IEC 9899:1990 中 关于函数声明的部分: 函数在调用前必须有一个可用的声明,如果没有被声明,则该函数默认被隐式声明,该隐式声明没有参数,返回值为int [2] 定义 C中函数定义的语法如下 c 1 2 3 4 return_type function_name(arg1, arg2, ... argn) { function body // 函数中要处理任务的逻辑 } return_type:函数返回值的数据类型 function_name:函数名 arg1, arg2, …argn:参数列表(可选),定义传递给函数的数据类型、顺序和参数的数量。 function body:调用函数时任务处理和执行的语句 调用 调用是指要由编译器执行的函数,可以在任何部分调用 虚函数void 如果函数没有返回值,则使用关键字 void,主要用于两个方面: 打印具体信息供用户阅读的函数 引用参数,函数通常不是用于返回一个内容,而是修改引用参数的,无需返回值 void 关键字使用注意: void仅用于限定函数返回值,函数参数,不可以修饰变量,因为无法对无类型的变量分配指针...

ch03 数组

Array [1] 数组是由单个元素组成的一组数据类型的变量 数组的元素存储在连续的内存位置 声明数组时应提及数组的大小 数组的计数从0开始 数组为一位数组与多维数组 数组首元素的地址与数组地址相同 数组包含 int, float, char, double 数据类型 Declaration and Initialization 表达式 说明 int my_array1[20]; 指定大小,来声明一个有20个元素的int数组 char my_array2[5]; 指定大小,来声明一个有5个元素的char数组 int my_array[] = {100, 200, 300, 400, 500} 声明时初始化一个数组(编译器自动求数组元素个数) int my_array1[5] = {100, 200, 300, 400, 500}; 声明时初始化 int my_array2[5] = {100, 200, 300}; 声明时初始化(剩余未初始化的元素,默认 0 值) int my_array2[5] = {0}; 声明时初始化(声明一个全0值的数组) int arr[10]; arr[0] = 5;arr[1] = 6;arr[2] = 7; 声明数组并初始化值(这种方法为初始化部分的默认值为随机数) char str[] = “zhangsan” 声明一个字符串(字符串是一个char类型数组) Advantages and Disadvantages 缺点**:大小限制**:声明(定义)后是固定的大小,不能通过运行时改变其大小...

ch02 格式化与流程控制

格式化 printf printf() 用于打印消息以及变量的值。 c 1 2 3 4 5 6 7 8 #include<stdio.h> int main() { int a = 24; printf("Welcome! \n"); printf("The value of a : %d",a); getchar(); return 0; } sprintf sprintf() 不打印字符串,是将字符值和格式化结构一并存储在一个数组中。 c 1 2 3 4 5 6 7 8 9 10 11 12 13 int main() { char buffer[50]; int a = 10, b = 20, c; c = a + b; sprintf(buffer, "Sum of %d and %d is %d", a, b, c); // The string "sum of 10 and 20 is 30" is stored // into buffer instead of printing on stdout printf("%s", buffer); return 0; } scanf 从标准输入读取用户输入的...

ch01 变量和数据类型

C语言关键字 [1] ==C语言有32个关键字== auto:定义自动变量,主要是声明变量的生存周期 break, continue : break 语句在遇到最内层循环时立即终止。还用于终止 switch 语句。 case, switch, default:使用 switch 和 case 语句声明一个switch分支 char:用于声明character 类型的变量 const:声明常量 do…while: double: double-precision 浮点数变量类型 float:single-precision 浮点数的变量类型 if, else:声明if/else 条件判断 enum:用于声明枚举类型 extern:关键字声明变量或函数在其声明的文件之外具有外部链接。 for:C 语言的三种循环之一,for循环 goto: 用于将程序的控制权转移到指定的标签 int:声明 integer 类型的变量 short, long, signed, unsigned:是类型修饰符,它们改变基本数据类型的含义以产生新类型。 short int: -32768 to 32767 long int: -2147483648 to 214743648 signed int: -32768 to 32767 unsigned int: 0 to 65535 return: 终止函数并返回值 sizeof:评估变量或常量的大小 register:创建比普通变量快得多的寄存器变量。 static:创建一个静态变量。静态变量的值持续到程序结束。 struct:用于声明结构体。结构体可以包含不同类型的变量。 typedef:用于将类型与标识符显式关联。 union:用于将不同类型的变量分组在一个名称下。 void:没有任何意义,函数修饰为没有返回值,参数修饰为没有参数 volatile:提醒编译器它后面所定义的变量随时都有可能改变 C语言控制语句 ==C语言有9种控制语句== (control statements)...

ch0 ide

Visual Studio使用 离线安装包 在页面 [4] 下载安装引导命令,下载完成后使用命令(对于C++来说) bat 1 vs_Professional.exe --layout ‪1111 --add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended --lang en-US zh-CN 随后会触发下载,等待下载完成后,在 --layout 指定的目录上点击 vs_setup 开始离线安装。 Note: 对于完全脱离C盘安装可以使用下面的脚本,更改变量为要安装的路径 bat 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 :: 关闭终端回显 @echo off SET ROOT_PATH=D:\Program Files\Microsoft Visual Studio SET X86_PATH=%ROOT_PATH%\Program Files (x86) SET X86_VS_PATH=%X86_PATH%\Microsoft Visual Studio SET X86_SDK_PATH=%X86_PATH%\Microsoft SDKs SET X86_KITS_PATH=%X86_PATH%\Windows Kits SET X86_AV_PATH=%X86_PATH%\Application Verifier SET X64_PATH=%ROOT_PATH%\Program Files rem SET X64_VS_PATH=%X64_PATH%\Microsoft Visual Studio SET X64_AV_PATH=%X64_PATH%\Application Verifier SET X64_SQL_PATH=%X64_PATH%\Microsoft SQL Server SET PD_PATH=%ROOT_PATH%\ProgramData SET PD_VS_PATH=%PD_PATH%\Microsoft\VisualStudio SET PD_PC_PATH=%PD_PATH%\Package Cache @echo =======link directory to %ROOT_PATH%=======: SET S_X86_SKD_PATH=C:\Program Files (x86)\Microsoft SDKs SET S_X86_VS_PATH=C:\Program Files (x86)\Microsoft Visual Studio SET S_X86_KITS_PATH=C:\Program Files (x86)\Windows Kits SET S_X86_AV_PATH=C:\Program Files (x86)\Application Verifier SET S_X64_AV_PATH=C:\Program Files\Application Verifier SET S_X64_SQL_PATH=C:\Program Files\Microsoft SQL Server SET S_PD_VS_PATH=C:\ProgramData\Microsoft\VisualStudio SET S_PD_PC_PATH=C:\ProgramData\Package Cache pause @echo =======setting visual studio environment=======: @echo =======check directory exist=======: if not exist %ROOT_PATH% ( echo "%ROOT_PATH%目录不存在,已创建该目录!" md "%ROOT_PATH%" ) if not exist %X86_PATH% ( echo "%X86_PATH%目录不存在,已创建该目录!" md "%X86_PATH%" ) if not exist %X86_VS_PATH% ( echo "%X86_VS_PATH%目录不存在,已创建该目录!" md "%X86_VS_PATH%" ) if not exist %X86_SDK_PATH% ( echo "%X86_SDK_PATH%目录不存在,已创建该目录!" md "%X86_SDK_PATH%" ) if not exist %X86_KITS_PATH% ( echo "%X86_KITS_PATH%目录不存在,已创建该目录!" md "%X86_KITS_PATH%" ) if not exist %X86_AV_PATH% ( echo "%X86_AV_PATH%目录不存在,已创建该目录!" md "%X86_AV_PATH%" ) if not exist %X64_PATH% ( echo "%X64_PATH%目录不存在,已创建该目录!" md "%X64_PATH%" ) if not exist %X64_AV_PATH% ( echo "%X64_AV_PATH%目录不存在,已创建该目录!" md "%X64_AV_PATH%" ) if not exist %X64_SQL_PATH% ( echo "%X64_SQL_PATH%目录不存在,已创建该目录!" md "%X64_SQL_PATH%" ) if not exist %PD_PATH% ( echo "%PD_PATH%目录不存在,已创建该目录!" md "%PD_PATH%" ) if not exist %PD_VS_PATH% ( echo "%PD_VS_PATH%目录不存在,已创建该目录!" md "%PD_VS_PATH%" ) if not exist %PD_PC_PATH% ( echo "%PD_PC_PATH%目录不存在,已创建该目录!" md "%PD_PC_PATH%" ) @echo =======link directory to %ROOT_PATH%=======: :: x86 link mklink /j "%S_X86_SKD_PATH%" "%X86_SDK_PATH%" mklink /j "%S_X86_VS_PATH%" "%X86_VS_PATH%" mklink /j "%S_X86_KITS_PATH%" "%X86_KITS_PATH%" mklink /j "%S_X86_AV_PATH%" "%X86_AV_PATH%" :: x64 link mklink /j "%S_X64_AV_PATH%" "%X64_AV_PATH%" mklink /j "%S_X64_SQL_PATH%" "%X64_SQL_PATH%" :: ProgramData link mklink /j "%S_PD_VS_PATH%" "%PD_VS_PATH%" mklink /j "%S_PD_PC_PATH%" "%PD_PC_PATH%" pause VS快捷键 快捷键 含义 Ctrl + k,Ctrl + f 自动格式化代码 Ctrl + k,Ctrl + c 注释代码 Ctrl + k,Ctrl + u 取消注释代码 F9 设置断点 F5 调试运行 Ctrl + F5 不调试运行 Ctrl + Shift + b 编译,不运行 F10 next调试 F11 step调试 调试 添加行号:工具–》选项 –》文本编辑器–》C/C++ –》行号...

漏桶算法与令牌桶算法

Principle of token bucket 随着互联网的发展,在处理流量的方法也不仅仅为 first-come,first-served,而在共享网络中实现流量管理的基本机制就是排队。而公平算法则是实现在优先级队列中基于哪些策略来排队的 “公平队列” 。Token Bucket 则是为公平排队提供了替代方案。Fair Queue 与 Token Bucket的区别主要在,对于Fair Queue来讲,如果请求者目前空闲,Queue会将该请求者的带宽分配给其他请求者;而 Token Bucket 则是分配给请求者的带宽是带宽的上限。 通过例子了解算法原理 假设出站带宽是 4个数据包/ms,此时有一个需求为,为一个特定的发送端 A 来分配 1个数据包/ms的带宽。此时可以使用公平排队的方法分给发送 A 25%的带宽。 此时存在的问题是我们希望可以灵活地允许 A 的数据包以无规则的时间间隔发送。例如假设 A 在每个数据包发送后等待1毫秒后再开始下一个数据包的发送。 sence1:此时假设 A 以 1ms 的间隔去发送数据包,而由于某种原因导致应该在 t=6 到达的数据包却在 t=6.5 到达。随后的数据包在 t=7 准时到达,在这种情况下是否应该保留到t=7.5? sence2:或者是否允许在 t=6.5 发送一个迟到的数据包,在 t=7 发送下一个数据包,此时理论上平均速率仍然还是 1 个数据包/ms? 显然sence2是合理的,这个场景的解决方法就是令牌桶算法,规定 A 的配额,允许指定平均速率和突发容量。当数据包不符合令牌桶规范,那么就认为其不合理,此时会做出一下相应: delay,直到桶准备好 drop mark,标记为不合规的数据包 delay 被称为 整形 shaping , shaping 是指在某个时间间隔内发送超过 Bc(Committed Burst)的大小,Bc 在这里指桶的尺寸。由于数据流量是突发性的,当在一段时间内不活动后,再次激活后的在一个间隔内发送的数量大于 Bc ,那么额外的流量被称为Be (burst excess)。 将流量丢弃或标记超额流量,保持在一个流量速率限制称为 “管制” policing。...

深入理解Kubernetes Pod网络原理 - Kubernetes网络模型 1

本文是关于深入理解Kubernetes网络原理系列第4章 深入理解Kubernetes Pod网络原理 - 网络名称空间 深入理解Kubernetes Pod网络原理 - Linux虚拟网络技术 深入理解Kubernetes Pod网络原理 - CNI 深入理解Kubernetes Pod网络原理 - 跟随 flannel 学习CNI原理 深入理解Kubernetes Pod网络原理 - 跟随 flannel + multus 剖析 Chained Plugins 深入理解Kubernetes Pod网络原理 - 从零实现一个 CNI Plugin part 1 (Shell) 深入理解Kubernetes Pod网络原理 - 从零实现一个 CNI Plugin part 2 (libcni) 深入理解Kubernetes Pod网络原理 - Kubernetes网络模型 1 深入理解Kubernetes Pod网络原理 - Kubernetes网络模型 2 深入理解Kubernetes Pod网络原理 - Pod网络排错思路 概述 本文将简述探讨 Kubernetes 中常见的网络模型,以及对这些网络模型的 route path 进行分析。本章节是作为CNI 原理的前置条件,也为后续的练习提供一些基础知识。...

Kubernetes Pod网络排错思路

本文是关于深入理解Kubernetes网络原理系列第4章 深入理解Kubernetes Pod网络原理 - 网络名称空间 深入理解Kubernetes Pod网络原理 - Linux虚拟网络技术 深入理解Kubernetes Pod网络原理 - CNI 深入理解Kubernetes Pod网络原理 - 跟随 flannel 学习CNI原理 深入理解Kubernetes Pod网络原理 - 跟随 flannel + multus 剖析 Chained Plugins 深入理解Kubernetes Pod网络原理 - 从零实现一个 CNI Plugin part 1 (Shell) 深入理解Kubernetes Pod网络原理 - 从零实现一个 CNI Plugin part 2 (libcni) 深入理解Kubernetes Pod网络原理 - Kubernetes网络模型 1 深入理解Kubernetes Pod网络原理 - Kubernetes网络模型 2 深入理解Kubernetes Pod网络原理 - Pod网络排错思路 Overview 本文将引入一个思路:“在Kubernetes集群发生网络异常时如何排查”。文章将引入Kubernetes 集群中网络排查的思路,包含网络异常模型,常用工具,并且提出一些案例以供学习。 Pod常见网络异常分类 网络排查工具 Pod网络异常排查思路及流程模型 CNI网络异常排查步骤 案例学习 Pod网络异常 网络异常大概分为如下几类:...

基于Prometheus的Kubernetes网络调度器

Overview 本文将深入讲解 如何扩展 Kubernetes scheduler 中各个扩展点如何使用,与扩展scheduler的原理,这些是作为扩展 scheduler 的所需的知识点。最后会完成一个实验,基于网络流量的调度器。 kubernetes调度配置 kubernetes集群中允许运行多个不同的 scheduler ,也可以为Pod指定不同的调度器进行调度。在一般的Kubernetes调度教程中并没有提到这点,这也就是说,对于亲和性,污点等策略实际上并没有完全的使用kubernetes调度功能,在之前的文章中提到的一些调度插件,如基于端口占用的调度 NodePorts 等策略一般情况下是没有使用到的,本章节就是对这部分内容进行讲解,这也是作为扩展调度器的一个基础。 Scheduler Configuration [1] kube-scheduler 提供了配置文件的资源,作为给 kube-scheduler 的配置文件,启动时通过 --onfig= 来指定文件。目前各个kubernetes版本中使用的 KubeSchedulerConfiguration 为, 1.21 之前版本使用 v1beta1 1.22 版本使用 v1beta2 ,但保留了 v1beta1 1.23, 1.24, 1.25 版本使用 v1beta3 ,但保留了 v1beta2,删除了 v1beta1 下面是一个简单的 kubeSchedulerConfiguration 示例,其中 kubeconfig 与启动参数 --kubeconfig 是相同的功效。而 kubeSchedulerConfiguration 与其他组件的配置文件类似,如 kubeletConfiguration 都是作为服务启动的配置文件。 yaml 1 2 3 4 apiVersion: kubescheduler.config.k8s.io/v1beta1 kind: KubeSchedulerConfiguration clientConnection: kubeconfig: /etc/srv/kubernetes/kube-scheduler/kubeconfig Notes: --kubeconfig 与 --config 是不可以同时指定的,指定了 --config 则其他参数自然失效 [2]...

如何理解kubernetes调度框架与插件?

调度框架 [1] 本文基于 kubernetes 1.24 进行分析 调度框架(Scheduling Framework)是Kubernetes 的调度器 kube-scheduler 设计的的可插拔架构,将插件(调度算法)嵌入到调度上下文的每个扩展点中,并编译为 kube-scheduler 在 kube-scheduler 1.22 之后,在 pkg/scheduler/framework/interface.go 中定义了一个 Plugin 的 interface,这个 interface 作为了所有插件的父级。而每个未调度的 Pod,Kubernetes 调度器会根据一组规则尝试在集群中寻找一个节点。 go 1 2 3 type Plugin interface { Name() string } 下面会对每个算法是如何实现的进行分析 在初始化 scheduler 时,会创建一个 profile,profile是关于 scheduler 调度配置相关的定义 go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 func New(client clientset.Interface, ....

kube-scheduler的调度上下文

Scheduler Scheduler 是整个 kube-scheduler 的一个 structure,提供了 kube-scheduler 运行所需的组件。 go 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 type Scheduler struct { // Cache是一个抽象,会缓存pod的信息,作为scheduler进行查找,操作是基于Pod进行增加 Cache internalcache.Cache // Extenders 算是调度框架中提供的调度插件,会影响kubernetes中的调度策略 Extenders []framework.Extender // NextPod 作为一个函数提供,会阻塞获取下一个ke'diao'du NextPod func() *framework.QueuedPodInfo // Error is called if there is an error. It is passed the pod in // question, and the error Error func(*framework....

kubernetes的决策组件 - kube-scheduler原理分析

Overview [1] kubernetes集群中的调度程序 kube-scheduler 会 watch 未分配节点的新创建的Pod,并未该Pod找到可运行的最佳(特定)节点。那么这些动作或者说这些原理是怎么实现的呢,让我们往下剖析下。 对于新创建的 pod 或其他未调度的 pod来讲,kube-scheduler 选择一个最佳节点供它们运行。但是,Pod 中的每个容器对资源的要求都不同,每个 Pod 也有不同的要求。因此,需要根据具体的调度要求对现有节点进行过滤。 在Kubernetes集群中,满足 Pod 调度要求的节点称为可行节点 ( feasible nodes FN) 。如果没有合适的节点,则 pod 将保持未调度状态,直到调度程序能够放置它。也就是说,当我们创建Pod时,如果长期处于 Pending 状态,这个时候应该看你的集群调度器是否因为某些问题没有合适的节点了 调度器为 Pod 找到 FN 后,然后运行一组函数对 FN 进行评分,并在 FN 中找到得分最高的节点来运行 Pod。 调度策略在决策时需要考虑的因素包括个人和集体资源需求、硬件/软件/策略约束 (constraints)、亲和性 (affinity) 和反亲和性( anti-affinity )规范、数据局部性、工作负载间干扰等。 如何为pod选择节点? kube-scheduler 为pod选择节点会分位两部: 过滤 (Filtering) 打分 (Scoring) 过滤也被称为预选 (Predicates),该步骤会找到可调度的节点集,然后通过是否满足特定资源的请求,例如通过 PodFitsResources 过滤器检查候选节点是否有足够的资源来满足 Pod 资源的请求。这个步骤完成后会得到一个包含合适的节点的列表(通常为多个),如果列表为空,则Pod不可调度。 打分也被称为优选(Priorities),在该步骤中,会对上一个步骤的输出进行打分,Scheduer 通过打分的规则为每个通过 Filtering 步骤的节点计算出一个分数。 完成上述两个步骤之后,kube-scheduler 会将Pod分配给分数最高的 Node,如果存在多个相同分数的节点,会随机选择一个。 kubernetes的调度策略 Kubernetes 1.21之前版本可以在代码 kubernetes\pkg\scheduler\algorithmprovider\registry.go 中看到对应的注册模式,在1.22 scheduler 更换了其路径,对于registry文件更换到了kubernetes\pkg\scheduler\framework\plugins\registry.go ;对于kubernetes官方说法为,调度策略是用于“预选” (Predicates )或 过滤(filtering ) 和 用于 优选(Priorities)或 评分 (scoring)的...

深入理解Kubernetes 4A - Admission Control源码解析

本文是关于Kubernetes 4A解析的第3章 深入理解Kubernetes 4A - Authentication源码解析 深入理解Kubernetes 4A - Authorization源码解析 深入理解Kubernetes 4A - Admission Control源码解析 深入理解Kubernetes 4A - Audit源码解析 TLS Everywhere - 解密kubernetes集群的安全认证 所有关于Kubernetes 4A部分代码上传至仓库 github.com/cylonchau/hello-k8s-4A 如有错别字或理解错误地方请多多担待,代码是以1.24进行整理,实验是以1.19环境进行,差别不大 BACKGROUND admission controllers的特点: 可定制性:准入功能可针对不同的场景进行调整。 可预防性:审计则是为了检测问题,而准入控制器可以预防问题发生 可扩展性:在kubernetes自有的验证机制外,增加了另外的防线,弥补了RBAC仅能对资源提供安全保证。 下图,显示了用户操作资源的流程,可以看出 admission controllers 作用是在通过身份验证资源持久化之前起到拦截作用。在准入控制器的加入会使kubernetes增加了更高级的安全功能。 图:Kubernetes API 请求的请求处理步骤图 Source:https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/ 这里找到一个大佬博客画的图,通过两张图可以很清晰的了解到admission webhook流程,与官方给出的不一样的地方在于,这里清楚地定位了kubernetes admission webhook 处于准入控制中,RBAC之后,push 之前。 图:Kubernetes API 请求的请求处理步骤图(详细) Source:https://www.armosec.io/blog/kubernetes-admission-controller/ 两种控制器有什么区别? 根据官方提供的说法是 Mutating controllers may modify related objects to the requests they admit; validating controllers may not 从结构图中也可以看出,validating 是在持久化之前,而 Mutating 是在结构验证前,根据这些特性我们可以使用 Mutating 修改这个资源对象内容(如增加验证的信息),在 validating 中验证是否合法。...

如何为visio扩展云服务图标

各个云厂商都会为自己的服务提供通用可缩放矢量图形 (SVG) 图标,以便用户为自己的软件绘制架构图,例如Microsoft 为Visio 提供 Azure 服务的图标。文本在这里简单整理了几个关于云服务的图标 Azure-Design 提供了大量并完整的azure的一些图标 AWS-Architecture-Icons 提供了一些关于AWS的图标,不过图标为2019年时的 Microsoft-Integration-and-Azure 整合了一些关于微软的图标,并附带了矢量图 更多的图标可以在github或google搜索相关关键词 visio stencil 网络上还是有很多相关的图标库 将图标导入到visio中 为了能使下载的图标在Visio 中可用,只需要简单的一个步骤即可。 将下载下来的图标放置到 C:\Users\<UserName>\Documents\My Shapes 中文系统为 用户目录\文档\我的图形 我的图形需要安装visio后才会有这个文件夹 如图所示: 测试导入后的效果,我们在这里导入了aws与azure的图标库,故可以看到有两个,但是两个中又包含很多,已经足够使用了 最后再附上一个大神制作的 VISIO Protable 版本,匿名网盘,失效不补

使nginx支持分布式追踪

Background NGINX 是一个通用且流行的应用程序。也是最流行的 Web 服务器,它可用于提供静态文件内容,但也通常与其他服务一起用作分布式系统中的组件,在其中它用作反向代理、负载均衡 或 API 网关。 分布式追踪 distributed tracing 是一种可用于分析与监控应用程序的机制,将追踪在从源到目的的整个过程中的单个请求,这与仅通过单个应用程序域来追踪请求的形式不同。 换句话说,我们可以说分布式追踪是对跨多个系统的多个请求的拼接。拼接通常由一个或多个相关 ID 完成,并且跟踪通常是一组记录的、跨所有系统的结构化日志事件,存储在一个中心位置。 在这种背景的情况下, OpenTracing 应运而生。OpenTracing 是一个与应用供应商无关的 API,它可帮助开发人员轻松地跟踪单一请求的域。目前有多种开源产品都支持 OpenTracing(例如,Jaeger, skywalking 等),并将其作为一种检测分布式追踪的标准化方法。 本文将围绕,从0到1实现在nginx配置分布式追踪的架构的简单实例说明。本文实例使用的组件为 nginx v1.22 jaeger-all-in-on v1.38 nginx-opentracing v1.22 jaeger-client-cpp v0.9 源码构建nginx-opentracing 准备nginx-opentracing nginx-opentracing 仓库中可以看到,官方为每个nginx版本都提供了一个编译好的动态库(Nginx1.19.13+),我们可以直接拿来使用这个动态库,如果你想将这个利用Nginx 提供的编译参数 --add-module=/path/to/module 构建为nginx的内置功能的话,可能会出现一些问题,例如下面的一些错误: text 1 ngx_http_opentracing_module.so/config was found bash 1 2 3 /root/nginx-opentracing-0.25.0/opentracing//src/ngx_http_opentracing_module.cpp In file included from /root/nginx-opentracing-0.25.0/opentracing//src/ngx_http_opentracing_module.cpp:1:0: /root/nginx-opentracing-0.25.0/opentracing//src/load_tracer.h:3:38: fatal error: opentracing/dynamic_load.h: No such file or directory 根据 issue 中查询得知 nginx-opentracing 需要嵌入到nginx中,是需要一些 opentracing-cpp 因为对c++不熟,尝试调试很久还是上面的错误,故直接使用了官方提供的动态库。...

利用kubernetes中的leader选举机制自定义HA应用

Backgroud 前一章中,对kubernetes的选举原理进行了深度剖析,下面就通过一个example来实现一个,利用kubernetes提供的选举机制完成的高可用应用。 对于此章需要提前对一些概念有所了解后才可以继续看下去 leader election mechanism RBCA Pod runtime mechanism Implementation 代码实现 如果仅仅是使用Kubernetes中的锁,实现的代码也只有几行而已。 go 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 package main import ( "context" "flag" "fmt" "os" "os/signal" "syscall" "time" metav1 "k8s....

源码分析Kubernetes HA机制 - leader election

Overview 在 Kubernetes的 kube-controller-manager , kube-scheduler, 以及使用 Operator 的底层实现 controller-rumtime 都支持高可用系统中的leader选举,本文将以理解 controller-rumtime (底层的实现是 client-go) 中的leader选举以在kubernetes controller中是如何实现的。 Background 在运行 kube-controller-manager 时,是有一些参数提供给cm进行leader选举使用的,可以参考官方文档提供的 参数 来了解相关参数。 bash 1 2 3 4 5 6 7 --leader-elect Default: true --leader-elect-renew-deadline duration Default: 10s --leader-elect-resource-lock string Default: "leases" --leader-elect-resource-name string Default: "kube-controller-manager" --leader-elect-resource-namespace string Default: "kube-system" --leader-elect-retry-period duration Default: 2s ... 本身以为这些组件的选举动作时通过etcd进行的,但是后面对 controller-runtime 学习时,发现并没有配置其相关的etcd相关参数,这就引起了对选举机制的好奇。怀着这种好奇心搜索了下有关于 kubernetes的选举,发现官网是这么介绍的,下面是对官方的说明进行一个通俗总结。simple leader election with kubernetes 通过阅读文章得知,kubernetes API 提供了一中选举机制,只要运行在集群内的容器,都是可以实现选举功能的。 Kubernetes API通过提供了两个属性来完成选举动作的 ResourceVersions:每个API对象唯一一个ResourceVersion Annotations:每个API对象都可以对这些key进行注释 注:这种选举会增加APIServer的压力。也就对etcd会产生影响...

源码分析Kubernetes controller组件 - controller-runtime

Overview controller-runtime 是 Kubernetes 社区提供可供快速搭建一套 实现了controller 功能的工具,无需自行实现Controller的功能了;在 Kubebuilder 与 Operator SDK 也是使用 controller-runtime 。本文将对 controller-runtime 的工作原理以及在不同场景下的使用方式进行简要的总结和介绍。 controller-runtime structure controller-runtime 主要组成是需要用户创建的 Manager 和 Reconciler 以及 Controller Runtime 自己启动的 Cache 和 Controller 。 Manager:是用户在初始化时创建的,用于启动 Controller Runtime 组件 Reconciler:是用户需要提供来处理自己的业务逻辑的组件(即在通过 code-generator 生成的api-like而实现的controller中的业务处理部分)。 Cache:一个缓存,用来建立 Informer 到 ApiServer 的连接来监听资源并将被监听的对象推送到queue中。 Controller: 一方面向 Informer 注册 eventHandler,另一方面从队列中获取数据。controller 将从队列中获取数据并执行用户自定义的 Reconciler 功能。 图:controller-runtime structure 图:controller-runtime flowchart 由图可知,Controller会向 Informer 注册一些列eventHandler;然后Cache启动Informer(informer属于cache包中),与ApiServer建立监听;当Informer检测到资源变化时,将对象加入queue,Controller 将元素取出并在用户端执行 Reconciler。 Controller引入 我们从 controller-rumtime项目的 example 进行引入看下,整个架构都是如何实现的。 可以看到 example 下的实际上实现了一个 reconciler 的结构体,实现了 Reconciler 抽象和 Client 结构体...

扩展Kubernetes API的另一种方式 - APIServer aggregation

Overview What is Kubernetes aggregation Kubernetes apiserver aggregation AA 是Kubernetes提供的一种扩展API的方法,目前并没有GA Difference between CRD and AA 众所周知,kubernetes扩展API的方法大概为三种:CRD、AA、手动扩展源码。根据CNCF分享中Min Kim说的AA更关注于实践,而用户无需了解底层的原理,这里使用过 kubebuilder, code-generator 的用户是很能体会到这点。官方也给出了CRD与AA的区别 API Access Control Authentication CR: All strategies supported. Configured by root apiserver. AA: Supporting all root apiserver’s authenticating strategies but it has to be done via authentication token review api except for authentication proxy which will cause an extra cost of network RTT. Authorization CR: All strategies supported. Configured by root apiserver....

手写一个kubernetes controller

Overview 根据Kuberneter文档对Controller的描述,Controller在kubernetes中是负责协调的组件,根据设计模式可知,controller会不断的你的对象(如Pod)从当前状态与期望状态同步的一个过程。当然Controller会监听你的实际状态与期望状态。 Writing Controllers go 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 package main import ( "flag" "fmt" "os" "time" v1 "k8s....