레이블이 lsns인 게시물을 표시합니다. 모든 게시물 표시
레이블이 lsns인 게시물을 표시합니다. 모든 게시물 표시

overlay network 사용하기

# 들어가기 전에
# overlay network 실제 네트워크가 위에서 동작하는 가상네트워크다.
# overlay network 로 물리적으로 떨어져 있는 네트워크들도 마치 같은 네트워크에 있는 LAN 처럼 취급할 수 있다.
# 종류로 Virtual eXtensible LAN (VXLan)가 있다.
# OSI7계층 중 L2(datalink), L3(network) 에 걸쳐 사용되고, L2 프레임을 캡슐화해 터널링한다.
# MTU(Maximum Transmission Unit)는 패킷이나 프레임단위로 전송할때 최대 크기로 일반적으로 1500byte 으로 설정되는데 VXLan 사용시 캡슐화에 50byte 가 필요하기 때문에 1450byte 로 설정한다.
# ICMP(Internet Control Message Protocol) 는 L3 동작하며 대상 IP 의 상태(이상없는지)를 확인하는 프로토콜이다.
# ARP(Address Resolution Protocol)은 L3 동작하며 IP 주소를 L2의 물리주소(MAC, Media Access Control)주소로 바인딩시키기 위한 프로토콜이다.
# FDB(Fowarding DataBase)는 L2 에서 포워딩을 위해 MAC 주소를 저장하고 있다.


#####


# 테스트 환경 : vagrant ubuntu-1804
HOST_NAME = "ubuntu1804"    # node1 192.168.104.2
HOST_NAME2 = "ubuntu1804-2" # node2 192.168.104.3

# node1,2 각각 접속시 
vagrant ssh ubuntu184
vagrant ssh ubuntu184-2

# vxlan 으로 노드간 통신하기
# node1, node2 는 다음과 같이 구성(연결)할 것이다.
[node1]
pinkns(eth0:12.12.12.2/24) <-> overns(veth1 <-> br0:arp참고 <-> vxlan1:fdb참고) <-> host(eth1:192.168.104.2) <-> 외부
[node2]
pinkns(eth0:12.12.12.3/24),skyns(eth0:12.12.12.4/24) <-> overns(veth1 <-> br0:arp참고 <-> vxlan1:fdb참고) <-> host(eth1:192.168.104.3) <-> 외부

# node1, node2 각각 overns, pinkns 이름의 network namespace(netns) 생성
ip netns add overns
ip netns add pinkns

# node1, node2 각각 network namespace 확인
ip netns

# node1, node2 각각 veth1(overns) <-> eth0(pinkns) 연결(link 생성)
ip link add dev veth1 mtu 1450 netns overns type veth peer name eth0 mtu 1450 netns pinkns

# 참고로 ip netns exec overns 대신 overns 에 조인해서 작업할 경우
# 작업후 호스트 network namespace 로 돌아오기 위해 exit 잊지 말자.
# nsenter --net=/var/run/netns/overns

# node1(overns), node2(overns) 에서 ip link 확인
ip netns exec overns ip link

# node1(pinkns) 에서 �eth0 에 mac,ip address 추가
ip netns exec pinkns ip link set dev eth0 address 02:42:c0:a8:00:02
ip netns exec pinkns ip addr add dev eth0 12.12.12.2/24

# node2(pinkns) 에서 eth0 에 mac,ip address 추가
ip netns exec pinkns ip link set dev eth0 address 02:42:c0:a8:00:03
ip netns exec pinkns ip addr add dev eth0 12.12.12.3/24

# node1(overns), node2(overns) 에서 bridge 생성
ip netns exec overns ip link add dev br0 type bridge
ip netns exec overns ip addr add dev br0 12.12.12.1/24

# node1(overns), node2(overns) 에서 ip, link 확인
ip netns exec overns ip a
ip netns exec overns ip link

# node1, node2 에서 vxlan(overns) 생성
# type vxlan : vxlan 타입 생성
# id 42 : vxlan 식별자 42
# proxy : vxlan 이 ARP 요청에 대신 응답하도록 설정
# learning : 커널이 패킷을 파악해 bridge FDB 를 자동으로 설정할 수 있도록 설정
# dstport 4789 : vxlan 터널링에 사용하는 UDP 포트로 4789 사용
ip link add dev vxlan1 netns overns type vxlan id 42 proxy learning dstport 4789

