๋„์ปค์™€ ๋ชจ๋‘, ๋ชจ๋‘, ๋ชจ๋‘

ํ•ต์‹ฌ์š”์•ฝ: ์ปจํ…Œ์ด๋„ˆ์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋น„๊ตํ•˜๋Š” ๊ฐœ์š” ๊ฐ€์ด๋“œ์ž…๋‹ˆ๋‹ค. Docker ๋ฐ ๊ธฐํƒ€ ์œ ์‚ฌํ•œ ์‹œ์Šคํ…œ์˜ ๊ธฐ๋Šฅ์ด ๊ณ ๋ ค๋ฉ๋‹ˆ๋‹ค.

๋„์ปค์™€ ๋ชจ๋‘, ๋ชจ๋‘, ๋ชจ๋‘

๋ชจ๋“  ๊ฒƒ์ด ์–ด๋””์„œ ์™”๋Š”์ง€์— ๋Œ€ํ•œ ์ž‘์€ ์—ญ์‚ฌ

์ด์•ผ๊ธฐ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ถ„๋ฆฌํ•˜๋Š” ์ž˜ ์•Œ๋ ค์ง„ ์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ chroot์ž…๋‹ˆ๋‹ค. ๋™์ผํ•œ ์ด๋ฆ„์˜ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์€ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ํ˜ธ์ถœํ•œ ํ”„๋กœ๊ทธ๋žจ์€ ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์˜ ํŒŒ์ผ์—๋งŒ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ”„๋กœ๊ทธ๋žจ์— ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฃจํŠธ ๊ถŒํ•œ์ด ๋ถ€์—ฌ๋˜๋ฉด ์ž ์žฌ์ ์œผ๋กœ chroot๋ฅผ "ํƒˆ์ถœ"ํ•˜์—ฌ ๊ธฐ๋ณธ ์šด์˜ ์ฒด์ œ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ฃจํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ณ€๊ฒฝ ์™ธ์—๋„ ๊ธฐํƒ€ ๋ฆฌ์†Œ์Šค(RAM, ํ”„๋กœ์„ธ์„œ)๋Š” ๋ฌผ๋ก  ๋„คํŠธ์›Œํฌ ์•ก์„ธ์Šค๋„ ์ œํ•œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๋ฐฉ๋ฒ•์€ ์šด์˜ ์ฒด์ œ ์ปค๋„์˜ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปจํ…Œ์ด๋„ˆ ๋‚ด์—์„œ ๋ณธ๊ฒฉ์ ์ธ ์šด์˜ ์ฒด์ œ๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ์šด์˜ ์ฒด์ œ๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ํ˜ธ์ถœ๋˜์ง€๋งŒ ๋ณธ์งˆ์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋…๋ฆฝ์ ์ธ ์šด์˜ ์ฒด์ œ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฐ ์šด์˜ ์ฒด์ œ๋Š” ๊ธฐ๋ณธ ์šด์˜ ์ฒด์ œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ปค๋„์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” FreeBSD Jails, Solaris Zones, OpenVZ ๋ฐ Linux์šฉ LXC๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๋””์Šคํฌ ๊ณต๊ฐ„๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค๋ฅผ ํ†ตํ•ด์„œ๋„ ๊ฒฉ๋ฆฌ๊ฐ€ ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ๊ฐ ์ปจํ…Œ์ด๋„ˆ์—๋Š” ํ”„๋กœ์„ธ์„œ ์‹œ๊ฐ„, RAM ๋ฐ ๋„คํŠธ์›Œํฌ ๋Œ€์—ญํญ์— ๋Œ€ํ•œ ์ œํ•œ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. chroot์— ๋น„ํ•ด ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋– ๋‚˜๋Š” ๊ฒƒ์ด ๋” ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์ปจํ…Œ์ด๋„ˆ์˜ ์ˆ˜ํผ์œ ์ €๋Š” ์ปจํ…Œ์ด๋„ˆ์˜ ๋‚ด์šฉ์—๋งŒ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์˜ ์šด์˜ ์ฒด์ œ๋ฅผ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ํ•ด์•ผ ํ•˜๊ณ  ์ด์ „ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ปค๋„(Linux์™€ ๊ด€๋ จ์ด ์žˆ๊ณ  FreeBSD์™€ ๊ด€๋ จ์ด ์žˆ์Œ)์˜ ๊ฒฝ์šฐ ์ปค๋„ ๊ฒฉ๋ฆฌ ์‹œ์Šคํ…œ์„ "๋ŒํŒŒ"ํ•˜์—ฌ ๊ธฐ๋ณธ ์šด์˜ ์ฒด์ œ์— ์•ก์„ธ์Šคํ•  ๊ฐ€๋Šฅ์„ฑ์ด XNUMX์ด ์•„๋‹™๋‹ˆ๋‹ค.

์ปจํ…Œ์ด๋„ˆ(์ดˆ๊ธฐํ™” ์‹œ์Šคํ…œ, ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž ๋“ฑ ํฌํ•จ)์—์„œ ๋ณธ๊ฒฉ์ ์ธ ์šด์˜ ์ฒด์ œ๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๋Œ€์‹  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ฆ‰์‹œ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ทธ๋Ÿฌํ•œ ๊ธฐํšŒ(ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ์Œ)๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฐ ๊ธฐํƒ€ ํŒŒ์ผ). ์ด ์•„์ด๋””์–ด๋Š” ์ปจํ…Œ์ด๋„ˆํ™”๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐ€์ƒํ™”์˜ ๊ธฐ๋ฐ˜์ด ๋˜์—ˆ์œผ๋ฉฐ, ๊ทธ ์ค‘ ๊ฐ€์žฅ ์œ ๋ช…ํ•˜๊ณ  ์ž˜ ์•Œ๋ ค์ง„ ๋Œ€ํ‘œ์ž๋Š” Docker์ž…๋‹ˆ๋‹ค. ์ด์ „ ์‹œ์Šคํ…œ์— ๋น„ํ•ด ๋ณด๋‹ค ์œ ์—ฐํ•œ ๊ฒฉ๋ฆฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜๊ณผ ์ปจํ…Œ์ด๋„ˆ ๊ฐ„ ๊ฐ€์ƒ ๋„คํŠธ์›Œํฌ์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ์ œ๊ณต ์ง€์› ๋ฐ ์ปจํ…Œ์ด๋„ˆ ๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ ์ถ”์ ์„ ํ†ตํ•ด ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰์„ ์œ„ํ•ด ๋‹ค์ˆ˜์˜ ๋ฌผ๋ฆฌ์  ์„œ๋ฒ„์—์„œ ์ผ๊ด€๋œ ๋‹จ์ผ ํ™˜๊ฒฝ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ˆ˜๋™์œผ๋กœ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ด€๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋„์ปค

Docker๋Š” ๊ฐ€์žฅ ์œ ๋ช…ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…Œ์ด๋„ˆํ™” ์†Œํ”„ํŠธ์›จ์–ด์ž…๋‹ˆ๋‹ค. Go ์–ธ์–ด๋กœ ์ž‘์„ฑ๋˜์—ˆ์œผ๋ฉฐ Linux ์ปค๋„์˜ ํ‘œ์ค€ ๊ธฐ๋Šฅ(cgroup, ๋„ค์ž„์ŠคํŽ˜์ด์Šค, ๊ธฐ๋Šฅ ๋“ฑ)์€ ๋ฌผ๋ก  Aufs ํŒŒ์ผ ์‹œ์Šคํ…œ ๋ฐ ์ด์™€ ์œ ์‚ฌํ•œ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋””์Šคํฌ ๊ณต๊ฐ„์„ ์ ˆ์•ฝํ•ฉ๋‹ˆ๋‹ค.

