1. Openstack 환경 구성 (Victoria 버전)

리눅스/OpenStack|2023. 7. 5. 13:15
반응형

설치 과정중 추가 정보가 필요한 경우 아래 공식 문서를 참조해주세요.

* Openstack Documents : https://docs.openstack.org/ko_KR/

* 본 매뉴얼은 다음 포스팅을 참고하여 재작성 하였습니다. : https://yumserv.tistory.com/294

* 서버 구성 : Controller, Neutron, Compute, Storage 각 한대씩 준비하였고 OS 환경은 Ubuntu 20.04 입니다.

- Controller : 115.68.142.99

- Neutron : 115.68.142.100

- Compute : 115.68.142.101

- Storage : 115.68.142.102 // 추가 디스크 장착 (/dev/sdb)

 

 

1. 기본 환경 구성

 

1) 호스트네임 설정

(모든 노드에서)

# vi /etc/hosts

127.0.0.1 localhost localhost.localdomain
115.68.142.99 controller
115.68.142.100 neutron
115.68.142.101 compute
115.68.142.102 storage

 

(각 노드에서)

# hostnamectl set-hostname controller    // 컨트롤러 서버에서

# hostnamectl set-hostname neutron      // 뉴트론 서버에서

# hostnamectl set-hostname compute     // 컴퓨트 서버에서

# hostnamectl set-hostname storage     // 스토리지 서버에서

 

2) time 서버 설정

(모든 서버에서)

# vi /etc/systemd/timesyncd.conf

[Time]
NTP=time.bora.net

 

# systemctl restart systemd-timesyncd

 

3) Openstack 리포지토리 추가

(모든 서버에서)

# apt -y install software-properties-common
# add-apt-repository cloud-archive:victoria

# apt -y update
# apt -y upgrade
# apt -y install python3-openstackclient

 

4) SQL 설치

(Controller 서버에서)

# apt-get -y install mariadb-server

# mysql_secure_installation

Enter current password for root (enter for none): (그냥 엔터)

Set root password? [Y/n] y

New password: (사용할 root 비밀번호 입력)
Re-enter new password: (사용할 root 비밀번호 입력)

Remove anonymous users? [Y/n] y

Disallow root login remotely? [Y/n] y

Remove test database and access to it? [Y/n] y

Reload privilege tables now? [Y/n] y

 

MariaDB 설정 파일을 생성합니다.

# vi /etc/mysql/mariadb.conf.d/99-openstack.cnf

[mysqld]
bind-address = 115.68.142.99    // 접근 허용할 IP (본 Controller 서버 IP)
default-storage-engine = innodb
innodb_file_per_table = on
max_connections = 4096
collation-server = utf8_general_ci
character-set-server = utf8

데몬을 재시작하여 설정을 적용합니다.

# systemctl restart mysqld

 

5) 메세지큐 설치

각 서버간 통신을 위해 메세지큐가 필요합니다.

 

(Controller 서버에서)

패키지를 설치합니다.

# apt-get -y install rabbitmq-server

 

rabbitmq 사용자 계정을 추가해줍니다. (설정, 쓰기, 읽기 모두 허용)
# rabbitmqctl add_user openstack 12345678
Adding user "openstack" ...

 

# rabbitmqctl set_permissions openstack "." "." ".*"
Setting permissions for user "openstack" in vhost "/" ...   

 

6) memcached 설치

(Controller 서버에서)

# apt-get -y install memcached

# sed -i 's/127.0.0.1/0.0.0.0/' /etc/memcached.conf

# systemctl restart memcached

 

방화벽을 사용하고 있다면 memcached 데몬 포트 (TCP 11211) 를 허용해 주세요.

 

 

2. Keystone 설치

 

(Controller 서버에서)

1) Keystone 데이터베이스 및 계정 생성

# mysql -p

MariaDB [(none)]> create database keystone;
MariaDB [(none)]> grant all privileges on keystone.* to keystone@'localhost' identified by '12345678';
MariaDB [(none)]> grant all privileges on keystone.* to keystone@'%' identified by '12345678';
MariaDB [(none)]> flush privileges;

 

2) Keystone 패키지 설치 및 설정

# apt-get -y install keystone python3-openstackclient apache2 libapache2-mod-wsgi-py3 python3-oauth2client 
# vi /etc/keystone/keystone.conf

[DEFAULT]
log_dir = /var/log/keystone

[database]
connection = mysql+pymysql://keystone:12345678@controller/keystone

[token]
provider = fernet

 

Keystone 관리 명령어 glance-manage 를 통해 Keystone 데이터베이스에 필요한 테이블을 생성합니다.

# su -s /bin/bash keystone -c "keystone-manage db_sync"

 

keystone-manage 를 이용하여 fernet 키 저장소를 초기화 합니다.

# keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone

# keystone-manage credential_setup --keystone-user keystone --keystone-group keystone

 

keystone-manage bootstrap 을 사용해 사용자, 프로젝트, 역할을 생성하고 새로 생성된 프로젝트 사용자에게 부여합니다.

# keystone-manage bootstrap --bootstrap-password 12345678 \
    --bootstrap-admin-url http://controller:5000/v3/ \
    --bootstrap-internal-url http://controller:5000/v3/ \
    --bootstrap-public-url http://controller:5000/v3/ \
    --bootstrap-region-id AZ1

 

여기에서 AZ1 은 가용존을 구분하기 위해 입력된 값입니다.

방화벽을 사용하고 있다면 Keystone 데몬 포트 (TCP 5000, TCP 35357) 를 허용해 주세요.

 

3) Apache 웹 서버 설정

# echo "ServerName controller" >> /etc/apache2/apache2.conf

# systemctl restart apache2

 

4) 관리자 환경변수 설정

# vi admin-openrc

export OS_PROJECT_DOMAIN_NAME=Default
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=12345678
export OS_AUTH_URL=http://controller:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
export OS_AUTH_TYPE=password

 

# source admin-openrc

 

Openstack 관리 명령어는 admin 환경 변수를 설정해야 실행이 가능합니다.

보통 controller 서버 로그인 시, 적용 해주는 것이 일반적이며, 이후에 관리 명령이 실행되지 않을 경우 해당 환경 변수 설정이 누락 되었는지 확인해보시기 바랍니다.

환경 변수가 잘 적용되었는지 확인하기 위해 token 정보를 조회해 봅니다.

# openstack token issue

+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field      | Value                                                                                                                                                                                   |
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| expires    | 2023-07-06T00:29:30+0000                                                                                                                                                                |
| id         | gAAAAABkpfzaysyUUIKuSEBP7g4KGHip6yuFrGK2LYtXiYTq5NT1j9Mha_vxESc7_a3Xc69Rx3ID56kn1oyxs0ZJ0iK46qEGqUoxL7S4ZbfK2uSC24iSrwIJ1W9D0bQ5pv6m3YhBht6gK04n1pXaoD9ahM6cS3wKl8osJhUshRyd-GrJ6Cg8pM8 |
| project_id | 677861619c5445368a353ebeb0bcba2b                                                                                                                                                        |
| user_id    | 7ffedad885e1490e9f5598081077f5a8                                                                                                                                                        |
+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

 

5) 프로젝트, 사용자, 역할 생성

 

# openstack project create --domain default --description "Service Project" service

+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description | Service Project                  |
| domain_id   | default                          |
| enabled     | True                             |
| id          | 38f4f6c42e614625a309679c45db8a08 |
| is_domain   | False                            |
| name        | service                          |
| options     | {}                               |
| parent_id   | default                          |
| tags        | []                               |
+-------------+----------------------------------+

 

생성된 프로젝트를 확인합니다.

# openstack project list

+----------------------------------+---------+
| ID                               | Name    |
+----------------------------------+---------+
| 38f4f6c42e614625a309679c45db8a08 | service |
| 677861619c5445368a353ebeb0bcba2b | admin   |
+----------------------------------+---------+

 

 

3. Glance 설치

 

(Controller 서버에서)

1) 데이터베이스 생성

Glance DB 패스워드 생성시 특수문자를 인식하지 못하는 경우가 있다고 하니 주의하시기 바랍니다.

(참고 : https://bugs.launchpad.net/glance/+bug/1695299)

# mysql -p
MariaDB [(none)]> create database glance;
MariaDB [(none)]> grant all privileges on glance.* to 'glance'@'localhost' identified by '12345678';
MariaDB [(none)]> grant all privileges on glance.* to 'glance'@'%' identified by '12345678';
MariaDB [(none)]> flush privileges;

 

2) Glance 사용자, 서비스, 엔드포인트 생성

# openstack user create --domain default --password 12345678 glance

+---------------------+----------------------------------+
| Field               | Value                            |
+---------------------+----------------------------------+
| domain_id           | default                          |
| enabled             | True                             |
| id                  | 41d916460e594a6996a779821f7aaaa9 |
| name                | glance                           |
| options             | {}                               |
| password_expires_at | None                             |
+---------------------+----------------------------------+

 

# openstack role add --project service --user glance admin

 

서비스 glance 를 생성합니다.

# openstack service create --name glance --description 'OpenStack Image' image

+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description | OpenStack Image                  |
| enabled     | True                             |
| id          | 8b63b37cb389408cbc0c9596c54351f3 |
| name        | glance                           |
| type        | image                            |
+-------------+----------------------------------+

 

image 서비스를 사용할 endpoint 를 생성합니다. public, internal, admin 환경 세군데에서 진행합니다.

# openstack endpoint create --region AZ1 image public http://controller:9292

+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | 7d4985792d104e7689028b448cdcd9e7 |
| interface    | public                           |
| region       | AZ1                              |
| region_id    | AZ1                              |
| service_id   | 8b63b37cb389408cbc0c9596c54351f3 |
| service_name | glance                           |
| service_type | image                            |
| url          | http://controller:9292           |
+--------------+----------------------------------+

 

# openstack endpoint create --region AZ1 image internal http://controller:9292

+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | edba45a5976140d1826b5fbeb61cb8ba |
| interface    | internal                         |
| region       | AZ1                              |
| region_id    | AZ1                              |
| service_id   | 8b63b37cb389408cbc0c9596c54351f3 |
| service_name | glance                           |
| service_type | image                            |
| url          | http://controller:9292           |
+--------------+----------------------------------+

 

# openstack endpoint create --region AZ1 image internal http://controller:9292

+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | 276c3f3e3dd641b3bac59e78c5cbf86f |
| interface    | internal                         |
| region       | AZ1                              |
| region_id    | AZ1                              |
| service_id   | 8b63b37cb389408cbc0c9596c54351f3 |
| service_name | glance                           |
| service_type | image                            |
| url          | http://controller:9292           |
+--------------+----------------------------------+

 

Glance 서비스가 생성된 것을 확인합니다.

# openstack service list
+----------------------------------+----------+----------+
| ID                               | Name     | Type     |
+----------------------------------+----------+----------+
| 8b63b37cb389408cbc0c9596c54351f3 | glance   | image    |
| ffbd73da330946528c15f9db34380078 | keystone | identity |
+----------------------------------+----------+----------+

 

Endpoint 가 생성된 것을 확인합니다.

# openstack endpoint list
+----------------------------------+--------+--------------+--------------+---------+-----------+----------------------------+
| ID                               | Region | Service Name | Service Type | Enabled | Interface | URL                        |
+----------------------------------+--------+--------------+--------------+---------+-----------+----------------------------+
| 276c3f3e3dd641b3bac59e78c5cbf86f | AZ1    | glance       | image        | True    | internal  | http://controller:9292     |
| 529ebbd795334185b45b6bb43ffabfac | AZ1    | keystone     | identity     | True    | internal  | http://controller:5000/v3/ |
| 776e98c8e99e4f65acab76d0d06a58a5 | AZ1    | keystone     | identity     | True    | admin     | http://controller:5000/v3/ |
| 7d4985792d104e7689028b448cdcd9e7 | AZ1    | glance       | image        | True    | public    | http://controller:9292     |
| e204698c2a504534b962a36fbacc73eb | AZ1    | keystone     | identity     | True    | public    | http://controller:5000/v3/ |
| edba45a5976140d1826b5fbeb61cb8ba | AZ1    | glance       | image        | True    | internal  | http://controller:9292     |
+----------------------------------+--------+--------------+--------------+---------+-----------+----------------------------+

 

3) Glance 패키지 설치

# apt-get -y install glance

 

4) Glance 설정파일 수정

glance-api.conf 파일은 Glance 서비스가 클라이언트로부터 API 요청을 받아들이기 위해 사용됩니다.

 

# vi /etc/glance/glance-api.conf

[DEFAULT]
show_image_direct_url = True
[database]
connection = mysql+pymysql://glance:12345678@controller/glance
backend = sqlalchemy

[keystone_authtoken]
auth_uri = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = glance
password =  12345678

[paste_deploy]
flavor = keystone

[glance_store]
stores = file,http default_store = file
filesystem_store_datadir = /var/lib/glance/images/

[image_format]
disk_formats = ami,ari,aki,vhd,vhdx,vmdk,raw,qcow2,vdi,iso,ploop.root-tar

 

설정 파일의 권한을 변경합니다.

# chmod 640 /etc/glance/glance-api.conf
# chown root:glance /etc/glance/glance-api.conf

 

glance 관리 명령어 glance-manage 를 통해 glance 데이터베이스에 필요한 테이블을 생성합니다.

# su -s /bin/bash glance -c "glance-manage db_sync"

 

설정한 파일을 적용하기 위해 데몬을 재시작 합니다.

# systemctl restart glance-api

 

방화벽을 사용하고 있다면 glance-api, glance-registry 데몬 포트 (TCP 9191, TCP 9292) 를 허용해 주세요.

 

5) 검증 방법

cirros OS 이미지를 다운로드 받고, admin 환경에서 이미지를 생성합니다.

# wget http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img

# openstack image create "cirros" --file cirros-0.3.5-x86_64-disk.img --disk-format qcow2 --container-format bare --public

+------------------+--------------------------------------------------------------------------------------------------------------------------------------------+
| Field            | Value                                                                                                                                      |
+------------------+--------------------------------------------------------------------------------------------------------------------------------------------+
| container_format | bare                                                                                                                                       |
| created_at       | 2023-07-06T00:22:42Z                                                                                                                       |
| disk_format      | qcow2                                                                                                                                      |
| file             | /v2/images/5cee962f-6018-4cf3-9027-3b03257d7d0f/file                                                                                       |
| id               | 5cee962f-6018-4cf3-9027-3b03257d7d0f                                                                                                       |
| min_disk         | 0                                                                                                                                          |
| min_ram          | 0                                                                                                                                          |
| name             | cirros                                                                                                                                     |
| owner            | 677861619c5445368a353ebeb0bcba2b                                                                                                           |
| properties       | os_hidden='False', owner_specified.openstack.md5='', owner_specified.openstack.object='images/cirros', owner_specified.openstack.sha256='' |
| protected        | False                                                                                                                                      |
| schema           | /v2/schemas/image                                                                                                                          |
| status           | queued                                                                                                                                     |
| tags             |                                                                                                                                            |
| updated_at       | 2023-07-06T00:22:42Z                                                                                                                       |
| visibility       | public                                                                                                                                     |
+------------------+--------------------------------------------------------------------------------------------------------------------------------------------+

 

이미지 생성된 것을 확인합니다.

# openstack image list
+--------------------------------------+--------+--------+
| ID                                   | Name   | Status |
+--------------------------------------+--------+--------+
| 5cee962f-6018-4cf3-9027-3b03257d7d0f | cirros | active |
+--------------------------------------+--------+--------+

 

 

4. Nova 설치

 

(Controller 서버에서)

1) 데이터베이스 및 계정 생성

nova_cell0 데이터 베이스는 nova-api, nova-conductor, nova-compute 서비스에 의해 사용되며 스케줄링에 실패한 인스턴스의 정보를 저장합니다.
placement 의 경우, 인스턴스 생성에 필요한 자원, 나머지 자원, 전체 사용량에 대한 정보를 저장하기 위해 사용됩니다.

 

# mysql -p

MariaDB [(none)]> create database nova;
MariaDB [(none)]> grant all privileges on nova.* to nova@'localhost' identified by '12345678';
MariaDB [(none)]> grant all privileges on nova.* to nova@'%' identified by '12345678';
MariaDB [(none)]> create database nova_api;
MariaDB [(none)]> grant all privileges on nova_api.* to nova@'localhost' identified by '12345678';
MariaDB [(none)]> grant all privileges on nova_api.* to nova@'%' identified by '12345678';
MariaDB [(none)]> create database nova_cell0;
MariaDB [(none)]> grant all privileges on nova_cell0.* to nova@'localhost' identified by '12345678';
MariaDB [(none)]> grant all privileges on nova_cell0.* to nova@'%' identified by '12345678';
MariaDB [(none)]> create database placement;
MariaDB [(none)]> grant all privileges on placement.* to placement@'localhost' identified by '12345678';
MariaDB [(none)]> grant all privileges on placement.* to placement@'%' identified by '12345678';
MariaDB [(none)]> flush privileges;

 

2) Nova 사용자, 서비스, 엔드포인트 생성

nova 사용자를 생성하고 role 을 추가합니다.

# openstack user create --domain default --project service --password 12345678 nova

+---------------------+----------------------------------+
| Field               | Value                            |
+---------------------+----------------------------------+
| default_project_id  | 38f4f6c42e614625a309679c45db8a08 |
| domain_id           | default                          |
| enabled             | True                             |
| id                  | f50cd8f1bb594da68697b7bd5893fdf7 |
| name                | nova                             |
| options             | {}                               |
| password_expires_at | None                             |
+---------------------+----------------------------------+

 

# openstack role add --project service --user nova admin

 

placement 사용자를 생성하고 role 을 추가합니다.

# openstack user create --domain default --project service --password 12345678 placement