# node1(overns), node2(overns) 에서 veth1 <-> br0 연결
ip netns exec overns ip link set veth1 master br0

# node1(overns), node2(overns) 에서 vxlan1 <-> br0 연결
ip netns exec overns ip link set vxlan1 master br0

# node1, node2 각각 overns, pinkns 의 장치들 모두 power on
ip netns exec overns ip link set br0 up
ip netns exec overns ip link set vxlan1 up
ip netns exec overns ip link set veth1 up
ip netns exec pinkns ip link set eth0 up

# node1(overns) 에서
# 목적지 ip(12.12.12.3),mac(02:42:c0:a8:00:03)를 사용하는 vxlan1 정보를 ARP 테이블에 기록
ip netns exec overns ip neighbor add 12.12.12.3 lladdr 02:42:c0:a8:00:03 dev vxlan1

# node2(overns)에서
# 목적지 ip(12.12.12.2),mac(02:42:c0:a8:00:02)를 사용하는 vxlan1 정보를 ARP 테이블에 기록
ip netns exec overns ip neighbor add 12.12.12.2 lladdr 02:42:c0:a8:00:02 dev vxlan1

# node1(overns), node2(overns) 에서 neighbor 확인
ip netns exec overns ip neighbor show

# node1(overns) 에서
# bridge fdb 설정 추가
# 192.168.104.3 : 목적지 IP
# 42 : 목적지 vni(VXLAN Network Identifier) ID
# 4789 : 목적지 Port
# 다음과 같이 수동으로 설정하면 permanent 하게 유지된다.
ip netns exec overns bridge fdb add 02:42:c0:a8:00:03 dev vxlan1 self dst 192.168.104.3 vni 42 port 4789

# node1(overns) 에서 fdb 설정 확인하면 permanent 표시가 있다.
ip netns exec overns bridge fdb show | grep 02:42:c0:a8:00:03

# node1(overns) 에서 br0, vxlan 에서 패킷 확인시
ip netns exec overns tcpdump -l -i br0
ip netns exec overns tcpdump -l -i vxlan1

# 위에서 vxlan 디바이스 생성 시에 learning 옵션사용했기 때문에 fdb, ARP 정보는 커널에서 패킷 분석해서 설정해준다.
# 하지만 수동설정(permanent)와 달리 aging 으로 인해 일정 시간 지나면 설정이 제거된다.
# node2(overns)에서 다음과 같이 다시 수동으로 변경하면 permanent 하게 설정된다.
ip netns exec overns bridge fdb replace 02:42:c0:a8:00:02 dev vxlan1 self dst 192.168.104.2 vni 42 port 4789

# node2(overns)에서 다시 fdb 설정 확인하면 permanent 가 있다.
ip netns exec overns bridge fdb show | grep 02:42:c0:a8:00:02

# 참고로 overns 의 FORWARD 가 허용으로 되어 있는지 확인
ip netns exec overns iptables -t filter -L | grep -i policy
Chain INPUT (policy ACCEPT)
Chain FORWARD (policy ACCEPT)
Chain OUTPUT (policy ACCEPT)

# node1(pinkns조인 상태) -> node2(pinkns) ping 해보면 응답을 받는다.
ip netns exec pinkns ping 12.12.12.3

# node2(pinkns조인 상태) -> node1(pinkns) ping 해보면 응답을 받는다.
ip netns exec pinkns ping 12.12.12.2



#####


# node1 에 새로운 skyns network namespace 추가하고 통신하기

# node1 에서 skyns 네트워크네임스페이스 추가, mac,ip 등 추가하고 power on
ip netns add skyns
ip link add dev veth2 mtu 1450 netns overns type veth peer name eth0 mtu 1450 netns skyns
ip netns exec skyns ip link set dev eth0 address 02:42:c0:a8:00:04
ip netns exec skyns ip addr add dev eth0 12.12.12.4/24
ip netns exec overns ip link set veth2 master br0
ip netns exec overns ip link set veth2 up
ip netns exec skyns ip link set eth0 up

# node1(skyns) -> node1(pinkns) ping 테스트
ip netns exec skyns ping 12.12.12.2