๋„์ปค์™€ ๋ชจ๋‘, ๋ชจ๋‘, ๋ชจ๋‘
์ถœ์ฒ˜: ์œ„ํ‚ค๋ฏธ๋””์–ด

๊ตฌ์กฐ

๋ฒ„์ „ 1.11 ์ด์ „์—๋Š” Docker๋Š” ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ, ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰, API ์š”์ฒญ ์ฒ˜๋ฆฌ ๋“ฑ ์ปจํ…Œ์ด๋„ˆ์™€ ๊ด€๋ จ๋œ ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋‹จ์ผ ์„œ๋น„์Šค๋กœ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฒ„์ „ 1.11๋ถ€ํ„ฐ Docker๋Š” ์„œ๋กœ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆ„์–ด์กŒ์Šต๋‹ˆ๋‹ค. ์ปจํ…Œ์ด๋„ˆ์˜ ์ „์ฒด ์ˆ˜๋ช… ์ฃผ๊ธฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ปจํ…Œ์ด๋„ˆd(๋””์Šคํฌ ๊ณต๊ฐ„ ํ• ๋‹น, ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ, ๋„คํŠธ์›Œํฌ ์ž‘์—…, ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰, ์„ค์น˜ ๋ฐ ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ง) ๊ทธ๋ฆฌ๊ณ  Linux ์ปค๋„์˜ cgroup ๋ฐ ๊ธฐํƒ€ ๊ธฐ๋Šฅ ์‚ฌ์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ ํ™˜๊ฒฝ์ธ runC๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. Docker ์„œ๋น„์Šค ์ž์ฒด๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€๋˜์ง€๋งŒ ์ด์ œ๋Š” ์ปจํ…Œ์ด๋„ˆ๋กœ ๋ณ€ํ™˜๋œ API ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ญํ• ๋งŒ ํ•ฉ๋‹ˆ๋‹ค.

๋„์ปค์™€ ๋ชจ๋‘, ๋ชจ๋‘, ๋ชจ๋‘

์„ค์น˜ ๋ฐ ๊ตฌ์„ฑ

์ œ๊ฐ€ ๊ฐ€์žฅ ์ข‹์•„ํ•˜๋Š” docker ์„ค์น˜ ๋ฐฉ๋ฒ•์€ docker-machine์ธ๋ฐ, ์ด๋Š” ์›๊ฒฉ ์„œ๋ฒ„(๋‹ค์–‘ํ•œ ํด๋ผ์šฐ๋“œ ํฌํ•จ)์— docker๋ฅผ ์ง์ ‘ ์„ค์น˜ํ•˜๊ณ  ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ ์™ธ์—๋„ ์›๊ฒฉ ์„œ๋ฒ„์˜ ํŒŒ์ผ ์‹œ์Šคํ…œ๊ณผ ์ž‘์—…์ด ๊ฐ€๋Šฅํ•˜๊ณ  ๋‹ค์–‘ํ•œ ๋ช…๋ น์„ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ 2018๋…„ ์ดํ›„์—๋Š” ํ”„๋กœ์ ํŠธ๊ฐ€ ๊ฑฐ์˜ ๊ฐœ๋ฐœ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€๋ถ€๋ถ„์˜ Linux ๋ฐฐํฌํŒ์— ๋Œ€ํ•œ ํ‘œ์ค€ ๋ฐฉ์‹(๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ถ”๊ฐ€ ๋ฐ ํ•„์š”ํ•œ ํŒจํ‚ค์ง€ ์„ค์น˜)์œผ๋กœ ์„ค์น˜ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ๋ฐฉ๋ฒ•์€ ์˜ˆ๋ฅผ ๋“ค์–ด Ansible ๋˜๋Š” ๊ธฐํƒ€ ์œ ์‚ฌํ•œ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜๋Š” ์ž๋™ ์„ค์น˜์—๋„ ์‚ฌ์šฉ๋˜์ง€๋งŒ ์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ๊ณ ๋ คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์„ค์น˜๋Š” Centos 7์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๊ฐ€์ƒ ๋จธ์‹ ์„ ์„œ๋ฒ„๋กœ ์‚ฌ์šฉํ•˜์—ฌ ์„ค์น˜ํ•˜๋ ค๋ฉด ์•„๋ž˜ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

# yum install -y yum-utils
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# yum install docker-ce docker-ce-cli containerd.io

์„ค์น˜ ํ›„์—๋Š” ์„œ๋น„์Šค๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์‹œ์ž‘ ๋ชจ๋“œ์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanent

๋˜ํ•œ ์‚ฌ์šฉ์ž๊ฐ€ sudo ์—†์ด docker๋กœ ์ž‘์—…ํ•˜๊ณ , ๋กœ๊น…์„ ์„ค์ •ํ•˜๊ณ , ์™ธ๋ถ€์—์„œ API์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋ฅผ ํ™œ์„ฑํ™”ํ•˜๊ณ , ๋ฐฉํ™”๋ฒฝ์„ ๋ณด๋‹ค ์ •ํ™•ํ•˜๊ฒŒ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ์•Š๋Š” docker ๊ทธ๋ฃน์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š” ๋ชจ๋“  ๊ฒƒ). ์œ„์™€ ์•„๋ž˜์˜ ์˜ˆ์—์„œ๋Š” ๊ธˆ์ง€๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹จ์ˆœ์„ฑ๊ณผ ๋ช…ํ™•์„ฑ์„ ์œ„ํ•ด ์ƒ๋žตํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์„œ๋Š” ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•˜์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ํŠน์ง•๋“ค

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋„์ปค ๋จธ์‹  ์™ธ์—๋„ ์ปจํ…Œ์ด๋„ˆ์šฉ ์ด๋ฏธ์ง€๋ฅผ ์ €์žฅํ•˜๋Š” ๋„๊ตฌ์ธ ๋„์ปค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ(Docker Registry)์™€ ์ปจํ…Œ์ด๋„ˆ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ๋ฅผ ์ž๋™ํ™”ํ•˜๋Š” ๋„๊ตฌ์ธ ๋„์ปค ์ž‘์„ฑ(Docker Compose)๋„ ์žˆ์œผ๋ฉฐ, YAML ํŒŒ์ผ์€ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ฐ ๊ธฐํƒ€ ๊ด€๋ จ ์‚ฌํ•ญ(์˜ˆ: ๋„คํŠธ์›Œํฌ, ์Šคํ† ๋ฆฌ์ง€ ๋ฐ์ดํ„ฐ์šฉ ์˜๊ตฌ ํŒŒ์ผ ์‹œ์Šคํ…œ)

CICD์šฉ ์ปจ๋ฒ ์ด์–ด๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ ํฅ๋ฏธ๋กœ์šด ๊ธฐ๋Šฅ์€ ์†Œ์œ„ ์Šค์›œ(swarm) ๋ชจ๋“œ(๋ฒ„์ „ 1.12 ์ด์ „์—๋Š” docker swarm์œผ๋กœ ์•Œ๋ ค์ง)์ธ ํด๋Ÿฌ์Šคํ„ฐ ๋ชจ๋“œ์—์„œ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๋ชจ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ์„œ๋ฒ„์—์„œ ๋‹จ์ผ ์ธํ”„๋ผ๋ฅผ ์กฐ๋ฆฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์„œ๋ฒ„ ์œ„์— ๊ฐ€์ƒ ๋„คํŠธ์›Œํฌ๊ฐ€ ์ง€์›๋˜๊ณ  ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ๊ฐ€ ๋‚ด์žฅ๋˜์–ด ์žˆ์œผ๋ฉฐ ์ปจํ…Œ์ด๋„ˆ์— ๋Œ€ํ•œ ๋น„๋ฐ€๋„ ์ง€์›๋ฉ๋‹ˆ๋‹ค.

