Below you will find pages that utilize the taxonomy term “IT”
如何临时或永久修改route table
内容摘要
如何修改route table,如何临时增加或删除路由条目,如何永久添加或删除路由条目。主要涉及route命令、nmcli命令、相关配置文件持久化位置等
临时修改,重启后丢失
直接使用 route 命令可以进行临时修改,但是在系统重启或者是执行interface重启后会丢失。
命令使用方式:
route {add | delete} {-host | -net} {des_ip} [netmask {net mask}] [gw {gw}] [dev {device}]
route add:命令关键字,表示增加路由,若要删除路由,则为route del;
-host | -net:表示路由目标是主机还是网段;
netmask:表示路由目标为网段时才会使用到,表示路由目标网段的子网掩码;
gw:命令关键字,后面跟下一跳网关;
dev:命令关键字,后面跟具体设备名,表示路由是从该设备出去。
metric:为路由指定所需跳数里的多个路由中选择与转发包中的目标地址最为匹配的路由。所选的路由具有最少的跳数。跳数能够反映途经节点的数量、路径的速度、路径可靠性、路径吞吐量以及管理属性。
示例:
添加路由:
route add –host 192.168.168.110 dev eth0
route add –host 192.168.168.119 gw 192.168.168.1
route add -net 192.168.3.0/24 dev eth0
route add -net 192.168.2.0/24 gw 192.168.2.254
route add –net 180.200.0.0 netmask 255.255.0.0 gw 10.200.6.201 dev eth0 metric 1
envoy proxy调研笔记
内容提要
我们主要想了解 envoy 如何提供 L4/L7的代理服务,envoy具体提供哪些功能,我们如何利用这些功能实现我们的业务场景。在envoy如何提供代理能力方面,主要有两点:1. envoy 如何从控制面获取配置; 2. envoy 如何根据配置信息进行路由。在如何利用envoy提供的功能实现我们的业务场景方面,主要是 如何将 k8s集群中的相关资源对象的描述信息,转换为envoy 的配置。
本文我们将围绕以上两个方面,进行介绍,主要有以下相关内容:
-
envoy是什么?为了解决什么问题,具有什么特点,能力边界在哪里。
-
明确envoy中的基本术语,以及envoy的基本工作框架,处理流程。
-
envoy的动态配置能力。控制面如何将k8s集群中的route资源描述信息动态实时地传达到envoy?
-
有了路由配置信息后,envoy如何对请求进行路由。这部分内容主要聚焦在路由能力,这个能力主要是由http route filter提供。这部分涉及到一些代码实现层面的处理以及相关数据结构。
-
envoy的主要组件与模型:线程模型、常见组件、过滤器等。
-
对几个控制面组件的简单对比。
-
为了便于评估envoy能够对哪些业务需求提供支持,简单罗列了envoy提供的功能特性。
Envoy 是什么¶
根据envoy官网的定义,envoy是一个开源的为云原生应用而设计的边缘和服务代理(edge and service proxy)。使用c++ 编写,设计定位是用于大规模微服务服务网格架构的通用数据平面。为的是解决以下在大规模微服务场景中存在的挑战:1. 复杂异构系统中的网络维护;2. 流量监控中的困难;3. 扩缩容。
通常来说有两种部署方式,一种是作为sidecar 和微服务应用部署在一起,将网络相关的逻辑从微服务中抽离出来,提供服务网格的数据面能。

另一种部署方式是作为一个代理网关部署,作为微服务集群的流量入口。

