๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“š Book Review/๐Ÿ“˜ Kubernetes Best Practice

[Kubernetes Best Practice] 13. ์™ธ๋ถ€ ์„œ๋น„์Šค์™€ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํ†ตํ•ฉ

by Seongpyo Hong 2021. 4. 4.

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

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


์ด๋ฒˆ ์žฅ์—์„œ๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ์™€ ์™ธ๋ถ€ ์„œ๋น„์Šค๋ฅผ ํ†ตํ•ฉํ•˜๋Š” ์ƒํ™ฉ์— ๋Œ€ํ•˜์—ฌ ๋‹ค๋ฃจ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์—์„œ ์šด์˜๋˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์„œ๋น„์Šค๋Š” VM ํ˜น์€ ๋ฌผ๋ฆฌ ๋จธ์‹ ์—์„œ ์‹คํ–‰๋˜๋Š” ์„œ๋น„์Šค์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜, ๋‹ค๋ฅธ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šค์— ์กด์žฌํ•˜๋Š” ์„œ๋น„์Šค์™€ ์—ฐ๊ฒฐ๊ดผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. 


์™ธ๋ถ€ ์„œ๋น„์Šค ์‚ฌ์šฉ

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

๊ณ ์ •๋œ IP๋ฅผ ๊ฐ€์ง€๋Š” ์„œ๋น„์Šค

๊ณ ์ •๋œ IP๋ฅผ ๊ฐ€์ง€๋Š” ์„œ๋น„์Šค์˜ ๊ฒฝ์šฐ, Selector๊ฐ€ ์—†๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ํด๋Ÿฌ์Šคํ„ฐ DNS๋ฅผ ํ†ตํ•ด ๊ฒ€์ƒ‰๋˜๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์„œ๋น„์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Service.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

ํ•ด๋‹น ์„œ๋น„์Šค์— ๋Œ€ํ•œ Endpoint๋กœ ์™ธ๋ถ€ ์„œ๋น„์Šค์˜ IP๋ฅผ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Endpoint.yaml

apiVersion: v1
kind: Endpoints
metadata:
  name: my-service
subsets:
  - addresses:
      - ip: 192.0.2.42
    ports:
      - port: 9376

 

๋™์ ์ธ IP๋ฅผ ๊ฐ€์ง€๋Š” ์„œ๋น„์Šค

ํด๋ผ์šฐ๋“œ ํ™˜๊ฒฝ์— ๋ฐฐํฌ๋˜์–ด์žˆ๋Š” ์„œ๋น„์Šค์™€ ๊ฐ™์ด ๋™์ ์ธ IP๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์„œ๋น„์Šค์˜ ๊ฒฝ์šฐ์—๋Š” ์œ„์˜ ๋ฐฉ๋ฒ•์ฒ˜๋Ÿผ IP๋ฅผ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” CNAME ๋ ˆ์ฝ”๋“œ ๊ธฐ๋ฐ˜ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. CNAME ๋ ˆ์ฝ”๋“œ๋Š” DNS ์ฃผ์†Œ์™€ ์„œ๋ฒ„์˜ IP๊ฐ€ ์ง์ ‘ ๋งคํ•‘๋˜๋Š” A ๋ ˆ์ฝ”๋“œ์™€๋Š” ๋‹ฌ๋ฆฌ ๋˜ ๋‹ค๋ฅธ DNS ์ฃผ์†Œ๋กœ ๋งคํ•‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. 

NAME                     TYPE                VALUE
--------------------------------------------------
bar.example.com.   CNAME            foo.example.com.
foo.example.com.   A                      192.0.2.23

์ฆ‰, ์„œ๋น„์Šค๊ฐ€ ๋‹ค๋ฅธ DNS ์ฃผ์†Œ๋กœ ๋งคํ•‘๋˜๋Š” CNAME ๋ ˆ์ฝ”๋“œ ์„œ๋น„์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋™์ ์œผ๋กœ IP์ฃผ์†Œ๊ฐ€ ๋ณ€ํ•˜๋Š” ์™ธ๋ถ€์„œ๋น„์Šค์— ์•ˆ์ •์ ์œผ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•œ ์˜ˆ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

 

์™ธ๋ถ€ DNS๋ฅผ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๊ฐ€ ํ•ด์„ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ

์™ธ๋ถ€ DNS ์ด๋ฆ„์ด ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ ๋„คํŠธ์›Œํฌ ๋ฒ”์œ„๋ณด๋‹ค ํฐ ๊ฒฝ์šฐ์—๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๊ฐ€ ํ•ด์„ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” DNS ์ด๋ฆ„์„ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค DNS์˜ ์„ค์ •์„ ๋ณ€๊ฒฝํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด v1.12.0 ์ดํ›„๋ถ€ํ„ฐ kube-dns๊ฐ€ ์•„๋‹Œ CoreDNS๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์— ๋Œ€ํ•œ ์„ค์ •์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. CoreDNS ์„œ๋ฒ„๋Š” kube-system ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— coredns๋ผ๋Š” ConfigMap์„ ํ†ตํ•ด DNS ์„œ๋ฒ„ ์„ค์ •์ธ Corefile์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ DNS ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๋„๋ก ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
            lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
            ttl 30
        }
        prometheus :9153
        cache 30
        loop
        reload
        loadbalance
        forward . 172.16.0.1
    }    
    consul.local:53 {
        errors
        cache 30
        forward . 10.150.0.1
    }

