BoyChai's Blog https://blog.boychai.xyz/ zh-CN BoyChai的博客,计算机网络爱好者,倾心于互联网发展 Tue, 16 May 2023 04:34:00 +0000 Tue, 16 May 2023 04:34:00 +0000 HELM-Kubernetes包管理工具(Chart包简单使用) https://blog.boychai.xyz/index.php/archives/57/ https://blog.boychai.xyz/index.php/archives/57/ Tue, 16 May 2023 04:34:00 +0000 BoyChai 目录结构

文档地址:https://helm.sh/zh/docs/topics/charts/

通过下面命令创建一个chart,指定chart名:mychart

[root@Kubernetes charts]# helm create mychart
Creating mychart
[root@Kubernetes charts]# tree mychart
mychart
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml

3 directories, 10 files
目录介绍
charts存放子chart的目录,目录里存放这个chart依赖的所有子chart
Chart.yaml保存chart的基本信息,包括名字、描述信息及版本等,这个变量文件都可以被template目录下文件所引用
templates模板文件目录,目录里面存放所有yaml模板文件,包含了所有部署应用的yaml文件
templates/deployment.yaml创建deployment对象的模板文件
templates/_helpers.tpl_放置模板助手的文件,可以在整个chart中重复使用,是放一些templates目录下这些yaml都有可能会用的一些模板
templates/hpa.yaml
templates/ingress.yaml
templates/NOTES.txt存放提示信息的文件,介绍chart帮助信息,helm install部署后展示给用户,如何使用chart等,是部署chart后给用户的提示信息
templates/serviceaccount.yaml
templates/service.yaml
templates/tests用于测试的文件,测试完部署完chart后,如web,做一个连接,看看是否部署成功
templates/tests/test-connection.yaml用于渲染模板的文件(变量文件,定义变量的值)定义templates目录下的yaml文件可能引用到的变量
values.yamlvalues.yaml用于存储templates目录中模板文件中用到变量的值,这些变量定义都是为了让templates目录下yaml引用

案例1

需求

编写一个chart,不引用内置对象的变量值(用HELM3发布创建一个ConfigMap,创建到K8s集群中,发布其他应用也一样,我们由浅入深进行学习)

创建实例

编写Chart:

[root@Kubernetes charts]# helm create myConfigMapChart
Creating myConfigMapChart
[root@Kubernetes charts]# cd myConfigMapChart/templates/
[root@Kubernetes templates]# rm -rf ./*
[root@Kubernetes templates]# vim configmap.yaml
# 文件内容如下
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-cm-chart
data:
  myValue: "Hello,World"

创建release实例:

[root@Kubernetes charts]# ls
mychart  myConfigMapChart  
[root@Kubernetes charts]# helm install mycm ./myConfigMapChart/
NAME: mycm
LAST DEPLOYED: Thu May 11 00:26:16 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

查看release实例:

[root@Kubernetes charts]# helm list
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
mycm    default         1               2023-05-11 00:26:16.392817959 +0800 CST deployed        myConfigMapChart-0.1.0  1.16.0  

查看release的详细信息:

[root@Kubernetes charts]# helm get manifest mycm
---
# Source: myConfigMapChart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-cm-chart
data:
  myValue: "Hello,World"

删除release实例:

[root@Kubernetes charts]# helm uninstall mycm
release "mycm" uninstalled
[root@Kubernetes charts]# helm list
NAME    NAMESPACE       REVISION        UPDATED STATUS  CHART   APP VERSION

案例2

需求

案例1只是简单的创建一个configmap实际和直接apply没啥区别,案例2将引入变量进行创建chart,把configmap的名称改为变量的方式进行创建。

创建实例

修改Chart:

[root@Kubernetes charts]# vim myConfigMapChart/templates/configmap.yaml 
[root@Kubernetes charts]# cat myConfigMapChart/templates/configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  # name: my-cm-chart
  name: {{ .Release.Name }}-configmap
data:
  # myValue: "Hello,World"
  myValue: {{ .Values.MY_VALUE }}
[root@Kubernetes charts]# > myConfigMapChart/values.yaml
[root@Kubernetes charts]# vim myConfigMapChart/values.yaml 
[root@Kubernetes charts]# cat !$
cat myConfigMapChart/values.yaml
MY_VALUE: "Hello,World"

创建实例:

[root@Kubernetes charts]# helm install mycm2 ./myConfigMapChart/
NAME: mycm2
LAST DEPLOYED: Thu May 11 00:49:06 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

查看实例:

[root@Kubernetes charts]# helm list 
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
mycm2   default         1               2023-05-11 00:49:06.855993522 +0800 CST deployed        myConfigMapChart-0.1.0  1.16.0
[root@Kubernetes charts]# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      77d
mycm2-configmap    1      87s

YAML解释:

apiVersion: v1
kind: ConfigMap
metadata:
  # name: my-cm-chart
  name: {{ .Release.Name }}-configmap
data:
  # myValue: "Hello,World"
  myValue: {{ .Values.MY_VALUE }}
  • {{ .Release.Name }}-configmap
    最前面的.从作用域最顶层命名空间开始,即:在顶层命名空间中开始寻找Release对象,再查找Name对象。这个就是通过内置对象获取内置对象的变量值(Release的名称)作为拼接成ConfigMap的名字。
  • {{ .Values.MY_VALUE }}
    这个是其他变量会去values.yaml文件中寻找对应的变量

引用内置对象或其他变量的好处:
如果metadata.name中色湖之的值就是一个固定值,这样的模板是无法在k8s中多次部署的,所以我们可以试着在每次安装chart时,都自动metadata.name的设置为release的名称,因为每次部署release的时候实例名称是不一样的,这样部署的时候里面的资源名也就可以作为一个分区,而可以进行重复部署。

测试渲染

HELM提供了一个用来渲染模板的命令,该命令可以将模板内容渲染出来,但是不会进行任何安装的操作。可以用该命令来测试模板渲染的内容是否正确。语法如下:

helm install [release实例名] chart目录 --debug --dry-run

例:

[root@Kubernetes charts]# helm install mycm3 ./myConfigMapChart/ --debug --dry-run
install.go:200: [debug] Original chart version: ""
install.go:217: [debug] CHART PATH: /root/charts/myConfigMapChart

NAME: mycm3
LAST DEPLOYED: Thu May 11 01:03:15 2023
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
{}

COMPUTED VALUES:
MY_VALUE: Hello,World

HOOKS:
MANIFEST:
---
# Source: myConfigMapChart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  # name: my-cm-chart
  name: mycm3-configmap 