envoy可以提供的能力有:负载均衡、可用性增强能力(如超时、熔断、重试等)、可观测性、指标监控等。
envoy的一大特点是可以通过xDS实现实时的动态配置更新。在k8s容器集群中,部署的应用会不停地新增、减少、漂移,路由配置会不停地发生变化,xDS 这一特性能很好地在这种频繁发生路由配置变化的场景下高效运作。不仅仅是路由相关的配置可以热加载生效,envoy 可以通过xds进行除本身二进制文件之外的几乎所有变更,也就是除非需要更新envoy本身,否则任何变更都无需将envoy停止运行,这为我们的运维变更带来了极大的便利性。
除了支持xds进行动态配置,envoy也支持进行静态配置,但是通常来说,由于其配置具有很高的灵活度,也导致了配置具有较高的复杂性,难以人工维护,通常来说都是由代码生成。
envoy只扮演数据平面的角色,不扮演控制平面的角色。尽管envoy适用于k8s集群云原生场景,但是并不会对k8s集群的路由相关资源进行监控,并转换为相关的路由配置。因此我们需要有控制面程序来完成对k8s集群中路由相关资源进行监控,来完成路由配置的生成,并通过xds将配置同步到envoy中。
当前常见的控制面实现有:istio、contour、emissary-ingress(ambassador)、gloo等。以conotur为例,常见的部署形态如下所示:

