티스토리 뷰

IT/Container&k8s

컨테이너

Hayley Shim 2024. 8. 31. 16:45

안녕하세요. Kubernetes Advanced Networking Study(=KANS) 3기 모임에서 스터디한 내용을 정리했습니다.

해당 글에서는 컨테이너에 대해 알아보겠습니다. 

 

컨테이너

- 독립된 리눅스 환경(pivot-root, namespace, Overlay filesystem, cgroup)을 보장받는 프로세스

- 애플리케이션(프로세스) 동작에 필요한 파일들만 패키징된 이미지를 실행하여 동작

- 컨테이너 환경이 조성된곳 어디에서나(온프레미스/클라우드 환경)에서도 실행할 수 있음

 

사전) 실습 환경 구성

- 사전 준비 : aws 계정, ssh 키 페어

- 구성 : VPC 1개(퍼블릭 서브넷 2개), EC2 인스턴스 1대(ubuntu 22.04 LTS, t3.small)

 

*CloudFormation 스택 배포 

# YAML 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/kans/kans-1w.yaml

# CloudFormation 스택 배포
# aws cloudformation deploy --template-file kans-1w.yaml --stack-name mylab --parameter-overrides KeyName=<My SSH Keyname> SgIngressSshCidr=<My Home Public IP Address>/32 --region ap-northeast-2
예시) aws cloudformation deploy --template-file kans-1w.yaml --stack-name mylab --parameter-overrides KeyName=kp-hayley SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2

## Tip. 인스턴스 타입 변경 : MyInstanceType=t2.micro
예시) aws cloudformation deploy --template-file kans-1w.yaml --stack-name mylab --parameter-overrides MyInstanceType=t2.micro KeyName=hayley-kp SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2

# CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력
aws cloudformation describe-stacks --stack-name mylab --query 'Stacks[*].Outputs[0].OutputValue' --output text --region ap-northeast-2

# [모니터링] CloudFormation 스택 상태 : 생성 완료 확인
while true; do 
  date
  AWS_PAGER="" aws cloudformation list-stacks \
    --stack-status-filter CREATE_IN_PROGRESS CREATE_COMPLETE CREATE_FAILED DELETE_IN_PROGRESS DELETE_FAILED \
    --query "StackSummaries[*].{StackName:StackName, StackStatus:StackStatus}" \
    --output table
  sleep 1
done

# Ansible Server EC2 SSH 접속
ss

 

 

 

*Ubuntu EC2 SSH 접속 : 기본 정보 확인

# SSH 접속 : ubuntu 계정
ssh -i ~/.ssh/kp-hayley.pem ubuntu@$(aws cloudformation describe-stacks --stack-name mylab --query 'Stacks[*].Outputs[0].OutputValue' --output text --region ap-northeast-2)
------------------------
# 현재 디렉터리 확인
pwd

# 계정 정보 확인
whoami
id

# 버전 확인
lsb_release -a

 

 

# CPU, Mem, Disk 등 기본 정보 확인
hostnamectl
lscpu
htop
free -h
df -hT /
mount
findmnt -A
cat /etc/hosts

# iptables 정책 확인
sudo iptables -t filter -L
sudo iptables -t nat -L

# 네트워크 정보 확인 - 리눅스아재력테스트
ip -br -c addr show
ip a(=ip addr) 혹은 ifconfig
ip route 혹은 route -n

# 프로세스 확인 - 셸변수
ps auf
pstree -p
echo $$
kill -9 $$

1. 도커 소개

 

1.1 도커란?

도커 : 가상실행 환경을 제공해주는 오픈소스 플랫폼. 도커에서는 이 가상실행 환경을 '컨테이너(Container)'라고 부름

- 컨테이너화된 프로세스(Containerized Process)

 

 

1.2 컨테이너와 가상머신

https://www.docker.com/resources/what-container

- 컨테이너는 운영체제를 제외한 나머지 애플리케이션 실행에 필요한 모든 파일을 패키징한다는 점에서 OS레벨 가상화를 지원. 게스트OS 와 하이버파이저가 없기 때문에 이로 인한 오버헤드를 줄임으로써 훨씬 더 가볍게 프로세스를 실행할 수 있고 컨테이너에 대한 복제와 배포가 더 용이