data:
  # myValue: "Hello,World"
  myValue: Hello,World
[root@Kubernetes charts]# helm list
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
]]>
0 https://blog.boychai.xyz/index.php/archives/57/#comments https://blog.boychai.xyz/index.php/feed/
HELM-Kubernetes包管理工具(介绍与安装) https://blog.boychai.xyz/index.php/archives/56/ https://blog.boychai.xyz/index.php/archives/56/ Sat, 13 May 2023 01:27:00 +0000 BoyChai 传统部署方式

传统服务部署到K8s集群的流程:
拉取代码-----》打包编译-----》构建镜像-----》准备相关的yaml文件-----》kubectl apply进行部署

传统方式部署引发的问题:

  1. 随着引用的增多,需要维护大量的yaml文件
  2. 不能根据一套yaml文件来创建多个环境,需要手动进行修改。
    PS: 一般环境都分为dev、预生产、生产环境,部署完了dev这套环境,后面再部署预生产和生产环境,还需要复制出两套,并手动修改才行。

什么是HELM

Helm是K8s的包管理工具,可以方便地发现、共享和构建K8s应用
Helm是k8s的包管理器,相当于centos系统中的yum工具,可以将一个服务相关的所有资源信息整合到一个chart中,并且可以使用一套资源发布到多个环境中,可以将应用程序的所有资源和部署信息组合到单个部署包中。
就像Linux下的rpm包管理器,如yum/apt等,可以很方便的将之前打包好的yaml文件部署到k8s上。

HELM的组件

  1. Chart:就是helm的一个整合后的chart包,包含一个应用所有的K8s声明模板,类似于yum的rpm包或者apt的dpkg文件。helm将打包的应用程序部署到k8s并将它们构成chart。这些chart将所有预配置的应用程序资源以及所有版本都包含再一个已于管理的包中。
  2. HELM客户端:helm的客户端组件,负责和K8s apiserver通信
  3. Repository:用于发布和存储chart包的仓库,类似yum仓库和docker仓库。
  4. Release:用chart包部署的一个实例。通过chart在K8s中部署的应用都会产生一个唯一的Release,统一chart部署多次就会产生多个Release。

HELM2和HELM3

  1. helm3移除了Tiller组件 helm2中helm客户端和K8s通信时通过Tiller组件和K8s通信,helm3移除了Tiller组件,直接使用kubeconfig文件和K8s apiserver通信。
  2. 删除release命令变更
    helm delete release-name --purge --------》 helm uninstall release-name
  3. 查看charts信息命令变更
    helm inspect release-name -------》 helm show chart-name
  4. 拉取charts包命令变更
    helm fetch chart-name -------》 helm pull chart-name
  5. helm3中必须指定release名称,如果需要生成一个随机名称,需要加选项--generate-name,helm2中如果不指定release名称,可以自动生成一个随机名称
    helm install ./mychart --generate-name

    安装HELM

    相关连接:
    Github:https://github.com/helm/helm/releases
    官网:https://helm.sh/zh/docs/intro/install/

下载好对应的版本上传到服务器进行解压缩

[root@Kubernetes helm]# ls
helm-v3.11.3-linux-amd64.tar.gz
[root@Kubernetes helm]# tar xvf helm-v3.11.3-linux-amd64.tar.gz 
linux-amd64/
linux-amd64/LICENSE
linux-amd64/README.md
linux-amd64/helm

之后配置一下系统环境,让命令可以在系统中随机调用

[root@Kubernetes helm]# ls
helm-v3.11.3-linux-amd64.tar.gz  linux-amd64
[root@Kubernetes helm]# cd linux-amd64/
[root@Kubernetes linux-amd64]# pwd
/opt/helm/linux-amd64
[root@Kubernetes linux-amd64]# vim /etc/profile
#追加下面内容
export PATH=$PATH:/opt/helm/linux-amd64
[root@Kubernetes linux-amd64]# source /etc/profile

检查一下是否安装成功

[root@Kubernetes ~]# helm version
version.BuildInfo{Version:"v3.11.3", GitCommit:"323249351482b3bbfc9f5004f65d400aa70f9ae7", GitTreeState:"clean", GoVersion:"go1.20.3"}
]]>
0 https://blog.boychai.xyz/index.php/archives/56/#comments https://blog.boychai.xyz/index.php/feed/
[Go]gRPC-介绍 https://blog.boychai.xyz/index.php/archives/55/ https://blog.boychai.xyz/index.php/archives/55/ Tue, 09 May 2023 14:54:00 +0000 BoyChai gRPC是一款语言中立、平台中立、开源的远程过程调用系统,gRPC客户端和服务端可以在多种环境中运行和交互。,例如用java写一个服务端,可以用go语言写客户端调用。

数据在进行网络传输的时候,需要进行序列化,序列化协议有很多种,比如xml、json、protobuf等。

gRPC默认应用使用protocol buffers,这是google开源的一套成熟的结构数据序列化机制。

序列化: 将数据结构或对象转换成二进制串的过程。

反序列化: 将在虚拟化过程中所生产的二进制串转换成数据结构或对象的过程。

参考资料

]]>
0 https://blog.boychai.xyz/index.php/archives/55/#comments https://blog.boychai.xyz/index.php/feed/
[闲谈]吹爆Obsidian笔记 https://blog.boychai.xyz/index.php/archives/54/ https://blog.boychai.xyz/index.php/archives/54/ Fri, 05 May 2023 15:20:00 +0000 BoyChai 在学习过程中,我认为不做笔记就等于白学,对于我来说做笔记很重要,学习的知识越来越多,知识碎片的整理就越来越麻烦。

在高一的时候我一直是使用Windows自带的记事本做笔记,当时觉得挺舒服,但是学的东西越来越复杂就发现自带的记事本根本满足不了我的需求,笔记的重点、代码、图片在记事本中都展现不开。于是去尝试了一些新的记笔软件,Word、Markdown(Typora)、OneNote,Word和OneNote使用微软的office 365体验还不错但是需要付费使用,wps动不动弹一些没用的窗口我的强迫症受不了一点。当时为了用微软的Word和OneNote特意去买的office 365,在使用这俩记笔记的时候中间学习过程中接触到了Markdown于是就去尝试Typora了,发现Markdown是真的香,不管是体验还是写作的时候。唯一一点不好的是这玩意有学习成本,学个一俩小时就能使用,这点学习成本也无所谓了。

