Ubuntu 22.04 에서 Ansible 2.10.8 설치 및 설정, 플레이북 활용

리눅스/OS 일반|2023. 10. 12. 11:34
반응형

Ansible 은 인프라스트럭처 관리와 소프트웨어 프로비저닝을 자동화하기 위한 오픈 소스 도구 및 프레임워크입니다. Ansible 은 다음 3가지의 핵심 구성 요소를 가지고 있습니다.
- 인벤토리 : 관리 대상 호스트 (서버, 가상 머신 등) 의 목록 및 그룹을 정의하는 INI 또는 YAML 파일
- 플레이북 : 작업 (task), 역할 (role), 변수, 조건문 등을 포함한 YAML 파일로, 여러 대상 호스트에서 작업을 수행
- 모듈 : 특정 작업을 수행하기 위한 실행 가능한 코드 블록

 

Ubuntu 22.04 기반에서 Ansible 을 설치, 설정하고 실제로 실행하는 방법을 알아보겠습니다.

 

[테스트를 위한 사전 준비]

- Ubuntu 22.04 기반 서버 3대 (Ansible 서버 1대, 대상 호스트 2대)

 

 

1. 설치

 

Ansible 설치는 굉장히 간단합니다.

Ansible 명령을 수행할 Ansible 서버에만 몇 개의 패키지를 설치하면 되며, 작업을 수행할 서버에 설치할 패키지 또는 Agent 는 없습니다.

(그렇기 때문에 본 매뉴얼의 모든 명령은 Ansible 서버에서만 실행합니다)

Ansible 는 SSH 기반으로 명령을 수행하기 때문에 sshpass 패키지까지 설치해줘야 합니다.

그리고 Ansible 은 Python 으로 제작되었기 때문에 Ansible 설치시 Python 도 같이 설치가 됩니다.

# apt -y update

# apt -y upgrade

# apt -y install ansible sshpass

# ansible --version
ansible 2.10.8
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0]

 

 

2. 인벤토리 설정

 

1) 인벤토리 파일 생성

관리하는 서버의 정보를 담은 파일을 아래와 같이 생성합니다.

섹션 이름은 서버를 그룹핑하기 위한 명칭으로 적절히 설정하면 되고,

대상 호스트는 IP 또는 도메인으로 입력할 수 있습니다.

섹션 내에 여러대의 호스트 추가가 가능합니다.

# vi servers.ini

[web]
10.101.0.23
[db]
10.101.0.34

 

2) SSH 공개키 복사

Ansible 은 ssh 를 이용하여 대상 호스트로 명령을 수행합니다.

ssh 공개키를 생성하고 대상 호스트에 설정하여두면 Ansible 명령 실행시마다 패스워드를 입력하는 번거로움을 줄일 수 있습니다.

# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): (그냥 엔터)
Enter passphrase (empty for no passphrase): (그냥 엔터)
Enter same passphrase again: (그냥 엔터)
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:2bKuWWJfCBqiNnkCYgKZRmI6GEZDynqWbGM41/TsbAk root@kuru80-223962
The key's randomart image is:
+---[RSA 3072]----+
|=B               |
|X+.              |
|Oo  .            |
|++ + o   o       |
|B.@ E + S .      |
|=O.o * o +       |
|.= .. B + .      |
|. +  o * .       |
|      o.o        |
+----[SHA256]-----+

생성된 공개키를 대상 호스트로 복사합니다. 처음 호스트 접속시 패스워드가 필요하지만 키 복사가 완료된 후에는 패스워드가 필요 없게 됩니다.

# ssh-copy-id root@10.101.0.23

# ssh-copy-id root@10.101.0.34

 

3) 연결 테스트

Ansible 에서 주로 사용하는 옵션은 세가지가 있습니다. (help 에서는 더 많은 옵션이 출력됩니다)

-m : 모듈

-i : 인벤토리

-u : 유저명

유저명은 제외하고 아래와 같이 인벤토리 (servers.ini) 에 등록된 모든 호스트에 ping 테스트를 해봅니다.

참고로 all 말고 섹션명을 지정해주면 인벤토리 내의 특정 세션에 등록된 호스트로만 명령을 실행합니다.

# ansible -i servers.ini all -m ping
10.101.0.34 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
10.101.0.23 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

 

 

3. 옵션

 

Ansible 은 기본적으로 작업을 병렬 처리 합니다.

기본 동시 처리되는 호스트 개수는 5개 입니다.

# ansible-config dump |grep -i forks
DEFAULT_FORKS(default) = 5

 

서버의 자원이 충분하여 동시에 처리되는 양을 늘리고자 할 경우 아래와 같이 설정파일을 수정하여 동시처리 개수를 늘릴 수 있습니다.

설정파일은 아래 여러 가지 방법중 한가지 방법을 이용하여 설정할 수 있으며, 우선 순위대로 검색되는 구성 파일으로 적용되어집니다.

- ANSIBLE_CONFIG (환경변수)
- ansible.cfg (현재 디렉토리)
- ~/.ansible.cfg (홈디렉토리)
- /etc/ansible/ansible.cfg

 

디렉토리가 바뀌어도 항상 적용이 가능하도록 세번째 방법으로 설정해보겠습니다.

# vi ~/.ansible.cfg

[defaults]
forks = 10

 

저장만 해도 변경된 것이 확인되었습니다.

# ansible-config dump |grep -i forks
DEFAULT_FORKS(/root/.ansible.cfg) = 10

 

아래는 중요하거나 자주 사용하는 옵션입니다. 모두 [default] 섹션에 넣어주면 됩니다.

- remote_user

: 원격 호스트에 연결할 때 사용할 SSH 사용자 이름을 지정합니다. 기본값은 현재 사용자의 이름입니다. 이 옵션을 설정하여 명시적으로 원격 사용자를 지정할 수 있습니다.
예) remote_user = myuser

 

- private_key_file

: SSH 키 파일의 경로를 지정합니다. 이 옵션을 사용하여 사용자 지정 SSH 키 파일을 사용할 수 있습니다.
예) private_key_file = /path/to/ssh/keyfile

 

- inventory

: 인벤토리 파일의 경로를 지정합니다. 기본적으로 ansible.cfg 파일이 있는 디렉토리에서 inventory 파일을 검색하며, 이 옵션을 사용하여 사용자 정의 인벤토리 파일을 지정할 수 있습니다. 인벤토리 파일의 경로를 지정하면 ansible 명령 실행시 -i 옵션을 이용해 인벤토리 파일을 일일이 명시하지 않아도 됩니다.
예) inventory = /root/servers.ini

 

- roles_path

: 역할 (roles) 디렉토리의 기본 경로를 지정합니다. 이 옵션을 사용하여 역할을 저장하는 디렉토리를 사용자 정의할 수 있습니다.
예) roles_path = /path/to/custom/roles

 

- forks

: 병렬로 실행될 작업 수를 지정합니다. 기본값은 5이며, 시스템 리소스에 따라 적절한 값을 설정할 수 있습니다.
예) forks = 10

 

- become

: 작업을 슈퍼 유저(루트) 권한으로 실행할지 여부를 지정합니다. yes로 설정하면 슈퍼 유저로 작업을 실행합니다.
예) become = yes

 

- become_user

: 슈퍼 유저(루트) 권한으로 작업을 실행할 때 사용할 사용자를 지정합니다.
예) become_user = root

 

- timeout

: SSH 연결 또는 명령 실행의 타임아웃을 지정합니다. 기본값은 10초입니다.
예) timeout = 30

 

 

4. 플레이북 설정

 

플레이북 (playbook) 을 활용한 다양한 예시를 준비했습니다.

 

1) 대상 서버로 파일 복사하기

아래와 같이 플레이북 파일을 작성합니다.

# vi copy.yaml

---
- name: Copy a file to a remote server
  hosts: web
  tasks:
    - name: Copy a file
      copy:
        src: /root/servers.ini
        dest: /root/

 

- 플레이북 파일의 시작은 --- 로 시작하고, 여러개의 작업이 있을 경우 작업 단위마다 - 으로 구분해줘야 합니다.

- hosts : 섹션을 지정합니다. hosts 를 web 섹션으로 하지 않고 all 로 입력 할 경우 인벤토리에 등록된 모든 호스트로 파일을 복사하게 됩니다.

- name : 작업을 구분하기 위한 명칭입니다. (위, 아래 둘다)

- copy : 복사하려는 로컬 파일과 붙여넣으려는 대상 호스트의 디렉토리를 지정합니다.

 

작성한 플레이북을 실행합니다.

# ansible-playbook -i servers.ini copy.yaml

 

2) 패스워드 변경하기

대상 호스트의 root 패스워드를 변경합니다.

# vi chpasswd.yaml

---
- name: Update Remote Server Password
  hosts: all
  tasks:
    - name: Update password
      user:
        name: root
        update_password: always
        password: "{{ '12345678' | password_hash('sha512') }}"

 

- name: 플레이북의 이름을 정의합니다. 이 이름은 플레이북을 식별하기 위해 사용됩니다.
- hosts: 플레이북이 실행될 호스트 그룹을 지정합니다. "all"은 모든 호스트를 대상으로 하는 것을 의미합니다.
- tasks: 플레이북에서 실행할 작업 목록을 정의합니다.
- name: 각 작업의 이름을 지정합니다. 이것은 작업을 식별하기 위한 레이블입니다.
- user 모듈: 이 모듈은 사용자 관리 작업을 수행합니다.
- name: root: user 모듈에 전달된 사용자 이름으로 "root" 사용자를 지정합니다. 이 플레이북은 "root" 사용자의 비밀번호를 변경합니다.
- update_password: always: 사용자 모듈의 update_password 옵션을 "always"로 설정하면 항상 비밀번호를 업데이트하도록 강제합니다.
- password: user 모듈에서 변경할 비밀번호를 정의합니다. 이 플레이북에서는 "12345678"을 password_hash 필터를 사용하여 SHA-512로 해싱한 값을 비밀번호로 설정합니다. 해싱된 비밀번호를 사용하면 보안성을 향상시킬 수 있습니다.

 

작성한 플레이북을 실행합니다.

# ansible-playbook -i servers.ini chpasswd.yaml

 

3) 패키지 설치하기

이 예시는 원격 서버의 APT 패키지 관리자를 사용하여 패키지를 설치합니다.
# vi apt.yaml

---
- name: Install a package on a remote server
  hosts: web
  tasks:
    - name: Install package
      apt:
        name: apache2
        state: present

 

- name: 플레이북의 이름을 정의합니다. 이 이름은 플레이북을 식별하기 위해 사용됩니다.
- hosts: 플레이북이 실행될 호스트 그룹을 지정합니다. "web"은 모든 호스트를 대상으로 하는 것을 의미합니다.
- tasks: 플레이북에서 실행할 작업 목록을 정의합니다.
- apt 모듈: 패키지 설치 작업을 수행합니다.

 