- 가상 머신은 기존의 서버에 하이퍼바이저를 설치하고, 그 위에 가상 OS와 패키징한 VM을 만들어 실행하는 방식인 하드웨어 레벨의 가상화를 지원. 개별 VM은 독립된 OS를 사용하여 도커에 비해 고립성(보안)은 더 좋지만, 오버헤드가 크고 무겁고 느리다는 단점을 가짐

 

1.3 도커 아키텍처

https://docs.docker.com/get-started/overview/#docker-architecture

 

2. 도커 기본 사용

2.1 기초 Linux Process 이해 : /proc

영상 출처 : https://youtu.be/xewZYX1e5R8?si=x8lF0HOdR5-CUmfS&t=891

 

- 프로세스실행 중인 프로그램의 인스턴스를 의미. OS에서 프로세스를 관리하며, 각 프로세스는 고유한 ID(PID)를 가짐.

- 프로세스는 CPU와 메모리를 사용하는 기본 단위로, OS 커널(Cgroup)에서 각 프로세스의 자원을 관리함.

 

# 프로세스 정보 확인
ps

# /sbin/init 1번 프로세스 확인
# 프로세스별 CPU 차지율, Memory 점유율, 실제 메모리 사용량 등 확인 
ps aux
ps -ef

 

# 프로세스 트리 확인
pstree --help
pstree
pstree -a
pstree -p
pstree -apn
pstree -apnT
pstree -apnTZ
pstree -apnTZ | grep -v unconfined

 

# 실시간 프로세스 정보 출력
top -d 1
htop

# 특정 프로세스 정보 찾기
pgrep -h

# [터미널1]
sleep 10000

# [터미널2]
pgrep sleep
pgrep sleep -u root
pgrep sleep -u ubuntu

 

- 리눅스의 /proc 디렉터리는 커널이 동적으로 생성하는 정보를 실시간 제공 : 시스템 상태, 프로세스(/proc/[PID]), HW 정보

#
mount -t proc
findmnt /proc
TARGET SOURCE FSTYPE OPTIONS
/proc  proc   proc   rw,nosuid,nodev,noexec,relatime

#
ls /proc
tree /proc -L 1
tree /proc -L 1 | more

 

 

# 커널이 동적으로 생성하는 정보
# CPU에 대한 정보가 포함되어 있습니다. 
# CPU 모델, 코어 수, 클럭 속도 등의 정보를 확인할 수 있습니다.
cat /proc/cpuinfo 

# 메모리 사용 현황을 보여줍니다. 
# 전체 메모리, 사용 중인 메모리, 가용 메모리, 캐시 메모리 등 다양한 메모리 관련 정보를 제공합니다.
cat /proc/meminfo

# 시스템이 부팅된 후 경과된 시간을 초 단위로 보여줍니다. 
# 첫 번째 숫자는 총 가동 시간, 두 번째 숫자는 시스템의 유휴 시간입니다.
cat /proc/uptime

# 시스템의 현재 부하 상태를 나타냅니다. 
# 첫 번째 세 개의 숫자는 1, 5, 15분간의 시스템 부하 평균을 의미하며, 네 번째 숫자는 현재 실행 중인 프로세스와 총 프로세스 수, 마지막 숫자는 마지막으로 실행된 프로세스의 PID를 나타냅니다.
cat /proc/loadavg

# 커널 버전, GCC 버전 및 컴파일된 날짜와 같은 커널의 빌드 정보를 포함합니다.
cat /proc/version

# 커널이 인식하고 있는 파일 시스템의 목록을 보여줍니다.
cat /proc/filesystems

# 시스템에서 인식된 파티션 정보를 제공합니다. 
# 디스크 장치와 해당 파티션 크기 등을 확인할 수 있습니다.
cat /proc/partitions

 

 

# 실시간(갱신) 정보
cat /proc/uptime
cat /proc/uptime
cat /proc/uptime

# 프로세스별 정보
ls /proc > 1.txt

# [터미널1]
sleep 10000

# [터미널2]
## 프로세스별 정보
ls /proc > 2.txt
ls /proc
diff 1.txt 2.txt
pstree -p
ps -C sleep
pgrep sleep

 

 

## sleep 프로세스 디렉터리 확인
tree /proc/$(pgrep sleep) -L 1
tree /proc/$(pgrep sleep) -L 2 | more

