Kubernetes์˜ ์ธ๊ธฐ ์ฆ๊ฐ€์— ๋Œ€ํ•ด

ํ—ค์ด ํ•˜๋ธŒ๋ฅด!

์—ฌ๋ฆ„์ด ๋๋‚  ๋ฌด๋ ต, ์šฐ๋ฆฌ๋Š” ์ด ์ฃผ์ œ์— ๋Œ€ํ•ด ๊ณ„์†ํ•ด์„œ ์—ฐ๊ตฌํ•˜๊ณ  ์žˆ์Œ์„ ์ƒ๊ธฐ์‹œํ‚ค๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. Kubernetes ๊ทธ๋ฆฌ๊ณ  XNUMX์›” ์ดˆ์— ์ด ํ”„๋กœ์ ํŠธ์˜ ์ƒํ™ฉ์„ ๋ณด์—ฌ์ฃผ๋Š” Stackoverflow์˜ ๊ธฐ์‚ฌ๋ฅผ ๊ฒŒ์‹œํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

Kubernetes์˜ ์ธ๊ธฐ ์ฆ๊ฐ€์— ๋Œ€ํ•ด

๋…์„œ๋ฅผ ์ฆ๊ธฐ์‹ญ์‹œ์˜ค!

์ด ๊ธ€์„ ์“ฐ๋Š” ์‹œ์ ์—์„œ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์˜ ์‹œ๋Œ€๋Š” ๋Œ€๋žต XNUMX๋…„ ์ •๋„๋‹ค. ์—ฌ์„ฏ ์‚ด, ๊ทธ๋ฆฌ๊ณ  ์ง€๋‚œ XNUMX๋…„ ๋™์•ˆ ์ธ๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ๋†’์•„์ ธ ๊พธ์ค€ํžˆ ์ƒ์œ„๊ถŒ์— ๋žญํฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ข‹์•„ํ•˜๋Š” ํ”Œ๋žซํผ. ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋Š” ์˜ฌํ•ด XNUMX์œ„๋ฅผ ์ฐจ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์š”์•ฝํ•˜์ž๋ฉด, Kubernetes๋Š” ์ปจํ…Œ์ด๋„ˆํ™”๋œ ์›Œํฌ๋กœ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์กฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋œ ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค.

์ปจํ…Œ์ด๋„ˆ๋Š” Linux์—์„œ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฒฉ๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ํŠน๋ณ„ํ•œ ์„ค๊ณ„๋กœ ์‹œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค. 2007๋…„๋ถ€ํ„ฐ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. cgroup, 2002๋…„ ์ดํ›„ โ€“ ๋„ค์ž„์ŠคํŽ˜์ด์Šค. ์ปจํ…Œ์ด๋„ˆ๋Š” 2008๋…„์— ์ถœ์‹œ๋˜๋ฉด์„œ ํ›จ์”ฌ ๋” ์ข‹๊ฒŒ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. LXC, Google์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž์ฒด ๋‚ด๋ถ€ ๊ธฐ์—… ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๊ฐœ๋ฐœํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ณด๊ทธ, ์—ฌ๊ธฐ์„œ "๋ชจ๋“  ์ž‘์—…์€ ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค." 2013๋…„์—๋Š” Docker๊ฐ€ ์ฒ˜์Œ ์ถœ์‹œ๋˜์—ˆ๊ณ  ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋งˆ์นจ๋‚ด ์ธ๊ธฐ ์žˆ๋Š” ๋Œ€๋Ÿ‰ ์†”๋ฃจ์…˜์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹น์‹œ ์ปจํ…Œ์ด๋„ˆ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜์„ ์œ„ํ•œ ์ฃผ์š” ๋„๊ตฌ๋Š” ๋ฉ” ์†Œ์Šค, ๊ทธ๋Š” ํฐ ์ธ๊ธฐ๋ฅผ ์–ป์ง€๋Š” ๋ชปํ–ˆ์ง€๋งŒ. Kubernetes๋Š” 2015๋…„์— ์ฒ˜์Œ ์ถœ์‹œ๋œ ํ›„ ์ด ๋„๊ตฌ๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ๋ถ„์•ผ์˜ ์‚ฌ์‹ค์ƒ ํ‘œ์ค€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Kubernetes๊ฐ€ ์ธ๊ธฐ ์žˆ๋Š” ์ด์œ ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ๋ช‡ ๊ฐ€์ง€ ์งˆ๋ฌธ์— ๋‹ตํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋“ค์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์— ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋งˆ์ง€๋ง‰์œผ๋กœ ํ•ฉ์˜ํ•œ ๋•Œ๋Š” ์–ธ์ œ์˜€์Šต๋‹ˆ๊นŒ? ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณต๋˜๋Š” ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋ฅผ ์•Œ๊ณ  ์žˆ๋Š” ๊ฐœ๋ฐœ์ž๋Š” ๋ช‡ ๋ช…์ž…๋‹ˆ๊นŒ? ์˜ค๋Š˜๋‚  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ž‘๋™ ๋ฐฉ์‹์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋Š” ํด๋ผ์šฐ๋“œ ๊ด€๋ฆฌ์ž๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋ฉ๋‹ˆ๊นŒ? ์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ์ด๋Ÿฌํ•œ ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋‹ต์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

