Linux 原生

性能检查工具

开机自启动指令

关闭/开启自动更新

服务器文件夹共享/远程文件夹

# 挂载
sudo mount -t nfs  10.xxx.xxx.xxx:/path-to-share /path-to-mount
# 取消挂载
sudo unmount.nfs /path-to-mount
  • 本机:文件链接

tee 命令

磁盘容量分配扩容

  • 直接根据参考文献的方法修改即可获得满容量的 Ubuntu
  • 指令:
sudo lvextend -L +100G /dev/mapper/ubuntu--vg-ubuntu--lv
sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv

全局搜索文件或文件夹

  • 参考文献:在 ubuntu 中搜索文件或文件夹的方法_ubuntu find 文件夹_-牧野-的博客-CSDN 博客
  • whereis+ 文件名: 用于程序名的搜索,搜索结果只限于二进制文件(参数-b)、man 说明文件(参数-m)和源代码文件(参数-s),如果省略参数,则返回所有信息。
  • find / -name + 文件名: find 是在指定的目录下遍历查找,如果目录使用 / 则表示在所有目录下查找,find 方式查找文件消耗资源比较大,速度也慢一点。
  • locate+ 文件名: linux 会把系统内所有的文件都记录在一个数据库文件中,使用 locate+ 文件名的方法会在 linux 系统维护的这个数据库中去查找目标,相比 find 命令去遍历磁盘查找的方式,效率会高很多,比较推荐使用这种方法。但有一个问题是数据库文件不是实时更新的,一般会每周更新一次,所以使用 locate 命令查找到的结果不一定是准确的。当然可以在使用 locate 之前通过 updatedb 命令更新一次数据库,保证结果的性。
  • which+ 可执行文件名:which 的作用是在 PATH 变量指定的路径中,搜索某个系统命令的位置,并且返回第一个搜索结果。使用 which 命令,就可以看到某个系统命令是否存在,以及执行的到底是哪一个位置的命令。which 指令会在环境变量 $PATH 设置的目录里查找符合条件的文件,所以基本的功能是寻找可执行文件。

###

###

wait 指令

  • wait [作业指示或进程号]
    • 1.等待作业号或者进程号制定的进程退出,返回最后一个作业或进程的退出状态状态。如果没有制定参数,则等待所有子进程的退出,其退出状态为 0.
    • 2.如果是 shell 中等待使用 wait,则不会等待调用函数中子任务。在函数中使用 wait,则只等待函数中启动的后台子任务。
    • 3.在 shell 中使用 wait 命令,相当于高级语言里的多线程同步。

grep 和 awk 指令用于提取 csv 中的行

  • 这段 Shell 脚本的主要作用是循环处理一组客户端(max_clients 个客户端),对于每个客户端,它执行以下操作:

    • 使用 grep 命令查找匹配客户端 ID 的行,这些行位于 ${log_path}/frame_path.csv 文件中。^${client_id} 表示以客户端 ID 开头的行。
    • grep "^${client_id}" ${log_path}/frame_path.csv 用于在文件中查找匹配的行。
    • > /dev/null 2>&1 表示将标准输出和标准错误重定向到 /dev/null,即将匹配结果的输出静默化,只关心命令的返回状态码。
  • 检查 grep 命令的返回状态码,如果状态码为 0,表示找到了匹配的行,即客户端 ID 存在于文件中。

    • 如果客户端 ID 存在于文件中(即状态码为 0),则使用 awk 命令从 ${log_path}/frame_path.csv 文件中提取符合条件的行,并将结果保存到 ${log_path}/frame_stats_${client_id}.csv 文件中。
    • awk "NR==1 || /^${client_id}/" ${log_path}/frame_path.csv 用于提取匹配条件的行。条件是:行号为 1(即文件的第一行)或以客户端 ID 开头的行。
    • 提取的结果将被保存到以客户端 ID 命名的 CSV 文件中,文件名格式为 frame_stats_${client_id}.csv
grep "^${client_id}" ${log_path}/frame_path.csv > /dev/null 2>&1
if [ $? -eq 0 ]; then
  awk "NR==1 || /^${client_id}/" ${log_path}/frame_path.csv > ${log_path}/frame_stats_${client_id}.csv

动态链接库和可执行文件

  • 查看当前系统中动态链接库的信息【在哪里】
ldconfig -p | grep tinfo
  • 查看动态链接库和可执行文件的依赖动态库
ldd ./node
ldd ./libreadline.so.8
  • 利用 patchelf 修改某些链接
# 针对动态库
patchelf \
    --set-rpath /usr/sw-cluster/apps/lib/glibc-2.17/lib64/:/usr/sw-cluster/apps/Anaconda/anaconda3/lib/ \
    ./libreadline.so.8
    
# 针对可执行文件
patchelf \
    --set-rpath /usr/sw-cluster/apps/lib/glibc-2.17/lib64/:/usr/sw-cluster/apps/Anaconda/anaconda3/lib/ \
    --set-interpreter /usr/sw-cluster/apps/lib/glibc-2.17/lib64/ld-linux-x86-64.so.2 \
    ./libreadline.so.8
    