到了高二的这个阶段学习的东西越来越多,笔记文件的数量越来越多,只使用Typora来整理越来越麻烦,遇到问题寻找笔记的时候也比较麻烦,多设备同步只能通过网盘来做也很麻烦。于是就想着用一些云笔记的产品来解决上面的这些问题。尝试了语雀、印象、Notion这些软件甚至尝试了直接写CSDN这种博客、把笔记放到GitHub。尝试了这些之后说一下感受吧,把笔记放到CSDN和GitHub会更麻烦。语雀和印象还不错但是感觉界面太乱了我不是很喜欢,直到遇到了Notion这个,优点挺多但是缺点也不少。它不需要客户端就可以直接用,直接打开网页访问notion就可以直接用,多端数据都是同步的,提供笔记索引,还可以套用各种模板(套用模板之后就不仅仅可以几比几了),最重要的就是页面巨简洁,用起来很舒服。缺点就是官方不支持中文,之后笔记不提供大纲。找笔记是方便了,翻笔记就麻烦了。也能接受吧,就一直用的Notion。

直到昨天更新了一下Notion,他的侧栏展示笔记目录的地方原本是每个文件夹都是分层的自动会去缩进,更新了之后第三层目录他就不会去缩进了,展开一个分组的笔记他和上一级分组处在同一列缩进消失了,这让我的强迫症很难受。我去尝试搜索怎么解决这个问题,由于时刚更新的也没有太多的文章来写这个东西我也搜不到。但是在搜索的过程接触到了Obsidian这个软件,他有一个功能关系谱图直接吸引到我了,使着好奇的心态去尝试了一下发现这个软件真的是太完美了,界面简洁(个人感觉比notion都简洁),可以看笔记的大纲,可以做到多设备同步笔记(需要其他技术支持),优秀的插件社区(真就是啥都能干),通过插件社区不管是脑图、流程图、绘图、任务管理、日报周报、数据分析......都能干真找不出来他干不了的活,真是太强了。notion的缺点他都没有,除了同步需要其他的技术支持才能做到之外其他的相比notion都要更加优秀。Obsidian做多设备的数据同步官方的服务需要额外加钱,我这里直接不考虑,其他的办法就是通过社区插件,我是用Remotely save插件的WebDav来实现,后续不出意外我也会做相关的教程,数据都是放在自己服务器上面的也比较放心,自己可以根据实际情况进行备份,我的这个WebDav还提供给别人用于是就用rsync加了一个备份的服务,定时顶点备份到我的备份服务上。

不知道使用什么笔记软件软件的我这边建议直接去花半天学习一下Markdown的语法然后直接使用Obsidian,直接少走不少的弯路。强烈推荐使用Obsidian!!!

]]>
0 https://blog.boychai.xyz/index.php/archives/54/#comments https://blog.boychai.xyz/index.php/feed/
[Go]设计模式整理 https://blog.boychai.xyz/index.php/archives/53/ https://blog.boychai.xyz/index.php/archives/53/ Wed, 26 Apr 2023 13:51:14 +0000 BoyChai 0 https://blog.boychai.xyz/index.php/archives/53/#comments https://blog.boychai.xyz/index.php/feed/ [分区工具]Fdisk(MBR分区工具) https://blog.boychai.xyz/index.php/archives/52/ https://blog.boychai.xyz/index.php/archives/52/ Thu, 30 Mar 2023 12:22:00 +0000 BoyChai 概述

fdisk是一种用于管理磁盘分区的工具,常用于Linux和其他Unix-like操作系统中。它可以用于创建、删除和修改磁盘分区,并支持多种文件系统类型,例如FAT、ext2、ext3等。

fdisk还可以显示当前系统中所有磁盘的分区信息,包括磁盘标识符、分区类型、分区大小等。使用fdisk,用户可以轻松地管理磁盘空间,为不同的操作系统或应用程序分配不同的存储空间。

除此之外,fdisk还支持MBR(Master Boot Record)分区方案,它是一种常见的磁盘分区方案,能够在BIOS引导下启动操作系统。

MBR

MBR(Master Boot Record)分区是指使用MBR分区方案的磁盘分区方式。MBR分区方案是一种常见的分区方案,能够在BIOS引导下启动操作系统。MBR分区方案将磁盘的前512个字节(即MBR)用于存储分区表和引导程序。其中分区表记录了磁盘分区的信息,包括分区类型、分区起始位置、分区大小等。MBR分区方案最多支持4个主分区或3个主分区和1个扩展分区,扩展分区可以划分为多个逻辑分区。MBR分区方案已经存在了很长时间,但是它有一个缺点,即它只支持最大2TB的磁盘容量。如果需要使用更大的磁盘,就需要使用GPT(GUID Partition Table)分区方案。

环境

系统:Rocky Linux release 8.5

工具:fdisk from util-linux 2.32.1

硬盘:虚拟机添加了一块20G的硬盘

虚拟机属性

实践

主分区

[root@host ~]# lsblk -p                           // 通过lsblk来查看一下新增的硬盘位置(/dev/sdb)
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
/dev/sr0                 11:0    1 1024M  0 rom
[root@host ~]# fdisk /dev/sdb                    // 使用fdisk工具对/dev/sdb这块硬盘进行分区

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x178d8de5.

Command (m for help): n                         // 输入n进行新建分区操作
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p                            // p是创建主分区,e是创建逻辑分区
Partition number (1-4, default 1): 1             // 选择分区号,默认为1,这里可以改其他的(MBR分区最多有4个分区)
First sector (2048-41943039, default 2048):      // 起始扇区选择默认即可
Last sector, +sectors or +size{K,M,G,T,P} (2048-41943039, default 41943039): +5G    //设置分区大小我这里设置5G

Created a new partition 1 of type 'Linux' and of size 5 GiB.    //提示创建成功

Command (m for help): p                     // p查看分区表
Disk /dev/sdb: 20 GiB, 21474836480 bytes, 41943040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x178d8de5

Device     Boot Start      End  Sectors Size Id Type
/dev/sdb1        2048 10487807 10485760   5G 83 Linux                // 创建好的分区

Command (m for help): w                                        // 保存之前的分区操作
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
[root@host ~]# mkfs.xfs /dev/sdb1                          // 格式化创建好的分区
meta-data=/dev/sdb1              isize=512    agcount=4, agsize=327680 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=1310720, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@host ~]# mkdir /sdb1                           // 创建挂载位置
[root@host ~]# mount /dev/sdb1 /sdb1                  // 将格式化好的分区进行挂载
[root@host ~]# lsblk -p                                // 查看分区情况
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
└─/dev/sdb1               8:17   0    5G  0 part /sdb1          // 已经挂载好可以使用了
/dev/sr0                 11:0    1 1024M  0 rom

