Windows 10 이후 버전에서 Windows terminal 을 사용할 수 있다.

뿐만 아니라 OS 자체에 ssh 를 기본적으로 제공함으로서 cmd 나 powershell 에서 불편했던 WSL 이나 Linux 를 관리하는데 유용하게 사용할 수 있다.

 

Windows Terminal 설치

https://docs.microsoft.com/ko-kr/windows/terminal/install

Microsoft Store 에서 Windows Terminal 을 검색하여 설치하면 된다.

Windows Terminal 의 Pane 기능

Windows Terminal 을 사용하면서 하나의 세션에서 화면을 분할하는 창(Pane) 기능을 활용하면 새로운 세션을 생성하거나 탭을 활용하는 것보다 시각적으로 효과적이다. Linux 의 tmux 와 동일한 기능이다.

 

Windows Terminal 의 Pane 활용 단축키 

새로운 창 (세로로 만들기) : [alt] + [shift] + [+]

새로운 창 (가로로 만들기) :  [alt] + [shift] + [-]

창 크기 조정 :  [alt] + [shift] + [방향키]

창 이동하기 :  [alt] + [방향키]

 

Windows Terminal 의 Pane 활용 예시

새로운 창 (세로 옆으로 만들기) : [alt] + [shift] + [+]

새로운 창 (가로 아래에 만들기) :  [alt] + [shift] + [-]

창 크기 조정 :  [alt] + [shift] + [방향키]

 

창 이동하기 :  [alt] + [방향키]

하나의 창에서 다른 창으로 포커스를 이동하는 방법입니다. 

 

 

이번 포스트에서는 Windows Terminal 에서 Pane 을 활용하는 방법을 알아 봤습니다.

간단하네요.

지난 번에 이어 몇가지 모듈을 더 살펴 보겠습니다.

 

(6) 명령 수행

특정 명령을 수행하는 시나리오 입니다.

[root@labco7ans ansible]# cat 07.command.yml
---
- hosts: win
  gather_facts: no
  tasks:
  - name: run an executable using win_command
    win_command: whoami.exe

  - name: run a cmd command
    win_command: cmd.exe /c mkdir C:\test
    
[root@labco7ans ansible]# ansible-playbook -i hosts 07.command.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [run an executable using win_command] ***************************************************************************************************************************
changed: [172.16.3.106]

TASK [run a cmd command] *********************************************************************************************************************************************
changed: [172.16.3.106]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

생성되었습니다.

PS C:\> dir

    Directory: C:\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
<생략>
d-----        6/29/2020   4:33 PM                Temp
d-----        6/30/2020  10:35 AM                test
d-r---        6/29/2020   4:46 PM                Users
d-----        6/29/2020   4:45 PM                Windows

그런데 이를 한번 더 실행하면 어떨까요?

[root@labco7ans ansible]# ansible-playbook -i hosts 07.command.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [run an executable using win_command] ***************************************************************************************************************************
changed: [172.16.3.106]

TASK [run a cmd command] *********************************************************************************************************************************************
fatal: [172.16.3.106]: FAILED! => {"changed": true, "cmd": "cmd.exe /c mkdir C:\\test", "delta": "0:00:00.140629", "end": "2020-06-30 01:35:51.440674", "msg": "non-zero return code", "rc": 1, "start": "2020-06-30 01:35:51.300045", "stderr": "A subdirectory or file C:\\test already exists.\r\n", "stderr_lines": ["A subdirectory or file C:\\test already exists."], "stdout": "", "stdout_lines": []}

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=1    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

stderr로 "A subdirectory or file C:\\test already exists.\r\n" 이 발생합니다.

이러한 command는 멱등성의 단위가 아닌 별개의 작업으로 간주됩니다.

한가지 더 살펴볼 것은 앞서 살펴본 예제에서도 있던 register입니다. register 를 whoami.exe 결과를 받아오는데 사용될 수도 있습니다. 예제를 조금 수정했습니다.

[root@labco7ans ansible]# cat 07.command2.yml
---
- hosts: win
  gather_facts: no
  tasks:
  - name: run an executable using win_command
    win_command: whoami.exe
    register: output
  - debug: msg="{{ output.stdout }}"