# 针对之前已经存在链接的相关库
patchelf --replace-needed libm.so.6 /usr/sw-cluster/apps/lib/glibc-2.17/lib64/libm.so.6 ./ninja

patchelf --replace-needed libc.so.6 /usr/sw-cluster/apps/lib/glibc-2.17/lib64/libc.so.6 ./ninja
  • 在神威上的 patchelf:/usr/sw-cluster/apps/Anaconda/anaconda3/bin/patchelf

软链接

  • linux 软链接
ln -s 源文件 目标文件

查看系统的硬件信息

体系架构

  • x86

CPU 区分是金牌还是银牌

电口/光口

  • 光口
    • 光口是服务器和网络中对各种光纤端口的统称,它是以光作为信息的承载介质。光口可能包含有从 ST 到 SFF(小型化光纤连接器,以 MTRJ 和 LC 为主)的各种光纤接口,因此在布线施工后期配备光纤跳线时,需要核实光口的光纤接口种类,以免在布线配置时假定的光纤跳线种类与实际使用的 要求不匹配。
    • 光纤接口是用来连接光纤线缆的物理接口。其原理是利用了光从光密介质进入光疏介质从而发生了全反射。通常有 SC、ST、FC 等几种类型,它们由日本 NTT 公司开发。FC 是 Ferrule Connector 的缩写,其外部加强方式是采用金属套,紧固方式为螺丝扣。ST 接口通常用于 10Base-F,SC 接口通常用于 100Base-FX。
    • 查看光口数量的指令: lspci | grep Network
    • 宝德没有光卡
  • 电口
    • 电口是服务器和网络中对 RJ45 等各种双绞线接口的统称,其原因是这些端口都使用电作为信息的承载介 质,不过有时它也会包含同轴电缆端口。通常电口可能使用百兆以太网、千兆以太网、万兆以太网或其它种类的传输协议。
    • 电口是相对光口来讲的,是指防火器的物理特性,主要指铜缆,包括普通的网线和射频同轴电缆,是处理的电信号。目前使用普遍的网络接口有百兆电口和千兆电口等。简单来说,电口就是普通的双绞线(Twirst Pair)接口,一般速率为 10M 或者 100M,部分支持 1000M.电口的最远距离为 100 米。光口的线缆上传输的是光信号,而电口的线缆上传输的是电信号,例如高电平(代表 1),低电平(代表 0)。
    • 查看电口数量的指令:lspci -vvv|grep Ether

万兆网卡配光模块

  • 宝德服务器没有

高性能 SAS RAID 卡及缓存

  • 查看 SAS RAID 卡信息:lspci -v -s $(lspci | grep -i raid |awk '{print $1}')

硬盘数量

wsl 相关操作

重启 ssh

  • 和普通的 linux 不太一样!
sudo service ssh --full-restart

GPU Sharing

概念学习文档

SSH 和 SCP 相关的指令

快速免密登录

# 客户端(本地电脑,实验室电脑)生成公钥 id_rsa.pub 私钥 id_rsa
ssh-keygen
# LINUX客户端公钥上传到远端
ssh-copy-id -i ~/.ssh/id_rsa.pub "-p 51100 ubuntu@172.18.166.98"
# WINDOWS 将 ~/.ssh/id_rsa.pub 的内容复制到服务器的 ~/.ssh/authorized_keys

ssh 登录遇到的问题

解决重启后无法 ssh

scp 传输文件和文件夹

scp -P 远程端口 本地文件名 远程主机名@远程主机ip:远程主机保存文件位置

scp -P 远程端口 -r 本地文件夹 远程主机名@远程主机ip:远程主机保存文件位置
scp -P 远程端口 -r 本地文件夹 --exclude '想要排除的文件名' 远程主机名@远程主机ip:远程主机保存文件位置

ssh 远程执行脚本

# 给文件增加执行权限
chmod +x /home/ubuntu/jellyfish/test_ssh_remote.sh

# 远程执行
ssh -n ubuntu@10.43.229.166 -p 22 /home/ubuntu/jellyfish/test_ssh_remote.sh

SSH 客户端会话超时机制

虚拟机

vmware 虚拟机相关

KVM 虚拟机

解压/压缩命令索引

tar.gz 压缩

  • tar zxvf MY_NAME.tar.gz

tgz 压缩

  • tar zxvf MY_NAME.tgz

.gz 压缩

.zip 压缩

  • unzip -d 目标目录 .zip 文件

##

##

##

gcloud/gsutil 下载文件

  • 参考 chatgpt 的解决方案
  • 使用 gsutil 工具或 gcloud 命令行工具来下载这些文件,前提是你已经进行了身份验证并具有相应的权限。以下是使用 gsutil 下载文件的示例:

    • 安装 gsutil(如果尚未安装):curl https://sdk.cloud.google.com | bash
    • 安装完成后,执行以下命令以设置 gsutilexec -l $SHELL
    • 使用 gsutil 下载文件:gsutil cp gs://waymo_open_dataset_v_1_0_0/training/training_0001.tar .
  • 请确保你已经进行了身份验证并且具有下载所需文件的权限。如果需要登录到 Google 帐户并获取访问权限,请使用 gcloud 命令行工具进行身份验证和授权。

    • 初始化身份验证和授权:gcloud init