逻辑分区

[root@host ~]# fdisk /dev/sdb                            // 对/dev/sdb进行分区

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): n                            // 创建分区
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): e                           // 创建逻辑分区
Partition number (2-4, default 2):              // 分区号
First sector (10487808-41943039, default 10487808):       // 设置起始扇区选择默认即可
Last sector, +sectors or +size{K,M,G,T,P} (10487808-41943039, default 41943039):       // 设置大小,逻辑分区的默认大小是剩余全部存储空间,这里我选择默认。 

Created a new partition 2 of type 'Extended' and of size 15 GiB.  

Command (m for help): p                                 // 查看分区表
Disk /dev/sdb: 20 GiB, 21474836480 bytes, 41943040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x178d8de5

Device     Boot    Start      End  Sectors Size Id Type
/dev/sdb1           2048 10487807 10485760   5G 83 Linux
/dev/sdb2       10487808 41943039 31455232  15G  5 Extended               // 创建好了一个逻辑分区大小为15G

Command (m for help): w                      // 保存分区操作
The partition table has been altered.
Syncing disks.
[root@host ~]# lsblk -p
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb1               8:17   0    5G  0 part /sdb1
└─/dev/sdb2               8:18   0   15G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom

逻辑子分区

创建好逻辑分区之后就可以在逻辑分区里面创建无数个子分区,这样就逃离了MBR分区方式的分区限制。

[root@host ~]# fdisk /dev/sdb    // 对/dev/sdb进行分区

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): n         // 新建分区
All space for primary partitions is in use.
Adding logical partition 5      // 当创建好逻辑分区之后就会发现分区号会从5开始增加
First sector (10489856-41943039, default 10489856):             // 磁盘起始位置,默认即可
Last sector, +sectors or +size{K,M,G,T,P} (10489856-41943039, default 41943039): +1G     //设置大小

Created a new partition 5 of type 'Linux' and of size 1 GiB.

Command (m for help): n                 // 继续创建
All space for primary partitions is in use.
Adding logical partition 6  
First sector (12589056-41943039, default 12589056): 
Last sector, +sectors or +size{K,M,G,T,P} (12589056-41943039, default 41943039): +1G

Created a new partition 6 of type 'Linux' and of size 1 GiB.

Command (m for help): n            // 继续创建
All space for primary partitions is in use.
Adding logical partition 7
First sector (14688256-41943039, default 14688256): 
Last sector, +sectors or +size{K,M,G,T,P} (14688256-41943039, default 41943039): +1G

Created a new partition 7 of type 'Linux' and of size 1 GiB.

Command (m for help): w              // 保存
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
[root@host ~]# lsblk -p                  // 查看分区表
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb1               8:17   0    5G  0 part /sdb1
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom

这里会发现sdb磁盘一共创建了7个分区。

删除分区

以sdb1为例,sdb1这个分区已经挂载到了/sdb1目录已经在使用了,在删除分区前需要取消挂载。具体操作方法如下

[root@host ~]# lsblk -p                                      // 查看分区状态   
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb1               8:17   0    5G  0 part /sdb1         // 发现/dev/sdb1已经挂载到/sdb1目录下
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom  
[root@host ~]# umount /sdb1                                 // 取消挂载
[root@host ~]# lsblk -p                                              
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb1               8:17   0    5G  0 part            // 已经取消挂载了
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom  
[root@host ~]# fdisk /dev/sdb

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): d                                // d(delete)删除分区
Partition number (1,2,5-7, default 7): 1               // 删除分区号,这里选择1

Partition 1 has been deleted.

Command (m for help): w                                // 保存位置
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

[root@host ~]# lsblk -p                          // 查看磁盘状态
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk      // 发现sdb1已经消失         
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom

使用分区

格式化分区

创建好分区之后需要格式化之后才可以挂载使用,格式化需要使用mkfs工具,这里不多讲。关于格式化的格式可以使用mkfs.来查看

[root@host ~]# mkfs.
mkfs.cramfs  mkfs.ext2    mkfs.ext3    mkfs.ext4    mkfs.minix   mkfs.xfs

这里使用xfs来格式化创建的分区(逻辑分区只能格式化子分区不能直接格式化逻辑分区)。

[root@host ~]# lsblk -p                          // 查看分区状态
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom  
[root@host ~]# mkfs.xfs /dev/sdb5              // 使用xfs类型格式化sdb5
meta-data=/dev/sdb5              isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@host ~]# mkfs.xfs /dev/sdb6               // 使用xfs类型格式化sdb6
meta-data=/dev/sdb6              isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@host ~]# mkfs.xfs /dev/sdb7              // 使用xfs类型格式化sdb7                 
meta-data=/dev/sdb7              isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@host ~]# lsblk -p                        // 查看分区状态
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part 
├─/dev/sdb6               8:22   0    1G  0 part 
└─/dev/sdb7               8:23   0    1G  0 part 
/dev/sr0                 11:0    1 1024M  0 rom

挂载分区

当格式化分区之后可以通过mount来进行挂载,挂载好的分区就可以使用了。

[root@host ~]# mkdir -p /disk/sdb{5..7}     // 创建挂载目录
[root@host ~]# mount /dev/sdb5 /disk/sdb5   // 挂载sdb5
[root@host ~]# mount /dev/sdb6 /disk/sdb6   // 挂载sdb6
[root@host ~]# mount /dev/sdb7 /disk/sdb7   // 挂载sdb7
[root@host ~]# lsblk -p          // 查看分区状态
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
/dev/sda                  8:0    0   20G  0 disk 
├─/dev/sda1               8:1    0    1G  0 part /boot
└─/dev/sda2               8:2    0   19G  0 part 
  ├─/dev/mapper/rl-root 253:0    0   17G  0 lvm  /
  └─/dev/mapper/rl-swap 253:1    0    2G  0 lvm  [SWAP]
/dev/sdb                  8:16   0   20G  0 disk 
├─/dev/sdb2               8:18   0    1K  0 part 
├─/dev/sdb5               8:21   0    1G  0 part /disk/sdb5
├─/dev/sdb6               8:22   0    1G  0 part /disk/sdb6
└─/dev/sdb7               8:23   0    1G  0 part /disk/sdb7
/dev/sr0                 11:0    1 1024M  0 rom
]]>
0 https://blog.boychai.xyz/index.php/archives/52/#comments https://blog.boychai.xyz/index.php/feed/
[折腾]绕过校园网WEB认证解决方案 https://blog.boychai.xyz/index.php/archives/50/ https://blog.boychai.xyz/index.php/archives/50/ Fri, 17 Mar 2023 04:05:00 +0000 BoyChai 原理分析