+---------------------+----------------------------------+
| Field               | Value                            |
+---------------------+----------------------------------+
| default_project_id  | 38f4f6c42e614625a309679c45db8a08 |
| domain_id           | default                          |
| enabled             | True                             |
| id                  | c51301d9aabc47af86673f151cd5532c |
| name                | placement                        |
| options             | {}                               |
| password_expires_at | None                             |
+---------------------+----------------------------------+

 

# openstack role add --project service --user placement admin

 

nova 및 placement 서비스를 생성합니다.

# openstack service create --name nova --description "OpenStack Compute service" compute

+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description | OpenStack Compute service        |
| enabled     | True                             |
| id          | 27e1df36ca7d49938bfd9d60550462b5 |
| name        | nova                             |
| type        | compute                          |
+-------------+----------------------------------+

 

# openstack service create --name placement --description "Openstack Compute Placement service" placement

+-------------+-------------------------------------+
| Field       | Value                               |
+-------------+-------------------------------------+
| description | Openstack Compute Placement service |
| enabled     | True                                |
| id          | e5c63604451544fc9313069c6f8056ad    |
| name        | placement                           |
| type        | placement                           |
+-------------+-------------------------------------+

 

nova 및 placement 엔드포인트를 생성합니다.

# openstack endpoint create --region AZ1 compute public http://controller:8774/v2.1/%\(tenant_id\)s

+--------------+-------------------------------------------+
| Field        | Value                                     |
+--------------+-------------------------------------------+
| enabled      | True                                      |
| id           | f6c634f7903d40cdbb93d72acc4175d0          |
| interface    | public                                    |
| region       | AZ1                                       |
| region_id    | AZ1                                       |
| service_id   | 27e1df36ca7d49938bfd9d60550462b5          |
| service_name | nova                                      |
| service_type | compute                                   |
| url          | http://controller:8774/v2.1/%(tenant_id)s |
+--------------+-------------------------------------------+

 

# openstack endpoint create --region AZ1 compute internal http://controller:8774/v2.1/%\(tenant_id\)s

+--------------+-------------------------------------------+
| Field        | Value                                     |
+--------------+-------------------------------------------+
| enabled      | True                                      |
| id           | 1196854aa45f437dacddcb7757f8229c          |
| interface    | internal                                  |
| region       | AZ1                                       |
| region_id    | AZ1                                       |
| service_id   | 27e1df36ca7d49938bfd9d60550462b5          |
| service_name | nova                                      |
| service_type | compute                                   |
| url          | http://controller:8774/v2.1/%(tenant_id)s |
+--------------+-------------------------------------------+

 

# openstack endpoint create --region AZ1 compute admin http://controller:8774/v2.1/%\(tenant_id\)s

+--------------+-------------------------------------------+
| Field        | Value                                     |
+--------------+-------------------------------------------+
| enabled      | True                                      |
| id           | 4ad6b5fb561f44b18b485c90c31dd7d6          |
| interface    | admin                                     |
| region       | AZ1                                       |
| region_id    | AZ1                                       |
| service_id   | 27e1df36ca7d49938bfd9d60550462b5          |
| service_name | nova                                      |
| service_type | compute                                   |
| url          | http://controller:8774/v2.1/%(tenant_id)s |
+--------------+-------------------------------------------+

 

# openstack endpoint create --region AZ1 placement public http://controller:8778

+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | 43655df1d7514d8d8e33d1de68e6ffcf |
| interface    | public                           |
| region       | AZ1                              |
| region_id    | AZ1                              |
| service_id   | e5c63604451544fc9313069c6f8056ad |
| service_name | placement                        |
| service_type | placement                        |
| url          | http://controller:8778           |
+--------------+----------------------------------+

 

# openstack endpoint create --region AZ1 placement internal http://controller:8778

+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | 20364072c19e42be973e175227057bb3 |
| interface    | internal                         |
| region       | AZ1                              |
| region_id    | AZ1                              |
| service_id   | e5c63604451544fc9313069c6f8056ad |
| service_name | placement                        |
| service_type | placement                        |
| url          | http://controller:8778           |
+--------------+----------------------------------+

 

# openstack endpoint create --region AZ1 placement admin http://controller:8778

+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | f5b2f83c4dc74adbbcae3242485c5ba5 |
| interface    | admin                            |
| region       | AZ1                              |
| region_id    | AZ1                              |
| service_id   | e5c63604451544fc9313069c6f8056ad |
| service_name | placement                        |
| service_type | placement                        |
| url          | http://controller:8778           |
+--------------+----------------------------------+

 

3) Nova 패키지 설치 및 설정

# apt-get -y install nova-api nova-conductor nova-scheduler nova-novncproxy placement-api python3-novaclient

# vi /etc/nova/nova.conf

[DEFAULT]
enabled_apis = osapi_compute,metadata
transport_url = rabbit://openstack:12345678@controller
my_ip = 115.68.142.99
use_neutron = True
firewall_driver = nova.virt.firewall.NoopFirewallDriver

[api_database]
connection = mysql+pymysql://nova:12345678@controller/nova_api

[database]
connection = mysql+pymysql://nova:12345678@controller/nova
[api]
auth_strategy = keystone

[keystone_authtoken]
auth_uri = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = nova
password = 12345678

[vnc]
enabled = true
vncserver_listen = 115.68.142.99
vncserver_proxyclient_address = 115.68.142.99

[glance]
api_servers = http://controller:9292

[oslo_concurrency]
lock_path = /var/lib/nova/tmp

[placement]
os_region_name = AZ1
project_domain_name = Default
project_name = service
auth_type = password
user_domain_name = Default
auth_url = http://controller:5000/v3
username = placement
password = 12345678

[wsgi]
api_paste_config = /etc/nova/api-paste.ini

[quota]
instances = -1
cores = -1
ram = -1
floating_ips = -1
fixed_ips = -1

 

* quota 섹션의 -1 값은 사용할 수 있는 자원의 최대치 (무한대) 를 뜻합니다.

 

설정파일의 권한을 변경합니다.

# chmod 640 /etc/nova/nova.conf

# chgrp nova /etc/nova/nova.conf

 

# vi /etc/placement/placement.conf

[DEFAULT]
debug = false

[api]
auth_strategy = keystone

[keystone_authtoken]
www_authenticate_uri = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = placement
password = 12345678

[placement_database]
connection = mysql+pymysql://placement:12345678@controller/placement

 

설정파일의 권한을 변경합니다.

# chmod 640 /etc/placement/placement.conf

# chgrp placement /etc/placement/placement.conf

 

4) 데이터베이스 추가

# su -s /bin/bash placement -c "placement-manage db sync"
# su -s /bin/bash nova -c "nova-manage api_db sync"
# su -s /bin/bash nova -c "nova-manage cell_v2 map_cell0"
# su -s /bin/bash nova -c "nova-manage db sync"
# su -s /bin/bash nova -c "nova-manage cell_v2 create_cell --name cell0"

 

5) 서비스 재시작

# systemctl restart apache2

# systemctl restart nova-api
# systemctl restart nova-conductor
# systemctl restart nova-scheduler
# systemctl restart nova-novncproxy

# openstack compute service list
+----+----------------+------------+----------+---------+-------+----------------------------+
| ID | Binary         | Host       | Zone     | Status  | State | Updated At                 |
+----+----------------+------------+----------+---------+-------+----------------------------+
|  8 | nova-conductor | controller | internal | enabled | up    | 2023-07-06T01:09:31.000000 |
| 14 | nova-scheduler | controller | internal | enabled | up    | 2023-07-06T01:09:30.000000 |
+----+----------------+------------+----------+---------+-------+----------------------------+

 

방화벽을 사용하고 있다면 nova 관련 데몬 포트 (TCP 6080, TCP 8774, TCP 8775, TCP 8778) 를 허용해 주세요.

 

6) Nova 패키지 설치

지금까지 Controller 에서 설치, 설정을 진행했는데, Compute 서버와 통신하고 정상 동작하기 위해 Compute 서버에서도 패키지를 설치하고 설정을 해주어야 합니다.

(Compute 서버에서)

# apt-get -y install nova-compute nova-compute-kvm

# vi /etc/nova/nova.conf

[DEFAULT]
lock_path = /var/lock/nova
state_path = /var/lib/nova
enabled_apis = osapi_compute,metadata
transport_url = rabbit://openstack:12345678@controller
my_ip = 115.68.142.101
use_neutron = True
firewall_driver = nova.virt.firewall.NoopFirewallDriver

[api]
auth_strategy = keystone

[keystone_authtoken]
auth_uri = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = nova
password = 12345678

[vnc]
enabled = True
vncserver_listen = 0.0.0.0
vncserver_proxyclient_address = 115.68.142.101
novncproxy_base_url = http://controller:6080/vnc_auto.html

[glance]
api_servers = http://controller:9292

[oslo_concurrency]
lock_path = /var/lib/nova/tmp

[placement]
os_region_name = AZ1
project_domain_name = Default
project_name = service
auth_type = password
user_domain_name = Default
auth_url = http://controller:5000/v3
username = placement
password = 12345678

 

가상화 모듈이 지원 가능한지 확인합니다.

# lsmod | grep kvm
kvm_intel             282624  0
kvm                   663552  1 kvm_intel

 

# systemctl restart nova-compute libvirtd

 

Controller 서버에서 compute 노드를 확인합니다.

(Controller 서버에서)

# su -s /bin/bash nova -c "nova-manage cell_v2 discover_hosts"

# openstack compute service list

+----+----------------+------------+----------+---------+-------+----------------------------+
| ID | Binary         | Host       | Zone     | Status  | State | Updated At                 |
+----+----------------+------------+----------+---------+-------+----------------------------+
|  8 | nova-conductor | controller | internal | enabled | up    | 2023-07-06T01:36:37.000000 |
| 14 | nova-scheduler | controller | internal | enabled | up    | 2023-07-06T01:36:39.000000 |
| 22 | nova-compute   | compute    | nova     | enabled | up    | 2023-07-06T01:36:37.000000 |
+----+----------------+------------+----------+---------+-------+----------------------------+

 

새로운 compute 노드를 추가할 때 controller 서버에서 nova-manage cell_v2 discover_hosts 를 꼭 실행해야 합니다.

또는 /etc/nova/nova.conf 에서 적절한 interval 을 설정 할 수 있습니다.

[scheduler]
discover_hosts_in_cells_interval = 300

 

 

5. Horizon 설치

 

(Controller 서버에서)

1) Horizon 패키지 설치

# apt-get -y install openstack-dashboard

# vi /etc/openstack-dashboard/local_settings.py

...

:99번째줄 (IP 수정)
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '115.68.142.99:11211',
    },
}

:112번째줄 추가 (Memcached 섹션 저장 서비스 구성)
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"

:126번째줄 (Controller IP 로 수정, Identity API 버전3 활성화)
OPENSTACK_HOST = "115.68.142.99"
OPENSTACK_KEYSTONE_URL = "http://controller:5000/v3"

:131번째줄 (표준시간 설정)
TIME_ZONE = "Asia/Seoul"

: 맨아래 추가 (Default 를 대시보드를 통해 사용자에 대한 디폴트 도메인으로 구성)
OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True
OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'Default'

 

# systemctl restart apache2

 

2) 대시보드 접속

웹브라우저에서 Controller 서버 IP 뒤에 /horizon 을 추가하여 접속하면 대시보드가 출력됩니다.

http://115.68.142.99/horizon

 

 

6. Neutron 설치

 

(Controller 서버에서)

1) Neutron 데이터베이스 및 사용자를 생성

# mysql -p

MariaDB [(none)]> create database neutron;
MariaDB [(none)]> grant all privileges on neutron.* to neutron@'localhost' identified by '12345678';
MariaDB [(none)]> grant all privileges on neutron.* to neutron@'%' identified by '12345678';
MariaDB [(none)]> flush privileges;

 

2) Neutron 사용자, 서비스, 엔드포인트 생성

# openstack user create --domain default --project service --password 12345678 neutron

+---------------------+----------------------------------+
| Field               | Value                            |
+---------------------+----------------------------------+
| default_project_id  | 38f4f6c42e614625a309679c45db8a08 |
| domain_id           | default                          |
| enabled             | True                             |
| id                  | d62dec54e0384ef0b2b61c09a1fe2161 |
| name                | neutron                          |
| options             | {}                               |
| password_expires_at | None                             |
+---------------------+----------------------------------+

 

# openstack role add --project service --user neutron admin

# openstack service create --name neutron --description "Openstack Networking service" network

+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description | Openstack Networking service     |
| enabled     | True                             |
| id          | 6e80e82fa3294924a38cbb032ac8a04b |
| name        | neutron                          |
| type        | network                          |
+-------------+----------------------------------+

 

# openstack endpoint create --region AZ1 network public http://controller:9696

+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | 414f06489a1345f88aaf7af3754c4fc5 |
| interface    | public                           |
| region       | AZ1                              |
| region_id    | AZ1                              |
| service_id   | 6e80e82fa3294924a38cbb032ac8a04b |
| service_name | neutron                          |
| service_type | network                          |
| url          | http://controller:9696           |
+--------------+----------------------------------+

 

# openstack endpoint create --region AZ1 network internal http://controller:9696

+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | 9a44b4b468db496793b786a1a73ad8b6 |
| interface    | internal                         |
| region       | AZ1                              |
| region_id    | AZ1                              |
| service_id   | 6e80e82fa3294924a38cbb032ac8a04b |
| service_name | neutron                          |
| service_type | network                          |
| url          | http://controller:9696           |
+--------------+----------------------------------+

 

# openstack endpoint create --region AZ1 network admin http://controller:9696

+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | 86b8980507f84e71b41dcaf57c9bcb96 |
| interface    | admin                            |
| region       | AZ1                              |
| region_id    | AZ1                              |
| service_id   | 6e80e82fa3294924a38cbb032ac8a04b |
| service_name | neutron                          |
| service_type | network                          |
| url          | http://controller:9696           |
+--------------+----------------------------------+

 

3) Neutron 패키지 설치 및 설정

# apt-get -y install neutron-server

# vi /etc/neutron/neutron.conf

[DEFAULT]
core_plugin = ml2

service_plugins = router
allow_overlapping_ips = true
transport_url = rabbit://openstack:12345678@controller
auth_strategy = keystone
notify_nova_on_port_status_changes = true
notify_nova_on_port_data_changes = true
network_auto_schedule = True
router_auto_schedule = True
allow_automatic_dhcp_failover = True
allow_automatic_l3agent_failover = True
agent_down_time = 60
allow_automatic_lbaas_agent_failover = true
#global_physnet_mtu = 1550
use_syslog = True
syslog_log_facility = LOG_LOCAL1
#dhcp_agents_per_network = 3

[oslo_messaging_rabbit]
#pool_max_size = 50
#pool_max_overflow = 50
#pool_timeout = 30

[agent]
root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf

[database]
connection = mysql+pymysql://neutron:12345678@controller/neutron
max_pool_size = 50
retry_interval = 10
max_overflow = 50

[keystone_authtoken]
auth_url = http://controller:5000/v3
memcached_servers = controller:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = neutron
password = 12345678

[nova]
auth_url = http://controller:5000
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = AZ1
project_name = service
username = nova
password = 12345678

 

ml2.conf 파일을 수정 합니다.

ml2 플러그인은 인스턴스에게 Layer2 가상 네트워크 인프라를 제공하는 리눅스 브리지 기술입니다.

# vi /etc/neutron/plugins/ml2/ml2_conf.ini

[DEFAULT]
[ml2]
type_drivers = flat,vlan,vxlan,gre
tenant_network_types = vxlan
mechanism_drivers = openvswitch,l2population
extension_drivers = port_security
#path_mtu = 1550

[ml2_type_flat]
flat_networks = provider
[ml2_type_vxlan]
vni_ranges = 1:1000
[securitygroup]
enable_ipset = True

 

nova.conf 파일에 Neutron 내용을 추가합니다.

# vi /etc/nova/nova.conf

[DEFAULT]
use_neutron = True
firewall_driver = nova.virt.firewall.NoopFirewallDriver

[neutron]
url = http://controller:9696
auth_url = http://controller:5000
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = AZ1
project_name = service
username = neutron
password = 12345678
service_metadata_proxy = True
metadata_proxy_shared_secret = 12345678

 

# ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini

 

4) 데이터베이스 테이블 추가 및 Neutron 재시작

# su -s /bin/bash neutron -c "neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugin.ini upgrade head"

# systemctl restart neutron-server

 

방화벽을 사용하고 있다면 neutron 데몬 포트 (TCP 9696) 를 허용해 주세요.

 

5) Nuetron 패키지 설치

지금까지 Controller 에서 설치, 설정을 진행했는데, Neutron 서버와 통신하고 정상 동작하기 위해 Neutron 서버에서도 패키지를 설치하고 설정을 해주어야 합니다.

 

(Neutron 서버에서)

IP4 포워딩 내용을 아래 파일에 추가하고 적용합니다.

# vi /etc/sysctl.conf

...
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.ip_forward = 0

 

# sysctl -p
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.ip_forward = 0

 

패키지를 설치하고 파일을 설정합니다.

# apt-get -y install neutron-openvswitch-agent neutron-l3-agent neutron-dhcp-agent neutron-metadata-agent neutron-plugin-ml2

# vi /etc/neutron/neutron.conf

[DEFAULT]
core_plugin = ml2
service_plugins = router
allow_overlapping_ips = true
transport_url = rabbit://openstack:12345678@controller
auth_strategy = keystone
notify_nova_on_port_status_changes = true
notify_nova_on_port_data_changes = true
use_syslog = True
syslog_log_facility = LOG_LOCAL1

[oslo_messaging_rabbit]
pool_max_size = 50
pool_max_overflow = 50
pool_timeout = 30

[agent]
root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf

[keystone_authtoken]
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = neutron
password = 12345678

 

openvswitch_agent.ini 파일을 수정합니다.

이 파일은 openvswitch 플러그인을 사용하기 위한 용도로 쓰입니다.

# vi /etc/neutron/plugins/ml2/openvswitch_agent.ini

[DEFAULT]

[agent]
tunnel_types = vxlan
l2_population = True
ovsdb_monitor_respawn_interval = 30

[ovs]
bridge_mappings = provider:br0
local_ip = 115.68.142.100

[securitygroup]
firewall_driver = openvswitch
enable_security_group = false
enable_ipset = true

 

metadata_agent.ini 파일을 수정합니다.

이 파일은 metadata 에이전트가 사용하는 파일로써 인증정보와 같은 설정정보를 인스턴스에게 제공합니다.

# vi /etc/neutron/metadata_agent.ini

[DEFAULT]
nova_metadata_host = controller
metadata_proxy_shared_secret = 12345678

 

dhcp_agent.ini 파일을 수정합니다.

이 파일은 dhcp 에이전트가 사용하는 파일로써 가상네트워크에 dhcp 서비스를 제공합니다.

# vi /etc/neutron/dhcp_agent.ini

[DEFAULT]
interface_driver = openvswitch
dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq
enable_isolated_metadata = True
enable_metadata_network = True
force_metadata = True

[ovs]
ovsdb_timeout = 600

 

l3_agent.ini 파일을 수정합니다.

이 파일은 L3 에이전트가 사용하는 파일로써 셀프서비스 가상 네트워크에 라우팅과 NAT서비스를 제공하는 역할을 합니다.

# vi /etc/neutron/l3_agent.ini

[DEFAULT]
interface_driver = openvswitch
external_network_bridge =
verbose = True
[ovs]

 

지금까지 설정했던 Neutron 관련 데몬을 재시작 하여 설정을 적용합니다.

# systemctl restart neutron-dhcp-agent
# systemctl restart neutron-l3-agent
# systemctl restart neutron-metadata-agent
# systemctl restart neutron-openvswitch-agent
# systemctl restart openvswitch-switch

 

6) 인터페이스 ovs 설정 및 rc.local 설정

기본 설치되어 있는 netplan 을 사용하지 말고 되도록 ifupdown 패키지를 이용합니다.

# apt-get -y install ifupdown

# vi /etc/network/interfaces

...

auto eno1
iface eno1 inet manual

auto br0
iface br0 inet static
address 115.68.142.100
netmask 255.255.255.224
gateway 115.68.142.97

 

서버가 부팅될때 아래내용이 자동으로 실행될 수 있도록 합니다.

아래 파일을 생성하여 내용을 작성합니다.

# vi /etc/rc.local

#!/bin/bash

ovs-vsctl del-br br0
ovs-vsctl add-br br0
ovs-vsctl add-port br0 eno1

systemctl restart neutron-openvswitch-agent neutron-l3-agent neutron-dhcp-agent neutron-metadata-agent
systemctl restart networking

exit 0

 

파일 내용이 실행될 수 있는 권한을 줍니다.

# chmod 755 /etc/rc.local

 

서비스 실행파일에 아래와 같이 내용 추가후 부팅시 활성화 될 수 있도록 합니다.

# vi /lib/systemd/system/rc-local.service

...

[Install]
WantedBy=multi-user.target

 

# systemctl enable --now rc-local

 

Netplan 을 부팅시 사용하지 않도록 비활성화 하고, 설정을 읽을 수 없도록 /etc/netplan 디렉토리 내의 모든 netplan 설정 파일 이름을 변경합니다.

# systemctl disable systemd-networkd

# mv /etc/netplan/50-cloud-init.yaml /etc/netplan/50-cloud-init.yaml.bak

# mv /etc/netplan/00-installer-config.yaml /etc/netplan/00-installer-config.yaml.bak


ifupdown 을 부팅시 사용하도록 활성화 합니다.
# systemctl enable networking

 

부팅시 resolv.conf 파일이 초기화 되지 않도록 합니다.

# apt-get -y install resolvconf

# echo "nameserver 8.8.8.8" >> /etc/resolvconf/resolv.conf.d/head

# resolvconf -u


현재까지의 네트워크 설정을 재부팅하여 적용하고 잘 동작하는지 확인합니다.
# reboot

 

7) Neutron 패키지 설치 및 설정

지금까지 Controller, Neutron 에서 설치, 설정을 진행했는데, Compute 서버와 통신하고 정상 동작하기 위해 Compute 서버에서도 패키지를 설치하고 설정을 해주어야 합니다.

 

(Compute 서버에서)

# apt-get -y install neutron-server openvswitch-switch neutron-openvswitch-agent neutron-l3-agent

# vi /etc/neutron/neutron.conf

[DEFAULT]
core_plugin = ml2
transport_url = rabbit://openstack:12345678@controller
auth_strategy = keystone
syslog_log_facility = LOG_LOCAL1
use_syslog = True
rpc_response_timeout=1200

[agent]
root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf

[keystone_authtoken]
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = neutron
password = 12345678

[oslo_concurrency]
lock_path = /var/lib/neutron/tmp

 

# vi /etc/neutron/plugins/ml2/openvswitch_agent.ini

[DEFAULT]
[agent]
tunnel_types = vxlan
l2_population = True
ovsdb_monitor_respawn_interval = 30

[ovs]
local_ip = 115.68.142.101
bridge_mappings = provider:br0

[securitygroup]
firewall_driver = openvswitch
enable_security_group = false
enable_ipset = true

 

# vi /etc/neutron/l3_agent.ini

[DEFAULT]
interface_driver = openvswitch
external_network_bridge =
verbose = True

 

# vi /etc/nova/nova.conf

...

[neutron]
url = http://controller:9696
auth_url = http://controller:5000
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = AZ1
project_name = service
username = neutron
password = 12345678

 

지금까지 설정했던 Neutron 관련 데몬을 재시작 하여 설정을 적용합니다.

# systemctl restart neutron-server

# systemctl restart nova-compute

 

8) 인터페이스 ovs 설정 및 rc.local 설정

기본 설치되어 있는 netplan 을 사용하지 말고 되도록 ifupdown 패키지를 이용합니다.

# apt-get -y install ifupdown

# vi /etc/network/interfaces

...

auto eno1
iface eno1 inet manual

auto br0
iface br0 inet static
address 115.68.142.101
netmask 255.255.255.224
gateway 115.68.142.97

 

서버가 부팅될때 아래내용이 자동으로 실행될 수 있도록 합니다.

아래 파일을 생성하여 내용을 작성합니다.

# vi /etc/rc.local

#!/bin/bash

ovs-vsctl del-br br0
ovs-vsctl add-br br0
ovs-vsctl add-port br0 eno1

systemctl restart openvswitch-switch neutron-openvswitch-agent
systemctl restart networking
sleep 10
systemctl restart neutron-openvswitch-agent nova-compute

exit 0

 

파일 내용이 실행될 수 있는 권한을 줍니다.

# chmod 755 /etc/rc.local

 

서비스 실행파일에 아래와 같이 내용 추가후 부팅시 활성화 될 수 있도록 합니다.

# vi /lib/systemd/system/rc-local.service

...

[Install]
WantedBy=multi-user.target

 

# systemctl enable --now rc-local

 

Netplan 을 부팅시 사용하지 않도록 비활성화 하고, 설정을 읽을 수 없도록 /etc/netplan 디렉토리 내의 모든 netplan 설정 파일 이름을 변경합니다.

# systemctl disable systemd-networkd

# mv /etc/netplan/50-cloud-init.yaml /etc/netplan/50-cloud-init.yaml.bak

# mv /etc/netplan/00-installer-config.yaml /etc/netplan/00-installer-config.yaml.bak


ifupdown 을 부팅시 사용하도록 활성화 합니다.
# systemctl enable networking

 

부팅시 resolv.conf 파일이 초기화 되지 않도록 합니다.

# apt-get -y install resolvconf

# echo "nameserver 8.8.8.8" >> /etc/resolvconf/resolv.conf.d/head

# resolvconf -u


현재까지의 네트워크 설정을 재부팅하여 적용하고 잘 동작하는지 확인합니다.
# reboot

 

(Controller 서버에서)

Neutron 설정이 잘 되었는지 컨트롤러 서버에서 확인합니다.

# openstack network agent list

+--------------------------------------+--------------------+---------+-------------------+-------+-------+---------------------------+
| ID                                   | Agent Type         | Host    | Availability Zone | Alive | State | Binary                    |
+--------------------------------------+--------------------+---------+-------------------+-------+-------+---------------------------+
| 015f70db-ed34-48f0-89aa-c46628f53c23 | Metadata agent     | compute | None              | :-)   | UP    | neutron-metadata-agent    |
| 08c999e6-d746-4267-8113-3db128625588 | L3 agent           | compute | nova              | :-)   | UP    | neutron-l3-agent          |
| 9b1fdb08-e982-4811-a956-541d1022e751 | Open vSwitch agent | neutron | None              | :-)   | UP    | neutron-openvswitch-agent |
| b390e1e8-0c69-4bc5-8bd5-37dda5eed35f | Metadata agent     | neutron | None              | :-)   | UP    | neutron-metadata-agent    |
| f51b1e0e-d00e-427c-9c67-56ad9f7292cd | DHCP agent         | neutron | nova              | :-)   | UP    | neutron-dhcp-agent        |
+--------------------------------------+--------------------+---------+-------------------+-------+-------+---------------------------+

 

Controller 서버와 VM 서버의 IP 통신이 가능하면 관리가 편리하므로 미리 Controller 서버에서도 사설 대역을 추가해줍니다.

(나중에 VM 에 공인 IP 로 192.168.0.x 를 추가할 예정 : https://sysdocu.tistory.com/1836)

 

(Controller 서버에서)

기본 설치되어 있는 netplan 을 사용하지 말고 되도록 ifupdown 패키지를 이용합니다.

# apt-get -y install ifupdown

# vi /etc/network/interfaces

...

auto eno1
iface eno1 inet static
    address 115.68.142.99
    netmask 255.255.255.224
    gateway 115.68.142.97

iface eno1 inet static
    address 192.168.0.10
    netmask 255.255.255.0

 

Netplan 을 부팅시 사용하지 않도록 비활성화 하고, 설정을 읽을 수 없도록 /etc/netplan 디렉토리 내의 모든 netplan 설정 파일 이름을 변경합니다.

# systemctl disable systemd-networkd

# mv /etc/netplan/50-cloud-init.yaml /etc/netplan/50-cloud-init.yaml.bak

# mv /etc/netplan/00-installer-config.yaml /etc/netplan/00-installer-config.yaml.bak


ifupdown 을 부팅시 사용하도록 활성화 합니다.
# systemctl enable networking

 

부팅시 resolv.conf 파일이 초기화 되지 않도록 합니다.

# apt-get -y install resolvconf

# echo "nameserver 8.8.8.8" >> /etc/resolvconf/resolv.conf.d/head

# resolvconf -u


현재까지의 네트워크 설정을 재부팅하여 적용하고 잘 동작하는지 확인합니다.
# reboot

 

 

7. Cinder 설치

 

(Controller 서버에서)

1) Cinder 데이터베이스 및 계정 생성

# mysql -p

MariaDB [(none)]> create database cinder;

MariaDB [(none)]> grant all privileges on cinder.* to cinder@'localhost' identified by '12345678';
MariaDB [(none)]> grant all privileges on cinder.* to cinder@'%' identified by '12345678';
MariaDB [(none)]> flush privileges;

 

2) Cinder 사용자 및 서비스 등록
# openstack user create --domain default --password 12345678 cinder

+---------------------+----------------------------------+
| Field               | Value                            |
+---------------------+----------------------------------+
| domain_id           | default                          |
| enabled             | True                             |
| id                  | c1833292afec47658596f7a3771337b8 |
| name                | cinder                           |
| options             | {}                               |
| password_expires_at | None                             |
+---------------------+----------------------------------+


# openstack role add --project service --user cinder admin
# openstack service create --name cinderv2 --description "OpenStack Block Storage" volumev2

+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description | OpenStack Block Storage          |
| enabled     | True                             |
| id          | eb4c53c170a643a08068485439f32a83 |
| name        | cinderv2                         |
| type        | volumev2                         |
+-------------+----------------------------------+


# openstack service create --name cinderv3 --description "OpenStack Block Storage" volumev3

+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description | OpenStack Block Storage          |
| enabled     | True                             |
| id          | 3263f76988c04a84814c62cce4b4ce6f |
| name        | cinderv3                         |
| type        | volumev3                         |
+-------------+----------------------------------+

 

# openstack endpoint create --region AZ1 volumev2 public http://controller:8776/v2/%\(project_id\)s

+--------------+------------------------------------------+
| Field        | Value                                    |
+--------------+------------------------------------------+
| enabled      | True                                     |
| id           | 0c3040f43f404434b04b96d9986d1e3e         |
| interface    | public                                   |
| region       | AZ1                                      |
| region_id    | AZ1                                      |
| service_id   | eb4c53c170a643a08068485439f32a83         |
| service_name | cinderv2                                 |
| service_type | volumev2                                 |
| url          | http://controller:8776/v2/%(project_id)s |
+--------------+------------------------------------------+

 

# openstack endpoint create --region AZ1 volumev2 internal http://controller:8776/v2/%\(project_id\)s

+--------------+------------------------------------------+
| Field        | Value                                    |
+--------------+------------------------------------------+
| enabled      | True                                     |
| id           | f2fce6f293da42fa87f31c93ad85fd9c         |
| interface    | internal                                 |
| region       | AZ1                                      |
| region_id    | AZ1                                      |
| service_id   | eb4c53c170a643a08068485439f32a83         |
| service_name | cinderv2                                 |
| service_type | volumev2                                 |
| url          | http://controller:8776/v2/%(project_id)s |
+--------------+------------------------------------------+


# openstack endpoint create --region AZ1 volumev2 admin http://controller:8776/v2/%\(project_id\)s

+--------------+------------------------------------------+
| Field        | Value                                    |
+--------------+------------------------------------------+
| enabled      | True                                     |
| id           | b9edd3f7f1664a0aab6bdfb357a4a2a2         |
| interface    | admin                                    |
| region       | AZ1                                      |
| region_id    | AZ1                                      |
| service_id   | eb4c53c170a643a08068485439f32a83         |
| service_name | cinderv2                                 |
| service_type | volumev2                                 |
| url          | http://controller:8776/v2/%(project_id)s |
+--------------+------------------------------------------+


# openstack endpoint create --region AZ1 volumev3 public http://controller:8776/v3/%\(project_id\)s

+--------------+------------------------------------------+
| Field        | Value                                    |
+--------------+------------------------------------------+
| enabled      | True                                     |
| id           | 595deda044bc40378148f61a9849ee7e         |
| interface    | public                                   |
| region       | AZ1                                      |
| region_id    | AZ1                                      |
| service_id   | 3263f76988c04a84814c62cce4b4ce6f         |
| service_name | cinderv3                                 |
| service_type | volumev3                                 |
| url          | http://controller:8776/v3/%(project_id)s |
+--------------+------------------------------------------+

 

# openstack endpoint create --region AZ1 volumev3 internal http://controller:8776/v3/%\(project_id\)s

+--------------+------------------------------------------+
| Field        | Value                                    |
+--------------+------------------------------------------+
| enabled      | True                                     |
| id           | f38d56eb94d94b05a16707b04e0ee446         |
| interface    | internal                                 |
| region       | AZ1                                      |
| region_id    | AZ1                                      |
| service_id   | 3263f76988c04a84814c62cce4b4ce6f         |
| service_name | cinderv3                                 |
| service_type | volumev3                                 |
| url          | http://controller:8776/v3/%(project_id)s |
+--------------+------------------------------------------+

 

# openstack endpoint create --region AZ1 volumev3 admin http://controller:8776/v3/%\(project_id\)s
+--------------+------------------------------------------+
| Field        | Value                                    |
+--------------+------------------------------------------+
| enabled      | True                                     |
| id           | 28dd03c124d04dc19490cd5499f36048         |
| interface    | admin                                    |
| region       | AZ1                                      |
| region_id    | AZ1                                      |
| service_id   | 3263f76988c04a84814c62cce4b4ce6f         |
| service_name | cinderv3                                 |
| service_type | volumev3                                 |
| url          | http://controller:8776/v3/%(project_id)s |
+--------------+------------------------------------------+


3) 패키지 설치 및 환경설정
# apt-get -y install cinder-api cinder-scheduler
# vi /etc/cinder/cinder.conf

[DEFAULT]
transport_url = rabbit://openstack:12345678@controller
auth_strategy = keystone
my_ip = 115.68.142.99

[database]
connection = mysql+pymysql://cinder:12345678@controller/cinder

[keystone_authtoken]
www_authenticate_url = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = cinder
password = 12345678

[oslo_concurrency]
lock_path = /var/lib/cinder/tmp


데이터베이스 테이블을 생성합니다.
# su -s /bin/sh -c "cinder-manage db sync" cinder

 

Nova 설정 파일에 Cinder 섹션을 추가 합니다.

# vi /etc/nova/nova.conf

...

[cinder]
os_region_name = AZ1


데몬을 재시작하여 설정한 내용을 반영합니다.
# systemctl restart nova-api
# systemctl restart cinder-scheduler
# systemctl restart apache2

4) Storage 서버 설정

지금까지 Controller 에서 설치, 설정을 진행했는데, Storage 서버와 통신하고 정상 동작하기 위해 Storage 서버에서도 패키지를 설치하고 설정을 해주어야 합니다.

(Storage 서버에서)
# apt-get -y install lvm2 thin-provisioning-tools

이미지를 저장할 두번째 하드 디스크가 필요한데, 장착 후에 파티션을 생성하지 않은 상태에서 아래와 같이 실행합니다.