์•ฝ๊ฐ„์˜ ์ˆ˜์ •์„ ๊ฑฐ์ณ docker compose์˜ YAML ํŒŒ์ผ์„ ์ด๋Ÿฌํ•œ ํด๋Ÿฌ์Šคํ„ฐ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ๋‹ค์–‘ํ•œ ๋ชฉ์ ์œผ๋กœ ์ค‘์†Œ ๊ทœ๋ชจ ํด๋Ÿฌ์Šคํ„ฐ์˜ ์œ ์ง€ ๊ด€๋ฆฌ๋ฅผ ์™„์ „ํžˆ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๊ทœ๋ชจ ํด๋Ÿฌ์Šคํ„ฐ์˜ ๊ฒฝ์šฐ ์Šค์›œ ๋ชจ๋“œ์˜ ์œ ์ง€ ๊ด€๋ฆฌ ๋น„์šฉ์ด Kubernetes์˜ ์œ ์ง€ ๊ด€๋ฆฌ ๋น„์šฉ์„ ์ดˆ๊ณผํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ Kubernetes๊ฐ€ ์„ ํ˜ธ๋ฉ๋‹ˆ๋‹ค. runC ์™ธ์—๋„ ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ ํ™˜๊ฒฝ ๋“ฑ์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์นดํƒ€ ์ปจํ…Œ์ด๋„ˆ

๋„์ปค๋กœ ์ž‘์—…ํ•˜๊ธฐ

์„ค์น˜ ๋ฐ ๊ตฌ์„ฑ ํ›„์—๋Š” ๊ฐœ๋ฐœ ํŒ€์„ ์œ„ํ•ด GitLab ๋ฐ Docker Registry๋ฅผ ๋ฐฐํฌํ•  ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์–ด์…ˆ๋ธ”ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์„ธ ๊ฐœ์˜ ๊ฐ€์ƒ ๋จธ์‹ ์„ ์„œ๋ฒ„๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์—ฌ๊ธฐ์— ๋ถ„์‚ฐํ˜• FS GlusterFS๋ฅผ ์ถ”๊ฐ€๋กœ ๋ฐฐํฌํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‚ด๊ฒฐํ•จ์„ฑ ๋ฒ„์ „์˜ Docker ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ด๋ฅผ Docker ๋ณผ๋ฅจ ์Šคํ† ๋ฆฌ์ง€๋กœ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‹คํ–‰ํ•  ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ: Docker Registry, Postgresql, Redis, Swarm ๊ธฐ๋ฐ˜์˜ GitLab Runner๋ฅผ ์ง€์›ํ•˜๋Š” GitLab. ํด๋Ÿฌ์Šคํ„ฐ๋ง์„ ๊ฐ–์ถ˜ Postgresql์„ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค ์Šคํ†จ๋ก , ๋”ฐ๋ผ์„œ Postgresql ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด GlusterFS๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‚˜๋จธ์ง€ ์ค‘์š”ํ•œ ๋ฐ์ดํ„ฐ๋Š” GlusterFS์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ์„œ๋ฒ„(node1, node2, node3๋ผ๊ณ  ํ•จ)์— GlusterFS๋ฅผ ๋ฐฐํฌํ•˜๋ ค๋ฉด ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜๊ณ  ๋ฐฉํ™”๋ฒฝ์„ ํ™œ์„ฑํ™”ํ•˜๊ณ  ํ•„์š”ํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

# yum -y install centos-release-gluster7
# yum -y install glusterfs-server
# systemctl enable glusterd
# systemctl start glusterd
# firewall-cmd --add-service=glusterfs --permanent
# firewall-cmd --reload
# mkdir -p /srv/gluster
# mkdir -p /srv/docker
# echo "$(hostname):/docker /srv/docker glusterfs defaults,_netdev 0 0" >> /etc/fstab

์„ค์น˜ ํ›„ GlusterFS ๊ตฌ์„ฑ ์ž‘์—…์€ ํ•˜๋‚˜์˜ ๋…ธ๋“œ(์˜ˆ: node1)์—์„œ ๊ณ„์†๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

# gluster peer probe node2
# gluster peer probe node3
# gluster volume create docker replica 3 node1:/srv/gluster node2:/srv/gluster node3:/srv/gluster force
# gluster volume start docker

๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฒฐ๊ณผ ๋ณผ๋ฅจ์„ ๋งˆ์šดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(๋ช…๋ น์€ ๋ชจ๋“  ์„œ๋ฒ„์—์„œ ์‹คํ–‰๋˜์–ด์•ผ ํ•จ).

# mount /srv/docker

Swarm ๋ชจ๋“œ๋Š” ๋ฆฌ๋”๊ฐ€ ๋  ์„œ๋ฒ„ ์ค‘ ํ•˜๋‚˜์— ๊ตฌ์„ฑ๋˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ํด๋Ÿฌ์Šคํ„ฐ์— ์ฐธ์—ฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ฒซ ๋ฒˆ์งธ ์„œ๋ฒ„์—์„œ ๋ช…๋ น์„ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ๋‹ค๋ฅธ ์„œ๋ฒ„์—์„œ ์‹คํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ดˆ๊ธฐ ํด๋Ÿฌ์Šคํ„ฐ ์„ค์ •, node1์—์„œ ๋ช…๋ น์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

# docker swarm init
Swarm initialized: current node (a5jpfrh5uvo7svzz1ajduokyq) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-0c5mf7mvzc7o7vjk0wngno2dy70xs95tovfxbv4tqt9280toku-863hyosdlzvd76trfptd4xnzd xx.xx.xx.xx:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
# docker swarm join-token manager

๋‘ ๋ฒˆ์งธ ๋ช…๋ น์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ node2 ๋ฐ node3์—์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

# docker swarm join --token SWMTKN-x-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxx xx.xx.xx.xx:2377
This node joined a swarm as a manager.

์ด์ œ ์„œ๋ฒ„์˜ ์˜ˆ๋น„ ๊ตฌ์„ฑ์ด ์™„๋ฃŒ๋˜์—ˆ์œผ๋‹ˆ ์„œ๋น„์Šค ์„ค์ •์„ ์ง„ํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ฌ๋ฆฌ ์ง€์ •ํ•˜์ง€ ์•Š๋Š” ํ•œ ์‹คํ–‰ํ•  ๋ช…๋ น์€ node1์—์„œ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.

์šฐ์„  ์ปจํ…Œ์ด๋„ˆ์šฉ ๋„คํŠธ์›Œํฌ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

# docker network create --driver=overlay etcd
# docker network create --driver=overlay pgsql
# docker network create --driver=overlay redis
# docker network create --driver=overlay traefik
# docker network create --driver=overlay gitlab

๊ทธ๋Ÿฐ ๋‹ค์Œ ์„œ๋ฒ„๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ผ๋ถ€ ์„œ๋น„์Šค๋ฅผ ์„œ๋ฒ„์— ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3

๋‹ค์Œ์œผ๋กœ Traefik ๋ฐ Stolon์— ํ•„์š”ํ•œ etcd ๋ฐ์ดํ„ฐ, KV ์Šคํ† ๋ฆฌ์ง€๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. Postgresql๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์„œ๋ฒ„์— ์—ฐ๊ฒฐ๋œ ์ปจํ…Œ์ด๋„ˆ์ด๋ฏ€๋กœ ๋ชจ๋“  ์„œ๋ฒ„์—์„œ ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