작성한 플레이북을 실행합니다.

# ansible-playbook -i servers.ini apt.yaml

 

4) 데몬 컨트롤 하기

이 예제에서는  Ubuntu 에서 Apache 웹 서버를 시작하는 플레이북을 사용합니다.
# vi apache2.yaml

---
- name: Start Apache Web Server
  hosts: web
  become: yes
  tasks:
    - name: Ensure Apache service is running
      service:
        name: apache2
        state: started


- name: 플레이북의 이름을 지정합니다.
- hosts: 플레이북을 실행할 호스트 그룹 또는 호스트 이름을 지정합니다.
- become: yes: become 키워드를 사용하여 플레이북을 실행할 때 슈퍼유저(루트) 권한으로 실행합니다. 이는 데몬 또는 서비스를 시작하거나 중지할 때 필요한 권한을 얻기 위해 사용됩니다.
- tasks: 수행할 작업 목록을 나열합니다.
- name: 작업의 이름을 지정합니다.
- service 모듈: 서비스 관리 작업을 수행하는 모듈입니다.
- name: apache2: 서비스의 이름을 지정합니다. Ubuntu 에서 Apache 웹 서버는 apache2 로 알려져 있습니다.
- state: started: 서비스를 시작하도록 지정합니다. 이 작업은 Apache 웹 서버가 이미 실행 중인 경우에는 아무 작업도 수행하지 않습니다.

 

작성한 플레이북을 실행합니다.

# ansible-playbook -i servers.ini apache2.yaml

 

5) 사용자 생성 및 그룹 할당
이 예시는 원격 서버에 사용자를 생성하고 그룹에 할당하는 플레이북입니다. user 및 group 모듈을 사용합니다.

# vi useradd.yaml

---
- name: Create a user and assign to a group
  hosts: web
  tasks:
    - name: Create a group
      group:
        name: developers
        state: present

    - name: Create a user
      user:
        name: sysdocu
        groups: developers
        state: present

 

* 설명

- name: 플레이북의 이름을 지정합니다.
- hosts: 플레이북을 실행할 호스트 그룹 또는 호스트 이름을 지정합니다.
- tasks: 수행할 작업 목록을 나열합니다.
- group 및 user 모듈: 그룹 및 사용자 생성 및 할당 작업을 수행합니다.

 

작성한 플레이북을 실행합니다.

# ansible-playbook -i servers.ini useradd.yaml

 

6) 보안 패치 적용
서버에 보안 패치를 적용합니다.
# vi update.yaml

---
- name: Apply security patches
  hosts: all
  tasks:
    - name: Update package cache
      apt:
        update_cache: yes
      become: yes

    - name: Upgrade all packages
      apt:
        upgrade: safe
      become: yes

 

작성한 플레이북을 실행합니다.

# ansible-playbook -i servers.ini update.yaml

 

7) MySQL 설치 및 설정
MySQL 데이터베이스를 설치하고 설정합니다.

DB 생성, 계정 생성 및 DB 권한 부여까지 진행합니다.
# vi mysql.yaml

---
- name: Install MySQL and Configure Database
  hosts: db
  become: yes
  tasks:
    - name: Install MySQL Server
      apt:
        name: mysql-server
        state: present

    - name: Start MySQL Service
      service:
        name: mysql
        state: started

    - name: Install python3-pymysql
      apt:
        name: python3-pymysql
        state: present

    - name: Change MySQL root password
      mysql_user:
        login_user: root
        login_password: ''
        name: root
        password: 12345678
        host: localhost
        login_unix_socket: /var/run/mysqld/mysqld.sock

    - name: Create a MySQL Database
      mysql_db:
        login_user: root
        login_password: 12345678
        name: sysdocudb
        state: present

    - name: Create a MySQL User
      mysql_user:
        name: sysdocu
        password: 12345678
        priv: sysdocudb.*:ALL

    - name: Flush MySQL Privileges
      mysql_user:
        login_user: root
        login_password: 12345678
        name: sysdocu
        host: localhost
        priv: "*.*:ALL,GRANT"
        append_privs: yes

 

작업을 설명하면, 아래와 같이 순차 처리됩니다.

- MySQL 설치

- MySQL 시작

- python3-pymysql 설치 (Ansible 에서 MySQL 관리하기 위해 필요)

- root 패스워드 변경 (null -> 12345678)

- DB 생성

- DB 계정 생성

- 계정에 DB 권한 부여

* 작업별로 MySQL 쿼리 실행을 위해 root 계정정보를 입력해 주었습니다.

 

작성한 플레이북을 실행합니다.

# ansible-playbook -i servers.ini mysql.yaml

 

8) Docker 컨테이너 배포 및 관리

Docker 컨테이너를 배포하고 관리합니다.

플레이북에서 대상 호스트에 Docker 패키지와 docker-py 설치 작업 후 컨테이너를 구동하는 절차로 작성하면 되지만, 여기에서는 Docker 및 docker-py 가 대상 호스트에 설치되었다고 가정하고 컨테이너 구동 방법만 설명드립니다.

 

* 참고 : Docker 및 docker-py 설치 (Ubuntu 22.04)

(대상 호스트에서)

# apt -y install apt-transport-https ca-certificates curl gnupg lsb-release
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg |gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# echo   "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" |tee /etc/apt/sources.list.d/docker.list > /dev/null
# apt -y update
# apt -y install docker-ce docker-ce-cli containerd.io

# apt -y install python3-pip

# pip3 install docker-py

 

플레이북을 작성합니다.

(Ansible 서버에서)

# vi docker.yaml

---
- name: Deploy Docker containers
  hosts: db
  tasks:
    - name: Pull Docker image
      docker_image:
        name: nginx:latest

    - name: Run a Docker container
      docker_container:
        name: my_nginx
        image: nginx:latest
        ports:
          - "80:80"

 

- name: 플레이북의 이름을 지정합니다. 이 이름은 플레이북을 식별하는 레이블입니다.
- hosts: 플레이북을 실행할 호스트 또는 호스트 그룹을 지정합니다. 이 예시에서는 "db" 호스트 그룹에 대한 작업을 수행합니다.
- tasks: 플레이북에서 실행할 작업 목록을 정의합니다.
- name: 각 작업의 이름을 지정합니다. 이것은 작업을 식별하는 레이블입니다.
- docker_image 모듈: 이 모듈은 Docker 이미지 관리 작업을 수행합니다. name 속성은 다운로드하려는 Docker 이미지의 이름을 지정합니다. 이 예시에서는 "nginx:latest" 이미지를 다운로드합니다.
- docker_container 모듈: 이 모듈은 Docker 컨테이너 관리 작업을 수행합니다. name 속성은 컨테이너의 이름을 지정하고, image 속성은 사용할 Docker 이미지를 지정합니다. ports 속성은 컨테이너와 호스트 간의 포트 매핑을 설정합니다. 이 예시에서는 "my_nginx"라는 이름의 컨테이너를 생성하고 "nginx:latest" 이미지를 사용하며, 호스트의 80번 포트와 컨테이너의 80번 포트를 연결합니다.

작성한 플레이북을 실행합니다.

# ansible-playbook -i servers.ini docker.yaml

 

반응형

댓글()

Windows 에서 Docker 사용하기 (Windows Container)

윈도우즈/OS 일반|2023. 10. 10. 14:50
반응형

윈도우즈에서 Docker 를 사용하는 방법입니다.

여기에서는 Docker 를 이용해 Windows Container 를 가동해 보겠습니다.

Windows Container 는 Windows 10, 11 또는 Windows Server 2016 이후의 버전을 기반으로 실행해야 합니다.

저는 Windows 2019 Server 기반에서 진행하였습니다.

 

 

1. Hyper-V 설치

 

윈도우즈 파워쉘을 열고 아래 명령을 실행하여 Hyper-V 구성요소를 설치합니다.

PS C:\Users\Administrator> Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
지금 컴퓨터를 다시 시작하여 이 작업을 완료하시겠습니까?
[Y] Yes  [N] No  [?] 도움말 (기본값은 "Y"): Y

 

'Y' 를 입력하여 리부팅을 합니다.

 

 

2. Docker Desktop for Windows 설치

 

부팅이 되었다면 아래 URL 에 접속하여 윈도우즈용 Docker 를 다운로드 받아 설치합니다.

https://docs.docker.com/desktop/install/windows-install 으로 접속하여 [Docker Desktop for Windows] 버튼을 클릭해 설치파일을 다운로드하고, 실행하여 설치합니다.

현재 날짜 기준으로 Docker Desktop 4.24.1 버전이 설치되었습니다.

설치 완료 후, 재부팅을 해야 합니다.

부팅되어 윈도우즈에 다시 로그인을 하면 Docker Desktop 에서 아래와 같은 메세지가 출력됩니다.

 

-----

Windows 17763 is deprecated

You can still use Docker Desktop but you are on Windows 17763.

You will not be able to install further major updates (3.6.0 and above).

We recommend upgrading to the latest version of Windows.

-----

Windows 17763은 더 이상 사용되지 않습니다.
Docker Desktop을 계속 사용할 수 있지만 Windows 17763을 사용하고 있습니다.
추가 주요 업데이트(3.6.0 이상)를 설치할 수 없습니다.
최신 버전의 Windows로 업그레이드하는 것이 좋습니다.

-----

 

[OK] 버튼을 누르고 사용 동의를 묻는 질문에 동의합니다.

그 다음 저는 로그인을 스킵하고 진행하였습니다. (맨 아래 밑줄 클릭)

직업을 묻는 창이 뜨는데 마찬가지로 스킵하고 진행하였습니다.

이제 Docker Desktop 사용준비가 완료되었습니다.

 

 

3. Windows Container 이미지 다운로드

 

Windows Container 는 latest TAG 를 지원하지 않으므로 아래 페이지에서 TAG 를 확인 후 정확하게 입력해줘야 합니다.

- Server Core : https://hub.docker.com/_/microsoft-windows-servercore

- Nano Server : https://hub.docker.com/_/microsoft-windows-nanoserver

- Windows : https://hub.docker.com/_/microsoft-windows

- Windows Server : https://hub.docker.com/_/microsoft-windows-server

 

nanoserver:ltsc2022 버전을 다운로드 하기위해 파워쉘을 실행해 아래와 같이 명령어를 입력합니다.

PS C:\Users\Administrator> docker pull mcr.microsoft.com/windows/nanoserver:2022-amd64
[2023-10-10T06:40:43.321895600Z][docker-credential-desktop.system][W] Windows version might not be up-to-date: The system cannot find the file specified.
2022-amd64: Pulling from windows/nanoserver
no matching manifest for linux/amd64 in the manifest list entries

 