# pvcreate /dev/sdb

  Physical volume "/dev/sdb" successfully created.

 

# vgcreate cinder-volumes /dev/sdb

  Volume group "cinder-volumes" successfully created

 

# pvdisplay

  --- Physical volume ---
  PV Name               /dev/sdb
  VG Name               cinder-volumes
  PV Size               <232.89 GiB / not usable <3.18 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              59618
  Free PE               59618
  Allocated PE          0
  PV UUID               BnFfxK-A80q-HCPm-upNP-FCit-4wQt-iJxhOK

 

# vgdisplay

  --- Volume group ---
  VG Name               cinder-volumes
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                0
  Open LV               0
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               232.88 GiB
  PE Size               4.00 MiB
  Total PE              59618
  Alloc PE / Size       0 / 0   
  Free  PE / Size       59618 / 232.88 GiB
  VG UUID               UIE0CZ-iI3n-bSTC-zMGj-VZFX-EwNs-hbgNyi

# vi /etc/lvm/lvm.conf

...

devices {
        ...
        filter = [ "a/sdb/", "r/.*/" ]
        ...
}

...

 

위에서 sdb 는 디스크 장치명입니다.

 

# apt-get -y install cinder-volume

# vi /etc/cinder/cinder.conf

[DEFAULT]
rootwrap_config = /etc/cinder/rootwrap.conf
api_paste_confg = /etc/cinder/api-paste.ini
iscsi_helper = tgtadm
volume_name_template = volume-%s
volume_group = cinder-volumes
verbose = True
auth_strategy = keystone
state_path = /var/lib/cinder
lock_path = /var/lock/cinder
volumes_dir = /var/lib/cinder/volumes
enabled_backends = lvm
transport_url = rabbit://openstack:12345678@controller
my_ip = 115.68.142.99
glance_api_servers = http://controller:9292

[oslo_concurrency]
lock_path = /var/lib/cinder/tmp
[database]
connection = mysql+pymysql://cinder:12345678@controller/cinder

[keystone_authtoken]
www_authenticate_uri = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = cinder
password = 12345678

[lvm]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_group = cinder-volumes
target_protocol = iscsi
target_helper = tgtadm

 

# systemctl restart cinder-volume

# systemctl restart tgt

 

Controller 서버에서 볼륨 서비스를 확인합니다.

(Controller 서버에서)

# openstack volume service list
+------------------+-------------+------+---------+-------+----------------------------+
| Binary           | Host        | Zone | Status  | State | Updated At                 |
+------------------+-------------+------+---------+-------+----------------------------+
| cinder-scheduler | controller  | nova | enabled | up    | 2023-07-06T22:53:51.000000 |
| cinder-volume    | storage@lvm | nova | enabled | up    | 2023-07-06T22:53:53.000000 |
+------------------+-------------+------+---------+-------+----------------------------+

 

반응형

댓글()

[MySQL] AUTO_INCREMENT 초기화

리눅스/MySQL|2023. 7. 4. 16:27
반응형

[ 현재 auto_increment 확인 ]

 

아래 예제는 list 테이블의 auto_increment 값을 확인하는 쿼리이며, Auto_increment 컬럼에서 다음 순번을 확인할 수 있습니다.

 

mysql> show table status like 'list';
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation          | Checksum | Create_options | Comment |
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+---------+
| list | InnoDB |      10 | Dynamic    |    0 |              0 |       16384 |               0 |        32768 |         0 |        3855011 | 2023-01-17 08:29:02 | NULL        | NULL       | utf8mb3_general_ci |     NULL |                |         |
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+---------+

 

 

[ auto_increment 초기화 ]

 

mysql> alter table [테이블명] auto_increment='1';

 

설정 후, 다음 insert 쿼리의 값은 1 번으로 입력됩니다.

 

반응형

댓글()

oc get co/dns 실행 에러 DNS "default" reports Progressing=True: "Have 4 available DNS pods, want 5."

리눅스/OpenShift|2023. 6. 30. 10:24
반응형

원인 파악 도중 특정 노드에 원격접속이 되지 않아 결국 리부팅으로 해결하여 절차만 기록해두었습니다.

 

아래와 같은 에러가 발생했을때

# oc get co/dns
NAME   VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
dns    4.12.0    True        True          False      49d     DNS "default" reports Progressing=True: "Have 4 available DNS pods, want 5."

 

DNS Pod 를 확인합니다.

# oc get pod -n openshift-dns
NAME                  READY   STATUS             RESTARTS       AGE
dns-default-d88tp     2/2     Running            0              49d
dns-default-jk4gh     0/2     CrashLoopBackOff   988 (7s ago)   49d
dns-default-lklsh     2/2     Running            0              49d
dns-default-svtxz     2/2     Running            0              49d
dns-default-z2plz     2/2     Running            0              49d
node-resolver-8m85h   1/1     Running            0              49d
node-resolver-h6g59   1/1     Running            0              49d
node-resolver-nchv9   1/1     Running            0              49d
node-resolver-s927r   1/1     Running            0              49d
node-resolver-xwltt   1/1     Running            0              49d

 

dns-default 이름의 Pod 는 노드의 개수만큼 존재 하는데, master node, worker node 가 모두 5개인데, 4개만 사용 가능하다고 출력되고 있습니다.

문제가 발생한 Pod 는 어느 노드의 Pod 인지 확인합니다.

# oc get pod dns-default-jk4gh -n openshift-dns -o wide

NAME                READY   STATUS             RESTARTS           AGE   IP           NODE                      NOMINATED NODE   READINESS GATES
dns-default-jk4gh   0/2     CrashLoopBackOff   1001 (3m47s ago)   49d   10.131.0.6   worker01.az1.sysdocu.kr   <none>           <none>

 

worker01 임을 확인하였습니다.

해당 Pod 의 로그를 확인합니다.

# oc logs dns-default-jk4gh -n openshift-dns
Defaulted container "dns" out of: dns, kube-rbac-proxy
open exec fifo /proc/self/fd/5: too many open files in system

 

좀 더 자세한 문제 확인을 위해 worker01 서버에 접속합니다.

# ssh core@115.68.142.104
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

 

접근 불가가 확인되었습니다. 참고로 다른 노드로는 원격접속이 원활히 진행되었습니다.

worker01 노드에 원격접근 자체가 불가능하여 해당 서버를 리부팅 하였고, 그 이후 dns-default 가 정상으로 돌아왔습니다.

# oc get pod dns-default-jk4gh -n openshift-dns -o wide
NAME                READY   STATUS    RESTARTS   AGE   IP            NODE                      NOMINATED NODE   READINESS GATES
dns-default-jk4gh   2/2     Running   1007       49d   10.131.0.13   worker01.az1.sysdocu.kr   <none>           <none>

 

# oc get co/dns
NAME   VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
dns    4.12.0    True        False         False      49d  

 

콘솔에서 worker01 노드에 로그인이 가능하도록 root 패스워드 설정을 해놓으면 원인을 파악할 수 있던 상황이였는데 core 계정으로 네트워크 로그인만 가능하도록 되어 있어 어쩔수 없이 리부팅하였으며, 이를 계기로 모든 노드에 root 패스워드 설정을 진행하였습니다.

 

참고로, dns 에러 외에 oc get co 명령으로 보였던 몇가지 항목의 에러가 위 조치로 인해 모두 해결되었습니다.

 

image-registry                             4.12.0    True        True          False      49d     Progressing: The registry is ready...


ingress                                    4.12.0    True        True          True       49d     The "default" ingress controller reports Degraded=True: DegradedConditions: One or more other status conditions indicate a degraded state: DeploymentReplicasAllAvailable=False (DeploymentReplicasNotAvailable: 1/2 of replicas are available)

 

monitoring                                 4.12.0    False       True          True       42h     reconciling Prometheus Operator Admission Webhook Deployment failed: updating Deployment object failed: waiting for DeploymentRollout of openshift-monitoring/prometheus-operator-admission-webhook: got 1 unavailable replicas

 

network                                    4.12.0    True        True          False      49d     DaemonSet "/openshift-network-diagnostics/network-check-target" is not available (awaiting 1 nodes)...

 

반응형

댓글()

Openshift / Kubernetes 파드 (Pod) 스케쥴링 - Affinity 옵션

리눅스/OpenShift|2023. 6. 23. 11:41
반응형

Replicas 또는 ReplicaSet 구성후 운영중인 Pod 가 삭제될때, 가용성을 따져보아 다른 worker node 로 재생성되기도 하는데, 여기에서는 Affinity 기능을 이용해 같은 worker node 로 재생성 되도록 하는 방법을 알아봅니다. Affinity 는 worker node 에 Pod 를 배치할때 사용하는 옵션입니다.

 

우선 노드 선택이 가능하도록 노드에 라벨을 추가하여, 키와 값을 입력합니다.

현재 아래와 같이 worker node 가 두개 있는데, 이 노드에 키와 값을 입력해주겠습니다.

# oc get nodes
NAME                      STATUS   ROLES                  AGE   VERSION
master01.az1.sysdocu.kr   Ready    control-plane,master   43d   v1.25.4+77bec7a
master02.az1.sysdocu.kr   Ready    control-plane,master   43d   v1.25.4+77bec7a
master03.az1.sysdocu.kr   Ready    control-plane,master   43d   v1.25.4+77bec7a
worker01.az1.sysdocu.kr   Ready    worker                 42d   v1.25.4+77bec7a
worker02.az1.sysdocu.kr   Ready    worker                 42d   v1.25.4+77bec7a

 

# oc label nodes worker01.az1.sysdocu.kr choice=ALL choicesub=wnode1
node/worker01.az1.sysdocu.kr labeled

- Group 용도로 'choice:ALL' 생성

- 노드 전용으로 'choicesub:wnode1' 생성

 

# oc label nodes worker02.az1.sysdocu.kr choice=ALL choicesub=wnode2

node/worker02.az1.sysdocu.kr labeled

- Group 용도로 'choice:ALL' 생성

- 노드 전용으로 'choicesub:wnode2' 생성

 

* 참고

라벨 삭제 방법입니다. 라벨명 (예: choicesub) 뒤에 - 를 꼭 붙여야 삭제됩니다.

# oc label node <노드명> <라벨명>-

 

설정된 상태를 확인합니다.

# oc get node -L choice,choicesub
NAME                      STATUS   ROLES                  AGE   VERSION           CHOICE   CHOICESUB
master01.az1.sysdocu.kr   Ready    control-plane,master   49d   v1.25.4+77bec7a            
master02.az1.sysdocu.kr   Ready    control-plane,master   49d   v1.25.4+77bec7a            
master03.az1.sysdocu.kr   Ready    control-plane,master   49d   v1.25.4+77bec7a            
worker01.az1.sysdocu.kr   Ready    worker                 49d   v1.25.4+77bec7a   ALL      wnode1
worker02.az1.sysdocu.kr   Ready    worker                 49d   v1.25.4+77bec7a   ALL      wnode2

 

아래와 같이 Deployment yaml 파일을 작성 합니다.

# vi deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      securityContext:
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: app
        image: default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/python
        ports:
        - containerPort: 80
          protocol: TCP
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
          runAsNonRoot: true
      imagePullSecrets:
      - name: sysdocu

      # affinity 사용 옵션
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms: 
            - matchExpressions:   # 특정 Label 의 node 에 Pod 를 생성
              - key: choicesub
                operator: In
                values:
                -
wnode1

 

Affinity 는 Node Affinity 와 Pod Affinity 가 있는데, 어느것을 기준으로 하는지에 따라 다릅니다.

- Node Affinity : 생성된 Pod 를 특정 worker node 에서 가동

- Pod Affinity : Replicas 로 생성된 동일한 Pod 를 같은 worker node 에서 가동
- Pod AntiAffinity : Replicas 로 생성된 동일한 Pod 를 다른 worker node 에서 가동

 

operator 는 Node Affinity 규칙에 사용되는 연산자를 지정하는 필드입니다.

- In : 특정 키 (key) 의 값을 포함하는 경우에 매치. 즉, 값 (values) 이 키에 포함되어 있는 경우 해당 노드에 Pod 를 생성
- Exists : 특정 키 (key) 가 존재하는 경우에 매치. 값 (values) 에 관계없이 키가 존재하면 해당 노드에 Pod 를 생성
- Gt (Greater than) : 특정 키 (key) 의 값이 지정한 값 (values) 보다 큰 경우에 매치. 주로 숫자 값을 비교할 때 사용
- Lt (Less than) : 특정 키 (key) 의 값이 지정한 값 (values) 보다 작은 경우에 매치. 역시 숫자 값을 비교할 때 사용
- NotIn : 특정 키 (key) 의 값을 포함하지 않는 경우에 매치. 값 (values) 이 키에 포함되지 않은 경우 해당 노드에 Pod 를 생성
- DoesNotExist : 특정 키 (key) 가 존재하지 않는 경우에 매치. 값 (values) 에 관계없이 키가 존재하지 않으면 해당 노드에 Pod 를 생성

 

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

참고로, Kubernetes 사용자는 아래 oc 명령대신 kuberctl 을 사용하면 됩니다.

# oc apply -f deployment.yaml

 

Pod 가 어느 worker node 에 생성되었는지 확인합니다.

# oc get pod -o wide
NAME                              READY   STATUS    RESTARTS   AGE   IP            NODE                      NOMINATED NODE   READINESS GATES
app-5f86cc794b-656dg   1/1     Running   0          27s   10.131.0.13   worker01.az1.sysdocu.kr   <none>           <none>

 

Affinity 옵션값의 노드 라벨을 다른 노드로 변경하고, apply 명령으로 적용하면 곧바로 기존 Pod 는 삭제되고, 지정한 노드에 Pod 가 생성됩니다.

원래 Pod 는 스케쥴링 되는 노드 (worker node) 의 가용성 체크 뒤, Round-Robin 방식으로 분배 생성되지만 Affinity 적용 후에는 지정한 노드로만 생성되는것을 확인 할 수 있습니다.

 

노드를 변경하고 (wnode1 -> wnode2)

# sed -i 's/wnode1/wnode2/' deployment.yaml

 

적용합니다.

# oc apply -f deployment.yaml

 

Pod 상태를 확인해보면 지정한 노드에 Pod 가 생성되어진 것을 볼 수 있습니다.
# oc get pod -o wide
NAME                   READY   STATUS        RESTARTS   AGE    IP             NODE                      NOMINATED NODE   READINESS GATES
app-54f888586f-xbmlj   1/1     Running       0          11s    10.128.3.242   worker02.az1.sysdocu.kr   <none>           <none>
app-5f86cc794b-656dg   1/1    Terminating   0          12m   10.131.0.13   worker01.az1.sysdocu.kr   <none>           <none>

 

반응형

댓글()

dd 명령어로 파일 생성하기

리눅스/OS 일반|2023. 6. 20. 16:13
반응형

# dd if=/dev/zero of=sysdocu.bin bs=100M count=10

 

위와 같이 실행시 1GB (100MB * 10) 짜리 sysdocu.bin 파일이 생성됩니다.

 

반응형

댓글()

Openshift / Kubernetes 컨테이너 권한 설정하기

리눅스/OpenShift|2023. 6. 20. 09:13
반응형

Openshift 또는 Kubernetes 에서 컨테이너 생성시 권한을 제한하여 보안을 강화하는 방법이 있습니다.

Pod 생성시 컨테이너 권한 제한 예제입니다.

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: container1
    image: docker.io/php
    securityContext:
      capabilities:
        add: ["ALL"]
        remove: ["SYS_ADMIN", "SETUID", "SETGID", "SETPCAP", "SYS_MODULE", "SYS_BOOT", "NET_ADMIN", "SYS_RAWIO"]
...

 

위 예제에서 container1 컨테이너의 securityContext 에서 SYS_ADMIN 외 여러개의 권한을 제한하도록 설정하였습니다. 이렇게 하면 container1 에서만 시스템 관리 작업과 기타 작업을 위한 명령어 사용이 제한됩니다. 아래는 securityContext의 capabilities 섹션에서 remove 필드에 사용할 수 있는 종류 중 일부 목록입니다. 아래 항목을 remove 필드에 추가하여 사용을 제한하면, 컨테이너 보안 강화에 도움이 됩니다.

"SETPCAP": 프로세스의 임의의 캐퍼빌리티 설정을 방지합니다.
"SYS_MODULE": 커널 모듈의 적재 및 언로드를 방지합니다.
"SYS_RAWIO": 장치에 대한 원시 입출력을 방지합니다.
"SYS_PACCT": 프로세스 계정 정보에 대한 접근을 제한합니다.
"SYS_ADMIN": 시스템 관리 작업을 수행할 수 있는 권한을 제한합니다.
"SYS_NICE": 프로세스에 대한 우선 순위 설정을 방지합니다.
"SYS_RESOURCE": 자원 제한에 대한 설정을 방지합니다.
"SYS_TIME": 시스템 시간 설정을 방지합니다.
"SYS_PTRACE": 다른 프로세스에 대한 추적 기능을 제한합니다.
"SYS_BOOT": 부팅 설정을 제한합니다.
"DAC_READ_SEARCH": 파일의 소유권 및 검색 설정에 대한 권한을 제한합니다.
"LINUX_IMMUTABLE": 파일의 변경 및 수정을 방지합니다.
"NET_ADMIN": 네트워크 설정에 대한 권한을 제한합니다.
"IPC_LOCK": 공유 메모리 세그먼트에 대한 락 설정을 방지합니다.

 

반응형

댓글()

리눅스 CLI 에서 Github 원격지 리포지토리 (repogitory) 소스코드 다운로드하기 (Public / Private)

리눅스/OS 일반|2023. 6. 16. 14:39
반응형

Github 에 올려진 소스 코드를 다운로드 하는 방법입니다.