[root@labco7ans ansible]# ansible-playbook -i hosts 07.command2.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [run an executable using win_command] ***************************************************************************************************************************
changed: [172.16.3.106]

TASK [debug] *********************************************************************************************************************************************************
ok: [172.16.3.106] => {
    "msg": "labw16ans\\administrator\r\n"
}

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

(7) 환경 변수 설정

시스템 환경변수를 추가하는 시나리오 입니다.

[root@labco7ans ansible]# cat 08.env.yml
---
- hosts: win
  gather_facts: no
  tasks:
  - name: Set an environment variable for all users
    win_environment:
      state: present
      name: NewVariable
      value: New Value
      level: machine

[root@labco7ans ansible]# ansible-playbook -i hosts 08.env.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [Set an environment variable for all users] *********************************************************************************************************************
changed: [172.16.3.106]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

아래와 같이 생성되었습니다.

C:\Users\User1>set |findstr New
NewVariable=New Value

Windows 서버의 환경변수는 시스템 환경변수와 사용자 환경변수로 나뉩니다. 이를 level로 정의합니다. 하기 참고하시기 바랍니다. 

공식문서의 Notes에서도 언급된 내용은, 이 module 자체가 변경사항을 전파하지 않는다는 점입니다(This module does not broadcast change events). 그러하므로 변경사항을 세션이나 시스템에 반영하기 위해 새로운 세션을 생성하거나 reboot이 필요할 수 있습니다.

참고: https://docs.ansible.com/ansible/latest/modules/win_environment_module.html#win-environment-module

 

자매품으로 win_path 모듈로 세부 element를 수정할 수 있습니다. 기본적인 환경변수 추가는 win_envrionment를 사용하시기 바랍니다.

참고: https://docs.ansible.com/ansible/latest/modules/win_path_module.html#win-path-module

 

(8) 레지스트리 관리

레지스트리를 관리하는 시나리오는 아래와 같습니다.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters의 CrashOnCtrlScroll를 1로 세팅

[root@labco7ans ansible]# cat 09.reg.yml
---
- hosts: win
  gather_facts: no
  tasks:
  - name: Add or update registry with dword entry 'CrashOnCtrlScroll', and containing 1 as the hex value
    win_regedit:
      path: HKLM:\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters
      name: CrashOnCtrlScroll
      data: 0x1
      type: dword
      
[root@labco7ans ansible]# ansible-playbook -i hosts 09.reg.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [Add or update registry with dword entry 'CrashOnCtrlScroll', and containing 1 as the hex value] ****************************************************************
changed: [172.16.3.106]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

아래와 같이 값이 입력되었습니다.

<사전>
C:\>reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters
    WorkNicely    REG_DWORD    0x0

<사후>
C:\>reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters
    WorkNicely    REG_DWORD    0x0
    CrashOnCtrlScroll    REG_DWORD    0x1

다른 방법은 별도의 reg 파일을 작성 후 win_regmerge로 적용시킬 수도 있습니다. 이 경우 앞서 살펴본 win_copy로 필요한 reg 파일을 전달하고 적용시킬 수 있습니다.

참고: https://docs.ansible.com/ansible/latest/modules/win_regmerge_module.html#win-regmerge-module

 

(9) 페이지파일 설정

페이지 파일을 설정하는 시나리오입니다.

[root@labco7ans ansible]# ansible win -i hosts -m win_pagefile
172.16.3.106 | SUCCESS => {
    "automatic_managed_pagefiles": true,
    "changed": false,
    "pagefiles": []
}

[root@labco7ans ansible]# cat 10.pagefile.yml
---
- hosts: win
  gather_facts: no
  tasks:
  - name: Disable AutomaticManagedPagefile and set C pagefile
    win_pagefile:
      drive: C
      initial_size: 2048
      maximum_size: 2048
      automatic: no
      state: present