先说一下原理,连接上校园网设备之后只要不进行认证,大部分的流量只要是经过校园网设备都会拦截之后给客户端重定向到一个认证页面(本文封面),让其进行认证。不进行认证的小部分流量比如说是dhcp、dns都不会进行拦截重定向,dhcp要进行分配ip,刚连接的设备需要通过这个dhcp才可以拿到自己的ip地址,dns是域名解析服务也不会拦截。他们的端口分别是DHCP(UDP/67服务端、UDP/68客户端)、DNS(UDP/53),目前只发现了这两个服务的端口是不被拦截的。我们可以通过这些端口来绕过流量的拦截。例如使用虚拟专用网络、虚拟隧道等技术来实现绕过拦截。

干!!!

软件介绍

本文服务端使用V2ray软件进行绕过,项目地址以及文档地址如下:

项目地址:https://github.com/v2fly/v2ray-core

文档地址:https://www.v2fly.org/

客户端为了方便采用V2rayN和服务端进行链接,项目地址如下:

项目地址:https://github.com/2dust/v2rayN

部署搭建

我们在服务端部署一下v2ray,如何去下载这里不多讲解,部署方式如下

# 下载
[root@dj1 work]# wget https://github.com/v2fly/v2ray-core/releases/download/v5.3.0/v2ray-linux-64.zip
100%[==============================================================================================>] 11,706,579  3.22MB/s   in 3.5s
# 解压
[root@dj1 work]# unzip v2ray-linux-64.zip 
Archive:  v2ray-linux-64.zip
  inflating: config.json             
  inflating: geosite.dat             
  inflating: geoip-only-cn-private.dat  
   creating: systemd/
   creating: systemd/system/
  inflating: systemd/system/v2ray.service  
  inflating: systemd/system/v2ray@.service  
  inflating: vpoint_socks_vmess.json  
  inflating: geoip.dat               
  inflating: v2ray                   
  inflating: vpoint_vmess_freedom.json
# 配置
[root@dj1 work]# mv config.json config.json.bak
[root@dj1 work]# vim config.json
# 配置如下
{
    "inbounds": [
        {
            "port": 53, // 服务器监听端口
            "protocol": "vmess",
            "settings": {
                "clients": [
                    {
                        "id": "0297a6ed-9152-4ad1-a80a-b248a9c4d3ad"
                    }
                ]
            },
            "streamSettings": {
                "network": "mkcp", //此处的 mkcp 也可写成 kcp,两种写法是起同样的效果
                "kcpSettings": {
                    "uplinkCapacity": 5,
                    "downlinkCapacity": 100,
                    "congestion": true,
                    "header": {
                        "type": "none"
                    }
                }
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom"
        }
    ]
}
# 运行v2ray,这里采用screen工具放在后台运行.
[root@dj1 work]# screen -S V2
[root@dj1 work]# ./v2ray run
V2Ray 5.3.0 (V2Fly, a community-driven edition of V2Ray.) Custom (go1.20 linux/amd64)
A unified platform for anti-censorship.
2023/03/17 13:02:30 Using default config:  /root/work/config.json
2023/03/17 13:02:30 [Warning] V2Ray 5.3.0 started
# ctrl + a + d
[detached from 81853.V2]

这里就配置好了,我这里用的是V2ray的VMess协议端口用的是dns的53端口关于VMess的配置文档可以在V2ray的文档中找到这里不多做解释,clients中的id算是链接的token,需要记住,这个id不能随便写,需要通过特殊的算法生成可以直接使用v2rayn来生成 这里也多做讲解。

客户端链接

下载方式这里不细说了,去github中的版本列表中都有。下载好之后打开软件,在左上角服务器-》添加VMess服务器中配置,配置如下

V2rayN配置

地址填写自己的服务器地址,用户id这里可以直接生成,需要和服务端一样。协议选择kcp即可。

配置好之后"右键左下角的v2ray的图标选择路由-》全局"。之后再设置一下代理"右键右下角图标-》系统代理-》自动配置系统代理"。

连接上校园网之后就会发现不会再跳转到认证页面。实际上网的速度和服务器的网络规格挂钩。不是用校园网的时候建议关闭代理不然数据会一直走代理会出现限速的现象可以通过"右键右下角图标-》系统代理-》清除系统代理"来解决。

]]>
1 https://blog.boychai.xyz/index.php/archives/50/#comments https://blog.boychai.xyz/index.php/feed/
[Go]GIN框架-请求参数 https://blog.boychai.xyz/index.php/archives/49/ https://blog.boychai.xyz/index.php/archives/49/ Fri, 27 Jan 2023 14:53:00 +0000 BoyChai Get请求参数

普通参数

请求

http://localhost:8080/query?id=123&name=user

接收

第一种方式

r.GET("/query", func(context *gin.Context) {
    // 获取传参
    id := context.Query("id")
    name := context.Query("name")
    // 设置某个参数的默认值
    sex := context.DefaultQuery("sex", "unknown")
    // 检查address值是否传入
    address, ok := context.GetQuery("address")
    context.JSON(http.StatusOK, gin.H{
        "id":         id,
        "name":       name,
        "sex":        sex,
        "address":    address,
        "address-ok": ok,
    })
})

第二种方式

提前定义结构体

// 定义结构体需要表示form名称,如果不标识则传参时key必须和结构体的对应的值一样比如Id就必须传入Id,id是不行的
type User struct {
    Id      int64  `form:"id"'`
    Name    string `form:"name"`
    Sex     string `form:"sex"`
    // binding是指传参必须拥有此参数
    Address string `form:"address" binding:"required"'`
}
r.GET("/query", func(context *gin.Context) {
    var user User
    err := context.BindQuery(&user)
    if err != nil {
        log.Println(err)
    }
    context.JSON(http.StatusOK, gin.H{
        "id":      user.Id,
        "name":    user.Name,
        "sex":     user.Sex,
        "address": user.Address,
    })
})

第三种方式

提前定义结构体