YAML๋กœ์„œ์˜ ์ธํ”„๋ผ

Puppet๊ณผ Chef์—์„œ Kubernetes๋กœ ์ „ํ™˜ํ•œ ์„ธ๊ณ„์—์„œ ๊ฐ€์žฅ ํฐ ๋ณ€ํ™” ์ค‘ ํ•˜๋‚˜๋Š” "์ฝ”๋“œ๋กœ์„œ์˜ ์ธํ”„๋ผ"์—์„œ ํŠนํžˆ YAML๊ณผ ๊ฐ™์€ "๋ฐ์ดํ„ฐ๋กœ์„œ์˜ ์ธํ”„๋ผ"๋กœ์˜ ์ด๋™์ด์—ˆ์Šต๋‹ˆ๋‹ค. ํฌ๋“œ, ๊ตฌ์„ฑ, ๋ฐฐํฌ๋œ ์ธ์Šคํ„ด์Šค, ๋ณผ๋ฅจ ๋“ฑ์„ ํฌํ•จํ•˜๋Š” Kubernetes์˜ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋Š” YAML ํŒŒ์ผ์—์„œ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:

apiVersion: v1
kind: Pod
metadata:
  name: site
  labels:
    app: web
spec:
  containers:
    - name: front-end
      image: nginx
      ports:
        - containerPort: 80