[root@labco7ans ansible]# ansible-playbook -i hosts 10.pagefile.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [Disable AutomaticManagedPagefile and set C pagefile] ***********************************************************************************************************
changed: [172.16.3.106]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[root@labco7ans ansible]# ansible win -i hosts -m win_pagefile
172.16.3.106 | SUCCESS => {
    "automatic_managed_pagefiles": false,
    "changed": false,
    "pagefiles": [
        {
            "caption": "C:\\ 'pagefile.sys'",
            "description": "'pagefile.sys' @ C:\\",
            "initial_size": 2048,
            "maximum_size": 2048,
            "name": "C:\\pagefile.sys"
        }
    ]
}

페이지 파일 세팅을 적용하기 위해 reboot이 필요할 수 있습니다. reboot 시나리오를 추가했습니다. pagefile 단계가 changed 상태가되면 reboot이 진행되는 시나리오입니다.

[root@labco7ans ansible]# cat 10.pagefile2.yml
---
- hosts: win
  gather_facts: no
  tasks:
  - name: Disable AutomaticManagedPagefile and set C pagefile
    win_pagefile:
      drive: C
      initial_size: 4096
      maximum_size: 4096
      automatic: no
      state: present
    register: pagefile

  - name: Reboot server
    win_reboot:
      msg: "Page file moved,rebooting..."
      pre_reboot_delay: 15
    when: pagefile.changed
    
[root@labco7ans ansible]# ansible-playbook -i hosts 10.pagefile2.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [Disable AutomaticManagedPagefile and set C pagefile] ***********************************************************************************************************
changed: [172.16.3.106]

TASK [Reboot server] *************************************************************************************************************************************************
changed: [172.16.3.106]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[root@labco7ans ansible]# ansible win -i hosts -m win_pagefile
172.16.3.106 | SUCCESS => {
    "automatic_managed_pagefiles": false,
    "changed": false,
    "pagefiles": [
        {
            "caption": "C:\\ 'pagefile.sys'",
            "description": "'pagefile.sys' @ C:\\",
            "initial_size": 4096,
            "maximum_size": 4096,
            "name": "C:\\pagefile.sys"
        }
    ]
}

 

(10) 로컬 보안 정책 관리

로컬 보안 정책(secpol)을 변경하는 시나리오입니다.

먼저 secedit을 export해서 변경하려는 값을 살펴 봅니다.

C:\>SecEdit.exe /export /cfg C:\temp\output.ini

The task has completed successfully.
See log %windir%\security\logs\scesrv.log for detail info.

C:\>type C:\temp\output.ini
[Unicode]
Unicode=yes
[System Access]
MinimumPasswordAge = 0
MaximumPasswordAge = 42
MinimumPasswordLength = 0
PasswordComplexity = 1
<생략>

MaximumPasswordAge 을 90으로 변경해 보는 시나리오를 수행해보겠습니다.

파일에서 확인한 내용으로 section에서 [System Access] 를 필요한 key와 value 를 각각 설정합니다.

[root@labco7ans ansible]# cat 11.secpol.yml
---
- hosts: win
  gather_facts: no
  tasks:
  - name: Set the maximum password age
    win_security_policy:
      section: System Access
      key: MaximumPasswordAge
      value: 90
      
[root@labco7ans ansible]# ansible-playbook -i hosts 11.secpol.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [Set the maximum password age] **********************************************************************************************************************************
changed: [172.16.3.106]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

아래와 같이 변경되었습니다.

C:\>SecEdit.exe /export /cfg C:\temp\output2.ini

The task has completed successfully.
See log %windir%\security\logs\scesrv.log for detail info.

C:\>type C:\temp\output2.ini | findstr Password
MinimumPasswordAge = 0
MaximumPasswordAge = 90
MinimumPasswordLength = 0
PasswordComplexity = 1
PasswordHistorySize = 0
<생략>

 

(11) 업데이트 적용

윈도우즈의 패치는 아래와 같이 진행할 수 있습니다.

- name: Install all critical and security updates
  win_updates:
    category_names:
    - CriticalUpdates
    - SecurityUpdates
    state: installed
  register: update_result

- name: Reboot host if required
  win_reboot:
  when: update_result.reboot_required

다만 Windows 서버의 업데이트는 약간의 복잡성을 가지고 있습니다. 상기의 시나리오는 MS나 WSUS 로의 업데이트가 가능한 환경이라는 전제가 되있어야합니다.