// 定义结构体需要表示form名称,如果不标识则传参时key必须和结构体的对应的值一样比如Id就必须传入Id,id是不行的
type User struct {
    Id      int64  `form:"id"'`
    Name    string `form:"name"`
    Sex     string `form:"sex"`
    // binding是指传参必须拥有此参数
    Address string `form:"address" binding:"required"'`
}
r.GET("/query", func(context *gin.Context) {
    var user User
    err := context.ShouldBindQuery(&user)
    if err != nil {
        log.Println(err)
    }
    context.JSON(http.StatusOK, gin.H{
        "id":      user.Id,
        "name":    user.Name,
        "sex":     user.Sex,
        "address": user.Address,
    })
})

返回值

第一种方式

状态码200

{
    "address": "",
    "address-ok": false,
    "id": "123",
    "name": "user",
    "sex": "unknown"
}

第二种方式

状态码400

后台会报:

2023/01/27 22:18:55 Key: 'User.Address' Error:Field validation for 'Address' failed on the 'required' tag
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 200
{
    "address": "",
    "id": 123,
    "name": "user",
    "sex": ""
}

第三种方式

状态码200

后台会报:

2023/01/27 22:19:33 Key: 'User.Address' Error:Field validation for 'Address' failed on the 'required' tag
{
    "address": "",
    "id": 123,
    "name": "user",
    "sex": ""
}

数组参数

请求

http://localhost:8080/query?address=beijing&address=qingdao

接收

第一种方式

r.GET("/query", func(context *gin.Context) {
    address := context.QueryArray("address")
    context.JSON(http.StatusOK, address)
})

第二种方式

提前定义结构体

type Address struct {
    Address []string `form:"address"`
}
r.GET("/query", func(context *gin.Context) {
    var address Address
    err := context.BindQuery(&address)
    if err != nil {
        log.Println(err)
    }
    context.JSON(http.StatusOK, address)
})

第三种方式

提前定义结构体

type Address struct {
    Address []string `form:"address"`
}
r.GET("/query", func(context *gin.Context) {
    var address Address
    err := context.ShouldBindQuery(&address)
    if err != nil {
        log.Println(err)
    }
    context.JSON(http.StatusOK, address)
})

返回值

第一种方式

状态码200

[
    "beijing",
    "qingdao"
]

第二种方式

状态码200

{
    "Address": [
        "beijing",
        "qingdao"
    ]
}

第三种方式

状态码200

{
    "Address": [
        "beijing",
        "qingdao"
    ]
}

map参数

请求

http://localhost:8080/query?addressMap[home]=beijing&addressMap[company]=qingdao

接收

r.GET("/query", func(context *gin.Context) {
    addressMap := context.QueryMap("addressMap")
    context.JSON(http.StatusOK, addressMap)
})

返回值

状态码200

{
    "company": "qingdao",
    "home": "beijing"
}

POST请求

post请求一般是表单参数和json参数

表单请求

请求

http://localhost:8080/query

form-data

id=123
name=user
address=beijing
address=qingdao
addressMap[home]=beijing
addressMap[company]=qingdao

接收

r.POST("/query", func(context *gin.Context) {
    id := context.PostForm("id")
    name := context.PostForm("name")
    address := context.PostFormArray("address")
    addressMap := context.PostFormMap("addressMap")
    context.JSON(http.StatusOK, gin.H{
        "id":         id,
        "name":       name,
        "address":    address,
        "addressMap": addressMap,
    })
})

PS:

接收也可以使用func (c *gin.Context) ShouldBind(obj any) error {}函数进行接收和上面get讲的差不多一样这里不再讲解

返回值

状态码200

{
    "address": [
        "beijing",
        "qingdao"
    ],
    "addressMap": {
        "company": "qingdao",
        "home": "beijing"
    },
    "id": "123",
    "name": "user"
}

JSON请求

请求

http://localhost:8080/query

raw or json

{
    "address": [
        "beijing",
        "qingdao"
    ],
    "addressMap": {
        "company": "qingdao",
        "home": "beijing"
    },
    "id": 123,
    "name": "user",
    "sex":"Male"
}

接收

定义结构体,接收json数据结构体不需要加form表示,接收时会自动把Name转换为name进行匹配接收或者添加json的标识进行匹配

type User struct {
    Id         int64              `json:"id"`
    Name       string            
    Sex        string            
    Address    []string          
    AddressMap map[string]string 
}
    r.POST("/query", func(context *gin.Context) {
        var user User
        err := context.ShouldBindJSON(&user)
        if err != nil {
            log.Println(err)
        }
        context.JSON(http.StatusOK, user)
    })

返回值

状态码200

{
    "Id": 123,
    "Name": "user",
    "Sex": "Male",
    "Address": [
        "beijing",
        "qingdao"
    ],
    "AddressMap": {
        "company": "qingdao",
        "home": "beijing"
    }
}

文件请求

代码实现

r.POST("/save", func(context *gin.Context) {
   form, err := context.MultipartForm()
   if err != nil {
      log.Println(err)
   }
   for _, fileArray := range form.File {
      for _, v := range fileArray {
         context.SaveUploadedFile(v, "./"+v.Filename)
      }
   }
   context.JSON(http.StatusOK, form.Value)
})

context.MultipartForm()返回的from里面有俩值,一个是文件数组,还有一个是提交的参数。上传好的文件会被context.SaveUploadedFile保存到本地

]]>
0 https://blog.boychai.xyz/index.php/archives/49/#comments https://blog.boychai.xyz/index.php/feed/
[Go]GIN框架-路由 https://blog.boychai.xyz/index.php/archives/48/ https://blog.boychai.xyz/index.php/archives/48/ Thu, 19 Jan 2023 14:55:00 +0000 BoyChai 路由概述

路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 函数(GET、POST 等)组成的,涉及到应用如何响应客户端对某个网站节点的访问。

RESTful API

RESTful API 是目前比较成熟的一套互联网应用程序的 API 设计理论,所以我们设计我们的路由的时候建议参考 RESTful API 指南。

在 RESTful 架构中,每个网址代表一种资源,不同的请求方式表示执行不同的操作:

请求方式操作
GET(SELECT)从服务器中获取资源
POST(CREATE)在服务器中创建资源
PUT(UPDATE)在服务器中更新更改资源
DELETE(DELETE)在服务器中删除资源

创建路由

GET

// GET
r.GET("/GET", func(c *gin.Context) {
    c.String(http.StatusOK, "GET")
})

POST

// POST
r.POST("/POST", func(c *gin.Context) {
    c.String(http.StatusOK, "POST")
})

PUT

// PUT
r.PUT("/PUT", func(c *gin.Context) {
    c.String(http.StatusOK,"PUT")
})

DELETE

// DELETE
r.DELETE("/DELETE", func(c *gin.Context) {
    c.String(http.StatusOK, "DELETE")
})

