基于Swarm、Portainer、Jenkins,打造小型容器化DevOps(一)
前言:新坑指南:在小型公司里,部署k8s技术和运维都没到要求,又想体会容器带来的遍历可以试试这个方案。虚拟机环境hostnameipOSdescprod-master-7010.10.10.70CentOS Linux release 7.2.1511 (Core)prod-master-7110.10.10.71CentOS Linux release 7.2.1511 (Core)...
·
前言:
新坑指南:在小型公司里,部署k8s技术和运维都没到要求,又想体会容器带来的遍历可以试试这个方案。
虚拟机环境
hostname | ip | OS | desc |
prod-master-70 | 10.10.10.70 | CentOS Linux release 7.2.1511 (Core) | |
prod-master-71 | 10.10.10.71 | CentOS Linux release 7.2.1511 (Core) | |
prod-worker-72 | 10.10.10.72 | CentOS Linux release 7.2.1511 (Core) | |
prod-worker-73 | 10.10.10.73 | CentOS Linux release 7.2.1511 (Core) | |
prod-worker-74 | 10.10.10.74 | CentOS Linux release 7.2.1511 (Core) | |
prod-master-75 | 10.10.10.75 | CentOS Linux release 7.2.1511 (Core) | |
prod-worker-76 | 10.10.10.76 | CentOS Linux release 7.2.1511 (Core) | |
prod-master-77 | 10.10.10.77 | CentOS Linux release 7.2.1511 (Core) | |
prod-worker-20 | 10.10.10.20 | CentOS Linux release 7.6.1810 (Core) | |
prod-worker-16 | 192.168.100.16 | CentOS Linux release 7.6.1810 (Core) | |
prod-master-17 | 192.168.100.17 | CentOS Linux release 7.6.1810 (Core) |
基础环境准备
配置yum源
由于同时操作主机比较多,若是分别的登录主机会比较麻烦,Ansible挺好挺强大,奈何刚开始看,就自己写了个批量远程操作脚本,后续操作都是基于这个脚本
auto-ssh-remote.sh
#!/bin/bash
nuts::isUbuntu() {
[[ -n "$(command -v "apt")" ]] && echo "ubuntu"
}
nuts::isCentOS() {
[[ -n "$(command -v "yum")" ]] && echo "centos"
}
#
## 生成当前控制主机的SSH秘钥对
## 若存在,则不覆盖
#
nuts::autoGenerateSSHKey() {
echo "_>: begin generate ssh key..."
expect <<EOF
set timeout -1
spawn ssh-keygen -t rsa -f $HOME/.ssh/id_dsa
expect {
"Overwrite" { send "n\n"; exp_continue }
"passphrase" { send "\n"; exp_continue }
}
EOF
echo ''
}
#
## 与指定HOST主机建立SSH免秘钥登录
## 读取相同目录下${host}_${user}文件中的HOST密码,
## 若不存在${host}_${user}文件,读取相同目录下password文件中的HOST密码,这里存储的是统一默认密码
## 若不存在password文件,则提示手动输入HOST密码
## 并缓存到.nuts_cache/文件夹下,并在最后清除
#
nuts::autoCopySSHKeyToHosts() {
local host=${1:?"[${FUNCNAME}] 需要免密登录的HOST主机名/地址!"'$1:host HOST主机名/地址' }
local port=${2:?"[${FUNCNAME}] 需要免密登录的HOST的SSH端口!"'$2:port HOSTSSH端口' }
local user=${3:?"[${FUNCNAME}] 需要免密登录的HOST的user账户!"'$3:user user账户' }
shift
echo "_>: begin copy local ssh pubkey to $user@$host:$port..."
unset passwd
[[ -f ${host}_${user} ]] && : ${passwd:=$(cat ${host}_${user})}
[[ -z $passwd ]] && [[ -f password ]] && : ${passwd:=$(cat password)}
[[ -z $passwd ]] && read -p "_>: Please input $host login $user's password:" -s passwd
# cache password to local .nuts_cache/${host}_${user}
mkdir -p $HOME/.nuts_cache/
echo $passwd >$HOME/.nuts_cache/${host}_${user}
expect <<EOF
set timeout -1
spawn ssh-copy-id -i $HOME/.ssh/id_dsa -p $port $user@$host
expect {
"password" { send "$passwd\n"; exp_continue }
"connecting" { send "yes\n"; exp_continue }
}
EOF
unset passwd
echo ''
}
#
## 从hosts文件中读取需要配置的HOST主机列表
## 格式 ip:port:user
#
nuts::loadHostList() {
local hostList=$(grep "^[0-9]\{0,3\}\.[0-9]\{0,3\}\.[0-9]\{0,3\}\.[0-9]\{0,3\}:[0-9]\{1,5\}:.*" hosts)
[[ -z $hostList ]] && ${2?"[${FUNCNAME}] 需要免密登录的HOST主机信息!"'$2:hostList HOST信息' }
echo $hostList
}
#
## 在hosts主机列表中执行指定函数
#
nuts::runFunctionNoCmd() {
local funcs=${1:?"[${FUNCNAME}] 需要调用的函数名称!"'$1:funcs 函数名称列表' }
local hostList=$(nuts::loadHostList)
for hostInfo in $hostList; do
local tmp=${hostInfo%:*}
for curFunc in $*; do
echo "_>: begin run function [$curFunc] no CMD on host list..."
$curFunc "${hostInfo%%:*}" "${tmp#*:}" "${hostInfo##*:}"
echo ''
done
done
echo ''
}
#
## 在hosts主机列表中执行指定函数
#
nuts::runFunctionWithCmd() {
local func=${1:?"[${FUNCNAME}] 需要调用的函数名称!"'$1:func 函数名称' }
shift 1
local params=${1:?"[${FUNCNAME}] 需要调用的函数参数!"'$2:params 函数参数列表' }
local i=0
local num=$#
unset __NUTS_CACHE_CMD
declare -g __NUTS_CACHE_CMD=()
while [[ $i -lt $num ]]; do
__NUTS_CACHE_CMD[$i]="$1"
shift 1
i=$(expr $i + 1)
done
__nuts::runFunctionWithCmd $func
}
__nuts::runFunctionWithCmd() {
local func=${1:?"[${FUNCNAME}] 需要调用的函数名称!"'$1:func 函数名称' }
local hostList=$(nuts::loadHostList)
for hostInfo in $hostList; do
local tmp=${hostInfo%:*}
echo "_>: begin run function [$func] with CMD on host list..."
$func "${hostInfo%%:*}" "${tmp#*:}" "${hostInfo##*:}" "__NUTS_CACHE_CMD"
echo ''
done
echo ''
}
#
## 拷贝文件到指定Host的$HOME/.nuts_cache/中
## 读取相同目录下${host}_${user}文件中的HOST密码,
## 若不存在${host}_${user}文件,读取相同目录下password文件中的HOST密码,这里存储的是统一默认密码
## 若不存在password文件,则提示手动输入HOST密码
## 需要手动清除
#
nuts::copyFilesToRemote() {
local host=${1:?"[${FUNCNAME}] 需要免密登录的HOST主机名/地址!"'$1:host HOST主机名/地址' }
local port=${2:?"[${FUNCNAME}] 需要免密登录的HOST的SSH端口!"'$2:port HOSTSSH端口' }
local user=${3:?"[${FUNCNAME}] 需要免密登录的HOST的user账户!"'$3:user user账户' }
local source=${4:?"[${FUNCNAME}] 需要远程拷贝的本地文件!"'$4:source source文件' }
shift
echo "_>: begin copy local files to $user@$host:$port..."
ssh -p $port $user@$host "mkdir -p $HOME/.nuts_cache/;"
[[ $source == "__NUTS_CACHE_CMD" ]] && source=${__NUTS_CACHE_CMD[0]}
scp -P $port -r $source $user@$host:$HOME/.nuts_cache/
}
#
## 在远程Host上执行command
#
nuts::remoteExec() {
local host=${1:?"[${FUNCNAME}] 需要免密登录的HOST主机名/地址!"'$1:host HOST主机名/地址' }
local port=${2:?"[${FUNCNAME}] 需要免密登录的HOST的SSH端口!"'$2:port HOSTSSH端口' }
local user=${3:?"[${FUNCNAME}] 需要免密登录的HOST的user账户!"'$3:user user账户' }
local command=${4:?"[${FUNCNAME}] 需要远程执行的SHELL命令!"'$4:command SHELL命令' }
shift
echo "_>: begin run command on remote $user@$host:$port..."
local i=0
local num=${#__NUTS_CACHE_CMD[*]}
while [[ $i -lt $num ]]; do
local command=${__NUTS_CACHE_CMD[$i]}
echo $(expr $i + 1) $num $command
ssh -p $port $user@$host "$command"
i=$(expr $i + 1)
done
}
#
## 在远程Host上使用sudo执行command
#
nuts::remoteSudoExec() {
local host=${1:?"[${FUNCNAME}] 需要免密登录的HOST主机名/地址!"'$1:host HOST主机名/地址' }
local port=${2:?"[${FUNCNAME}] 需要免密登录的HOST的SSH端口!"'$2:port HOSTSSH端口' }
local user=${3:?"[${FUNCNAME}] 需要免密登录的HOST的user账户!"'$3:user user账户' }
local command=${4:?"[${FUNCNAME}] 需要远程执行的SHELL命令!"'$4:command SHELL命令' }
shift
echo "_>: begin run sudo command on remote $user@$host:$port..."
local i=0
local num=${#__NUTS_CACHE_CMD[*]}
ssh -p $port $user@$host "mkdir -p $HOME/.nuts_sudo/"
scp -P $port -r $HOME/.nuts_cache/${host}_${user} $user@$host:$HOME/.nuts_sudo/
while [[ $i -lt $num ]]; do
local command=${__NUTS_CACHE_CMD[$i]}
echo $(expr $i + 1) $num $command
ssh -p $port $user@$host "cat $HOME/.nuts_sudo/${host}_${user}|sudo -S $command"
i=$(expr $i + 1)
done
ssh -p $port $user@$host "rm -rf $HOME/.nuts_sudo/"
}
#
## 自动SSH免密登录
#
nuts::initialization() {
if [[ $(nuts::isUbuntu) == "ubuntu" ]]; then
echo "initializing base environment..."
sudo apt install -y expect ansible
fi
if [[ $(nuts::isCentOS) == "centos" ]]; then
echo "initializing base environment..."
sudo yum install -y expect ansible
fi
echo ''
nuts::autoGenerateSSHKey
# nuts::autoCopySSHKeyToHosts "172.16.1.182" "22" "wntime"
nuts::runFunctionNoCmd "nuts::autoCopySSHKeyToHosts"
}
#
## 清除缓存文件夹
#
nuts::clearRuntime() {
# 清除缓存文件夹.nuts_cache/
[[ -d $HOME/.nuts_cache/ ]] && rm -rf $HOME/.nuts_cache/
}
#########################################################################################################
if [[ $# -gt 0 ]]; then
i=0
num=$#
unset __NUTS_CACHE_CMD
declare -g __NUTS_CACHE_CMD=()
while [[ $i -lt $num ]]; do
__NUTS_CACHE_CMD[$i]="$1"
shift 1
i=$(expr $i + 1)
done
__nuts::runFunctionWithCmd "nuts::remoteExec"
else
# 自动SSH免密登录
nuts::initialization
# 自动SUDO免密,执行有风险
# nuts::runFunctionWithCmd "nuts::remoteSudoExec" \
# "sed -i '/%sudo.*ALL=(ALL:ALL).*ALL/a ubuntu\tALL=(ALL:ALL)\tNOPASSWD:ALL' /etc/sudoers" \
# "sed -i '/root.*ALL=(ALL).*ALL/a wntime\tALL=(ALL)\tNOPASSWD:ALL' /etc/sudoers"
# 配置自定义环境变量
nuts::runFunctionWithCmd "nuts::remoteExec" \
"[[ -n \"$(command -v 'apt')\" ]] && sed -i \"s/^alias ll='ls -alF'/alias ll='ls -lvh --color=auto'/g\" $HOME/.bashrc" \
"[[ -n \"$(command -v 'apt')\" ]] && sed -i \"s/^alias la='ls -A'/alias la='ls -alvh --color=auto'/g\" $HOME/.bashrc" \
\
"[[ -n \"$(command -v 'yum')\" ]] && sed -i \"/alias ll='ls -lvh --color=auto'/d\" $HOME/.bashrc" \
"[[ -n \"$(command -v 'yum')\" ]] && sed -i \"/alias la='ls -lavh --color=auto'/d\" $HOME/.bashrc" \
"[[ -n \"$(command -v 'yum')\" ]] && echo \"alias ll='ls -lvh --color=auto'\" >>$HOME/.bashrc" \
"[[ -n \"$(command -v 'yum')\" ]] && echo \"alias la='ls -lavh --color=auto'\" >>$HOME/.bashrc" \
". $HOME/.bashrc"
# 清除缓存文件夹
nuts::clearRuntime
fi
使用185作为控制主机:
[wntime@master-185 ~]$ chmod +x auto-ssh-remote.sh
[wntime@master-185 ~]$ ll
total 28K
-rw-rw-r--. 1 wntime wntime 14 Jun 10 15:22 10.10.10.20_wntime #特定主机用户的密码
-rwxrwxr-x. 1 wntime wntime 8.9K Jun 23 16:46 auto-ssh-remote.sh #多主机远程执行脚本
-rw-rw-r--. 1 wntime wntime 534 Jul 2 14:54 hosts #主机ssh列表,格式:ip:port:user
-rw-rw-r--. 1 wntime wntime 15 Jun 10 17:09 password #若密码都一样,则只需要一个password文件存放密码就可以了
[wntime@master-185 ~]$
# 执行初始化,控制主机181到各个服务器的单向免秘钥登录
[wntime@master-185 ~]$ ./auto-ssh-remote.sh
initializing base environment...
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
extras/7/x86_64/primary_db | 242 kB 00:00:00
Package expect-5.45-14.el7_1.x86_64 already installed and latest version
No package ansible available.
Nothing to do
_>: begin generate ssh key...
spawn ssh-keygen -t rsa -f /home/wntime/.ssh/id_dsa
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/wntime/.ssh/id_dsa.
Your public key has been saved in /home/wntime/.ssh/id_dsa.pub.
The key fingerprint is:
SHA256:EOJlvFpYRDibJ1f0Wft/BxqDuMOxFoQqOJuUE2tcJQU wntime@master-185
The key's randomart image is:
+---[RSA 2048]----+
| E+B*.. . |
| .=+oo.. o . |
| . ..*oo. o . |
|..= =.=o . . . |
|oB. .* S . o o |
|o+... . = + o |
|o * . +|
| . . o|
| |
+----[SHA256]-----+
_>: begin run function [nuts::autoCopySSHKeyToHosts] no CMD on host list...
_>: begin copy local ssh pubkey to wntime@10.10.10.20:1046...
spawn ssh-copy-id -i /home/wntime/.ssh/id_dsa -p 1046 wntime@10.10.10.20
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/wntime/.ssh/id_dsa.pub"
The authenticity of host '[10.10.10.20]:1046 ([10.10.10.20]:1046)' can't be established.
ECDSA key fingerprint is SHA256:DUKrMP5+obHgqNJ1jOc3PnfejVvJCn3ZFZVoaysxbgE.
ECDSA key fingerprint is MD5:22:1a:b7:e9:79:f5:2a:d5:cf:36:09:dc:9d:70:2a:84.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
wntime@10.10.10.20's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -p '1046' 'wntime@10.10.10.20'"
and check to make sure that only the key(s) you wanted were added.
... ...
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@192.168.100.17:1046...
1 7 [[ -n "" ]] && sed -i "s/^alias ll='ls -alF'/alias ll='ls -lvh --color=auto'/g" /home/wntime/.bashrc
2 7 [[ -n "" ]] && sed -i "s/^alias la='ls -A'/alias la='ls -alvh --color=auto'/g" /home/wntime/.bashrc
3 7 [[ -n "/usr/bin/yum" ]] && sed -i "/alias ll='ls -lvh --color=auto'/d" /home/wntime/.bashrc
4 7 [[ -n "/usr/bin/yum" ]] && sed -i "/alias la='ls -lavh --color=auto'/d" /home/wntime/.bashrc
5 7 [[ -n "/usr/bin/yum" ]] && echo "alias ll='ls -lvh --color=auto'" >>/home/wntime/.bashrc
6 7 [[ -n "/usr/bin/yum" ]] && echo "alias la='ls -lavh --color=auto'" >>/home/wntime/.bashrc
7 7 . /home/wntime/.bashrc
[wntime@master-185 ~]$
验证SSH免秘钥登录:
配置yum的源统一使用aliyun的源
# 备份
./auto-ssh-remote.sh "sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak"
# 替换
./auto-ssh-remote.sh "sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo"
# 更新
./auto-ssh-remote.sh "sudo yum makecache"
配置主机名称
修改host文件,只配置master节点信息,注释掉worker节点
hosts文件
#10.10.10.20:1046:wntime
10.10.10.70:1046:wntime
10.10.10.71:1046:wntime
#10.10.10.72:1046:wntime
#10.10.10.73:1046:wntime
#10.10.10.74:1046:wntime
10.10.10.75:1046:wntime
#10.10.10.76:1046:wntime
10.10.10.77:1046:wntime
#192.168.100.16:1046:wntime
192.168.100.17:1046:wntime
# 执行
[wntime@master-185 ~]$ ./auto-ssh-remote.sh 'ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-master-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-master-${tmp##*.}"'
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@10.10.10.70:1046...
1 1 ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-master-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-master-${tmp##*.}"
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@10.10.10.71:1046...
1 1 ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-master-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-master-${tmp##*.}"
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@10.10.10.75:1046...
1 1 ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-master-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-master-${tmp##*.}"
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@10.10.10.77:1046...
1 1 ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-master-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-master-${tmp##*.}"
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@192.168.100.17:1046...
1 1 ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-master-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-master-${tmp##*.}"
配置worker节点名称
# 修改hosts文件
10.10.10.20:1046:wntime
#10.10.10.70:1046:wntime
#10.10.10.71:1046:wntime
10.10.10.72:1046:wntime
10.10.10.73:1046:wntime
10.10.10.74:1046:wntime
#10.10.10.75:1046:wntime
10.10.10.76:1046:wntime
#10.10.10.77:1046:wntime
192.168.100.16:1046:wntime
#192.168.100.17:1046:wntime
# 执行
[wntime@master-185 ~]$ ./auto-ssh-remote.sh 'ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-worker-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-worker-${tmp##*.}"'
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@10.10.10.20:1046...
1 1 ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-worker-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-worker-${tmp##*.}"
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@10.10.10.72:1046...
1 1 ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-worker-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-worker-${tmp##*.}"
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@10.10.10.73:1046...
1 1 ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-worker-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-worker-${tmp##*.}"
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@10.10.10.74:1046...
1 1 ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-worker-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-worker-${tmp##*.}"
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@10.10.10.76:1046...
1 1 ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-worker-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-worker-${tmp##*.}"
_>: begin run function [nuts::remoteExec] with CMD on host list...
_>: begin run command on remote wntime@192.168.100.16:1046...
1 1 ipaddr=($(/usr/sbin/ifconfig |grep broadcast)); tmp=${ipaddr[1]}; sudo sed -i "s/.*/prod-worker-${tmp##*.}/g" /etc/hostname; sudo hostnamectl set-hostname "prod-worker-${tmp##*.}"
同步服务器时间
# 修改hosts文件,配置所有服务器时间同步
./auto-ssh-remote.sh "sudo yum install -y ntpdate" \
"sudo ntpdate time.nist.gov"
到此基础的yum,ssh免秘钥,hostname都配置好了。
更多推荐
已为社区贡献2条内容
所有评论(0)