위와 같은 메세지가 출력된다면 Linux 컨테이너를 실행하도록 되어 있는 것입니다. Windows 컨테이너로 실행하려면 플랫폼 옵션을 추가해 줍니다.

PS C:\Users\Administrator> docker pull --platform windows/amd64 mcr.microsoft.com/windows/nanoserver:2022-amd64

[2023-10-10T06:51:52.322714700Z][docker-credential-desktop.system][W] Windows version might not be up-to-date: The system cannot find the file specified.
2022-amd64: Pulling from windows/nanoserver
no matching manifest for windows/amd64 10.0.17763 in the manifest list entries

 

플랫폼은 변경되었으나, 에러가 발생했습니다. 에러는 아래에서 잡도록 하고 우선 플랫폼 옵션이 번거로우므로 기본 설정으로 변경하여 옵션을 생략하도록 합니다.

윈도우 하단 우측의 트레이에서 Docker 아이콘을 우클릭하면 'Switch to Windows containers...' 옵션이 보입니다. 이를 클릭하고 다시 명령을 실행해 보겠습니다.

PS C:\Users\Administrator> docker pull mcr.microsoft.com/windows/nanoserver:2022-amd64
[2023-10-10T07:23:17.806412500Z][docker-credential-desktop.system][W] Windows version might not be up-to-date: The system cannot find the file specified.
2022-amd64: Pulling from windows/nanoserver
no matching manifest for windows/amd64 10.0.17763 in the manifest list entries

 

옵션을 제외하고 Windows 컨테이너로 다운로드 시도한것이 보입니다. 하지만 에러가 해결되지는 않았습니다.

OS 버전을 확인합니다.

PS C:\Users\Administrator> docker info |findstr 'Operating System'
 Operating System: Microsoft Windows Server Version 1809 (OS Build 17763.107)

 

현재 OS 버전은 1809 이므로 1809 이후의 버전은 구동하지 못합니다.

원래 다운로드 받으려고 했던 2022-amd64 버전을 1809-amd64 로 변경하여 다운로드 합니다.

PS C:\Users\Administrator> docker pull mcr.microsoft.com/windows/nanoserver:1809-amd64
[2023-10-10T07:40:06.050064200Z][docker-credential-desktop.system][W] Windows version might not be up-to-date: The system cannot find the file specified.
1809-amd64: Pulling from windows/nanoserver
f10ae9b68062: Pull complete
Digest: sha256:1b377c168fe2aeef3acd02d3a654c1280b45e6151d66d71ca1d50292e1cce106
Status: Downloaded newer image for mcr.microsoft.com/windows/nanoserver:1809-amd64
mcr.microsoft.com/windows/nanoserver:1809-amd64

What's Next?
[2023-10-10T07:40:14.293630700Z][docker-credential-desktop.system][W] Windows version might not be up-to-date: The system cannot find the file specified.
[2023-10-10T07:40:14.369957100Z][docker-credential-desktop.system][W] Windows version might not be up-to-date: The system cannot find the file specified.
  View a summary of image vulnerabilities and recommendations → docker scout quickview mcr.microsoft.com/windows/nanoserver:1809-amd64

 

다운로드가 잘 되었습니다. 도커 이미지 목록에도 보이는지 확인합니다.

PS C:\Users\Administrator> docker images
REPOSITORY                             TAG          IMAGE ID       CREATED       SIZE
mcr.microsoft.com/windows/nanoserver   1809-amd64   bd7fe7d0dddd   5 weeks ago   252MB

 

참고로 배포되는 컨테이너 TAG 리스트는 아래에서 확인이 가능합니다.

- Server Core : https://mcr.microsoft.com/v2/windows/servercore/tags/list

- Nano Server : https://mcr.microsoft.com/v2/windows/nanoserver/tags/list

- Windows : https://mcr.microsoft.com/v2/windows/tags/list

- Windows Server : https://mcr.microsoft.com/v2/windows/server/tags/list

 

 

4. Windows Container 실행

 

아래와 같이 실행하면 컨테이너의 명령프롬프트 실행이 가능합니다.

PS C:\Users\Administrator> docker run -it mcr.microsoft.com/windows/nanoserver:1809-amd64 cmd.exe

 

cmd.exe 대신 ipconfig.exe 를 입력하면 명령 수행 후 컨테이너가 바로 종료됩니다.

그래서 추가작업이 필요한 경우 cmd.exe 를 실행하고 출력된 명령프롬프트에서 추가 명령을 진행하면 됩니다.

이제, 컨테이너 목적으로 사용하시려면 Dockerfile 을 작성해서 웹서버와 같은 서비스를 구동해 보시기 바랍니다.

 

 

* 참고 (Container 원격 접속)

 

아래 링크에서 확인된 바로는 윈도우즈 컨테이너에서는 RDP 나 GUI 를 제공하지 않는다고 나와 있습니다.

 

https://github.com/microsoft/Windows-Containers/issues/306#issuecomment-1376440627

"Windows 컨테이너 이미지에서 제거되었으므로 지원되지 않습니다. 조만간 RDP 나 GUI 를 사용할 계획이 없기 때문에 Windows 컨테이너 구현 방식을 대대적으로 재설계해야 합니다. 애플리케이션에 GUI 나 RDP 가 필요한 경우 VM 을 계속 사용하는 것이 좋습니다. Azure Virtual Desktop 이나 Azure VM 과 같은 서비스가 더 적합할 수 있습니다."

 

https://learn.microsoft.com/en-us/virtualization/windowscontainers/quick-start/lift-shift-to-containers#what-cant-be-moved-to-windows-containers

- 지원되지 않는 응용프로그램/기능 : 데스크톱이 필요한 애플리케이션

- 지원되지 않는 이유 : 컨테이너가 GUI (Graphic User Interface) 를 지원하지 않음

- 이 문제를 해결할 수 있습니까? : 애플리케이션에서 GUI 만 설치하면 되는 경우 자동 설치로 변경하는 것이 해결책이 될 수 있습니다.

- 지원되지 않는 응용프로그램/기능 : RDP(Remote Desktop Protocol)를 사용하는 응용프로그램

- 지원되지 않는 이유 : RDP는 대화형 세션을 위한 것이므로 위의 원칙이 여기서도 적용됩니다.

- 이 문제를 해결할 수 있습니까? : WAC(Windows Admin Center) 또는 Remote PowerShell을 원격 관리 대신 사용할 수 있습니다.

 

특정 버전에서 RDP 를 사용할 수 있는 방법이 있다고 하는데 이마저도 완벽히 동작하지는 않는듯 합니다.

https://withinrafael.com/2018/03/09/using-remote-desktop-services-in-containers/

 

마이크로소프트에서 공식적으로 컨테이너에서 RDP 는 제공하지 않는다고 하였고, 향후 계획도 없다고 하였으므로 컨테이너에 RDP 접속은 할 수 없는것으로 판단됩니다. 컨테이너 목적이 다르므로, 그래도 원격접속을 하고 싶을 경우 VM 을 이용하면 됩니다.

반응형

댓글()

개인 도커 레지스트리 (Docker Registry) 구축하기

반응형

Docker Registry 는 Docker 이미지를 업로드 하거나, 다운로드하여 컨테이너를 생성하는 등 이미지 저장소의 역할을 담당합니다. Docker Hub 와 같이 알려진 공개 Docker Registry 말고, 개인적으로 사용 가능한 Docker Registry 를 직접 만들어 보겠습니다.

보통은 Private Registry 라고 하며 Kubernetes 내에서 생성하고 사설 네트워크로 연결하도록 구성하지만, 여기에서는 별도의 단독 서버 1대 (공인IP) 로만 구성할 예정입니다. Registry 서버가 Kubernetes Cluster 와 동일한 스위치 내에 위치한다면 방화벽을 설치함으로써 Private Registry 과 같은 형태로 만들 수 있습니다. 이런 형태로 서비스에 적용할 예정이라면 스토리지 여러대로 GlusterFS 나 Ceph 를 구성하고 별도로 마운트하고 도커 서비스를 구동할 서버 1대로 구성하면 됩니다.

 

다시 말씀 드리면, 두가지 방식중 아래 방식으로 진행합니다.

- Kubernetes 설치, 스토리지 준비, PV 및 PVC 생성, Registry Pod 생성

- Docker 설치, Registry Container 생성

 

[환경 및 사전준비]

OS : Ubuntu 22.04

/data 디렉토리 생성 (로컬 호스트의 이미지 저장소)

 

 

1. SSL 인증서 생성

 

Registry 를 사용할때 파일을 업로드 하거나 다운로드 하게되는데, 이때 암호화 전송이 필요합니다.

(암호화 전송 없이 http 프로토콜을 사용하는 옵션도 있긴 합니다)

인증서가 없을 경우, Let's encrypt SSL 에서 무료 인증서를 발급받을 수 있습니다.

운영체제에 따라 인증서 발급 명령이 다르므로 아래 포스팅을 확인하여 자신의 운영체제에 맞는 명령을 참고하시기 바랍니다.

https://sysdocu.tistory.com/search/let's%20encrypt

 

발급 방법은 위 포스팅에 있으므로 여기에서는 생략하고 넘어가겠습니다.

이제 도메인 인증서를 생성하였고, 인증서를 master 서버의 /root/certs 디렉토리에 복사해 두었습니다.

- 도메인 : registry.az1.sysdocu.kr

- 인증서 파일 위치 : /opt/registry/certs/

 

 

2. Docker 설치

 

Registry 서비스는 Docker Registry 컨테이너를 이용할 것이기 때문에 Docker 패키지를 설치해야 합니다.

패키지 목록을 최신화하고 업그레이드 합니다.
# apt -y update

# apt -y upgrade
# apt -y install apt-transport-https ca-certificates curl gnupg lsb-release

Docker 공식 GPG 를 설치합니다.
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg |gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Docker 공식 저장소를 추가합니다.
# echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" |tee /etc/apt/sources.list.d/docker.list > /dev/null

Docker 를 설치하고 확인합니다.

# apt -y update
# apt -y install docker-ce docker-ce-cli containerd.io
# docker --version

Docker version 24.0.6, build ed223bc

 

 

3. Registry 설치 및 가동

 

Docker Hub 에서 Docker Registry 최신버전 이미지를 다운로드 합니다.
# docker pull registry:latest
latest: Pulling from library/registry
7264a8db6415: Pull complete 
c4d48a809fc2: Pull complete 
88b450dec42e: Pull complete 
121f958bea53: Pull complete 
7417fa3c6d92: Pull complete 
Digest: sha256:d5f2fb0940fe9371b6b026b9b66ad08d8ab7b0d56b6ee8d5c71cb9b45a374307
Status: Downloaded newer image for registry:latest
docker.io/library/registry:latest

 