其他创建方法

所有类型

如果同一个地址想要所有类型的请求都支持使用那么可以通过下面代码进行创建

// 接收所有类型请求
r.Any("/Any", func(c *gin.Context) {
    c.String(http.StatusOK, "Any")
})

两个或多个

// 先创建一个方法
func requestReturn(c *gin.Context) {
    c.String(http.StatusOK, "OTHER")
}
// 在创建请求URL
r.GET("/OTHER", requestReturn)
r.POST("/OTHER", requestReturn)

URI

静态URI

r.GET("/user/find", func(c *gin.Context) {
    c.String(http.StatusOK, "any")
})

路径参数

r.GET("/user/find/:id", func(c *gin.Context) {
    c.String(http.StatusOK, c.Param("id"))
})

模糊参数

// 使用path来接收值
r.GET("/user/*path", func(c *gin.Context) {
    c.String(http.StatusOK, c.Param("path"))
})

路由分组

在实际开发中,路由可能会有很多的版本,为了方便开发管理可以使用以下方法进行分组创建

// 路由分组
v1 := r.Group("v1")
v2 := r.Group("v2")
v1.GET("/user/find", func(c *gin.Context) {
    c.String(http.StatusOK, "/v1/user/find")
})
v2.GET("/user/find", func(c *gin.Context) {
    c.String(http.StatusOK, "/v2/user/find")
})
]]>
0 https://blog.boychai.xyz/index.php/archives/48/#comments https://blog.boychai.xyz/index.php/feed/
Containerd-容器管理 https://blog.boychai.xyz/index.php/archives/47/ https://blog.boychai.xyz/index.php/archives/47/ Thu, 12 Jan 2023 14:30:00 +0000 BoyChai Containerd概述

什么是Containerd

Containerd是一个行业标准的容器运行时,强调简单性、健壮性和可移植性。它可以作为Linux和Windows的守护进程使用,它可以管理其主机系统的完整容器生命周期:映像传输和存储、容器执行和监督、低级存储和网络附件等。

Docker和Containerd的关系

最开始ContainerdDocker的一部分,但是Docker的公司把Containerd剥离出来并捐赠给了一个开源社区(CNCF)独发展和运营。阿里云,AWS, GoogleIBMMicrosoft将参与到Containerd的开发中。

为什么要学习Containerd

kubernetes在1.5版本就发布了CRI(Container Runtime Interface)容器运行时接口,但是Docker是不符合这个标准的,Docker在当时又占据了大部分市场直接弃用Docker是不可能的,所以当时kubernetes单独维护了一个适配器(dockershim)单独给Docker用。

Docker的功能有很多,实际kubernetes用到的功能只是一小部分,而那些用不到的功能半身就可能带来安全隐患。

在1.20版本就发消息打算弃用Docker不再默认支持Docker当容器运行时。

在1.24版本正式弃用(移除dockershim)。在1.24之后的版本如果还想使用Docker作为底层的容器管理工具则需要单独安装dockershim

Containerd是支持CRI标准的,所以自然也就将容器运行时切换到Containerd上面了。

安装Containerd

YUM

直接使用docker的镜像源安装即可。

[root@host ~]# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
Adding repo from: https://download.docker.com/linux/centos/docker-ce.repo
[root@host ~]# yum -y install containerd.io 
......
[root@host ~]# rpm -qa containerd.io
containerd.io-1.6.15-3.1.el8.x86_64

使用下面命令设置开机自启并启动containerd

systemctl enable --now containerd

二进制

安装包

Containerd有两种安装包,区别如下

  • 第一种是containerd-xxx,这种包用于单机测试没问题,不包含runC,需要提前安装。
  • 第二种是cri-containerd-cni-xxxx,包含runc和k8s里的所需的相关文件。k8s集群里面需要用到此包。虽然包含runC,但是依赖系统中的seccomp(安全计算模式,用来限制系统资源的模式)

本文采用第二种包进行安装。

获取安装包

下载地址:Github

本文采用的版本是cri-containerd-cni-1.6.15-linux-amd64.tar.gz

下载好上传到服务器里面即可

[root@host ~]# mkdir containerd
[root@host ~]# mv cri-containerd-cni-1.6.15-linux-amd64.tar.gz containerd/
[root@host ~]# cd containerd
[root@host containerd]# tar xvf cri-containerd-cni-1.6.15-linux-amd64.tar.gz 
[root@host containerd]# ls
cri-containerd-cni-1.6.15-linux-amd64.tar.gz  etc  opt  usr

手动安装

[root@host containerd]# cp ./etc/systemd/system/containerd.service /etc/systemd/system/
[root@host containerd]# cp usr/local/sbin/runc /usr/sbin/
[root@host containerd]# cp usr/local/bin/ctr /usr/bin/
[root@host containerd]# cp ./usr/local/bin/containerd /usr/local/bin/
[root@host containerd]# mkdir /etc/containerd
[root@host containerd]# containerd config default > /etc/containerd/config.toml

修改配置

[root@host containerd]# cat /etc/containerd/config.toml |grep sandbox
    sandbox_image = "registry.k8s.io/pause:3.6"

这个参数是指向了一个镜像地址,这个地址在国内是被墙的,通过下面命令替换,下面的地址是我在dockerhub上面做的副本。

[root@host containerd]# sed -i 's/registry.k8s.io\/pause:3.6/docker.io\/boychai\/pause:3.6/g' /etc/containerd/config.toml 
[root@test containerd]# cat /etc/containerd/config.toml |grep sandbox_image
    sandbox_image = "docker.io/boychai/pause:3.6"

启动服务

[root@host containerd]# systemctl enable --now containerd
Created symlink /etc/systemd/system/multi-user.target.wants/containerd.service → /etc/systemd/system/containerd.service.
[root@host containerd]# ctr version
Client:
  Version:  v1.6.15
  Revision: 5b842e528e99d4d4c1686467debf2bd4b88ecd86
  Go version: go1.18.9

Server:
  Version:  v1.6.15
  Revision: 5b842e528e99d4d4c1686467debf2bd4b88ecd86
  UUID: ebf1fe8b-37f7-4d94-8277-788e9f2c2a17
[root@test containerd]# runc -v
runc version 1.1.4
commit: v1.1.4-0-g5fd4c4d1
spec: 1.0.2-dev
go: go1.18.9
libseccomp: 2.5.1

镜像管理

帮助信息

[root@host ~]# ctr images -h
NAME:
   ctr images - manage images

