스터디

A101 - 1주차

willamette 2024. 1. 14. 04:04

1주차

aws cloudformation describe-stacks --stack-name **mylab** --query 'Stacks[*].**Outputs[0]**.OutputValue' --output text --region ap-northeast-2

실습 환경

  • 마스터 노드 내 hosts 파일에 도메인 수동 매핑
  • 10.10.1.10 server 10.10.1.11 tnode1 10.10.1.12 tnode2 10.10.1.13 tnode3 # 키 복사 for i in {1..3}; do **ssh-copy-id root@tnode$i**; done

인벤토리: 관리할 대상 호스트를 지정, ini/yaml 스타일

# 범위 설정 : 192.168.4.0 ~ 192.168.4.255 사이의 IP 범위를 표현
[master]
db[01:03].foo.link 

# datacenter 그룹이 webserver, dbservers를 자식으로 포함할 때 
[webservers]
web1.example.com
web2.example.com

[db-servers]
db01.example.com
db02.example.com

[datacenter:children]
webservers
dbservers

플레이북 환경설정: ansible.cfg

변수

우선순위: 추 변수 > 플레이 변수 > 호스트 변수 > 그룹 변수

  • 그룹 변수: 인벤토리에 정의된 호스트 그룹에 적용되는 변수
    • 그룹 변수를 이용해 해당 그룹 내에서 카운팅을 한다면
    # inventory
    [web]
    tnode1
    tnode2
    
    [db]
    tnode3
    
    [all:children]
    web
    db
    
    [replica]
    tnode1
    tnode2
    
    [replica:vars]
    special_user = archon
    
# create-user.yml
---
- hosts: replica
  tasks:
  - name: Create User {{ special_user }}
    ansible.builtin.user:
      name: "{{ special_user }}"
      state: present 
  - name: Create User with populate vars
    ansible.builtin.user: 
      name: "{{ special_user + ansible_play_hosts | length | string }}"
      state: present
$ ansible-playbook create-user.yml --check --diff -vvv
...
changed: [tnode2] => {
    "changed": true,
    "invocation": {
        "module_args": {
            "append": false,
            "authorization": null,
            "comment": null,
            "create_home": true,
            "expires": null,
            "force": false,
            "generate_ssh_key": null,
            "group": null,
            "groups": null,
            "hidden": null,
            "home": null,
            "local": null,
            "login_class": null,
            "move_home": false,
            "name": "archon2",
            "non_unique": false,
            "password": null,
            "password_expire_max": null,
            "password_expire_min": null,
            "password_lock": null,
            "profile": null,
            "remove": false,
            "role": null,
            "seuser": null,
            "shell": null,
            "skeleton": null,
            "ssh_key_bits": 0,
            "ssh_key_comment": "ansible-generated on tnode2",
            "ssh_key_file": null,
            "ssh_key_passphrase": null,
            "ssh_key_type": "rsa",
            "state": "present",
            "system": false,
            "uid": null,
            "umask": null,
            "update_password": "always"
        }
    }
}

...
changed: [tnode1] => {
    "changed": true,
    "invocation": {
        "module_args": {
            "append": false,
            "authorization": null,
            "comment": null,
            "create_home": true,
            "expires": null,
            "force": false,
            "generate_ssh_key": null,
            "group": null,
            "groups": null,
            "hidden": null,
            "home": null,
            "local": null,
            "login_class": null,
            "move_home": false,
            "name": "archon2",
            "non_unique": false,
            "password": null,
            "password_expire_max": null,
            "password_expire_min": null,
            "password_lock": null,
            "profile": null,
            "remove": false,
            "role": null,
            "seuser": null,
            "shell": null,
            "skeleton": null,
            "ssh_key_bits": 0,
            "ssh_key_comment": "ansible-generated on tnode1",
            "ssh_key_file": null,
            "ssh_key_passphrase": null,
            "ssh_key_type": "rsa",
            "state": "present",
            "system": false,
            "uid": null,
            "umask": null,
            "update_password": "always"
        }
    }
}

PLAY RECAP *********************************************************************************************************************************************************
tnode1                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  • 호스트 변수: 해당 호스트에서만 사용 가능, 인벤토리에서 해당 호스트에 인라인으로 정의
  • # inventory [web] tnode1 user=nginx
  • 플레이 변수: 플레이북 내에서 선언된 변수
  • # <https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#defining-variables-in-included-files-and-roles> # users.yml user: templer # create-user.yml - hosts: all var_files: - users.yml tasks: - name: create user {{ user }} #파일명 기재 필요없이 바로 변수명 참조 가능
  • 추가 변수: ansible 실행 시 인라인 아규먼트로 넘겨주는 변수 ansible-playbook -e user=templer ...
  • 작업 변수: 플레이 결과를 저장하기 위한 변수

