前言:

        新坑指南:在小型公司里,部署k8s技术和运维都没到要求,又想体会容器带来的遍历可以试试这个方案。

虚拟机环境 

hostnameipOSdesc
prod-master-7010.10.10.70CentOS Linux release 7.2.1511 (Core)
prod-master-7110.10.10.71CentOS Linux release 7.2.1511 (Core)
prod-worker-7210.10.10.72CentOS Linux release 7.2.1511 (Core)
prod-worker-7310.10.10.73CentOS Linux release 7.2.1511 (Core)
prod-worker-7410.10.10.74CentOS Linux release 7.2.1511 (Core)
prod-master-7510.10.10.75CentOS Linux release 7.2.1511 (Core)
prod-worker-7610.10.10.76CentOS Linux release 7.2.1511 (Core)
prod-master-7710.10.10.77CentOS Linux release 7.2.1511 (Core)
prod-worker-2010.10.10.20CentOS Linux release 7.6.1810 (Core)
prod-worker-16192.168.100.16CentOS Linux release 7.6.1810 (Core)
prod-master-17192.168.100.17CentOS 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都配置好了。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