CentOS 7 환경에서 테스트하였습니다.

1. 패키지 설치
우선 소스 코드를 다운로드 하기위해 github 패키지를 설치합니다.
# yum -y install git


2. Public 코드 다운로드
공개 코드는 아무나 접근하여 다운로드가 가능하므로 아래와 같이 실행할 수 있습니다.
# git clone https://github.com/sysdocu/html-sample.git

리포지토리 이름으로 생성된 디렉토리로 이동합니다.
# cd html-sample

파일 내용을 확인합니다.
# ls -al

3. Private 코드 다운로드
1) 직접 계정 입력
Private 리포지토리 URL 을 공개 코드 다운로드와 같이 명령을 실행하면 Username, Password 를 입력하는 절차가 출력됩니다. 하지만 CLI 에서 명령 한줄로 처리하고자 할때 아래와 같이 사용이 가능합니다.
# git clone https://<username>:<password>@github.com/sysdocu/html-secret.git

CLI 한줄에 계정 정보 입력시 <username> 이나 <password> 에 특수문자가 들어가게 될 경우 아래와 같은 문자로 치환해주어야 합니다.

[이미지 출처] https://stackoverflow.com/questions/10054318/how-do-i-provide-a-username-and-password-when-running-git-clone-gitremote-git/10056098#10056098

2) Git 자격 증명 사용
직접 계정을 입력하는 방법은 history 에도 남고 패스워드가 탈취될 가능성이 있기 때문에 안전한 방법이 아닙니다. 하지만 강화된 보안 방법인 'Git 자격 증명' 을 사용하면 계정이 아닌 토큰으로 인증이 가능하며, 계정에 대한 작업 권한도 제어가 가능하고, 일정 시간이 지나 토큰의 효력이 상실되기 때문에 패스워드 탈취에 대한 부담도 줄일 수 있습니다.

 

우선 Github 에 로그인을 하고 토큰 생성 페이지 (바로가기 : https://github.com/settings/tokens) 로 이동합니다.

페이지 내에서 'Generate a personal access token' 링크 또는 'Generate new token' > 'Generate new token (classic)' 을 누르고, 토큰 발급 이유를 'Note' 에 적당히 입력 후, 토큰의 만료 기간을 선택합니다. repo 의 모든 기능에만 체크하고, 하단의 [Generate token] 를 누르면 토큰이 출력됩니다. 이것을 복사하여 CLI 명령어에 사용하도록 합니다.

# git clone https://<token>@github.com/sysdocu/html-secret.git


다운로드가 확인되었으며, 리포지토리 이름으로 생성된 디렉토리로 이동합니다.
# cd html-secret

파일 내용을 확인합니다.
# ls -al

 

반응형

댓글()

C/C++ 프로그레스바 (ProgressBar)

프로그래밍/C, C++|2023. 6. 16. 07:57
반응형

C/C++의 콘솔 환경에서 프로그레스바 (진행바) 구현 소스입니다.

아래와 같이 심플하게 개수, 프로그레스바, 진행률 이 출력됩니다.

 

10/10 [==================================================] 100%

 

#include <stdio.h>
#include <stdlib.h>  
#include <windows.h> // Sleep 함수 

int main() {
        const char bar = '='; // 프로그레스바 문자  
        const char blank = ' '; // 비어있는 프로그레스바 문자  
        const int LEN = 20; // 프로그레스바 길이  
        const int MAX = 1000; // 진행작업 최대값 
        const int SPEED = 50; // 카운트 증가 대기시간  
        int count = 0; // 현재 진행된 작업  
        int i; // 반복문 전용 변수  
        float tick = (float)100/LEN; // 몇 %마다 프로그레스바 추가할지 계산 
        printf("%0.2f%% 마다 bar 1개 출력\n\n", tick); 
        int bar_count; // 프로그레스바 갯수 저장 변수  
        float percent; // 퍼센트 저장 변수  
        while(count <= MAX) {
                printf("\r%d/%d [", count, MAX); // 진행 상태 출력  
                percent = (float)count/MAX*100; // 퍼센트 계산  
                bar_count = percent/tick; // 프로그레스바 갯수 계산  
                for(i=0; i<LEN; i++) { // LEN길이의 프로그레스바 출력  
                        if(bar_count > i) { // 프로그레스바 길이보다 i가 작으면 
                                printf("%c", bar);
                        } else { // i가 더 커지면  
                                printf("%c", blank);
                        }
                }
                printf("] %0.2f%%", percent); // 퍼센트 출력  
                count++; // 카운트 1증가  
                Sleep(SPEED); // SPEEDms 대기  
        }
        printf(" done!\n\n");
        system("pause"); // 프로그램 종료 전 일시정지  
        return 0; 
}

 

1000개의 전체 작업량 중 1개가 완료되었다면 진행률은 0.1%가 됩니다.
현재 진행량/전체 진행량 * 100 = 진행률(%)
100분율 계산법입니다.
해당 연산은 코드의 19행에서 진행하고 있습니다.
현재 진행량은 코드상에서 count 변수
전체 진행향은 코드상에서 MAX 변수입니다.

진행률을 계산했으면 해당 진행률을 기준으로 프로그레스바(진행바)를 출력해야합니다.
100(%)/프로그레스바 길이 = 몇 %마다 프로그레스바 1개 출력
만약 프로그레스바의 길이가 20이라고 하면
100/20 = 5
[====================] 100%
위의 모습일겁니다.

길이는 고정되어있음으로 진행률 퍼센트에 따라 = 문자를 출력해줘야 하죠
코드의 13행에서 해당 계산을 진행하고 있습니다.
계산 후 tick 이라는 변수에 저장해두었습니다.

20길이의 프로그레스바는 5% 마다 = 한개를 출력합니다.
10%라고 하면 == 를 출력하겠죠?

17~31행의 while 문은 0~전체 진행량까지 반복하는 반복문입니다.
19행에서 매번 반복마다 진행률(%)을 계산하여
20행에서 프로그레스바 = 문자를 몇개 출력할지 계산한 후
그 아래 21행 for문에서 출력을 합니다.

for문은 0~LEN 까지 반복을 하는데 LEN은 프로그레스바의 길이가 저장되있는 변수이름입니다.
20이라고 가정하면 0~20까지 반복하계되죠
bar_count는 20행에서 현재 %는 몇개의 =문자를 출력할지 저장되어있습니다.

만약 프로그레스바 길이가 20이고 진행률이 7%라고 가정합시다.

1 - 13행처럼 먼저 몇 %마다 =문자를 출력할지 계산
100/20 = 5(%)
tick = 5

2 - bar_count에 현재 퍼센트는 몇개의 =를 출력할지 계산
percent/tick = 갯수
7/5 = 1(나머지 버림)
bar_count = 1

3 - for문에서 출력
LEN이 20이므로 i = 0~20
if(bar_count > i) 
0~20까지 i가 증가하면서 bar_count와 비교하여 출력
bar_count는 현재 1이 저장되어있으므로 i가 0일때만 참
20번 반복하면서 =하나를 출력하게 되고
거짓인 경우에는 else 로 가서 공백을 출력합니다.

4 - for문으로 출력 후 퍼센트 출력 및 count 증가
count(현재 진행량)를 1 증가

위의 과정을 현재 진행량~전체 진행량까지 반복하여 100%가 되면 종료합니다.
출력하는데 왜 이어서 출력이 되지않고 원래 위치 그대로에서 출력될까요?
그 문제는 18행에 있습니다.
printf("\r")

\r 이스케이프 시퀀스는 해당 라인의 첫 번째 위치로 이동합니다.
첫 번째로 이동한 후 다시 출력을 하게되어 위치가 바뀌지않고 진행되는이유입니다.

 

[출처] https://geundung.dev/43

 

 

반응형

댓글()

Openshift 4.12.0 PV, PVC (GlusterFS) 를 이용한 Volume 추가

리눅스/OpenShift|2023. 6. 8. 14:59
반응형

GlusterFS Cluster 정보를 이용하여 Endpoint 를 작성합니다.

# vi endpoint.yaml

apiVersion: v1
kind: Endpoints
metadata:
  name: glusterfs-cluster
subsets:
  - addresses:
      - ip: 115.68.249.122
      - ip: 115.68.248.172
      - ip: 115.68.249.106
    ports:
      - port: 1

 

* 설명

subsets: address: ip: 는 GlusterFS 클러스터를 구성하는 서버의 실제 IP 주소여야 합니다.

subsets: ports: port: 에 입력하는 포트번호는 무시해도 됩니다.

 

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

# oc apply -f endpoint.yaml
endpoints/glusterfs-cluster created

 

적용된 Endpoint 를 확인합니다.

# oc get ep
NAME                          ENDPOINTS                                            AGE
endpoints/glusterfs-cluster   115.68.249.122:1,115.68.248.172:1,115.68.249.106:1   12m

 

PV (Persistent Volume) 생성을 위한 yaml 파일을 작성합니다.

# vi pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: glusterfs-pv
spec:
  storageClassName: ""
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  glusterfs:
    endpoints: glusterfs-cluster
    path: /gv0
    readOnly: false
  persistentVolumeReclaimPolicy: Retain

 

storageClassName: 빈 문자열을 명시적으로 사용해야 합니다. 그렇지 않으면 기본 StorageClass 가 설정됩니다.

glusterfs: endpoints: 에는 먼저 생성했던 Endpoint 이름 입니다.

glusterfs: path: 에는 마운트할 GlusterFS 의 볼륨입니다. 앞에 슬래시를 꼭 붙여줘야 합니다. 그리고 /gv0/apple 과 같이 쿼터 적용된 디렉토리로도 마운트 가능합니다.

persistentVolumeReclaimPolicy: 의 Retain 값은 PV 가 삭제되어도 GlusterFS 내의 데이터는 삭제하지 않겠다는 뜻입니다.

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

# oc apply -f pv.yaml

persistentvolume/glusterfs-pv created

 

Pod 와 PV 를 연결하기 위한 PVC (PersistentVolumeClaim) yaml 파일을 작성합니다.

# vi pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: glusterfs-pvc
spec:
  storageClassName: ""
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
  volumeName: glusterfs-pv

 

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

# oc apply -f pvc.yaml

persistentvolumeclaim/glusterfs-pvc created

 

Deployment yaml 를 작성하여 Pod 가 생성되도록 합니다.

# vi deployment_volume.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: glusterfs-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: glusterfs-pod
  template:
    metadata:
      labels:
        app: glusterfs-pod
    spec:
      securityContext:
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: glusterfs-pod
        image: default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/python
        ports:
        - containerPort: 8080
          protocol: TCP
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
          runAsNonRoot: true
        volumeMounts:
        - name: my-volume
          mountPath: /data
      volumes:
      - name: my-volume
        persistentVolumeClaim:
          claimName: glusterfs-pvc
      imagePullSecrets:
      - name: sysdocu

 

volumeMounts: mountPath: 는 Pod 내에서 마운트 될 디렉토리를 의미하며 디렉토리가 없는 경우 자동으로 생성됩니다.

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

# oc apply -f deployment_volume.yaml

 

Pod 에 Volume 이 잘 연결되었는지 확인합니다.

# oc get pod
NAME                                    READY   STATUS        RESTARTS   AGE
glusterfs-deployment-7c45b99b7c-pstl5   1/1     Running       0          7s

 

# oc rsh glusterfs-deployment-7c45b99b7c-pstl5

$ df -h
Filesystem                Size  Used Avail Use% Mounted on
overlay                   233G   36G  197G  16% /
tmpfs                      64M     0   64M   0% /dev
tmpfs                     7.8G     0  7.8G   0% /sys/fs/cgroup
shm                        64M     0   64M   0% /dev/shm
tmpfs                     7.8G   53M  7.7G   1% /etc/passwd
115.68.249.122:/gv0   10G  135M  9.9G   2% /data
/dev/sda4                 233G   36G  197G  16% /etc/hosts
tmpfs                      15G   20K   15G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                     7.8G     0  7.8G   0% /proc/acpi
tmpfs                     7.8G     0  7.8G   0% /proc/scsi
tmpfs                     7.8G     0  7.8G   0% /sys/firmware

 

* 참고

마운트가 되지 않을 경우 Pod 부터 정상 가동 (Running) 되지 않습니다. 그런 경우에 GlusterFS 를 구성하는 노드가 DNS 에서 질의되지 않는 호스트명으로 되어있는지 확인해 볼 필요가 있습니다. gnode1, gnode2, gnode3 등의 호스트명으로 GlusterFS 노드가 구성 되어 있다면 worker 노드에서 마운트 하지 못하므로 모든 스케쥴링 되는 Openshift 노드 (worker node) 에 /etc/hosts 파일을 수정하여 GlusterFS 를 구성하는 노드의 IP 와 호스트명을 등록해놔야 합니다.

 

반응형

댓글()

CentOS 7 에서 GlusterFS 를 yum 으로 설치하기 (각종 구성 방법)

리눅스/OS 일반|2023. 6. 7. 11:41
반응형

GlusterFS 는 분산 파일 시스템으로써 여러 대의 서버를 클러스터로 구성하여 대용량의 데이터를 분산 저장하고 관리할 수 있는 기술입니다. RAID 와 같이 각각의 노드에 데이터를 따로 저장하거나 (Distributed), 복제 저장하거나 (Replicated), 분산 저장 (Disperse) 이 가능합니다. GlusterFS 는 Redhat 이 개발하고 오픈 소스로 제공되며, 다양한 용도의 분산 스토리지 및 파일 공유에 이용됩니다.

 

본 매뉴얼에서의 테스트 환경은 CentOS 7 이며, 다양한 볼륨 구성을 예제로 다루었습니다.

CentOS 6 또는 8 버전은 설치 방법에 약간 차이가 있으니 아래 Documents 를 참고해 주세요.

https://wiki.centos.org/SpecialInterestGroup/Storage/gluster-Quickstart

 

[사전 작업]
각 노드에 추가 Disk 를 연결하고 /data 디렉토리로 마운트 했습니다.
그리고 각 마운트 디렉토리 안에 gv0 이라는 Brick 디렉토리를 생성해 두었습니다.

Brick 디렉터리는 GlusterFS 볼륨에서 데이터를 저장하는 디렉터리를 뜻합니다.
- /data/gv0

 

 

1. GlusterFS 서버 구축

 

1) hostname 설정

호스트 명을 변경합니다.
# hostnamectl set-hostname gnode1  // 1번 노드에서
# hostnamectl set-hostname gnode2  // 2번 노드에서

# hostnamectl set-hostname gnode3  // 3번 노드에서

 

(모든 노드에서)
호스트를 등록 합니다.
# vi /etc/hosts

127.0.0.1   localhost localhost.localdomain gnode1
192.168.10.20 gnode2
192.168.10.30 gnode3

 

위는 gnode1 의 hosts 내용인데, 자신의 노드는 따로 행을 추가하지 말고 127.0.0.1 라인에 기록해 둡니다.

gnode2, gnode3 노드에서의 hosts 는 각각 다음과 같습니다.

127.0.0.1   localhost localhost.localdomain gnode2
192.168.10.10 gnode1
192.168.10.30 gnode3

 

127.0.0.1   localhost localhost.localdomain gnode3
192.168.10.10 gnode1
192.168.10.20 gnode2

 

2) 패키지 설치
GlusterFS 설치를 위한 Repository 를 등록해줍니다.
등록은 yum 로 간단히 할 수 있습니다.
# yum -y install centos-release-gluster

 

GlusterFS 패키지를 설치합니다.
# yum -y install glusterfs glusterfs-libs glusterfs-server

서버 부팅시 glusterd 데몬이 자동 구동 되도록 하고, 현재 세션에서도 구동시켜줍니다.
# systemctl enable --now glusterd

 

설치된 버전을 확인합니다.

# glusterd --version
glusterfs 9.6
Repository revision: git://git.gluster.org/glusterfs.git
Copyright (c) 2006-2016 Red Hat, Inc. <https://www.gluster.org/>
GlusterFS comes with ABSOLUTELY NO WARRANTY.
It is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3
or later), or the GNU General Public License, version 2 (GPLv2),
in all cases as published by the Free Software Foundation.

 

서버간 통신이 이루어져야 하므로 firewalld 또는 iptables 와 같은 방화벽에서 서로의 IP 를 허용해주거나, 데이터가 없는 테스트 서버일 경우 방화벽을 잠시 내려 테스트 합니다.

 

 

2. 복제 (Replica) 볼륨 구성

 

replica 볼륨은 데이터를 여러 브릭에 복제하여 데이터의 안정성과 내구성을 제공합니다.

RAID 시스템의 1 (mirror) 과 유사합니다. 노드 2대로만 구성하는 것이 아니고 여러대로 복제가 가능합니다.

GlusterFS 에서는 기본 3대 이상으로 구성할 것을 권하고 있으며, 2대로 구성을 원할경우 아래 '8. 판사 (Arbiter) 볼륨 구성' 을 참고하세요.

여기에서는 3대의 노드로 구성해 보겠습니다.

패키지 설치와 호스트네임 등록 이후의 설정은 하나의 노드에서만 합니다.

 

1) Pool 연결

(gnode1 노드에서)

Cluster Pool 을 구성합니다.

# gluster peer probe gnode2

peer probe: success

# gluster peer probe gnode3
peer probe: success

 

연결된 노드를 확인합니다.

gnode1 에서 명령 실행시 연결된 두개의 노드 (gnode2, gnode3) 가 보입니다.

# gluster peer status
Number of Peers: 2

 

Hostname: gnode2
Uuid: edea03f3-472b-47b5-a711-ed06763631c4
State: Peer in Cluster (Connected)

 

Hostname: gnode3
Uuid: 0771cb09-89d3-4a5b-8e7d-3980473ffc0e
State: Peer in Cluster (Connected)

 

