https://velog.io/@yange/Vagrant-Ansible-9.20
2.1 CentOS01.qcow2 파일 다운로드
- cd /ansible # ansible 디렉토리에서 작업
wget https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1905.qcow2.xz
2.2 압축 해제
- 압축해제
xz -d CentOS-7-x86_64-GenericCloud-1905.qcow2.xz
2.3 libguestfs-tools 다운로드
yum -y install libguestfs-tools libguestfs-xfs
2.4. 이미지에 패스워드 입력하기
- 이미지 커스텀마이즈
virt-customize -a centos01.qcow2 --root-password password:test123 --selinux-relabel
2.5 이미지 복사
- 이미지 4개 생성
cp CentOS-7-x86_64-GenericCloud-1905.qcow2 centos01.qcow2 cp centos01.qcow2 centos02.qcow2 cp centos01.qcow2 centos03.qcow2 cp centos01.qcow2 centos00.qcow2
2.6 인스턴스 생성하기
- 인스턴스 4개 생성
virt-install --name ansible-server --vcpus 1 --ram 1024 --disk=/ansible/centos00.qcow2 --import --graphics none
virt-install --name ansible-node2 --vcpus 1 --ram 1024 --disk=/root/ansible/centos02.qcow2 --import --graphics none --serial pty --console pty &
virt-install --name ansible-node3 --vcpus 1 --ram 1024 --disk=/root/ansible/centos03.qcow2 --import --graphics none --serial pty --console pty &
virt-install --name ansible-node1 --vcpus 1 --ram 1024 --disk=/root/ansible/centos01.qcow2 --import --graphics none --serial pty --console pty &
- 설치되면서 자동으로 콘솔 접속이 진행된다 콘솔에서 나가기 Ctrl + ]
- 생성 완료
2.6.2 만약 접속이 안된다면 아래와 같이 해본다
- 볼륨은 남겨두고 인스턴스만 삭제
virsh undifine ansible-server
- 인스턴스 생성
virt-install --name ansible-server --vcpus 1 --ram 1024 --disk=/root/ansible/centos00.qcow2 --import --graphics none --serial pty --console pty
2.7 VM 에서 나온 상태에서 다시 VM 으로 진입하기
virsh console ansible-node1
- 최종적으로 ansible-server 로 들어가기
- 인스턴스 생성확인
virsh list --all
211.183.3.148 server 211.183.3.151 node1 211.183.3.149 node2 211.183.3.150 node3
2.8 ansible-server setting
- 호스트 네임 번경
hostnamectl set-hostname ansible-server
- 각종 패키지의 최신 버전을 제공하는 community 기반의 저장소 설치
yum -y install epel-release
- 앤서블 설치
yum -y install ansible
- 키 생성
ssh-keygen -q -f ~/.ssh/id_rsa -N ""
- node 1,2,3에게 ~/.ssh/authorized_keys에게 id_rsa.pub 값 전달하기
- 접속해보기
ssh -i ~/.ssh/id_rsa -l root 211.183.3.151 ssh -i ~/.ssh/id_rsa -l root 211.183.3.149 ssh -i ~/.ssh/id_rsa -l root 211.183.3.150
- 211.183.3.X 에 대한 SSH 접속시 root로 접속하고, Key file로 ~/.ssh/id_rsa를 사용하여 접속
cat /etc/ssh/ssh_config # 맨 아래에 다음과 같이 입력한다. Host 211.183.3.* User root IdentityFile ~/.ssh/id_rsa # 혹은 파일 접속없이 다음과 같이 입력한다. cat<<EOF >>/etc/ssh/ssh_config Host 211.183.3.* User root IdentityFile ~/.ssh/id_rsa EOF
- 다양한 모듈 사용
- ping - 지정된 노드에 로그인이 가능한지 여부와 파이썬 철치 여부를 확인할 수 있는 모듈
- shell - 타겟(노드)에서 쉘 명령을 실행할 수 있는 모듈
- user - 사용자 생성, 삭제, 수정할 수 있는 모듈
- yum - yum을 이용해 특정 패키지의 설치와 삭제
- copy - 로컬에서 작성한 파일을 노드에 복사할 수 있는 모듈
1. ping
관리할 Node 주소 설정
- 별도로 인벤토리 파일 만들어 사용하기
예) ansible -i seoul.lstvi /etc/ansible/hosts # 맨 아래에 node ip 적기 211.183.3.151 211.183.3.149 211.183.3.150
- Ansible 실행
[root@ansible-server ~]# ansible all -m ping 211.183.3.149 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } 211.183.3.150 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } 211.183.3.151 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" }
- ip옆에 SUCCESS 인 것을 확인할 수 있다. 변경 사항이 없으므로 changed 는 false 이다. pong 은 ping 에 대한 응답이다
Inventory 파일 사용해보기
- 데이터 센터 리전 별로 구분하기
[root@ansible-server ~]# touch seoul.lst [root@ansible-server ~]# touch busan.lst [root@ansible-server ~]# echo "211.183.3.151" >> seoul.lst [root@ansible-server ~]# echo "211.183.3.149" >> seoul.lst [root@ansible-server ~]# echo "211.183.3.150" >> busan.lst
- 서울.lst에 있는 ip에 핑을 보내겠다.
ansible all -i seoul.lst -m ping
ansible all -i busan.lst -m ping
- 다음과 같이 web과 db로 나누어 핑 보내보기
[root@ansible-server ~]# vi seoul.lst [web] 211.183.3.151 [db] 211.183.3.149
[root@ansible-server ~]# ansible web -i seoul.lst -m ping
- ip만 보기
[root@ansible-server ~]# ansible all -m ping --list-host hosts (3): 211.183.3.151 211.183.3.149 211.183.3.150
[quiz] zone 에 상관없이 모든 DC 에서 웹 서버들로부터만 응답을 받아보세요
[root@ansible-server ~]# ansible all -m ping --list-host hosts (3): 211.183.3.151 211.183.3.149 211.183.3.150 [root@ansible-server ~]# ansible web -i seoul.lst -m ping 211.183.3.151 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } [root@ansible-server ~]# ansible web -i seoul.lst -i busan.lst -m ping 211.183.3.151 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong"
[quiz] Zone 상관 없이 web 서버들만 업데이트
ansible web -i seoul.lst -i busan.lst -m shell -a 'yum -y update' # -i 는 인벤토리를 지정 # 위와 같이 shell 모듈을 이용하여 shell 명령을 내린다
- 만약 모듈 쉘을 이용하여 특정 패키지를 설치했고 다시 한번 동일 명령을 실행한다면? 설치를 진행한다 물론 설치가 되어 있으므로 결과에서는 "이미 설치되어있다"가 출력된다
- 좋지않다.
- 이런경우 yum 모듈을 이용하면 이미설치가 된 상태에서는 다시 한번 설치를 진행하면 skip 한다.
- 결국 shell은 ansible에서 사용하기에 적절한 모듈은 아니다.
3. user
사용자 생성 및 삭제
- user2 생성
[root@ansible-server ~]# ansible all -m user -a "name=user2"
- ansible은 멱등성을 사용한다.
- 동일한 명령을 실행하더라도 결과가 달라지지 않는다.
- 예를 들어 앤서블을 이용하여 httpd를 설치하고 이후 다시 설치를 진행하면 이 경우 해당 명령을 bash를 이용하였다면 추가 설치를 진행시킨다.
- 처음 설치 : changed -> true
- 두번째 설치 : changed -> false
- 이를 이용하게 되면 불필요한 작업을 skip하게 되므로 리소스를 줄일 수 있게 된다.
- user add user2(추가 또는 생성) -> userdel user2(삭제)
- 생성되어 있는 상태를 보장해줘 -> present
- 삭제되어 있는 상태를 보장해 달라 -> absent
-> start -> started
-> stop -> stopped- user2 삭제
[root@ansible-server ~]# ansible all -m user -a "name=user2 state=absent"
- user2 삭제 확인 해보기
[root@ansible-server ~]# ansible all -m shell -a "cat /etc/passwd | grep user2"
4. yum
yum을 이용한 특정 패키지의 설치와 삭제
- curl 설치
[root@ansible-server ~]# ansible all -m yum -a "name=curl state=present"
- curl 삭제
[root@ansible-server ~]# ansible all -m yum -a "name=curl state=absent"
- git 설치
[root@ansible-server ~]# ansible all -m yum -a "name=git state=present" # 명령에 state=present가 없어도 동일하게 설치된다.
- git clone하기
ansible all -m git -a "repo=https://github.com/beomtaek/k8s-quiz.git dest=/root/gittest"
- 파일 목록확인
[root@ansible-server ~]# ansible all -m shell -a "ls /root/gittest"
[quiz]
- 웹 서버 설치 및 홈 디렉토리에 index.html 을 복사 붙여넣기
ansible all -m yum -a "name=httpd state=present" -k
- 웹 서버 설치
echo "<h2>yang</h2>" > index.html
- index.html 생성
ansible all -m copy -a "src=index.html dest=/var/www/html/index.html"
- server 의 index.html 을 node 의 디렉토리에 복사
[root@ansible-server ~]# ansible all -m shell -a "ls /var/www/html" 211.183.3.149 | CHANGED | rc=0 >> index.html 211.183.3.150 | CHANGED | rc=0 >> index.html 211.183.3.151 | CHANGED | rc=0 >> index.html
- 실행하기
ansible all -m service -a "name=httpd state=started" # = ansible all -m shell -a "systemctl start httpd"
- service 모듈을 통해 state 를 started 로 지정하여 해당 서비스가 시작된 상태를 보장해준다.
- 해당 주소로 접속하면 index.html이 나타난다.
http://211.183.3.149/
[quiz2]
- git hub 의 아무 저장소에 간단한 index.html 파일을 올려두세요!!! (내용은 shop)
- git 모듈을 이용하여 기존 동작중인 웹서버의 /var/www/html/shop 아래에 github 에 있는 index.html 파일을 클론 시키세요!
- http://211.183.3.x/shop으로 파일을 확인할 수 있어야 한다.
[해설]
- index.html 업로드
ansible all -m git -a "repo=https://github.com/Yangyang0429/tutorial.git dest=/var/www/html/shop"
- 접속해보기
http://211.183.3.149/shop
서비스 중지하기
ansible all -m service -a "name=httpd state=stopped"
httpd 삭제하기
ansible all -m yum -a "name=httpd state=absent"
- IaC
- 코드를 이용하여 인프라를 구추가고 사용가능하 준비 상태를 만들어 줄 수 있다. -> 프로비저닝
- 추가적으로 아주 정밀하지는 않지만 자동화도 지원한다.
- 현재 Vagrant와 Kvm간의 연결을 위한 모듈(terraform과 kvm)은 결합도가 낮다.
- vagrant + virtualbox는 결합도가 높다
- 실제 클라우드 환경에 IaC를 적용할 때에는
1. Vagrant 실습 환경 구성
- 기존 실습했던 가상 머신은 중지시키자
1.1 가상머신 리스트 확인 및 중지
[root@localhost ansible]# virsh list --all Id Name State ---------------------------------------------------- 4 ansible-server running 5 ansible-node2 running 6 ansible-node3 running 7 ansible-node1 running
- 중지
[root@localhost ansible]# virsh destroy ansible-node1
- 삭제
[root@localhost ansible]# virsh undefine ansible-node1
1.2 vagrant의 설치와 libvirt(kvm)용 vagrant 플러그인 설치하기
yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
yum -y install libvirt-daemon-kvm libvirt-client vagrant gcc-c++ make libstdc++-devel libvirt-devel
systemctl restart libvirtd vagrant plugin install vagrant-libvirt vagrant -v Vagrant 2.2.16
- vagrant 실습을 위한 파일 생성
mkdir project1; cd project1
- 현재 디렉토리에서 프로젝트를 시작한다고 명시
vagrant init
- Vagrantfile 보기
- Vagrantfile은 프로비저닝을 위한 도구이다(네트워크, vm 생성 등)
vi Vagrantfile 8 Vagrant.configure("2") do |config| # "2" 해당 버전에서 제공되는 것 # do - do 부터 end 사이에 하나의 작업을 수행 # |config| - 작업 내용 중에 config 작업을 수행한다. - 여러개의 작업을 둘 수 있다. - | | 는 일종의 작업 구분자 15 config.vm.box = "base" # base 이미지 말들기 # 만약 다른 이미지를 사용하고 싶다면 "" 안에 사용하고 싶은 이미지의 이름 즉, centos7을 사용하고 싶다면 "centos/7"로 변경하면 된다.
- Vagrantfile 파일 수정
8 Vagrant.configure("2") do |config| 15 config.vm.box = "centos/7" 16 config.vm.host_name = "server" 26 config.vm.network "forwarded_port", guest: 22, host: 20021, id: 'ssh ' #id는 ssh를 위한것(id는 특별히 지정해줄 필요없다.) 35 config.vm.network "private_network", ip: "192.168.33.10" # eth1 IP
- Vagrantfile 파일 실행
vagrant up
- 가상머신 생성 확인
[root@localhost project1]# virsh list --all Id Name State ---------------------------------------------------- 1 project1_default running - ansible-node1 shut off - ansible-node2 shut off - ansible-node3 shut off - ansible-server shut off
- vagrant에 접속
[root@localhost project1]# vagrant ssh default
- ip 확인
[vagrant@server ~]$ ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:42:e7:01 brd ff:ff:ff:ff:ff:ff inet 192.168.121.155/24 brd 192.168.121.255 scope global noprefixroute dynamic eth0 valid_lft 2748sec preferred_lft 2748sec inet6 fe80::5054:ff:fe42:e701/64 scope link valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:13:a8:5f brd ff:ff:ff:ff:ff:ff inet 192.168.33.10/24 brd 192.168.33.255 scope global noprefixroute eth1 valid_lft forever preferred_lft forever inet6 fe80::5054:ff:fe13:a85f/64 scope link valid_lft forever preferred_lft forever
- 초기 환경
virsh undefine server virsh undefine node1 virsh undefine node2 virsh undefine node3 virsh destroy
1. /ansible/project2 생성
mkdir /ansible/project2; cd /ansible/project2
2. vagrant init
vagrant init
6.1 키 생성
- 키 생성
ssh-keygen -q -f ~/.ssh/id_rsa -N ""
3. vi Vagrantfile을 열어서 아래의 내용을 만족하도록 프로비저닝한다.
인스턴스 box public network private network server centos/7 지정하지 말것 10.10.10.10 node1 10.10.10.11 node2 10.10.10.12 node3 10.10.10.13
- vi Vagrantfile 파일 수정
vi Vagrantfile Vagrant.configure("2") do |config| ######### Ansible server ######### config.vm.define "server" do |cfg| cfg.vm.box = "centos/7" cfg.vm.host_name = "server" cfg.vm.network "private_network", ip: "10.10.10.10" cfg.vm.network "forwarded_port", guest: 22, host:60011, auto_correct: true, id: "ssh" cfg.vm.provision "shell", inline: "yum install -y epel-release" cfg.vm.provision "shell", inline: "yum install -y ansible" cfg.vm.provision "file", source: "~/.ssh/id_rsa", destination: "~/.ssh/id_rsa" end ######### Ansible node1 ######### config.vm.define "node1" do |cfg| cfg.vm.box = "centos/7" cfg.vm.host_name = "node1" cfg.vm.network "private_network", ip: "10.10.10.11" cfg.vm.network "forwarded_port", guest: 22, host:60012, auto_correct: true, id: "ssh" end ######### Ansible node2 ######### config.vm.define "node2" do |cfg| cfg.vm.box = "centos/7" cfg.vm.host_name = "node2" cfg.vm.network "private_network", ip: "10.10.10.12" cfg.vm.network "forwarded_port", guest: 22, host:60013, auto_correct: true, id: "ssh" end ######### Ansible node3 ######### config.vm.define "node3" do |cfg| cfg.vm.box = "centos/7" cfg.vm.host_name = "node3" cfg.vm.network "private_network", ip: "10.10.10.13" cfg.vm.network "forwarded_port", guest: 22, host:60014, auto_correct: true, id: "ssh" end end
4. vagrant up -> 이후 virsh list --all, vagrant ssh server/vagrant ssh node1 등으로 접속하여 상태확인
[root@localhost project2]# virsh list --all Id Name State ---------------------------------------------------- 2 project2_node3 running 3 project2_node2 running 4 project2_node1 running 5 project2_server running
vagrant ssh server vagrant ssh node1 vagrant ssh node2 vagrant ssh node3
5. Vagrantfile 중 server 항목에 ansible 설치를 추가하여 provision 한다.
- vi Vagrantfile server 항목에 추가
cfg.vm.provision "shell", inline: "yum install -y epel-release" cfg.vm.provision "shell", inline: "yum install -y ansible"
vagrant provision
6. 로컬에서(211.183.3.99 호스트) 새로운 키페어를 만든다.
private key는 server로 전달 public key는 node들에게 전달
7. vagrant ssh server로 진입하여 /etc/ansible/hosts 파일에 node들의 ip를 등록하고 ansible all -m ping이 성공해야 한다.
/etc/ansible/hosts # 맨 아래에 추가 10.10.10.11 10.10.10.12 10.10.10.13
- 종료
vagrant halt
- 성공
또 다른 방법
[root@localhost project2]# cat Vagrantfile ; echo ------------------- ; cat ssh_config_mykey # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.define "server" do |cfg0| cfg0.vm.box = "centos/7" cfg0.vm.host_name = "server" cfg0.vm.network "private_network", ip: "10.10.10.10" cfg0.vm.network "forwarded_port", guest: 22, host: 20010, id: "ssh" cfg0.vm.provision "shell", inline: "yum -y install epel-release && yum -y install ansible" cfg0.vm.provision "file", source: "mykey.pem", destination: "/home/vagrant/.ssh/mykey.pem" cfg0.vm.provision "shell", inline: "chmod 600 /home/vagrant/.ssh/mykey.pem" cfg0.vm.provision "file", source: "ssh_config_mykey", destination: "/home/vagrant/ssh_config_mykey" cfg0.vm.provision "shell", inline: "cat /home/vagrant/ssh_config_mykey >> /etc/ssh/ssh_config" cfg0.vm.provision "shell", inline: "echo '10.10.10.11' >> /etc/ansible/hosts" cfg0.vm.provision "shell", inline: "echo '10.10.10.12' >> /etc/ansible/hosts" cfg0.vm.provision "shell", inline: "echo '10.10.10.13' >> /etc/ansible/hosts" cfg0.vm.provision "shell", inline: "ssh-keyscan 10.10.10.11 >> /home/vagrant/.ssh/known_hosts" cfg0.vm.provision "shell", inline: "ssh-keyscan 10.10.10.12 >> /home/vagrant/.ssh/known_hosts" cfg0.vm.provision "shell", inline: "ssh-keyscan 10.10.10.13 >> /home/vagrant/.ssh/known_hosts" cfg0.vm.provision "shell", inline: "chown vagrant.vagrant /home/vagrant/.ssh/known_hosts" end config.vm.define "node1" do |cfg1| cfg1.vm.box = "centos/7" cfg1.vm.host_name = "node1" cfg1.vm.network "private_network", ip: "10.10.10.11" cfg1.vm.network "forwarded_port", guest: 22, host: 20011, id: "ssh" cfg1.vm.provision "file", source: "mykey.pem.pub", destination: "/home/vagrant/.ssh/mykey.pem.pub" cfg1.vm.provision "shell", inline: "cat /home/vagrant/.ssh/mykey.pem.pub >> /home/vagrant/.ssh/authorized_keys" end config.vm.define "node2" do |cfg2| cfg2.vm.box = "centos/7" cfg2.vm.host_name = "node2" cfg2.vm.network "private_network", ip: "10.10.10.12" cfg2.vm.network "forwarded_port", guest: 22, host: 20012, id: "ssh" cfg2.vm.provision "file", source: "mykey.pem.pub", destination: "/home/vagrant/.ssh/mykey.pem.pub" cfg2.vm.provision "shell", inline: "cat /home/vagrant/.ssh/mykey.pem.pub >> /home/vagrant/.ssh/authorized_keys" end config.vm.define "node3" do |cfg3| cfg3.vm.box = "centos/7" cfg3.vm.host_name = "node3" cfg3.vm.network "private_network", ip: "10.10.10.13" cfg3.vm.network "forwarded_port", guest: 22, host: 20013, id: "ssh" cfg3.vm.provision "file", source: "mykey.pem.pub", destination: "/home/vagrant/.ssh/mykey.pem.pub" cfg3.vm.provision "shell", inline: "cat /home/vagrant/.ssh/mykey.pem.pub >> /home/vagrant/.ssh/authorized_keys" end end ------------------- Host 10.10.10.* User vagrant IdentityFile /home/vagrant/.ssh/mykey.pem