# mkdir -p /srv/etcd

๋‹ค์Œ์œผ๋กœ etcd๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

00etcd.yml

version: '3.7'

services:
  etcd1:
    image: quay.io/coreos/etcd:latest
    hostname: etcd1
    command:
      - etcd
      - --name=etcd1
      - --data-dir=/data.etcd
      - --advertise-client-urls=http://etcd1:2379
      - --listen-client-urls=http://0.0.0.0:2379
      - --initial-advertise-peer-urls=http://etcd1:2380
      - --listen-peer-urls=http://0.0.0.0:2380
      - --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - --initial-cluster-state=new
      - --initial-cluster-token=etcd-cluster
    networks:
      - etcd
    volumes:
      - etcd1vol:/data.etcd
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node1]
  etcd2:
    image: quay.io/coreos/etcd:latest
    hostname: etcd2
    command:
      - etcd
      - --name=etcd2
      - --data-dir=/data.etcd
      - --advertise-client-urls=http://etcd2:2379
      - --listen-client-urls=http://0.0.0.0:2379
      - --initial-advertise-peer-urls=http://etcd2:2380
      - --listen-peer-urls=http://0.0.0.0:2380
      - --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - --initial-cluster-state=new
      - --initial-cluster-token=etcd-cluster
    networks:
      - etcd
    volumes:
      - etcd2vol:/data.etcd
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node2]
  etcd3:
    image: quay.io/coreos/etcd:latest
    hostname: etcd3
    command:
      - etcd
      - --name=etcd3
      - --data-dir=/data.etcd
      - --advertise-client-urls=http://etcd3:2379
      - --listen-client-urls=http://0.0.0.0:2379
      - --initial-advertise-peer-urls=http://etcd3:2380
      - --listen-peer-urls=http://0.0.0.0:2380
      - --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - --initial-cluster-state=new
      - --initial-cluster-token=etcd-cluster
    networks:
      - etcd
    volumes:
      - etcd3vol:/data.etcd
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node3]

volumes:
  etcd1vol:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/etcd"
  etcd2vol:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/etcd"
  etcd3vol:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/etcd"

networks:
  etcd:
    external: true

# docker stack deploy --compose-file 00etcd.yml etcd

์ž ์‹œ ํ›„ etcd ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ์ž‘๋™๋˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

# docker exec $(docker ps | awk '/etcd/ {print $1}')  etcdctl member list
ade526d28b1f92f7: name=etcd1 peerURLs=http://etcd1:2380 clientURLs=http://etcd1:2379 isLeader=false
bd388e7810915853: name=etcd3 peerURLs=http://etcd3:2380 clientURLs=http://etcd3:2379 isLeader=false
d282ac2ce600c1ce: name=etcd2 peerURLs=http://etcd2:2380 clientURLs=http://etcd2:2379 isLeader=true
# docker exec $(docker ps | awk '/etcd/ {print $1}')  etcdctl cluster-health
member ade526d28b1f92f7 is healthy: got healthy result from http://etcd1:2379
member bd388e7810915853 is healthy: got healthy result from http://etcd3:2379
member d282ac2ce600c1ce is healthy: got healthy result from http://etcd2:2379
cluster is healthy

Postgresql์šฉ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ  ๋ชจ๋“  ์„œ๋ฒ„์—์„œ ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

# mkdir -p /srv/pgsql

๋‹ค์Œ์œผ๋กœ Postgresql์„ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

01pgsql.yml

version: '3.7'

services:
  pgsentinel:
    image: sorintlab/stolon:master-pg10
    command:
      - gosu
      - stolon
      - stolon-sentinel
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
      - --log-level=debug
    networks:
      - etcd
      - pgsql
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 30s
        order: stop-first
        failure_action: pause
  pgkeeper1:
    image: sorintlab/stolon:master-pg10
    hostname: pgkeeper1
    command:
      - gosu
      - stolon
      - stolon-keeper
      - --pg-listen-address=pgkeeper1
      - --pg-repl-username=replica
      - --uid=pgkeeper1
      - --pg-su-username=postgres
      - --pg-su-passwordfile=/run/secrets/pgsql
      - --pg-repl-passwordfile=/run/secrets/pgsql_repl
      - --data-dir=/var/lib/postgresql/data
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    environment:
      - PGDATA=/var/lib/postgresql/data
    volumes:
      - pgkeeper1:/var/lib/postgresql/data
    secrets:
      - pgsql
      - pgsql_repl
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node1]
  pgkeeper2:
    image: sorintlab/stolon:master-pg10
    hostname: pgkeeper2
    command:
      - gosu
      - stolon 
      - stolon-keeper
      - --pg-listen-address=pgkeeper2
      - --pg-repl-username=replica
      - --uid=pgkeeper2
      - --pg-su-username=postgres
      - --pg-su-passwordfile=/run/secrets/pgsql
      - --pg-repl-passwordfile=/run/secrets/pgsql_repl
      - --data-dir=/var/lib/postgresql/data
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    environment:
      - PGDATA=/var/lib/postgresql/data
    volumes:
      - pgkeeper2:/var/lib/postgresql/data
    secrets:
      - pgsql
      - pgsql_repl
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node2]
  pgkeeper3:
    image: sorintlab/stolon:master-pg10
    hostname: pgkeeper3
    command:
      - gosu
      - stolon 
      - stolon-keeper
      - --pg-listen-address=pgkeeper3
      - --pg-repl-username=replica
      - --uid=pgkeeper3
      - --pg-su-username=postgres
      - --pg-su-passwordfile=/run/secrets/pgsql
      - --pg-repl-passwordfile=/run/secrets/pgsql_repl
      - --data-dir=/var/lib/postgresql/data
      - --cluster-name=stolon-cluster
      - --store-backend=etcdv3
      - --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    environment:
      - PGDATA=/var/lib/postgresql/data
    volumes:
      - pgkeeper3:/var/lib/postgresql/data
    secrets:
      - pgsql
      - pgsql_repl
    deploy:
      replicas: 1
      placement:
        constraints: [node.labels.nodename == node3]
  postgresql:
    image: sorintlab/stolon:master-pg10
    command: gosu stolon stolon-proxy --listen-address 0.0.0.0 --cluster-name stolon-cluster --store-backend=etcdv3 --store-endpoints http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
    networks:
      - etcd
      - pgsql
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 30s
        order: stop-first
        failure_action: rollback

volumes:
  pgkeeper1:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/pgsql"
  pgkeeper2:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/pgsql"
  pgkeeper3:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/pgsql"

secrets:
  pgsql:
    file: "/srv/docker/postgres"
  pgsql_repl:
    file: "/srv/docker/replica"

networks:
  etcd:
    external: true
  pgsql:
    external: true

๋น„๋ฐ€์„ ์ƒ์„ฑํ•˜๊ณ  ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

# </dev/urandom tr -dc 234567890qwertyuopasdfghjkzxcvbnmQWERTYUPASDFGHKLZXCVBNM | head -c $(((RANDOM%3)+15)) > /srv/docker/replica
# </dev/urandom tr -dc 234567890qwertyuopasdfghjkzxcvbnmQWERTYUPASDFGHKLZXCVBNM | head -c $(((RANDOM%3)+15)) > /srv/docker/postgres
# docker stack deploy --compose-file 01pgsql.yml pgsql