vault

root@server:~/my-ansible# ansible-vault create userdata.yml
New Vault password: qwe123
Confirm New Vault password: qwe123

root@server:~/my-ansible# ansible-vault view userdata.yml 
Vault password: oops
ERROR! Decryption failed (no vault secrets were found that could decrypt) on userdata.yml for userdata.yml

root@server:~/my-ansible# ansible-vault view userdata.yml 
Vault password: qwe123
>> 
password: qwe123

root@server:~/my-ansible# cat userdata.yml 
$ANSIBLE_VAULT;1.1;AES256
64363633616336623064396337346230623739643362303532303831343739386338366166393232
6236313531333864613763646538316637346533386437660a333536663861343330396234316361
31336234636430623961326262393763613434663963393731396537346461326335623262303831
3561376130653532320a326133373462386235613636663031306232663836376435333630376234
65623632393436653937363437633830653131646666393037323932326633326630

root@server:~/my-ansible# ansible-playbook --vault-id @prompt create-user.yml

facts = 대상 호스트 정보

역시 이런 IaC에선 호스트 정보 스크래핑이 빠질 수가 없다.

saltstack에서 grains와 거의 동일해보임 https://docs.saltproject.io/en/latest/topics/grains/index.html

---
- hosts: all
  tasks:
  - name: Print all facts
    ansible.builtin.debug:
      var: ansible_facts
  - debug:
      msg: |
        hostname: {{ ansible_facts.hostname }}
        distributioni: {{ ansible_facts.distribution }}

TASK [debug] *******************************************************************************************************************************************************
ok: [tnode1] => {
    "msg": "hostname: tnode1\\ndistributioni: Ubuntu\\n"
}
ok: [tnode2] => {
    "msg": "hostname: tnode2\\ndistributioni: Ubuntu\\n"
}
  • 만약 모종의 사유로 fact 수집을 비활성화 하고 싶다면 https://november11tech.tistory.com/108
  • --- - hosts: all gather_facts: no 와 같이 하면 다음과 같은 Fact gathering이 안 나올 것임 TASK [Gathering Facts] ********************************************************************************************************************************************* ok: [tnode2] ok: [tnode1]

도전과제

# uptime 확인
---
- hosts: replica
  tasks:
  - name: get uptime
    ansible.builtin.shell: /usr/bin/uptime
    register: uptime

  - debug:
      var: uptime

TASK [debug] *******************************************************************************************************************************************************
ok: [tnode1] => {
    "uptime": {
        "changed": true,
        "cmd": "/usr/bin/uptime",
        "delta": "0:00:00.007493",
        "end": "2024-01-14 02:48:26.050096",
        "failed": false,
        "msg": "",
        "rc": 0,
        "start": "2024-01-14 02:48:26.042603",
        "stderr": "",
        "stderr_lines": [],
        "stdout": " 02:48:26 up  1:39,  1 user,  load average: 0.23, 0.05, 0.02",
        "stdout_lines": [
            " 02:48:26 up  1:39,  1 user,  load average: 0.23, 0.05, 0.02"
        ]
    }
}
ok: [tnode2] => {
    "uptime": {
        "changed": true,
        "cmd": "/usr/bin/uptime",
        "delta": "0:00:00.007402",
        "end": "2024-01-14 02:48:25.998745",
        "failed": false,
        "msg": "",
        "rc": 0,
        "start": "2024-01-14 02:48:25.991343",
        "stderr": "",
        "stderr_lines": [],
        "stdout": " 02:48:25 up  1:39,  1 user,  load average: 0.11, 0.03, 0.01",
        "stdout_lines": [
            " 02:48:25 up  1:39,  1 user,  load average: 0.11, 0.03, 0.01"
        ]
    }
}
# fact 이용한 커널 버전 확인
- name: Print all facts
    ansible.builtin.debug:
      var: ansible_facts
  - debug:
      msg: |
        kernel version: {{ ansible_facts.kernel }}
        distributioni: {{ ansible_facts.distribution }}

꿀팁

  • ansible-playbook --syntax-check : syntax check
  • ansible-playbook --check : dry-run