다른 노드에서도 같은 명령을 사용해보면 자신의 노드를 제외한 총 2개의 노드 정보가 확인됩니다.

참고로 peer 노드 제거 명령은 'gluster peer detach <노드명>' 을 사용합니다.

 

Pool 리스트를 확인합니다.

# gluster pool list
UUID Hostname  State
edea03f3-472b-47b5-a711-ed06763631c4 gnode2    Connected 
0771cb09-89d3-4a5b-8e7d-3980473ffc0e gnode3    Connected 
25d3f6cb-b2ed-4aa1-add7-0a27890ed5ed localhost Connected 

 

이 명령에서는 자신의 노드를 포함한 총 3개의 노드 정보가 확인됩니다.

 

2) 볼륨 생성

데이터를 저장할 수 있도록 GlusterFS 볼륨을 생성합니다.

(gnode1 노드에서)

3대의 노드를 하나의 볼륨으로 묶습니다. (볼륨명 : gv0, 복제본 : 3)

# gluster volume create gv0 replica 3 gnode1:/data/gv0 gnode2:/data/gv0 gnode3:/data/gv0

volume create: gv0: success: please start the volume to access data

 

여기에서 volume create: gv0: failed: /data/gv0 is already part of a volume 에러가 출력되는 분은 아래 '5. 볼륨 재구성' 을 참고하세요.

노드 서버 3대로 복제 저장 구성을 한 이유는 2대로만 복제 구성하면 스플릿 브레인에 취약할 수 있기 때문입니다. 스플릿 브레인은 분산 파일 시스템에서 복제된 데이터의 일관성을 유지하기 위해 중요한 개념입니다. 복제된 볼륨이 스플릿 브레인에 취약하다는 것은 데이터의 불일치가 발생할 수 있는 가능성이 있다는 것을 의미합니다. 복제 2 볼륨은 두 개의 복제본을 가지고 있으므로 데이터의 일관성을 유지하기 위해 두 복제본이 동기화되어야 합니다. 그러나 네트워크 문제, 장애 등의 이유로 복제본 간의 통신이 중단되면 각각의 복제본이 독립적으로 운영되는 상황이 발생할 수 있습니다. 이는 데이터의 일관성을 해치는 스플릿 브레인 상태를 초래할 수 있습니다.

 

gv0 볼륨을 시작합니다.

# gluster volume start gv0

volume start: gv0: success

 

gv0 볼륨 상태를 확인합니다.

# gluster volume info gv0

 
Volume Name: gv0
Type: Replicate
Volume ID: 09540703-2a84-4dce-bb6c-af156cf1813d
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 3 = 3
Transport-type: tcp
Bricks:
Brick1: gnode1:/data/gv0
Brick2: gnode2:/data/gv0
Brick3: gnode3:/data/gv0
Options Reconfigured:
cluster.granular-entry-heal: on
storage.fips-mode-rchecksum: on
transport.address-family: inet
nfs.disable: on
performance.client-io-threads: off

 

* 중요 : 볼륨 생성 후 옵션을 하나 설정합니다.

볼륨 구성이 어떠한 형태이던 (비록 replica 일지라도) GlusterFS Cluster 를 구성하는 한 개의 peer 가 장애가 났을때 Client 는 42초간 (default) GlusterFS 의 응답을 기다리느라 데이터를 읽거나 쓰지 못하게 됩니다. 서비스 제공시 42초는 긴 시간이기 때문에 장애 서버의 다운을 감지하고 해당 peer 를 빠르게 제거하기 위한 옵션 network.ping-timeout 을 설정해 주어야 합니다.

여기에서는 서버 응답 대기시간을 0초로 적용합니다. 이렇게 하면 peer 다운시 찰나의 지연 (delay) 이 있지만 끊어지지 않으며 데이터 유실또한 발생하지 않습니다.

# gluster volume set gv0 network.ping-timeout 0

volume set: success

# gluster volume info | grep timeout
network.ping-timeout: 0

추후 장애 peer 복구시 파티션 (Brick Directory) 연결 및 glusterd 데몬이 순자적으로 이루어진다면, 다른 peer 에서 생성, 변경된 파일이 자동으로 동기화되어 최신 데이터를 유지하게 됩니다.

 

사용가능한 옵션 종류는 아래 URL 에서 확인 가능합니다.

https://access.redhat.com/documentation/ko-kr/red_hat_gluster_storage/3.5/html/administration_guide/volume_option_table

 

* 데이터 저장 형태

데이터가 어느 노드에 어떻게 저장되는지 확인하고 싶어서 적당한 크기의 파일을 하나씩 입력해 보았고 아래 내용으로 확인되었습니다.

- 파일을 저장하면 replica 3 으로 구성된 gnode1, gnode2, gnode3 노드에 동일한 데이터 저장

 

 

3. Quota 설정

 

Brick 디렉토리에 하위 디렉토리를 생성하여 용량을 제한을 할 수 있습니다.

공식 Document : https://docs.gluster.org/en/v3/Administrator%20Guide/Directory%20Quota/

 

gv0 볼륨 쿼터 설정을 활성화 합니다.

# gluster volume quota gv0 enable

volume quota : success

 

참고로 비활성화는 enable 대신 disable 을 입력합니다.

그리고 Client 가 마운트하여 사용하던 중 쿼터 제한을 걸때 사용하는 옵션이 있는데 이에 대한 설명은 아래와 같습니다. (Default : on)

# gluster volume set gv0 quota-deem-statfs on

 

* 참고

- on: GlusterFS는 디렉토리의 용량 제한을 강제로 적용하고, 해당 디렉토리에서 사용 가능한 실제 용량을 디렉토리의 용량 제한으로 간주합니다. 즉, 사용자가 설정한 용량 제한보다 실제 사용 중인 용량이 크더라도 GlusterFS는 해당 디렉토리의 용량 제한을 적용합니다. 이는 사용자가 실제 사용 중인 용량을 고려하지 않고 일관된 용량 제한을 유지하고자 할 때 유용합니다.

(예 : 2GB 데이터 사용중에 쿼터를 1GB 로 제한하면, 제한값은 1GB 에 머물러 있음)
- off: GlusterFS는 디렉토리의 용량 제한을 강제로 적용하지 않고, 실제 사용 중인 용량을 기준으로 디렉토리의 용량 제한을 판단합니다. 즉, 사용자가 설정한 용량 제한보다 실제 사용 중인 용량이 크다면 GlusterFS는 해당 디렉토리의 용량 제한을 초과로 간주합니다. 이는 실제 사용 중인 용량을 기준으로 용량 제한을 적용하고자 할 때 유용합니다.

(예 : 2GB 데이터 사용중에 쿼터를 1GB 로 제한하면, 제한값은 2GB 에 머물러 있음)

 

하위 디렉토리를 그냥 만들면 mkdir 명령을 내린 노드에서만 디렉토리가 생성되기때문에 쿼터 적용이 되지 않습니다.

볼륨을 마운트하고 디렉토리를 만들어 놓아야 합니다.

Client 또는 아무 node 에서나 마운트 명령을 내려도 상관없습니다.

# mkdir /imsi

# mount -t glusterfs gnode1:/gv0 /imsi

# mkdir /imsi/{apple,banana,grape}

# umount /imsi

 

하위 디렉토리에 각 1G 씩 용량 제한을 합니다.

디렉토리를 지정할때는 Brick 디렉토리 (/data/gv0) 를 제외하고 하위 디렉토리만 입력합니다.

# gluster volume quota gv0 limit-usage /apple 1GB

volume quota : success
# gluster volume quota gv0 limit-usage /banana 1GB
volume quota : success
# gluster volume quota gv0 limit-usage /grape 1GB
volume quota : success

 

gv0 볼륨의 쿼터 설정값을 확인합니다.

# gluster volume quota gv0 list

                  Path                   Hard-limit  Soft-limit      Used  Available  Soft-limit exceeded? Hard-limit exceeded?
-------------------------------------------------------------------------------------------------------------------------------
/apple                                     1.0GB     80%(819.2MB)   0Bytes   1.0GB              No                   No
/banana                                    1.0GB     80%(819.2MB)   0Bytes   1.0GB              No                   No
/grape                                     1.0GB     80%(819.2MB)   0Bytes   1.0GB              No                   No

 

Hard-limit 는 1GB 로 원하는 용량이 제한 되었지만, Soft-limit 는 80% 선으로 설정된 것이 보입니다.

- Hard-limit : 사용자 또는 프로세스가 설정된 최대 제한을 초과하지 못하도록 하는 제한하는 값입니다.

- Soft-limit : 사용자 또는 프로세스가 현재 사용 중인 리소스의 제한으로, 사용자가 시스템 리소스를 임시로 초과할 수 있는 한계를 설정합니다. Soft-limit은 Hard-limit 보다 작거나 같아야 합니다. Soft-limit 을 초과하려는 경우에는 경고가 발생하지만 작업을 계속할 수 있습니다. 시스템의 안정성을 고려하기 위해 용량이 거의 채워져간다는 알림을 주기 위한 용도 정도로 보면 됩니다.

 

Soft-limit 도 100% 까지 사용하기 위해 아래와 같이 변경 설정 해줍니다.

# gluster volume quota gv0 limit-usage /apple 1GB 100
volume quota : success
# gluster volume quota gv0 limit-usage /banana 1GB 100
volume quota : success
# gluster volume quota gv0 limit-usage /grape 1GB 100
volume quota : success

 

변경 내용을 확인합니다.

# gluster volume quota gv0 list
                  Path                   Hard-limit  Soft-limit      Used  Available  Soft-limit exceeded? Hard-limit exceeded?
-------------------------------------------------------------------------------------------------------------------------------
/apple                                     1.0GB    100%(1.0GB)   0Bytes   1.0GB              No                   No
/banana                                    1.0GB    100%(1.0GB)   0Bytes   1.0GB              No                   No
/grape                                     1.0GB    100%(1.0GB)   0Bytes   1.0GB              No                   No

 

 

4. Client 마운트

 

GlusterFS 에서는 몇가지 마운트 방법을 제공합니다. GlusterFS (FUSE), NFS, iSCSI, SMB 방식인데 여기에서는 일반적인 FUSE 방식을 설명하겠습니다.

Client 에서 마운트에 필요한 패키지를 설치하고 마운트를 합니다.

GlusterFS 서버를 찾을 수 있도록 도메인을 연결하면 좋겠지만 현재 테스트 환경에서는 hosts 파일을 이용하였으므로 Client 에서도 찾을 수 있도록 /etc/hosts 파일에 아래 내용을 작성해 줍니다.

# vi /etc/hosts

127.0.0.1   localhost localhost.localdomain
192.168.10.10 gnode1
192.168.10.20 gnode2
192.168.10.30 gnode3

 

그리고 마운트 할때는 gnode1 부터 gnode3 까지 아무 서버로 연결해도 상관없습니다.

# yum -y install glusterfs-client

# mkdir /backup

# mount -t glusterfs gnode1:/gv0 /backup

 

또는 쿼터 적용된 디렉토리로 마운트가 가능합니다.

# mount -t glusterfs gnode1:/gv0/apple /backup

 

마운트 디렉토리에 파일을 쓰면 모든 노드에 동일하게 복제되어 저장됩니다.

 

 

-------------------- 여기부터 다양한 스토리지 구성 테스트 --------------------

 

 

5. 볼륨 재구성 (볼륨 완전 삭제, 재생성)

 

볼륨을 삭제하고 다시 구성할때 에러가 발생하는데 어떻게 해결하는지 알아봅니다.

볼륨을 중지해야 삭제가 가능하기 때문에 먼저 중지 명령을 내립니다.

# gluster volume stop gv0
Stopping volume will make its data inaccessible. Do you want to continue? (y/n) y
volume stop: gv0: success

 

볼륨을 삭제합니다.
# gluster volume delete gv0
Deleting volume will erase all information about the volume. Do you want to continue? (y/n) y
volume delete: gv0: success

 

이 상태에서 동일한 디렉토리로 볼륨 설정을 하면 아래와 같이 에러가 발생합니다.

# gluster volume create gv0 replica 3 gnode1:/data/gv0 gnode2:/data/gv0 gnode3:/data/gv0
volume create: gv0: failed: /data/gv0 is already part of a volume

 

이는 볼륨을 생성하려는 디렉토리에 메타데이터가 있거나 구성의 흔적 때문인데, 해결책은 아래와 같습니다.

 

(모든 노드에서 : 볼륨 구성했던 이력이 있는 모든 서버)

# setfattr -x trusted.glusterfs.volume-id /data/gv0
# setfattr -x trusted.gfid /data/gv0
# rm -rf /data/gv0/.glusterfs*

 

그리고 하나의 노드에서 아래와 같이 명령을 내리면 볼륨이 정상적으로 생성됩니다.

# gluster volume create gv0 replica 3 gnode1:/data/gv0 gnode2:/data/gv0 gnode3:/data/gv0
volume create: gv0: success: please start the volume to access data

 

 

6. 장애 노드 (peer) 교체

 

replica 3 (peer 3개) 으로 구성된 cluster 에서 1개의 노드 (peer) 가 장애나면 2개의 peer 에서 무정지로 서비스가 가능합니다. 이때 장애난 peer 를 새로운 서버로 변경한다고 했을때 cluster 를 재구성 하는 방법 입니다.

gnode1, gnode2, gnode3 중에서 gnode2 가 장애 났다고 가정합니다.

 

사전작업으로 gnode2 노드에 추가 Disk 를 연결하고 /data 디렉토리로 마운트 했습니다.
그리고 마운트 디렉토리 안에 gv0 이라는 Brick 디렉토리를 생성해 두었습니다..
- /data/gv0

 

(gnode1 또는 gnode3 에서)

remove-brick 명령을 이용해 장애난 peer 를 replica cluster 에서 제외합니다. (replica 3 -> 2)
# gluster volume remove-brick gv0 replica 2 gnode2:/data/gv0 force
Remove-brick force will not migrate files from the removed bricks, so they will no longer be available on the volume.
Do you want to continue? (y/n) y
volume remove-brick commit force: success

 

peer 목록에서 제외합니다.
# gluster peer detach gnode2
All clients mounted through the peer which is getting detached need to be remounted using one of the other active peers in the trusted storage pool to ensure client gets notification on any changes done on the gluster configuration and if the same has been done do you want to proceed? (y/n) y
peer detach: success

볼륨 정보를 확인합니다.
# gluster volume info
 
Volume Name: gv0
Type: Replicate
Volume ID: 8e2fbb51-5f00-43f3-9d09-0655cac39dfb
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: gnode1:/data/gv0
Brick2: gnode3:/data/gv0
Options Reconfigured:
performance.client-io-threads: off
nfs.disable: on
transport.address-family: inet
storage.fips-mode-rchecksum: on
cluster.granular-entry-heal: on
network.ping-timeout: 0

gnode2 라는 peer 가 cluster 에서 제거된 것이 확인되었습니다.
다시 peer 를 추가 하고 replica 3 으로 재설정하여 데이터를 동기화 합니다. 

# gluster peer probe gnode2
peer probe: success

add-brick 명령으로 새로운 노드 하나만 기입하여 replica 3 으로 재구성 합니다.
# gluster volume add-brick gv0 replica 3 gnode2:/data/gv0
volume add-brick: success

 

이렇게 작업은 마무리 되었습니다.
참고로 success 메세지가 출력되어도 데이터가 동기화 되는 것에는 시간이 걸리므로 상태를 잘 지켜보시기 바랍니다.

 

 

7. 복제 (Replica) 볼륨 확장

 

1) Replica 증설 및 축소

3개의 노드가 replica 3 으로 구성된 상태에서 노드를 한대 더 추가하여 replica 4 로 구성해보겠습니다. (replica 3 -> 4)

먼저 추가되는 노드 (gnode4) 에서 사전 작업을 해주세요.

- 추가디스크 mount (/data) 및 디렉토리 생성 (/data/gv0)

- hostname 및 hosts 설정 (기존 노드 포함)

- glusterfs 패키지 설치 및 가동

 

기존 노드 서버에서 피어를 추가하고 재구성 명령을 실행합니다.

# gluster peer probe gnode4
peer probe: success

# gluster volume add-brick gv0 replica 4 gnode4:/data/gv0
volume add-brick: success

 

볼륨 정보를 출력합니다.

# gluster volume info
 
Volume Name: gv0
Type: Replicate
Volume ID: 63328573-90cc-4272-8094-9fd7b9d74821
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 4 = 4
Transport-type: tcp
Bricks:
Brick1: gnode1:/data/gv0
Brick2: gnode2:/data/gv0
Brick3: gnode3:/data/gv0
Brick4: gnode4:/data/gv0
Options Reconfigured:
features.quota-deem-statfs: on
features.inode-quota: on
features.quota: on
cluster.granular-entry-heal: on
storage.fips-mode-rchecksum: on
transport.address-family: inet
nfs.disable: on
performance.client-io-threads: off

 

추가했던 노드를 제거하는 방법은 다음과 같습니다. (replica 4 -> 3)

# gluster volume remove-brick gv0 replica 3 gnode4:/data/gv0 force
Remove-brick force will not migrate files from the removed bricks, so they will no longer be available on the volume.
Do you want to continue? (y/n) y
volume remove-brick commit force: success

 

# gluster peer detach gnode4
All clients mounted through the peer which is getting detached need to be remounted using one of the other active peers in the trusted storage pool to ensure client gets notification on any changes done on the gluster configuration and if the same has been done do you want to proceed? (y/n) y
peer detach: success

 

볼륨 정보를 확인합니다.

# gluster volume info
 