์ž ์‹œ ํ›„(๋ช…๋ น ์ถœ๋ ฅ ์ฐธ์กฐ) ๋„์ปค ์„œ๋น„์Šค ls๋ชจ๋“  ์„œ๋น„์Šค๊ฐ€ ์ž‘๋™ ์ค‘์ธ์ง€ ํ™•์ธ) Postgresql ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

# docker exec $(docker ps | awk '/pgkeeper/ {print $1}') stolonctl --cluster-name=stolon-cluster --store-backend=etcdv3 --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 init

Postgresql ํด๋Ÿฌ์Šคํ„ฐ์˜ ์ค€๋น„ ์ƒํƒœ ํ™•์ธ:

# docker exec $(docker ps | awk '/pgkeeper/ {print $1}') stolonctl --cluster-name=stolon-cluster --store-backend=etcdv3 --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 status
=== Active sentinels ===

ID      LEADER
26baa11d    false
74e98768    false
a8cb002b    true

=== Active proxies ===

ID
4d233826
9f562f3b
b0c79ff1

=== Keepers ===

UID     HEALTHY PG LISTENADDRESS    PG HEALTHY  PG WANTEDGENERATION PG CURRENTGENERATION
pgkeeper1   true    pgkeeper1:5432         true     2           2
pgkeeper2   true    pgkeeper2:5432          true            2                   2
pgkeeper3   true    pgkeeper3:5432          true            3                   3

=== Cluster Info ===

Master Keeper: pgkeeper3

===== Keepers/DB tree =====

pgkeeper3 (master)
โ”œโ”€pgkeeper2
โ””โ”€pgkeeper1

์™ธ๋ถ€์—์„œ ์ปจํ…Œ์ด๋„ˆ์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋ฅผ ์—ด๋„๋ก traefik์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

03traefik.yml

version: '3.7'

services:
  traefik:
    image: traefik:latest
    command: >
      --log.level=INFO
      --providers.docker=true
      --entryPoints.web.address=:80
      --providers.providersThrottleDuration=2
      --providers.docker.watch=true
      --providers.docker.swarmMode=true
      --providers.docker.swarmModeRefreshSeconds=15s
      --providers.docker.exposedbydefault=false
      --accessLog.bufferingSize=0
      --api=true
      --api.dashboard=true
      --api.insecure=true
    networks:
      - traefik
    ports:
      - 80:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      replicas: 3
      placement:
        constraints:
          - node.role == manager
        preferences:
          - spread: node.id
      labels:
        - traefik.enable=true
        - traefik.http.routers.traefik.rule=Host(`traefik.example.com`)
        - traefik.http.services.traefik.loadbalancer.server.port=8080
        - traefik.docker.network=traefik

networks:
  traefik:
    external: true

# docker stack deploy --compose-file 03traefik.yml traefik

Redis ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์ด๋ฅผ ์œ„ํ•ด ๋ชจ๋“  ๋…ธ๋“œ์— ์Šคํ† ๋ฆฌ์ง€ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

# mkdir -p /srv/redis

05redis.yml

version: '3.7'

services:
  redis-master:
    image: 'bitnami/redis:latest'
    networks:
      - redis
    ports:
      - '6379:6379'
    environment:
      - REDIS_REPLICATION_MODE=master
      - REDIS_PASSWORD=xxxxxxxxxxx
    deploy:
      mode: global
      restart_policy:
        condition: any
    volumes:
      - 'redis:/opt/bitnami/redis/etc/'

  redis-replica:
    image: 'bitnami/redis:latest'
    networks:
      - redis
    ports:
      - '6379'
    depends_on:
      - redis-master
    environment:
      - REDIS_REPLICATION_MODE=slave
      - REDIS_MASTER_HOST=redis-master
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_PASSWORD=xxxxxxxxxxx
      - REDIS_PASSWORD=xxxxxxxxxxx
    deploy:
      mode: replicated
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: any

  redis-sentinel:
    image: 'bitnami/redis:latest'
    networks:
      - redis
    ports:
      - '16379'
    depends_on:
      - redis-master
      - redis-replica
    entrypoint: |
      bash -c 'bash -s <<EOF
      "/bin/bash" -c "cat <<EOF > /opt/bitnami/redis/etc/sentinel.conf
      port 16379
      dir /tmp
      sentinel monitor master-node redis-master 6379 2
      sentinel down-after-milliseconds master-node 5000
      sentinel parallel-syncs master-node 1
      sentinel failover-timeout master-node 5000
      sentinel auth-pass master-node xxxxxxxxxxx
      sentinel announce-ip redis-sentinel
      sentinel announce-port 16379
      EOF"
      "/bin/bash" -c "redis-sentinel /opt/bitnami/redis/etc/sentinel.conf"
      EOF'
    deploy:
      mode: global
      restart_policy:
        condition: any

volumes:
  redis:
    driver: local
    driver_opts:
      type: 'none'
      o: 'bind'
      device: "/srv/redis"

networks:
  redis:
    external: true

# docker stack deploy --compose-file 05redis.yml redis

Docker ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

06registry.yml

version: '3.7'

services:
  registry:
    image: registry:2.6
    networks:
      - traefik
    volumes:
      - registry_data:/var/lib/registry
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: on-failure
      labels:
        - traefik.enable=true
        - traefik.http.routers.registry.rule=Host(`registry.example.com`)
        - traefik.http.services.registry.loadbalancer.server.port=5000
        - traefik.docker.network=traefik

volumes:
  registry_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/registry"

networks:
  traefik:
    external: true

# mkdir /srv/docker/registry
# docker stack deploy --compose-file 06registry.yml registry

๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ - GitLab:

08gitlab-runner.yml

version: '3.7'

services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    networks:
      - pgsql
      - redis
      - traefik
      - gitlab
    ports:
      - 22222:22
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        postgresql['enable'] = false
        redis['enable'] = false
        gitlab_rails['registry_enabled'] = false
        gitlab_rails['db_username'] = "gitlab"
        gitlab_rails['db_password'] = "XXXXXXXXXXX"
        gitlab_rails['db_host'] = "postgresql"
        gitlab_rails['db_port'] = "5432"
        gitlab_rails['db_database'] = "gitlab"
        gitlab_rails['db_adapter'] = 'postgresql'
        gitlab_rails['db_encoding'] = 'utf8'
        gitlab_rails['redis_host'] = 'redis-master'
        gitlab_rails['redis_port'] = '6379'
        gitlab_rails['redis_password'] = 'xxxxxxxxxxx'
        gitlab_rails['smtp_enable'] = true
        gitlab_rails['smtp_address'] = "smtp.yandex.ru"
        gitlab_rails['smtp_port'] = 465
        gitlab_rails['smtp_user_name'] = "[email protected]"
        gitlab_rails['smtp_password'] = "xxxxxxxxx"
        gitlab_rails['smtp_domain'] = "example.com"
        gitlab_rails['gitlab_email_from'] = '[email protected]'
        gitlab_rails['smtp_authentication'] = "login"
        gitlab_rails['smtp_tls'] = true
        gitlab_rails['smtp_enable_starttls_auto'] = true
        gitlab_rails['smtp_openssl_verify_mode'] = 'peer'
        external_url 'http://gitlab.example.com/'
        gitlab_rails['gitlab_shell_ssh_port'] = 22222
    volumes:
      - gitlab_conf:/etc/gitlab
      - gitlab_logs:/var/log/gitlab
      - gitlab_data:/var/opt/gitlab
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
        - node.role == manager
      labels:
        - traefik.enable=true
        - traefik.http.routers.gitlab.rule=Host(`gitlab.example.com`)
        - traefik.http.services.gitlab.loadbalancer.server.port=80
        - traefik.docker.network=traefik
  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    networks:
      - gitlab
    volumes:
      - gitlab_runner_conf:/etc/gitlab
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
        - node.role == manager