参考链接:
- https://www.tetrate.io/blog/get-started-with-envoy-in-5-minutes/
- https://www.tetrate.io/what-is-envoy-proxy/#:~:text=Introducing Envoy Proxy,data plane for service mesh.
envoy的基本概念和框架¶
基本概念:
https://www.envoyproxy.io/docs/envoy/v1.21.4/intro/arch_overview/intro/terminology:
使用make进行golang编译中的小问题及解决方案
- 报错信息:Clock skew detected. Your build may be incomplete.
make: Warning: Clock skew detected. Your build may be incomplete.
表示检测到了时钟偏差,通常发生在将代码从开发主机拷贝到编译主机进行编译,而两个设备系统之间的时间上存在差距。
解决方案:
find ./ -type f | xargs touch
将所有文件进行一次touch,刷新时间为本地时间,然后进行编译
- 报错信息:
no required module provides package main.go; to add it:
go get main.go
解决方案
修改 makefile中 build 的命令行:
由
go build -o bin/manager main.go
改为:
go build -o bin/manager ${MODULE}/path/to/the/dir/of/main.go
${MODULE} 为当前项目module值,可在 go.mod中获取,即开头的 module值
/path/to/the/dir/of/main.go 为main.go所在目录在本项目中的相对路径
envoy 动态路由配置信息查看
envoy 通过静态配置和动态配置接口共同决定 路由配置信息。在contour + envoy 的部署使用模式下,envoy 的静态配置中主要定义了如何从contour 获取动态配置信息,而contour 作为 envoy 的控制面 xds server运行,将从k8s 集群 的ingress 资源描述中获取到的路由信息通过xds发送给 envoy。
因此,我们可以通过两种方式来获取 envoy路由配置的相关信息:
- 一种是通过contour 暴露的接口,去看 contour 给 envoy 发送的内容
- 一种是通过 envoy 暴露的接口去看envoy接收生效的内容
查看 contour发送的内容
contour 提供了命令行交互能力,可以执行命令 contour cli eds 等命令去获取endpoint等配置的信息。
相关命令:
获取 contour pod信息:
CONTOUR_POD=$(kubectl -n projectcontour get pod -l app=contour -o jsonpath='{.items[0].metadata.name}')
进入该pod执行查看命令:
kubectl -n projectcontour exec ${CONTOUR_POD} -c contour -- contour cli eds --cafile=/certs/ca.crt --cert-file=/certs/tls.crt --key-file=/certs/tls.key
其中eds 表示查看 endpoint 相关配置
支持以下基本信息查看:
- eds: endpoint 信息
- cds: cluster信息
- rds: route信息
- lds: listener 信息
注意这个是一个持续监听的接口,执行后不会退出,当k8s集群ingress相关资源对象发生变化时,又或获取最新配置内容。
wait非子进程退出
背景
有这样一个业务场景,需要主进程可以监测它创建的子进程是否还存活,通常来说使用 waitpid 来获取子进程的状态变化情况,就可以实现需求。但是我们希望在主进程异常退出重启后还能够监测之前创建的子进程的存活情况,但是waitpid 又只能针对子进程使用。于是就有了以下问题:
- 为什么waitpid只能针对子进程使用?
- 有没有什么方法可以改变子进程的父进程?
- 有没有什么方式可以监测非子进程的退出,或者是其他状态变化?
为什么waitpid只能针对子进程使用?
wait, waitpid, waitid 这三个系统函数都是为了等待进程状态发生变化。
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
这三个系统调用都是用于等待调用进程的子进程的状态改变,并获取到子进程状态变化的相关信息。状态变化包括:子进程终止、子进程收到信号停止、子进程收到信号被唤醒。当进程退出的时候,会进程资源会被回收,但是包含进程pid、进程退出状态、资源使用信息等的一个“最小信息集”会被保留,会在进程表中占用一个位置。当父进程使用 wait 系列函数时可以获取到已经终止的子进程的最小信息集所含信息,同时这些信息被清理,占用的进程表资源被回收。如果父进程没有wait并回收掉已经终结的子进程的进程表资源,子进程就会成为僵尸进程(zombies)。如果进程资源始终占用着进程表资源,将进程表资源耗尽,使得系统无法再创建新的进程。如果父进程终止了,那么僵尸进程会被系统一号进程领养,并由一号进程自动执行 wait 调用,将僵尸进程清理、将所占用的资源回收。
关于这个几个函数的使用细节可以查看 man 手册,有以下几点值得注意:
- 如果父进程在调用 wait 函数时,子进程的状态已经发生了变化,那么调用会立即返回,否则,会阻塞。但是这个行为可以通过options参数进行配置, options 是一个位控制参数, options 配置上
WNOHANG时可以是调用不阻塞,而是立即返回。 - 默认情况下 wait 函数只等待 子进程退出进入终结态的情况,这个行为可以通过options参数进行配置,配置上
WUNTRACED时可以 wait 子进程进入 stop 状态,配置上WCONTINUED可以 wait 处于 stop 状态中的进程被 SIGCONT 信号唤醒。 - status 参数不为 NULL 时,可以接受进程状态变化的相关信息,这些信息可以通过 相关宏对 status 处理得到。
- 当 对非子进程调用 wait 系列函数时,会返回错误 ECHILD。
当 对非子进程调用 wait 系列函数时,会返回错误 ECHILD。那么为什么呢?
学海拾贝-20220227-20220228
问题目录
- git merge 时不对message进行确认
- Windows上用户名不区分大小写
- 蓝绿部署、红黑部署、灰度发布
- docker no space left on device
- LVM进行逻辑卷扩容
1. git merge 时不对message进行确认
在进行 git merge 时会默认进入一个编辑 merge message 的编辑交互中,但是我们有时不希望进行内容变更或不希望进行交互编辑。
如果是不进行内容变更,可以使用 --no-edit :
git merge test-branch --no-edit
如果是不希望进行交互编辑,可以使用 -m 在 merge 时指定 message 内容:
git merge test-branch -m "the message that you want to commit"
ref: https://git-scm.com/docs/git-merge
2. Windows上用户名不区分大小写
Windows 下的用户名不区分大小写;但是,密码区分大小写。
linux 下的用户名区分大小写。
3. 蓝绿部署、红黑部署、灰度发布
-
蓝绿部署
在蓝绿色部署中,维护两套服务:“蓝色”服务和“绿色”服务。在任意时刻,只有一套服务被用于处理请求。另一套服务处于闲置状态。
进行新版本发布时,我们可以先将闲置状态的服务进行升级,再将生产流量从另一套服务切换过来。蓝绿没有什么特殊含义,只是为了便于区别和表述,我们可以将工作中的服务环境称为蓝色环境,而将闲置环境称为绿色环境。将绿环境部署新版本服务后,进行流量切换。一旦生产流量从蓝色完全转移到绿色,蓝色就可以在回滚或退出生产的情况下保持待机,也可以更新成为下次更新的模板。
ref:
-
红黑部署
与蓝绿部署类似,红黑发布也是通过两个集群完成软件版本的升级。
当前提供服务的所有机器都运行在红色集群 A 中,当需要发布新版本的时候,具体流程是这样的:
- 先在云上申请一个黑色集群 B,在 B 上部署新版本的服务;
- 等到 B 升级完成后,我们一次性地把负载均衡全部指向 B;
- 把 A 集群从负载均衡列表中删除,并释放集群 A 中所有机器。
这样就完成了一个版本的升级。
学海拾贝-20220221-20220227
内容目录
- docker run 覆盖原有entrypoint
- docker 拉取指定架构的镜像
- vim块模式进行批量操作
- nginx proxy_pass
- docker latest标签
- mac chrome强制刷新
- 命令行修改密钥密码
1. docker run 覆盖原有entrypoint
使用 --entrypoint
docker run --entrypoint <new command> [docker_image]
以命令行交互模式运行容器进行交互操作:
docker run -it --entrypoint /bin/bash [docker_image]
更多信息,比如对于 entrypoint 和 cmd 的区别等,可参考:
- https://docs.docker.com/engine/reference/run/#entrypoint-default-command-to-execute-at-runtime
- https://phoenixnap.com/kb/docker-run-override-entrypoint
- https://yeasy.gitbook.io/docker_practice/image/dockerfile/entrypoint
- https://www.bmc.com/blogs/docker-cmd-vs-entrypoint/
2. docker 拉取指定架构的镜像
- 容器技术、虚拟机技术、模拟环境,各项技术上运行的程序对宿主机架构、指令集、宿主机内核的依赖情况
虚拟机技术在宿主机上通过虚拟化技术模拟硬件设备,虚拟机运行在虚拟化层之上,仿佛自己运行在物理机上一般。每台虚拟机有自己的内核,有自己的操作系统在运行。
通过模拟技术可以通过软件模拟出与底层不同架构的硬件,实际上有点像是在做翻译,比如在x86平台模拟ARM平台环境,再在这个模拟环境中运行ARM架构操作系统的虚拟机。比如这篇文章介绍了如何通过Qemu来实现在x86平台模拟运行ARM系统。
ref:https://cloud.tencent.com/developer/article/1823083
容器本质上是有特殊限制的进程,依赖的是宿主机内核,宿主机操作系统。因此尽管容器技术可以做到一处打包处处运行的便捷性,但是需要确保运行的镜像指令集与宿主机操作系统一致。
因此我们需要使用与宿主机具有相同架构的镜像进行使用。
关于虚拟机技术和容器技术的演进、差别的更多信息可以在kubernetes in action查看学习。
- 多架构支持
docker镜像可以支持多架构,也就是说一个镜像可以有不同的架构、不同的操作系统的变体。当我们运行一个支持多架构的镜像时,docker会自动选择与宿主机的操作系统和架构契合的镜像变体。
ref:https://docs.docker.com/desktop/multi-arch/
- docker pull 命令行拉取指定架构
我们也可以通过--platform 参数指定镜像的系统和架构,或者通过指定镜像的sha256值(摘要)来使用指定的镜像。
方法一:使用--platform 参数:
docker pull --platform linux/arm64 alpine:latest
方法二:指定镜像的sha256值(摘要)
首先列出所有支持的架构,然后指定sha256值(摘要)进行拉取。例如:
# list all supported architectures (manifest):
$ docker manifest inspect ckulka/multi-arch-example
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 2200,
"digest": "sha256:6eaeab9bf8270ce32fc974c36a15d0bac4fb6f6cd11a0736137c4248091b3646",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 2413,
"digest": "sha256:f02e0fd2918a894ecd49d67b802c22082dc3c6424f6566e1753a83ba833b0993",
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "v5"
}
},
...
# pull by digest, e.g. arm arch (pulled on linux machine):
$ docker pull ckulka/multi-arch-example@sha256:f02e0fd2918a894ecd49d67b802c22082dc3c6424f6566e1753a83ba833b0993
ref:https://stackoverflow.com/questions/60114854/pull-docker-image-for-different-architecture/60116565
如何在nginx创建临时重定向和永久重定向
重定向的概念
http重定向是将一个域名或者地址重新指向另一个域名或地址的方式。重定向的方式有多种,每一种对客户端而言都有些不同之处。其中两种最常见的重定向方式是临时重定向和永久重定向。
临时重定向的返回码是 302。 临时重定向是用于一个url暂时需要通过一个临时站点进行服务的场景。当你的网站需要进行临时维护时,你可能就会希望在你进行维护期间,将访问重定向到另一个临时页码,在页面中提供临时服务或者通知用户网站正在进行维护,很快会恢复服务。
永久重定向的返回码是 301。这个返回码希望告诉浏览器,应该放弃访问当前的url,并不再尝试访问当前URL。这种方式适用于当你的站点进行了永久性的迁移的情况,比如进行了域名更换等。
你可以通过在nginx的配置中向server 配置块中添加如下内容来创建一个临时重定向:
rewrite^/oldlocation$http://www.newdomain.com/newlocation redirect;
类似地,可以添加如下内容来创建一个永久重定向:
rewrite^/oldlocation$http://www.newdomain.com/newlocation permanent;
就下来将会对nginx 中每种类型的重定向进行更加深入的解释,以及给出一些特别案例的用法。(待更新。。。。。)
ref: How To Create Temporary and Permanent Redirects with Nginx
jekyll post page 生成脚本
脚本功能:
- md 文件创建
- md 头内容生成
- 生成随机短地址作为permalink,以便为每个page实现固定地址
脚本内容:
#!/usr/bin/env bash
DIR="${0%/*}"
title=`echo $@ | sed 's/[ ][ ]*/-/g'`
post_date=`date +"%Y-%m-%d %T"`
post_name="`date "+%Y-%m-%d"`-${title}.markdown"
random_addr=`openssl rand -hex 8 | md5 | cut -c1-8`
cat > ${DIR}/../_posts/${post_name} << EOF
---
layout: post
title: "${title}"
description: ""
date: ${post_date} +0800
categories: default
permalink: /posts/${random_addr}/
tags: [writing]
---
EOF
使用方法:
./new_post.sh <the new page name>
containerd导入本地镜像的一个小坑
containerd 命令行工具为 ctr
本地镜像导入命令:
ctr image import <path/to/image/file>
注意:当tar包没有tag信息时,导入之后,无报错,errno 为0,但是 通过 ctr images ls 查看却没有相关的镜像。这种情况,需要添加 --digests=true 来导入:
ctr image import --digests=true <path/to/images/file>
jekyll静态blog部署 checklist
-
安装jekyll
1.1 安装ruby
为了避免版本冲突问题,使用rbenv进行安装(以ubuntu为例,参考https://gorails.com/setup/ubuntu/18.04)
-
安装rbenv
cd git clone https://github.com/rbenv/rbenv.git ~/.rbenv echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc echo 'eval "$(rbenv init -)"' >> ~/.bashrc exec $SHELL git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc exec $SHELL -
安装ruby
rbenv install 3.0.3 rbenv global 3.0.3检查安装是否符合预期
ruby -v -
安装 Bundler
gem install bundler
1.2 安装jekyll
gem install jekyll bundler -
-
创建blog project
方案一: 安装好ruby后,安装jekyll,并创建blog project:
gem install bundler jekyll jekyll new myblog方案二:直接选择自己喜欢的主题,从github将项目克隆到本地