์ด ๋ณด๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด DevOps ๋˜๋Š” SRE ์ „๋ฌธ๊ฐ€๊ฐ€ Python ๋˜๋Š” Javascript์™€ ๊ฐ™์€ ์–ธ์–ด๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ์›Œํฌ๋กœ๋“œ๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ธํ”„๋ผ๋ฅผ ๋ฐ์ดํ„ฐ๋กœ ๊ตฌ์„ฑํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • GitOps ๋˜๋Š” Git Operations ๋ฒ„์ „ ์ œ์–ด. ์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  Kubernetes YAML ํŒŒ์ผ์„ git ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ๋ณด๊ด€ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์–ธ์ œ ๋ณ€๊ฒฝํ–ˆ๋Š”์ง€, ๋ˆ„๊ฐ€ ๋ณ€๊ฒฝํ–ˆ๋Š”์ง€, ์ •ํ™•ํžˆ ๋ฌด์—‡์ด ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํŠนํžˆ ์ง์›๋“ค์ด ํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์•„์•ผ ํ•˜๋Š” ๊ณณ์—์„œ ๋ชจํ˜ธ์„ฑ์„ ์ œ๊ฑฐํ•จ์œผ๋กœ์จ ์กฐ์ง ์ „์ฒด์˜ ์šด์˜ ํˆฌ๋ช…์„ฑ์„ ๋†’์ด๊ณ  ์šด์˜ ํšจ์œจ์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. ๋™์‹œ์— ๊ฐ„๋‹จํžˆ ํ’€ ์š”์ฒญ์„ ๋ณ‘ํ•ฉํ•˜์—ฌ Kubernetes ๋ฆฌ์†Œ์Šค๋ฅผ ์ž๋™์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฌ์›Œ์กŒ์Šต๋‹ˆ๋‹ค.
  • ํ™•์žฅ์„ฑ. ๋ฆฌ์†Œ์Šค๊ฐ€ YAML๋กœ ์ •์˜๋˜๋ฉด ํด๋Ÿฌ์Šคํ„ฐ ์šด์˜์ž๊ฐ€ Kubernetes ๋ฆฌ์†Œ์Šค์—์„œ ํ•˜๋‚˜ ๋˜๋Š” ๋‘ ๊ฐœ์˜ ์ˆซ์ž๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ํ™•์žฅ ๋ฐฉ๋ฒ•์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์‰ฌ์›Œ์ง‘๋‹ˆ๋‹ค. Kubernetes๋Š” ๋‚ฎ์€ ์ˆ˜์ค€๊ณผ ๋†’์€ ์ˆ˜์ค€์˜ ํŠธ๋ž˜ํ”ฝ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ํŠน์ • ๋ฐฐํฌ ๊ตฌ์„ฑ์— ํ•„์š”ํ•œ ์ตœ์†Œ ๋ฐ ์ตœ๋Œ€ ํฌ๋“œ ์ˆ˜๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํฌ๋“œ์˜ ์ˆ˜ํ‰ ์ž๋™ ํฌ๊ธฐ ์กฐ์ •์„ ์œ„ํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŠธ๋ž˜ํ”ฝ ๊ธ‰์ฆ์œผ๋กœ ์ธํ•ด ์ถ”๊ฐ€ ์šฉ๋Ÿ‰์ด ํ•„์š”ํ•œ ๊ตฌ์„ฑ์„ ๋ฐฐํฌํ•œ ๊ฒฝ์šฐ maxReplicas๋ฅผ 10์—์„œ 20์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp-deployment
  minReplicas: 1
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

  • ๋ณด์•ˆ ๋ฐ ๊ด€๋ฆฌ. YAML์€ Kubernetes์—์„œ ์‚ฌ๋ฌผ์ด ๋ฐฐํฌ๋˜๋Š” ๋ฐฉ์‹์„ ํ‰๊ฐ€ํ•˜๋Š” ๋ฐ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ฃผ์š” ๋ณด์•ˆ ๋ฌธ์ œ๋Š” ์›Œํฌ๋กœ๋“œ๊ฐ€ ๊ด€๋ฆฌ์ž๊ฐ€ ์•„๋‹Œ ์‚ฌ์šฉ์ž๋กœ ์‹คํ–‰๋˜๋Š”์ง€ ์—ฌ๋ถ€์™€ ๊ด€๋ จ๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ˜ํ…Œ์ŠคํŠธ, YAML/JSON ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ธฐ ๋ฐ ์ •์ฑ… ์—์ด์ „ํŠธ ์—ด๊ธฐ, ์ปจํ…์ŠคํŠธ๋ฅผ ํ™•์ธํ•˜๋Š” ์ •์ฑ… ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ธฐ ๋ณด์•ˆ์ปจํ…์ŠคํŠธ ์›Œํฌ๋กœ๋“œ์—์„œ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ด€๋ฆฌ์ž ๊ถŒํ•œ์œผ๋กœ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž๋Š” ๊ฐ„๋‹จํ•œ ์ •์ฑ…์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ ˆ๊ณ , ์ด๋ ‡๊ฒŒ :

package main

deny[msg] {
  input.kind = "Deployment"
  not input.spec.template.spec.securityContext.runAsNonRoot = true
  msg = "Containers must not run as root"
}

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

ํ™•์žฅ์„ฑ

Kubernetes๋Š” ํ™•์žฅ์„ฑ์ด ๋งค์šฐ ๋›ฐ์–ด๋‚˜๋ฉฐ ๊ฐœ๋ฐœ์ž๋“ค์€ ์ด๋ฅผ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. Pod, ๋ฐฐํฌ ๋“ฑ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฆฌ์†Œ์Šค ์„ธํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. StatefulSets, ๋น„๋ฐ€, ConfigMaps, ๋“ฑ. ์‚ฌ์‹ค, ์‚ฌ์šฉ์ž์™€ ๊ฐœ๋ฐœ์ž๋Š” ์–‘์‹์— ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ๋ฆฌ์†Œ์Šค ์ •์˜.