다운로드 된 이미지를 확인합니다.

# docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
registry     latest    0030ba3d620c   3 weeks ago   24.1MB

 

Registry 에 접근할 사용자를 생성합니다.

사용자 생성 방식은 htpasswd 를 이용하였습니다.

# apt -y install apache2-utils

# mkdir -p /opt/registry/auth

# htpasswd -c -b -B /opt/registry/auth/htpasswd sysdocu 12345678
Adding password for user sysdocu

 
이제 Registry Docker 이미지, SSL 인증서, 사용자 계정이 준비되었습니다.

컨테이너를 다음과 같은 명령으로 가동합니다.
# docker run --name MyRegistry --restart=always -p 5000:5000 \
    -v /opt/registry/auth:/auth \
    -v /opt/registry/certs:/certs \
    -v /data:/var/lib/registry \
    -e "REGISTRY_AUTH=htpasswd" \
    -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
    -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/fullchain1.pem \
    -e REGISTRY_HTTP_TLS_KEY=/certs/privkey1.pem \
    -e REGISTRY_COMPATIBILITY_SCHEMA1_ENABLED=true \
    -d registry

* 참고

-v: command not found, -e: command not found 등의 에러 출력시 행 사이에 줄이 떨어져 있는 것이므로 메모장에 기입해 빈 행을 없애거나 역슬래시를 제거하여 한줄 명령으로 사용하면 됩니다.

 

* 설명

--name MyRegistry : 실행되는 컨테이너의 이름을 MyRegistry 로 설정합니다.
--restart=always : 컨테이너가 종료되거나 실패할 경우 자동으로 다시 시작하도록 설정합니다.

-p 5000:5000 : 호스트의 포트 5000 과 컨테이너의 포트 5000 을 연결하여 Registry 에 엑세스할 수 있게 합니다.

-v /opt/registry/auth:/auth : 호스트의 /opt/registry/auth 디렉토리와 컨테이너 내의 /auth 디렉토리를 볼륨 마운트합니다. 이 디렉토리는 사용자 인증 정보를 저장하기 위한 것으로, htpasswd 형식의 사용자 인증 파일이 여기에 저장됩니다.
-v /opt/registry/certs:/certs : 호스트의 /opt/registry/certs 디렉토리와 컨테이너 내의 /certs 디렉토리를 볼륨 마운트합니다. 이 디렉토리에는 TLS (SSL) 인증서 및 키 파일이 저장됩니다.
-v /data:/var/lib/registry : 호스트의 /data 디렉토리와 컨테이너 내의 /var/lib/registry 디렉토리를 볼륨 마운트합니다. 여기에는 레지스트리의 이미지 데이터가 저장됩니다.

-e "REGISTRY_AUTH=htpasswd" : 환경 변수를 설정하여 레지스트리가 htpasswd 형식의 사용자 인증을 사용하도록 합니다.
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" : htpasswd 형식의 사용자 인증을 위한 Realm 을 설정합니다.
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd : 사용자 인증 정보를 저장하는 htpasswd 파일의 경로를 지정합니다.
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/fullchain1.pem : TLS (SSL) 인증서 파일의 경로를 설정합니다.
-e REGISTRY_HTTP_TLS_KEY=/certs/privkey1.pem : TLS (SSL) 인증서의 개인 키 파일의 경로를 설정합니다.
-e REGISTRY_COMPATIBILITY_SCHEMA1_ENABLED=true : Docker Registry v2의 호환성을 유지하고 Docker v1/v1 API를 사용할 수 있도록 활성화합니다.
-d registry : 컨테이너를 백그라운드에서 실행하도록 설정하고, 다운로드 받아놓은 registry 라는 Docker Image 를 사용하여 컨테이너를 시작합니다.

 

구동된 컨테이너를 확인합니다.

# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS                                       NAMES
f246853edd47   registry   "/entrypoint.sh /etc…"   6 seconds ago   Up 5 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   MyRegistry

 

포트도 5000 번으로 정상적으로 열린것이 확인되었습니다.

# netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      23260/systemd-resol 
tcp        0      0 0.0.0.0:5000            0.0.0.0:*               LISTEN      54372/docker-proxy  
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      18912/sshd: /usr/sb 
tcp6       0      0 :::5000                 :::*                    LISTEN      54379/docker-proxy  
tcp6       0      0 :::22                   :::*                    LISTEN      18912/sshd: /usr/sb 

 

만들어진 Registry 컨테이너로 로그인을 해봅니다.

계정은 위에서 htpasswd 로 생성했던 계정입니다.

# docker login -u sysdocu -p 12345678 https://registry.az1.sysdocu.kr:5000
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

 

로그인 성공하여 접근 허용이 되었으면, Registry 이미지 리스트를 확인합니다.

업로드한 이미지가 없기때문에 아직은 아무것도 출력되지 않습니다.

# curl -u sysdocu:12345678 https://registry.az1.sysdocu.kr:5000/v2/_catalog
{"repositories":[]}

 

여기까지 Registry 구축이 완료되었습니다.

아래는 다른 서버에서 Registry 를 사용하는 방법입니다.

 

 

4. 이미지 업로드 및 컨테이너 생성

 

두가지 방법이 있는데, 여기에서는 기본 컨테이너에서 내용을 변경해보는 아래 방식으로 진행합니다.

- Docker Hub 이미지 그대로 Registry 에 업로드

- Docker Hub 이미지를 받아서 수정하고 Registry 에 업로드

 

진행할 예제는 php:7.4-apache 기준으로 작성하였습니다.
우선 php:7.4-apache 이미지를 다운로드 합니다.

# docker pull docker.io/php:7.4-apache

 

테스트용으로 PHP 소스 파일을 만듭니다.

# mkdir ./source

# vi ./source/index.php

<?php
echo "Good job";
?>

 

Dockerfile 을 아래 내용으로 작성합니다.
# vi Dockerfile

FROM docker.io/php:7.4-apache
COPY ./source/ /var/www/html/
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
CMD ["apache2-foreground"]

 

* 설명

FROM docker.io/php:7.4-apache : 기본 이미지를 지정하는 부분입니다. php2.4 와 apache 웹서버가 설치된 이미지 입니다.
COPY ./source/ /var/www/html/ : 호스트 시스템의 ./source/ 디렉토리의 내용을 컨테이너 내부의 /var/www/html/ 디렉토리로 복사하는 명령입니다. 

RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf : Apache 웹서버에 ServerName 옵션을 추가합니다.
CMD ["apache2-foreground"] : 컨테이너가 시작될 때 실행될 명령입니다. 여기에서는 Apache 웹 서버를 시작합니다.

 

만들어진 Dockerfile 을 사용하여 Docker 이미지를 새로 만듭니다.

형식) docker build --tag <새 이미지 이름> <Dockerfile 위치>

# docker build --tag php7.4-apache-update .

 

만들어진 새 이미지가 확인 되었습니다.

# docker images
REPOSITORY             TAG       IMAGE ID       CREATED          SIZE
php7.4-apache-update   latest    b36ddfe193e1   28 seconds ago   453MB
registry               latest    0030ba3d620c   3 weeks ago      24.1MB

 

이번에는 로컬에 만들어져 있는 php7.4-apache-update 이미지를 Registry 에 올려 보겠습니다.

업로드 권한이 필요하므로 생성했던 htpasswd 계정을 이용해 Registry 에 로그인을 합니다.

(아까 위에서 로그인 했을 경우 생략 가능)

# docker login -u sysdocu -p 12345678 https://registry.az1.sysdocu.kr:5000

 

태그 설정을 하고 업로드 합니다.

태그 이름은 로컬에 만들어놓은 이름 (php7.4-apache-update) 과 동일하게 하겠습니다.

그리고 sysdocu 라는 디렉토리로 이미지 용도를 구분 짓도록 하겠습니다.

# docker tag php7.4-apache-update registry.az1.sysdocu.kr:5000/sysdocu/php7.4-apache-update

# docker push registry.az1.sysdocu.kr:5000/sysdocu/php7.4-apache-update
Using default tag: latest
The push refers to repository [registry.az1.sysdocu.kr:5000/sysdocu/php7.4-apache-update]
61323a0752b4: Pushed 
3d4722dde23c: Pushed 
3d33242bf117: Pushed 
529016396883: Pushed 
5464bcc3f1c2: Pushed 
28192e867e79: Pushed 
d173e78df32e: Pushed 
0be1ec4fbfdc: Pushed 
30fa0c430434: Pushed 
a538c5a6e4e0: Pushed 
e5d40f64dcb4: Pushed 
44148371c697: Pushed 
797a7c0590e0: Pushed 
f60117696410: Pushed 
ec4a38999118: Pushed 
latest: digest: sha256:2a03e9c0ac98d726ec0f6707d4bd6265aec6de5b0aa3b982315b9eaae0b61123 size: 3449

 

Registry 컨테이너 가동시 지정했던 로컬 호스트 디렉토리 /data 에서 컨테이너에 올려진 데이터가 확인됩니다.

# ll /data/docker/registry/v2/repositories/sysdocu/php7.4-apache-update/
total 20
drwxr-xr-x 5 root root 4096 Sep  6 02:26 ./
drwxr-xr-x 3 root root 4096 Sep  6 02:26 ../
drwxr-xr-x 3 root root 4096 Sep  6 02:26 _layers/
drwxr-xr-x 4 root root 4096 Sep  6 02:26 _manifests/
drwxr-xr-x 2 root root 4096 Sep  6 02:26 _uploads/

 

이렇게도 확인이 됩니다.

아까는 빈 내용이였던 Registry 에 업로드한 이미지가 확인됩니다.

# curl -u sysdocu:12345678 https://registry.az1.sysdocu.kr:5000/v2/_catalog
{"repositories":["sysdocu/php7.4-apache-update"]}

 

이제 업로드 된 이미지를 활용하여 애플리케이션을 구동할 수 있습니다.

방법은 두가지 형식이 있으며 여기에서는 간단히 Docker 컨테이너로 생성해 보겠습니다.

- Kubernetes (Openshift, K-PaaS 등) 에서 Pod 생성, Service 생성

- Docker 에서 컨테이너 생성

# docker run -d -p 80:80 registry.az1.sysdocu.kr:5000/sysdocu/php7.4-apache-update

 

* 설명
-d : 컨테이너를 백그라운드에서 실행합니다.
-p 80:80 : 호스트의 포트 80 을 컨테이너의 포트 80 으로 매핑합니다. 즉, 웹 서버가 동작하는 포트에 접근할 수 있게 됩니다.
registry.az1.sysdocu.kr:5000/sysdocu/php7.4-apache-update : 실행할 Docker 이미지를 지정합니다.

 

