构建以普通用户启动的keepalived镜像
参考文档 :
- keepalived-non-root.service
https://sources.debian.org/src/keepalived/1%3A2.2.7-1/keepalived/keepalived-non-root.service.in/#:~:text=%23%20This%20systemd%20service%20file%20allows%20keepalived%20to,install%20the%20%23%20file%20in%20%2Fusr%2Flib%2Fsystemd%2Fsystem%20as%20keepalived.service - 高可用组件keepalived 如何以非root方式运行
https://blog.csdn.net/qq_15328161/article/details/130183713 - docker run命令参考手册
https://docs.docker.com/engine/containers/run/#runtime-privilege-and-linux-capabilities
1.构建镜像需要的文件 :
Dockerfile-multistage-non-root
# 用于构建镜像的Dockerfile(以普通用户启动keepalived)keepalived-2.2.8.tar.gz
# keepalived源码alpine:3.20.3.tar.gz
# 基于alpine 3.20.3的官方基础镜像config/keepalived.conf
# 运行keepalived所需的配置文件(构建镜像不需要,但运行keepalived时需要)
2.构建镜像
2.1 Dockerfile-multistage-non-root
的内容
如下是Dockerfile-multistage-non-root
的内容
# 多阶段构建keepalived镜像
# 基础镜像为alpine:3.20.3
# keepalived : 2.2.8
# 以非root用户启动keepalived (UID:1001)
# 构建镜像需要如下内容 :
# - alpine镜像 : alpine:3.20.3
# - keepalived源码 : keepalived-$KEEPALIVED_VERSION.tar.gz . 其中 : KEEPALIVED_VERSION为2.2.8
# - Dockerfile : 即本文 : Dockerfile-multistage-non-root
# 构建命令为 : docker buildx build -t keepalived:2.2.8-non-root -f Dockerfile-multistage-non-root .
# 第一阶段 : 构建keepalived
# 操作系统版本
ARG ALPINE_VERSION=3.20.3
FROM alpine:$ALPINE_VERSION AS build-keepalived
# ========如下为环境变量========
# 普通用户的HOME目录
ENV KA_HOME=/home/wht
# keepalived的源文件解压后的目录
ENV KA_SOURCE=/home/wht/keepalived-source
# keepalived编译后的目录
ENV KA_TARGET=/home/wht/keepalived
# 使用国内仓库(阿里云)
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
# KA的源码来自本地(需要将KA源码keepalived-${KEEPALIVED_VERSION}.tar.gz拷贝到image目录下)
ENV KEEPALIVED_VERSION=2.2.8
COPY keepalived-${KEEPALIVED_VERSION}.tar.gz ./keepalived.tar.gz
# 1.安装必要的包
# 2.创建普通用户
# 3.解压源码到$KA_SOURCE目录下
# 4.设置源码的owner为普通用户
RUN apk --no-cache add \
autoconf \
automake \
gcc \
ipset-dev \
iptables-dev \
libnfnetlink-dev \
libnl3-dev \
make \
musl-dev \
libnftnl-dev \
file-dev \
net-snmp-dev \
pcre2-dev \
networkmanager-dev \
libip4tc \
libip6tc \
openssl-dev \
&& adduser --uid 1001 --disabled-password wht \
&& mkdir -p $KA_SOURCE \
&& tar -xzf keepalived.tar.gz --strip 1 -C $KA_SOURCE \
&& chown wht -R $KA_SOURCE
WORKDIR $KA_SOURCE
# 指定运行keepalived的用户
USER wht
RUN ./autogen.sh \
&& ./configure --prefix=$KA_TARGET --disable-dynamic-linking --enable-bfd --enable-regex \
--enable-json --enable-log-file --enable-snmp --enable-snmp-vrrp \
&& make && make install
# =============================================================
# 第二阶段 : 构建keepalived镜像
ARG ALPINE_VERSION
FROM alpine:$ALPINE_VERSION
# 使用国内仓库(阿里云)
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
# ========如下为环境变量========
# 普通用户的HOME目录
ENV KA_HOME=/home/wht
# keepalived的源文件解压后的目录
ENV KA_SOURCE=/home/wht/keepalived-source
# keepalived编译后的目录
ENV KA_TARGET=/home/wht/keepalived
# 1.安装运行时需要的包(新增 libcap-setcap 包)
# 2.创建名为wht的用户(UID:1001)
# 3.创建目标目录且设置owner为普通用户
RUN apk --no-cache add \
ipset \
iptables \
libnfnetlink \
libnl3 \
openssl \
libnftnl \
file \
net-snmp \
pcre2 \
networkmanager \
libip4tc \
libip6tc \
libcap-setcap \
&& adduser --uid 1001 --disabled-password wht \
&& mkdir -p $KA_TARGET/sbin \
&& chown wht -R $KA_TARGET
# 拷贝上一构建阶段的结果(注意:目标目录必须以/结束)
COPY --from=build-keepalived --chown=wht $KA_TARGET $KA_TARGET/
# 为普通用户的keepalived设置cap_
RUN setcap 'cap_net_admin,cap_net_bind_service,cap_sys_module,cap_sys_nice,cap_sys_resource,cap_net_raw,cap_chown,cap_kill,cap_sys_admin=+ep' /home/wht/keepalived/sbin/keepalived
# 指定运行keepalived的用户
USER wht
WORKDIR $KA_TARGET
2.2 执行构建
docker buildx build -t keepalived:2.2.8-non-root -f Dockerfile-multistage-non-root .
#3.得到的镜像如下所示 :
如下为执行docker images
的输出结果
REPOSITORY TAG IMAGE ID CREATED SIZE
keepalived 2.2.8-non-root 1df79523a554 25 seconds ago 54.9MB
4.验证keepalived的版本
docker run --privileged --rm keepalived:2.2.8-non-root sbin/keepalived --version
说明 :
- 执行
docker run
命令需要使用--cap-add=ALL
或--privileged
,否则报错为exec sbin/keepalived: operation not permitted
- 可执行程序
keepalived
的完整路径是/home/wht/keepalived/sbin/keepalived
上述命令输出如下:
Keepalived v2.2.8 (04/04,2023), git commit v2.2.7-154-g292b299e+
Copyright(C) 2001-2023 Alexandre Cassen, <acassen@gmail.com>
Built with kernel headers for Linux 6.6.0
Running on Linux 5.14.0-325.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Jun 9 19:47:16 UTC 2023
Distro: Alpine Linux v3.20
configure options: --prefix=/home/wht/keepalived --disable-dynamic-linking --enable-bfd --enable-regex --enable-json --enable-log-file --enable-snmp --enable-snmp-vrrp
Config options: LIBIPSET NFTABLES LVS REGEX VRRP VRRP_AUTH VRRP_VMAC JSON BFD OLD_CHKSUM_COMPAT SNMP_VRRP SNMP_CHECKER FILE_LOGGING LOG_FILE_APPEND INIT=systemd
System options: VSYSLOG MEMFD_CREATE IPV6_MULTICAST_ALL IPV4_DEVCONF LIBNL3 RTA_ENCAP RTA_EXPIRES RTA_NEWDST RTA_PREF FRA_SUPPRESS_PREFIXLEN FRA_SUPPRESS_IFGROUP FRA_TUN_ID RTAX_CC_ALGO RTAX_QUICKACK RTEXT_FILTER_SKIP_STATS FRA_L3MDEV FRA_UID_RANGE RTAX_FASTOPEN_NO_COOKIE RTA_VIA FRA_PROTOCOL FRA_IP_PROTO FRA_SPORT_RANGE FRA_DPORT_RANGE RTA_TTL_PROPAGATE IFA_FLAGS LWTUNNEL_ENCAP_MPLS LWTUNNEL_ENCAP_ILA IPTABLES NET_LINUX_IF_H_COLLISION NETINET_LINUX_IF_ETHER_H_COLLISION LIBIPVS_NETLINK IPVS_DEST_ATTR_ADDR_FAMILY IPVS_SYNCD_ATTRIBUTES IPVS_64BIT_STATS IPVS_TUN_TYPE IPVS_TUN_CSUM IPVS_TUN_GRE VRRP_IPVLAN IFLA_LINK_NETNSID INET6_ADDR_GEN_MODE VRF SO_MARK
5.启动keepalived
假设将keepalived
部署到/storage/keepalived
目录下
目录的结构如下所示 :
/storage/keepalived
├── config
│ └── keepalived-non-root.conf
├── logs
├── pid
└── start-keepalived-non-root.sh
5.1 运行环境为 :
操作系统 : centos9 stream
Docker版本 : docker-ce 27.1.1
5.2 创建目录且设置目录的owner为1001 :
mkdir -p /storage/keepalived/{config,logs,pid}
chown 1001 -R /storage/keepalived
5.3 脚本start-keepalived-non-root.sh
的内容如下:
# keepalived:2.2.8-non-root镜像中指定了启动keepalived的用户为UID 1001
# 因此启动容器需要某些特权
# 停止并删除原容器
docker rm -f keepalived
# 如果存在PID文件,则删除
if [ -f /storage/keepalived/pid/keepalived.pid ]; then
rm /storage/keepalived/pid/keepalived.pid
fi
if [ -f /storage/keepalived/pid/keepalived-vrrp.pid ]; then
rm /storage/keepalived/pid/keepalived-vrrp.pid
fi
# 镜像keepalived:2.2.8-non-root的SHA256/IMAGE ID为3aa2e3fa1acc
#
# 这些cap暂时未设置 : --cap-add=CHOWN --cap-add=KILL --cap-add=SETUID --cap-add=SETGID
# 如下文件都是相对路径,即WORKDIR为/home/wht/keepalived. --log-file必须指定日志文件的全路径
docker run -d \
--net=host \
--restart always \
--name keepalived \
--cap-add=NET_ADMIN --cap-add=SYS_MODULE --cap-add=SYS_NICE --cap-add=SYS_RESOURCE \
--cap-add=NET_RAW --cap-add=NET_BIND_SERVICE --cap-add=SYS_ADMIN \
-v /storage/keepalived/config/keepalived-non-root.conf:/home/wht/keepalived/config/keepalived-non-root.conf \
-v /storage/keepalived/logs:/home/wht/keepalived/logs \
-v /storage/keepalived/pid:/home/wht/keepalived/pid \
-v /etc/localtime:/etc/localtime \
keepalived:2.2.8-non-root sbin/keepalived --vrrp --use-file=config/keepalived-non-root.conf \
--log-file=/home/wht/keepalived/logs/keepalived.log --log-console --log-detail --dont-fork \
--pid=pid/keepalived.pid --vrrp_pid=pid/keepalived-vrrp.pid
5.4 config/keepalived-non-root.conf
的内容如下 :
! Configuration File for keepalived
# 参考文档 : https://www.keepalived.org/manpage.html
# Global definitions
global_defs {
router_id LVS_DEVEL
max_auto_priority 5
# sets the default interface for static addresses.
# (default: eth0)
default_interface ens160
# Set the default VRRP version to use
# (default: 2, but IPv6 instances will use version 3)
vrrp_version 3
}
vrrp_instance VI_1 {
# MASTER or BACKUP
state MASTER
# 网卡
interface ens160
virtual_router_id 51
# 选择MASTER时,高优先级赢.要称为MASTER,则优先级比其他高50+
priority 150
advert_int 1
# VIP地址
virtual_ipaddress {
192.168.132.110
}
}
说明 :
- 1.上面为
master
状态的配置文件。如果是backup
状态的配置文件,只需将MASTER
改为BACKUP
- 2.状态为
backup
的配置文件的priority
的值要低于150 - 3.修改
interface
为网卡名称 - 4.修改VIP地址
5.5 启动后,在logs
目录下生成日志文件
keepalived.log
keepalived_vrrp.log
5.6 查看VIP地址是否生效
执行ip addr show
,看相应网卡是否出现了VIP地址