์˜ˆ๋ฅผ ๋“ค์–ด ๋ฆฌ์†Œ์Šค๋ฅผ ์ •์˜ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ CronTab, ๊ทธ๋Ÿฌ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: crontabs.my.org
spec:
  group: my.org
  versions:
    - name: v1
      served: true
      storage: true
      Schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                cronSpec:
                  type: string
                  pattern: '^(d+|*)(/d+)?(s+(d+|*)(/d+)?){4}$'
                replicas:
                  type: integer
                  minimum: 1
                  maximum: 10
  scope: Namespaced
  names:
    plural: crontabs
    singular: crontab
    kind: CronTab
    shortNames:
    - ct

๋‚˜์ค‘์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ CronTab ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

apiVersion: "my.org/v1"
kind: CronTab
metadata:
  name: my-cron-object
spec:
  cronSpec: "* * * * */5"
  image: my-cron-image
  replicas: 5

Kubernetes์˜ ํ™•์žฅ์„ฑ์„ ์œ„ํ•œ ๋˜ ๋‹ค๋ฅธ ์˜ต์…˜์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž์‹ ์˜ ๋ช…๋ น๋ฌธ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฐ์‚ฐ์ž "์— ๋”ฐ๋ผ ์ž‘๋™ํ•˜๋Š” Kubernetes ํด๋Ÿฌ์Šคํ„ฐ์˜ ํŠน์ˆ˜ ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค.์ œ์–ด ํšŒ๋กœ" ์šด์˜์ž์˜ ๋„์›€์œผ๋กœ ์‚ฌ์šฉ์ž๋Š” Kubernetes API์™€ ์ •๋ณด๋ฅผ ๊ตํ™˜ํ•˜์—ฌ CRD(์‚ฌ์šฉ์ž ์ •์˜ ๋ฆฌ์†Œ์Šค ์ •์˜) ๊ด€๋ฆฌ๋ฅผ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปค๋ฎค๋‹ˆํ‹ฐ์—๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž์‹ ๋งŒ์˜ ์—ฐ์‚ฐ์ž๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ ๋„๊ตฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ค‘ - ์—ฐ์‚ฐ์ž ํ”„๋ ˆ์ž„์›Œํฌ ๊ณผ ์—ฐ์‚ฐ์ž SDK. ์ด SDK๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์‹ ์†ํ•˜๊ฒŒ ์—ฐ์‚ฐ์ž ์ƒ์„ฑ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ฐ˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ช…๋ น์ค„์—์„œ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ operator-sdk new my-operator --repo github.com/myuser/my-operator

๊ทธ๋Ÿฌ๋ฉด YAML ํŒŒ์ผ ๋ฐ Golang ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•˜์—ฌ ์šด์˜์ž๋ฅผ ์œ„ํ•œ ๋ชจ๋“  ์ƒ์šฉ๊ตฌ ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

.
|____cmd
| |____manager
| | |____main.go
|____go.mod
|____deploy
| |____role.yaml
| |____role_binding.yaml
| |____service_account.yaml
| |____operator.yaml
|____tools.go
|____go.sum
|____.gitignore
|____version
| |____version.go
|____build
| |____bin
| | |____user_setup
| | |____entrypoint
| |____Dockerfile
|____pkg
| |____apis
| | |____apis.go
| |____controller
| | |____controller.go

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•„์š”ํ•œ API์™€ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$ operator-sdk add api --api-version=myapp.com/v1alpha1 --kind=MyAppService

$ operator-sdk add controller --api-version=myapp.com/v1alpha1 --kind=MyAppService

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋งˆ์ง€๋ง‰์œผ๋กœ ์—ฐ์‚ฐ์ž๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ์ปจํ…Œ์ด๋„ˆ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

$ operator-sdk build your.container.registry/youruser/myapp-operator

๊ฐœ๋ฐœ์ž๊ฐ€ ๋” ๋งŽ์€ ์ œ์–ด๋ฅผ ์›ํ•˜๋Š” ๊ฒฝ์šฐ Go ํŒŒ์ผ์˜ ์ƒ์šฉ๊ตฌ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ปจํŠธ๋กค๋Ÿฌ์˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์ˆ˜์ •ํ•˜๋ ค๋ฉด ํŒŒ์ผ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. controller.go.