# node1(pinkns) -> node1(skyns) ping 테스트
ip netns exec pinkns ping 12.12.12.4

# node2(overns) 에서 fdb 추가
ip netns exec overns ip neighbor add 12.12.12.4 lladdr 02:42:c0:a8:00:04 dev vxlan1

# node1(skyns) -> node2(pinkns) ping 테스트
ip netns exec skyns ping 12.12.12.3


#####


# node3(192.168.104.4) 추가하고 node1,2와 통신하기

# vagrantfile 노드 추가 후 
# HOST_NAME3 = "ubuntu1804-3" # node3 192.168.104.4
# ubuntu1804-3(node3) 만 추가로 띄우기
# vagrant up
# ubuntu1804-3(node3) 접속
vagrant ssh ubuntu184-3

# node3 overns,pinkns, skyns network namespace 추가
ip netns add overns
ip netns add pinkns
ip netns add skyns

# node3 veth1(overns) <-> eth0(pinkns) 연결(link 생성)
ip link add dev veth1 mtu 1450 netns overns type veth peer name eth0 mtu 1450 netns pinkns

# node3 veth1(overns) <-> eth0(skyns) 연결(link 생성)
ip link add dev veth2 mtu 1450 netns overns type veth peer name eth0 mtu 1450 netns skyns

# node3(pinkns) 에서 eth0 에 mac,ip address 추가
ip netns exec pinkns ip link set dev eth0 address 02:42:c0:a8:00:0a
ip netns exec pinkns ip addr add dev eth0 12.12.12.10/24

# node3(skyns) 에서 eth0 에 mac,ip address 추가
ip netns exec skyns ip link set dev eth0 address 02:42:c0:a8:00:0b
ip netns exec skyns ip addr add dev eth0 12.12.12.11/24

# node3(overns) 에서 bridge 생성
ip netns exec overns ip link add dev br0 type bridge
ip netns exec overns ip addr add dev br0 12.12.12.1/24

# node3(overns) 에서 vxlan 생성
ip link add dev vxlan1 netns overns type vxlan id 42 proxy learning dstport 4789

# node3(overns) 에서 veth1 <-> br0, veth2 <-> br0, vxlan1 <-> br0 연결
ip netns exec overns ip link set veth1 master br0
ip netns exec overns ip link set veth2 master br0
ip netns exec overns ip link set vxlan1 master br0

# node3 overns, pinkns, skyns 의 장치들 모두 power on
ip netns exec overns ip link set br0 up
ip netns exec overns ip link set vxlan1 up
ip netns exec overns ip link set veth1 up
ip netns exec overns ip link set veth2 up
ip netns exec pinkns ip link set eth0 up
ip netns exec skyns ip link set eth0 up

# node3(overns) 에 node1,node2 ip,mac 정보를 ARP 테이블에 기록
ip netns exec overns ip neighbor add 12.12.12.3 lladdr 02:42:c0:a8:00:03 dev vxlan1
ip netns exec overns ip neighbor add 12.12.12.2 lladdr 02:42:c0:a8:00:02 dev vxlan1

# node3(overns) 에 node1,nod2 ip,mac 정보를 fdb 로 기록
ip netns exec overns bridge fdb add 02:42:c0:a8:00:02 dev vxlan1 self dst 192.168.104.2 vni 42 port 4789
ip netns exec overns bridge fdb add 02:42:c0:a8:00:03 dev vxlan1 self dst 192.168.104.3 vni 42 port 4789

# node1(overns), node2(overns) 에 node3 ip,mac 정보를 ARP 테이블에 기록
ip netns exec overns ip neighbor add 12.12.12.10 lladdr 02:42:c0:a8:00:0a dev vxlan1
ip netns exec overns ip neighbor add 12.12.12.11 lladdr 02:42:c0:a8:00:0b dev vxlan1

# node1(overns), node2(overns) 에 node3 ip,mac 정보를 fdb 로 기록
ip netns exec overns bridge fdb add 02:42:c0:a8:00:0a dev vxlan1 self dst 192.168.104.4 vni 42 port 4789
ip netns exec overns bridge fdb add 02:42:c0:a8:00:0b dev vxlan1 self dst 192.168.104.4 vni 42 port 4789

# node1(pinkns) -> node3(pinkns), node3(skyns) ping 테스트
ip netns exec pinkns ping 12.12.12.10
ip netns exec pinkns ping 12.12.12.11