代理/源相关

  • wget 代理

    • 参考文献:
    • 直接加上 -e “[ip]:[port]”
  • apt 源修改
  • Ubuntu 源修改

    • 参考文献

GPU 模式设置

Cuda 相关的指令

查看 cuda 版本

nvcc –version

cuda 多版本切换

安装 nvidia driver

安装 cudnn

Linux 权限相关操作

<strong>增加读权限
</strong>chmod +r filename 
<strong>增加写权限
</strong>chmod +w filename 
<strong>增加执行权限
</strong>chmod +x filename 
<strong>同时增加多个权限
</strong>chmod +rw filename # 增加读和写权限 
chmod +rx filename # 增加读和执行权限 
chmod +wx filename # 增加写和执行权限 
<strong>移除权限
</strong>chmod -r filename # 移除读权限 
chmod -w filename # 移除写权限 
chmod -x filename # 移除执行权限 
<strong>设置特定权限例如设置所有者具有读写权限组用户具有读权限其他用户具有读权限):
</strong>chmod u=rw,go=r filename

进程与线程相关操作

寻找父进程下的子进程

  • pgrep -P

检查进程的文件和网络请求

ls /proc/<pid>/fd

lsof -p <pid> # 这个指令可以检查到所有的情况, 通常可以加上 `| grep TCP` 来检索TCP链接

Shell 与.sh 脚本

Oh-my-zsh 危险的 shell

sh ~/.oh-my-zsh/tools/uninstall.sh 

Are you sure you want to remove Oh My Zsh? [y/N] y
Removing ~/.oh-my-zsh
Found ~/.zshrc -- Renaming to /home/ubuntu/.zshrc.omz-uninstalled-2023-10-09_10-41-54
Looking for original zsh config...
No original zsh config found
Thanks for trying out Oh My Zsh. It's been uninstalled.
Don't forget to restart your terminal!

如何通过 grub 进入安全模式修改启动脚本为 shell

  • 第三步,nano /etc/passwd 。修改 root 用户和当前用户的登录 shell
<strong>Before
root:x:0:0:root:/root:/bin/zsh
<your_user_name>:x:1000:1000:<your_user_name>,,,:/home/<your_user_name>:/bin/zsh
After
root:x:0:0:root:/root:/bin/bash
</strong><strong><your_user_name>:x:1000:1000:<your_user_name>,,,:/home/<your_user_name>:/bin/bash</strong>
  • 第四步,回到默认模式,重启主机
<strong>systemctl default
</strong><strong>exit</strong>

bash 相关指令

  • 参考资料:linux 下/etc/profile /etc/bashrc /root/.bashrc /root/.bash_profile 这四个配置文件的加载顺序_51CTO 博客_linux 下的命令
  • 四种不同的环境变量配置

    • /etc/profile 设置的是系统全局环境和登录系统的一些配置,该配置对所有用户生效;
    • /etc/bashrc 是 shell 全局自定义配置文件,主要用于自定义 shell,该配置对所有用户的 shell 都生效;
    • /root/.bashrc 用于单独自定义 root 用户的 bash,只对 root 用户的 bash 生效,如果要使 elk 用户生效,则需要配置/home/elk/.bashrc 文件;
    • /root/.bash_profile 用于单独自定义 root 用户的系统环境,只对 root 用户生效,如果要使 elk 用户生效,则需要配置/home/elk/.bash_profile。
  • 生效的顺序:/etc/profile > /etc/bashrc > /root/.bashrc > /root/.bash_profile

bash 避免环境变量出错的增加写法

export LD_LIBRARY_PATH=/usr/local/cuda-11.6/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

.sh 脚本相关

$!和$?和 $#

  1. $!

    • 含义:$! 表示最后一个在后台运行的作业(进程)的进程 ID。
    • 作用:通常用于在后台运行一个任务后,获取该任务的进程 ID,以便后续监控、控制或等待该任务的完成。
  2. $?

    • 含义:$? 表示上一个命令的退出状态码(返回值)。当一个命令成功执行时,其退出状态码通常为 0,如果出现错误或失败,状态码会是一个非零值,具体的值通常用于指示失败的原因。
    • 作用:主要用于判断上一个命令是否成功执行。通常在脚本中,可以根据 $? 的值来决定下一步的操作,例如,根据不同的状态码采取不同的处理方式。
  3. $#

    1. 含义:获取命令行参数的个数。
#!/bin/bash

# 执行一个命令,假设这个命令是成功的
ls

# 检查上一个命令的退出状态码
if [ $? -eq 0 ]; then
  echo "命令执行成功"
else
  echo "命令执行失败"