๋˜ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ EVERYWHERE๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์„ ์–ธ์  YAML ํŒŒ์ผ๋งŒ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…๋ น๋ฌธ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Apache Kafka์˜ ์—ฐ์‚ฐ์ž๋Š” ๋Œ€๋žต์ ์œผ๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ. ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ช‡ ๊ฐ€์ง€ ๋ช…๋ น๋งŒ์œผ๋กœ Kubernetes ์œ„์— Kafka ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$ kubectl kudo install zookeeper
$ kubectl kudo install kafka

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‹ค๋ฅธ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

$ kubectl kudo install kafka --instance=my-kafka-name 
            -p ZOOKEEPER_URI=zk-zookeeper-0.zk-hs:2181 
            -p ZOOKEEPER_PATH=/my-path -p BROKER_CPUS=3000m 
            -p BROKER_COUNT=5 -p BROKER_MEM=4096m 
            -p DISK_SIZE=40Gi -p MIN_INSYNC_REPLICAS=3 
            -p NUM_NETWORK_THREADS=10 -p NUM_IO_THREADS=20

ํ˜์‹ 

์ง€๋‚œ ๋ช‡ ๋…„ ๋™์•ˆ ์ฃผ์š” Kubernetes ๋ฆด๋ฆฌ์Šค๋Š” ๋ช‡ ๋‹ฌ๋งˆ๋‹ค ์ถœ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์—ฐ๊ฐ„ XNUMX~XNUMX๊ฐœ์˜ ์ฃผ์š” ๋ฆด๋ฆฌ์Šค๊ฐ€ ์ถœ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์— ๋„์ž…๋œ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์˜ ์ˆ˜๋Š” ์ค„์–ด๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”์šฑ์ด, ์ด ์–ด๋ ค์šด ์‹œ๊ธฐ์—๋„ ๋‘”ํ™”๋  ์กฐ์ง์€ ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ์ƒํ™ฉ์„ ์‚ดํŽด๋ณด์‹ญ์‹œ์˜ค. Github์˜ Kubernetes ํ”„๋กœ์ ํŠธ ํ™œ๋™.

์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ์›Œํฌ๋กœ๋“œ ์ „๋ฐ˜์— ๊ฑธ์ณ ์ž‘์—…์„ ๋ณด๋‹ค ์œ ์—ฐํ•˜๊ฒŒ ํด๋Ÿฌ์Šคํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ”„๋กœ๋•์…˜์— ์ง์ ‘ ๋ฐฐํฌํ•  ๋•Œ ๋” ํฐ ์ œ์–ด๋ ฅ์„ ๋ˆ„๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปค๋ฎค๋‹ˆํ‹ฐ

Kubernetes ์ธ๊ธฐ์˜ ๋˜ ๋‹ค๋ฅธ ์ฃผ์š” ์ธก๋ฉด์€ ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ๊ฐ•์ ์ž…๋‹ˆ๋‹ค. 2015๋…„ ๋ฒ„์ „ 1.0์ด ์ถœ์‹œ๋˜์ž Kubernetes๋Š” ๋‹ค์Œ์˜ ํ›„์›์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. ํด๋ผ์šฐ๋“œ ๋„ค์ดํ‹ฐ๋ธŒ ์ปดํ“จํŒ… ์žฌ๋‹จ.

