January 12, 2024
使用kubectl create service 命令无法为pod创建service问题
"\u003cp\u003e在做一个试验时,无意中发现使用 \u003ccode\u003ekubectl create service\u003c/code\u003e 命令无法为一个通过 \u003ccode\u003edeployment\u003c/code\u003e 创建出来的pod创建对应的 \u003ccode\u003eservice\u003c/code\u003e, 感觉有点奇怪,经过分析才明白怎么回事,这里将过程记录一下。\u003c/p\u003e\n\u003cp\u003e这里需要说明一下,本文操作全部是通过 \u003ccode\u003ekubectl create\u003c/code\u003e 命令来完成的,并没有使用 \u003ccode\u003ekubectl apply -f pod.yaml\u003c/code\u003e 这种方式。\u003c/p\u003e\n\u003cp\u003e这里先创建一个实验命名空间 \u003ccode\u003elab\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ kubectl create ns lab\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e首先创建一个\u003ccode\u003edeployment\u003c/code\u003e 对象\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ kubectl create deployment test --image\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003enginx:1.23-alpine --replicas\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e --port\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e80\u003c/span\u003e -n lab\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e确认创建成功\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ kubectl get deploy,pod -n lab\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eNAME READY UP-TO-DATE AVAILABLE AGE\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edeployment.apps/test 2/2 \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2 …\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e"
December 2, 2023
pod sandbox 创建netns源码分析
"\u003cp\u003e在上一篇《\u003ca href=\"https://blog.haohtml.com/archives/33163/\"\u003e创建Pod源码解析\u003c/a\u003e》文中,我们大概介绍了Pod的整体创建过程。其中有一步很重要,就是在创建三类容器之前必须先创建一个 \u003ccode\u003e sandbox\u003c/code\u003e (\u003ca href=\"https://github.com/kubernetes/kubernetes/blob/v1.27.3/pkg/kubelet/kuberuntime/kuberuntime_manager.go#L1079\"\u003e源码\u003c/a\u003e),本篇就来分析一下sandbox这一块的 \u003ccode\u003enetns\u003c/code\u003e 实现过程。\u003c/p\u003e\n\u003cp\u003e对 \u003ccode\u003esandbox\u003c/code\u003e 的创建由 \u003ccode\u003ekubelet\u003c/code\u003e 组件通过调用 \u003ca href=\"https://kubernetes.io/zh-cn/docs/concepts/architecture/cri/\"\u003eCRI\u003c/a\u003e 容器运行时服务来实现的,对于容器运行的实现目前市面上有多个,如 \u003ca href=\"https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/#docker\"\u003eDocker Engine\u003c/a\u003e(不推荐)、 \u003ca href=\"https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/#containerd\"\u003econtainerd\u003c/a\u003e、\u003ca href=\"https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/#cri-o\"\u003eCRI-O\u003c/a\u003e 等,由于目前生产环境中选择 containerd 的占大多数,所以这里我们以 \u003ccode\u003econtainerd\u003c/code\u003e 为例来看一下其实现过程。\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/containerd/containerd/blob/32bf805e5703bc91387d047fa76625e915ac2b80/pkg/cri/server/sandbox_run.go\"\u003ehttps://github.com/containerd/containerd/blob/32bf805e5703bc91387d047fa76625e915ac2b80/pkg/cri/server/sandbox_run.go\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e对 sandbox 的创建是由 cri 服务调用 \u003ccode\u003eRunPodSandbox()\u003c/code\u003e方法来实现的。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// RunPodSandbox creates and starts a pod-level sandbox. …\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e"
November 28, 2023
Rust中与闭包相关的三个trait
"\u003cp\u003e在 Rust 中,闭包就是一种能捕获 \u003ccode\u003e上下文环境变量\u003c/code\u003e 的函数。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e range \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e get_range_count \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e range.count(); \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e代码里的这个 \u003ccode\u003eget_range_count\u003c/code\u003e 就是闭包,range 是被这个闭包捕获的环境变量。\u003c/p\u003e\n\u003cp\u003e虽然说它是一种函数,但是不通过 \u003ccode\u003efn\u003c/code\u003e 进行定义。\u003cstrong\u003e在 Rust 中,并不把这个闭包的类型处理成 fn 这种函数指针类型,而是有单独的类型定义。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e切记这里是将闭包处理成是 \u003ccode\u003e单独的类型定义\u003c/code\u003e,这一点区别与其它开发语言。\u003c/p\u003e\n\u003cp\u003e至于按哪一种类型来处理,这个没有办法得知,因为只有在Rust编译器在编译的时候才可以确定其类型,并且在确定类型时,还需要根据这个闭包捕获上下文环境变量时的行为来确定。\u003c/p\u003e\n\u003ch1 id=\"闭包trait分类\"\u003e闭包trait分类\u003c/h1\u003e\n\u003cp\u003e根据闭包行为划分为三类trait( 主因是受到所有权影响):\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003ccode\u003eFnOnce\u003c/code\u003e 适用于能被调用一次的闭包,\u003ccode\u003e所有闭包\u003c/code\u003e都至少实现了这个 trait,因为所有闭包都必须能够被调用。一个会将捕获的值移出闭包体的闭包只实现 \u003ccode\u003eFnOnce\u003c/code\u003e trait,这是因为它只能被调用一次。其获取了上下文环境变量的所有权。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eFnMut\u003c/code\u003e 适用于 …\u003c/li\u003e\u003c/ol\u003e"
November 16, 2023
Rust中的迭代器iter
"\u003cp\u003e迭代器模式允许你对一个序列的项进行某些处理。\u003cstrong\u003e迭代器\u003c/strong\u003e(\u003cem\u003eiterator\u003c/em\u003e)负责遍历序列中的每一项和决定序列何时结束的逻辑。当使用迭代器时,我们无需重新实现这些逻辑。\u003c/p\u003e\n\u003cp\u003e在 Rust 中,迭代器是 \u003cstrong\u003e惰性的\u003c/strong\u003e(\u003cem\u003elazy\u003c/em\u003e),这意味着在调用方法使用迭代器之前它都不会有效果。例如,示例中的代码通过调用定义于 \u003ccode\u003eVec\u003c/code\u003e 上的 \u003ccode\u003eiter\u003c/code\u003e 方法在一个 vector \u003ccode\u003ev1\u003c/code\u003e 上创建了一个迭代器。这段代码本身没有任何用处:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e v1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evec!\u003c/span\u003e[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e v1_iter \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e v1.iter();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e迭代器被储存在 \u003ccode\u003ev1_iter\u003c/code\u003e 变量中。一旦创建迭代器之后,可以选择用多种方式利用它。\u003c/p\u003e\n\u003ch1 id=\"迭代器分类\"\u003e迭代器分类\u003c/h1\u003e\n\u003cp\u003eRust 中迭代器根据 \u003ccode\u003e所有权\u003c/code\u003e 可分为 \u003ccode\u003eiter()\u003c/code\u003e、\u003ccode\u003eiter_mut()\u003c/code\u003e、\u003ccode\u003einto_iter()\u003c/code\u003e 三种迭代器,使用场景:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e获取集合元素不可变引用的迭代器,对应方法为 \u003ccode\u003eiter()\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e获取集合元素可变引用的迭代器,对应方法为 \u003ccode\u003eiter_mut()\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e获取集合元素所有权的迭代器,对应方法为 \u003ccode\u003einto_iter()\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e也就是说当你在 Rust 中看到调用了 \u003ccode\u003eiter()\u003c/code\u003e 方法,则表示这里使用了不可 …\u003c/p\u003e"
November 7, 2023
Rust 中的 Result 与 Option
"\u003cp\u003e在 Rust 中有两个常用的 \u003ccode\u003eenum\u003c/code\u003e 枚举类型,分别为 \u003ccode\u003eResult\u003c/code\u003e 和 \u003ccode\u003eOption\u003c/code\u003e,本节介绍它们两者各自的使用场景和用法。\u003c/p\u003e\n\u003cp\u003e这里我们先给出结论\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e结果 \u003ccode\u003eResult\u003c/code\u003e 表示 \u003ccode\u003e成功\u003c/code\u003e 或 \u003ccode\u003e失败\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e选项 \u003ccode\u003eOption\u003c/code\u003e 表示 \u003ccode\u003e有\u003c/code\u003e 或者 \u003ccode\u003e无\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e当从本地读取一个文件时,这时候可能读取成功,也有可能由于文件不存在或权限不足导致读取时候,这种场景一般就需要使用 \u003ccode\u003eResult\u003c/code\u003e;而当从一组数据集中查询指定元素是否存在时,这时有可能存在,也有可能不存在(用None 表示),这时情况就应该选择Option。\u003c/p\u003e\n\u003cp\u003e由此看到,这两个枚举类型的区别理解起来还是挺简单的,下面我们单独对每一种类型做一下详细的介绍。\u003c/p\u003e\n\u003ch1 id=\"结果-result\"\u003e结果 Result\u003c/h1\u003e\n\u003cp\u003e定义\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eenum\u003c/span\u003e Result\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT, E\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e Ok(T),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e Err(E),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ccode\u003eResult\u0026lt;T, E\u0026gt;\u003c/code\u003e 类型拥有两个取值:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eOk(value)\u003c/code\u003e 表示操作成功,并包装操作返回的 \u003ccode\u003evalue\u003c/code\u003e(\u003ccode\u003evalue\u003c/code\u003e 拥有 \u003ccode\u003eT\u003c/code\u003e 泛类型)。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eErr(why)\u003c/code\u003e,表示操作失败,并包装 \u003ccode\u003ewhy\u003c/code\u003e,它(但愿)能够解释失败的原因(\u003ccode\u003ewhy\u003c/code\u003e 拥有 \u003ccode\u003eE\u003c/code\u003e 类型)。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e举个例子,这里打开 …\u003c/p\u003e"
October 2, 2023
kubectr 一款快速查看Pod容器的kubectl插件
"\u003cp\u003e以前工作中经常需要查看Pod里容器相关信息,特别是容器镜像信息,以前一直是通过 \u003ccode\u003ekubectl describe\u003c/code\u003e命令查看的\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ kubectl describe my-pod\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e但由于输出的内容特别多,查看容器关键信息特别麻烦。印象最深的莫过于在部署 \u003ccode\u003eistio\u003c/code\u003e时,由于国内网络环境不稳定,经常性的遇到镜像下载失败的情况,当时极其的头疼。\u003c/p\u003e\n\u003cp\u003e于是最近花了一点时间,开发了一款快速查看 Pod 容器信息的插件 \u003ca href=\"https://github.com/cfanbo/kubectr\"\u003ekubectr\u003c/a\u003e 。\u003c/p\u003e\n\u003ch1 id=\"安装\"\u003e安装\u003c/h1\u003e\n\u003cp\u003e安装方法主要有三种\u003c/p\u003e\n\u003ch2 id=\"krew-安装推荐\"\u003ekrew 安装(推荐)\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ kubectl krew install ctr\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cblockquote\u003e\n\u003cp\u003e目前已提交到 \u003ca href=\"https://github.com/kubernetes-sigs/krew\"\u003ekrew\u003c/a\u003e ,但由于官方审核速度较慢,此安装方法不敢保证可用\u003c/p\u003e\u003c/blockquote\u003e\n\u003ch2 id=\"二进制安装\"\u003e二进制安装\u003c/h2\u003e\n\u003cp\u003e从 \u003ca href=\"https://github.com/cfanbo/kubectr/releases\"\u003ehttps://github.com/cfanbo/kubectr/releases\u003c/a\u003e 下载对应的平台版本,并解压到对应的 PATH 环境变量目录即可。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ tar zxvf kubectr_linux_amd64.tar.gz\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ sudo mv kubectr /usr/local/bin/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ kubectr -h\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"源码安装\"\u003e源码安装\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ git clone …\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e"
September 22, 2023
envoy中 lua filter 与 wasm filter使用教程
"\u003cp\u003e在 Envoy 中当我们需要对 \u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-msg-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager\"\u003ehttp_connection_manager\u003c/a\u003e 中的请求进行修改时,如添加或删除一个请求header,一般通过 \u003ccode\u003eHTTP Filter\u003c/code\u003e 过滤器来实现。\u003c/p\u003e\n\u003cp\u003e而在Envoy 包含的几十个Filter中,通常会选择 \u003ccode\u003eLua Filter \u003c/code\u003e(\u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/lua/v3/lua.proto#extensions-filters-http-lua-v3-lua\"\u003eextensions.filters.http.lua.v3.Lua\u003c/a\u003e) 或 \u003ccode\u003eWasm Filter\u003c/code\u003e (\u003ca href=\"https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/wasm/v3/wasm.proto#extensions-filters-http-wasm-v3-wasm\"\u003eextensions.filters.http.wasm.v3.Wasm\u003c/a\u003e)这两类过滤器。\u003c/p\u003e\n\u003ch1 id=\"lua-filter-与-wasm-filter\"\u003eLua Filter 与 Wasm Filter\u003c/h1\u003e\n\u003cp\u003e下表是 \u003ccode\u003eLua Filter\u003c/code\u003e 与 \u003ccode\u003eHTTP Filter\u003c/code\u003e 的对比\u003c/p\u003e\n\u003ctable\u003e\n \u003cthead\u003e\n \u003ctr\u003e\n \u003cth\u003e\u003c/th\u003e\n \u003cth\u003eLua Filter\u003c/th\u003e\n \u003cth\u003eWasm Filter\u003c/th\u003e\n \u003c/tr\u003e\n \u003c/thead\u003e\n \u003ctbody\u003e\n \u003ctr\u003e\n \u003ctd\u003e编程语言\u003c/td\u003e\n \u003ctd\u003eLua,解释型脚本语言\u003c/td\u003e\n \u003ctd\u003eWebAssembly,编译型语言\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e运行环境\u003c/td\u003e\n \u003ctd\u003eEnvoy 内置的 Lua …\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e"
September 17, 2023
WebAssembly开发入门教程
"\u003ch1 id=\"wasm简介\"\u003ewasm简介\u003c/h1\u003e\n\u003cp\u003eWebAssembly(Wasm)是一种通用字节码技术,它可以将其他编程语言(如 Go、Rust、C/C++ 等)的程序代码编译为可在浏览器或服务端环境直接执行的字节码程序。\u003c/p\u003e\n\u003ch1 id=\"使用场景\"\u003e使用场景\u003c/h1\u003e\n\u003cp\u003e主要有两个使用场景,分别为 浏览器 和 服务端。\u003c/p\u003e\n\u003ch2 id=\"浏览器\"\u003e浏览器\u003c/h2\u003e\n\u003cp\u003ewasm最早的出现是为了解决浏览器端的性能问题,让web应用可以达到与本地原生应用类似的性能。\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://blogstatic.haohtml.com/uploads/2023/09/640.png\" alt=\"Image\"\u003e\u003c/p\u003e\n\u003cp\u003e对于浏览器chrome 采用了v8 javascript引擎,其内置了一个 Wasm Runtime,因此可以实现对 wasm 的支持,这也正是浏览器可以运动wasm的原因。\u003c/p\u003e\n\u003ch2 id=\"服务端\"\u003e服务端\u003c/h2\u003e\n\u003cp\u003e2019 年 3 月,Mozilla 推出了 WebAssembly 系统接口(Wasi),以标准化 WebAssembly 应用程序与系统资源之间的交互抽象,例如文件系统访问、内存管理和网络连接,该接口类似于 POSIX 等标准 API。\u003cstrong\u003eWasi 规范的出现极大地扩展了 WebAssembly 的应用场景,使得 Wasm 不仅限于在浏览器中运行,而且可以在服务器端得到应用\u003c/strong\u003e。同时,平台开发者可以针对特定的操作系统和运行环境提供 Wasi 接口的不同实现,允 …\u003c/p\u003e"
September 5, 2023
istio 中 sidecar 注入实现原理
"\u003cp\u003e在 istio 中为了对流量进行有效的管理,一般通过\u003ccode\u003e注入\u003c/code\u003e的方式将代理 \u003ccode\u003eistio-proxy\u003c/code\u003e 与应用程序一起位于同一个Pod,然后通过 \u003ccode\u003eistio-init \u003c/code\u003e initContainer修改 iptables 实现 \u003ccode\u003eingress\u003c/code\u003e 或 \u003ccode\u003eegress\u003c/code\u003e,那么在 istio 中这个注入是如何实现的呢,本节对其实现原理进行一些分析。\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://istio.io/latest/docs/concepts/security/arch-sec.svg\" alt=\"https://istio.io/latest/docs/concepts/security/arch-sec.svg\"\u003e\u003c/p\u003e\n\u003ch1 id=\"实现原理\"\u003e实现原理\u003c/h1\u003e\n\u003cp\u003e在上一节\u003ca href=\"https://blog.haohtml.com/archives/34883/\"\u003e《apiserver 中的webhook开发教程》\u003c/a\u003e 我们介绍过\u003ccode\u003eadmission controller\u003c/code\u003e 基本实现原理,由此得知当创建一个资源对象的时候,可以通过定义 \u003ccode\u003eValidatingWebhookConfiguration\u003c/code\u003e 或 \u003ccode\u003eMutatingWebhookConfiguration\u003c/code\u003e 实现在创建的进程中对这些 webhook 进行调用。而 \u003ccode\u003eMutatingWebhookConfiguration\u003c/code\u003e 则可以对请求的资源进行修改。在istio中的 \u003ccode\u003einjection\u003c/code\u003e 正是基于此原理实现的。\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://blogstatic.haohtml.com/uploads/2023/08/6ca5dd6b207691069de1cf4df59cc6ad.png\" alt=\"\"\u003e\u003c/p\u003e\n\u003ch1 id=\"webhook配置\"\u003ewebhook配置\u003c/h1\u003e\n\u003cp\u003e当我们在k8s集群中安装 istio 后,会创建一些资源,如 \u003ccode\u003edeployment\u003c/code\u003e、\u003ccode\u003eservice\u003c/code\u003e、\u003ccode\u003ecrd\u003c/code\u003e 等\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ istioctl …\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e"
August 31, 2023
terraform 中的 provider
"\u003cp\u003e本文主要对 \u003ca href=\"https://www.terraform.io/\"\u003eterraform\u003c/a\u003e 中的 \u003ccode\u003eProviders\u003c/code\u003e 进行介绍,让刚刚接触 \u003ccode\u003eterraform\u003c/code\u003e 的用户对其有一个大概的了解,以下内容翻译自:https://developer.hashicorp.com/terraform/language/providers\u003c/p\u003e\n\u003ch1 id=\"什么是-providers\"\u003e什么是 Providers\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003e实践:\u003c/strong\u003e Try the \u003ca href=\"https://developer.hashicorp.com/terraform/tutorials/configuration-language/provider-use?utm_source=WEBSITE\u0026amp;utm_medium=WEB_IO\u0026amp;utm_offer=ARTICLE_PAGE\u0026amp;utm_content=DOCS\"\u003ePerform CRUD Operations with Providers\u003c/a\u003e tutorial.\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003eTerraform 依赖于称为提供商的插件来与\u003ccode\u003e云提供商\u003c/code\u003e、\u003ccode\u003eSaaS 提供商\u003c/code\u003e和 \u003ccode\u003e其他 API\u003c/code\u003e 进行交互。 Terraform 配置必须声明它们需要哪些 \u003ccode\u003eproviders\u003c/code\u003e,以便 \u003ccode\u003eTerraform\u003c/code\u003e 可以 \u003cstrong\u003e安装\u003c/strong\u003e 和 \u003cstrong\u003e使用\u003c/strong\u003e 它们。此外,某些提供商在使用之前需要进行配置(例如 \u003ccode\u003e端点 URL\u003c/code\u003e 或 \u003ccode\u003e云区域\u003c/code\u003e)。\u003c/p\u003e\n\u003ch1 id=\"providers-能做什么\"\u003eProviders 能做什么\u003c/h1\u003e\n\u003cp\u003e每一个 Providers 都会有一组 Terraform 可以管理的 \u003ca href=\"https://developer.hashicorp.com/terraform/language/resources\"\u003eresource types\u003c/a\u003e 和或 \u003ca href=\"https://developer.hashicorp.com/terraform/language/data-sources\"\u003edata sources\u003c/a\u003e。如我们经常使用的 \u003ca href=\"https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs\"\u003edocker provider\u003c/a\u003e, 它提供了一些 \u003ccode\u003eResources\u003c/code\u003e 和 \u003ccode\u003eData sources\u003c/code\u003e,使用 …\u003c/p\u003e"
August 19, 2023
k8s 中 CRD controller 开发教程
"\u003cp\u003e本文主要介绍 \u003ccode\u003ecrd controller\u003c/code\u003e 的基本开发过程,让每一个刚接触k8s开发的同学都可以轻松开发自己的控制器。\u003c/p\u003e\n\u003ch1 id=\"kubebuilder-简介\"\u003ekubebuilder 简介\u003c/h1\u003e\n\u003cp\u003e\u003ccode\u003ekubebuilder\u003c/code\u003e 是一个帮助开发者快速开发 \u003ccode\u003ekubernetes API\u003c/code\u003e 的脚手架命令行工具,其依赖 \u003ccode\u003econtroller-tools\u003c/code\u003e 和 \u003ccode\u003econtroller-runtime\u003c/code\u003e 两个库。其中 \u003ccode\u003econtroller-runtime\u003c/code\u003e 简化 \u003ccode\u003ekubernetes controller\u003c/code\u003e 的开发,并且对 \u003ccode\u003ekubernetes\u003c/code\u003e 的几个常用库进行了二次封装, 以简化开发工程。而 \u003ccode\u003econtroller-tool\u003c/code\u003e 主要功能是代码生成。\u003c/p\u003e\n\u003cp\u003e下图是使用 \u003ccode\u003ekubebuilder\u003c/code\u003e 的工作流程图:\u003cimg src=\"https://blogstatic.haohtml.com/uploads/2023/08/76264fc22f097ec97349461e383ed996.webp\" alt=\"format%2Cpng\"\u003e\u003c/p\u003e\n\u003ch1 id=\"安装-kubebuilder\"\u003e安装 kubebuilder\u003c/h1\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# download kubebuilder and install locally.\n➜ curl -L -o kubebuilder \u0026#34;https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)\u0026#34;\n➜ chmod +x kubebuilder …\u003c/code\u003e\u003c/pre\u003e"
August 3, 2023
apiserver 中的webhook开发教程
"\u003cp\u003ek8s: v1.27.3\u003c/p\u003e\n\u003ch2 id=\"what-are-they.wp-block-heading\"\u003e什么是准入控制插件?\u003ca href=\"https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/admission-controllers/#what-are-they\"\u003e\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003e准入控制器\u003c/strong\u003e 是一段代码,它会在请求通过\u003cstrong\u003e认证\u003c/strong\u003e和\u003cstrong\u003e鉴权\u003c/strong\u003e之后、对象被持久化之前拦截到达 API 服务器的请求。\u003cimg src=\"https://blogstatic.haohtml.com/uploads/2023/08/6ca5dd6b207691069de1cf4df59cc6ad.png\" alt=\"\"\u003e\u003c/p\u003e\n\u003cp\u003e准入控制器可以执行 \u003cstrong\u003e变更(Mutating)\u003c/strong\u003e 和或 \u003cstrong\u003e验证(Validating)\u003c/strong\u003e 操作。 变更(mutating)控制器可以根据被其接受的请求更改相关对象;验证(validating)控制器则不行。\u003c/p\u003e\n\u003cp\u003e准入控制器限制创建、删除、修改对象的请求。 准入控制器也可以阻止自定义动作,例如通过 API 服务器代理连接到 Pod 的请求。 准入控制器\u003cstrong\u003e不会\u003c/strong\u003e (也不能)阻止读取(\u003cstrong\u003eget\u003c/strong\u003e、\u003cstrong\u003ewatch\u003c/strong\u003e 或 \u003cstrong\u003elist\u003c/strong\u003e)对象的请求。\u003c/p\u003e\n\u003cp\u003e某些控制器既是变更准入控制器又是验证准入控制器。如果两个阶段之一的任何一个控制器拒绝了某请求,则整个请求将立即被拒绝,并向最终用户返回错误。\u003c/p\u003e\n\u003cp\u003eKubernetes 1.27 中的准入控制器由下面的\u003ca href=\"https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/admission-controllers/#what-does-each-admission-controller-do\"\u003e列表\u003c/a\u003e组成, 并编译进 \u003ccode\u003ekube-apiserver\u003c/code\u003e 可执行文件,并且只能由集群管理员配置。 在该列表中,有两个特殊的控制器:\u003ccode\u003eMutatingAdmissionWebhook\u003c/code\u003e 和 \u003ccode\u003eValidatingAdmissionWebhook\u003c/code\u003e。 它们 …\u003c/p\u003e"
August 1, 2023
k8s之kube-controller-manager 源码分析
"\u003cp\u003eKubernetes 控制器管理器(\u003ccode\u003ekube-controller-manager\u003c/code\u003e)是一个守护进程,内嵌随 Kubernetes 一起发布的核心控制回路。 在机器人和自动化的应用中,控制回路是一个永不休止的循环,用于调节系统状态。 在 Kubernetes 中,每个控制器是一个控制回路,通过 API 服务器监视集群的共享状态, 并尝试进行更改以将当前状态转为期望状态。 目前,Kubernetes 自带的控制器例子包括副本控制器、节点控制器、命名空间控制器和服务账号控制器等。\u003c/p\u003e\n\u003cp\u003e本文不对 \u003ccode\u003ekube-controller-manager\u003c/code\u003e 管理的每个控制器的执行原理做介绍,只是从全局观看一下kube-controller-manager 启动每个控制器的整体实现过程。\u003c/p\u003e\n\u003cp\u003ek8s: v1.27.3\u003c/p\u003e\n\u003cp\u003e文件: \u003ca href=\"https://github.com/kubernetes/kubernetes/blob/v1.27.3/cmd/kube-controller-manager/app/controllermanager.go\"\u003ecmd/kube-controller-manager/app/controllermanager.go\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"控制器选项初始化\"\u003e控制器选项初始化\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// cmd/kube-controller-manager/app/controllermanager.go#L104\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc …\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e"
July 31, 2023
k8s调度器插件开发教程
"\u003cp\u003e上一篇 \u003ca href=\"https://blog.haohtml.com/archives/33138\"\u003e《k8s调度器 kube-scheduler 源码解析》\u003c/a\u003e 大概介绍一调度器的内容,提到扩展点的插件这个概念,下面我们看看如何开发一个自定义调度器。\u003c/p\u003e\n\u003cp\u003e本文源码托管在 \u003ca href=\"https://github.com/cfanbo/sample-scheduler\"\u003ehttps://github.com/cfanbo/sample-scheduler\u003c/a\u003e。\u003c/p\u003e\n\u003ch1 id=\"插件机制\"\u003e插件机制\u003c/h1\u003e\n\u003cp\u003e在Kubernetes调度器中,共有两种插件机制,分别为 \u003ccode\u003ein-tree\u003c/code\u003e 和 \u003ccode\u003eout-of-tree\u003c/code\u003e。\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eIn-tree插件(内建插件):这些插件是作为Kubernetes核心组件的一部分直接编译和交付的。它们与Kubernetes的源代码一起维护,并与Kubernetes版本保持同步。这些插件以静态库形式打包到kube-scheduler二进制文件中,因此在使用时不需要单独安装和配置。一些常见的in-tree插件包括默认的调度算法、Packed Scheduling等。\u003c/li\u003e\n\u003cli\u003eOut-of-tree插件(外部插件):这些插件是作为独立项目开发和维护的,它们与Kubernetes核心代码分开,并且可以单独部署和更新。本质上,out-of-tree插件是基于Kubernetes的调度器扩展点进行开发的。这些插件以独立的二进制文件 …\u003c/li\u003e\u003c/ol\u003e"
July 28, 2023
k8s调试之 kube-apiserver 组件
"\u003cp\u003e上一节\u003ca href=\"https://blog.haohtml.com/archives/34402\"\u003e《GoLand+dlv进行远程调试》\u003c/a\u003e我们介绍了如何使用 \u003ccode\u003eGoLand\u003c/code\u003e 进行远程调试,本节我们就以 \u003ccode\u003ekube-apiserver\u003c/code\u003e 为例演示一下调试方法。\u003c/p\u003e\n\u003ch1 id=\"服务器环境\"\u003e服务器环境\u003c/h1\u003e\n\u003cp\u003e作为开发调试服务器,需要安装以下环境\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e安装 \u003ccode\u003eGolang\u003c/code\u003e 环境,国内最好设置 \u003ccode\u003eGOPROXY\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e安装 \u003ccode\u003edlv\u003c/code\u003e 调试工具\u003c/li\u003e\n\u003cli\u003e安装 \u003ccode\u003eDocker\u003c/code\u003e 环境, 同时安装 \u003ccode\u003econtainerd\u003c/code\u003e 服务(对应官方教程中的 \u003ccode\u003econtainerd.io\u003c/code\u003e 安装包)并设置代理\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch1 id=\"同步代码本地\"\u003e同步代码(本地)\u003c/h1\u003e\n\u003cp\u003e以下为我们本机环境设置。\u003c/p\u003e\n\u003cp\u003e本机下载 \u003ca href=\"https://github.com/kubernetes/kubernetes\"\u003ekubernetes\u003c/a\u003e 仓库\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone --filter\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eblob:none https://github.com/kubernetes/kubernetes.git\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cblockquote\u003e\n\u003cp\u003e这里指定 –filter=bold:none 可以实现最小化下载\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003e这里 k8s 项目目录为 \u003ccode\u003e/Users/sxf/workspace/kubernetes\u003c/code\u003e, 对应远程服务器目录为 \u003ccode\u003e/home/sxf/workspace/kubernetes\u003c/code\u003e,如图所示\u003cimg src=\"https://blogstatic.haohtml.com/uploads/2023/07/d2b5ca33bd970f64a6301fa75ae2eb22-6.png\" alt=\"\"\u003e\u003c/p\u003e\n\u003cp\u003e映射关系配置\u003cimg src=\"https://blogstatic.haohtml.com/uploads/2023/07/d2b5ca33bd970f64a6301fa75ae2eb22-7.png\" alt=\"\"\u003e\u003c/p\u003e\n\u003cp\u003e同时选择自动上传 \u003ccode\u003eAutomatic upload (Always)\u003c/code\u003e 菜单,这 …\u003c/p\u003e"