fi

# 后台运行一个命令,并获取其进程 ID
sleep 10 &
background_pid=$!
echo "后台进程 ID:$background_pid"

# 模拟一个失败的命令
ls /nonexistent_directory

# 再次检查上一个命令的退出状态码
if [ $? -eq 0 ]; then
  echo "命令执行成功"
else
  echo "命令执行失败"
fi

./myscript.sh arg1 arg2 arg3  

echo "参数个数: " $#  # 3

批量将文件里面的字段修改成需求字段的脚本

  1. find "${clients_cfg_dir}/.temp/":使用 find 命令来查找文件和目录,${clients_cfg_dir}/.temp/ 是查找的起始目录,表示从这个目录开始进行查找。
  2. -type f:这是 find 命令的选项,指定只查找文件(而不是目录或其他类型的文件)。 -type f 表示查找普通文件。
  3. -exec sed -i "s/client_ip/${client_ip}/g" {} \;:当 find 找到一个文件后,执行 -exec 后面的命令。在这里,sed -i "s/client_ip/${client_ip}/g" {} 表示对找到的文件执行 sed 命令,将文件中的所有 client_ip 字符串替换为 ${client_ip}

    • sed:用于处理文本流的工具,这里用于替换文本。
    • -ised 的选项,表示直接在原始文件上进行修改,而不是在标准输出中显示结果。
    • "s/client_ip/${client_ip}/g"sed 的替换命令,将文件中的所有 client_ip 替换为 ${client_ip}
    • {}:这个占位符会被 find 命令找到的文件名所替代。
    • \;:表示 -exec 命令结束。
find "${clients_cfg_dir}/.temp/" -type f -exec sed -i "s/client_ip/${client_ip}/g" {} \;

判断条件

  • 判断当前文件夹下面是否有文件

    • [ -e temp_clients_pid.txt ]
  • 判断字符串是否为空

    • [ -z "${network_trace_type}" ]

trap 截获指令操作

trap "stop" SIGHUP SIGINT SIGTERM

  • trap 是一个 Shell 命令,用于捕获(trap)或处理信号。
  • SIGHUP, SIGINT, 和 SIGTERM 是三种不同的信号,它们分别表示:

    • SIGHUP:挂起信号(Hang Up),通常由终端关闭引发。
    • SIGINT:中断信号(Interrupt),通常由用户在终端按下 Ctrl+C 引发。
    • SIGTERM:终止信号(Terminate),通常用于请求进程正常终止。
  • "stop" 是在接收到上述信号时要执行的命令。

    • while IFS= read -r pid; do ... done < temp_clients_pid.txt 表示逐行读 temp_clients_pid.txt 的内容,并每次赋值给 pid 变量
function stop() {
  echo "Stopping..."
  while IFS= read -r pid; do
    kill -TERM ${pid}
    wait $pid
    echo "Finshed pid ${pid}"
  done < temp_clients_pid.txt 
  rm temp_clients_pid.txt
  exit  
}
trap "stop" SIGHUP SIGINT SIGTERM

linux 安装多版本 gcc/g++

在 Linux 上安装多个 GCC 版本并支持多版本切换可以使用工具如 update-alternatives 来管理。以下是在 Linux 上安装多个 GCC 版本的一般步骤:

  1. (新版本)安装所需的GCC版本:

首先,您需要安装额外的 GCC 版本。对于 GCC 10.0,您可以使用包管理器来安装:

sudo apt update
   sudo apt install gcc-10 g++-10

这将安装 GCC 10.0 和相应的 g++。

  1. (老版本)安装所需的GCC版本:
  1. 使用update-alternatives设置默认版本:

update-alternatives 是一个用于管理 Linux 系统上可替代项的工具。您可以使用它来配置系统上的不同 GCC 版本。

首先,添加 GCC 10.0 到 update-alternatives 中:

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100
   sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 100

上述命令将 GCC 10.0 和 g++ 10.0 添加到备选列表中,并设置优先级为 100(可以根据需要进行更改)。

  1. 配置默认版本:

使用以下命令选择默认版本:

sudo update-alternatives --config gcc

然后,选择您希望作为默认版本的 GCC。重复此步骤以选择默认的 g++ 版本。

  1. 验证GCC版本:

您可以使用以下命令验证已安装的 GCC 版本:

gcc --version
   g++ --version

确保显示的版本号与您选择的默认版本一致。

  1. 切换版本:

每次需要更改 GCC 版本时,您可以使用 update-alternatives 来切换。例如,要切换到 GCC 11.4.0:

sudo update-alternatives --config gcc

然后选择 GCC 11.4.0 作为默认版本。

通过这些步骤,您可以在 Linux 系统上同时安装多个 GCC 版本,并根据需要进行切换。请注意,确保备份项目并测试切换是否正常工作,以避免潜在的兼容性问题。

Docker 相关的 Linux 指令

安装教程

解决权限问题

sudo groupadd docker #添加docker用户组
 
sudo gpasswd -a $USER docker #将登陆用户加入到docker用户组中
 