# 해당 프로세스를 실행할 때 사용된 명령어와 인자를 포함합니다.
cat /proc/$(pgrep sleep)/cmdline

# 프로세스의 현재 작업 디렉터리에 대한 심볼릭 링크입니다. 
# ls -l로 확인하면 해당 프로세스가 현재 작업 중인 디렉터리를 알 수 있습니다.
ls -l /proc/$(pgrep sleep)/cwd

# 프로세스가 실행 중인 실행 파일에 대한 심볼릭 링크입니다.
ls -l /proc/$(pgrep sleep)/exe
cat /proc/$(pgrep sleep)/environ ; echo

# 프로세스의 메모리 맵을 나타냅니다. 
# 메모리 영역의 시작과 끝 주소, 접근 권한, 매핑된 파일 등을 확인할 수 있습니다.
cat /proc/$(pgrep sleep)/maps

# 프로세스의 상태 정보를 포함한 파일입니다. 
# 이 파일에는 프로세스의 상태, CPU 사용량, 메모리 사용량, 부모 프로세스 ID, 우선순위 등의 다양한 정보가 담겨 있습니다.
cat /proc/$(pgrep sleep)/stat

# 프로세스의 상태 정보를 사람이 읽기 쉽게 정리한 파일입니다. 
# PID, PPID(부모 PID), 메모리 사용량, CPU 사용률, 스레드 수 등을 확인할 수 있습니다.
cat /proc/$(pgrep sleep)/status

 

 

2.2 도커 설치 및 확인

도커 설치

# [터미널1] 관리자 전환
sudo su -
whoami
id

# 도커 설치
curl -fsSL https://get.docker.com | sh

 

# 도커 정보 확인 : Client 와 Server , Storage Driver(overlay2), Cgroup Version(2), Default Runtime(runc)
docker info
docker version

# 도커 서비스 상태 확인
systemctl status docker -l --no-pager

# 모든 서비스의 상태 표시 - 링크
systemctl list-units --type=service

# 도커 루트 디렉터리 확인 : Docker Root Dir(/var/lib/docker)
tree -L 3 /var/lib/docker

 

 

Manage Docker as a non-root user & Socket 소켓 - Link

- The Docker daemon binds to a Unix socket, not a TCP port. By default it's the root user that owns the Unix socket, and other users can only access it using sudo.

# [터미널2] 일반 유저 ubuntu 로 실습 진행
whoami


# 도커 서버 정보 획득 실패
docker info
...
Server:
ERROR: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.46/info": dial unix /var/run/docker.sock: connect: permission denied
errors pretty printing info

#
ls -l /run/docker.sock /var/run/docker.sock
file /var/run/docker.sock

 

 

# [터미널1] 관리자
sudo su -

#
sudo systemctl status docker -l --no-pager
docker info

# 소켓 정보 확인 : tcp, udp, sctp, Unix Domain
ss -h | grep sockets
ss -tl # 혹은 ss --tcp --listening
ss -xl # 혹은 ss --unix --listening
ss -xl | grep -i docker
u_str LISTEN 0      4096                               /run/docker.sock 69239            * 0          
u_str LISTEN 0      4096                   /var/run/docker/metrics.sock 69882            * 0          
u_str LISTEN 0      4096   /var/run/docker/libnetwork/914c2d2f1446.sock 69422            * 0

 

# 특정 소켓 파일을 사용하는 프로세스 확인
lsof /run/docker.sock
COMMAND  PID USER   FD   TYPE             DEVICE SIZE/OFF  NODE NAME
systemd    1 root   40u  unix 0xffff96bd96236a80      0t0 69239 /run/docker.sock type=STREAM
dockerd 5178 root    4u  unix 0xffff96bd96236a80      0t0 69239 /run/docker.sock type=STREAM

# unix domain socket 중 docker 필터링
lsof -U | grep -i docker

 

Unix Domain Socket by ChatGPT : 예) UDS 사용 - mysql 로컬 접속 시 , Istio proxy 와 Envoy 프로세스(XDS, SDS)간 로컬 통신 시

- Unix Domain은 동일한 시스템 내에서 실행되는 프로세스들 간의 통신을 의미하며, "Domain"은 로컬 시스템 내의 통신 영역을 나타냅니다.

 

Manage Docker as a non-root user

# [터미널2] 일반 유저 ubuntu 로 실습 진행
whoami