# node2(pinkns) -> node3(pinkns), node3(skyns) ping 테스트
ip netns exec pinkns ping 12.12.12.10
ip netns exec pinkns ping 12.12.12.11

# node3(pinkns) -> node1(skyns) ping 테스트
ip netns exec pinkns ping 12.12.12.2

# node3(pinkns) -> node2(skyns) ping 테스트
ip netns exec pinkns ping 12.12.12.3

# 모든 테스트가 끝나고 network namespace 삭제하려면
ip netns delete overns
ip netns delete pinkns
ip netns delete skyns

linux namespace

# 2002년 리눅스 커널에 포함된 namespace(mnt, pid, net, ipc, cgroup...타입) 로 isolation 구현
# 모든 프로세스들은 특정 네임스페이스에 속하고 unshare 로 새로운 네임스페이스에서 프로세스를 실행할 수 있다. 네임스페이스는 exit 로 빠져나올 수 있다.
# unshare 시 프로세스를 명시하지 않으면 ${SHELL}값(/bin/sh 또는 /bin/bash등)이 디폴트로 실행된다.

#####

# mnt namespace
# 부모(호스트)로 부터 격리된 mount타입(-m, --mount)의 네임스페이스로 /bin/bash 프로그램 실행
unshare --mount /bin/sh

# mount_ns 에 마운트하면 현재 네임스페이스에서만 마운트된것을 알 수 있다.
# tmpfs : 가상 메모리 파일시스템
# ushare 된 마운트 스페이스(격리됨)에서 생성한 마운트는 호스트에서 보이지 않는다.
mkdir /tmp/mount_ns
mount -n -t tmpfs tmpfs /tmp/mount_ns
mount | grep mount_ns

# 터미널을 하나 더 띄워 호스트 네임스페이스에서 보면 값이 다른것을 알 수 있다.
readlink /proc/$$/ns/mnt

# 호스트에서 tmpfs 마운트 정보가 안보이는것을 확인
mount | grep mount_ns

# 테스트 결과

#####

# pid namespace
# 새로운 pid(-p, --pid), -f(--fork) 네임스페이스으로 실행
# --mount-proc Just before running the program, mount the proc filesystem at mountpoint (default is /proc)
# --mount-prod 옵션을 사용하면 pid 네임스페이스가 /proc/{pid} 로 마운트되어 쉽게 pid 네임스페이스 접근할 수 있도록 해준다.(mount namspace 도 생긴다.)
unshare -fp --mount-proc /bin/sh

# 호스트 네임스페이스와 현재 pid 네임스페이스에 다른 pid 로 보인다.
# 현재 pid 네임스페이스에서 프로세스를 확인해보면 1번이다.
echo $$
ps -ef

# pid 네임스페이스에서의 pid namespace 정보를 보면
# 아래 호스트의 unshare mount namespace 와 다른것을 알 수 있다.
# unshare(mt ns id:4026532202) ---> pid-namespace /bin/sh (pid ns id:4026532203)
lsns -t pid -p 1

# 호스트에서 unshare 프로세스 pid 찾기
ps -ef | grep unshare

# ushare 프로세스의 namespace 정보
# ls -ahl /proc/{pid}/ns 로도 알 수 있다.
lsns -p {pid}

# mnt 네임스페이스ID 로 확인
lsns {namespace id}

# 테스트 결과 화면

#####

# cgroup namespace
# cgroup 는 controlgroup으로 프로세스의 리소스 제어하는 파일시스템이다.(sys/fs/cgroup)
# sleep 백그라운드 프로세스를 freezer(cgroup 작업 중지,재개를 위한 subsystem)의 sub2로 등록
mkdir -p /sys/fs/cgroup/freezer/sub2
sleep 100000 &
[1] 2932

# 테스트를 위해 sleep pid 환경변수로 설정 
export sleep_pid=2932

# sleep pid 를 sub2 cgroup 으로 등록
echo ${sleep_pid} > /sys/fs/cgroup/freezer/sub2/cgroup.procs

# 현재 프로세스도 freezer sub1 로 등록하자.
mkdir -p /sys/fs/cgroup/freezer/sub1