컨테이너가 실행되면 웹 서버가 시작되어 호스트의 IP 또는 도메인과 80 번 포트로 웹서버에 접속할 수 있게 됩니다.

# curl http://registry.az1.sysdocu.kr

Good job

 

반응형

댓글()

Kubernetes 1.28 에서 MetalLB 설치하기

반응형

MetalLB 를 설치하면 LoadBalancer 를 사용할 수 있는데, 이는 외부에서 접근하는 공인 IP 를 Pod 에 부여함으로써 온전히 애플리케이션의 포트를 NodePort (30000~32767) 와 같이 임의 포트가 아닌 공식 표준 포트를 사용할 수 있게 됩니다.

아래 예제의 Kubernetes 환경은 1.28 버전이며, 모든 명령은 master (control-plane) 서버에서 진행하였습니다.

 

공식 홈페이지 Documents : https://metallb.universe.tf/installation/

 

 

1. kube-proxy 구성 편집

 

kube-proxy 를 사용하는 경우 ARP 모드를 사용해야 합니다.

아래 명령을 이용해 kube-proxy 구성을 편집합니다.

# kubectl edit configmap -n kube-system kube-proxy
configmap/kube-proxy edited

...
ipvs:
  strictARP: true
...

 

위 내용으로 저장합니다.

 

 

2. MetalLB 설치

 

MetalLB 컴포넌트 등을 하나의 파일로 설치합니다. 작성일 기준 최신 버전은 0.13.10 입니다.

# kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml

 

MetalLB 관련 Pod 가 잘 생성되었는지 확인합니다.

Running 상태까지 되는데 시간이 소요될 수 있습니다. (모든 Pod 1/1)

# kubectl get pod -n metallb-system
NAME                          READY   STATUS    RESTARTS   AGE
controller-5c6b6c8447-4kzpl   1/1     Running   0          15m
speaker-6fxtx                 1/1     Running   0          15m
speaker-7gg7s                 1/1     Running   0          15m
speaker-z284z                 1/1     Running   0          15m

 

 

3. IP Pool 생성

 

라우팅 처리를 하기위해 보유하고 있는 IP 리스트를 등록합니다.

Pod 에서 IP 를 사용할 수 있도록 상단 스위치단에서 IP 설정이 이루어져 있어야 합니다.

아래는 28비트 대역 2개를 추가해 보았습니다.

실제로 Pod 에 할당하려는 IP 범위를 적어줍니다.

# vi ippool.yaml

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 115.68.142.130-115.68.142.140
  - 115.68.142.146-115.68.142.156

 

IP 를 추가할때는 서브넷 마스크를 별도로 지정하지 않아도 주소 범위 내의 모든 IP 주소를 사용할 수 있도록 인식합니다. MetalLB 는 주소 범위를 기반으로 자동으로 서브넷 마스크를 계산하기 때문입니다.

작성한 yaml 파일을 적용합니다.

# kubectl apply -f ippool.yaml

ipaddresspool.metallb.io/first-pool created

 

* 에러 발생시 ----------

여기에서 다음과 같은 에러가 발생했을때 조치방법 입니다.

Error from server (InternalError): error when creating "ippool.yaml": Internal error occurred: failed calling webhook "ipaddresspoolvalidationwebhook.metallb.io": failed to call webhook: Post "https://webhook-service.metallb-system.svc:443/validate-metallb-io-v1beta1-ipaddresspool?timeout=10s": dial tcp 10.102.110.54:443: connect: connection refused

 

이때는 아래와 같이 metallb-webhook-configuration 설정을 삭제하고 다시 실행해 보세요.

# kubectl delete validatingwebhookconfigurations metallb-webhook-configuration
validatingwebhookconfiguration.admissionregistration.k8s.io "metallb-webhook-configuration" deleted

----------------------------

 

L2 네트워크를 생성하고 적용합니다.

# vi l2.yaml

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: my-l2
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool

 

# kubectl apply -f l2.yaml

l2advertisement.metallb.io/my-l2 created

 

 

4. 테스트 (Pod 생성 및 IP 연결)

 

테스트를 위해 Nginx Pod 를 생성하고 공인 IP 를 할당하여 외부 통신이 되는지 확인합니다.

# kubectl create deploy nginx --image=nginx

deployment.apps/nginx created

 

# kubectl expose deploy nginx --port 80 --type LoadBalancer

service/nginx exposed

 

# kubectl get services
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
kubernetes   ClusterIP      10.96.0.1       <none>           443/TCP        3d
nginx        LoadBalancer   10.111.72.120   115.68.142.130   80:32088/TCP   20m

 

Kubernetes Cluster 외부의 네트워크에서 출력된 IP 로 접근하여 Nginx 가 열리는지 확인합니다.

# curl http://115.68.142.130

 

반응형

댓글()

Kubernetes 1.28 에서 worker 노드 제거 및 추가하기

반응형

1. 노드 제거하기

 

시스템 장애 또는 OS 재설치 등의 이유로 worker 노드 하나를 제거해야 할 수 있습니다.

제거하기 전의 Cluster 상태는 아래와 같습니다.

 

# kubectl get nodes
NAME      STATUS                     ROLES           AGE     VERSION
master    Ready                      control-plane   2d22h   v1.28.1
worker1   Ready                      <none>          2d22h   v1.28.1
worker2   Ready                      <none>          2d22h   v1.28.1

 

worker2 노드를 Kubernetes 클러스터에서 제거하고 다시 연결하는 프로세스는 다음과 같이 진행할 수 있습니다.
주의할 점이 하나 있는데, 노드를 클러스터에서 제거하면 해당 노드에서 실행 중인 모든 컨테이너와 Pod가 중지됩니다.

먼저 worker2 노드에서 실행 중인 Pod 를 다른 노드로 옮기거나 제거해야 합니다.

이 명령어는 worker2 노드에서 실행 중인 Pod 를 다른 노드로 옮기고, DaemonSet Pod 는 무시합니다.

# kubectl drain worker2 --ignore-daemonsets

node/worker2 cordoned
Warning: ignoring DaemonSet-managed Pods: kube-system/kube-proxy-8tqss
node/worker2 drained

 

이 상태로 node 리스트를 확인해보면, 해당 노드에 스케쥴링이 비활성화 된 것이 보입니다.

# kubectl get nodes
NAME      STATUS                     ROLES           AGE     VERSION
master    Ready                      control-plane   2d22h   v1.28.1
worker1   Ready                      <none>          2d22h   v1.28.1
worker2   Ready,SchedulingDisabled   <none>          2d22h   v1.28.1

 

worker2 노드를 클러스터 목록에서 제거합니다.
# kubectl delete node worker2

# kubectl get nodes
NAME      STATUS   ROLES           AGE     VERSION
master    Ready    control-plane   2d22h   v1.28.1
worker1   Ready    <none>          2d22h   v1.28.1

 

 

2. 노드 추가하기

 

worker2 노드를 다시 클러스터에 추가하려면 해당 노드를 다시 등록해야 합니다.

OS 를 재설치 한 경우 worker 노드의 환경 구성은 아래 URL 을 참고합니다.

https://sysdocu.tistory.com/1851

 

worker 노드 준비가 되었으면 master 서버에서 토큰 생성과 함께 join 명령을 출력합니다.

생성된 토큰의 유효 시간은 1일 (24시간) 이며, --ttl 1h 이런 옵션을 줄 경우 토큰 유효 시간을 지정할 수 있습니다.

(master 노드에서)

# kubeadm token create --print-join-command
kubeadm join 115.68.142.104:6443 --token pa3e56.88nw5c48vmbyr522 --discovery-token-ca-cert-hash sha256:82020f205bd07cd7b964a40227f33db5109adc523f042e742d7c6ec8443efbdc

 

(worker2 노드에서)

master 노드에서 출력된 명령줄을 실행합니다.

# kubeadm join 115.68.142.104:6443 --token pa3e56.88nw5c48vmbyr522 --discovery-token-ca-cert-hash sha256:82020f205bd07cd7b964a40227f33db5109adc523f042e742d7c6ec8443efbdc

 

추가된 worker2 노드를 확인합니다.

(master 노드에서)

# kubectl get nodes
NAME      STATUS   ROLES           AGE     VERSION
master    Ready    control-plane   2d23h   v1.28.1
worker1   Ready    <none>          2d23h   v1.28.1
worker2   Ready    <none>          3m44s   v1.28.1

 

* 에러 조치

master 서버에서 Pod 생성시 에러가 발생한다면 추가한 worker 노드에서 다음과 같이 조치 가능합니다.

 

[ 에러 ]

Events:
  Type     Reason                  Age                   From               Message
  ----     ------                  ----                  ----               -------
  Normal   Scheduled               37m                   default-scheduler  Successfully assigned ceph-csi-rbd/ceph-csi-rbd-nodeplugin-n9b2v to worker3
  Warning  FailedCreatePodSandBox  31m (x26 over 37m)    kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = cri-o configured with cgroupfs cgroup manager, but received systemd slice as parent: /kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podd3fc3e78_f49c_4239_b271_55e406fd0b76.slice

 

[ 해결 ]

아래 kubelet 설정 파일에서 cgroup driver 를 바꿔줍니다.

(추가된 worker 노드에서)

# vi /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf

...

Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml --cgroup-driver=cgroupfs"
...

 

# systemctl daemon-reload
# systemctl restart kubelet

 

반응형

댓글()

Ubuntu 22.04 netplan 설정하기

리눅스/Network|2023. 9. 4. 13:50
반응형

Ubuntu 22.04 에서는 netplan 이 업데이트 되어 설정법이 약간 바뀌었습니다.

네트워크 설정 파일을 생성 합니다.

# vi /etc/netplan/50-cloud-init.yaml 

network:
  version: 2
  ethernets:
    eno1:
      addresses: [ 115.68.142.104/27 ]
      routes:
        - to: default
          via: 115.68.142.97
      nameservers:
        addresses: [ 8.8.8.8 ]

 

* 설명

eno1 : 네트워크 장치명입니다. 명칭을 모를경우 ip link 명령으로 확인이 가능합니다.

addresses : 비트수까지 기록해줘야 합니다. netmask 를 입력하는 곳이 없기 때문입니다.

routes: via : 게이트웨이 IP 를 입력합니다.

nameservers: addresses : 네임서버 IP 를 입력합니다.

 

설정을 적용합니다.

# netplan apply

 

 

 

 

 

 

 

반응형

댓글()

Ubuntu 22.04 에서 CRI-O, Kubernetes 1.28 Cluster, Calico 설치 및 애플리케이션 배포

반응형

Kubernetes 는 컨테이너의 생성, 배포, 실행을 하는 등 컨테이너를 관리하는 오픈소스 플랫폼 입니다.