Volume Name: gv0
Type: Replicate
Volume ID: 63328573-90cc-4272-8094-9fd7b9d74821
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 3 = 3
Transport-type: tcp
Bricks:
Brick1: gnode1:/data/gv0
Brick2: gnode2:/data/gv0
Brick3: gnode3:/data/gv0
Options Reconfigured:
features.quota-deem-statfs: on
features.inode-quota: on
features.quota: on
cluster.granular-entry-heal: on
storage.fips-mode-rchecksum: on
transport.address-family: inet
nfs.disable: on
performance.client-io-threads: off

 

2) Replica 용량 증설

replica 3 은 복제본이 3개 있다는 뜻이므로 데이터 안정성을 어느정도 확보 했다고 볼 수 있습니다. 하지만 노드의 용량이 줄어들 경우에는 또다른 노드를 마련해서 데이터 저장 공간을 확보해야 하는데요. 추가할 노드 수는 복제본 수의 배수여야 합니다. (예: replica 3 의 볼륨 확장시 3의 배수인 6, 9, 12, ... 의 개수로만 추가 가능)

추가된 노드를 GlusterFS 클러스터에 포함 시키는 방법은 아래와 같습니다.

먼저 추가되는 노드 (gnode4, gnode5, gnode6) 에서 사전 작업을 해주세요.

- 추가디스크 mount (/data) 및 디렉토리 생성 (/data/gv0)

- hostname 및 hosts 설정 (기존 노드 포함)

- glusterfs 패키지 설치 및 가동

 

그리고 기존 노드에서 peer 를 추가합니다.

# gluster peer probe gnode4

# gluster peer probe gnode5

# gluster peer probe gnode6

 

볼륨 상태를 출력하여 추가된 노드를 확인합니다.

# gluster volume status
Status of volume: gv0
Gluster process                             TCP Port  RDMA Port  Online  Pid
------------------------------------------------------------------------------
Brick gnode1:/data/gv0                      49152     0          Y       11850
Brick gnode2:/data/gv0                      49152     0          Y       9917 
Brick gnode3:/data/gv0                      49152     0          Y       29859
Self-heal Daemon on localhost               N/A       N/A        Y       12991
Quota Daemon on localhost                   N/A       N/A        Y       13185
Self-heal Daemon on gnode2                  N/A       N/A        Y       10432
Quota Daemon on gnode2                      N/A       N/A        Y       10537
Self-heal Daemon on gnode5                  N/A       N/A        Y       9175 
Quota Daemon on gnode5                      N/A       N/A        Y       9186 
Self-heal Daemon on gnode6                  N/A       N/A        Y       9173 
Quota Daemon on gnode6                      N/A       N/A        Y       9184 
Self-heal Daemon on gnode4                  N/A       N/A        Y       6471 
Quota Daemon on gnode4                      N/A       N/A        Y       6483 
Self-heal Daemon on gnode3                  N/A       N/A        Y       30817
Quota Daemon on gnode3                      N/A       N/A        Y       30979
 
Task Status of Volume gv0
------------------------------------------------------------------------------
There are no active volume tasks

 

위에서 노드가 추가되었지만 아직 Brick 사용 상태는 아닌것으로 확인됩니다.

추가한 노드에도 데이터가 쓰여질 수 있도록 볼륨을 확장해야 합니다.

이를 위해 gluster volume add-brick 명령을 사용합니다.

볼륨명과 replica 구성은 그대로 하고, 추가할 노드만 적어주면 됩니다.

# gluster volume add-brick gv0 replica 3 gnode4:/data/gv0 gnode5:/data/gv0 gnode6:/data/gv0
volume add-brick: success

 

볼륨 상태를 확인합니다.

# gluster volume info
 
Volume Name: gv0
Type: Distributed-Replicate
Volume ID: 24463284-fb20-4d4b-9d13-0b891c2f892f
Status: Started
Snapshot Count: 0
Number of Bricks: 2 x 3 = 6
Transport-type: tcp
Bricks:
Brick1: gnode1:/data/gv0
Brick2: gnode2:/data/gv0
Brick3: gnode3:/data/gv0
Brick4: gnode4:/data/gv0
Brick5: gnode5:/data/gv0
Brick6: gnode6:/data/gv0
Options Reconfigured:
features.quota-deem-statfs: on
features.inode-quota: on
features.quota: on
cluster.granular-entry-heal: on
storage.fips-mode-rchecksum: on
transport.address-family: inet
nfs.disable: on
performance.client-io-threads: off

 

'replica 3 구성이 2세트로, 총 6개의 brick 이 구성되어 있다' 라는 뜻인데 아래와 같이 Brick 상태를 보면 추가된 brick 3개는 아직 활성화되지 않은 것으로 출력됩니다.

# gluster volume status |grep Brick
Brick gnode1:/data/gv0                      49152     0          Y       30890
Brick gnode2:/data/gv0                      49152     0          Y       23376
Brick gnode3:/data/gv0                      49152     0          Y       16274
Brick gnode4:/data/gv0                      N/A       N/A        N       N/A  
Brick gnode5:/data/gv0                      N/A       N/A        N       N/A  
Brick gnode6:/data/gv0                      N/A       N/A        N       N/A 

 

볼륨을 확장 (add-brick) 하거나 축소 (remove-brick) 할 때는 서버 간에 데이터 균형을 재조정해야 하는데, 이때 필요한 패키지가 glusterfs-geo-replication 입니다. 데이터 균형을 맞추기 전에 패키지 설치를 해야합니다.

# yum -y install glusterfs-geo-replication

 

rebalance 명령으로 데이터 균형 작업을 진행합니다.

# gluster volume rebalance gv0 start
volume rebalance: gv0: success: Rebalance on gv0 has been started successfully. Use rebalance status command to check status of the rebalance process.
ID: df6c2123-04d7-4b45-9311-e05430db6cac


rebalance 상태는 다음 명령으로 확인할 수 있습니다.

status 항목에 모든 작업이 completed 된것과 volume rebalance 작업이 성공되었다는 메세지를 확인할 수 있습니다.
# gluster volume rebalance gv0 status
                                    Node Rebalanced-files          size       scanned      failures       skipped               status  run time in h:m:s
                               ---------      -----------   -----------   -----------   -----------   -----------         ------------     --------------
                                  gnode2                0        0Bytes             2             0             0            completed        0:00:00
                                  gnode3                0        0Bytes             2             0             0            completed        0:00:00
                                  gnode4                0        0Bytes             0             0             0            completed        0:00:00
                                  gnode5                0        0Bytes             1             0             0            completed        0:00:00
                                  gnode6                0        0Bytes             1             0             0            completed        0:00:00
                               localhost                0        0Bytes             2             0             0            completed        0:00:00
volume rebalance: gv0: success

 

Client 에서는 마운트 되어 있던 GlusterFS 파티션 가용 공간이 자동으로 두 배 늘어난 것이 확인됩니다.

(용량 확장 전)

# df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        889M     0  889M   0% /dev
tmpfs           907M   84K  907M   1% /dev/shm
tmpfs           907M   97M  810M  11% /run
tmpfs           907M     0  907M   0% /sys/fs/cgroup
/dev/vda1        25G   17G  9.0G  65% /
tmpfs           182M     0  182M   0% /run/user/0
gnode1:/gv0      10G  135M  9.9G   2% /backup

 

(용량 확장 후)

# df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        889M     0  889M   0% /dev
tmpfs           907M   84K  907M   1% /dev/shm
tmpfs           907M   97M  810M  11% /run
tmpfs           907M     0  907M   0% /sys/fs/cgroup
/dev/vda1        25G   17G  9.0G  65% /
tmpfs           182M     0  182M   0% /run/user/0
gnode1:/gv0      20G  270M   20G   2% /backup

 

* 데이터 저장 형태

데이터가 어느 노드에 어떻게 저장되는지 확인하고 싶어서 적당한 크기의 파일을 하나씩 입력해 보았고 아래 내용으로 확인되었습니다.

- 파일을 저장하면 처음 replica 3 으로 구성된 gnode1, gnode2, gnode3 노드에 데이터 저장

- 추가 파일을 저장하면 나중 replica 3 으로 구성된 gnode4, gnode5, gnode6 노드에 데이터 저장

- 디렉토리는 모든 노드에서 생성

- Client 에서는 모든 노드의 데이터가 합쳐져 보임

즉, gnode1 (또는 gnode2 또는 gnode3) 의 데이터와 gnode4 (또는 gnode5 또는 gnode6) 의 데이터를 합치면 온전한 사용자 데이터가 된다는 것을 확인하였습니다.

 

3) Replica 구성 및 볼륨 제거

볼륨을 제거하면 구성 방식 (replica, stripe 등) 정보가 같이 삭제 됩니다.

우선 마운트 되어있는 Client 에서 모두 unmount 하여 스토리지를 분리합니다.

# umount /backup

 

운영중인 볼륨을 중지합니다.

# gluster volume stop gv0
Stopping volume will make its data inaccessible. Do you want to continue? (y/n) y
volume stop: gv0: success

 

볼륨을 삭제 합니다.

gluster volume delete gv0
Deleting volume will erase all information about the volume. Do you want to continue? (y/n) y
volume delete: gv0: success

 

아직 테스트하던 peer 는 연결되어진 상태입니다. 볼륨을 재구성 할 예정이므로 peer 연결 해제 및 데이터 삭제 방법만 알아두고 넘어가기로 합니다.

* 노드 분리 방법

# gluster peer detach <노드 이름>

* 데이터 삭제 (각 노드에서 실행)

# setfattr -x trusted.glusterfs.volume-id /data/gv0
# setfattr -x trusted.gfid /data/gv0
# rm -rf /data/gv0/.glusterfs*

 

 

8. 분산 (Disperse) 볼륨 구성 - with Parity peer

 

disperse 볼륨은 데이터와 패리티를 사용하여 데이터를 분산 저장하고, 손상된 브릭의 데이터를 복구할 수 있는 내구성을 제공합니다.

RAID 시스템의 5 구성과 매우 유사한 기능을 제공하고 있어서 파일을 쓸 경우 모든 Brick 에 동시 분산 저장이 되기 때문에 파일 I/O 속도가 빠르며 peer 한 대가 다운되어도 나머지 peer 에서 데이터 조합이 가능하기 때문에 무정지 서비스가 가능합니다. 하지만 peer 두 대 이상이 다운될 경우 Client 에서는 모든 데이터를 읽지 못하게 됩니다.

그럼 disperse 형식으로 볼륨을 생성해 보겠습니다.

먼저 gnode1 노드에서 peer 를 추가 합니다.

# gluster peer probe gnode2

# gluster peer probe gnode3

 

볼륨을 생성합니다.

# gluster volume create gv0 disperse 3 gnode1:/data/gv0 gnode2:/data/gv0 gnode3:/data/gv0
volume create: gv0: success: please start the volume to access data

disperse 3 옵션은 3개의 노드 (peer) 로 분산 저장 구성한다는 의미입니다. 결국 2개의 데이터 peer 와 1개의 패리티 peer 로 자동 구성됩니다.

 

생성한 볼륨을 시작합니다.

# gluster volume start gv0
volume start: gv0: success

 

볼륨에 서버 응답 대기시간을 0초로 적용합니다.

# gluster volume set gv0 network.ping-timeout 0

volume set: success

 

볼륨 정보를 확인합니다.

# gluster volume info
 
Volume Name: gv0
Type: Disperse
Volume ID: fb35eca2-9c54-4768-9ea9-eb27c0fd223d
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x (2 + 1) = 3
Transport-type: tcp
Bricks:
Brick1: gnode1:/data/gv0
Brick2: gnode2:/data/gv0
Brick3: gnode3:/data/gv0
Options Reconfigured:

network.ping-timeout: 0
storage.fips-mode-rchecksum: on
transport.address-family: inet
nfs.disable: on

 

여기에서 'Number of Bricks: 1 x (2 + 1) = 3' 를 볼 수 있는데, 위에서 설명한대로 (2 + 1) 은 2개의 데이터 Brick 과 1개의 Parity Brick 으로 구성되어 있음을 나타냅니다. 앞에 1 x 는 '이런 세트가 하나있다' 라고 이해하시면 됩니다.

Parity Brick 은 데이터 안정성을 위해 자동 생성되는 Brick 으로, 구성하는 서버 수량에 따라 아래와 같이 자동 할당 됩니다. 그리고 각각의 Brick 이 10GB 의 용량을 가지고 있을때 사용가능한 최종 데이터 저장 용량은 아래와 같습니다.

- 노드가 2개 일때 : 구성 불가. 최소한 3대가 필요합니다.

- 노드가 3개 일때 : 1 x (2 + 1) = 3  # 총 20GB

- 노드가 4개 일때 : 1 x (3 + 1) = 4  # 총 30GB

- 노드가 5개 일때 : 1 x (4 + 1) = 5  # 총 40GB

특이사항으로, 4대로 구성할때만 아래와 같은 메세지가 출력됩니다.

There isn't an optimal redundancy value for this configuration. Do you want to create the volume with redundancy 1 ? (y/n) y

 

* 데이터 저장 형태

데이터가 어느 노드에 어떻게 저장되는지 확인하고 싶어서 적당한 크기의 파일을 하나씩 입력해 보았고 아래 내용으로 확인되었습니다.

- 데이터 노드 (peer) 에 나뉘어져 저장

   > 데이터 노드가 2대 일때 : 10MB 파일 저장시 gnode1 에 5M, gnode2 에 5M 저장

   > 데이터 노드가 3대 일때 : 10MB 파일 저장시 gnode1 에 3.4M, gnode2 에 3.4M, gnode3 에 3.4M 저장

- 1대의 데이터 peer 에 저장되는 용량만큼 Parity Peer 에 저장

- 디렉토리는 모든 노드에서 생성

- 데이터 peer 에 생성되는 용량은 512 byte 단위로 생성됌

   > 이용자가 10 byte 텍스트 파일을 생성하더라도 데이터 peer 마다 512 byte 크기의 파일이 생성

   > 데이터 peer 가 2대 일때, 이용자가 1000 byte 파일을 생성한다면 각 peer 마다 512 byte 크기의 파일이, 이용자가 1200 byte 파일을 생성하면 각 peer 마다 1024 byte 크기의 파일이 생성 됌.

- peer 1대 장애 : Client 에서 데이터 및 서비스 유지 가능

- peer 2대 장애 : Client 에서 '입력/출력 오류' 상태로 빠짐. 추후 서버가 부팅되어 peer 파티션이 연결되고 glusterd 데몬이 구동되면 자동 연결 됌

 

참고로 disperse 볼륨에서는 패리티 파편을 명시적으로 지정하지 않습니다. GlusterFS 에서는 disperse 볼륨에 대한 패리티 파편의 위치를 추적하지 않습니다. 대신, disperse 볼륨은 데이터와 패리티를 조합하여 고유한 분산 방식으로 데이터를 보관합니다. 따라서, disperse 볼륨에서는 특정 peer 가 패리티 peer 인지를 명확하게 알 수 없습니다. 데이터와 패리티 파편은 모든 peer 에 균등하게 분산되므로 각 peer 는 동시에 데이터와 패리티를 저장합니다.

 

 

9. 판사 (Arbiter) 볼륨 구성

 

Arbiter 는 GlusterFS 의 Replica 구성에서 사용되는 옵션 중 하나입니다. Replica 구성은 데이터를 여러 Brick 에 복제하여 내구성과 가용성을 제공하는 방식입니다. 일반적으로 Replica 구성은 세 개의 복제 Brick 을 사용하지만, Arbiter 를 사용하면 세 번째 복제 Brick 대신에 판사 (Arbiter) Brick 을 사용합니다.
Arbiter 의 역할은 데이터의 복제를 수행하는 것이 아니라 복제 집합의 일부로서 데이터의 일관성을 유지하는 역할을 합니다. 각 복제 Brick 은 데이터를 가지고 있지만, 판사 Brick 은 실제 데이터를 저장하지 않고, 오로지 복제 그룹 내의 데이터 일관성을 확인하는 역할을 수행합니다. 따라서 Arbiter 를 사용하면 세 번째 Brick 으로 저장할 데이터 용량을 절약할 수 있습니다.
Arbiter 를 사용하는 Replica 구성은 데이터의 내구성과 가용성을 유지하면서 용량 효율성을 개선할 수 있습니다. 예를 들어, 10GB 의 데이터를 저장해야 할 때, 일반적인 Replica 구성은 3개의 10GB Brick 을 필요로 합니다. 그러나 Arbiter 를 사용하는 Replica 구성에서는 2개의 10GB Brick 과 1개의 Arbiter Brick 만으로도 같은 수준의 내구성을 제공할 수 있습니다. (Replica 2 를 구성하는 2개의 Brick 에 데이터 차이가 있어도 Arbiter 때문에 어떤게 최신 peer 인지 구분 가능)

 

gnode1 노드에서 peer 를 추가 합니다.

# gluster peer probe gnode2

# gluster peer probe gnode3

 

Arbiter 볼륨을 생성합니다.

# gluster volume create gv0 replica 2 arbiter 1 gnode1:/data/gv0 gnode2:/data/gv0 gnode3:/data/gv0
volume create: gv0: success: please start the volume to access data

 

볼륨을 시작합니다.

# gluster volume start gv0
volume start: gv0: success

 

볼륨에 서버 응답 대기시간을 0초로 적용합니다.

# gluster volume set gv0 network.ping-timeout 0

volume set: success

 

볼륨 정보를 확인합니다.

# gluster volume info
 
Volume Name: gv0
Type: Replicate
Volume ID: 2b88b6dd-c50d-4752-96fd-7acb98ce0d53
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x (2 + 1) = 3
Transport-type: tcp
Bricks:
Brick1: gnode1:/data/gv0
Brick2: gnode2:/data/gv0
Brick3: gnode3:/data/gv0 (arbiter)
Options Reconfigured:

network.ping-timeout: 0
cluster.granular-entry-heal: on
storage.fips-mode-rchecksum: on
transport.address-family: inet
nfs.disable: on
performance.client-io-threads: off

 