volumes:
  gitlab_conf:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/conf"
  gitlab_logs:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/logs"
  gitlab_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/data"
  gitlab_runner_conf:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/gitlab/runner"

networks:
  pgsql:
    external: true
  redis:
    external: true
  traefik:
    external: true
  gitlab:
    external: true

# mkdir -p /srv/docker/gitlab/conf
# mkdir -p /srv/docker/gitlab/logs
# mkdir -p /srv/docker/gitlab/data
# mkdir -p /srv/docker/gitlab/runner
# docker stack deploy --compose-file 08gitlab-runner.yml gitlab

ํด๋Ÿฌ์Šคํ„ฐ ๋ฐ ์„œ๋น„์Šค์˜ ์ตœ์ข… ์ƒํƒœ:

# docker service ls
ID                  NAME                   MODE                REPLICAS            IMAGE                          PORTS
lef9n3m92buq        etcd_etcd1             replicated          1/1                 quay.io/coreos/etcd:latest
ij6uyyo792x5        etcd_etcd2             replicated          1/1                 quay.io/coreos/etcd:latest
fqttqpjgp6pp        etcd_etcd3             replicated          1/1                 quay.io/coreos/etcd:latest
hq5iyga28w33        gitlab_gitlab          replicated          1/1                 gitlab/gitlab-ce:latest        *:22222->22/tcp
dt7s6vs0q4qc        gitlab_gitlab-runner   replicated          1/1                 gitlab/gitlab-runner:latest
k7uoezno0h9n        pgsql_pgkeeper1        replicated          1/1                 sorintlab/stolon:master-pg10
cnrwul4r4nse        pgsql_pgkeeper2        replicated          1/1                 sorintlab/stolon:master-pg10
frflfnpty7tr        pgsql_pgkeeper3        replicated          1/1                 sorintlab/stolon:master-pg10
x7pqqchi52kq        pgsql_pgsentinel       replicated          3/3                 sorintlab/stolon:master-pg10
mwu2wl8fti4r        pgsql_postgresql       replicated          3/3                 sorintlab/stolon:master-pg10
9hkbe2vksbzb        redis_redis-master     global              3/3                 bitnami/redis:latest           *:6379->6379/tcp
l88zn8cla7dc        redis_redis-replica    replicated          3/3                 bitnami/redis:latest           *:30003->6379/tcp
1utp309xfmsy        redis_redis-sentinel   global              3/3                 bitnami/redis:latest           *:30002->16379/tcp
oteb824ylhyp        registry_registry      replicated          1/1                 registry:2.6
qovrah8nzzu8        traefik_traefik        replicated          3/3                 traefik:latest                 *:80->80/tcp, *:443->443/tcp

๋˜ ์–ด๋–ค ์ ์„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‚˜์š”? https๋ฅผ ํ†ตํ•ด ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก Traefik์„ ๊ตฌ์„ฑํ•˜๊ณ  Postgresql ๋ฐ Redis์— ๋Œ€ํ•œ TLS ์•”ํ˜ธํ™”๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋ฏธ PoC๋กœ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ œ๊ณต๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ Docker์˜ ๋Œ€์•ˆ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํฌ๋“œ ๋งจ

ํฌ๋“œ(ํฌ๋“œ, ํ•จ๊ป˜ ๋ฐฐํฌ๋œ ์ปจํ…Œ์ด๋„ˆ ๊ทธ๋ฃน)๋ณ„๋กœ ๊ทธ๋ฃนํ™”๋œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๊ฝค ์ž˜ ์•Œ๋ ค์ง„ ๋˜ ๋‹ค๋ฅธ ์—”์ง„์ž…๋‹ˆ๋‹ค. Docker์™€ ๋‹ฌ๋ฆฌ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ์„œ๋น„์Šค๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์œผ๋ฉฐ ๋ชจ๋“  ์ž‘์—…์€ libpod ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ Go๋กœ ์ž‘์„ฑ๋˜์—ˆ์œผ๋ฉฐ runC์™€ ๊ฐ™์€ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด OCI ํ˜ธํ™˜ ๋Ÿฐํƒ€์ž„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋„์ปค์™€ ๋ชจ๋‘, ๋ชจ๋‘, ๋ชจ๋‘

Podman์œผ๋กœ ์ž‘์—…ํ•˜๋Š” ๊ฒƒ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์—์„œ Docker์˜ ์ž‘์—…์„ ์—ฐ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค(์ด ๊ธฐ์‚ฌ์˜ ์ €์ž๋ฅผ ํฌํ•จํ•˜์—ฌ ์ด๋ฅผ ์‹œ๋„ํ•œ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด).

$ alias docker=podman

๊ณ„์† ์ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ Podman์˜ ์ƒํ™ฉ์€ ๋งค์šฐ ํฅ๋ฏธ๋กญ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ดˆ๊ธฐ ๋ฒ„์ „์˜ Kubernetes๊ฐ€ Docker์™€ ํ•จ๊ป˜ ์ž‘๋™ํ–ˆ๋‹ค๋ฉด 2015๋…„๊ฒฝ ์ปจํ…Œ์ด๋„ˆ ์„ธ๊ณ„(OCI - Open Container Initiative)๊ฐ€ ํ‘œ์ค€ํ™”๋˜๊ณ  Docker๊ฐ€ ์ปจํ…Œ์ด๋„ˆd์™€ runC๋กœ ๋ถ„ํ• ๋œ ํ›„, Kubernetes์—์„œ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ Docker์˜ ๋Œ€์•ˆ์ธ CRI-O๊ฐ€ ๊ฐœ๋ฐœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์ ์—์„œ Podman์€ ์ปจํ…Œ์ด๋„ˆ ๊ทธ๋ฃนํ™”๋ฅผ ํฌํ•จํ•˜์—ฌ Kubernetes์˜ ์›์น™์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ Docker์˜ ๋Œ€์•ˆ์ด์ง€๋งŒ ํ”„๋กœ์ ํŠธ์˜ ์ฃผ์š” ๋ชฉ์ ์€ ์ถ”๊ฐ€ ์„œ๋น„์Šค ์—†์ด Docker ์Šคํƒ€์ผ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ถ„๋ช…ํ•œ ์ด์œ ๋กœ ์Šค์›œ ๋ชจ๋“œ๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ํ•„์š”ํ•˜๋ฉด Kubernetes๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๋ถ„๋ช…ํžˆ ๋งํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์„ค์น˜

Centos 7์— ์„ค์น˜ํ•˜๋ ค๋ฉด Extras ์ €์žฅ์†Œ๋ฅผ ํ™œ์„ฑํ™”ํ•œ ํ›„ ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ๊ฒƒ์„ ์„ค์น˜ํ•˜์‹ญ์‹œ์˜ค.

# yum -y install podman

๋‹ค๋ฅธ ํŠน์ง•๋“ค