# 현재프로세스 확인, 테스트를 위해 현재 pid 환경변수로 설정 
echo $$
2178
export parent_pid=$(echo $$)

# 현재 프로세스 pid 를 sub1 cgroup 으로 등록
echo ${parent_pid} > /sys/fs/cgroup/freezer/sub1/cgroup.procs

# freezer (init process, PID 1), parent, sleep pid 확인
cat /proc/1/cgroup | grep freezer
cat /proc/${parent_pid}/cgroup | grep freezer
cat /proc/${sleep_pid}/cgroup | grep freezer

# freezer 파일 확인
tree -L 1 /sys/fs/cgroup/freezer/
/sys/fs/cgroup/freezer/
├── cgroup.clone_children
├── cgroup.procs
├── cgroup.sane_behavior
├── docker
├── notify_on_release
├── release_agent
├── sub1
├── sub2
└── tasks

# 새로운 cgroup(-C, --cgroup) 네임스페이스로 실행
unshare -Cm /bin/sh

# freezer (init process, PID 1), parent, sleep pid 확인해보면
# sub1 --> / 가 루트가 되고
# sub2 --> ../sub2 로 변경되었지만 호스트 cgroup 은 그대로 보인다.
cat /proc/1/cgroup | grep freezer
cat /proc/2178/cgroup | grep freezer
cat /proc/2932/cgroup | grep freezer

# 테스트 결과

#####

# stress 툴로 시스템 부하(cpu)를 테스트해보자.
# new_root 에 bash 준비하기
mkdir -p new_root/{bin,usr,lib,lib64} new_root/lib/x86_64-linux-gnu/ new_root/usr/lib/x86_64-linux-gnu
cp /bin/bash new_root/bin
cp /bin/mount new_root/bin
cp /lib/x86_64-linux-gnu/{libtinfo.so.5,libdl.so.2,libc.so.6} new_root/lib
cp /lib64/ld-linux-x86-64.so.2 new_root/lib64