์—ฌ๊ธฐ์„œ forward์™€ consul.local์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • consul.local : ๋งŒ์•ฝ 10.150.0.1์— ์œ„์น˜ํ•œ Consul DNS ์„œ๋ฒ„๊ฐ€ ์žˆ๊ณ , ์ด์— ๋Œ€ํ•ด ์ ๋ฏธ์‚ฌ๊ฐ€ .consul.local์ธ ๊ฒฝ์šฐ DNS ์กฐํšŒ๋ฅผ Consul ์„œ๋ฒ„์—์„œ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • forward : ๊ธฐ๋ณธ์ ์œผ๋กœ ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด๋ถ€์˜ DNS์—์„œ ์ฐพ์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์ „์— ์ •์˜๋œ /etc/reslov.conf์—์„œ ์ฐพ๊ฒŒ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์™ธ๋ถ€ DNS ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ (์œ„์— ์˜ˆ์ œ์—์„œ๋Š” 172.16.0.1์ด๋ผ๊ณ  ๊ฐ€์ •) forward์— ํ•ด๋‹น DNS ์„œ๋ฒ„ ์ฃผ์†Œ๋ฅผ ๋ช…์‹œํ•จ์œผ๋กœ์จ ์™ธ๋ถ€ DNS ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„œ๋น„์Šค ๋…ธ์ถœ

ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด๋ถ€์—์„œ ์™ธ๋ถ€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์™ธ๋ถ€์—์„œ ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด๋ถ€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ์™ธ๋ถ€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค Pod๊ฐ„์— ๋ผ์šฐํŒ… ์„ค์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๋ถ€ ๋กœ๋“œ๋ฐธ๋Ÿฐ์„œ ์‚ฌ์šฉ (ํด๋ผ์šฐ๋“œ)

๊ฐ€์žฅ ์†์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ๋‚ด๋ถ€ ๋กœ๋“œ๋ฐธ๋Ÿฐ์„œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ํด๋ผ์šฐ๋“œ ํ”„๋กœ๋ฐ”์ด๋”๋Š” ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ ํƒ€์ž…์˜ ์„œ๋น„์Šค๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€ ํŠธ๋ž˜ํ”ฝ์„ ํด๋Ÿฌ์Šคํ„ฐ Pod์„ ๋…ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ VPC ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ์„œ๋น„์Šค์˜ ๊ฒฝ์šฐ ์™ธ๋ถ€๋กœ ๋…ธ์ถœํ•˜๋Š” ๊ฒƒ์€ ๋ณด์•ˆ์ƒ ์œ„ํ—˜์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ๋‚ด๋ถ€ ๋กœ๋“œ๋ฐธ๋Ÿฐ์„œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ VPC์— ํ• ๋‹น๋˜๋Š” ๋‚ด๋ถ€ ๋กœ๋“œ๋ฐธ๋Ÿฐ์„œ๋ฅผ ์„ค์ •ํ•จ์œผ๋กœ์จ VPC์—๋งŒ ๋…ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ผ์šฐ๋“œ ํ”„๋กœ๋ฐ”์ด๋”์— ๋”ฐ๋ผ  ์ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • AWS : service.beta.kubernetes.io/aws-load-balancer-internal: "true" ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€
  • GCP : networking.gke.io/load-balancer-type: "Internal" ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€ 

NodePort ์‚ฌ์šฉ (์˜จํ”„๋ ˆ๋ฏธ์Šค)

์˜จํ”„๋ ˆ๋ฏธ์Šค์— ๊ตฌ์ถ•๋œ ์„œ๋ฒ„์˜ ๊ฒฝ์šฐ์—๋Š” ๋‚ด๋ถ€ ๋กœ๋“œ๋ฐธ๋Ÿฐ์„œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด ๋ชจ๋“  ๋…ธ๋“œ์˜ ํ•ด๋‹น ํฌํŠธ๋ฅผ ๊ฐœ๋ฐฉํ•˜๋Š” NodePort ํƒ€์ž…์˜ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ ์™ธ๋ถ€์—์„œ๋Š” node-ip:port ํ˜•ํƒœ๋กœ ์„œ๋น„์Šค๋ฅผ ๋…ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ๊ฐ€์ƒ IP๋ฅผ ๊ฐ€์ง€๋Š” ๋กœ๋“œ๋ฐธ๋Ÿฐ์„œ๋ฅผ ๊ตฌ์ถ•ํ•ด ์„œ๋น„์Šค๋ฅผ ๋…ธ์ถœํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

๋Œ“๊ธ€