๋‹ค์–‘ํ•œ ์ปค๋ฎค๋‹ˆํ‹ฐ๋„ ์žˆ์–ด์š” SIG (Special Interest Groups)์€ ํ”„๋กœ์ ํŠธ๊ฐ€ ๋ฐœ์ „ํ•จ์— ๋”ฐ๋ผ Kubernetes์˜ ๋‹ค์–‘ํ•œ ์˜์—ญ์—์„œ ์ž‘์—…ํ•˜๋Š” ๋ฐ ์ค‘์ ์„ ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ทธ๋ฃน์€ ์ง€์†์ ์œผ๋กœ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ Kubernetes ์ž‘์—…์„ ๋”์šฑ ํŽธ๋ฆฌํ•˜๊ณ  ํŽธ๋ฆฌํ•˜๊ฒŒ ๋งŒ๋“ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Cloud Native Foundation์€ ๋˜ํ•œ ์ด ๊ธ€์„ ์“ฐ๋Š” ์‹œ์ ์— ์„ธ๊ณ„ ์ตœ๋Œ€ ๊ทœ๋ชจ์˜ ์˜คํ”ˆ ์†Œ์Šค ์ปจํผ๋Ÿฐ์Šค์ธ CloudNativeCon/KubeCon์„ ์ฃผ์ตœํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ XNUMX๋…„์— XNUMXํšŒ ๊ฐœ์ตœ๋˜๋Š” ์ด ํ–‰์‚ฌ์—๋Š” Kubernetes์™€ ์ƒํƒœ๊ณ„๋ฅผ ๊ฐœ์„ ํ•˜๊ณ  XNUMX๊ฐœ์›”๋งˆ๋‹ค ๋‚˜ํƒ€๋‚˜๋Š” ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ๋ฐฐ์šฐ๊ณ ์ž ํ•˜๋Š” ์ˆ˜์ฒœ ๋ช…์˜ ์ „๋ฌธ๊ฐ€๊ฐ€ ๋ชจ์ž…๋‹ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€ Cloud Native Foundation์€ ๊ธฐ์ˆ ๊ฐ๋…์œ„์›ํšŒ, SIG์™€ ํ•จ๊ป˜ ์‹ ๊ทœ ๋ฐ ๊ธฐ์กด ๊ฒ€ํ†  ํ”„๋กœ์ ํŠธ ํด๋ผ์šฐ๋“œ ์ƒํƒœ๊ณ„์— ์ดˆ์ ์„ ๋งž์ถ˜ ์ž๊ธˆ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ”„๋กœ์ ํŠธ์˜ ๋Œ€๋ถ€๋ถ„์€ Kubernetes์˜ ๊ฐ•์ ์„ ํ–ฅ์ƒํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ, ์‚ฌ๋žŒ๋“ค์ด ํ•จ๊ป˜ ๋ญ‰์น˜๋ฉด์„œ ๋™์‹œ์— ์ƒˆ๋กœ์šด ์‚ฌ๋žŒ๋“ค์„ ํ™˜์˜ํ•˜๋Š” ์ „์ฒด ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ์˜์‹์ ์ธ ๋…ธ๋ ฅ์ด ์—†์—ˆ๋‹ค๋ฉด Kubernetes๋Š” ์ง€๊ธˆ์ฒ˜๋Ÿผ ์„ฑ๊ณตํ•˜์ง€ ๋ชปํ•  ๊ฒƒ์ด๋ผ๊ณ  ๋ฏฟ์Šต๋‹ˆ๋‹ค.

๋ฏธ๋ž˜

์•ž์œผ๋กœ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ์ฃผ์š” ๊ณผ์ œ ์ค‘ ํ•˜๋‚˜๋Š” ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ์ธํ”„๋ผ๊ฐ€ ์•„๋‹Œ ์ฝ”๋“œ ์ž์ฒด์˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŠธ๋ Œ๋“œ์— ๋ถ€ํ•ฉํ•˜๋Š” ์„œ๋ฒ„๋ฆฌ์Šค ์•„ํ‚คํ…์ฒ˜ ํŒจ๋Ÿฌ๋‹ค์ž„, ์ด๋Š” ์˜ค๋Š˜๋‚  ์ตœ๊ณ ์˜ ๊ฒƒ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๊ณ ๊ธ‰ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์›์–ด๋ฏผ ะธ ์˜คํ”ˆํŒŒ์Šค, Kubernetes๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ๋ฐœ์ž๋กœ๋ถ€ํ„ฐ ์ธํ”„๋ผ๋ฅผ ์ถ”์ƒํ™”ํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ธฐ์‚ฌ์—์„œ ์šฐ๋ฆฌ๋Š” Kubernetes์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ํ‘œ๋ฉด์ ์œผ๋กœ๋งŒ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์ด๋Š” ๋น™์‚ฐ์˜ ์ผ๊ฐ์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค. Kubernetes ์‚ฌ์šฉ์ž๋Š” ์›ํ•˜๋Š” ๋Œ€๋กœ ๋‹ค์–‘ํ•œ ๋ฆฌ์†Œ์Šค, ๊ธฐ๋Šฅ ๋ฐ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

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