여기에서는 Ubuntu 22.04 버전의 서버 3대로 (master 노드 1대 / worker 노드 2대) Kubernetes 1.28 을 구성하는 방법에 대해 설명합니다.

- 공식 Documents : https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

 

 

1. CRI-O 설치

 

CRI-O 공식 홈페이지 : https://cri-o.io

 

Pod 를 실행하고 관리할 수 있도록 Containerd 나 CRI-O 와 같은 컨테이너 런타임을 설치해야 합니다.

여기에서는 CRI-O 를 설치하도록 하겠습니다.

 

(모든 노드에서)

서버별로 호스트네임을 설정하고 각 노드에 호스트명으로 통신 가능하도록 hosts 파일에 추가합니다.

# hostnamectl set-hostname master      // master 노드에서

# hostnamectl set-hostname worker1    // worker1 노드에서

# hostnamectl set-hostname worker2    // worker2 노드에서

# vi /etc/hosts

127.0.0.1 localhost
10.101.0.5 master
10.101.0.10 worker1
10.101.0.12 worker2

 

CRI-O 는 설치할 Kubernetes 버전과 동일한 버전으로 설치합니다.

(모든 노드에서)

# OS=xUbuntu_22.04
# VERSION=1.28

 

# echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
# echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list

# curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/Release.key | apt-key add -
# curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | apt-key add -

# apt -y update

# apt -y upgrade    // 설치중 묻는 질문에 기본값으로 답변

# apt -y install cri-o cri-o-runc cri-tools    // 설치중 묻는 질문에 기본값으로 답변

# systemctl enable --now crio

 

설치를 잘 마쳤으면 CRI-O 버전이 확인됩니다.

# crio version
crio version 1.28.0
Version:        1.28.0
GitCommit:      unknown
GitCommitDate:  unknown
GitTreeState:   clean
BuildDate:      2023-08-28T05:59:01Z
GoVersion:      go1.19
Compiler:       gc
Platform:       linux/amd64
Linkmode:       dynamic

...

 

 

2. Kubernetes 설치

 

Kubernetes 공식 홈페이지 : https://kubernetes.io

 

(모든 노드에서)

kubelet 사용을 위해 swap 을 반드시 비활성화 시켜줍니다.

# swapoff -a

# cat /etc/fstab

fstab 에서도 swap 파티션이 존재한다면 주석처리하여 비활성화 시킵니다.

 

이제 kubeadm, kubelet, kubectl 를 설치해야 하는데, 이 세가지는 모두 Kubernetes 클러스터 관리와 상호 작용을 위한 도구입니다.
- kubeadm : 클러스터를 부트스트랩하는 명령
- kubelet : 클러스터의 모든 노드에서 실행되는 POD와 컨테이너 시작과 같은 작업을 수행하는 컴포넌트
- kubectl : 클러스터와 통신하기 위한 CLI 유틸리티

 

패키지 저장소에서 파일을 안전하게 다운로드 받기 위해 아래 패키지를 설치합니다.

# apt -y install apt-transport-https ca-certificates

 

현재 기준 Kubernetes 최신 버전인 1.28 버전의 공용 서명 키를 다운로드합니다.

# curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

 

Kubernetes Repository 를 추가합니다.

# echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

 

APT 패키지 인덱스를 업데이트하고 kubelet, kubeadm, kubectl 을 설치합니다.

그리고 패키지가 자동으로 버전업 되지 않도록 고정합니다.

# apt -y update
# apt -y install kubelet kubeadm kubectl    // 설치중 묻는 질문에 기본값으로 답변
# apt-mark hold kubelet kubeadm kubectl

 

커널에 필요한 모듈을 로드 합니다.

(모든 노드에서)

# modprobe overlay
# modprobe br_netfilter

# cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

 

sysctl 파라메타 값을 설정하고 리부팅 없이 적용합니다.
# cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# sysctl --system

 

CRI-O는 기본적으로 systemd 라는 cgroup 드라이버를 사용합니다. 

(모든 노드에서)

# cat <<EOF | sudo tee /etc/crio/crio.conf.d/02-cgroup-manager.conf
[crio.runtime]
conmon_cgroup = "pod"
cgroup_manager = "systemd"
EOF

 

 

3. Cluster 생성

 

서버간 통신할 사설 네트워크 대역을 설정합니다.

현재 노드와 중복되지 않도록 새로운 대역으로 설정해 주었습니다.

- Nodes network : 10.101.0.0/24

- Pods network : 10.101.1.0/24

쿠버네티스 구성에 필요한 이미지를 다운로드 받아야 하므로 이 단계에서 시간이 약간 소요됩니다.

(master 노드에서)

# kubeadm init --pod-network-cidr=10.101.1.0/24

 

아래는 쿠버네티스 컨트롤 플레인이 성공적으로 초기화 되었을때 출력하는 메세지 입니다.

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 10.101.0.5:6443 --token w6ioaq.l37qcxuvs98q4n02 \
--discovery-token-ca-cert-hash sha256:bddfcfabe16f76edbb6a8af08a835ebf9defc67d902dd02091174e1bccacaa76

 

위에 나와있는 안내 대로 추가 명령을 실행하는데, 현재는 root 상태이므로 아래명령으로 Kubernetes 사용자 환경을 로드 합니다.

일반 사용자 상태로 진행을 원할 경우 위 안내된 mkdir 부분부터 세줄 명령을 실행하면 됩니다.

(master 노드에서)
# export KUBECONFIG=/etc/kubernetes/admin.conf

 

앞으로 SSH 접속시마다 자동으로 환경이 로드 되도록 하면 편리합니다.

# echo 'export KUBECONFIG="/etc/kubernetes/admin.conf"' >> ~/.bashrc

 

master 노드에서 확인 가능한 노드 상태를 출력합니다.

# kubectl get nodes
NAME     STATUS   ROLES           AGE   VERSION
master   Ready    control-plane   39s   v1.28.1

 

worker 노드에서는 아래와 같이 master 서버에 join (가입) 합니다.

token 과 hash 값은 쿠버네티스 컨트롤 플레인이 초기화 되었을때 출력된 값으로 합니다.

 

(모든 worker 노드에서)

# kubeadm join 10.101.0.5:6443 --token w6ioaq.l37qcxuvs98q4n02 \
--discovery-token-ca-cert-hash sha256:bddfcfabe16f76edbb6a8af08a835ebf9defc67d902dd02091174e1bccacaa76

 

다시 master 노드에서 확인 가능한 노드 상태를 출력하면 가입된 worker 노드 리스트까지 확인이 됩니다.

ROLES 부분이 아래와 같이 출력 되었는지 확인합니다.

(master 노드에서)

# kubectl get nodes
NAME      STATUS   ROLES           AGE     VERSION
master    Ready    control-plane   2m24s   v1.28.1
worker1   Ready    <none>          88s     v1.28.1
worker2   Ready    <none>          81s     v1.28.1

 

 

[참고 : Cluster 삭제]

 

이번에는 Cluster 를 삭제하는 방법을 안내합니다.

계속 Cluster 구성 진행을 원하시는 분은 이 부분을 건너뛰면 되고, 구성이 꼬이거나 처음부터 다시 하실 분만 참고하시면 됩니다.

 

(master 노드에서)

# kubeadm reset

# rm -r /etc/cni/net.d/*
# systemctl restart kubelet

 

(모든 worker 노드에서)

kubeadm join 명령을 하기 전에 아래 명령으로 기존 Cluster 정보를 삭제해야 합니다.

# kubeadm reset

# rm -rf /etc/kubernetes/*

# systemctl stop kubelet

 

 

4. Calico 설치

 

Calico 공식 홈페이지 : https://www.tigera.io/project-calico

 

Project Calico 는 Kubernetes에 대한 네트워크 정책 엔진입니다.
Calico 네트워크 정책 집행을 통해 네트워크 세분화 및 테넌트 격리를 구현할 수 있습니다.

 

1) Calico 설치하기

(master 노드에서)

Tigera Calico 연산자 및 사용자 지정 리소스 정의를 설치합니다.

현재 기준 Calico 최신버전은 3.26.1 입니다.
# kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml

필요한 커스텀 리소스를 생성하여 Calico 를 설치합니다.

배포하는 yaml 파일에서 CIDR 정보를 자신이 사용하는 네트워크 정보로 수정하고 생성합니다.

# wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml

# sed -i 's/192.168.0.0\/16/10.101.1.0\/24/' custom-resources.yaml 

# kubectl create -f custom-resources.yaml

다음 명령을 사용하여 모든 Pod 가 실행 중인지 확인합니다.

이 부분에서 모든 STATUS 값이 Running 이 되기까지 약간의 시간이 소요됩니다.

# kubectl get pods -n calico-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-7fd8984cb7-b5t6n   1/1     Running   0          2m37s
calico-node-74bjg                          1/1     Running   0          2m37s
calico-node-8mrfw                          1/1     Running   0          2m37s
calico-node-9xn6h                          1/1     Running   0          2m37s
calico-typha-d4c4b7984-l4p5j               1/1     Running   0          2m37s
calico-typha-d4c4b7984-lc9hm               1/1     Running   0          2m31s
csi-node-driver-9lmnz                      2/2     Running   0          2m37s
csi-node-driver-hzt8h                      2/2     Running   0          2m37s
csi-node-driver-ljsds                      2/2     Running   0          2m37s

 

 

5. 애플리케이션 배포

 

볼륨을 포함한 애플리케이션을 배포하고 외부에서 접근하기 위한 네트워크 설정 및 도메인 연결 예제입니다.

 

1) Namespace

애플리케이션을 생성하고 배포할 작업공간을 생성하고 현재의 공간으로 변경해줍니다.

(master 노드에서)

# kubectl create ns sysdocu

# kubectl config set-context --current --namespace=sysdocu

 

2) Volume 생성

NFS, GlusterFS, Ceph 등 별도의 서버를 미리 구성하고 해당 공간을 할당받기 위해

PV (Persistent Volume) 와 PVC (Persistent Volume Claim) 를 생성하는 방법도 있지만,

여기에서는 Pod 가 배포된 worker 노드의 공간을 할애하는 hostPath 방법으로 진행해 보겠습니다.

hostPath 를 사용할 경우 디렉토리를 지정하는 것 외에 별도 작업은 없습니다.

html 데이터를 저장할 디렉토리를 생성합니다.

(모든 worker 노드에서)

# mkdir /html

 

3) Deployment 생성

Deployment 를 사용하면 Pod 생성 및 여러가지 옵션을 추가하여 다양한 구성이 가능합니다.

Deployment yaml 파일을 작성합니다.

(master 노드에서)

# vi deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
          volumeMounts:
            - name: html-volume
              mountPath: /html/user001
      volumes:
        - name: html-volume
          hostPath:
            path: /usr/share/nginx/html
            type: DirectoryOrCreate

 