# Create the docker group : 도커 스크립트 생성 시 자동 생성되어 그룹 확인만 진행
sudo groupadd docker
getent group | tail -n 3

# Add your user to the docker group.
echo $USER
sudo usermod -aG docker $USER

# ssh logout
exit

 

# ssh 재접속 후 확인

#
docker info


# 컨테이너 실행
docker run hello-world

#
docker ps
docker ps -a
docker images

# 중지된 컨테이너 삭제
docker ps -aq
docker rm -f $(docker ps -aq)
docker ps -a

 

컨테이너가 host의 docker socker file 공유로 도커 실행 - Link1 , Link2

#
docker run --rm -it -v /run/docker.sock:/run/docker.sock -v /usr/bin/docker:/usr/bin/docker ubuntu:latest bash
--------------------
docker info
docker run -d --rm --name webserver nginx:alpine
docker ps
docker rm -f webserver
docker ps -a
exit
--------------------

 

- Jenkins 컨테이너 : 도커 빌드 과정에서 활용 - DockerHub , Github , Docs

# Jenkins 컨테이너 실행
docker run -d -p 8080:8080 -p 50000:50000 --name jenkins-server --restart=on-failure -v jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker jenkins/jenkins

# 확인
docker ps
docker volume ls
local     jenkins_home

# 초기 암호 확인
docker exec -it jenkins-server cat /var/jenkins_home/secrets/initialAdminPassword

# Jenkins 컨테이너 웹 접속 주소 확인 : 초기 암호 입력
echo "http://$(curl -s ipinfo.io/ip):8080"

# jdk 확인
docker exec -it jenkins-server java --version
# JAVA_HOME 확인
docker exec -it jenkins-server sh -c 'echo $JAVA_HOME'
# Git 확인
docker exec -it jenkins-server git -v

# 기본 사용자 확인
docker exec -it jenkins-server whoami

# Jenkins 컨테이너에서 도커 명령 실행
docker exec -it --user 0 jenkins-server whoami
docker exec -it --user 0 jenkins-server docker info
docker exec -it --user 0 jenkins-server docker run --rm hello-world
docker exec -it --user 0 jenkins-server docker ps

# Jenkins 컨테이너 삭제
docker rm -f jenkins-server
docker volume rm jenkins_home

 

Jenkins 컨테이너로 해당 호스트의 Docker 데몬을 사용하는 파이프라인 구성 및 해당 동작이 가능한 원리에 대해서 정리

 

도커 설치 후 기본 정보 확인

# [터미널1] 관리자 권한

# 프로세스 확인 - 셸변수
ps -ef
pstree -p

# 시스템에 (마운트 된) disk free 디스크 여유 공간 확인
df -hT

# 네트워크 정보 확인 >> docker0 네트워크 인터페이스가 추가됨, 현재는 DOWN 상태
ip -br -c addr
ip -c addr
ip -c link
ip -br -c link
ip -c route

 

# 이더넷 브리지 정보 확인
brctl show

# iptables 정책 확인
iptables -t filter -S
iptables -t nat -S

## filter 에 FORWARD 가 기존 ACCEPT 에서 DROP 로 변경됨
## filter 에 FORWARD 에 docker0 에서 docker0 혹은 외부로 전달 허용 정책이 추가됨
iptables -t filter -S
-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN

## nat POSTROUTING 에 172.17.0.0/16 에서 외부로 전달 시 매스커레이딩(SNAT) 정책이 추가됨
iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN

 

 

2.3 컨테이너 실행 및 확인

- Ubuntu 호스트 VM 에서 동작하는 컨테이너의 네트워크 정보 샘플 https://youtu.be/SJFO2w5Q2HI

 

1) nginx 컨테이너를 백그라운드로 실행

nginx (웹 서버/프록시 소프트웨어 - 링크 생코) 이미지로 컨테이너 실행 시 백그라운드로 동작 - Web Server Survey & Official Image

 

nginx - Official Image | Docker Hub

Quick reference Supported tags and respective Dockerfile links 1.27.1, mainline, 1, 1.27, latest, 1.27.1-bookworm, mainline-bookworm, 1-bookworm, 1.27-bookworm, bookworm⁠1.27.1-perl, mainline-perl, 1-perl, 1.27-perl, perl, 1.27.1-bookworm-perl, mainline-