# mount 명령등 준비하기
cp -rv /bin/{ls,cat,mount,umount,mkdir,rmdir,rm,cp,grep,ps} new_root/bin
cp -rv /usr/lib/x86_64-linux-gnu/* new_root/usr/lib/x86_64-linux-gnu
cp -rv /lib/x86_64-linux-gnu/* new_root/lib/x86_64-linux-gnu
cp -rv /lib64/* new_root/lib64

# stress, cgroup 툴 설치
apt-get install -y stress cgroup-tools

# chroot 후 필요한 파일들 복사
mkdir -p new_root/usr/bin/bin
cp /usr/bin/{top,stress,cgcreate,cgset,cgexec} new_root/usr/bin/

# top 실행시 필요한 파일들 복사
mkdir -p new_root/usr/share/terminfo
cp -r /usr/share/terminfo/ new_root/usr/share/terminfo

# cgcreate 시 root uid 파악에 필요
mkdir -p new_root/etc
cp /etc/group new_root/etc/group
cp /etc/passwd new_root/etc/passwd

# cgroup 관련 마운트 확인
mount | grep -E "cgroup*.cpu"

# chroot 후 mount 하기
chroot new_root
mkdir -p /sys/fs/cgroup
mkdir -p /sys/fs/cgroup/{cpuset,"cpu,cpuacct"}
mount -t cgroup -o cpuset cgroup /sys/fs/cgroup/cpuset
mount -t cgroup -o cpu,cpuacct cgroup /sys/fs/cgroup/cpu,cpuacct

# /proc 마운트
mkdir -p /proc
mount -t proc proc /proc

# mycgroup 생성 및 확인
cgcreate -a root -g cpu:mycgroup
ls -al /sys/fs/cgroup/cpu,cpuacct/ | grep mycgroup

# CPU 사용률(%) = (cpu.cfs_quota_us / cpu.cfs_period_us) * 100
# cpu.cfs_period_us 를 확인해 보면 100000(us, 100ms) 이다.
# cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us
# 따라서 cpu.cfs_quota_us=30000 을 주면 30% cpu 사용률로 제한한다.
cgset -r cpu.cfs_quota_us=30000 mycgroup

# mycgroup 에 strecc -c(--cpu) 1로 부하 테스트 백그라운드로 실행
cgexec -g cpu:mycgroup stress -c 1 &

# top 으로 stress 프로세스 30% 사용 확인
export TERM="xterm-256color"
top
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 3129 root      20   0    8248     96      0 R  30.0  0.0   0:03.50 stress

# 테스트 결과

#####

# net namespace
# 새로운 network(-n, --net) 네임스페이스으로 실행
unshare --net /bin/sh

# 호스트 네임스페이스와 정보가 다른것을 알 수 있다.
ip a

# 테스트 결과

# ip 로 net namespace 생성해보기
ip netns add mynet

# net namespace 확인
ip netns list
# 또는
ls /var/run/netns

# nsenter 로 net네임스페이스(--net)에 들어가기
# 별도 프로그램 명시하지 않으면 디폴트로 $SHELL -> /bin/bash 를 실행한다.
nsenter --net=/var/run/netns/mynet
ip a

# net 네임스페이스에서 현재 프로세스의 pid,user,ipc,mnt등의 네임스페이스 정보 확인
lsns -p $$

# 호스트에서 net 네임스페이스 id 확인
# readlink /proc/$$/ns/net 대신 lsns 명령어로도 네임스페이스 정보를 확일 수 있다.
# lsns -t 타입 -p pid
lsns -t net -p $$

# 테스트 결과

#####

# user namespace 생성
# 새로운 user(-U, --user) 네임스페이스으로 실행
unshare --user /bin/sh

# 새로운 user 네임스페이스에서의 사용자 정보 확인
whoami
id

# 네임스페이스 확인해보기
ls -al /proc/$$/ns
lsns -p $$

# 테스트 결과 화면

# container 와 호스트 root 가 같은것인지 확인해보기
# docker 로 busybox 컨테이너 띄우기
docker container run -it --name busybox --rm busybox

# ps 로 보면 root 로 실행됐고, uid=0 으로 되어 있다
ps -ef
id

# 현재 프로세스의 user 네임스페이스 확인
readlink /proc/$$/ns/user

# 호스트에서도 확인해보면 root 이름이고 uid=0 이다.
ps -ef | grep root | head -3
id

# 호스트에서 현재 프로세스의 user 네임스페이스 확인해보면 위 container user namespace id 와 같은것을 알 수 있다.
# 결국 container 의 root 도 호스트 user 네임스페이스를 공유하기 때문에 호스트 root 와 같은것이다.
readlink /proc/$$/ns/user

# 테스트 결과 화면

# 참고로 docker v1.10 이상 부터는 별도의 user namespace 를 지원하지만
기본적으로 docker 로 컨테이너를 실행하면 root 로 프로세스를 실행한다.(user namespace 를 별도로 만들지 않고 호스트를 user namespace 를 사용한다.)
# 이 때문에 container root 계정이 악용될 수 있음을 인지해야 한다.
# docker remap 설정으로 uid 를 다르게할 수 있다. 아래 별도 포스트로 정리

#####

# uts(unix time sharing system) namespace
# 새로운 uts(-u, --uts) 네임스페이스으로 실행
unshare --uts /bin/sh

# 호스트명 변경하고 확인
hostname ysoftman
hostname

# 터미널을 하나 더 띄워 호스트를 확인해 보면 영향을 주지 않는것을 알 수 있다.
# 테스트 화면

#####

# ipc(interprocess communication) namespace
# shared memory, queue, semaphore 등의 리소스에서 사용되며 같은 ipc 네임스페이스안 프로세스들은 ipc 통신할 수 있다.
# ipc (shared memory, pipe) 상태 정보 보기
# -m  Write information about active shared memory segments.
ipcs -m

# ipc shared memeory 리소스 1000byte 생성
# -m Create a shared memory segment of size bytes.
ipcmk -M 1000

# 1000 byte shared memory segemnt 가 생성된것을 확인할 수 있다.
ipcs -m

# 새로운 ipc(-i, --ipc) 네임스페이스 생성
unshare --ipc /bin/sh

# 새로운 ipc 네임스페이스에서는 호스트에서 만든 1000bytes 리소스가 보이지 않는다.
ipcs -m

# 호스트로 나오기
exit

# ipc 리소스 삭제
# -M Remove the shared memory segment created with shmkey after the last detach is performed.
ipcrm -M {shared memory segment key}

# 삭제된 리소스 확인 
ipcs -m

# 위 과정을 테스트한 결과