작성한 yaml 파일을 적용하여 생성합니다.

# kubectl apply -f deployment.yaml

deployment.apps/nginx-deployment created

 

Pod 가 자동 생성되는데, 아래와 같이 확인이 가능합니다.

# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-694db9fb84-b5h2r   1/1     Running   0          20s

 

4) Service 생성

네트워크 접근이 가능하도록 Service 를 생성해 줍니다.

테스트 목적이긴 하지만 외부 네트워크에서 접근이 되도록 해보겠습니다.

Service yaml 파일을 작성합니다.

# vi service.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080  # 여기에 원하는 NodePort 값을 지정하세요. (범위 : 30000~32767)

 

* 참고

Service 에서 생성할 type 은 ClusterIP, NodePort, LoadBalancer 가 있습니다.

- ClusterIP : 클러스터 내부 통신만 가능한 IP

- NodePort : worker 노드의 IP 와 지정한 포트 (30000~32767 로 제한) 를 이용해 Pod 에 연결 가능

- LoadBalancer : 별도의 공인 IP 가 할당되고, 포트를 마음대로 사용 가능 (베어메탈 환경에서는 MetalLB 를 설치 필요)

 

작성한 yaml 파일을 적용하여 생성합니다.

# kubectl apply -f service.yaml

service/nginx created

 

Service 생성시 Endpoint 도 같이 생성되는데, 두가지 정보를 함께 출력해보면 아래와 같습니다.

# kubectl get services,ep

NAME    TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
nginx   NodePort   10.110.222.108   <none>        80:30080/TCP   17s


NAME    ENDPOINTS        AGE
nginx   10.101.1.66:80   17s

 

외부 네트워크에서 접근되는지 확인합니다.

접근할 IP 는 Pod 가 위치하는 worker 노드인데, 아래 명령으로 확인 가능합니다.

# kubectl get pod -o wide

NAME                                READY   STATUS    RESTARTS   AGE     IP            NODE      NOMINATED NODE   READINESS GATES
nginx-deployment-694db9fb84-b5h2r   1/1     Running   0          7m22s   10.101.1.66   worker2   <none>           <none>

 

worker2 노드인것을 확인하였으며, 외부에서 worker2 노드의 공인 IP 와 위에서 설정한 포트 30080 으로 접근시 nginx 초기페이지가 출력되는것이 확인됩니다. 예제에서는 worker2 노드의 공인 IP 로 연결하였지만 실제로는 꼭 worker2 노드의 공인 IP 로 할 필요는 없습니다. NodePort 의 경우 master 또는 어떤 worker 노드로 연결하던 설정한 Pod 로 연결됩니다.

# curl 115.68.249.176:30080

 

5) Ingress 생성

Ingress 를 사용하면 도메인 연결이 가능합니다.

Ingress yaml 파일을 작성합니다.

# ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
  namespace: sysdocu
spec:
  rules:
  - host: nginx.sysdocu.kr    # 사용할 도메인
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx    # 연결할 Service 이름
            port:
              number: 80    # 연결할 Service 포트 번호

 

작성한 yaml 파일을 적용합니다.

# ingress.networking.k8s.io/nginx created

 

Ingress 가 생성되었습니다.

# kubectl get ingress
NAME    CLASS    HOSTS              ADDRESS   PORTS   AGE
nginx   <none>   nginx.sysdocu.kr             80      30s

 

사용할 도메인 (nginx.sysdocu.kr) 은 DNS 에서 IP 를 worker 노드의 IP 로 미리 등록해 놓아야 합니다.

아래와 같이 접속이 확인되었습니다.

# curl nginx.sysdocu.kr:30080

 

nginx 와 같은 웹서버에서 사용하는 포트는 보통 80 또는 443 이지만, NodePort 사용시 번거롭게 30000~32767 사이의 포트 번호를 사용해야 연결이 됩니다. 포트 번호없이 도메인만으로 접속을 원하는 경우 MetalLB 를 구성해 공인 IP 를 할당해 주면 됩니다.

- MetalLB 설치 : https://sysdocu.tistory.com/1854

 

 

 

 

반응형

댓글()

[Android] APNG 사용하기

프로그래밍/Android (Java)|2023. 8. 24. 08:10
반응형

움직이는 GIF 파일과 같이 움직이는 PNG 파일인 APNG 입니다.

GIF 보다 용량도 작고 고화질로 출력이 가능해 안드로이드의 아이콘이나 버튼으로 사용하기 좋습니다.

 

라이브러리 :  https://github.com/penfeizhou/APNG4Android

 

1. 준비

build.gradle 파일에 dependency 를 추가합니다.

...

repositories {
    mavenCentral()
}


...

APNG
dependencies {
    implementation 'com.github.penfeizhou.android.animation:apng:${VERSION}'
}


...

 

2. 사용

APNG 파일 (예: sysdocu.png) 은 assets 폴더에 저장합니다.

...

// asset 파일에서 불러오기
AssetStreamLoader assetLoader = new AssetStreamLoader(context, "sysdocu.png");

// APNG Drawable 생성
APNGDrawable apngDrawable = new APNGDrawable(assetLoader);

// 자동 실행
imageView.setImageDrawable(apngDrawable);

...

 

반응형

댓글()

오픈 클라우드 플랫폼 K-PaaS (구 PaaS-TA) 6.5 Container Platform Portal 사용하기

리눅스/PaaS|2023. 8. 9. 10:40
반응형

본 문서는 공식 Documents 를 참고하여 실습한 후 작성된 내용으로 구성되어 있습니다.

https://github.com/PaaS-TA/paas-ta-container-platform/blob/master/use-guide/portal/container-platform-portal-guide.md

 

컨테이너 플랫폼 포털 URL 은 master 서버 (IP 또는 호스트명) 와 포트 32703 을 이용해 접근이 가능합니다.

http://115.68.142.67:32703

 

 

1. 일반 사용자 추가

 

컨테이너 플랫폼 포털 (이하 '포털') 로그인 화면에서 하단의 'Register' 버튼을 눌러 회원가입을 합니다.

회원가입시 Username 은 로그인 아이디에 해당 되는 부분이므로 영문 작성을 하면 되고, [Register] 버튼을 눌러 가입하면 '관리자의 승인이 필요' 하다는 메세지가 출력됩니다.

 

관리자는 승인을 기다리는 계정에 Namespace (프로젝트) 를 생성 후 Role (권한) 부여를 해주어야 합니다.

테스트 목적으로 아래와 같이 설정하였습니다.

 

1) Namespace 및 Role 생성

위치 : Clusters > Namespaces 화면에서 [생성] 버튼 클릭

> Name : mynamespace 입력 (소문자로만 입력해야 합니다)

> Resource Quotas : cp-low-resourcequota 선택

> Limit Ranges : cp-low-limitrange 선택

> [저장] 버튼을 눌러 생성합니다.

 

2) Namespace 및 Role 할당

위치 : 포털 로그인 > Managements > Users > 'User' 탭 > '비활성' 탭 클릭

> 사용자 계정을 클릭 후, 하단 [수정] 버튼을 누릅니다.

> Authority : [User] 로 선택합니다.

> Namespaces ⁄ Roles 옆에 [선택] 클릭합니다.

> 위에서 생성했던 mynamespace (cp-admin-role) 체크 > [선택 완료] > [수정]

 

이제 계정이 활성 처리 되었습니다.

admin 을 로그아웃하고 일반 사용자 계정으로 로그인합니다.

 

 

2. 응용프로그램 배포

 

admin 계정으로는 모든 메뉴의 권한이 열려 있기 때문에 K-PaaS 에서 제공하는 기능을 모두 사용할 수 있습니다.

여기에서는 위에서 생성했던 일반 사용자 계정으로 응용프로그램을 배포하는 과정을 설명하겠습니다.

 

1) Deployment 생성

컨테이너를 다운로드 받고 응용프로그램을 배포할 수 있습니다.

위치 : 포털 로그인 > Workloads > Deployments

> [생성] 버튼을 누릅니다.

> YAML 입력창에 아래 내용을 작성하고 [저장] 버튼을 누릅니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

 

저장과 동시에 자동으로 yaml 설정값이 적용되며, Deployments 는 물론이고 Pods 와 ReplicaSets 메뉴에서도 관련 정보가 확인됩니다.

 

2) Services 생성

서비스를 NodePort 형식으로 생성하면 외부에서 응용 프로그램으로 연결이 가능해집니다.

위치 : 포털 로그인 > Services > Services

> [생성] 버튼을 누릅니다.

> YAML 입력창에 아래 내용을 작성하고 [저장] 버튼을 누릅니다.

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
  - name: nginx-port
    nodePort: 30001
    port: 80
    targetPort: 80

 

* Port 설명

- nodePort: 외부 네트워크에서 접속하는 포트 번호 입니다. (30000~32767 사이의 포트 번호를 사용) 이 포트는 Service Port 로 연결됩니다.

- port: Service 의 포트 번호 입니다. 이 포트는 targetPort 로 연결됩니다.

- targetPort: Pod 의 포트 입니다.

- 기본 80 포트 연결을 원할 경우 type 을 LoadBalancer 로 변경해야 합니다.

 

3) Ingresses 생성

개인이 소유하고 있는 도메인을 사용하는 방법입니다.

위치 : 포털 로그인 > Services > Ingresses

> [생성] 버튼을 누릅니다.

> Name : myingress 입력 (소문자로만 입력해야 합니다)

> Host : test.sysdocu.kr 입력 (네임서버 설정 IP 는 master node, worker node 어느것이든 상관 없습니다)

> Path : Prefix 선택, / 입력

> Target : 위에서 생성했던 Service 명, Port : 80 입력

> [저장] 버튼을 누릅니다.

 

4) 응용프로그램 접속

웹브라우저를 통해 준비된 도메인과 포트번호로 접근하면 웹서버 기본페이지가 출력됩니다.

http://test.sysdocu.kr:30001

 

5) 볼륨 추가

외부 스토리지의 일정 용량을 할당 받아 Pod 에 연결하는 방법입니다.

위치 : 포털 로그인 > Persistent Volume Claims

> [생성] 버튼을 누릅니다.

> YAML 입력창에 아래 내용을 작성하고 [저장] 버튼을 누릅니다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

 

볼륨을 위에서 생성했던 Pod 에 붙여 보겠습니다.

위치 : 포털 로그인 > Workloads > Deployments

> Deployments 이름 선택

> 아래 [수정] 버튼을 누릅니다.

> YAML 입력창에 아래 파란색으로 표시한 내용을 추가하고 [저장] 버튼을 누릅니다.

...

        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /backup
          name: my-pvc
      dnsPolicy: ClusterFirst

