03. DOCKER - 服务安装
系统初始化
准备测试虚拟机一台,具体配置如下:
主机名 | IP 地址 | 系统版本 | 内存(G) | CPU(核) | 硬盘(G) |
---|---|---|---|---|---|
node-01 | 192.168.200.101 | CentOS Linux release 7.9.2009 | 4 | 4 | 20 |
关闭防火墙和 Selinux
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭 Selinux
sed -i "s#^SELINUX=.*#SELINUX=disabled#g" /etc/selinux/config
setenforce 0
# 关闭 swap 分区
swapoff -a && sysctl -w vm.swappiness=0
sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab
配置 yum 源(云服务器不需要)
# 备份旧的 yum 源
cd /etc/yum.repos.d/
mkdir backup-$(date +%F)
mv *repo backup-$(date +%F)
# 添加阿里云 yum 源
curl http://mirrors.aliyun.com/repo/Centos-7.repo -o ali.repo
安装基础依赖
# 安装 epel 源
yum -y install epel-release
yum clean all
yum makecache
# 安装常用依赖
yum -y install gcc glibc gcc-c++ make cmake net-tools screen vim lrzsz tree dos2unix lsof \
tcpdump bash-completion wget ntp setuptool openssl openssl-devel bind-utils traceroute \
bash-completion bash-completion-extras glib2 glib2-devel unzip bzip2 bzip2-devel libevent libevent-devel \
ntp expect pcre pcre-devel zlib zlib-devel jq psmisc tcping yum-utils device-mapper-persistent-data \
lvm2 git device-mapper-persistent-data bridge-utils container-selinux binutils-devel \
ncurses ncurses-devel elfutils-libelf-devel
# 升级服务器
yum update
时间同步(云服务器不需要)
echo "# 互联网时间同步" >> /var/spool/cron/root
echo "*/5 * * * * /usr/sbin/ntpdate time2.aliyun.com >/dev/null 2>&1" >> /var/spool/cron/root
打开文件数优化
cat >> /etc/security/limits.conf << EOF
# 打开文件优化配置
* soft nofile 655360
* hard nofile 655350
* soft nproc 655350
* hard nproc 655350
* soft memlock unlimited
* hard memlock unlimited
EOF
内核优化
cat >> /etc/sysctl.d/user.conf << EOF
# 内核调优
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
fs.may_detach_mounts = 1
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
fs.file-max=52706963
fs.nr_open=52706963
net.netfilter.nf_conntrack_max=2310720
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl =15
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_orphans = 327680
net.ipv4.tcp_orphan_retries = 3
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.ip_conntrack_max = 65536
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_timestamps = 0
net.core.somaxconn = 16384
EOF
内核升级
docker 对于 CentOS 的要求为内核版本不低于 3.10
,尽管 7.9 已经是 3.10 版本,但还是有升级的必要。
同时作为生产环境,一般不会选择安装最新版本。但官方仓库中提供的 rpm 一般只会有一个 lt 和一个 ml 版本,所以需要从第三方下载想要的版本,统一服务器的内核版本,可以避免出现未知 BUG。
本次使用的是 4 版本最后一版:4.20
# 下载内核 rpm 包
cd /usr/local/src/
wget http://193.49.22.109/elrepo/kernel/el7/x86_64/RPMS/kernel-ml-4.20.13-1.el7.elrepo.x86_64.rpm
wget http://193.49.22.109/elrepo/kernel/el7/x86_64/RPMS/kernel-ml-devel-4.20.13-1.el7.elrepo.x86_64.rpm
# 安装内核
yum -y localinstall kernel-ml-*
# 查看顺序
awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
# 设置默认启动内核,上面的命令可以看到最新内核的序号是 0
grub2-set-default 0
# 重启系统
reboot
系统启动完成之后,查看内核情况:
uname -r
到此,系统初始化完成!
安装包准备
docker 目前有三种版本可供选择:nightly(开发版)
,test(测试版)
,stable(稳定版)
。
对于生产环境,为了避免因为版本不同导致集群出现未知 BUG,建议手动下载 rpm 包安装。本次安装版本为 20.10.9
,下载地址:
https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
如果觉得下载慢,可以使用国内的镜像地址:
http://mirrors.ustc.edu.cn/docker-ce/linux/centos/7/x86_64/stable/Packages/
需要下载的安装包如下:
- docker-ce-20.10.9-3.el7.x86_64.rpm(docker 引擎)
- docker-ce-cli-20.10.9-3.el7.x86_64.rpm(docker 引擎的命令行)
- containerd.io-1.6.6-3.1.el7.x86_64.rpm(守护进程,独立于 docker 工作,管理容器的生命周期)
- docker-ce-rootless-extras-20.10.9-3.el7.x86_64.rpm(ce 需要的依赖)
- docker-scan-plugin-0.9.0-3.el7.x86_64.rpm(cli 需要的依赖)
服务安装
事先将下载的安装包上传到 /usr/local/src/
目录然后开始进行安装。
# 卸载可能存在的旧版本 docker
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 安装新版本
cd /usr/local/src/
yum -y localinstall docker* containerd*
# 启动 docker
systemctl start docker
systemctl enable docker
systemctl status docker
查看 docker 信息:
docker version
结果如下:
服务优化
由于 docker 默认的 registry 是 docker hub,而 docker hub 又是外网的服务,可能因为网络原因访问,下载都会非常慢。所以需要将 registry 调整为国内的。
国内常用的 registry 有以下一些:
- 阿里云(需要注册用户):
https://<你的ID>.mirror.aliyuncs.com
- 网易:
http://hub-mirror.c.163.com
- 中科大:
https://docker.mirrors.ustc.edu.cn
通过增加配置来修改 docker 默认的 registry 地址:
# 创建 docker 数据目录
mkdir -p /ops/{data,service,log,backup,shell,package}
mkdir -p /ops/data/docker/{run,lib}
# 修改配置文件
# exec-opts:调整 docker 为 systemd 管理
# registry-mirrors:设置注册点
# bip:修改 docker 的网段
# exec-root:重新定义 docker 的运行目录
# data-root:重新定义 docker 的数据目录
cat > /etc/docker/daemon.json << EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"],
"bip": "172.16.0.1/16",
"exec-root": "/ops/data/docker/run",
"data-root": "/ops/data/docker/lib"
}
EOF
# 重启 docker
systemctl stop docker
systemctl start docker
systemctl status docker
如果不清楚网段划分,可以使用工具查看:
重启完成后查看 docker 信息:
docker info
如图所示:
故障排查
docker 在停止的时候可能会出现提醒:
Warning: Stopping docker.service, but it can still be activated by: docker.socket
告警的意思为:如果你试图连接到 docker socket,而 docker 服务没有运行,系统将自动启动 docker。
该配置是在 /lib/systemd/system/docker.service
中配置的:
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
所以这个告警可以忽略掉。
重启失败,大概可能是 /etc/docker/daemon.json 存在报错,可以通过错误日志查看信息:
tail -1000f /var/log/messages
故障问题 1
unable to configure the Docker daemon with file /etc/docker/daemon.json: invalid character 'Â' looking for beginning of value
查看配置文件没有问题,但是一直这个错误,所以我怀疑里面的 tab 或者空格存在问题,通过执行命令:
cat -A /etc/docker/daemon.json
发现文件中确实有很多特殊的字符,因为配置是网上复制的。通过将里面空格和 tab 替换成空格之后故障解决。
故障问题 2
unable to configure the Docker daemon with file /etc/docker/daemon.json: invalid character '}' looking for beginning of object key string
原因是我在 json 最后一个值后面也加了 ,
符号的缘故,删除了就好了。
daemon.json
配置文件 daemon.json
参数详解:
{
# 在引擎 API 中设置 CORS 标头
"api-cors-header": "",
# 要加载的授权插件
"authorization-plugins": [],
# 将容器附加到网桥
"bridge": "",
# 指定网桥 IP
"bip": "192.168.88.0/22",
# 为所有容器设置父 cgroup
"cgroup-parent": "",
# 分布式存储后端的 URL
"cluster-store": "",
# 设置集群存储选项(默认map [])
"cluster-store-opts": {},
# 要通告的地址或接口名称
"cluster-advertise": "",
# 启用调试模式,启用后,可以看到很多的启动信息。默认 false
"debug": true,
# 容器默认网关 IPv4 地址
"default-gateway": "",
# 容器默认网关 IPv6 地址
"default-gateway-v6": "",
# 容器的默认 OCI 运行时,默认为 runc
"default-runtime": "runc",
# 容器的默认 ulimit(默认[])
"default-ulimits": {},
# 设定容器 DNS 的地址,在容器的 /etc/resolv.conf 文件中可查看
"dns": ["192.168.1.1"],
# 容器 /etc/resolv.conf 文件,其他设置
"dns-opts": [],
# 设定容器的搜索域。
"dns-search": [],
# 运行时执行选项
"exec-opts": [],
# 执行状态文件的根目录,默认 /var/run/docker
"exec-root": "",
# 固定 IP 的 IPv4 子网
"fixed-cidr": "",
# 固定 IP 的 IPv6 子网
"fixed-cidr-v6": "",
# docker 运行时使用的根路径,默认 /var/lib/docker
"data-root": "/var/lib/docker",
# UNIX 接字的组,默认 docker
"group": "",
# 设置容器 hosts
"hosts": [],
# 启用容器间通信,默认 true
"icc": false,
# 绑定容器端口时的默认 IP,默认 0.0.0.0
"ip": "0.0.0.0",
# 启用 iptables 规则添加,默认 true
"iptables": false,
# 启用IPv6网络
"ipv6": false,
# 默认 true, 启用 net.ipv4.ip_forward
"ip-forward": false,
# 启用 IP 伪装,默认 true
"ip-masq": false,
# 设置私有仓库地址可以设为 http
"insecure-registries": ["120.123.122.123:12312"],
# docker 主机的标签
"labels": ["nodeName=node-101"],
# 在容器仍在运行时启用 docker 的实时还原
"live-restore": true,
# 容器日志的默认驱动程序,默认 json-file
"log-driver": "",
# 设置日志记录级别:"调试","信息","警告","错误","致命"
"log-level": "",
# 设置每个请求的最大并发下载量,默认 3
"max-concurrent-downloads": 3,
# 设置每次推送的最大同时上传数,默认 5
"max-concurrent-uploads": 5,
# 设置容器网络 MTU
"mtu": 0,
# 设置守护程序的 oom_score_adj,默认 -500
"oom-score-adjust": -500,
# Docker 守护进程的 PID 文件
"pidfile": "",
# 全时间戳机制
"raw-logs": false,
# 设置镜像加速
"registry-mirrors": ["https://192.498.89.232:89"],
# 启用 selinux 支持,默认 false
"selinux-enabled": false,
# 要使用的存储驱动程序
"storage-driver": "",
# 设置默认地址或群集广告地址的接口
"swarm-default-advertise-addr": "",
# 启动 TLS 认证开关,默认 false
"tls": true,
# 通过 CA 认证过的 certificate 文件路径,默认 ~/.docker/ca.pem
"tlscacert": "",
# TLS 的 certificate 文件路径,默认 ~/.docker/cert.pem
"tlscert": "",
# TLS 的 key 文件路径,默认 ~/.docker/key.pem
"tlskey": "",
# 使用 TLS 并做后台进程与客户端通讯的验证,默认 false
"tlsverify": true,
# 使用 userland 代理进行环回流量,默认 true
"userland-proxy": false,
# 用户名称空间的用户/组设置
"userns-remap": "",
# 存储驱动程序选项
"storage-opts": [
"overlay2.override_kernel_check=true",
"overlay2.size=15G"
],
# 容器默认日志驱动程序选项
"log-opts": {
"max-file": "3",
"max-size": "10m",
},
}