2대의 Replica 서버와 1대의 Arbiter 서버가 구성 되었습니다.

각 peer 가 10GB 일때, Client 에서 사용 가능한 최대 용량은 10G 입니다.

 

* 데이터 저장 형태

데이터가 어느 노드에 어떻게 저장되는지 확인하고 싶어서 적당한 크기의 파일을 하나씩 입력해 보았고 아래 내용으로 확인되었습니다.

- 10MB 파일 저장시 gnode1, gnode2 에 각각 10MB 파일 생성되고 gnode3 에는 0 Byte 의 파일 생성

- 디렉토리는 모든 노드에서 생성

- peer 1대 장애 : Client 에서 데이터 및 서비스 유지 가능

- peer 2대 장애 : Client 에서 '전송 종료지점이 연결되어 있지 않습니다' 상태로 빠짐. 추후 다운되었던 Replica 서버 또는 Arbiter 서버가 1대라도 부팅되어 peer 파티션이 연결되고 glusterd 데몬이 구동되면 자동 연결 됌

 

 

10. 통합 (Distributed) 볼륨 구성

 

Distributed 는 GlusterFS 의 기본 볼륨 구성값으로써 모든 peer 의 용량을 합하여 제공되는 방식입니다. disperse 볼륨과 같이 다량의 peer 에 동시에 데이터를 읽고 쓸 수 있는 구성이 아닌, 단순히 용량만 합하여 제공하기 때문에 peer 에 순차적으로 데이터를 저장하는 특징을 보입니다. 모든 peer 에 동시에 데이터를 읽고 쓰지 않으므로 속도가 disperse 보다 빠르지 않으며 parity peer 도 없기 때문에 하나의 peer 가 다운될 경우 데이터를 읽거나 쓰지 못하는 상황이 발생되며, peer 의 서버 대수가 많이 늘어날 수록 장애가 발생할 확률도 높아지게 됩니다.

distributed 볼륨 구성을 위해 gnode1 노드에서 peer 를 추가 합니다.

# gluster peer probe gnode2

 

중간에 아무런 옵션을 주지 않으면 기본 Distributed 상태로 볼륨이 생성됩니다.

# gluster volume create gv0 gnode1:/data/gv0 gnode2:/data/gv0
volume create: gv0: success: please start the volume to access data

 

볼륨을 시작합니다.

# gluster volume start gv0
volume start: gv0: success

 

볼륨에 서버 응답 대기시간을 0초로 적용합니다.

# gluster volume set gv0 network.ping-timeout 0

volume set: success

 

볼륨 정보를 확인합니다.

# gluster volume info
 
Volume Name: gv0
Type: Distribute
Volume ID: 77a483c0-479e-4237-91af-aa76058a3f2d
Status: Started
Snapshot Count: 0
Number of Bricks: 2
Transport-type: tcp
Bricks:
Brick1: gnode1:/data/gv0
Brick2: gnode2:/data/gv0
Options Reconfigured:

network.ping-timeout: 0
storage.fips-mode-rchecksum: on
transport.address-family: inet
nfs.disable: on

 

2대의 Brick 이 Distribute 로 구성 되었습니다.

각 peer 가 10GB 일때, Client 에서 사용 가능한 최대 용량은 20G 입니다.

 

* 데이터 저장 형태

데이터가 어느 노드에 어떻게 저장되는지 확인하고 싶어서 적당한 크기의 파일을 하나씩 입력해 보았고 아래 내용으로 확인되었습니다.

- gnode1 로 마운트하고 파일 저장시 gnode1 노드에 생성되고 계속 저장시 gnode1 노드 용량 (10GB) 까지만 저장 가능

- gnode2 로 마운트하고 파일 저장시 gnode2 노드에 생성되고 계속 저장시 gnode2 노드 용량 (10GB) 까지만 저장 가능

- Client 에서는 20GB 용량으로 보이고 gnode1, gnode2 에 저장된 데이터가 모두 보임

- 디렉토리는 모든 노드에서 생성

- peer 1대 장애 : 장애난 peer 의 데이터는 보이지 않고 남아있는 peer 내의 데이터만 보임. 추후 서버가 부팅되어 peer 파티션이 연결되고 glusterd 데몬이 구동되면 모든 파일들이 잘 보이게 됌

 

 

11. NFS 서비스 제공하기 (with NFS-Ganesha) --- 작성중

 

GlusterFS 를 일반적인 fuse 형식이 아닌 NFS 형식으로 마운트 할 수 있게 기능을 제공합니다.

볼륨 정보를 보면 아래와 같은 nfs 기본 옵션이 출력됩니다.

# gluster volume info
 
Volume Name: gv0
Type: Replicate
Volume ID: 563a8023-dc1c-4b2d-a86c-af8dcf21c5da
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 3 = 3
Transport-type: tcp
Bricks:
Brick1: gnode1:/data/gv0
Brick2: gnode2:/data/gv0
Brick3: gnode3:/data/gv0
Options Reconfigured:
cluster.granular-entry-heal: on
storage.fips-mode-rchecksum: on
transport.address-family: inet
nfs.disable: on
performance.client-io-threads: off

 

여기에서 NFS 를 사용하지 않는 옵션이 켜져 (on) 있습니다. 이것을 off 하고 몇가지 설정을 더 하면, GlusterFS 에서 제공하는 NFS 서버를 사용할 수 있습니다. 하지만 GlusterFS 에서 제공하는 NFS 서버 방식은 NFSv3 이고, 요새는 NFSv4 를 지원하는 NFS-Ganesha 가 별도 배포되고 있습니다. NFS-Ganesha 는 GlusterFS 와의 통합을 용이하게 하기 위해 개발된 것으로 기존의 GlusterFS NFS 서버 대신 NFS-Ganesha 를 사용하면 GlusterFS 와 NFS 간의 상호 운용성이 향상되고 다양한 기능과 유연성을 제공할 수 있습니다.
- 다양한 NFS 버전 지원 : NFSv3, NFSv4, NFSv4.1 및 NFSv4.2 를 지원하므로 다양한 클라이언트와의 상호 운용성이 높아집니다.
- 고급 기능 : 파일 시스템 관리, 보안, 액세스 제어, 성능 튜닝 등의 고급 기능을 제공합니다.
- 확장성 : 다중 프로토콜 지원, 클러스터링, 로드 밸런싱 등의 기능을 통해 GlusterFS 클러스터의 확장성을 향상시킵니다.
- 유연한 구성 : 다양한 구성 옵션과 플러그인 아키텍처를 제공하여 사용자의 요구에 맞게 유연하게 구성할 수 있습니다.

 

이러한 이유로 NFS-Ganesha 를 이용해 GlusterFS 의 NFS 서비스를 구성해 보겠습니다.

 

1) 설치

(모든 노드에서)

# yum -y install centos-release-nfs-ganesha30
# sed -i -e "s/enabled=1/enabled=0/g" /etc/yum.repos.d/CentOS-NFS-Ganesha-30.repo
# yum --enablerepo=centos-nfs-ganesha30 -y install nfs-ganesha-gluster

 

기본 설정 파일은 별도로 백업해놓고 새로운 설정을 추가 합니다.

# mv /etc/ganesha/ganesha.conf /etc/ganesha/ganesha.conf.ori
# vi /etc/ganesha/ganesha.conf

NFS_CORE_PARAM {
    mount_path_pseudo = true; # 가상 경로 사용 여부
    Protocols = 4;                       # 제공할 NFS 프로토콜 버전
}
EXPORT_DEFAULTS {
    Squash = "No_root_squash"; # Client 가 root 면 root 권한으로 파일 액세스 가능하도록
    FSAL {
        name = GLUSTER;     # 이름
        hostname = "gnode1"; # 현재 노드의 호스트명 또는 IP 주소
        volume = "gv0";           # GlusterFS 볼륨명
    }
}
EXPORT {
    Export_Id = 1;             # Client 식별자 : uniq ID (No)
    Path = "/data/gv0";      # GlusterFS 볼륨 마운트 경로 (여기에서는 최상위 디렉토리 제한) 
    Pseudo = "/gv0";         # 가상 경로 (마운트할때 명시되는 이름)
    Access_Type = None; # 접근 형식 (None : 접근불가, RO : 읽기전용, RW : 읽고쓰기)
}
EXPORT {
    Export_Id = 2;
    Path = "/data/gv0/apple";
    Pseudo = "/apple";
    Access_Type = RW;
}
LOG {
    Default_Log_Level = WARN; # 기본 로그 레벨
}

 

데몬 부팅 설정과 함께 데몬을 시작합니다.

# systemctl enable --now nfs-ganesha

 

서비스 포트 열린것이 확인되었습니다.

# netstat -nltp |grep ganesha
tcp6       0      0 :::875                  :::*                    LISTEN      18997/ganesha.nfsd  
tcp6       0      0 :::2049                 :::*                    LISTEN      18997/ganesha.nfsd 

 

2) Client 에서 마운트하기

마운트 하려는 디렉토리를 생성합니다.

# mkdir /backup

 

볼륨 전체는 마운트가 안되고,

# mount -t nfs gnode1:/gv0 /backup

 

하위 디렉토리는 마운트 가능합니다.

# mount -t nfs gnode1:/gv0/apple /backup

 

 

반응형

댓글()

Rocky Linux 9 에서 iSCSI 서비스 구축하기

리눅스/OS 일반|2023. 6. 2. 14:10
반응형

iSCSI 는 서버 간에 SCSI 명령을 TCP/IP 네트워크를 통해 전송하기 위한 프로토콜입니다. 이를 통해 원격 스토리지 장치에 접근하여 데이터를 전송하고 저장할 수 있습니다. iSCSI는 LAN 또는 WAN 을 통해 스토리지 리소스를 공유하고, 데이터 센터에서 스토리지 자원을 효율적으로 활용할 수 있도록 도와줍니다. iscsi-initiator (client) 와 target (server or storage) 간의 설정을 통해 iSCSI 를 사용하여 스토리지를 관리하고 데이터를 전송할 수 있습니다.

본 매뉴얼은 Rocky Linux 9 환경 (IP : 192.168.10.2) 에서 테스트 후 작성되었습니다.

 

 

1. iSCSI 서버 설치

 

1) targetcli 패키지 설치

targetcli 패키지를 설치합니다.

# dnf -y install targetcli

 

서버 부팅시 데몬이 자동으로 실행될 수 있도록 하고, 현재 세션에서도 데몬을 가동 시킵니다.

# systemctl enable target
# systemctl start target

 

이미지 파일이 저장될 디렉토리를 생성합니다.

볼륨이 큰 파티션이나 추가 장치를 마운트 해서 연결해도 됩니다.

# mkdir /storage

 

2) iSCSI target 만들기

targetcli 에 진입하면 IQN, LUN 등의 생성 및 관리 작업을 할 수 있습니다.

# targetcli
Warning: Could not load preferences file /root/.targetcli/prefs.bin.
targetcli shell version 2.1.53
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.

/> 

 

targetcli 에 진입하면 위와 같이 Warning 메세지를 볼 수 있는데, 별도의 사용자 환경 설정 파일을 생성하지 않아서 로드하지 못했다는 경고 메세지 입니다. 이 메시지는 문제를 일으키지 않으며, targetcli 의 기능에 지장을 주지 않습니다.

다음과 같이 1G 짜리 저장소 파일 (taget) 을 생성합니다.

형식) backstores/fileio create <backstore_fileio_이름> <이미지파일_전체_경로> <용량> <기록 방식>

/> backstores/fileio create disk01 /storage/1GB_image.img 1G write_back=false

Created fileio disk01 with size 1073741824

 

[ 스토리지 개체 생성 방식 ]

위 예시에서 이미 fileio 타입으로 파일을 생성했지만, 스토리지 개체를 생성하는 방식에는 두가지가 있으며 차이점은 아래와 같습니다.
- backstores/fileio : 파일을 사용하여 스토리지를 제공합니다. 이 방법은 이미지 파일이나 기존 파일 시스템을 사용하여 스토리지를 만들 수 있습니다. 파일 시스템 이미지 파일을 사용하면 가상의 블록 디바이스가 생성되어 iSCSI 타겟에 연결될 수 있습니다.
- backstores/block : 블록 장치 (파티션) 를 사용하여 스토리지를 제공합니다. 실제 블록 장치 (예: 하드 디스크) 나 루프백 장치를 사용하여 스토리지를 만들 수 있습니다. 블록 백스토어를 사용하면 블록 디바이스가 직접 iSCSI 타겟에 연결될 수 있습니다.

 

[ 쓰기 방식 ]

- write_back=true : 데이터를 메모리에 캐시한 후 비동기적으로 디스크에 기록합니다. 이는 성능을 향상시킬 수 있는 방식이지만, 시스템이 갑작스럽게 종료되는 경우 데이터 손실의 위험성이 있습니다.
- write_back=false : 데이터를 직접 디스크에 기록하며, 동기적인 방식으로 수행됩니다. 데이터의 일관성과 안정성이 보장됩니다. 그러나 성능은 약간 저하될 수 있습니다.

 

3) IQN 설정

IQN 은 반드시 형식에 맞게 작성해주어야 합니다.

형식) iqn.<연도>-<월>.<도메인 이름 역순>:<고유 이름>

/> iscsi/ create iqn.2023-06.kr.sysdocu:target01

Created target iqn.2023-06.kr.sysdocu:target01.
Created TPG 1.
Global pref auto_add_default_portal=true
Created default portal listening on all IPs (0.0.0.0), port 3260.

 

4) LUN 만들기

LUN (Logical Unit Number) 은 iSCSI target 에 연결된 논리적인 디스크 단위입니다.

LUN 을 만들기 위해 다음과 같이 명령을 실행합니다.

/> iscsi/iqn.2023-06.kr.sysdocu:target01/tpg1/luns create /backstores/fileio/disk01

Created LUN 0.

 

위 명령어는 target01 이라는 IQN 을 가진 target 의 TPG (Target Portal Group) 1 에 LUN 을 생성하고, 해당 LUN 을 /backstores/fileio/disk01 에 연결한다는 의미입니다.

 

5) IQN 의 ACL 생성

IQN ACL 을 생성하여 iSCSI 대상에 대한 액세스를 허용할 IQN 식별자를 명시적으로 지정합니다.

/> iscsi/iqn.2023-06.kr.sysdocu:target01/tpg1/acls create iqn.2023-06.kr.sysdocu:initiator01
Created Node ACL for iqn.2023-06.kr.sysdocu:initiator01
Created mapped LUN 0.

 

6) 계정 생성

target 에 계정을 생성하여 접근을 강화 할 수 있습니다.

본 항목을 건너뛰어도 Client 에서 마운트 가능하지만, Openshift 등 필요로 하는 곳이 있습니다.

계정 생성을 위해 target 의 initiator 로 이동합니다.

/> cd iscsi/iqn.2023-06.kr.sysdocu:target01/tpg1/acls/iqn.2023-06.kr.sysdocu:initiator01/

 

계정과 패스워드를 설정합니다.

/iscsi/iqn.20...u:initiator01> set auth userid=sysdocu
Parameter userid is now 'sysdocu'.
/iscsi/iqn.20...u:initiator01> set auth password=12345678
Parameter password is now '12345678'.

 

설정된 정보를 확인합니다.

/iscsi/iqn.20...u:initiator01> info
chap_password: 12345678
chap_userid: sysdocu
wwns:
iqn.2023-06.kr.sysdocu:initiator01

 

7) 정보 확인 및 저장

다음 명령어를 사용하여 생성한 IQN 과 LUN 정보를 확인할 수 있습니다.

/> ls iscsi/iqn.2023-06.kr.sysdocu:target01/tpg1/luns
o- luns .................................................................................................................. [LUNs: 1]
  o- lun0 .............................................................. [fileio/disk01 (/storage/1GB_image.img) (default_tg_pt_gp)]

 

그리고 exit 명령을 이용해 현재 상태를 저장하고 targetcli 를 빠져나갈 수 있습니다.

/> exit
Global pref auto_save_on_exit=true
Configuration saved to /etc/target/saveconfig.json

 

 

2. Client 에서 마운트 하기

 

1) client 패키지 설치

# yum install iscsi-initiator-utils  // CentOS

# apt-get install open-iscsi         // Ubuntu

 

2) iSCSI 시작

아래 파일에 IQN ACL 이름을 작성합니다.

# vi /etc/iscsi/initiatorname.iscsi

InitiatorName=iqn.2023-06.kr.sysdocu:initiator01

 

iscsi 와 iscsid 데몬이 시스템 부팅시 자동 구동되게 설정하고 현재 세션에서도 구동 합니다.

# systemctl enable iscsi

# systemctl enable iscsid

# systemctl start iscsi

# systemctl start iscsid

 

추후에 /etc/iscsi/initiatorname.iscsi 파일이 변경된 경우 iscsid 데몬을 재시작 해주어야 합니다.

 

3) Target 검색 및 연결

연결할 iSCSI Target 을 검색합니다.

# iscsiadm -m discovery -t st -p 192.168.10.2
192.168.10.2:3260,1 iqn.2023-06.kr.sysdocu:target01

 

iSCSI 장치를 연결합니다.

# iscsiadm -m node -T iqn.2023-06.kr.sysdocu:target01 -p 192.168.10.2:3260 -l

 

연결된 장치를 확인합니다.

# fdisk -l

...

Disk /dev/sda: 1 GiB, 1073741824 bytes, 2097152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 8388608 bytes

 

4) 해제 방법

사용을 하지 않을때 해제하는 방법은 아래와 같습니다.

연결 명령 마지막 옵션 l 을 u 로만 바꾸면 됩니다.

# iscsiadm -m node -T iqn.2023-06.kr.sysdocu:target01 -p 192.168.10.2:3260 -u

 

반응형

댓글()