Podman์€ systemd์šฉ ๋‹จ์œ„๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์„œ๋ฒ„ ์žฌ๋ถ€ํŒ… ํ›„ ์ปจํ…Œ์ด๋„ˆ ์‹œ์ž‘ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ systemd๋Š” ์ปจํ…Œ์ด๋„ˆ์—์„œ pid 1๋กœ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๋„๋ก ์„ ์–ธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ปจํ…Œ์ด๋„ˆ ๊ตฌ์ถ•์„ ์œ„ํ•œ ๋ณ„๋„์˜ ๋นŒ๋“œ ๋„๊ตฌ๊ฐ€ ์žˆ๊ณ , Kubernetes์™€ ํ˜ธํ™˜๋˜๋Š” ๊ตฌ์„ฑ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋Š” docker-compose์™€ ์œ ์‚ฌํ•œ ํƒ€์‚ฌ ๋„๊ตฌ๋„ ์žˆ์œผ๋ฏ€๋กœ Podman์—์„œ Kubernetes๋กœ์˜ ์ „ํ™˜์ด ์ตœ๋Œ€ํ•œ ๋‹จ์ˆœํ™”๋ฉ๋‹ˆ๋‹ค.

ํฌ๋“œ๋งจ๊ณผ ํ•จ๊ป˜ ์ผํ•˜๊ธฐ

Swarm ๋ชจ๋“œ๊ฐ€ ์—†์œผ๋ฏ€๋กœ(ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ Kubernetes๋กœ ์ „ํ™˜ํ•ด์•ผ ํ•จ) ๋ณ„๋„์˜ ์ปจํ…Œ์ด๋„ˆ์— ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค.

Podman-compose๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

# yum -y install python3-pip
# pip3 install podman-compose

Podman์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ ๊ตฌ์„ฑ ํŒŒ์ผ์€ ์•ฝ๊ฐ„ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์˜ˆ๋ฅผ ๋“ค์–ด ๋ณ„๋„์˜ ๋ณผ๋ฅจ ์„น์…˜์„ ์„œ๋น„์Šค๊ฐ€ ์žˆ๋Š” ์„น์…˜์œผ๋กœ ์ง์ ‘ ์ด๋™ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

gitlab-podman.yml

version: '3.7'

services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    hostname: gitlab.example.com
    restart: unless-stopped
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        gitlab_rails['gitlab_shell_ssh_port'] = 22222
    ports:
      - "80:80"
      - "22222:22"
    volumes:
      - /srv/podman/gitlab/conf:/etc/gitlab
      - /srv/podman/gitlab/data:/var/opt/gitlab
      - /srv/podman/gitlab/logs:/var/log/gitlab
    networks:
      - gitlab

  gitlab-runner:
    image: gitlab/gitlab-runner:alpine
    restart: unless-stopped
    depends_on:
      - gitlab
    volumes:
      - /srv/podman/gitlab/runner:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - gitlab

networks:
  gitlab:

# podman-compose -f gitlab-runner.yml -d up

๊ฒฐ๊ณผ:

# podman ps
CONTAINER ID  IMAGE                                  COMMAND               CREATED             STATUS                 PORTS                                      NAMES
da53da946c01  docker.io/gitlab/gitlab-runner:alpine  run --user=gitlab...  About a minute ago  Up About a minute ago  0.0.0.0:22222->22/tcp, 0.0.0.0:80->80/tcp  root_gitlab-runner_1
781c0103c94a  docker.io/gitlab/gitlab-ce:latest      /assets/wrapper       About a minute ago  Up About a minute ago  0.0.0.0:22222->22/tcp, 0.0.0.0:80->80/tcp  root_gitlab_1

systemd ๋ฐ kubernetes์— ๋Œ€ํ•ด ๋ฌด์—‡์ด ์ƒ์„ฑ๋˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ํฌ๋“œ์˜ ์ด๋ฆ„์ด๋‚˜ ID๋ฅผ ์ฐพ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

# podman pod ls
POD ID         NAME   STATUS    CREATED          # OF CONTAINERS   INFRA ID
71fc2b2a5c63   root   Running   11 minutes ago   3                 db40ab8bf84b

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค:

# podman generate kube 71fc2b2a5c63
# Generation of Kubernetes YAML is still under development!
#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-1.6.4
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2020-07-29T19:22:40Z"
  labels:
    app: root
  name: root
spec:
  containers:
  - command:
    - /assets/wrapper
    env:
    - name: PATH
      value: /opt/gitlab/embedded/bin:/opt/gitlab/bin:/assets:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    - name: TERM
      value: xterm
    - name: HOSTNAME
      value: gitlab.example.com
    - name: container
      value: podman
    - name: GITLAB_OMNIBUS_CONFIG
      value: |
        gitlab_rails['gitlab_shell_ssh_port'] = 22222
    - name: LANG
      value: C.UTF-8
    image: docker.io/gitlab/gitlab-ce:latest
    name: rootgitlab1
    ports:
    - containerPort: 22
      hostPort: 22222
      protocol: TCP
    - containerPort: 80
      hostPort: 80
      protocol: TCP
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
    volumeMounts:
    - mountPath: /var/opt/gitlab
      name: srv-podman-gitlab-data
    - mountPath: /var/log/gitlab
      name: srv-podman-gitlab-logs
    - mountPath: /etc/gitlab
      name: srv-podman-gitlab-conf
    workingDir: /
  - command:
    - run
    - --user=gitlab-runner
    - --working-directory=/home/gitlab-runner
    env:
    - name: PATH
      value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    - name: TERM
      value: xterm
    - name: HOSTNAME
    - name: container
      value: podman
    image: docker.io/gitlab/gitlab-runner:alpine
    name: rootgitlab-runner1
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
    volumeMounts:
    - mountPath: /etc/gitlab-runner
      name: srv-podman-gitlab-runner
    - mountPath: /var/run/docker.sock
      name: var-run-docker.sock
    workingDir: /
  volumes:
  - hostPath:
      path: /srv/podman/gitlab/runner
      type: Directory
    name: srv-podman-gitlab-runner
  - hostPath:
      path: /var/run/docker.sock
      type: File
    name: var-run-docker.sock
  - hostPath:
      path: /srv/podman/gitlab/data
      type: Directory
    name: srv-podman-gitlab-data
  - hostPath:
      path: /srv/podman/gitlab/logs
      type: Directory
    name: srv-podman-gitlab-logs
  - hostPath:
      path: /srv/podman/gitlab/conf
      type: Directory
    name: srv-podman-gitlab-conf
status: {}

์‹œ์Šคํ…œ:

# podman generate systemd 71fc2b2a5c63
# pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020

[Unit]
Description=Podman pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
Documentation=man:podman-generate-systemd(1)
Requires=container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
Before=container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service

