May 12, 2024
git 操作中那些常常被忽略的用法
"git merge 与 git rebase 的区别 对于两者的区别,网上已经有很多文章做了介绍,不过有些初学者没有亲自实验过,多数也是作为八股文死记硬背而已。本文为了让大家彻底搞懂两者的区别,所以搞了一个实验环境并模拟了一些真实环境的操作。\n实验环境主要用到两个分支,其中 main 分支做了主要分支,而 dev 作为开发功能分支。\n在生产环境中需要选择合适的分支,这里只是实验环境,所以分支名不是本文关注的重点。\nmain dev 说明 mkdir git-demo \u0026amp;\u0026amp; cd git-demo \u0026amp;\u0026amp; git init touch 1.txt \u0026amp;\u0026amp; git add . \u0026amp;\u0026amp; git commit -m \u0026lsquo;add 1.txt\u0026rsquo; f3c82ba touch 2.txt \u0026amp;\u0026amp; git add . \u0026amp;\u0026amp; git commit -m \u0026lsquo;add 2.txt\u0026rsquo; eb061da touch 3.txt \u0026amp;\u0026amp; git add . …"
April 29, 2024
kubernetes 网络中DNS解析原理
"当我们通过域名(例如 www.example.com)访问一个网站时,第一步就是通过DNS服务器找到目的服务器IP地址(例如 93.184.215.14),接着再将请求数据包发送到这个 IP 服务器。\n而要想通过 DNS 服务器进行域名,必须得先知道 DNS 服务器地址才行,而这一般是通过读取配置文件实现,在 *nux 操作系统中,DNS 服务器一般配置在 /etc/resolv.conf文件,如\nsearch default.svc.cluster.local svc.cluster.local cluster.local nameserver 10.96.0.10 options ndots:5 用户可以通过 nameserver 指定多个 DNS 服务器,依次对域名进行解析,如果解析成功,则解析操作立即中止,如果解析不到的话,则将回退到公网 DNS 服务器进行解析,这个公网 DNS 服务器一般是由网络运营商来定的,用户不需要关心。如果公网 DNS 仍解析失败的话,则直接响应域名无法解析,此时用户将无法正常访问域名。\n什么是 FQDN 在介绍域名解析前, …"
April 22, 2024
Kubernetes集群扩缩容方案
"动态扩缩容主要包括两个层级的动态扩缩容。一个层级是应用本身级别的扩缩容,如HPA、VPA。当应用负载过高时,可以通过HPA多部署几个Pods副本;或者通过VPA对当前Pod硬件资源进行扩容,以此来减少应用负载。\n另一层是对集群自身的扩容,如 worker 节点的扩容。如部署Pods应用时,如果出现无可用节点资源可用时,则通过 Cluster Autoscaler 加入一些新的节点,并在新节点上重建Pods。\n本文主要看一下应用这个层级的扩缩容方案。\n水平扩展HPA \u0026amp;\u0026amp; 垂直扩展VPA HPA 在 Kubernetes 中,HPA(HorizontalPodAutoscaler)也称为水平扩缩容,它将根据当前应用程序工作负载,自动更新工作负载资源 (例如 Deployment 或者 StatefulSet)以满足当前需求。简单讲的话,就是如果集群检测到当前应用程序的n个Pod负载如果比较高的话,就再创建几个Pod副本,以减少当前负载,也就是我们平时说的水平扩容。相反如果应用程序Pod负载比较低的话,则将Pod副本数量进行减少,节省服务器资源,这个就是水平缩容。\n它的工作 …"
April 10, 2024
kubernetes中overlay网络与underlay网络的区别
"Kubernetes 中的 overlay 网络和 underlay 网络是两个不同的网络层面。\nUnderlay 网络 在 Kubernetes 网络架构中,Underlay 网络是指承载 Kubernetes 网络流量的物理网络或底层网络。这个网络通常由物理交换机、路由器和其他网络硬件组成,它们之间通过各种路由协议(例如 OSPF、BGP 等)连接在一起组成的传统网络。\nUnderlay 网络负责为 Kubernetes 节点提供基本的网络连接,它为上层的 overlay 网络提供支持。\n总之,Kubernetes 的网络流量,例如 Pod 到 Pod、Pod 到 Service 等都将在这个 Underlay 网络上进行传输。\nOverlay 网络 对于 Overlay 网络也被称为 覆盖网络,想必只要接触过一点 kubernetes 网络知识的同学都不陌生,它主用来解决 不同节点 中 Pod 之间通讯的一种网络解决方案。 在上图可以看到 Overlay 网络是构建在 underlay 网络之上的一层虚拟网络,它通过封装数据包(如VXLAN)通过物理网络进行传输,到达目标网络后再 …"
March 19, 2024
如何实现访问k8s集群服务之原理
"当我们想将 k8s 集群里的服务向外暴露时,一般是将 k8s service 指定 LoadBalancer类型。目前大多数云厂商会绑定云平台的负载均衡器,并为其分配一个固定的公网 IP 从而向外提供服务。而对于我们自建的 kubernetes 裸机集群则只能选择类似 MetalLB 这类解决方案,这种情况下如何让用户可以通过这个 IP 访问到自建 k8s 的服务呢,本文来分析一下其实现原理。\n本文的环境安装了 MetallB,它指定分配 IP Pool 为内网 IP 地址,实验环境为 https://blog.haohtml.com/posts/install-kubernetes-in-raspberry-pi/。\n将外部请求流入集群节点 当我们需要访问一台机器时,无论是使用 IP 地址还是域名,最终都需要将其解析为 IP 地址。而要真正建立连接并传输数据,我们必须获取目标 IP 地址对应的 MAC 地址,这是由于 TCP/IP 协议分层机制决定的。\n在 TCP/IP 协议栈的链路层,数据是通过封装成数据帧的方式在局域网内传输的。数据帧中包含了目标 MAC 地址,用于标识应该将数据 …"
February 2, 2024
Raspberry Pi 安装Kubernetes
"这里是 arm64 架构,树莓派 4B, 四核八 G 内存 配置,系统为 Ubuntu 22.04.1 LTS\n$ uname -a Linux ubuntu 5.15.0-1049-raspi #52-Ubuntu SMP PREEMPT Thu Mar 14 08:39:42 UTC 2024 aarch64 aarch64 aarch64 GNU/Linux $ cat /etc/issue Ubuntu 22.04.1 LTS \\n \\l 环境检查 由于 k8s 会使用 8080 和 6443 这两个端口,因此要保证端口可用,然后禁用 swap。\nsudo swapoff -a 最后对安装环境初始化,参考 https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/\n安装 Docker 参考 https://docs.docker.com/engine/install/ubuntu/\n安装成功后,修改 cgroupdriver 为 systemd,同时为了国内访问 docker …"
January 12, 2024
使用kubectl create service 命令无法为pod创建service问题
"在做一个试验时,无意中发现使用 kubectl create service 命令无法为一个通过 deployment 创建出来的pod创建对应的 service, 感觉有点奇怪,经过分析才明白怎么回事,这里将过程记录一下。\n这里需要说明一下,本文操作全部是通过 kubectl create 命令来完成的,并没有使用 kubectl apply -f pod.yaml 这种方式。\n这里先创建一个实验命名空间 lab\n$ kubectl create ns lab 首先创建一个deployment 对象\n$ kubectl create deployment test --image=nginx:1.23-alpine --replicas=2 --port=80 -n lab 确认创建成功\n$ kubectl get deploy,pod -n lab NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/test 2/2 2 2 16s NAME DESIRED CURRENT READY AGE …"
December 2, 2023
pod sandbox 创建netns源码分析
"在上一篇《创建Pod源码解析》文中,我们大概介绍了Pod的整体创建过程。其中有一步很重要,就是在创建三类容器之前必须先创建一个 sandbox (源码),本篇就来分析一下sandbox这一块的 netns 实现过程。\n对 sandbox 的创建由 kubelet 组件通过调用 CRI 容器运行时服务来实现的,对于容器运行的实现目前市面上有多个,如 Docker Engine(不推荐)、 containerd、CRI-O 等,由于目前生产环境中选择 containerd 的占大多数,所以这里我们以 containerd 为例来看一下其实现过程。\nhttps://github.com/containerd/containerd/blob/32bf805e5703bc91387d047fa76625e915ac2b80/pkg/cri/server/sandbox_run.go\n对 sandbox 的创建是由 cri 服务调用 RunPodSandbox()方法来实现的。\n// RunPodSandbox creates and starts a pod-level sandbox. …"
November 28, 2023
Rust中与闭包相关的三个trait
"在 Rust 中,闭包就是一种能捕获 上下文环境变量 的函数。\nlet range = 0..10; let get_range_count = || range.count(); 代码里的这个 get_range_count 就是闭包,range 是被这个闭包捕获的环境变量。\n虽然说它是一种函数,但是不通过 fn 进行定义。在 Rust 中,并不把这个闭包的类型处理成 fn 这种函数指针类型,而是有单独的类型定义。\n切记这里是将闭包处理成是 单独的类型定义,这一点区别与其它开发语言。\n至于按哪一种类型来处理,这个没有办法得知,因为只有在Rust编译器在编译的时候才可以确定其类型,并且在确定类型时,还需要根据这个闭包捕获上下文环境变量时的行为来确定。\n闭包trait分类 根据闭包行为划分为三类trait( 主因是受到所有权影响):\nFnOnce 适用于能被调用一次的闭包,所有闭包都至少实现了这个 trait,因为所有闭包都必须能够被调用。一个会将捕获的值移出闭包体的闭包只实现 FnOnce trait,这是因为它只能被调用一次。其获取了上下文环境变量的所有权。 FnMut 适用于不会将 …"
November 16, 2023
Rust中的迭代器iter
"迭代器模式允许你对一个序列的项进行某些处理。迭代器(iterator)负责遍历序列中的每一项和决定序列何时结束的逻辑。当使用迭代器时,我们无需重新实现这些逻辑。\n在 Rust 中,迭代器是 惰性的(lazy),这意味着在调用方法使用迭代器之前它都不会有效果。例如,示例中的代码通过调用定义于 Vec 上的 iter 方法在一个 vector v1 上创建了一个迭代器。这段代码本身没有任何用处:\nlet v1 = vec![1, 2, 3]; let v1_iter = v1.iter(); 迭代器被储存在 v1_iter 变量中。一旦创建迭代器之后,可以选择用多种方式利用它。\n迭代器分类 Rust 中迭代器根据 所有权 可分为 iter()、iter_mut()、into_iter() 三种迭代器,使用场景:\n获取集合元素不可变引用的迭代器,对应方法为 iter()\n获取集合元素可变引用的迭代器,对应方法为 iter_mut()\n获取集合元素所有权的迭代器,对应方法为 into_iter()\n也就是说当你在 Rust 中看到调用了 iter() 方法,则表示这里使用了不可变迭代器,只能读 …"