newgrp docker  #更新用户组

Docker 登录操作

docker login

Docker 将自己的 image 分享到 dockerhub

# 首先要打tag
# 要加上自己的用户名
docker tag legion_ci_2004 xlcbingo1999/legion_ci_2004
docker push xlcbingo1999/legion_ci_2004

Docker 将当前容器的状态重新生成 Image

[root@youxi1 ~]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
centos                         latest              67fa590cfc1c        3 weeks ago         202MB
hub.c.163.com/library/tomcat   latest              72d2be374029        2 years ago         292MB
[root@youxi1 ~]# docker run -it centos:latest /bin/bash
[root@985ef7e0c4ca /]# yum -y install httpd
[root@985ef7e0c4ca /]# exit
exit

[root@youxi1 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
985ef7e0c4ca        centos:latest       
"/bin/bash"         
4 minutes ago       Exited (0) 2 minutes ago                       sharp_kare
9a81af9b4134        centos:latest       
"/bin/bash"         
2 days ago          Exited (0) 2 days ago                          pensive_dijkstra
3ecc9bafd429        centos:latest       
"/bin/bash"         
2 days ago          Exited (0) 2 days ago                          sleepy_wilbur
[root@youxi1 ~]# docker commit 985ef7e0c4ca centos:httpd
sha256:bdd371e6f1cf035bd501c09b28a2b2827900973a0defa9e35eadcd2f2f55e5e4
[root@youxi1 ~]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
centos                         httpd               bdd371e6f1cf        14 seconds ago      346MB
centos                         latest              67fa590cfc1c        3 weeks ago         202MB
hub.c.163.com/library/tomcat   latest              72d2be374029        2 years ago         292MB

Docker 中使用 sshd

SSH 连接 docker 中的 container - 知乎 (zhihu.com)

apt-get update
apt-get install passwd openssl openssh-server

vim /etc/ssh/sshd_config
service ssh restart

Docker 镜像相关操作

  • 查看所有的镜像
docker image ls

Docker 运行中的容器相关操作

  • 查看运行中的容器
docker ps

Docker 启动容器

docker run --gpus all -it <image_name>

Docker 中使用宿主机的代理


Docker 中修改源

# 编辑 Docker 配置文件
$ sudo vim /etc/docker/daemon.json
# 加入以下配置项
{
    "registry-mirrors": [
        "https://dockerproxy.com",
        "https://hub-mirror.c.163.com",
        "https://mirror.baidubce.com",
        "https://ccr.ccs.tencentyun.com"
    ]
}

$ sudo service docker restart

# 查看 Docker 信息
$ sudo docker info

# 出现以下字段代表配置成功
Registry Mirrors:
  https://dockerproxy.com/
  https://hub-mirror.c.163.com/
  https://mirror.baidubce.com/
  https://ccr.ccs.tencentyun.com/

Docker 挂载宿主机目录到容器中

Docker 挂载端口

dokcer run -itd -p 49159:80 -p 49160:22 ubuntu /bin/bash

新版 Docker 增加 nvidia-container-toolkit

  • 参考文献:
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker

docker-compose 安装

  • 参考文献:docker/compose: Define and run multi-container applications with Docker (github.com)
  • You can download Docker Compose binaries from the release page on this repository.

    • Rename the relevant binary for your OS to docker-compose and copy it to $HOME/.docker/cli-plugins
    • Or copy it into one of these folders to install it system-wide:
      • /usr/local/lib/docker/cli-plugins OR /usr/local/libexec/docker/cli-plugins
      • /usr/lib/docker/cli-plugins OR /usr/libexec/docker/cli-plugins
    • (might require making the downloaded file executable with chmod +x)

docker-compose 启动及后台启动指令

docker-compose up  #启动所有容器
docker-compose up -d  #后台启动并运行所有容器
docker-compose up --no-recreate -d  #不重新创建已经停止的容器
docker-compose up -d test2  #只启动test2这个容器
docker-compose stop  #停止容器
docker-compose start  #启动容器
docker-compose down #停止并销毁容器

K8S 相关的 Linux 指令

安装和配置 microk8s

sudo snap install microk8s --classic --channel=1.22/stable

sudo usermod -a -G microk8s $USER
mkdir -p $HOME/.kube
sudo chown -f -R <your_user_name> ~/.kube
sudo snap alias microk8s.kubectl kubectl
su - $USER
microk8s status --wait-ready

(通常是 /var/snap/microk8s/current/args/containerd-env)
加入两行:
HTTPS_PROXY=http://<ip>:7890
HTTP_PROXY=http://<ip>:7890
sudo snap restart microk8s
microk8s enable helm3
microk8s enable gpu
microk8s enable dns

kubectl config view --raw > ~/.kube/config

microk8s 增加和删除节点

  • 参考文献:microk8s 部署多节点 k8s 集群

microk8s 升级

进入容器的方法

kubectl exec -it gpu-operator-6f97b7b47c-gfdt5 -n gpu-operator-resources -- /bin/bash

配置 microk8s 内置 docker 的 registry.mirrors

编辑 /var/snap/microk8s/current/args/containerd-template.toml 文件

在 endpoint 添加 新的 国内 registry.mirrors , 如 “https://docker.mirrors.ustc.edu.cn”

[plugins.cri.registry]
      [plugins.cri.registry.mirrors]
        [plugins.cri.registry.mirrors."docker.io"]
          endpoint = [
                "https://docker.mirrors.ustc.edu.cn",
                "https://hub-mirror.c.163.com",
                "https://mirror.ccs.tencentyun.com",
                "https://registry-1.docker.io"
          ]

然后,先停止 microk8s,再启动 microk8s:

sudo microk8s stop
sudo microk8s start

完全卸载 microk8s

sudo snap remove microk8s

配置 microk8s 内置 docker 的 containerd-env 环境代理

${SNAP_DATA}/args/containerd-env

(通常是 /var/snap/microk8s/current/args/containerd-env)

加入两行:

HTTPS_PROXY=[http:///](http://:7890/)

HTTP_PROXY=[http:///](http://:7890/)

NO_PROXY=10.1.0.0/16,{K8SIP}/24

{K8SIP}的获取方式是:kubectl get services -A ,查看所有的 cluster-ip

然后重启 microk8s

配置变量使得环境不需要 sudo 和 microk8s 即可进入 kubectl

  • 失败方案

If you prefer to omit sudo, add your user to the microk8s group, and then re-login to your shell:

$ sudo usermod -a -G microk8s $USER

If you prefer to use kubectl rather than microk8s.kubectl:

$ mkdir -p $HOME/.kube

$ sudo microk8s kubectl config view –raw > $HOME/.kube/config

$ sudo chown -f -R $USER ~/.kube

sudo usermod -a -G microk8s $USER
mkdir -p $HOME/.kube
sudo chown -f -R <your_user_name> ~/.kube
sudo snap alias microk8s.kubectl kubectl

helm 的安装和代理

  • 安装:
sudo snap install helm --classic
  • 代理:helm install with proxy-掘金 (juejin.cn) 【不太需要】
  • 配置验证
# 临时验证
export KUBECONFIG=/var/snap/microk8s/current/credentials/client.config

# 始终可以
sudo cp /var/snap/microk8s/current/certs/ca.crt /usr/local/share/ca-certificates/microk8s.crt
sudo update-ca-certificates
sudo snap restart microk8s

helm 查看 chart 的版本[不建议用这个方法去安装 dashboard]

#helm 列出所有版本:
helm search repo kubernetes-dashboard/kubernetes-dashboard -l

helm install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --version 3.0.2

helm 卸载某个应用

helm uninstall kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard

安装 dashboard

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml

dashboard 如何登录

  • 老版本的 dashboard 登陆方式
# 配置端口
kubectl -n kubernetes-dashboard port-forward $POD_NAME 8443:8443
# kubectl -n kubernetes-dashboard port-forward kubernetes-dashboard-64c68cd4d5-k72nh 8443:8443  

# 检查密钥
kubectl -n kube-system get secret

# 获取密钥
kubectl describe secret deployment-controller-token-???? -n kube-system
eyJhbGciOiJSUzI1NiIsImtpZCI6IlV0YkxXQ1hjTTc2ajNoUUZDUDhISVVidnZrNHFZMDBJSE91WGlXQ2wyMDAifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZXBsb3ltZW50LWNvbnRyb2xsZXItdG9rZW4tZ3I5ZHYiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVwbG95bWVudC1jb250cm9sbGVyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiNWNiMjBiNGQtOGVjNi00NDUwLWIxZDUtZDk1NDg0NzRiZWFjIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRlcGxveW1lbnQtY29udHJvbGxlciJ9.bM3XroK7vnE0UcfO717WiK1dGJNVXp4CA9hUtNhPwt_MtOnYDEPbBpOhPJKoRf8-nPXFS67dE8Uc3VdOxVfBdAO4JodWbjLShmbQtOcMxjHtmyYbsctKCK3MVxuLD2RYGtarO82u0gkhrK7CsadB2UXXeLRERmpTLSBPnpL9ikLKMYeiimn8lax5EcDVMwj4-P-xZtifz6LcKNCl6PHZI8D_kIn7m8tfBGvSBhVD1lApaqlQcP8lvDsehjXM_wiRCE8IV0ce9Rd5J6DHm6GuCJxw1LXN8VxgY1JCR75ZXqEAiSTxKk3eYholodEDdNzjM0yedEZn0qVotzAo1NozEw
# 复制到网页中
  • 新版本登录方式

  • 延长检测时间
- name: kubernetes-dashboard
      image: 'kubernetesui/dashboard:v2.0.0-rc5'
      args:
        - '--auto-generate-certificates'
        - '--namespace=kubernetes-dashboard'
        - '--token-ttl=68400'     # 增加了此行

删除所有的 deployment/service/pod/replicaset/secret/namespace

kubectl delete -n adaptdl --all all
  • 第一步:检查某个命名空间下的所有内容 => kubectl get all -n adaptdl
NAME                                         READY   STATUS    RESTARTS   AGE
pod/adaptdl-adaptdl-sched-59c9cfd956-gt7p5   3/3     Running   1          96m
pod/adaptdl-registry-7f45598964-dds2p        1/1     Running   0          96m
pod/adaptdl-validator-5cf868d86b-htnw6       1/1     Running   0          96m

NAME                            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/adaptdl-adaptdl-sched   ClusterIP   10.152.183.45    <none>        9091/TCP         96m
service/adaptdl-registry        NodePort    10.152.183.126   <none>        5000:32000/TCP   96m
service/adaptdl-supervisor      ClusterIP   10.152.183.16    <none>        8080/TCP         96m
service/adaptdl-validator       ClusterIP   10.152.183.173   <none>        443/TCP          96m

NAME                                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/adaptdl-adaptdl-sched   1/1     1            1           96m
deployment.apps/adaptdl-registry        1/1     1            1           96m
deployment.apps/adaptdl-validator       1/1     1            1           96m

NAME                                               DESIRED   CURRENT   READY   AGE
replicaset.apps/adaptdl-adaptdl-sched-59c9cfd956   1         1         1       96m
replicaset.apps/adaptdl-registry-7f45598964        1         1         1       96m
replicaset.apps/adaptdl-validator-5cf868d86b       1         1         1       96m
  • 第二步:先 delete 所有的 deployment【会自动删除所有的 replicaset.apps 和 pod】
kubectl delete deployment.apps/adaptdl-registry -n adaptdl
  • 第三步:delete 所有的 service
  • 第四步[可选, 其实直接删除 namespace 也是可以直接删除这些的]:检索一下是否还有留存的 secrets:
kubectl get secrets -A
kubectl delete secret --all -n adaptdl
  • 第五步:删除最后的 namespace,完全干净的删除
kubectl delete namespace adaptdl

namespace 无法删除的问题

  • k8s 命名空间 Terminating 产生原因及解决方法 - Martin 工作生活 Record (leiyawu.com)
TODELNS=kserve-test
kubectl get ns ${TODELNS} -o json > ${TODELNS}.json
code ${TODELNS}.json
# 将"spec": {        "finalizers": [            "kubernetes"        ]    },更改为:"spec": {      },

kubectl proxy --port=8081

(新窗口) lsof -i:8081
(新窗口) TODELNS=kserve-test
(新窗口)  curl -k -H "Content-Type:application/json" -X PUT --data-binary @${TODELNS}.json http://127.0.0.1:8081/api/v1/namespaces/${TODELNS}/finalize

配置 kserve 服务

  • 其中阴影表示的是 Istio mesh,mesh 中的的流量属于集群内部(东西向)流量,而客户端访问 Kubernetes 集群内服务的流量属于外部(南北向)流量。
  • 将 K8S 中的服务暴露对外的几种方式

    • NodePort 、 LoadBalancer:K8S 内置的暴露服务的方式
    • K8S Ingress: 用于支持虚拟主机、隐藏和节省 IP 地址。Ingress 就是从 Kubernetes 集群外访问集群的入口,将用户的 URL 请求转发到不同的服务上。Ingress 相当于 Nginx、Apache 等负载均衡方向代理服务器,其中还包括规则定义,即 URL 的路由信息,路由信息得的刷新由 Ingress controller 来提供。
      • 同一个服务的的不同示例可能被调度到不同的节点上;
      • Kubernetes 通过 Service 对象将一个服务的多个实例组合在了一起,统一对外服务;
      • Kubernetes 在每个 node 中安装了 kube-proxy 组件来转发流量,它拥有的简单的负载均衡功能;
      • Kubernetes 集群外部流量可以通过 Ingress 进入集群中(Kubernetes 还有其他几种暴露服务的方式,如 NodePort、LoadBalancer 等);
  • Istio Gateway:Istio 补足了 Kubernetes 对于云原生应用的流量管理、可观察性和安全方面的短板,使得流量管理变得对应用程序透明,使这部分功能从应用程序中转移到了平台层,成为了云原生基础设施。
    • Istiod 作为控制平面,将配置下发给所有的 sidecar proxy 和 gateway(为了美观,图中没有画 Istiod 及 sidecar 之间的连接)
    • Istio 不再使用 kube-proxy 组件做流量转发,而是依托在每个 pod 中注入的 sidecar proxy,所有的 proxy 组成了 Istio 的数据平面;
    • 应用程序管理员可以和管理 Kubernetes 中的工作负载一样,通过声明式 API 操作 Istio mesh 中流量的行为;
    • Ingress 被 Gateway 资源所替代,Gateway 是一种特殊的 proxy,实际上也是复用的 Sidecar proxy;
    • 可以在虚拟机中安装 sidecar proxy,将虚拟机引入的 Istio mesh 中;
  • API 网关:API 网关是位于客户端和后端服务之间的 API 管理工具,一种将客户端接口与后端实现分离的方式,在微服务中得到了广泛的应用。当客户端发出请求时,API 网关会将其分解为多个请求,然后将它们路由到正确的位置,生成响应,并跟踪所有内容。

配置 kserve 的一个 torch 服务

curl -v -H "Host: ${SERVICE_HOSTNAME}" -H "Content-Type: application/json" http://${INGRESS_HOST}:${INGRESS_PORT}/v1/models/${MODEL_NAME}:predict -d @./input.json
  • GPU 支持
  • 多模型服务【The Scalability Problem - KServe Documentation Website

    • 随着机器学习方法在组织中越来越广泛采用,出现了部署大量模型的趋势。例如,新闻分类服务可以为每个新闻类别训练自定义模型。组织希望训练大量模型的另一个重要原因是保护数据隐私,因为隔离每个用户的数据并单独训练模型更安全。虽然通过为每个用例构建模型可以获得更好的推理准确性和数据隐私,但在 Kubernetes 集群上部署数千到数十万个模型更具挑战性。此外,服务基于神经网络的模型的用例越来越多。为了实现合理的延迟,这些模型最好在 GPU 上运行。然而,由于 GPU 是昂贵的资源,因此为许多基于 GPU 的模型提供服务的成本很高。
    • KServe 的原始设计为每个 InferenceService 部署一个模型。但是,在处理大量模型时,其“一个模型、一个服务器”范式给 Kubernetes 集群带来了挑战。为了扩展模型的数量,我们必须扩展推理服务的数量,这可以快速挑战集群的限制。
    • 推理场景中的 GPU Sharing:由于将 sidecar 注入到每个 pod 中,每个 InferenceService 都会产生资源开销。这通常会为每个 InferenceService 副本增加约 0.5 个 CPU 和 0.5G 内存资源。例如,如果我们部署 10 个模型,每个模型有 2 个副本,则资源开销为 10 * 2 * 0.5 = 10 CPU 和 10 * 2 * 0.5 = 10 GB 内存。每个模型的资源开销为 1CPU 和 1 GB 内存。使用当前方法部署许多模型将很快耗尽集群的计算资源。通过多模型服务,这些模型可以加载到一个 InferenceService 中,那么每个模型的平均开销为 0.1 个 CPU 和 0.1GB 内存。对于基于 GPU 的模型,所需的 GPU 数量随着模型数量的增长而线性增长,这不符合成本效益。如果多个模型可以加载到一台启用 GPU 的模型服务器(例如 TritonServer)中,那么我们在集群中需要的 GPU 就会少很多。
  • 预处理 - 推理 - 后处理 的 Pipeline:是否可以从中找到优化点【Feast - KServe Documentation Website
  • 问题:每次启动一个服务的时候似乎总在从网络上下载很大的镜像,尤其是 cuda 和 pytorch 的依赖镜像,是否会有合适的重用机制?

自定义 configmap 用于将本地

自定义 Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gpu-pod-testvgpu
spec:
  replicas: 1 # 必须项
  selector:
    matchLabels:
      app: gpu-pod-testvgpu
  template:
    metadata:
      labels:
        app: gpu-pod-testvgpu # 设置与 selector 匹配的标签
    spec:
      containers:
      - name: ubuntu-container
        image: pytorch/pytorch:1.8.1-cuda10.2-cudnn7-runtime
        volumeMounts: # 挂载卷
        - name: script-volume
          mountPath: /app/test-vgpu-resnet.py
          subPath: test-vgpu-resnet.py
        command: ["python", "/app/test-vgpu-resnet.py"] # 执行指令
        resources:
          limits:
            nvidia.com/gpu: 2 # requesting 2 vGPUs
            nvidia.com/gpumem: 3000 # Each vGPU contains 3000m device memory (Optional,Integer)
            nvidia.com/gpucores: 30 # Each vGPU uses 30% of the entire GPU (Optional,Integer)
      volumes: # 从先创建的volume中使用
      - name: script-volume
        configMap:
          name: test-vgpu-resnet

自定义 Job

apiVersion: batch/v1
kind: Job
metadata:
  name: gpu-pod-testvgpu
spec:
  template:
    spec:
      containers:
      - name: ubuntu-container
        image: pytorch/pytorch:1.8.1-cuda10.2-cudnn7-runtime
        volumeMounts:
        - name: script-volume
          mountPath: /app/test-vgpu-resnet.py
          subPath: test-vgpu-resnet.py
        command: ["python", "/app/test-vgpu-resnet.py"]
        resources:
          limits:
            nvidia.com/gpu: 2 # requesting 2 vGPUs
            nvidia.com/gpumem: 3000 # Each vGPU contains 3000m device memory (Optional,Integer)
            nvidia.com/gpucores: 30 # Each vGPU uses 30% of the entire GPU (Optional,Integer)
      restartPolicy: Never
      volumes:
      - name: script-volume
        configMap:
          name: test-vgpu-resnet

优雅退出