Ansible을 사용하여 여러 Ubuntu 22.04 서버의 초기 서버 설정을 자동화하는 방법
저자는 Write for DOnations 프로그램을 선택했습니다.
소개
자동화 플레이북.
Ansible은 에이전트가 없으므로 Ansible을 실행하려는 서버에 Ansible 구성 요소를 설치할 필요가 없습니다. 이러한 서버는 Ansible 호스트이며 WSL(Linux용 Windows 하위 시스템)이 설치되어 실행되어야 합니다.
이 튜토리얼에서는 Ansible을 사용하여 여러 Ubuntu 22.04 서버의 초기 서버 설정을 자동화합니다. 모든 서버에서 다음과 같은 초기 설정 작업을 수행합니다.
- 설치된 패키지 업데이트
- 관리자 권한이 있는 루트가 아닌 사용자 추가
- 루트가 아닌 사용자에 대한 SSH 액세스 활성화
- 방화벽 활성화
- SSH 액세스용 포트 변경 및 방화벽을 사용하여 무차별 대입 공격으로부터 보호하고 서버의 전반적인 보안 강화
- 루트 계정에 대한 원격 로그인 비활성화
- 중요한 서비스가 활성 상태인지 확인
- 더 이상 필요하지 않은 패키지 종속성 제거
Ansible을 사용하여 각 작업을 정의하는 포괄적인 플레이북을 실행하므로 해당 작업은 서버에 개별적으로 로그인할 필요 없이 단 하나의 명령으로 완료됩니다. 선택적 보조 플레이북을 실행하여 초기 서버 설정 후 서버 관리를 자동화할 수 있습니다.
전제 조건
이 자습서를 완료하려면 다음이 필요합니다.
- 로컬 시스템 또는 원격 Linux 서버가 될 수 있는 제어 노드 역할을 할 시스템에 Ansible이 설치됩니다. Ansible을 설치하려면 다른 운영 체제에 필요한 공식 Ansible 설치 가이드의 1단계를 따르십시오.\n
- 제어 노드가 원격 Ubuntu 22.04 서버인 경우 SSH 키 쌍 생성을 사용하여 설정해야 합니다.
- 제어 노드에 설치된 Git. 널리 사용되는 Linux 배포판에 대한 Git 설치 방법 자습서를 따르십시오.
- (선택 사항)
EDITOR
환경 셸 변수에 연결된 텍스트 편집기를 변경하려면 Ansible Vault 사용 방법 자습서의 Ansible Vault 편집기 설정에서. 이 튜토리얼에서는 Ansible Vault의 편집기로nano
를 사용합니다.
두 개 이상의 Ubuntu 22.04 서버 및 각 서버의 공용 IPv4 주소. Ansible을 사용하여 5단계에서 설정을 자동화하므로 사전 설정이 필요하지 않지만 위에서 언급한 Ansible 제어 노드에서 이러한 서버에 대한 SSH 액세스 권한이 있어야 합니다. DigitalOcean Droplets를 사용하는 경우 대시보드의 네트워킹 탭에 있는 각 서버의 공용 네트워크 섹션에서 IPv4 주소를 찾을 수 있습니다.
- 제어 노드가 원격 Ubuntu 22.04 서버인 경우
ssh-copy-id
를 사용하여 키 쌍을 호스트에 연결해야 합니다.
1단계 - 제어 노드에서 SSH 클라이언트 구성 파일 수정
이 단계에서는 제어 노드의 SSH 클라이언트 구성 파일에서 지시문을 수정합니다. 이렇게 변경한 후에는 자동으로 수락되므로 더 이상 원격 시스템의 SSH 키 지문을 수락하라는 메시지가 표시되지 않습니다. 각 원격 시스템에 대한 SSH 키 지문을 수동으로 수락하는 것은 번거로울 수 있으므로 이 수정은 Ansible을 사용하여 여러 서버의 초기 설정을 자동화할 때 확장 문제를 해결합니다.
Ansible의
known_hosts
모듈을 사용하여 단일 호스트에 대한 SSH 키 지문을 자동으로 수락할 수 있지만 이 자습서에서는 여러 호스트를 다루므로 제어 노드에서 SSH 클라이언트 구성 파일을 수정하는 것이 더 효과적입니다( 일반적으로 로컬 컴퓨터).시작하려면 제어 노드에서 터미널 애플리케이션을 실행하고
nano
또는 선호하는 텍스트 편집기를 사용하여 SSH 클라이언트 구성 파일을 엽니다.- sudo nano /etc/ssh/ssh_config
StrictHostKeyChecking
지시문이 포함된 줄을 찾습니다. 주석을 제거하고 다음과 같이 값을 변경합니다.... StrictHostKeyChecking accept-new ...
파일을 저장하고 닫습니다. SSH 클라이언트 구성 파일만 수정했기 때문에 SSH 데몬을 다시 로드하거나 다시 시작할 필요가 없습니다.
참고:
StrictHostKeyChecking
값을ask
에서accept-new
로 영구적으로 변경하지 않으려면 기본값으로 되돌릴 수 있습니다. 7단계에서 플레이북을 실행한 후. 값을 변경하면 시스템이 SSH 키 지문을 자동으로 수락하지만 지문이 변경되면 동일한 호스트의 후속 연결을 거부합니다. 이 기능은accept-new
변경이 해당 지시문의 값을no
로 변경하는 것만큼 보안 위험이 크지 않음을 의미합니다.이제 SSH 지시문을 업데이트했으므로 다음 단계에서 수행할 Ansible 구성을 시작합니다.
2단계 - Ansible Hosts 파일 구성
Ansible
hosts
파일(인벤토리 파일이라고도 함)에는 Ansible 호스트에 대한 정보가 포함되어 있습니다. 이 정보에는 그룹 이름, 별칭, 도메인 이름 및 IP 주소가 포함될 수 있습니다. 이 파일은 기본적으로/etc/ansible
디렉토리에 있습니다. 이 단계에서는 Prerequisites 섹션에서 스핀업한 Ansible 호스트의 IP 주소를 추가하여 이에 대해 Ansible 플레이북을 실행할 수 있습니다.시작하려면
nano
또는 선호하는 텍스트 편집기를 사용하여hosts
파일을 엽니다.- sudo nano /etc/ansible/hosts
파일의 소개 주석 뒤에 다음 줄을 추가합니다.
... host1 ansible_host=host1-public-ip-address host2 ansible_host=host2-public-ip-address host3 ansible_host=host3-public-ip-address [initial] host1 host2 host3 [ongoing] host1 host2 host3
host1
,host2
및host3
는 별칭입니다. 초기 서버 설정을 자동화하려는 각 호스트에 대해. 별칭을 사용하면 다른 곳에서 호스트를 더 쉽게 참조할 수 있습니다.ansible_host
는 Ansible 연결 변수이며 이 경우 대상 호스트의 IP 주소를 가리킵니다.initial
및ongoing
은 Ansible 호스트의 샘플 그룹 이름입니다. 호스트의 용도를 쉽게 알 수 있는 그룹 이름을 선택하십시오. 이러한 방식으로 호스트를 그룹화하면 호스트를 하나의 단위로 처리할 수 있습니다. 호스트는 둘 이상의 그룹에 속할 수 있습니다. 이 자습서의 호스트는 8단계의 초기 서버 설정을 위한initial
의 두 가지 다른 플레이북에서 사용되기 때문에 두 개의 다른 그룹에 할당되었습니다.hostN-public-ip-address
는 각 Ansible 호스트의 IP 주소입니다.host1-public-ip-address
와 후속 행을 자동화의 일부가 될 서버의 IP 주소로 바꾸십시오.파일 수정이 완료되면 저장하고 닫습니다.
인벤토리 파일에서 호스트를 정의하면 Ansible 자동화로 설정할 호스트를 지정하는 데 도움이 됩니다. 다음 단계에서는 샘플 플레이북으로 리포지토리를 복제하여 다중 서버 설정을 자동화합니다.
3단계 - Ansible Ubuntu 초기 서버 설정 리포지토리 복제
이 단계에서는 이 자동화에 필요한 파일이 포함된 GitHub의 샘플 리포지토리를 복제합니다.
이 리포지토리에는 샘플 다중 서버 자동화를 위한 세 개의 파일(
initial.yml
,ongoing.yml
및vars/default.yml
)이 포함되어 있습니다.initial.yml
파일은 초기 설정을 위해 Ansible 호스트에 대해 실행할 플레이와 작업이 포함된 기본 플레이북입니다.ongoing.yml
파일에는 초기 서버 설정 후 지속적인 유지 관리를 위해 호스트에 대해 실행할 작업이 포함되어 있습니다.vars/default.yml
파일에는 8단계에서 두 플레이북 모두에서 호출될 변수가 포함되어 있습니다.저장소를 복제하려면 다음 명령을 입력하십시오.
- git clone https://github.com/do-community/ansible-ubuntu.git
또는 GitHub 계정에 SSH 키를 추가한 경우 다음을 사용하여 저장소를 복제할 수 있습니다.
- git@github.com:do-community/ansible-ubuntu.git
이제 작업 디렉토리에
ansible-ubuntu
라는 폴더가 생겼습니다. 그것으로 변경:- cd ansible-ubuntu
이 튜토리얼의 나머지 부분을 위한 작업 디렉토리가 됩니다.
이 단계에서는 Ansible을 사용하여 여러 Ubuntu 22.04 서버를 자동화하기 위한 샘플 파일을 얻었습니다. 호스트에 특정한 정보가 포함된 파일을 준비하려면 시스템에서 작동하도록
vars/default.yml
파일을 업데이트합니다.4단계 - Ansible 변수 수정
이 플레이북은 시간이 지남에 따라 업데이트해야 할 수 있는 자동화에 대한 일부 정보를 참조합니다. 해당 정보를 하나의 변수 파일에 배치하고 플레이북에서 변수를 호출하는 것이 플레이북 내에서 변수를 하드 코딩하는 것보다 더 효율적이므로
vars/default.yml
파일에서 변수를 수정하여 이 단계에서 기본 설정 및 설정이 필요합니다.시작하려면
nano
또는 선호하는 텍스트 편집기로 파일을 엽니다.- nano vars/default.yml
다음 변수를 포함하는 파일의 내용을 검토합니다.
create_user: sammy ssh_port: 5995 copy_local_key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"
create_user
변수의 값은 각 호스트에서 생성될sudo
사용자의 이름이어야 합니다. 이 경우sammy
이지만 원하는 대로 사용자 이름을 지정할 수 있습니다.ssh_port
변수는 설정 후 Ansible 호스트에 연결하는 데 사용할 SSH 포트를 보유합니다. SSH의 기본 포트는22
이지만 포트를 변경하면 서버에 대한 자동 공격의 수가 크게 줄어듭니다. 이 변경은 선택 사항이지만 호스트의 보안 태세를 강화합니다.1024
와65535
사이에 있고 Ansible 호스트의 다른 애플리케이션에서도 사용하지 않는 잘 알려지지 않은 포트를 선택해야 합니다. 이 예에서는 포트5995
를 사용하고 있습니다.참고: 제어 노드가 Linux 배포판을 실행 중인 경우
/etc/services
에서1023
및grep
보다 높은 숫자를 선택하십시오. 예를 들어grep 5995 /etc/services
를 실행하여5995
가 사용되고 있는지 확인합니다. 출력이 없으면 해당 파일에 포트가 없는 것이므로 변수에 할당할 수 있습니다. 제어 노드가 Linux 배포판이 아니고 시스템에서 해당 항목을 찾을 수 없는 경우 서비스 이름 및 전송 프로토콜 포트 번호 레지스트리를 참조할 수 있습니다.copy_local_key
변수는 제어 노드의 SSH 공개 키 파일을 참조합니다. 해당 파일의 이름이id_rsa.pub
인 경우 해당 줄을 변경할 필요가 없습니다. 그렇지 않으면 제어 노드의 SSH 공개 키 파일과 일치하도록 변경하십시오. 제어 노드의~/.ssh
디렉터리에서 파일을 찾을 수 있습니다. 5단계에서 기본 플레이북을 실행하고sudo
권한이 있는 사용자가 생성된 후 Ansible 컨트롤러는 공개 키 파일을 사용자의 홈 디렉터리에 복사하므로 해당 사용자로 로그인할 수 있습니다. 초기 서버 설정 후 SSH를 통해.파일 수정이 완료되면 저장하고 닫습니다.
이제
vars/default.yml
의 변수에 값을 할당했으므로 Ansible은 8단계에서 플레이북을 실행하는 동안 해당 변수를 호출할 수 있습니다. 다음 단계에서는 Ansible을 사용합니다. 각 호스트에서 생성될 사용자의 암호를 생성하고 보호하기 위한 볼트.5단계 - Ansible Vault를 사용하여 암호화된 암호 파일 생성
Ansible Vault는 플레이북에서 참조할 수 있는 파일 및 변수를 생성하고 암호화하는 데 사용됩니다. Ansible Vault를 사용하면 플레이북을 실행하는 동안 민감한 정보가 일반 텍스트로 전송되지 않습니다. 이 단계에서는 각 호스트에서
sudo
사용자의 암호를 만드는 데 사용할 값을 가진 변수가 포함된 파일을 만들고 암호화합니다. 이러한 방식으로 Ansible Vault를 사용하면 초기 서버 설정 도중 및 이후에 플레이북에서 암호가 일반 텍스트로 참조되지 않도록 할 수 있습니다.여전히
ansible-ubuntu
디렉토리에서 다음 명령을 사용하여 볼트 파일을 만들고 엽니다.- ansible-vault create secret
메시지가 표시되면
비밀
파일을 암호화하는 데 사용할 암호를 입력하고 확인합니다. 이것이 볼트 암호입니다. 8단계에서 플레이북을 실행하는 동안 볼트 암호가 필요하므로 잊지 마십시오.볼트 암호를 입력하고 확인하면
비밀
파일이 셸의EDITOR
환경 변수에 연결된 텍스트 편집기에서 열립니다. 다음 줄을 파일에 추가하고type_a_strong_password_here
및type_a_salt_here
의 값을 바꿉니다.- password: type_a_strong_password_here
- password_salt: type_a_salt_here
password
변수의 값은 각 호스트에서 생성할sudo
사용자의 실제 비밀번호입니다.password_salt
변수는 salt 값을 사용합니다. 8단계.참고: 테스트에서 숫자로만 구성된 솔트가 8단계에서 플레이북을 실행하는 데 문제가 있음을 발견했습니다. 그러나 알파벳 문자로만 구성된 솔트는 작동했습니다. 영숫자 소금도 작동합니다. 소금을 지정할 때 이 점을 염두에 두십시오.
파일 수정이 완료되면 저장하고 닫습니다.
이제 호스트에서
sudo
사용자의 암호를 만드는 데 사용할 변수가 있는 암호화된 암호 파일을 만들었습니다. 다음 단계에서는 기본 Ansible 플레이북을 실행하여 2단계에서 지정한 서버의 초기 설정을 자동화합니다.6단계 - Ansible 호스트에 대해 기본 플레이북 실행
이 단계에서는 Ansible을 사용하여 인벤토리 파일에 지정한 수만큼 서버의 초기 서버 설정을 자동화합니다. 기본 플레이북에 정의된 작업을 검토하는 것으로 시작합니다. 그런 다음 호스트에 대해 플레이북을 실행합니다.
Ansible 플레이북은 각 플레이와 관련된 하나 이상의 작업이 있는 하나 이상의 플레이로 구성됩니다. Ansible 호스트에 대해 실행할 샘플 플레이북에는 총 14개의 작업이 있는 두 개의 플레이가 포함되어 있습니다.
플레이북을 실행하기 전에 설정 프로세스와 관련된 각 작업을 검토합니다. 시작하려면
nano
또는 선호하는 텍스트 편집기로 파일을 엽니다.- nano initial.yml
플레이 1:
파일의 첫 번째 섹션에는 플레이 동작에 영향을 미치는 다음 키워드가 포함되어 있습니다.
- name: Initial server setup tasks hosts: initial remote_user: root vars_files: - vars/default.yml - secret ...
name
은 연극이 실행될 때 터미널에 표시되는 연극에 대한 짧은 설명입니다.hosts
키워드는 어떤 호스트가 연극의 대상인지를 나타냅니다. 이 경우 키워드에 전달되는 패턴은 2단계에서/etc/ansible/hosts
파일에 지정한 호스트의 그룹 이름입니다.remote_user
를 사용합니다. 호스트에 로그인하는 데 사용할 사용자 이름을 Ansible 컨트롤러에 알려주는 키워드입니다(이 경우root
).vars_files
키워드는 작업을 실행할 때 재생이 참조할 변수가 포함된 파일을 가리킵니다.이 설정으로 Ansible 컨트롤러는 SSH 포트
22
를 통해root
사용자로 호스트에 로그인을 시도합니다. 로그인할 수 있는 각 호스트에 대해ok
응답을 보고합니다. 그렇지 않으면 서버에연결할 수 없음
이 있다고 보고하고 로그인할 수 있는 호스트에 대한 연극 작업 실행을 시작합니다. 이 설정을 수동으로 완료한 경우 이 자동화는ssh root@host-ip-address
를 사용하여 호스트에 로그인하는 것을 대체합니다.키워드 섹션 다음에는 순차적으로 실행할 작업 목록이 있습니다. 연극과 마찬가지로 각 작업은 작업이 수행할 작업에 대한 간단한 설명을 제공하는
이름
으로 시작합니다.작업 1: 캐시 업데이트
플레이북의 첫 번째 작업은 패키지 데이터베이스를 업데이트합니다.
... - name: update cache ansible.builtin.apt: update_cache: yes ...
이 작업은
ansible.builtin.apt
모듈을 사용하여 패키지 데이터베이스를 업데이트하므로update_cache: yes
로 정의됩니다. 이 작업은 Ubuntu 서버에 로그인하고sudo apt update
를 입력할 때와 동일한 작업을 수행하며, 종종 설치된 모든 패키지를 업데이트하기 위한 전주곡입니다.작업 2: 설치된 모든 패키지 업데이트
플레이북 업데이트 패키지의 두 번째 작업:
... - name: Update all installed packages ansible.builtin.apt: name: "*" state: latest ...
첫 번째 작업과 마찬가지로 이 작업도
ansible.builtin.apt
모듈을 호출합니다. 여기에서 패키지(name: \*\
) 및state: latest
를 지정하는 와일드카드를 사용하여 설치된 모든 패키지가 최신 상태인지 확인합니다. 서버에 로그인하고sudo apt upgrade -y
명령을 실행합니다.작업 3: NTP 서비스가 실행 중인지 확인
플레이북의 세 번째 작업은 NTP(Network Time Protocol) 데몬이 활성화되었는지 확인합니다.
... - name: Make sure NTP service is running ansible.builtin.systemd: state: started name: systemd-timesyncd ...
이 작업은
ansible.builtin.systemd
모듈을 호출하여systemd-timesyncd
, NTP 데몬이 실행 중인지 확인합니다(state: started
). 서버가 동일한 시간을 유지하도록 하려는 경우 이와 같은 작업을 실행하여 해당 서버에서 분산 응용 프로그램을 실행하는 데 도움이 될 수 있습니다.작업 4: sudo 그룹이 있는지 확인
플레이북의 네 번째 작업은
sudo
그룹이 있는지 확인합니다.... - name: Make sure we have a 'sudo' group ansible.builtin.group: name: sudo state: present ...
이 작업은
ansible.builtin.group
모듈을 호출하여sudo
라는 이름의 그룹이 호스트(state: present
)에 존재하는지 확인합니다. 다음 작업은 호스트에sudo
그룹이 있는지에 따라 달라지므로 이 작업은sudo
그룹이 있는지 확인하므로 다음 작업이 실패하지 않도록 할 수 있습니다. .작업 5: sudo 권한이 있는 사용자 만들기
플레이북의 다섯 번째 작업은
sudo
권한이 있는 루트가 아닌 사용자를 생성합니다.... - name: Create a user with sudo privileges ansible.builtin.user: name: "{{ create_user }}" state: present groups: sudo append: true create_home: true shell: /bin/bash password: "{{ password | password_hash('sha512', password_salt) }}" update_password: on_create ...
여기에서
ansible.builtin.user
모듈을 호출하고sudo
그룹을 사용자 그룹에 추가하여 각 호스트에서 사용자를 생성합니다. 사용자 이름은vars/default.yml
에서 지정한create_user
변수의 값에서 파생됩니다. 이 작업은 또한 사용자를 위한 홈 디렉토리가 생성되고 적절한 셸이 할당되도록 합니다.password
매개변수와 SHA-512 암호화 해시 알고리즘에서 설정한 비밀번호와 소금의 조합을 사용하여 사용자의 해시된 비밀번호를 생성합니다.비밀
볼트 파일과 쌍을 이루는 비밀번호는 일반 텍스트로 컨트롤러에 전달되지 않습니다.update_password
를 사용하면 사용자가 처음 생성될 때만 해시된 암호가 설정되도록 할 수 있습니다. 플레이북을 다시 실행하면 암호가 다시 생성되지 않습니다.작업 6: 원격 사용자를 위한 인증 키 설정
플레이북의 여섯 번째 작업은 사용자의 키를 설정합니다.
... - name: Set authorized key for remote user ansible.posix.authorized_key: user: "{{ create_user }}" state: present key: "{{ copy_local_key }}" ...
이 작업에서는
ansible.posix.authorized_key
를 호출하여 공개 SSH 키를 호스트에 복사합니다.user
의 값은 이전 작업에서 호스트에 생성된 사용자 이름이고key
는 복사할 키를 가리킵니다. 두 변수 모두var/default.yml
파일에 정의되어 있습니다. 이 작업은ssh-copy-id
명령을 수동으로 실행하는 것과 동일한 효과가 있습니다.작업 7: 루트에 대한 원격 로그인 비활성화
플레이북의 일곱 번째 작업은
root
사용자의 원격 로그인을 비활성화합니다.... - name: Disable remote login for root ansible.builtin.lineinfile: path: /etc/ssh/sshd_config state: present regexp: '^PermitRootLogin yes' line: 'PermitRootLogin no' ...
다음으로
ansible.builtin.lineinfile
모듈을 호출합니다. 이 작업은 정규식(regexp
)을 사용하여/etc/ssh/sshd_config
파일에서PermitRootLogin
으로 시작하는 줄을 검색한 다음line
의 값을 사용합니다. 이 작업은 이 플레이북에서 플레이를 실행한 후root
계정을 사용한 원격 로그인이 실패하도록 합니다. 작업 6에서 만든 사용자 계정을 사용한 원격 로그인만 성공합니다. 원격 루트 로그인을 비활성화하면 일반 사용자만 로그인할 수 있고 관리자 권한을 얻기 위해 일반적으로sudo
와 같은 권한 에스컬레이션 방법이 필요합니다.작업 8: SSH 포트 변경
플레이북의 여덟 번째 작업은 SSH 포트를 변경합니다.
... - name: Change the SSH port ansible.builtin.lineinfile: path: /etc/ssh/sshd_config state: present regexp: '^#Port 22' line: 'Port "{{ ssh_port }}"' ...
SSH는 잘 알려진 포트
22
에서 수신 대기하기 때문에 해당 포트를 대상으로 하는 자동화된 공격의 대상이 되는 경향이 있습니다. SSH가 수신 대기하는 포트를 변경하면 호스트를 공격하는 자동화된 공격의 수를 줄일 수 있습니다. 이 작업은 동일한ansible.builtin.lineinfile
모듈을 사용하여 SSH 데몬의 구성 파일에서regexp
로 시작하고 해당 값을 < 코드>라인 매개변수. SSH가 수신하는 새 포트 번호는 4단계에서ssh_port
변수에 할당한 포트 번호입니다. 이 플레이가 끝날 때 호스트를 다시 시작하면 로그인할 수 없습니다. 포트22
를 통해 호스트에.작업 9: UFW - SSH 연결 허용
플레이북의 아홉 번째 작업은 SSH 트래픽을 허용합니다.
... - name: UFW - Allow SSH connections community.general.ufw: rule: allow port: "{{ ssh_port }}" ...
여기에서 4단계를 호출합니다. 이 작업은
ufw allow 5995/tcp
명령을 수동으로 실행하는 것과 같습니다.작업 10: SSH에 대한 무차별 대입 시도 보호
열 번째 작업은 무차별 대입 공격으로부터 보호합니다.
... - name: Brute-force attempt protection for SSH community.general.ufw: rule: limit port: "{{ ssh_port }}" proto: tcp ...
community.general.ufw
모듈을 다시 호출하면 이 작업은 속도 제한규칙
을 사용하여 6회 이상의 연결 시도에 실패한 IP 주소에 대한 로그인 액세스를 거부합니다. 30초 기간 내의 SSH 포트.proto
매개변수는 대상 프로토콜(이 경우 TCP)을 가리킵니다.작업 11: UFW - 다른 수신 트래픽 거부 및 UFW 활성화
열한 번째 작업은 방화벽을 활성화합니다.
... - name: UFW - Deny other incoming traffic and enable UFW community.general.ufw: state: enabled policy: deny direction: incoming ...
이 작업에서 여전히
community.general.ufw
모듈에 의존하면서 방화벽을 활성화하고(state: enabled
) 기본정책
을 설정합니다. 들어오는 모든 트래픽을 거부합니다.작업 12: 더 이상 필요하지 않은 종속성 제거
이 연극의 열두 번째 작업은 패키지 종속성을 정리합니다.
... - name: Remove dependencies that are no longer required ansible.builtin.apt: autoremove: yes ...
ansible.builtin.apt
모듈을 다시 호출하여 이 작업은 서버에서 더 이상 필요하지 않은 패키지 종속성을 제거합니다. 이는sudo apt autoremove
명령을 실행하는 것과 동일합니다. 수동으로.작업 13: SSH 데몬 다시 시작
이 플레이북의 열세 번째 작업은 SSH를 다시 시작합니다.
... - name: Restart the SSH daemon ansible.builtin.systemd: state: restarted name: ssh
마지막 작업은
ansible.builtin.systemd
모듈을 호출하여 SSH 데몬을 다시 시작합니다. 데몬의 구성 파일에서 변경한 사항을 적용하려면 이 재시작을 수행해야 합니다. 이 작업은sudo systemctl restart ssh
를 사용하여 데몬을 다시 시작하는 것과 동일한 효과가 있습니다.호스트에 대한 초기 연결은
root
포트22
를 통해 이루어졌지만 이전 작업에서 포트 번호를 변경하고 원격 루트 로그인을 비활성화했기 때문에 SSH를 다시 시작해야 합니다. 극의 이 단계에서 데몬. 두 번째 플레이는 다른 연결 자격 증명(root
대신 사용자 이름 및22
가 아닌 새로 정의된 포트 번호)을 사용합니다.플레이 2: 초기 설정 후 호스트 재부팅
이 플레이는 플레이 1의 마지막 작업이 성공적으로 완료된 후 시작됩니다. 다음 키워드의 영향을 받습니다.
... - name: Rebooting hosts after initial setup hosts: initial port: "{{ ssh_port }}" remote_user: "{{ create_user }}" become: true vars_files: - vars/default.yml - ~/secret vars: ansible_become_pass: "{{ password }}" ...
hosts
키워드에 전달되는 패턴은 4단계에서/etc/ansible/hosts
파일에 지정된initial
그룹 이름입니다.첫 번째 플레이에서 Ansible 컨트롤러는
root
사용자로 호스트에 로그인했습니다. 첫 번째 플레이에서 원격 루트 로그인이 비활성화되었으므로 이제 Ansible 컨트롤러가 로그인해야 하는 사용자를 지정해야 합니다.remote_user
키워드는 Ansible 컨트롤러가 첫 번째 플레이의 작업 5에서 생성된sudo
사용자로 각 호스트에 로그인하도록 지시합니다.become
키워드는 정의된 호스트에서 작업 실행에 사용되는 권한 에스컬레이션을 지정합니다. 이 키워드는 필요할 때 호스트에서 작업을 실행하기 위한 루트 권한을 가정하도록 Ansible 컨트롤러에 지시합니다. 이 경우 컨트롤러는sudo
를 사용하여 루트 권한을 가정합니다.ansible_become_pass
키워드는 루트 권한을 가정하는 데 사용되는 암호인 권한 에스컬레이션 암호를 설정합니다. 이 경우 5단계에서 Ansible Vault를 사용하여 구성한 비밀번호로 변수를 가리킵니다.vars/default.yml
파일을 가리키는 것 외에도vars_files
키워드는 5단계에서 구성한비밀
파일도 가리킵니다.password
변수를 찾을 위치를 Ansible 컨트롤러에 알려줍니다.키워드 섹션 뒤에는 이 극에서 실행될 고독한 작업이 있습니다.
작업 14: 모든 호스트 재부팅
참고: 이것은 두 번째 플레이의 첫 번째 작업이지만 Ansible Controller는 이를 플레이 2의 태스크 1이 아니라 플레이북의 태스크 14로 보기 때문에 태스크 14로 번호가 지정됩니다.
플레이북의 마지막 작업은 모든 호스트를 재부팅합니다.
... - name: Reboot all hosts ansible.builtin.reboot:
첫 번째 플레이에서 작업을 완료한 후 호스트를 재부팅하면 애플리케이션 설치를 시작하기 전에 커널 또는 라이브러리에 대한 모든 업데이트가 적용됩니다.
전체 플레이북 파일은 다음과 같습니다.
- name: Initial server setup tasks hosts: initial remote_user: root vars_files: - vars/default.yml - secret tasks: - name: update cache ansible.builtin.apt: update_cache: yes - name: Update all installed packages ansible.builtin.apt: name: "*" state: latest - name: Make sure NTP service is running ansible.builtin.systemd: state: started name: systemd-timesyncd - name: Make sure we have a 'sudo' group ansible.builtin.group: name: sudo state: present - name: Create a user with sudo privileges ansible.builtin.user: name: "{{ create_user }}" state: present groups: sudo append: true create_home: true shell: /bin/bash password: "{{ password | password_hash('sha512', password_salt) }}" update_password: on_create - name: Set authorized key for remote user ansible.builtin.authorized_key: user: "{{ create_user }}" state: present key: "{{ copy_local_key }}" - name: Disable remote login for root ansible.builtin.lineinfile: path: /etc/ssh/sshd_config state: present regexp: '^PermitRootLogin yes' line: 'PermitRootLogin no' - name: Change the SSH port ansible.builtin.lineinfile: path: /etc/ssh/sshd_config state: present regexp: '^#Port 22' line: 'Port "{{ ssh_port }}"' - name: UFW - Allow SSH connections community.general.ufw: rule: allow port: "{{ ssh_port }}" - name: Brute-force attempt protection for SSH community.general.ufw: rule: limit port: "{{ ssh_port }}" proto: tcp - name: UFW - Deny other incoming traffic and enable UFW community.general.ufw: state: enabled policy: deny direction: incoming - name: Remove dependencies that are no longer required ansible.builtin.apt: autoremove: yes - name: Restart the SSH daemon ansible.builtin.systemd: state: restarted name: ssh - name: Rebooting hosts after initial setup hosts: initial port: "{{ ssh_port }}" remote_user: "{{ create_user }}" become: true vars_files: - vars/default.yml - secret vars: ansible_become_pass: "{{ password }}" tasks: - name: Reboot all hosts ansible.builtin.reboot:
파일 검토가 끝나면 저장하고 닫습니다.
참고: 플레이북에 새 작업을 추가하거나 기존 작업을 수정할 수 있습니다. 그러나 YAML은 간격에 민감하기 때문에 YAML 파일을 변경하면 파일이 손상될 수 있으므로 파일의 모든 측면을 편집할 경우 주의하십시오. Ansible 플레이북 작업에 대한 자세한 내용은 Ansible 플레이북 작성 방법 시리즈를 따르십시오.
이제 플레이북을 실행할 수 있습니다. 먼저 구문을 확인합니다.
- ansible-playbook --syntax-check --ask-vault-pass initial.yml
5단계에서 생성한 볼트 암호를 입력하라는 메시지가 표시됩니다. 인증에 성공한 후 YAML 구문에 오류가 없으면 출력은 다음과 같습니다.
Outputplaybook: initial.yml이제 다음 명령으로 파일을 실행할 수 있습니다.
- ansible-playbook --ask-vault-pass initial.yml
볼트 암호를 묻는 메시지가 다시 나타납니다. 인증에 성공하면 Ansible 컨트롤러는
root
사용자로 각 호스트에 로그인하고 플레이북의 모든 작업을 수행합니다. 각 서버에서 개별적으로ssh root@node-ip-address
명령을 실행하는 대신 Ansible은/etc/ansible/hosts
에 지정된 모든 노드에 연결합니다. 플레이북의 작업을 실행합니다.이 자습서의 샘플 호스트의 경우 Ansible이 3개 호스트에서 작업을 완료하는 데 약 3분이 걸렸습니다. 작업이 완료되면 다음과 같은 출력이 표시됩니다.
OutputPLAY RECAP ***************************************************************************************************** host1 : ok=16 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host2 : ok=16 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host3 : ok=16 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0성공적으로 평가된 각 작업 및 재생 키워드 섹션은
ok
열의 숫자에 포함됩니다. 두 번의 플레이에 걸쳐 14개의 작업이 있고 모두 성공적으로 평가된 경우 카운트는16
입니다. 평가된 작업 중11
만변경됨
열로 표시되는 서버의 변경으로 이어졌습니다.도달할 수 없는
수는 Ansible 컨트롤러가 로그인할 수 없는 호스트 수를 나타냅니다. 실패한 작업이 없으므로실패
의 수는0
입니다.작업에 지정된 조건이 충족되지 않으면 작업을
건너뜀
합니다(일반적으로when
매개변수 사용). 이 경우건너뛰는
작업은 없지만 8단계에서 적용할 수 있습니다.마지막 두 열(
rescued
및ignored
)은 재생 또는 작업에 대해 지정된 오류 처리와 관련됩니다.이제 플레이북에서 지정한 모든 작업을 완료하는 하나의 명령을 실행하기 위해 Ansible을 사용하여 여러 Ubuntu 22.04 서버의 초기 서버 설정을 성공적으로 자동화했습니다.
모든 것이 예상대로 작동하는지 확인하기 위해 호스트 중 하나에 로그인하여 설정을 확인합니다.
(선택 사항) 7단계 - 수동으로 서버 설정 확인
이전 단계 끝에서 재생 요약의 출력을 확인하려면 설정을 확인하기 위해 이전에 구성한 자격 증명을 사용하여 호스트 중 하나에 로그인할 수 있습니다. 이러한 작업은 Ansible 요약이 정확한 완료를 보고하기 때문에 학습 목적으로 선택 사항입니다.
다음 명령을 사용하여 호스트 중 하나에 로그인하여 시작합니다.
- ssh -p 5995 sammy@host1-public-ip-address
-p
옵션을 사용하여 6단계에서 SSH에 대해 구성한 사용자 지정 포트 번호를 가리킵니다. 해당 포트를 통해 해당 사용자로 호스트에 로그인할 수 있다면 Ansible은 이러한 작업을 성공적으로 완료했습니다.로그인한 후 패키지 데이터베이스를 업데이트할 수 있는지 확인하십시오.
- sudo apt update
암호를 입력하라는 메시지가 표시되고 5단계에서 사용자에 대해 구성한 암호로 인증할 수 있는 경우 Ansible이 사용자 생성 및 사용자 암호 설정 작업을 성공적으로 완료했음을 확인할 수 있습니다.
이제 설정 플레이북이 의도한 대로 작동했음을 알았으므로 지속적인 유지 관리를 위해 두 번째 플레이북을 실행할 수 있습니다.
(선택 사항) 8단계 - 호스트의 지속적인 유지 관리를 위해 Ansible 사용
3단계에서 실행한 초기 서버 설정 플레이북에서 지속적인 유지 관리에 사용할 수 있는
ongoing.yml
플레이북도 가져왔습니다. 이 단계에서는ongoing.yml
플레이북을 실행하여 이 자습서에서 설정한 호스트의 지속적인 유지 관리를 자동화합니다.플레이북을 실행하기 전에 각 작업을 검토합니다. 시작하려면
nano
또는 선호하는 텍스트 편집기로 파일을 엽니다.- nano ongoing.yml
초기 설정 플레이북과 달리 유지 관리 플레이북에는 단 하나의 플레이와 더 적은 수의 작업만 포함됩니다.
플레이 1:
파일의 첫 번째 섹션에 있는 다음 키워드는 연극의 동작에 영향을 미칩니다.
- hosts: ongoing port: "{{ ssh_port }}" remote_user: "{{ create_user }}" become: true vars_files: - vars/default.yml - secret vars: ansible_become_pass: "{{ password }}" ...
hosts
키워드에 전달된 그룹 외에 설정 플레이북의 두 번째 플레이에서 사용된 것과 동일한 키워드입니다.키워드 뒤에는 순차적으로 실행할 작업 목록이 있습니다. 설정 플레이북에서와 같이 유지 관리 플레이북의 각 작업은 수행할 작업에 대한 간단한 설명을 제공하는
이름
으로 시작합니다.작업 1: 캐시 업데이트
첫 번째 작업은 패키지 데이터베이스를 업데이트합니다.
... - name: update cache ansible.builtin.apt: update_cache: yes ...
이 작업은
ansible.builtin.apt
모듈을 사용하여 패키지 데이터베이스를 업데이트하므로update_cache: yes
로 정의됩니다. 이 작업은 Ubuntu 서버에 로그인하고sudo apt update
를 입력할 때와 동일한 작업을 수행합니다. 이는 종종 패키지를 설치하거나 설치된 모든 패키지를 업데이트하기 위한 전주곡입니다.작업 2: 설치된 모든 패키지 업데이트
두 번째 작업은 패키지를 업데이트합니다.
... - name: Update all installed packages ansible.builtin.apt: name: "*" state: latest ...
첫 번째 작업과 마찬가지로 이 작업도
ansible.builtin.apt
모듈을 호출합니다. 여기에서 패키지(name: \*\
) 및state: latest
를 지정하는 와일드카드를 사용하여 설치된 모든 패키지가 최신 상태인지 확인합니다. 서버에 로그인하고sudo apt upgrade -y
명령을 실행합니다.작업 3: NTP 서비스가 실행 중인지 확인
플레이북의 세 번째 작업은 NTP 데몬이 설정되었는지 확인합니다.
... - name: Make sure NTP service is running ansible.builtin.systemd: state: started name: systemd-timesyncd ...
서버의 활성 서비스는 다양한 이유로 실패할 수 있으므로 이러한 서비스가 활성 상태로 유지되도록 해야 합니다. 이 작업은
ansible.builtin.systemd
모듈을 호출하여 NTP 데몬인systemd-timesyncd
가 활성 상태로 유지되도록 합니다(state: started
).작업 4: UFW - 실행 중입니까?
네 번째 작업은 UFW 방화벽의 상태를 확인합니다.
... - name: UFW - Is it running? ansible.builtin.command: ufw status register: ufw_status ...
sudo ufw status
명령을 사용하여 Ubuntu에서 UFW 방화벽의 상태를 확인할 수 있습니다. 출력의 첫 번째 줄에는Status: active
또는Status: inactive
가 표시됩니다. 이 작업은ansible.builtin.command
모듈을 사용하여 동일한 명령을 실행한 다음 출력을ufw_status에 저장(
변수. 해당 변수의 값은 다음 작업에서 쿼리됩니다.등록
)합니다.작업 5: UFW - UFW 활성화 및 들어오는 트래픽 거부
다섯 번째 작업은 중지된 경우 UFW 방화벽을 다시 활성화합니다.
... - name: UFW - Enable UFW and deny incoming traffic community.general.ufw: state: enabled when: "'inactive' in ufw_status.stdout" ...
이 작업은
community.general.ufw
모듈을 호출하여ufw_status의 출력에
변수. 방화벽이 활성화되어 있으면inactive
라는 용어가 나타날 때만 방화벽을 활성화합니다.when
조건이 충족되지 않고 작업이건너뜀
으로 표시됩니다.작업 6: 더 이상 필요하지 않은 종속성 제거
이 플레이북의 여섯 번째 작업은 패키지 종속성을 정리합니다.
... - name: Remove dependencies that are no longer required ansible.builtin.apt: autoremove: yes ...
이 작업은
ansible.builtin.apt
모듈을 호출하여 서버에서 더 이상 필요하지 않은 패키지 종속성을 제거합니다. 이는sudo apt autoremove
명령을 실행하는 것과 같습니다.작업 7: 재부팅이 필요한지 확인
일곱 번째 작업은 재부팅이 필요한지 확인합니다.
... - name: Check if reboot required ansible.builtin.stat: path: /var/run/reboot-required register: reboot_required ...
Ubuntu에서 새로 설치되거나 업그레이드된 패키지는
/var/run/reboot-required
파일을 생성하여 설치 또는 업그레이드로 도입된 변경 사항을 적용하려면 재부팅이 필요하다는 신호를 보냅니다.stat /var/run/reboot-required
명령을 사용하여 해당 파일이 존재하는지 확인할 수 있습니다. 이 작업은ansible.builtin.stat
모듈을 호출하여 동일한 작업을 수행한 다음 출력을reboot_required에 저장(
변수. 해당 변수의 값은 다음 작업에서 쿼리됩니다.등록
)합니다.작업 8: 필요한 경우 재부팅
여덟 번째 작업은 필요한 경우 서버를 재부팅합니다.
... - name: Reboot if required ansible.builtin.reboot: when: reboot_required.stat.exists == true
작업 7에서
reboot_required
변수를 쿼리하여 이 작업은ansible.builtin.reboot
모듈을 호출하여 호스트를경우
에만 재부팅합니다./var/run/reboot-required
가 존재합니다. 재부팅이 필요하고 호스트가 재부팅되면 작업이변경됨
으로 표시됩니다. 그렇지 않으면 Ansible이 재생 요약에서건너뛰기
로 표시합니다.지속적인 유지 관리를 위한 전체 플레이북 파일은 다음과 같습니다.
- hosts: ongoing port: "{{ ssh_port }}" remote_user: "{{ create_user }}" become: true vars_files: - vars/default.yml - secret vars: ansible_become_pass: "{{ password }}" tasks: - name: update cache ansible.builtin.apt: update_cache: yes - name: Update all installed packages ansible.builtin.apt: name: "*" state: latest - name: Make sure NTP service is running ansible.builtin.systemd: state: started name: systemd-timesyncd - name: UFW - Is it running? ansible.builtin.command: ufw status register: ufw_status - name: UFW - Enable UFW and deny incoming traffic community.general.ufw: state: enabled when: "'inactive' in ufw_status.stdout" - name: Remove dependencies that are no longer required ansible.builtin.apt: autoremove: yes - name: Check if reboot required ansible.builtin.stat: path: /var/run/reboot-required register: reboot_required - name: Reboot if required ansible.builtin.reboot: when: reboot_required.stat.exists == true
파일 검토가 끝나면 저장하고 닫습니다.
참고: 플레이북에서 새 작업을 추가하거나 기존 작업을 수정할 수 있습니다. 그러나 YAML은 간격에 민감하기 때문에 YAML 파일을 변경하면 파일이 손상될 수 있으므로 파일의 모든 측면을 편집할 경우 주의하십시오. Ansible 플레이북 작업에 대한 자세한 내용은 Ansible 플레이북 작성 방법 시리즈를 따르십시오.
이제 파일을 실행할 수 있습니다. 먼저 구문을 확인합니다.
- ansible-playbook --syntax-check --ask-vault-pass ongoing.yml
5단계에서 생성한 볼트 암호를 입력하라는 메시지가 표시됩니다. 인증에 성공한 후 YAML 구문에 오류가 없으면 출력은 다음과 같습니다.
Outputplaybook: ongoing.yml이제 다음 명령으로 파일을 실행할 수 있습니다.
- ansible-playbook --ask-vault-pass ongoing.yml
볼트 암호를 입력하라는 메시지가 표시됩니다. 인증에 성공한 후 Ansible 컨트롤러는 각 호스트에
sammy
(또는 지정한 사용자 이름)로 로그인하여 플레이북의 작업을 수행합니다. 각 서버에서 개별적으로ssh -p 5995 sammy@host_ip_address
명령을 실행하는 대신 Ansible은 노드에 연결합니다./etc/ansible/hosts
의ongoing
그룹에서 지정한 다음 플레이북의 작업을 실행합니다.명령이 성공적으로 완료되면 다음 출력이 인쇄됩니다.
OutputPLAY RECAP ***************************************************************************************************** host1 : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 host2 : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 host3 : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0초기 서버 설정에 대한 재생 요약과 달리 이 재생 요약은
when
매개변수로 각 작업에 대해 설정된 조건이 충족되지 않았기 때문에건너뛴
두 작업을 기록합니다.각 호스트에 수동으로 로그인할 필요 없이 이 플레이북을 사용하여 호스트를 유지할 수 있습니다. 호스트에서 애플리케이션을 빌드하고 설치할 때 플레이북에 작업을 추가하여 Ansible로 해당 애플리케이션을 관리할 수도 있습니다.
결론
이 자습서에서는 Ansible을 사용하여 여러 Ubuntu 22.04 서버의 초기 설정을 자동화했습니다. 또한 해당 서버의 지속적인 유지 관리를 위해 보조 플레이북을 실행했습니다. Ansible 자동화는 분산 또는 클러스터 모드에서 MinIO와 같은 애플리케이션을 설정해야 할 때 시간을 절약해 주는 도구입니다.
Ansible에 대한 자세한 내용은 구성 관리 101: Ansible 플레이북 작성에서 확인할 수 있습니다.