Air-gapped 환경이라면 아래와 같은 시나리오도 생각해 볼 수 있습니다.

  • 웹서버 세팅 > 업데이트 파일을 Docroot에 복사 > playbook (win_get_url + win_hotfix로 설치)

업데이트 파일 이동을 위해 win_copy를 생각할 수도 있겠지만 win_copy의 경우 WinRM 상에서 동작하므로 용량이 큰 경우 효과적이지 않습니다 (Because win_copy runs over WinRM, it is not a very efficient transfer mechanism. If sending large files consider hosting them on a web service and using [win_get_url](https://docs.ansible.com/ansible/latest/modules/win_get_url_module.html#win-get-url-module) instead.) 공식문서의 커맨트를 따라 win_get_url을 사용했습니다.

혹은 download.windowsupdate.com을 URL 방화벽으로 오픈이 가능하다면 아래와 같이 진행할 수도 있습니다.

- name: Download KB3172729 for Server 2012 R2
  win_get_url:
    url: http://download.windowsupdate.com/d/msdownload/update/software/secu/2016/07/windows8.1-kb3172729-x64_e8003822a7ef4705cbb65623b72fd3cec73fe222.msu
    dest: C:\temp\KB3172729.msu

- name: Install hotfix
  win_hotfix:
    hotfix_kb: KB3172729
    source: C:\temp\KB3172729.msu
    state: present
  register: hotfix_result

- name: Reboot host if required
  win_reboot:
  when: hotfix_result.reboot_required

마지막 시나리오로 SSU 업데이트를 적용해 보겠습니다.

[root@labco7ans ansible]# cat 12.update.yml
---
- hosts: win
  gather_facts: no
  tasks:
  - name: Download SSU(KB4550994) for Server 2016
    win_get_url:
      url: http://download.windowsupdate.com/c/msdownload/update/software/secu/2020/04/windows10.0-kb4550994-x64_1df8a8ea245041495f3b219fb22f3849908d8e27.msu
      dest: C:\temp\KB4550994.msu

  - name: Install hotfix
    win_hotfix:
      hotfix_kb: KB4550994
      source: C:\temp\KB4550994.msu
      state: present
    register: hotfix_result

  - name: Reboot host if required
    win_reboot:
    when: hotfix_result.reboot_required
    
[root@labco7ans ansible]# ansible-playbook -i hosts 12.update.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [Download SSU(KB4550994) for Server 2016] ***********************************************************************************************************************
changed: [172.16.3.106]

TASK [Install hotfix] ************************************************************************************************************************************************
changed: [172.16.3.106]

TASK [Reboot host if required] ***************************************************************************************************************************************
skipping: [172.16.3.106]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=2    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

SSU 패치라 reboot task는 skip 되었고, 아래 결과를 보면 KB4550994 가 설치된 것을 알 수 있습니다.

C:\>wmic qfe
Caption                                     CSName     Description      FixComments  HotFixID   InstallDate  InstalledBy              InstalledOn  Name  ServicePackInEffect  Status
http://support.microsoft.com/?kbid=3192137  LABW16ANS  Update                        KB3192137               NT AUTHORITY\SYSTEM      9/12/2016
http://support.microsoft.com/?kbid=4550994  LABW16ANS  Security Update               KB4550994               LABW16ANS\Administrator  6/30/2020

이를 마지막으로 Windows 서버에서 ansible을 활용해 사용해볼만한 Windows Module을 살펴봤습니다.

 

 

참고

https://docs.ansible.com/ansible/latest/modules/win_feature_module.html#win-feature-module

https://docs.ansible.com/ansible/latest/user_guide/windows_usage.html#use-cases

https://geekflare.com/ansible-playbook-windows-example/

'IaC' 카테고리의 다른 글

ansible - windows 모듈 (1)  (0) 2022.02.04

ansible 에서 Windows 서버를 관리하기 위해 활용할 수 있는 몇가지 모듈을 살펴보겠습니다.

 

 

(1) 정보 가져오기

setup 모듈을 확인을 해보면 ansible_facts에 다양한 정보를 가져올 수 있습니다.

[root@labco7ans ansible]# ansible -i hosts win -m setup
172.16.3.106 | SUCCESS => {
    "ansible_facts": {
        "ansible_architecture": "64-bit",
        "ansible_bios_date": "11/26/2012",
        "ansible_bios_version": "Hyper-V UEFI Release v1.0",
<생략>
}

이를 아래와 같이 활용할 수 있습니다.

[root@labco7ans ansible]# cat 01.facts.yml
---
- hosts: win
  remote_user: ansible
  tasks:
  - name: gathering facts with ansible
    debug:
      msg:
        - " OS: {{ ansible_distribution }} "
        - " Version: {{ ansible_distribution_version }} "
        - " Hostname: {{ ansible_hostname }} "
        - " IPaddress: {{ ansible_ip_addresses }} "
        - " Core: {{ ansible_processor_cores }}"
        - " Mem: {{ ansible_memtotal_mb }}"
[root@labco7ans ansible]# ansible-playbook -i hosts 01.facts.yml

PLAY [win] *************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
ok: [172.16.3.106]

TASK [gathering facts with ansible] ************************************************************************************
ok: [172.16.3.106] => {
    "msg": [
        " OS: Microsoft Windows Server 2016 Datacenter ",
        " Version: 10.0.14393.0 ",
        " Hostname: labw16ans ",
        " IPaddress: [u'172.16.3.106', u'fe80::4183:9a41:126b:5eb'] ",
        " Core: 4",
        " Mem: 8192"
    ]
}

PLAY RECAP *************************************************************************************************************
172.16.3.106               : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

여러 대를 대상으로 했다면 조금 더 효과적으로 보였을 것 같습니다.

참고로 disk 정보는 별도의 win_disk_facts 모듈로 가져올 수 있습니다.

참고: https://docs.ansible.com/ansible/latest/modules/win_disk_facts_module.html#win-disk-facts-module

 

추가로 확인해보니 performance counter 관련된 모듈은 없습니다. 이는 모니터링에서 보는게 효과적일 것 같습니다.

다른 방법은 win_command 모듈로 wmic 명령을 전달 할 수도 있습니다.

---
- hosts: win
  tasks:
   - name: run wmic command
     win_command: wmic cpu get caption, deviceid, name, numberofcores, maxclockspeed, status
     register: usage
   - debug: msg="{{ usage.stdout }}"

참고로 앞선 win_ping 결과의 [Gathering Facts]를 보면 알 수 있듯이 playbook을 실행하면 기본적으로 ansible_facts를 사용해 서버 정보를 수집합니다. 이러한 정보를 활용을 하지 않는 경우 facts를 수집하지 않으므로써 수행 속도를 빠르게 할 수 있습니다. gather_facts: no 로 facts 수집을 생략할 수 있습니다.

[root@labco7ans ansible]# cat ping2.yml
---
- hosts: win
  gather_facts: no
  remote_user: ansible
  tasks:
  - name: ping test
    win_ping:
[root@labco7ans ansible]# ansible-playbook -i hosts ping2.yml

PLAY [win] *************************************************************************************************************

TASK [ping test] *******************************************************************************************************
ok: [172.16.3.106]

PLAY RECAP *************************************************************************************************************
172.16.3.106               : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

참고: https://ossian.tistory.com/98

 

(2) Doamin/계정 관리

Domain Join

여러 대의 서버를 AD join 해야하는 상황은 접속>정보 입력>인증>OS reboot>확인이 반복되야 합니다.

아래의 VM을 Domain에 Join하고 세팅하는 예시를 들어보겠습니다.

PS C:\Users\Administrator> Get-CimInstance Win32_ComputerSystem

Name             PrimaryOwnerName     Domain               TotalPhysicalMemory  Model               Manufacturer
----             ----------------     ------               -------------------  -----               ------------
WIN-VS4UITP6P9O  Windows User         WORKGROUP            8588902400           Virtual Machine     Microsoft Corpor...

아래의 playbook을 실행합니다.

[root@labco7ans ansible]# cat 02.ad_join.yml
- hosts: win_ad
  gather_facts: no
  tasks:
  - win_domain_membership:
      dns_domain_name: winlab.citec.com
      hostname: labw16ansad
      domain_admin_user: winlab\administrator
      domain_admin_password: dnlsehdn123$
      state: domain
    register: dmout

  - win_reboot:
    when: dmout.reboot_required

[root@labco7ans ansible]# ansible-playbook -i hosts 02.ad_join.yml

PLAY [win_ad] ********************************************************************************************************************************************************

TASK [win_domain_membership] *****************************************************************************************************************************************
changed: [172.16.3.107]

TASK [win_reboot] ****************************************************************************************************************************************************
changed: [172.16.3.107]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.107               : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

inventory 파일의 win_ad에 여러대의 IP가 등록되었다면 다수 서버의 설정을 한번에 할 수 있습니다.

TASK [win_reboot] 단계에서 서버의 재시작이 수행되고, 완료가 되면 접속이 됩니다.

아래와 같이 AD 조인과 hostname 변경된 것을 확인 할 수 있습니다.

PS C:\Users\administrator.WINLAB> Get-CimInstance Win32_ComputerSystem

Name             PrimaryOwnerName     Domain               TotalPhysicalMemory  Model               Manufacturer
----             ----------------     ------               -------------------  -----               ------------
LABW16ANSAD      Windows User         winlab.citec.com     8588902400           Virtual Machine     Microsoft Corpor...

 

User & Group 관리

아래는 로컬 계정 및 그룹을 관리하는 시나리오 입니다.

[root@labco7ans ansible]# cat 02.user_group.yml
- hosts: win
  gather_facts: no
  tasks:
  - name: Create local group to contain new users
    win_group:
      name: LocalGroup
      description: LocalGroup

  - name: Create local user
    win_user:
      name: '{{ item.name }}'
      password: '{{ item.password }}'
      groups: LocalGroup, Remote Desktop Users
      password_never_expires: yes
    loop:
    - name: User1
      password: Password1
    - name: User2
      password: Password2

[root@labco7ans ansible]# ansible-playbook -i hosts 02.user_group.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [Create local group to contain new users] ***********************************************************************************************************************
ok: [172.16.3.106]

TASK [Create local user] *********************************************************************************************************************************************
changed: [172.16.3.106] => (item={u'password': u'Password1', u'name': u'User1'})
changed: [172.16.3.106] => (item={u'password': u'Password2', u'name': u'User2'})

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

(3) feature 관리

서버에 Feature를 관리하는 시나리오 입니다.

[root@labco7ans ansible]# cat 03.feature.yml
- hosts: win
  gather_facts: no
  tasks:
  - name: Install IIS Web-Server with sub features and management tools
    win_feature:
      name: Web-Server
      state: present
      include_sub_features: yes
      include_management_tools: yes
    register: win_feature

  - name: Reboot if installing Web-Server feature requires it
    win_reboot:
    when: win_feature.reboot_required

[root@labco7ans ansible]# ansible-playbook -i hosts 03.feature.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [Install IIS Web-Server with sub features and management tools] *************************************************************************************************
changed: [172.16.3.106]

TASK [Reboot if installing Web-Server feature requires it] ***********************************************************************************************************
skipping: [172.16.3.106]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=1    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

curl로 접속해보니 default website가 호출됩니다.

[root@labco7ans ansible]# curl 172.16.3.106
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>IIS Windows Server</title>
<style type="text/css">
<!--
생략
-->
</style>
</head>
<body>
<div id="container">
<a href="http://go.microsoft.com/fwlink/?linkid=66138&amp;clcid=0x409"><img src="iisstart.png" alt="IIS" width="960" height="600" /></a>
</div>
</body>
 
(4) 서비스 관리

서버의 서비스를 관리하는 시나리오 입니다.

다들 아시겠지만 state는 상태를 의미하고, start_mode는 시작 유형입니다.

간단히 서비스를 재시작 하는 예제입니다.

[root@labco7ans ansible]# cat 04.service.yml
- hosts: win
  gather_facts: no
  tasks:
  - name: Restart a service
    win_service:
      name: spooler
      state: restarted

[root@labco7ans ansible]# ansible-playbook -i hosts 04.service.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [Restart a service] *********************************************************************************************************************************************
changed: [172.16.3.106]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

참고: https://docs.ansible.com/ansible/latest/modules/win_service_module.html

 

 

(5) 파일 복사

파일을 전송하는 시나리오 입니다.

[root@labco7ans ansible]# cat 05.copyto.yml
---
- hosts: win
  gather_facts: no
  tasks:
  - name: Copy a single file to remote
    win_copy:
      src: /root/ansible/files/foo.conf
      dest: C:\Temp\renamed-foo.conf

[root@labco7ans ansible]# ansible-playbook -i hosts 05.copyto.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [Copy a single file to remote] **********************************************************************************************************************************
changed: [172.16.3.106]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

파일 이동 성공!

c:\Temp>type renamed-foo.conf
foo conf file

만약 존재하던 설정파일이라면 backup: yes 옵션으로 기존 파일을 백업할 수도 있습니다.

옵션 중 remote_src: yes의 remote의 의미를 오해해서 한참 헤맸습니다. 이 옵션은 remote > ansible node가 아닙니다. remote src > remote dest 입니다.

[root@labco7ans ansible]# cat 05.copyremote.yml
---
- hosts: win
  tasks:
  - name: Copy File
    win_copy:
      src: C:\Windows\System32\drivers\etc\hosts
      dest: C:\Temp\hosts_backup
      remote_src: yes
      
[root@labco7ans ansible]# ansible-playbook -i hosts 05.copyremote.yml

PLAY [win] ***********************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************
ok: [172.16.3.106]

TASK [Copy File] *****************************************************************************************************************************************************
changed: [172.16.3.106]

PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106               : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

결과는 아래와 같습니다.

c:\Temp>dir
 Directory of c:\Temp

06/29/2020  04:33 PM    <DIR>          .
06/29/2020  04:33 PM    <DIR>          ..
07/16/2016  10:21 PM               824 hosts_backup
06/29/2020  04:05 PM                14 renamed-foo.conf
               2 File(s)            838 bytes
               2 Dir(s)  122,811,580,416 bytes free

 

 

참고: https://docs.ansible.com/ansible/latest/modules/win_copy_module.html#win-copy-module

docs.ansible.com의 Parameters를 확인하는 TIP
1) Parameter 설명을 보면 어느 버전에서 사용가능한지(ex. addded in 2.8)와 필수값(required)인지 등을 알 수 있습니다.
2) Choices/Default 값을 알 수 있습니다. 파란색 글자로 작성된 값이 default이므로 명시하지 않은 경우 적용됩니다.

 

 

참고

https://docs.ansible.com/ansible/latest/modules/win_feature_module.html#win-feature-module

https://docs.ansible.com/ansible/latest/user_guide/windows_usage.html#use-cases

https://geekflare.com/ansible-playbook-windows-example/

'IaC' 카테고리의 다른 글

ansible - windows 모듈 (2)  (0) 2022.02.04

Docker는 기본적으로 컨테이너의 네트워크 네임스페이스를 호스트의 runtime data에 추가하지 않는다 (/run의 tmpfs로 마운트 되는 /var/run을 의미함)

실행된 컨테이너의 pid로 심볼릭 링크를 만들어주면 컨테이너의 네트워크 네임스페이스를 확인 할 수 있다.

# 호스트 네트워크
root@docker1:~# ip -br -c a
lo               UNKNOWN        127.0.0.1/8 ::1/128
enp0s3           UP             10.0.2.15/24 fe80::31:14ff:fe45:3203/64
enp0s8           UP             192.168.50.10/24 fe80::a00:27ff:fe7c:22c3/64
docker0          UP             172.17.0.1/16 fe80::42:23ff:fef8:ad75/64
vethca6cbca@if7  UP             fe80::e07c:f6ff:fe2c:6d25/64

root@docker1:~# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
71118483fd2e   ubuntu    "bash"    9 minutes ago   Up 9 minutes             sharp_panini
root@docker1:~# ip netns list  # 컨테이너가 실행 중인데 네트워크 네임스페이스가 조회되지 않는다.
root@docker1:~# pid="$(docker inspect -f '{{.State.Pid}}' "711184" )"
root@docker1:~# echo $pid
8719
root@docker1:~# ls -l /var/run/netns
total 0
root@docker1:~# ln -s /proc/$pid/ns/net /var/run/netns/ubuntu
root@docker1:~# ip netns list
ubuntu (id: 0)
root@docker1:~# ip netns exec ubuntu ip -br -c a
lo               UNKNOWN        127.0.0.1/8
eth0@if8         UP             172.17.0.2/16
root@docker1:~#

 

참고

https://platform9.com/blog/container-namespaces-deep-dive-container-networking/

ubuntu 컨테이너 이미지에 ip 명령이 없을 때, apt source를 추가해주고 iproute2를 설치하면 된다.

iproute2 외 nettools 패키지도 네트워크 관련 좋은 도구가 많다.

 

root@71118483fd2e:/# ip -br -c a
bash: ip: command not found
root@71118483fd2e:/# apt install iproute2
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package iproute2
root@71118483fd2e:/# sed -i 's/archive.ubuntu.com/ftp.daum.net/g' /etc/apt/sources.list
root@71118483fd2e:/# apt update && apt -y install iproute2
Get:1 http://mirror.kakao.com/ubuntu focal InRelease [265 kB]
Get:2 http://mirror.kakao.com/ubuntu focal-updates InRelease [114 kB]
Get:3 http://mirror.kakao.com/ubuntu focal-backports InRelease [108 kB]
Get:4 http://mirror.kakao.com/ubuntu focal/universe amd64 Packages [11.3 MB]
Get:5 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:6 http://security.ubuntu.com/ubuntu focal-security/universe amd64 Packages [837 kB]
Get:7 http://mirror.kakao.com/ubuntu focal/multiverse amd64 Packages [177 kB]
Get:8 http://mirror.kakao.com/ubuntu focal/main amd64 Packages [1275 kB]
Get:9 http://mirror.kakao.com/ubuntu focal/restricted amd64 Packages [33.4 kB]
Get:10 http://mirror.kakao.com/ubuntu focal-updates/universe amd64 Packages [1118 kB]
Get:11 http://mirror.kakao.com/ubuntu focal-updates/main amd64 Packages [1844 kB]
Get:12 http://mirror.kakao.com/ubuntu focal-updates/multiverse amd64 Packages [33.7 kB]
Get:13 http://mirror.kakao.com/ubuntu focal-updates/restricted amd64 Packages [899 kB]
Get:14 http://mirror.kakao.com/ubuntu focal-backports/universe amd64 Packages [22.4 kB]
Get:15 http://mirror.kakao.com/ubuntu focal-backports/main amd64 Packages [50.8 kB]
Get:16 http://security.ubuntu.com/ubuntu focal-security/main amd64 Packages [1417 kB]
Get:17 http://security.ubuntu.com/ubuntu focal-security/multiverse amd64 Packages [30.1 kB]
Get:18 http://security.ubuntu.com/ubuntu focal-security/restricted amd64 Packages [833 kB]
Fetched 20.5 MB in 10s (2000 kB/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done
2 packages can be upgraded. Run 'apt list --upgradable' to see them.
Reading package lists... Done
Building dependency tree
Debconf/FrontEnd/Dialog.pm line 76.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (Can't locate Term/ReadLine.pm in @INC (you may need to install the Term::ReadLine module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.30.0 /usr/local/share/perl/5.30.0 /usr/lib/x86_64-linux-gnu/perl5/5.30 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.30 /usr/share/perl/5.30 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7.)
debconf: falling back to frontend: Teletype
Setting up iproute2 (5.5.0-1ubuntu1) ...
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (Can't locate Term/ReadLine.pm in @INC (you may need to install the Term::ReadLine module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.30.0 /usr/local/share/perl/5.30.0 /usr/lib/x86_64-linux-gnu/perl5/5.30 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.30 /usr/share/perl/5.30 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7.)
debconf: falling back to frontend: Teletype
Processing triggers for libc-bin (2.31-0ubuntu9.2) ...
root@71118483fd2e:/# ip -br -c a
lo               UNKNOWN        127.0.0.1/8
eth0@if8         UP             172.17.0.2/16

+ Recent posts