关于系统的改造探索
开篇:系统改造的调研报告
第一部分——Docker篇
第一章 Docker容器
第二章 Docker安装
第三章 构建自定义镜像
第四章 搭建镜像仓库
第五章 容器编排
第六章 容器监控
文章目录
- 关于系统的改造探索
- 第一部分——Docker篇
- 前言
- 一、在线环境
- 二、Docker Desktop
- 1、检查系统要求
- 2、安装Docker Desktop
- 3、解决Docker Engine stopped
- 三、 Docker Machine
- 三、Linux离线安装
- 四、Ansible批量安装
- 补充——root权限被回收
- 总结
前言
随着业务的发展,传统的架构已经不符合项目的要求了。双活、集群也渐渐提上了日程。。。
一、在线环境
受限于本地机器,如果只是单纯的学习使用,不妨试试 Play-With-Docker (PWD)是一个在线沙盒环境,由 Docker公司支持和推广。不过这个一个会话只能使用4个小时,没有魔法的话,速度很慢
相关快捷键:
复制:Ctrl + Insert,
粘贴:Shift + Insert、Ctrl + shift + V
二、Docker Desktop
Docker Desktop 是适用于 Mac、Linux 或 Windows 环境的一键安装应用程序,可让您构建、共享和运行容器化应用程序和微服务。它提供了一个简单的 GUI(图形用户界面),让您可以直接从机器管理 容器、应用程序 和 镜像,这个也是方便学习,本地调试用的,下边简单说下 Windows 的安装,这里以 Windows11 家庭版 为例:
1、检查系统要求
在此之前,先检查自己的系统是否符合要求:
WSL版本 可通过命令行窗口查看,打开 PowerShell ,输入:
wsl --version
笔者这里不符合要求,所以得去下载对应的升级包。这里大概描述一下(水点字数。嘿嘿~~),详情参考 Windows官网
- 启用适用于 Linux 的 Windows 子系统
以管理员身份打开 PowerShell(“开始”菜单 >“PowerShell” >单击右键 >“以管理员身份运行”),然后输入以下命令:
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
- 检测操作系统版本
- 启用虚拟机功能
PowerShell 窗口输入以下命令:
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
- 安装 Linux 内核更新包
- 在线安装(推荐)
PowerShell 窗口输入以下命令:
wsl.exe --install
wsl.exe --update
- 离线安装
现下载最新版本的 Linux 内核更新包,如果需要了解详细信息,可以去 WSL2-Linux-Kernel上查看。
直接安装可能出现下边这种情况:
可按照如下操作进行解决:
- 将 WSL 2 设置为默认版本
PowerShell 窗口输入以下命令:
wsl --set-default-version 2
再次输入 wsl --version
查看版本,已经成功升级为 WSL 2
2、安装Docker Desktop
准备好前置环境后,再去 Docker官网 下载安装包,这就是一个.exe文件,直接无脑下一步即可
根据提示,还需要打开 Hyper-V
由于 Windows版本 是 家庭版 ,不适用 Hyper-V,具体原因在 这里 查看。用 管理员 执行以下脚本解决:
pushd "%~dp0"
dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt
for /f %%i in ('findstr /i . hyper-v.txt 2^>nul') do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"
del hyper-v.txt
Dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /LimitAccess /ALL
现在 Docker Desktop 应该可以正常打开了。但是提示 Docker Engine stopped
3、解决Docker Engine stopped
- 设置 Docker Desktop Service 自启动
- 这个服务在任务管理器里边可能看不到,按 Win + R 打开运行对话框
- 输入 services.msc, 然后按回车或点击“确定”
- 打开 CPU虚拟化
打开任务管理器,检查是否已经开启虚拟化,如果未开启,参考 这里
- 检查 hypervisorlaunchtype 是否为 Auto
- 用管理员打开 Windows PowerShell
- 输入
bcdedit | findstr hypervisorlaunchtype
, 查看 hypervisorlaunchtype 的状态。如果不是 Auto ,则输入bcdedit /set hypervisorlaunchtype auto
并重启电脑
三、 Docker Machine
上述安装方式仅供学习使用,现在来看下如何在 Linux 上安装。Linux 上安装 Docker 安装分为在线、离线。在线安装单节点比较简单,这里就不赘述了,可以参考官方安装文档。这里主要看下使用 Docker Machine 进行批量安装
- 安装 Git
Windows 环境下 Docker Machine 需要Git Bash 才能使用(其他环境可以无视),现在官网下载并安装下 Git 。Git 安装直接无脑下一步即可
- 安装 Docker Machine
点击鼠标右键,打开 Git Bash :
输入以下内容,这里使用的 Docker Machine 的版本为 v0.16.2,大家根据自己的需求实际选择:
base=https://github.com/docker/machine/releases/download/v0.16.2 &&mkdir -p "$HOME/bin" &&curl -L $base/docker-machine-Windows-x86_64.exe > "$HOME/bin/docker-machine.exe" &&chmod +x "$HOME/bin/docker-machine.exe"
等待执行完毕后,执行 docker-machine.exe -v
查看版本
- 配置 SSH
在使用 Docker Machine 之前,要先配置 SSH。在 Git Bash 黑窗口下,执行如下命令:
#遇到提示一路回车即可
ssh-keygen
#传输给远程机子
ssh-copy-id -i ~/.ssh/*.pub root@192.168.233.139
连接远程机子不需要输入密码,则配置成功:
- 安装 Docker
在执行下列操作之前,需要保证目标机子可以联网,执行如下命令:
#连接远程主机
ssh root@192.168.233.139
cd /etc/yum.repos.d
rm -f *.repo
#修改源为阿里的
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repoyum makecache#卸载runc相关内容,否则会冲突
dnf remove runc -y
#永久关闭防火墙
systemctl stop firewalld.service
systemctl disable firewalld.service
#退出
exit#C:/Users/zs/.ssh/id_rsa 改成自己秘钥的位置,正常都在C:/Users/《当前用户名》/.ssh/id_rsa
docker-machine -D create --driver generic --generic-ip-address=192.168.233.139 --generic-ssh-key=C:/Users/hqd/.ssh/id_rsa --generic-ssh-user=root --engine-install-url=https://releases.rancher.com/install-docker/20.10.5.sh node1
等待安装完成后,输入 docker-machine ls
验证
这里资源有限,就不安装多台了,其他机子也是如法炮制就行了。Docker Machine 除了安装 Docker 环境之后,也有一定的管理 Docker 集群的能力,可以进行远程操作,下边以运行 Nginx 为例:
#切换到node1节点上
eval $(docker-machine env node1)
#运行nginx
docker run -itd --name nginx -p 8080:80 nginx
#切回本地
eval $(docker-machine env -u)
执行完成后验证:
注:现在 Docker 主推 Docker Desktop,Docker Machine 已经被弃用了,不过对于 20 之前的版本,还是可以使用的
三、Linux离线安装
上述安装步骤都基于有网的情况下,云上机子一般都无法联网,所以这里重点聊下离线安装
- 下载tgz包
先去官网下载tgz包,这里选择的是 20.10.5 版本(根据自己实际需求选择)
- 解压文件
tar -zxvf docker-20.10.5.tgz
- 移动到对应目录
cp docker/* /usr/bin/
- 配置阿里镜像加速
由于Docker是外国人的东西,所以仓库默认连的是外网,需要给它提提速。国内加速方式也挺多的,如:百度、阿里、交大等。这里就以阿里云的镜像加速器为例。如下:
步骤写的很清楚,跟着操作就是了,这里使用离线安装,还没有配置系统服务,后面两步先省略。如下:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["加速地址"]
}
EOF
注:截止今天,Docker Hub 已经无法访问了,国内镜像加速也陆续关闭,可试试下边的地址:
{"registry-mirrors": ["https://docker.m.daocloud.io","https://docker.nju.edu.cn","https://dockerproxy.com"]
}
- 启动并验证
现在只需要启动 Docker 即可,命令如下:
nohup dockerd &
Docker 已经启动完成,接着启动个 Nginx 验证一下。命令如下:
docker run -itd --name nginx -p 8080:80 nginx
通过ip:8080访问,如下:
- 注册系统服务
接着还需要把 Docker 注册为系统服务,方便 Linux 管理和启停
#写入service文件
tee /etc/systemd/system/docker.service <<- 'EOF'
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
Restart=on-failure[Install]
WantedBy=multi-user.target
EOF#设置开机自启
systemctl enable docker#启动docker
systemctl start docker
常见问题解答 (FAQ):
问 : 启动过程中遇到卡死的情况
答: 不妨看看防火墙有没有关
问: 启动过程中遇到:Job for docker.service failed because start of the service was attempted too often
答: systemctl reset-failed docker.service 尝试一下
问 : 遇到:Job for docker.service failed because the control process exited with error code.
See “systemctl status docker.service” and “journalctl -xeu docker.service” for details
答: 看下服务配置,如下:
vim /etc/systemd/system/docker.service#修改文件内容:
#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecStart=/usr/bin/dockerd#重新启动docker服务
systemctl daemon-reload
service dockerd restart
下边是原因,有兴趣的可以看下:
docker.sock 是 Docker 守护进程的通信接口,而 containerd.sock 是 containerd 的通信接口。两者在功能和使用场景上有所不同。docker.sock是一个完整的容器平台,包括了容器运行时、镜像管理、网络和存储等多个方面的功能,而 containerd.sock 则更加专注于容器的生命周期管理。因此,在选择使用哪个套接字时,取决于你的具体需求和应用场景
问 : XXXX
答: 如果还是不行,那只能重启了
四、Ansible批量安装
在集群情况,不可能一台台的离线安装过去,所以,需要借助一些工具进行批量部署。这里借助自动化部署工具——Ansible
Ansible 最好在 Linux 环境下执行,Windows 一路火花带闪电。关于 Ansible 的相关概念这里就不细说了,这里主要了解 剧本、清单 即可。剧本是指目标主机要执行的操作,清单即要操作的机子 。下边来一起实操一下就明白了
- 安装 Ansible
老样子,第一步需要先安装 Ansible,默认情况下,直接 执行pip install ansible
安装可能会提示 bash: pip: command not found… ,执行如下步骤:
#根据自己Python版本进行修改
curl -O https://bootstrap.pypa.io/pip/2.7/get-pip.py
#安装pip
python get-pip.py
#安装Ansible,根据python版本选择
pip install ansible==2.9.10#验证
ansible --version
- 配置 SSH
Ansible 在操作之前也需要先配置下 SSH:
#生成key,遇到提示,直接回车即可
ssh-keygen
#传输给远程机子
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.233.139
- 准备资源
这些是 Docker 相关的资源包,在部署之前需要提前准备
docker-20.10.5.tgz 可以去 官网 下载,docker-compose 可以去 这里 下载,docker 命令补全在 这里
daemon.json 配置文件,如下:
{"registry-mirrors": ["https://docker.m.daocloud.io","https://docker.nju.edu.cn","https://dockerproxy.com"],"insecure-registries": ["192.168.233.136:8080"],"exec-opts": ["native.cgroupdriver=systemd"]
}
docker.service 服务配置文件,如下:
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
Restart=on-failure[Install]
WantedBy=multi-user.target
- 配置连接信息
准备好资源后,接下来就是配置 Ansible 相关的内容,首先配置 Ansible 连接目标主机的用户、端口等信息,添加 ansible.cfg 文件。内容如下:
[defaults]
hostfile = hosts
remote_user = root
remote_port = 22
host_key_checking = False
- 配置 主机清单
接着配置需要操作的主机,添加 hosts 文件,配置如下:
[docker_hosts]
192.168.233.139
- 编写剧本
最后就是最重要的部分——剧本,剧本 指定了所有的操作,添加 docker-install.yml 文件如下:
---
- name: 安装dockerhosts: docker_hostsvars_prompt:- name: "install_docker"prompt: "Do you want to install Docker? (yes/no)"private: nobecome: yestasks:- name: 安装dockerblock: - name: 上传docker tar包synchronize:src: docker-20.10.5.tgzdest: /tmp/docker-20.10.5.tgz- name: 解压docker tar包ansible.builtin.unarchive:src: /tmp/docker-20.10.5.tgzdest: /tmpremote_src: yes- name: 上传docker-composesynchronize:src: docker-composedest: /tmp/docker/- name: 设置 docker 执行权限file:path: /tmp/docker/ # 这里替换成你的脚本路径recurse: yesmode: "u+x,g+x,o+x"- name: 移动docker到系统目录shell: mv -f /tmp/docker/* /usr/bin/- name: 上传 daemon.json 配置文件synchronize:src: daemon.jsondest: /etc/docker/- name: 上传 Docker 服务配置文件synchronize:src: docker.servicedest: /etc/systemd/system/- name: 关闭防火墙service:name: firewalldstate: stoppedwhen: ansible_service_mgr == 'systemd'- name: 永久禁用防火墙service:name: firewalldenabled: nowhen: ansible_service_mgr == 'systemd'- name: 临时开启宽容模式shell: setenforce 0- name: 永久开启宽容模式replace:path: /etc/selinux/configregexp: '^SELINUX=.*'replace: 'SELINUX=permissive'- name: 设置 Docker 服务开机自动systemd:name: dockerenabled: yes- name: 启动 Docker 服务service:name: dockerstate: startedwhen: install_docker == "yes"- name: 添加docker提示脚本block: - name: 上传 Docker 提示脚本synchronize:src: dockerdest: /etc/bash_completion.d- name: 使提示脚本生效lineinfile:path: ~/.bashrcline: "source /etc/bash_completion.d/docker"create: yesstate: present
- 部署
最后只要执行部署命令即可,如下:
ansible-playbook -i hosts docker-install.yml
执行完成后,目标机子已经安装好 Docker 了
补充——root权限被回收
环境已经差不多了,root权限 也要被收回了,之后只能使用普通用户进行操作。这就涉及到 Docker权限 问题,由于之前没有指定用户,从 容器 内部挂载出来的目录都是 root权限,普通用户是没有权限进行操作的,而且 容器 权限太高,有可能使主机被攻击。这又成了一个不得不解决的问题。先演示一下问题,还是用之前的YAML为例:
#删除原来nginx的日志路径
rm -rf /usr/local/docker/nginx/logs/
#赋予用户权限
chmod 777 /usr/bin/docker-compose
chmod 777 /var/run/docker.sock
#切换用户
su hqd
#启动
docker-compose -f docker-demo.yml up -d
可以看到,就算是用hqd用户启动,容器 内映射到宿主机的路径也是 root用户,这样 hqd用户 没权限进行任何操作
幸运的是,Docker 官方也意识到了这点,并提供了解决方案——用户命名空间。用户命名空间 简单来说:就是用户映射,容器 内部依旧是root用户操作,而 容器 内的 root,实际上是宿主机的普通用户。像是地方长官在地方是老大,但是到了京城,最大的还得是皇帝
接着看下如何指定用户命名空间:
- 映射从属用户和组 ID
先查看下需要指定用户的id和组id,这里我指定的用户是hqd:
id hqd
这里用户id和组id都是1000,先记下,后边要用到
配置 /etc/subuid 和 /etc/subgid :
#1000就是上边查到的用户id
cat >> /etc/subuid <<-'EOF'
hqd:1000:1
hqd:100000:65536
EOF#1000就是上边查到的组id
cat >> /etc/subgid <<-'EOF'
hqd:1000:1
hqd:100000:65536
EOF
这里配置需要注意,由于这里的 subuid 和 subgid 是空的,所以可以直接写入,如果原本已经存在值需要往下递推,下边是个例子:
a:100000:65536#165536 = 100000 + 65536
b:165536:65536#231072 = 165536 + 65536
c:231072:65536#296608 = 231072 + 65536
hqd:1000:1
hqd:296608:65536
如果是 CentOS7,则需要下边配置:
#CentOS需要下边配置
echo "user.max_user_namespaces=15000" >> /etc/sysctl.confgrubby --args="namespace.unpriv_enable=1 user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"reboot
否则会出现下边错误:
- 启用 userns-remap
修改 /etc/docker/daemon.json 文件,如下:
{"registry-mirrors": ["加速地址"],//这里配置是让docker信任该地址,否则会提示https安全问题"insecure-registries":["harbor-ip:8080","nexus-ip:8082","registry-ip:5000"]"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"],//这里配置用户名:组名"userns-remap": "hqd:hqd"
}
开始测试:
systemctl daemon-reload
systemctl restart docker
#删除原有nginx日志
rm -rf /usr/local/docker/nginx/logs
#赋予docker相关命令权限
chmod 777 /usr/bin/docker*
#赋予docker.sock权限
chmod 777 /var/run/docker.sock
#切换成hqd用户
su hqd
#启动
docker-compose -f docker-demo.yml up -d
可以看到,logs 文件夹已经变成了 hqd 用户所有了
用户命名空间已知限制,以下标准Docker功能与在启用了用户命名空间的情况下运行Docker守护程序不兼容:
- 与主机(–pid=host或–network=host)共享PID或NET名称空间
- 外部(卷或存储)驱动程序,这些驱动程序不知道或无法使用守护程序用户映射
- –privileged在docker run未指定的情况下 使用mode标志–userns=host
用户名称空间是一项高级功能,需要与其他功能配合。例如,如果从主机装载了卷,则必须预先安排文件所有权,需要对卷内容的读取或写入访问权限
尽管用用户命名空间的容器进程中的root用户具有该容器内超级用户的许多预期特权,但Linux内核基于内部知识(这是一个用用户命名空间的过程)施加了限制。一个值得注意的限制是无法使用该mknod命令。由root用户运行时,在容器内创建设备的权限被拒绝
用 k8s 不能添加上述操作,不过到时候又另外的解决办法,这里权且列出来,了解一下
总结
这里大致介绍了一些已知的 Docker 部署方式,如果还有其他更方便方式,欢迎大家进行补充