...

      terminationGracePeriodSeconds: 30
      volumes:
      - name: my-pvc
        persistentVolumeClaim:
          claimName: nginx-pvc
status:

...

 

Deployment 를 수정하면 Pod 가 재생성 됩니다.

Pod 이름을 확인하고, Pod bash 쉘에 진입하여 파티션을 확인합니다.

$ kubectl get pod -n mynamespace
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-b5cd59b6c-zj7pg   1/1     Running   0          1m33s

 

$ kubectl exec -it nginx-deployment-b5cd59b6c-zj7pg -n mynamespace -- /bin/bash

# df -h
Filesystem                                                                        Size  Used Avail Use% Mounted on
overlay                                                                            20G   11G  8.9G  54% /
tmpfs                                                                              64M     0   64M   0% /dev
tmpfs                                                                             3.9G     0  3.9G   0% /sys/fs/cgroup
shm                                                                                64M     0   64M   0% /dev/shm
tmpfs                                                                             795M  5.0M  790M   1% /etc/hostname
172.16.1.32:/data/mynamespace-nginx-pvc-pvc-4bde4a92-4288-415f-bba7-ca99bf4fb7fe   20G  2.7G   18G  14% /backup
/dev/vda1                                                                          20G   11G  8.9G  54% /etc/hosts
tmpfs                                                                             500M   12K  500M   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                                                                             3.9G     0  3.9G   0% /proc/acpi
tmpfs                                                                             3.9G     0  3.9G   0% /proc/scsi
tmpfs                                                                             3.9G     0  3.9G   0% /sys/firmware

 

* 참고

PVC 를 1G 로 설정했는데, 20G 로 보이는 이유는 NFS 를 PV (Persistent Volume) 로 사용하기 때문입니다.

NFS 에서는 계정별 Quota 설정이 없으므로 공유디렉토리 총 사용량이 출력됩니다.

할당받은 용량으로 보이길 원할 경우 Ceph, ISCSI, GlusterFS 등 용량 개별 할당이 가능한 PV 로 사용하는 방법이 있습니다.

 

6) ConfigMaps

ConfigMap 은 어플리케이션의 환경 설정 정보나 구성 값들을 분리하여 저장하는 리소스입니다. 이를 통해 설정 값들을 어플리케이션 코드와 분리하여 관리하고, 환경별로 다른 설정을 제공하거나 변경 사항을 쉽게 적용할 수 있습니다.

 

다음은 ConfigMap 의 database-url 설정 값을 DATABASE_URL 환경 변수로 설정하여 Pod 에서 사용하는 예시 입니다. 이렇게 설정한 값이 Pod 내의 환경 변수로 주입되어 어플리케이션에서 사용할 수 있습니다.

위치 : 포털 로그인 > ConfigMaps > ConfigMaps

> [생성] 버튼을 누릅니다.

> YAML 입력창에 아래 내용을 작성하고 [저장] 버튼을 누릅니다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  database-url: "mysql://sysdocu:12345678@db.sysdocu.kr/testdb"

 

그리고 Pod 에서 ConfigMap 을 사용할 수 있도록 Deployment 설정을 수정해줍니다.

위치 : 포털 로그인 > Workloads > Deployments

> Deployments 이름 선택

> 아래 [수정] 버튼을 누릅니다.

> YAML 입력창에 아래 파란색으로 표시한 내용을 추가하고 [저장] 버튼을 누릅니다.

...

      containers:
      - image: nginx
        imagePullPolicy: Always
        env:
          - name: DATABASE_URL
            valueFrom:
              configMapKeyRef:
                name: my-config
                key: database-url
        name: nginx

...

 

Pod 에서 변수를 확인해보겠습니다.

Pod 이름을 확인하고, Pod bash 쉘에 진입하여 변수를 잘 받아왔는지 확인합니다.

$ kubectl get pod -n mynamespace
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-799d57d87-zwjsz   1/1     Running   0          25s

 

$ kubectl exec -it nginx-deployment-799d57d87-zwjsz -n mynamespace -- /bin/bash

# echo $DATABASE_URL
mysql://sysdocu:12345678@db.sysdocu.kr/testdb

 

7) Managements

Managements 에서는 아래 기능 설정이 가능합니다.

- Roles : 작업에 대한 권한을 정의

- Resource Quotas : 네임스페이스 내의 모든 Pod, 리소스 및 객체의 사용량을 관리

- Limit Ranges : 컨테이너 및 Pod의 리소스 사용을 제한하는 데 사용

 

따로 필요한 부분만 설정하여 사용이 가능하지만 여기 예제에서는 한 번에 설정하고 적용하도록 하겠습니다.

아래 설정값을 먼저 작성해둡니다.

위치 : 포털 로그인 > Managements > Roles

> [생성] 버튼을 누릅니다.

> YAML 입력창에 아래 내용을 작성하고 [저장] 버튼을 누릅니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: mynamespace
  name: my-role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

 

my-role 이라는 Role 에 pods 리소스에 대한 get, list, watch 명령을 수행할 수 있는 권한을 주었습니다.

이어서 Resource Quotas 를 작성합니다.

 

위치 : 포털 로그인 > Managements > Resource Quotas

> [생성] 버튼을 누릅니다.

> YAML 입력창에 아래 내용을 작성하고 [저장] 버튼을 누릅니다.

apiVersion: v1
kind: ResourceQuota
metadata:
  namespace: mynamespace
  name: my-resource-quota
spec:
  hard:
    pods: "5"
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi

 

my-resource-quota 라는 Resource Quota 는 네임스페이스 내에서 최대 5개의 Pod 를 생성하며, CPU 및 메모리에 대한 요청과 제한 값을 설정하였습니다.

 

* 참고 : 권한 상승

YAML 저장시 "해당 리소스에 접근할 수 있는 권한이 없습니다." 라는 메세지가 출력될 경우, 포털 admin 계정으로 현재 계정에 대해 권한을 상승시켜주면 됩니다.

위치 : admin 계정으로 포털 로그인 > Managements > Users > 'User' 탭

> 사용자 계정을 클릭 후 하단 [수정] 버튼을 누릅니다.

Authority : [Cluster Admin] 으로 변경 후 [저장] 버튼을 누릅니다.

> admin 계정을 로그아웃 하고 다시 일반 계정으로 로그인합니다.

> 위 Resource Quota 를 생성합니다.

 

이어서 Limit Ranges 를 작성합니다.

위치 : 포털 로그인 > Managements > Limit Ranges

> [생성] 버튼을 누릅니다.

> YAML 입력창에 아래 내용을 작성하고 [저장] 버튼을 누릅니다.

apiVersion: v1
kind: LimitRange
metadata:
  namespace: mynamespace
  name: my-limit-range
spec:
  limits:
  - type: Container
    max:
      memory: 500Mi
    default:
      memory: 100Mi
    defaultRequest:
      memory: 50Mi

 

my-limit-range 라는 Limit Range 를 생성하여 컨테이너의 메모리에 대한 제한과 요청 값을 설정하였습니다.

 

Resource Quota, Limit Range 는 네임스페이스 내에서 생성해 두기만 하면 이후에 생성되는 Pod 에 자동 적용이 됩니다.

그리고 Role 은 일반적으로 Kubernetes 환경에서 사용하려면 Role Binding 과 ServiceAccount 를 추가로 생성해서 Deployment 에 연결시켜줘야 하지만, K-PaaS 에서는 Role 을 만들고 admin 계정으로 특정 계정의 Namespace 와 Role 을 선택해 주기만 하면 됩니다.

위에서 미리 생성했던 Role 을 계정에 적용해 보겠습니다.

우선, 일반 계정을 로그아웃 하고 admin 계정으로 로그인 합니다.

위치 : 포털 로그인 > Managements > Users

> 'Administrator' 탭에서 계정 이름 선택

> 아래 [수정] 버튼을 누릅니다.

> Authority 값을 Cluster Admin 에서 User 로 변경하고

> 바로 아래에 있는 Namespaces ⁄ Roles 의 [선택] 버튼을 누릅니다.

> 만들었던 Namespace 와 Role 을 선택합니다. (예 : mynamespace / my-role)

> [선택 완료] 버튼을 누릅니다.

> 하단의 [수정] 버튼을 누릅니다.

 

일반 계정에 권한이 적용되었습니다.

절차에서 알 수 있듯이 admin 계정이나 Cluster Admin 권한의 계정은 Role 적용이 되지 않습니다.

 

반응형

댓글()

iptables 명령으로 특정대역 22번 포트 허용 및 모두 차단

리눅스/Network|2023. 7. 31. 12:22
반응형

* 주의 : 룰에서 설정하는것이 아닌 iptables 명령을 통한 것이므로 리부팅이나 데몬 재시작시 룰이 초기화 되어 집니다.

 

iptables를 사용하여 22번 포트를 특정 대역에서만 열고 모두 차단하는 방법은 다음과 같습니다.
# iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
# iptables -A INPUT -p tcp --dport 22 -j DROP

 

위의 명령을 실행하면, 192.168.1.0/24 대역에서 오는 SSH (22번 포트) 접근은 허용되고, 나머지 모든 IP 주소에서 오는 SSH 접근은 차단됩니다.

기존의 규칙이 있다면 -I 옵션을 사용해서 적용해야 합니다.

# iptables -I INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
# iptables -A INPUT -p tcp --dport 22 -j DROP

반응형

댓글()

Ubuntu 20.04 기본 방화벽 변경하기 (ufw -> iptables)

리눅스/Network|2023. 7. 27. 13:57
반응형

기본 방화벽을 중지합니다.
# systemctl disable --now ufw

iptables 를 설치합니다.

# apt-get -y update
# apt-get -y install iptables-persistent
(설치중 물음에는 'Yes' 로 대답)

 

룰 파일 위치는 아래와 같습니다.

여기에서는 예시로 작성했으니 서버 상황에 맞게 수정해서 사용하시면 됩니다.

# vi /etc/iptables/rules.v4

*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

# Loopback 트래픽은 항상 허용합니다.
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT

# ICMP 를 허용합니다.
-A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT

# 특정 IP 주소에서 모든 포트로 들어오는 트래픽을 허용합니다.
-A INPUT -s 192.168.10.2 -p tcp -j ACCEPT
-A INPUT -s 172.16.1.0/24 -p tcp -j ACCEPT

# 이미 연결된 세션은 허용합니다.
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 모든 아이피에서 포트 80번으로 들어오는 연결을 허용합니다.
-A INPUT -p tcp --dport 80 -j ACCEPT

COMMIT

 

iptables 가동하고, 부팅시 자동 실행되도록 합니다.

# systemctl enable --now iptables

 

적용된 iptables 룰을 확인합니다.

# iptables -nL

 

반응형

댓글()