본문 바로가기
DevOps/IaC 자동화

[Vagrant] SSH 공개키 자동 등록 환경 설정, Ansible 사용

by 🌻♚ 2020. 12. 20.

이번 글에서는 Vagrant를 이용해서 ansible을 사용할 때 인증 작업을 생략하기 위해 SSH 공개키를 자동으로 등록하는 실습니다. Vagrant를 이용해서 provisioning할 때 Ansible을 많이 사용하게 됩니다. 그런데 ansible은 ssh를 통해 통신하기 때문에 ansible hosts에 직접 계정정보를 등록해주지 않는 이상 -k 옵션을 이용해야하지만...  vagrant에서 환경 세팅을 위해 -k 옵션을 사용할 수 없다. 이런 불편함을 해소하기 위해 공개키를 vagrant에서 직접 등록하여 provisioning을 편하게 진행할 수 있습니다.

 

Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant_API_Version = "2"
Vagrant.configure(Vagrant_API_Version) do |config|
  #node01
  config.vm.define:"node01" do |cfg|
    config.vm.box = "centos/7"
    cfg.vbguest.auto_update = false
    cfg.vm.provider:virtualbox do |vb|
      vb.name="CentOS-node01"
      vb.customize ["modifyvm", :id, "--cpus",1]
      vb.customize ["modifyvm", :id, "--memory",1024]
    end
    cfg.vm.host_name="node01"
    cfg.vm.synced_folder ".", "/vagrant", disabled:true
    cfg.vm.network "public_network", ip: "222.111.71.101"
    cfg.vm.network "forwarded_port", guest: 22, host:29211, auto_correct: false, id: "ssh"
    cfg.vm.provision "shell", path: "all_settings.sh"
  end

  #node02
  config.vm.define:"node02" do |cfg|
    config.vm.box = "centos/7"
    cfg.vbguest.auto_update = false
    cfg.vm.provider:virtualbox do |vb|
      vb.name="CentOS-node02"
      vb.customize ["modifyvm", :id, "--cpus",1]
      vb.customize ["modifyvm", :id, "--memory",1024]
    end
    cfg.vm.host_name="node02"
    cfg.vm.synced_folder ".", "/vagrant", disabled:true
    cfg.vm.network "public_network", ip: "222.111.71.102"
    cfg.vm.network "forwarded_port", guest: 22, host:29212, auto_correct: false, id: "ssh"
    cfg.vm.provision "shell", path: "all_settings.sh"
  end

  #master
  config.vm.define:"master" do |cfg|
    config.vm.box = "centos/7"
    cfg.vbguest.auto_update = false
    cfg.vm.provider:virtualbox do |vb|
      vb.name="CentOS-master"
      vb.customize ["modifyvm", :id, "--cpus",1]
      vb.customize ["modifyvm", :id, "--memory",2048]
    end
    cfg.vm.host_name="master"
    cfg.vm.synced_folder ".", "/vagrant", disabled:true
    cfg.vm.network "public_network", ip: "222.111.71.100"
    cfg.vm.network "forwarded_port", guest: 22, host:29210, auto_correct: false, id: "ssh"
    cfg.vm.provision "shell", path: "all_settings.sh"
    cfg.vm.provision "shell", path: "master_init.sh"
    cfg.vm.provision "shell", path: "nodes_ssh_key_settings.sh"
    cfg.vm.provision "file", source: "puppet_settings.yml", destination: "puppet_settings.yml"
    cfg.vm.provision "shell", inline: "ansible-playbook puppet_settings.yml"
  end
end

master에서 node로 통신하는 작업이 있기 때문에 node들을 먼서 provisioning해줍니다. 기본적으로 모든 서버에 all_settings.sh를 실행해주고 master에는 따로 실행해주는 작업이 더 추가됩니다.

 

 

all_settings.sh

#! /usr/bin/env bash

# install useful packages
yum install net-tools vim -y

# edit hosts
cat << EOF > /etc/hosts
127.0.0.1 localhost
::1 localhost
222.111.71.100 master
222.111.71.101 node01
222.111.71.102 node02
EOF

# ssh password Authentication no to yes
sed -i -e 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
systemctl restart sshd

ROOT_HOME=/root
VAGRANT_HOME=/home/vagrant

# create .ssh for root
mkdir -p $ROOT_HOME/.ssh
chmod 700 $ROOT_HOME/.ssh
touch $ROOT_HOME/.ssh/authorized_keys
chmod 644 $ROOT_HOME/.ssh/authorized_keys

hostname을 이용하기 위해 hosts파일을 모두 수정해주고 ssh를 Password로 접근가능하도록 sshd_config파일을 수정해줍니다. 이후 공개키를 등록하기 위해 경로를 생성해주고 권한을 부여합니다.

 

 

master_init.sh

#! /usr/bin/env bash

# install useful packages
yum install epel-release -y
yum install ansible -y
yum install sshpass -y

# edit ansible hosts
cat << EOF > /etc/ansible/hosts
[local]
master
[nodes]
node01
node02
EOF

master host에 ansible을 설치하고 password를 통해 접속하기 위해 sshpass를 설치하고 ansible hosts파일을 수정해줍니다.

 

nodes_ssh_key_settings.sh

#! /usr/bin/env bash

ssh-keygen -t rsa -N '' -f /root/.ssh/id_rsa <<< n

declare -a server_hosts=("node01" "node02")
declare -a server_users=("vagrant")
key_val=$(cat /root/.ssh/id_rsa.pub)
for host in "${server_hosts[@]}"; do
	sshpass -p vagrant ssh -o StrictHostKeyChecking=no root@$host "grep '$key_val' /root/.ssh/authorized_keys || echo '$key_val' >> /root/.ssh/authorized_keys"
	for user in "${server_users[@]}"; do
		sshpass -p vagrant ssh -o StrictHostKeyChecking=no $user@$host "grep '$key_val' /home/$user/.ssh/authorized_keys || echo '$key_val' >> /home/$user/.ssh/authorized_keys"
	done
done

master node의 root 계정에서 nodes의 root와 vagrant 계정에 비밀번호 없이 접속가능하도록 설정입니다. ansible playbook으로 설정했으면 좋았겠지만... ssh 통신이 가능하지 않아 command로 실행하게 되었습니다. 그런 과정에서 멱등성을 지키지 못하여 provisioning을 1번 이상 진행되면 이미 생성된 공개키를 다시 생성하거나 authorized_keys에 두번 등록되는 경우를 방지하기 위한 처리를 했습니다.

 

for문을 이용했고 server_hosts와 server_users를 추가해서 각각 서버와 사용자를 늘릴 수 있습니다. 비밀번호는 초기에 모두 vagrant로 설정된 것이 전제 조건입니다.

 

 

-master node에서 공개키를 scp로 전송합니다.

-ssh-keygen은 overwrite하는 경우를 방지하기 위해 promt의 답을 n으로 설정합니다.

-authorized-keys에 등록 중복을 방지하기 위해 grep 명령어로 해당 key가 있는지 확인합니다.

-마지막으로 전송한 공개키파일을 삭제합니다.

태그

, ,

댓글0