Linux 相关指令
Linux 原生
性能检查工具
-
最常用的几个命令:
- 参考文献:https://www.jianshu.com/p/3422ea8ad008
- Top
- Htop: 检查进程和内存占用
-
检查进程
开机自启动指令
关闭/开启自动更新
服务器文件夹共享/远程文件夹
# 挂载
sudo mount -t nfs 10.xxx.xxx.xxx:/path-to-share /path-to-mount
# 取消挂载
sudo unmount.nfs /path-to-mount
- 本机:文件链接
tee 命令
- 作用:从标准输入中复制到每一个文件,并输出到标准输出。
- 参考文献:为初学者介绍的 Linux tee 命令(6 个例子) - 知乎 (zhihu.com)
磁盘容量分配扩容
- 直接根据参考文献的方法修改即可获得满容量的 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
。
- 如果客户端 ID 存在于文件中(即状态码为 0),则使用
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 区分是金牌还是银牌
- CPU 比较网站:Intel Xeon E5-2660 vs Intel Xeon Silver 4110:有何不同? (versus.com)
-
CPU 系列对应
- E5 对位铜牌和银牌,以及 5000 系金牌
- E7 对位 6000 系金牌和铂金牌
- E3 对位 E-21xx/22xx
电口/光口
- 光口
- 光口是服务器和网络中对各种光纤端口的统称,它是以光作为信息的承载介质。光口可能包含有从 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}')
-
查看 SAS RAID 卡缓存
- 1GB / 2GB
- 应该是可以
-
RAID 5
- 宝德服务器上的 LSI MegaRAID SAS 9361-8i 是支持的:lsi9364-8i 阵列卡的不同版本介绍,全功能版比 lsi9361-8i 性价比高。 - 知乎 (zhihu.com)
硬盘数量
wsl 相关操作
重启 ssh
- 和普通的 linux 不太一样!
sudo service ssh --full-restart
GPU Sharing
概念学习文档
-
参考文献:
- 各大公司的方案:【精选】盘点来自工业界的 GPU 共享方案_夕小瑶的博客-CSDN 博客
- 从架构角度更详细一点的文章:NVIDIA MPS 总结
SSH 和 SCP 相关的指令
快速免密登录
- 参考文献:SSH 三步解决免密登录-CSDN 博客
# 客户端(本地电脑,实验室电脑)生成公钥 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 登录遇到的问题
- known_hosts 相关:(SSH 体系下的公私密钥的介绍和使用技巧) - 腾讯云开发者社区-腾讯云 (tencent.com)
- Ssh key 相关:SSH 下 authorized_keys, id_rsa, id_rsa.pub, known_hosts 作用_51CTO 博客_.ssh/id_rsa
- debug1: read_passphrase: can’t open /dev/tty: No such file or directory:连接 ssh 出现 Permission denied 之一解 - 三言三语 (best33.com)
解决重启后无法 ssh
- 参考文献:ssh 设置免密后仍需要输入密码的解决方案_mb63bbbecf48728 的技术博客_51CTO 博客
- 关键是要在服务端检查 sshd 的 log
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 虚拟机
- 相关指令:KVM 操作虚拟机常用命令_shaonbean 的博客-CSDN 博客
- 使用 virsh 查看虚拟机的 ip 和 mac 地址:kvm 虚拟机利用 virsh 查看 ip_kevinsingapore 的博客-CSDN 博客_virsh 查看虚拟机 ip
解压/压缩命令索引
tar.gz 压缩
- tar zxvf MY_NAME.tar.gz
tgz 压缩
- tar zxvf MY_NAME.tgz
.gz 压缩
- 参考文献:如何解压 GZ 文件 - 腾讯云开发者社区-腾讯云 (tencent.com)
- gzip -d file.gz: 这个命令将会将压缩文件解压缩,并且移除.gz 文件。
- gzip -dk file.gz:保持压缩文件不变,传递-k 选项给命令
.zip 压缩
- unzip -d 目标目录 .zip 文件
##
##
##
gcloud/gsutil 下载文件
- 参考 chatgpt 的解决方案
-
使用
gsutil
工具或gcloud
命令行工具来下载这些文件,前提是你已经进行了身份验证并具有相应的权限。以下是使用gsutil
下载文件的示例:- 安装
gsutil
(如果尚未安装):curl https://sdk.cloud.google.com | bash
- 安装完成后,执行以下命令以设置
gsutil
:exec -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
- 参考文献:超全超详细的安装 nvidia 显卡驱动教程_ubuntu 安装显卡驱动-CSDN 博客
- 下载.run 文件,直接安装即可?
安装 cudnn
- [该方案存在 bug]参考文献:ubuntu 安装 cuda10.2 以及 cudnn7.6.5 - 简书 (jianshu.com)
- [似乎可以修复上述方案中 bug 的解决方案]:解决 CuDNN runtime 版本和编译版本不同的问题_libcudnn.so 不同版本-CSDN 博客
Linux 权限相关操作
-
Linux sudo 权限:
-
- 加组;
-
-
危险的 777 权限:https://juejin.cn/post/6844903694509539336
<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
-
安装方法:
-
优雅的删除 zsh 的方法:
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
- 参考文献:[Solved] Fix login issue after removing zsh from Debian/Ubuntu - TREND OCEANS
- 第一步:进入 grub【一般是先进入 bios,然后马上退出,退出的时候按一下 ESC 即可进入。不要按太多次】
- 第二步,按 e 进入编辑模式,然后在 linux 的那一行加入 quiet 1,并按 ctrl-x 退出,即可进入安全模式
- 第三步,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 脚本相关
$!和$?和 $#
-
$!
:- 含义:
$!
表示最后一个在后台运行的作业(进程)的进程 ID。 - 作用:通常用于在后台运行一个任务后,获取该任务的进程 ID,以便后续监控、控制或等待该任务的完成。
- 含义:
-
$?
:- 含义:
$?
表示上一个命令的退出状态码(返回值)。当一个命令成功执行时,其退出状态码通常为 0,如果出现错误或失败,状态码会是一个非零值,具体的值通常用于指示失败的原因。 - 作用:主要用于判断上一个命令是否成功执行。通常在脚本中,可以根据
$?
的值来决定下一步的操作,例如,根据不同的状态码采取不同的处理方式。
- 含义:
-
$#
:- 含义:获取命令行参数的个数。
#!/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
批量将文件里面的字段修改成需求字段的脚本
-
find "${clients_cfg_dir}/.temp/"
:使用find
命令来查找文件和目录,${clients_cfg_dir}/.temp/
是查找的起始目录,表示从这个目录开始进行查找。 -
-type f
:这是find
命令的选项,指定只查找文件(而不是目录或其他类型的文件)。-type f
表示查找普通文件。 -
-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
:用于处理文本流的工具,这里用于替换文本。 -
-i
:sed
的选项,表示直接在原始文件上进行修改,而不是在标准输出中显示结果。 -
"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 版本的一般步骤:
- (新版本)安装所需的GCC版本:
首先,您需要安装额外的 GCC 版本。对于 GCC 10.0,您可以使用包管理器来安装:
sudo apt update
sudo apt install gcc-10 g++-10
这将安装 GCC 10.0 和相应的 g++。
- (老版本)安装所需的GCC版本:
- 使用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(可以根据需要进行更改)。
- 配置默认版本:
使用以下命令选择默认版本:
sudo update-alternatives --config gcc
然后,选择您希望作为默认版本的 GCC。重复此步骤以选择默认的 g++ 版本。
- 验证GCC版本:
您可以使用以下命令验证已安装的 GCC 版本:
gcc --version
g++ --version
确保显示的版本号与您选择的默认版本一致。
- 切换版本:
每次需要更改 GCC 版本时,您可以使用 update-alternatives
来切换。例如,要切换到 GCC 11.4.0:
sudo update-alternatives --config gcc
然后选择 GCC 11.4.0 作为默认版本。
通过这些步骤,您可以在 Linux 系统上同时安装多个 GCC 版本,并根据需要进行切换。请注意,确保备份项目并测试切换是否正常工作,以避免潜在的兼容性问题。
Docker 相关的 Linux 指令
安装教程
解决权限问题
- 参考文献:解决 Docker 安装后权限问题 Got permission denied while trying to connect to the Docker daemon socket_小可爱 bling 的博客-CSDN 博客
- 个人感觉这个方法会比较好!
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 容器内使用宿主机的代理配置 Zach Ke’s Notes (kebingzao.com)
- 解决方案【17.0 版本之后】:直接在宿主机上配置 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 — 从入门到实践 (gitbook.io)
- 指令:–mount type=bind,source=<>,target=<>
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
)
- Rename the relevant binary for your OS to
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
- 安装完成后马上执行的指令
- 允许 helm3
- 更改 tiller 的镜像位置: Helm 中 Tiller 镜像下载失败的解决办法_exec failed after 3 retires: pull image failed: fa-CSDN 博客
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_PROXY=[http://
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
- 参考文献:部署和访问 Kubernetes 仪表板(Dashboard) Kubernetes
- 请直接从这里找指令下载,否则会比较麻烦
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
- 参考文献:k8s 删除 pod 及 service - 明天,你好啊 - 博客园 (cnblogs.com)
- 第一/二/三步:[注意,前三部可以合并成一条指令]
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 服务
- 参考文档:First InferenceService - KServe Documentation Website
- 配置踩坑:一定要在 microk8s 1.22 或者以上配置才能成功,老版本的 api 不兼容!
-
istio 的作用
- 参考文献:如何理解 Istio Ingress,它与 API Gateway 有什么区别? · Jimmy Song
- API 网关作为客户端访问后端的入口,已经存在很长时间了,它主要是用来管理”南北向“的流量;近几年服务网格开始流行,它主要是管理系统内部,即“东西向”流量,而像 Istio 这样的服务网格还内置了网关,从而将系统内外部的流量纳入了统一管控。
- 其中阴影表示的是 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 服务
- 使用网上已有的模型:PyTorch - KServe Documentation Website
curl -v -H "Host: ${SERVICE_HOSTNAME}" -H "Content-Type: application/json" http://${INGRESS_HOST}:${INGRESS_PORT}/v1/models/${MODEL_NAME}:predict -d @./input.json
-
自己配置一个模型,上传到 kserve 中:
- 自己配置一个模型,上传到 kserve 中,并支持 serverless:
- Inference Graph => Serving mesh:一个推理服务需要好几个阶段,每个阶段的调度和分配!
- batch 处理推理请求:Inference Batcher - KServe Documentation Website
- Kserve 的调度器
- 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