USAGE:
   ctr images command [command options] [arguments...]

COMMANDS:
   check                    check existing images to ensure all content is available locally
   export                   export images
   import                   import images
   list, ls                 list images known to containerd
   mount                    mount an image to a target path
   unmount                  unmount the image from the target
   pull                     pull an image from a remote
   push                     push an image to a remote
   delete, del, remove, rm  remove one or more images by reference
   tag                      tag an image
   label                    set and clear labels for an image
   convert                  convert an image

OPTIONS:
   --help, -h  show help
命令概述
check检查镜像
export导出镜像
import导入镜像
list,ls列出镜像
mount挂载镜像
unmount卸载镜像
pull下载镜像
push推送镜像
delete,del,remove,rm删除镜像
tag修改标记
label修改标签
convert转换镜像

images可以使用简写 例如列出帮助信息"ctr i -h"

下载镜像

containerd支持OCI标准的镜像,所以可以用dockerhub中的镜像或者dockerfile构建的镜像。

ctr i pull 镜像名称

[root@host ~]# ctr images pull docker.io/library/nginx:alpine
docker.io/library/nginx:alpine:                                                   resolved       |++++++++++++++++++++++++++++++++++++++| 
index-sha256:659610aadb34b7967dea7686926fdcf08d588a71c5121edb094ce0e4cdbc45e6:    exists         |++++++++++++++++++++++++++++++++++++++| 
manifest-sha256:c1b9fe3c0c015486cf1e4a0ecabe78d05864475e279638e9713eb55f013f907f: exists         |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:c7a81ce22aacea2d1c67cfd6d3c335e4e14256b4ffb80bc052c3977193ba59ba:    done           |++++++++++++++++++++++++++++++++++++++| 
config-sha256:c433c51bbd66153269da1c592105c9c19bf353e9d7c3d1225ae2bbbeb888cc16:   exists         |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:8921db27df2831fa6eaa85321205a2470c669b855f3ec95d5a3c2b46de0442c9:    done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:83e90619bc2e4993eafde3a1f5caf5172010f30ba87bbc5af3d06ed5ed93a9e9:    done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:d52adec6f48bc3fe2c544a2003a277d91d194b4589bb88d47f4cfa72eb16015d:    exists         |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:10eb2ce358fad29dd5edb0d9faa50ff455c915138fdba94ffe9dd88dbe855fbe:    exists         |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:a1be370d6a525bc0ae6cf9840a642705ae1b163baad16647fd44543102c08581:    exists         |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:689b9959905b6f507f527ce377d7c742a553d2cda8d3529c3915fb4a95ad45bf:    exists         |++++++++++++++++++++++++++++++++++++++| 
elapsed: 11.2s                                                                    total:  15.7 M (1.4 MiB/s)                                       
unpacking linux/amd64 sha256:659610aadb34b7967dea7686926fdcf08d588a71c5121edb094ce0e4cdbc45e6...
done: 709.697156ms

查看镜像

crt images <ls|list>

[root@host ~]# ctr images ls
REF                            TYPE                                                      DIGEST                                                                  SIZE     PLATFORMS                                                                                LABELS 
docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:659610aadb34b7967dea7686926fdcf08d588a71c5121edb094ce0e4cdbc45e6 15.9 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -

镜像挂载

查看镜像的文件系统

crt images mount 镜像名称 本地目录

[root@host ~]# mkdir /mnt/nginx-alpine
[root@host ~]# ctr images mount docker.io/library/nginx:alpine /mnt/nginx-alpine/
sha256:a71c46316a83c0ac8c2122376a89b305936df99fa354c265f5ad2c1825e94167
/mnt/nginx-alpine/
[root@host ~]# cd /mnt/nginx-alpine/
[root@host nginx-alpine]# ls
bin  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

镜像卸载

卸载已经挂载到本地的镜像文件系统

crt images unmount 本地目录

[root@host ~]# ctr images unmount /mnt/nginx-alpine/
/mnt/nginx-alpine/
[root@host ~]# ls /mnt/nginx-alpine/

镜像导出

ctr images export --platform 平台 导出的文件名称 镜像名称

[root@host ~]# ctr images export --platform linux/amd64 nginx.tar docker.io/library/nginx:alpine
[root@host ~]# ls
anaconda-ks.cfg  containerd  nginx.tar

镜像删除

ctr images delete|del|remove|rm 镜像名称

[root@host ~]# ctr images del docker.io/library/nginx:alpine
docker.io/library/nginx:alpine
[root@host ~]# ctr images ls
REF TYPE DIGEST SIZE PLATFORMS LABELS

镜像导入

ctr images import 镜像文件名称

[root@host ~]# ctr images import  nginx.tar 
unpacking docker.io/library/nginx:alpine (sha256:659610aadb34b7967dea7686926fdcf08d588a71c5121edb094ce0e4cdbc45e6)...done
[root@host ~]# ctr images ls
REF                            TYPE                                                      DIGEST                                                                  SIZE     PLATFORMS                                                                                LABELS 
docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:659610aadb34b7967dea7686926fdcf08d588a71c5121edb094ce0e4cdbc45e6 15.9 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -  

镜像名称

更改某个镜像的名称

ctr images tag 原镜像 新镜像名

[root@host ~]# ctr images ls
REF                            TYPE                                                      DIGEST                                                                  SIZE     PLATFORMS                                                                                LABELS 
docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:659610aadb34b7967dea7686926fdcf08d588a71c5121edb094ce0e4cdbc45e6 15.9 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -      
[root@host ~]# ctr images ls
REF                            TYPE                                                      DIGEST                                                                  SIZE     PLATFORMS                                                                                LABELS 
docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:659610aadb34b7967dea7686926fdcf08d588a71c5121edb094ce0e4cdbc45e6 15.9 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -      
[root@host ~]# ctr images tag docker.io/library/nginx:alpine nginx:alpine
nginx:alpine
[root@host ~]# ctr images ls
REF                            TYPE                                                      DIGEST                                                                  SIZE     PLATFORMS                                                                                LABELS 
docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:659610aadb34b7967dea7686926fdcf08d588a71c5121edb094ce0e4cdbc45e6 15.9 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -      
nginx:alpine                   application/vnd.docker.distribution.manifest.list.v2+json sha256:659610aadb34b7967dea7686926fdcf08d588a71c5121edb094ce0e4cdbc45e6 15.9 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -  

容器管理

]]>
0 https://blog.boychai.xyz/index.php/archives/47/#comments https://blog.boychai.xyz/index.php/feed/