[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa
ExecStop=/usr/bin/podman stop -t 10 db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa/userdata/conmon.pid

[Install]
WantedBy=multi-user.target
# container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020

[Unit]
Description=Podman container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
Documentation=man:podman-generate-systemd(1)
RefuseManualStart=yes
RefuseManualStop=yes
BindsTo=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
After=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service

[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864
ExecStop=/usr/bin/podman stop -t 10 da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864/userdata/conmon.pid

[Install]
WantedBy=multi-user.target
# container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020

[Unit]
Description=Podman container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service
Documentation=man:podman-generate-systemd(1)
RefuseManualStart=yes
RefuseManualStop=yes
BindsTo=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
After=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service

[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start 781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3
ExecStop=/usr/bin/podman stop -t 10 781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3/userdata/conmon.pid

[Install]
WantedBy=multi-user.target

์•ˆํƒ€๊น๊ฒŒ๋„ ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ ์™ธ์— systemd์šฉ์œผ๋กœ ์ƒ์„ฑ๋œ ์œ ๋‹›์€ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์˜ˆ: ์„œ๋น„์Šค๊ฐ€ ๋‹ค์‹œ ์‹œ์ž‘๋  ๋•Œ ์ด์ „ ์ปจํ…Œ์ด๋„ˆ ์ •๋ฆฌ). ๋”ฐ๋ผ์„œ ์ด๋Ÿฌํ•œ ์ž‘์—…์€ ์ง์ ‘ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์›์น™์ ์œผ๋กœ Podman์€ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์‹œํ—˜ํ•ด๋ณด๊ณ , docker-compose์— ๋Œ€ํ•œ ์ด์ „ ๊ตฌ์„ฑ์„ ์ „์†กํ•œ ๋‹ค์Œ ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ Kubernetes๋กœ ์ด๋™ํ•˜๊ฑฐ๋‚˜ Docker์— ๋Œ€ํ•œ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด ๋Œ€์•ˆ์„ ์–ป๋Š” ๋ฐ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

rkt

๊ณ„ํš ๊ธฐ๋ก ๋ณด๊ด€์†Œ์— ๋“ค์–ด๊ฐ”๋‹ค ์•ฝ XNUMX๊ฐœ์›” ์ „์— RedHat์ด ์ด๋ฅผ ๊ตฌ์ž…ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•˜์ง€๋Š” ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค. ์ „๋ฐ˜์ ์œผ๋กœ ๋งค์šฐ ์ข‹์€ ์ธ์ƒ์„ ์ฃผ์—ˆ์ง€๋งŒ Docker, ํŠนํžˆ Podman๊ณผ ๋น„๊ตํ•˜๋ฉด ๊ฒฐํ•ฉ์ฒด์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. rkt ์œ„์— ๊ตฌ์ถ•๋œ CoreOS ๋ฐฐํฌํŒ๋„ ์žˆ์—ˆ์ง€๋งŒ(์›๋ž˜๋Š” Docker๊ฐ€ ์žˆ์—ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ ) RedHat ๊ตฌ๋งค ์ดํ›„ ์ง€์›์ด ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ํ”Œ๋ž˜์‰ฌ

๋‹ค๋ฅธ ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ, ์ž‘์„ฑ์ž๋Š” ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์‹คํ–‰ํ•˜๊ธฐ๋ฅผ ์›ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ์™€ ์ฝ”๋“œ๋กœ ํŒ๋‹จํ•˜๋ฉด ์ž‘์„ฑ์ž๋Š” ํ‘œ์ค€์„ ๋”ฐ๋ฅด์ง€ ์•Š๊ณ  ์›์น™์ ์œผ๋กœ ์ž์‹ ์˜ ๊ตฌํ˜„์„ ์ž‘์„ฑํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

์กฐ์‚ฌ ๊ฒฐ๊ณผ

Kubernetes์˜ ์ƒํ™ฉ์€ ๋งค์šฐ ํฅ๋ฏธ๋กญ์Šต๋‹ˆ๋‹ค. ํ•œํŽธ์œผ๋กœ๋Š” Docker๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์œ„ํ•œ ์ œํ’ˆ ํ™˜๊ฒฝ์„ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ๋Š” ํด๋Ÿฌ์Šคํ„ฐ(์Šค์›œ ๋ชจ๋“œ)๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํŠนํžˆ ์†Œ๊ทœ๋ชจ ํŒ€(3~5๋ช…)์— ํ•ด๋‹น๋ฉ๋‹ˆ๋‹ค. , ์ „์ฒด ๋กœ๋“œ๊ฐ€ ์ž‘๊ฑฐ๋‚˜, ๋†’์€ ๋กœ๋“œ๋ฅผ ํฌํ•จํ•˜์—ฌ Kubernetes ์„ค์ •์˜ ๋ณต์žก์„ฑ์„ ์ดํ•ดํ•˜๋ ค๋Š” ์š•๊ตฌ๊ฐ€ ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค.

Podman์€ ์™„์ „ํ•œ ํ˜ธํ™˜์„ฑ์„ ์ œ๊ณตํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ์ถ”๊ฐ€ ๋„๊ตฌ(buildah ๋ฐ ๊ธฐํƒ€)๋ฅผ ํฌํ•จํ•˜์—ฌ Kubernetes์™€์˜ ํ˜ธํ™˜์„ฑ์ด๋ผ๋Š” ํ•œ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ž‘์—… ๋„๊ตฌ ์„ ํƒ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ‘๊ทผํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์†Œ๊ทœ๋ชจ ํŒ€ ๋˜๋Š” ์˜ˆ์‚ฐ์ด ์ œํ•œ๋œ ๊ฒฝ์šฐ - Docker(์Šค์›œ ๋ชจ๋“œ ๊ฐ€๋Šฅ), ๊ฐœ์ธ ๋กœ์ปฌ ํ˜ธ์ŠคํŠธ์—์„œ ๊ฐœ๋ฐœํ•˜๊ธฐ ์œ„ํ•œ ๊ฒฝ์šฐ - Podman ๋™์ง€ ๋ฐ ๊ธฐํƒ€ ๋ชจ๋“  ์‚ฌ๋žŒ์„ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. - ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค.

Docker์˜ ์ƒํ™ฉ์ด ๋ฏธ๋ž˜์—๋„ ๋ณ€ํ•˜์ง€ ์•Š์„์ง€ ํ™•์‹ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ ๊ทธ๋“ค์€ ์„ ๊ตฌ์ž์ด๋ฉฐ ๋‹จ๊ณ„์ ์œผ๋กœ ์ ์ฐจ ํ‘œ์ค€ํ™”๋˜๊ณ  ์žˆ์ง€๋งŒ Podman์€ ๋ชจ๋“  ๋‹จ์ ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ (Linux์—์„œ๋งŒ ์ž‘๋™ํ•˜๊ณ  ํด๋Ÿฌ์Šคํ„ฐ๋ง ์—†์Œ, ์กฐ๋ฆฝ ๋ฐ ๊ธฐํƒ€ ์ž‘์—…์€ ํƒ€์‚ฌ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค) ๋ฏธ๋ž˜๋Š” ๋” ๋ช…ํ™•ํ•˜๋ฏ€๋กœ ์˜๊ฒฌ์—์„œ ์ด๋Ÿฌํ•œ ๊ฒฐ๊ณผ์— ๋Œ€ํ•ด ๋ชจ๋“  ์‚ฌ๋žŒ์ด ๋…ผ์˜ํ•˜๋„๋ก ์ดˆ๋Œ€ํ•ฉ๋‹ˆ๋‹ค.

PS 3์›” XNUMX์ผ์— '๋ฅผ ์ถœ์‹œํ•ฉ๋‹ˆ๋‹ค.๋„์ปค ๋น„๋””์˜ค ์ฝ”์Šค"์—์„œ ๊ทธ์˜ ์ž‘ํ’ˆ์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ์ถ”์ƒํ™”๋ถ€ํ„ฐ ๋„คํŠธ์›Œํฌ ๋งค๊ฐœ๋ณ€์ˆ˜, ๋‹ค์–‘ํ•œ ์šด์˜ ์ฒด์ œ ๋ฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ์ž‘์—…์˜ ๋‰˜์•™์Šค๊นŒ์ง€ ๋ชจ๋“  ๋„๊ตฌ๋ฅผ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์ˆ ์— ์ต์ˆ™ํ•ด์ง€๊ณ  Docker๋ฅผ ๊ฐ€์žฅ ์ž˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ„์น˜์™€ ๋ฐฉ๋ฒ•์„ ์ดํ•ดํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์šฐ์ˆ˜์‚ฌ๋ก€๋„ ๊ณต์œ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ถœ์‹œ ์ „ ์‚ฌ์ „ ์ฃผ๋ฌธ ๊ฐ€๊ฒฉ: RUB 5000. Docker Video Course ํ”„๋กœ๊ทธ๋žจ์„ ๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ•์ขŒ ํŽ˜์ด์ง€์—์„œ.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€