hub.docker.com

# nginx 이미지를 컨테이너 백그라운드로 실행
# -d 는 Detached 모드로 컨테이너를 실행. 컨테이너를 백그라운드에서 동작하는 애플리케이션으로써 실행하도록 설정.
# Detached 모드인 컨테이너는 반드시 컨테이너에서 프로그램이 실행돼야 하며 프로그램이 실행되지 않으면 컨테이너는 종료됩니다.
docker run -d nginx
docker ps

# 실행중인 컨테이너의 ID만 확인
docker ps -q

# 컨테이너 상세 정보 확인
# docker inspect '<NAME> 혹은 <ID>'
docker inspect $(docker ps -q)

# 컨테이너(=Instance)의 IP 정보 확인(JSON) - 링크
# docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $INSTANCE_ID
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q)
ping 172.17.0.2

# 호스트 네트워크 인터페이스 정보 확인
ip -c a
brctl show

# curl 로 http 접속 테스트 - 링크 링크2
curl `docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q)` | grep -o '<title>.*</title>'
curl -s 172.17.0.2 | grep -o '<title>.*</title>'

 

2) 컨테이너 상세 정보 확인 - 링크

docker inspect <CONTAINER_ID>

# 네트워크, 볼륨 등 컨테이너에 대한 모든 정보를 출력
docker inspect $(docker ps -q)
docker inspect $(docker ps -q) | more

# 컨테이너(=Instance)의 IP 정보 확인(JSON) - 링크
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q)
172.17.0.4
172.17.0.3
172.17.0.2

 

3) 컨테이너 로깅

# 컨테이너에서 출력되는 로그 기록을 확인 
docker logs <CONTAINER_ID>

# 백그라운드로 실행된 컨테이너의 로그를 직접 확인할 수 있습니다
# 터미널1 : -f 는 follow output 옵션입니다(tail -f) ⇒ <CTRL> + <C> 로 로깅을 종료
docker logs -f $(docker ps -q)
172.17.0.1 - - [01/Jun/2021:09:00:07 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"
172.17.0.1 - - [01/Jun/2021:09:00:09 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"
...

# 터미널2
curl `docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q)`
curl 172.17.0.2

 

4) 컨테이너 명령 전달

# 실행된 컨테이너에 새로운 패키지를 설치하거나 수정해야 하는 경우가 있습니다. 이런 경우에 exec 명령을 이용하여 컨테이너에 명령을 전달할 수 있습니다.
docker exec <CONTAINER_ID> <CMD>

# nginx 컨테이너의 index.html 내용을 변경하는 실행(exec)를 실습해보자
# nginx 컨테이너의 index.html 파일의 위치는 /usr/share/nginx/html/index.html 입니다
docker exec $(docker ps -q) ls /usr/share/nginx/html
docker exec $(docker ps -q) cat /usr/share/nginx/html/index.html

5) 컨테이너 삭제

# 실행 및 종료된 컨테이너까지 전부삭제
docker rm -f $(docker ps -a -q)

 

[참고 링크]

[Youtube - 널널한 개발자] 도커/가상화_이해하기 , Process , Process_Thread_차이 , 소켓의본질 소켓의본질

[Sam.0] 도커 없이 컨테이너 만들기 Update버전* - Link

 

if(kakao)dev2022 이게돼요? 도커없이 컨테이너 만들기

검색서비스 개발자로서 컨테이너 아키텍처와 동작 원리를 직접 학습하고 동료들과 나누면서 사내 교육 과정으로 탄생하게 된 '컨테이너 인터널'을 if(kakao)2022를 통해 외부에 공개합니다. 클라우

netpple.github.io

 

[Youtube - 널널한 개발자] 도커/가상화_이해하기 , Process , Process_Thread_차이 , 소켓의본질

 

https://speakerdeck.com/kakao/ige-dwaeyo-dokeo-eobsi-keonteineo-mandeulgi?slide=94

'IT > Container&k8s' 카테고리의 다른 글

컨테이너 네트워크 및 보안  (8) 2024.09.01
컨테이너 격리  (0) 2024.09.01
[k8s] Service Mesh  (0) 2023.10.29
[k8s] cluster install - cri-o runtime error  (0) 2023.10.29
[k8s] Security  (0) 2023.10.29
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함