์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํ™•์žฅ

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์ž‘์—… ํ™˜๊ฒฝ์˜ ์š”๊ตฌ์— ๋งž๊ฒŒ ์กฐ์ •ํ•˜๋Š” ๊ณ ๊ธ‰ ๊ณผ์ •์„ ์ดํ•ดํ•œ๋‹ค.

1 - ํ™•์žฅ API ์„œ๋ฒ„ ์„ค์ •

์• ๊ทธ๋ฆฌ๊ฒŒ์ด์…˜ ๋ ˆ์ด์–ด(aggregation layer)์™€ ์ž‘๋™ํ•˜๋„๋ก ํ™•์žฅ API ์„œ๋ฒ„๋ฅผ ์„ค์ •ํ•˜๋ฉด ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API ์„œ๋ฒ„๋ฅผ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์˜ ํ•ต์‹ฌ API์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹Œ ์ถ”๊ฐ€ API๋กœ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

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

๋ฒ„์ „ ํ™•์ธ์„ ์œ„ํ•ด์„œ, ๋‹ค์Œ ์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ kubectl version.

์• ๊ทธ๋ฆฌ๊ฒŒ์ด์…˜ ๋ ˆ์ด์–ด์™€ ์ž‘๋™ํ•˜๋„๋ก ํ™•์žฅ API ์„œ๋ฒ„ ์„ค์ •ํ•˜๊ธฐ

๋‹ค์Œ ๋‹จ๊ณ„๋Š” ํ™•์žฅ API ์„œ๋ฒ„๋ฅผ ๋†’์€ ์ˆ˜์ค€ ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•œ๋‹ค. ์ด ๋‹จ๊ณ„๋Š” YAML ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ์ƒ๊ด€์—†์ด ์ ์šฉ๋œ๋‹ค. ๋‘˜ ์‚ฌ์ด์˜ ์ฐจ์ด์ ์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์‹๋ณ„ํ•˜๋ ค๊ณ  ์‹œ๋„ํ•œ๋‹ค. YAML ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ์˜ˆ๋ฅผ ๋ณด๋ ค๋ฉด, ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ์—์„œ sample-apiserver๋ฅผ ์ฐธ๊ณ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋˜๋Š”, apiserver-builder์™€ ๊ฐ™์€ ๊ธฐ์กด์˜ ํƒ€์‚ฌ ์†”๋ฃจ์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šค์ผˆ๋ ˆํ†ค(skeleton)์„ ์ƒ์„ฑํ•˜๊ณ  ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๋ชจ๋‘ ์ž๋™ํ™”ํ•ด์•ผ ํ•œ๋‹ค.

  1. API์„œ๋น„์Šค(APIService) API๊ฐ€ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค(--runtime-config ํ™•์ธ). ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ์ผ๋ถ€๋Ÿฌ ํ•ด์ œํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ๊ธฐ๋ณธ์ ์œผ๋กœ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  2. API์„œ๋น„์Šค ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ํด๋Ÿฌ์Šคํ„ฐ ๊ด€๋ฆฌ์ž๊ฐ€ ์ž‘์„ฑํ•˜๋„๋ก RBAC ๊ทœ์น™์„ ์ž‘์„ฑํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. (API ํ™•์žฅ์€ ์ „์ฒด ํด๋Ÿฌ์Šคํ„ฐ์— ์˜ํ–ฅ์„ ์ฃผ๊ธฐ ๋•Œ๋ฌธ์—, ์šด์˜ ์ค‘์ธ ํด๋Ÿฌ์Šคํ„ฐ์—์„œ API ํ™•์žฅ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ/๊ฐœ๋ฐœ/๋””๋ฒ„๊น…์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.)
  3. ํ™•์žฅ API ์„œ๋น„์Šค๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  4. HTTPS๋ฅผ ์œ„ํ•ด ํ™•์žฅ API ์„œ๋ฒ„๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์„œ๋ฒ„ ์ธ์ฆ์„œ์— ์„œ๋ช…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  CA ์ธ์ฆ์„œ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ฐ€์ ธ์˜จ๋‹ค.
  5. HTTPS๋ฅผ ์œ„ํ•ด API ์„œ๋ฒ„๊ฐ€ ์‚ฌ์šฉํ•  ์„œ๋ฒ„ ์ธ์ฆ์„œ/ํ‚ค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ด ์ธ์ฆ์„œ๋Š” ์œ„์˜ CA ์ธ์ฆ์„œ์— ์˜ํ•ด ์„œ๋ช…ํ•ด์•ผ ํ•œ๋‹ค. ๋˜ํ•œ Kube DNS ์ด๋ฆ„์˜ CN์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค. ์ด๊ฒƒ์€ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์„œ๋น„์Šค์—์„œ ํŒŒ์ƒ๋˜์—ˆ์œผ๋ฉฐ <service name>.<service name namespace>.svc ํ˜•์‹์ด๋‹ค.
  6. ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ์„œ๋ฒ„ ์ธ์ฆ์„œ/ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์‹œํฌ๋ฆฟ์„ ์ƒ์„ฑํ•œ๋‹ค.
  7. ํ™•์žฅ API ์„œ๋ฒ„์— ๋Œ€ํ•œ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‹œํฌ๋ฆฟ์„ ๋ณผ๋ฅจ์œผ๋กœ ๋กœ๋“œํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. ํ™•์žฅ API ์„œ๋ฒ„์˜ ์ž‘๋™ํ•˜๋Š”(working) ์ด๋ฏธ์ง€์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ํฌํ•จํ•ด์•ผ ํ•œ๋‹ค. ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋Š” ๋„ค์ž„์ŠคํŽ˜์ด์Šค์—๋„ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  8. ํ™•์žฅ API ์„œ๋ฒ„๊ฐ€ ํ•ด๋‹น ๋ณผ๋ฅจ์—์„œ ํ•ด๋‹น ์ธ์ฆ์„œ๋ฅผ ๋กœ๋“œํ•˜๊ณ  HTTPS ํ•ธ๋“œ์…ฐ์ดํฌ์— ์‚ฌ์šฉ๋˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
  9. ๋„ค์ž„์ŠคํŽ˜์ด์Šค์—์„œ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์„œ๋น„์Šค ์–ด์นด์šดํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  10. ๋ฆฌ์†Œ์Šค์— ํ—ˆ์šฉํ•˜๋ ค๋Š” ์ž‘์—…์— ๋Œ€ํ•œ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ ๋กค(role)์„ ์ƒ์„ฑํ•œ๋‹ค.
  11. ๋„ค์ž„์ŠคํŽ˜์ด์Šค์˜ ์„œ๋น„์Šค ์–ด์นด์šดํŠธ์—์„œ ๋ฐฉ๊ธˆ ๋งŒ๋“  ํด๋Ÿฌ์Šคํ„ฐ ๋กค๋กœ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ ๋กค ๋ฐ”์ธ๋”ฉ์„ ์ƒ์„ฑํ•œ๋‹ค.
  12. ๋„ค์ž„์ŠคํŽ˜์ด์Šค์˜ ์„œ๋น„์Šค ์–ด์นด์šดํŠธ์—์„œ system:auth-delegator ํด๋Ÿฌ์Šคํ„ฐ ๋กค๋กœ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ ๋กค ๋ฐ”์ธ๋”ฉ์„ ๋งŒ๋“ค์–ด ์ธ์ฆ ๊ฒฐ์ •์„ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํ•ต์‹ฌ API ์„œ๋ฒ„์— ์œ„์ž„ํ•œ๋‹ค.
  13. ๋„ค์ž„์ŠคํŽ˜์ด์Šค์˜ ์„œ๋น„์Šค ์–ด์นด์šดํŠธ์—์„œ extension-apiserver-authentication-reader ๋กค๋กœ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋กค ๋ฐ”์ธ๋”ฉ์„ ์ƒ์„ฑํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ™•์žฅ API ์„œ๋ฒ„๊ฐ€ extension-apiserver-authentication ์ปจํ”ผ๊ทธ๋งต(configmap)์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
  14. ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API ์„œ๋น„์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์œ„์˜ CA ์ธ์ฆ์„œ๋Š” base64๋กœ ์ธ์ฝ”๋”ฉ๋˜์–ด, ์ƒˆ๋กœ์šด ๋ผ์ธ์ด ์ œ๊ฑฐ๋˜๊ณ  API ์„œ๋น„์Šค์—์„œ spec.caBundle๋กœ ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•œ๋‹ค. ์ด๊ฒƒ์€ namespaced๊ฐ€ ์•„๋‹ˆ์–ด์•ผ ํ•œ๋‹ค. kube-aggregator API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, base64 ์ธ์ฝ”๋”ฉ์ด ์ˆ˜ํ–‰๋˜๋ฏ€๋กœ PEM ์ธ์ฝ”๋”ฉ๋œ CA ๋ฒˆ๋“ค๋งŒ ํ†ต๊ณผํ•œ๋‹ค.
  15. kubectl์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌ์†Œ์Šค๋ฅผ ์–ป๋Š”๋‹ค. kubectl์„ ์‹คํ–‰ํ•˜๋ฉด, "No resources found."๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค. ์ด ๋ฉ”์‹œ์ง€๋Š” ๋ชจ๋“  ๊ฒƒ์ด ์ž‘๋™๋์ง€๋งŒ ํ˜„์žฌ ํ•ด๋‹น ๋ฆฌ์†Œ์Šค ์œ ํ˜•์˜ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š์•˜์Œ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

๋‹ค์Œ ๋‚ด์šฉ

2 - ๋‹ค์ค‘ ์Šค์ผ€์ค„๋Ÿฌ ์„ค์ •

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

์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์€ ํ•ด๋‹น ๋ฌธ์„œ์—์„œ ๋‹ค๋ฃจ์ง€ ์•Š๋Š”๋‹ค. kube-scheduler ๊ตฌํ˜„์„ ๋‹ค๋ฃจ๋Š” ๊ณต์‹ ์˜ˆ์‹œ๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์†Œ์Šค ๋””๋ ‰ํ† ๋ฆฌ์— ์žˆ๋Š” pkg/scheduler ๋ฅผ ์ฐธ๊ณ ํ•œ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

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

๋ฒ„์ „ ํ™•์ธ์„ ์œ„ํ•ด์„œ, ๋‹ค์Œ ์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ kubectl version.

์Šค์ผ€์ค„๋Ÿฌ ํŒจํ‚ค์ง•

์Šค์ผ€์ค„๋Ÿฌ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋กœ ํŒจํ‚ค์ง•ํ•œ๋‹ค. ํ•ด๋‹น ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ๊ธฐ๋ณธ ์Šค์ผ€์ค„๋Ÿฌ (kube-scheduler)๋ฅผ ๋‘ ๋ฒˆ์งธ ์Šค์ผ€์ค„๋Ÿฌ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. GitHub ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์†Œ์Šค์ฝ”๋“œ๋ฅผ ํด๋ก ํ•˜๊ณ  ์†Œ์Šค๋ฅผ ๋นŒ๋“œํ•˜์ž.

git clone https://github.com/kubernetes/kubernetes.git
cd kubernetes
make

kube-scheduler ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ๋‹ด์€ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์ž. ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œ ํ•˜๊ธฐ ์œ„ํ•œ Dockerfile์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

FROM busybox
ADD ./_output/local/bin/linux/amd64/kube-scheduler /usr/local/bin/kube-scheduler

ํŒŒ์ผ์„ Dockerfile๋กœ ์ €์žฅํ•˜๊ณ  ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œํ•œ ํ›„ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋กœ ํ‘ธ์‹œํ•˜์ž. ํ•ด๋‹น ์˜ˆ์ œ์—์„œ๋Š” ์ด๋ฏธ์ง€๋ฅผ Google Container Registry (GCR)๋กœ ํ‘ธ์‹œํ•˜๊ณ  ์žˆ๋‹ค. ์ด์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ GCR ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์ž.

docker build -t gcr.io/my-gcp-project/my-kube-scheduler:1.0 .
gcloud docker -- push gcr.io/my-gcp-project/my-kube-scheduler:1.0

์Šค์ผ€์ค„๋Ÿฌ์—์„œ ์‚ฌ์šฉํ•  ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋””ํ”Œ๋กœ์ด๋จผํŠธ ์ •์˜ํ•˜๊ธฐ

์ด์ œ ์Šค์ผ€์ค„๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๊ฐ€ ์žˆ์œผ๋‹ˆ, ํ•ด๋‹น ์ด๋ฏธ์ง€๋ฅผ ํฌํ•จํ•˜๋Š” ํŒŒ๋“œ ๊ตฌ์„ฑ์„ ์ƒ์„ฑํ•˜๊ณ  ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด์—์„œ ์‹คํ–‰ํ•ด๋ณด์ž. ํ•ด๋‹น ์˜ˆ์ œ์—์„œ๋Š”, ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด์— ์ง์ ‘ ํŒŒ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋Œ€์‹ ์— ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค. ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋Š” ๋ ˆํ”Œ๋ฆฌ์นด ์…‹์„ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์ด๋Š” ๋˜ ํŒŒ๋“œ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์Šค์ผ€์ค„๋Ÿฌ์— ๋Œ€ํ•œ ํšŒ๋ณต ํƒ„๋ ฅ์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค. ๋‹ค์Œ์€ ๋””ํ”Œ๋กœ์ด๋จผํŠธ์— ๋Œ€ํ•œ ๊ตฌ์„ฑ ํŒŒ์ผ์ด๋‹ค. ์ด ํŒŒ์ผ์„ my-scheduler.yaml์œผ๋กœ ์ €์žฅํ•œ๋‹ค.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-scheduler
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: my-scheduler-as-kube-scheduler
subjects:
- kind: ServiceAccount
  name: my-scheduler
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: system:kube-scheduler
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: my-scheduler-as-volume-scheduler
subjects:
- kind: ServiceAccount
  name: my-scheduler
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: system:volume-scheduler
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-scheduler-config
  namespace: kube-system
data:
  my-scheduler-config.yaml: |
    apiVersion: kubescheduler.config.k8s.io/v1
    kind: KubeSchedulerConfiguration
    profiles:
      - schedulerName: my-scheduler
    leaderElection:
      leaderElect: false    
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    component: scheduler
    tier: control-plane
  name: my-scheduler
  namespace: kube-system
spec:
  selector:
    matchLabels:
      component: scheduler
      tier: control-plane
  replicas: 1
  template:
    metadata:
      labels:
        component: scheduler
        tier: control-plane
        version: second
    spec:
      serviceAccountName: my-scheduler
      containers:
      - command:
        - /usr/local/bin/kube-scheduler
        - --config=/etc/kubernetes/my-scheduler/my-scheduler-config.yaml
        image: gcr.io/my-gcp-project/my-kube-scheduler:1.0
        livenessProbe:
          httpGet:
            path: /healthz
            port: 10259
            scheme: HTTPS
          initialDelaySeconds: 15
        name: kube-second-scheduler
        readinessProbe:
          httpGet:
            path: /healthz
            port: 10259
            scheme: HTTPS
        resources:
          requests:
            cpu: '0.1'
        securityContext:
          privileged: false
        volumeMounts:
          - name: config-volume
            mountPath: /etc/kubernetes/my-scheduler
      hostNetwork: false
      hostPID: false
      volumes:
        - name: config-volume
          configMap:
            name: my-scheduler-config

ํ•ด๋‹น ๋งค๋‹ˆํŽ˜์ŠคํŠธ์—์„œ๋Š” KubeSchedulerConfiguration์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•  ์Šค์ผ€์ค„๋Ÿฌ์˜ ํŠน์„ฑ์„ ์ •์˜ํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ์„ค์ •์€ ์ดˆ๊ธฐํ™” ๊ณผ์ •์—์„œ --config ์˜ต์…˜์„ ํ†ตํ•ด kube-scheduler์—๊ฒŒ ์ „๋‹ฌ๋œ๋‹ค. ํ•ด๋‹น ๊ตฌ์„ฑ ํŒŒ์ผ์€ my-scheduler-config ์ปจํ”ผ๊ทธ๋งต์— ์ €์žฅ๋œ๋‹ค. my-scheduler ๋””ํ”Œ๋กœ์ด๋จผํŠธ์˜ ํŒŒ๋“œ์—์„œ๋Š” my-scheduler-config ์ปจํ”ผ๊ทธ๋งต์„ ๋ณผ๋ฅจ์œผ๋กœ ๋งˆ์šดํŠธ ์‹œํ‚จ๋‹ค.

์•ž์„œ ์–ธ๊ธ‰ํ•œ ์Šค์ผ€์ค„๋Ÿฌ ๊ตฌ์„ฑ์—์„œ๋Š”, ๊ตฌํ˜„ํ•œ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ KubeSchedulerProfile์˜ ํ˜•์‹์œผ๋กœ ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋œ๋‹ค.

๋˜ํ•œ, kube-scheduler์™€ ๊ฐ™์€ ๊ถŒํ•œ์„ ๋ถ€์—ฌ๋ฐ›๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ „์šฉ ์„œ๋น„์Šค ์–ด์นด์šดํŠธ my-scheduler๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ•ด๋‹น ์„œ๋น„์Šค ์–ด์นด์šดํŠธ๋ฅผ ํด๋Ÿฌ์Šคํ„ฐ๋กค system:kube-scheduler์™€ ๋ฐ”์ธ๋”ฉํ•ด์•ผ ํ•œ๋‹ค.

์ด์™ธ์˜ ์ปค๋งจ๋“œ ๋ผ์ธ ์ธ์ž์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์€ kube-scheduler ๋ฌธ์„œ์—์„œ ์ฐธ๊ณ ํ•˜๊ณ  ์ด์™ธ์˜ ์‚ฌ์šฉ์ž ์ •์˜ kube-scheduler ๊ตฌ์„ฑ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์€ ์Šค์ผ€์ค„๋Ÿฌ ๊ตฌ์„ฑ ๋ ˆํผ๋Ÿฐ์Šค ์—์„œ ์ฐธ๊ณ ํ•œ๋‹ค.

๋‘ ๋ฒˆ์งธ ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ์‹คํ–‰ํ•˜๊ธฐ

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ, ์œ„์˜ ๊ตฌ์„ฑ ํŒŒ์ผ์—์„œ ๋ช…์‹œํ•œ ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋ฅผ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด์— ์ƒ์„ฑํ•œ๋‹ค.

kubectl create -f my-scheduler.yaml

์Šค์ผ€์ค„๋Ÿฌ ํŒŒ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.

kubectl get pods --namespace=kube-system
NAME                                           READY     STATUS    RESTARTS   AGE
....
my-scheduler-lnf4s-4744f                       1/1       Running   0          2m
...

๊ธฐ๋ณธ kube-scheduler ํŒŒ๋“œ์™€ ๋”๋ถˆ์–ด, my-scheduler ํŒŒ๋“œ๊ฐ€ ์‹คํ–‰("Running")๋˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ชฉ๋ก์—์„œ ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

๋ฆฌ๋” ์„ ์ถœ ํ™œ์„ฑํ™”

๋ฆฌ๋” ์„ ์ถœ์ด ํ™œ์„ฑํ™”๋œ ์ƒํƒœ๋กœ ๋‹ค์ค‘ ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

my-scheduler-config ์ปจํ”ผ๊ทธ๋งต์˜ YAML ํŒŒ์ผ์—์„œ KubeSchedulerConfiguration์˜ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ•„๋“œ๋“ค์„ ๊ฐฑ์‹ ํ•œ๋‹ค.

  • leaderElection.leaderElect ๋ฅผ true ๋กœ
  • leaderElection.resourceNamespace ๋ฅผ <lock-object-namespace> ๋กœ
  • leaderElection.resourceName ์„ <lock-object-name> ์œผ๋กœ

ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด์— RBAC๊ฐ€ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋Š” ์ƒํƒœ๋ผ๋ฉด, system:kube-scheduler ํด๋Ÿฌ์Šคํ„ฐ๋กค์„ ์—…๋ฐ์ดํŠธ ํ•ด์•ผ ํ•œ๋‹ค. ๋‹ค์Œ ์˜ˆ์‹œ์™€ ๊ฐ™์ด, ๊ตฌํ˜„ํ•œ ์Šค์ผ€์ค„๋Ÿฌ์˜ ์ด๋ฆ„์„ endpoints์™€ leases ๋ฆฌ์†Œ์Šค์— ์ ์šฉ๋˜๋Š” ๋ฃฐ์˜ resourceNames์— ์ถ”๊ฐ€ํ•˜์ž.

kubectl edit clusterrole system:kube-scheduler
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:kube-scheduler
rules:
  - apiGroups:
      - coordination.k8s.io
    resources:
      - leases
    verbs:
      - create
  - apiGroups:
      - coordination.k8s.io
    resourceNames:
      - kube-scheduler
      - my-scheduler
    resources:
      - leases
    verbs:
      - get
      - update
  - apiGroups:
      - ""
    resourceNames:
      - kube-scheduler
      - my-scheduler
    resources:
      - endpoints
    verbs:
      - delete
      - get
      - patch
      - update

ํŒŒ๋“œ์˜ ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ์ง€์ •ํ•˜๊ธฐ

์ด์ œ ๋‘ ๋ฒˆ์งธ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์‹คํ–‰๋˜๊ณ  ์žˆ์œผ๋‹ˆ, ํŒŒ๋“œ๋ฅผ ๋ช‡ ๊ฐœ ์ƒ์„ฑํ•˜์—ฌ ๊ธฐ๋ณธ ์Šค์ผ€์ค„๋Ÿฌ ๋˜๋Š” ์ƒˆ๋กœ ๋ฐฐ์น˜ํ•œ ์Šค์ผ€์ค„๋Ÿฌ์— ์˜ํ•ด ์Šค์ผ€์ค„๋ง์ด ๋˜๋„๋ก ์„ค์ •ํ•ด ๋ณด์ž. ํŠน์ • ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ํŒŒ๋“œ๋ฅผ ์Šค์ผ€์ค„๋งํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•ด๋‹น ํŒŒ๋“œ์˜ ๋ช…์„ธ์— ํ•ด๋‹น ์Šค์ผ€์ค„๋Ÿฌ์˜ ์ด๋ฆ„์„ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค. ์„ธ ๊ฐ€์ง€ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ•ด ๋ณด์ž.

  • ์Šค์ผ€์ค„๋Ÿฌ ์ด๋ฆ„์„ ๋ช…์‹œํ•˜์ง€ ์•Š์€ ํŒŒ๋“œ ๋ช…์„ธ

    apiVersion: v1
      kind: Pod
      metadata:
        name: no-annotation
        labels:
          name: multischeduler-example
      spec:
        containers:
        - name: pod-with-no-annotation-container
          image: registry.k8s.io/pause:2.0

    ์Šค์ผ€์ค„๋Ÿฌ ์ด๋ฆ„์„ ์ œ๊ณต๋ฐ›์ง€ ๋ชปํ–ˆ๋‹ค๋ฉด, ํŒŒ๋“œ๋Š” ์ž๋™์œผ๋กœ ๊ธฐ๋ณธ ์Šค์ผ€์ค„๋Ÿฌ์— ์˜ํ•ด ์Šค์ผ€์ค„๋ง์ด ์ˆ˜ํ–‰๋œ๋‹ค.

    ํ•ด๋‹น ํŒŒ์ผ์„ pod1.yaml๋กœ ์ €์žฅํ•˜๊ณ  ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ์— ์ œ์ถœํ•ด ๋ณด์ž.

    kubectl create -f pod1.yaml
    
  • default-scheduler๋ฅผ ๋ช…์‹œํ•œ ํŒŒ๋“œ ๋ช…์„ธ

    apiVersion: v1
      kind: Pod
      metadata:
        name: annotation-default-scheduler
        labels:
          name: multischeduler-example
      spec:
        schedulerName: default-scheduler
        containers:
        - name: pod-with-default-annotation-container
          image: registry.k8s.io/pause:2.0
      

    spec.schedulerName์˜ ๊ฐ’์œผ๋กœ ์Šค์ผ€์ค„๋Ÿฌ ์ด๋ฆ„์„ ์ œ๊ณตํ•จ์œผ๋กœ์จ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์ •ํ•ด์ง„๋‹ค. ์ด์™€ ๊ฐ™์€ ๊ฒฝ์šฐ์—์„œ๋Š”, ๊ธฐ๋ณธ ์Šค์ผ€์ค„๋Ÿฌ์˜ ์ด๋ฆ„์ธ default-scheduler๋ฅผ ๋ช…์‹œํ•˜๊ณ  ์žˆ๋‹ค.

    ํ•ด๋‹น ํŒŒ์ผ์„ pod2.yaml๋กœ ์ €์žฅํ•˜๊ณ  ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ์— ์ œ์ถœํ•ด ๋ณด์ž.

    kubectl create -f pod2.yaml
    
  • my-scheduler๋ฅผ ๋ช…์‹œํ•œ ํŒŒ๋“œ ๋ช…์„ธ

    apiVersion: v1
      kind: Pod
      metadata:
        name: annotation-second-scheduler
        labels:
          name: multischeduler-example
      spec:
        schedulerName: my-scheduler
        containers:
        - name: pod-with-second-annotation-container
          image: registry.k8s.io/pause:2.0
      

    ์ด์™€ ๊ฐ™์€ ๊ฒฝ์šฐ์—์„œ๋Š”, ์ง์ ‘ ๋ฐฐ์น˜ํ•œ ์Šค์ผ€์ค„๋Ÿฌ - my-scheduler๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ํŒŒ๋“œ์˜ ์Šค์ผ€์ค„๋ง์ด ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ช…์‹œํ•˜๊ณ  ์žˆ๋‹ค. spec.schedulerName์˜ ๊ฐ’์€ KubeSchedulerProfile ๋งคํ•‘์˜ schedulerName ํ•„๋“œ์™€ ์ผ์น˜ํ•ด์•ผ ํ•œ๋‹ค.

    ํ•ด๋‹น ํŒŒ์ผ์„ pod3.yaml๋กœ ์ €์žฅํ•˜๊ณ  ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ์— ์ œ์ถœํ•ด ๋ณด์ž.

    kubectl create -f pod3.yaml
    

    ์„ธ ๊ฐœ์˜ ํŒŒ๋“œ๊ฐ€ ๋ชจ๋‘ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ๋ณด์ž.

    kubectl get pods
    

ํŒŒ๋“œ๊ฐ€ ์›ํ•˜๋Š” ์Šค์ผ€์ค„๋Ÿฌ์— ์˜ํ•ด ์Šค์ผ€์ค„๋ง ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณด๊ธฐ

์ด๋ฒˆ ์˜ˆ์ œ๋“ค์„ ์ˆ˜์›”ํ•˜๊ฒŒ ์ง„ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด, ํŒŒ๋“œ๊ฐ€ ์‹ค์ œ๋กœ ์›ํ•˜๋Š” ์Šค์ผ€์ค„๋Ÿฌ์— ์˜ํ•ด ์Šค์ผ€์ค„๋ง๋˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ๋ณด์ง€ ์•Š์•˜๋‹ค. ํ•ด๋‹น ์‚ฌํ•ญ์€ ํŒŒ๋“œ์™€ ๋””ํ”Œ๋กœ์ด๋จผํŠธ ๊ตฌ์„ฑ ํŒŒ์ผ์˜ ์ œ์ถœ ์ˆœ์„œ๋ฅผ ๋ฐ”๊ฟ”๋ณด๋ฉด ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์ผ ์Šค์ผ€์ค„๋Ÿฌ ๋””ํ”Œ๋กœ์ด๋จผํŠธ ๊ตฌ์„ฑ ํŒŒ์ผ์„ ์ œ์ถœํ•˜๊ธฐ ์ „์— ๋ชจ๋“  ํŒŒ๋“œ์˜ ๊ตฌ์„ฑ ํŒŒ์ผ์„ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ์— ์ œ์ถœํ•œ๋‹ค๋ฉด, ๋‹ค๋ฅธ ๋‘ ๊ฐœ์˜ ํŒŒ๋“œ๋Š” ์Šค์ผ€์ค„๋ง ๋˜๋Š” ์™€์ค‘์— annotation-second-scheduler ํŒŒ๋“œ๋Š” ๋ฌด๊ธฐํ•œ "Pending" ์ƒํƒœ์— ๋จธ๋ฌด๋ฅด๋Š” ๊ฒƒ์„ ๊ด€์ฐฐํ•  ์ˆ˜ ์žˆ๋‹ค. ์Šค์ผ€์ค„๋Ÿฌ ๋””ํ”Œ๋กœ์ด๋จผํŠธ ๊ตฌ์„ฑ ํŒŒ์ผ์„ ์ œ์ถœํ•˜์—ฌ ์ƒˆ๋กœ์šด ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด, annotation-second-scheduler ํŒŒ๋“œ๋„ ์Šค์ผ€์ค„๋ง ๋œ๋‹ค.

๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š”, ์ด๋ฒคํŠธ ๋กœ๊ทธ์—์„œ "Scheduled" ํ•ญ๋ชฉ์„ ์ฐพ์•„ ํŒŒ๋“œ๊ฐ€ ์›ํ•˜๋Š” ์Šค์ผ€์ค„๋Ÿฌ์— ์˜ํ•ด ์Šค์ผ€์ค„๋ง ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

kubectl get events

๋˜ํ•œ, ๊ด€๋ จ๋œ ์ปจํŠธ๋กค ํ”Œ๋ ˆ์ธ ๋…ธ๋“œ๋“ค์˜ ์Šคํƒœํ‹ฑ ํŒŒ๋“œ ๋งค๋‹ˆํŽ˜์ŠคํŠธ๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋ฉ”์ธ ์Šค์ผ€์ค„๋Ÿฌ๋กœ ์‚ฌ์šฉ์ž ์ •์˜ ์Šค์ผ€์ค„๋Ÿฌ ๊ตฌ์„ฑ ๋˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

3 - HTTP ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API์— ์ ‘๊ทผ

์ด ํŽ˜์ด์ง€๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด HTTP ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•œ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

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

๋ฒ„์ „ ํ™•์ธ์„ ์œ„ํ•ด์„œ, ๋‹ค์Œ ์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ kubectl version.

ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ์‹คํ–‰ ์ค‘์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์—†๋‹ค๋ฉด, ์•„๋ž˜ ๋ช…๋ น์„ ์ž…๋ ฅํ•˜์—ฌ Hello world ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•œ๋‹ค.

kubectl create deployment node-hello --image=gcr.io/google-samples/node-hello:1.0 --port=8080

kubectl์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ก์‹œ ์„œ๋ฒ„ ์‹œ์ž‘

์•„๋ž˜ ์ปค๋งจ๋“œ๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API ์„œ๋ฒ„์˜ ํ”„๋ก์‹œ๋ฅผ ์‹œ์ž‘ํ•œ๋‹ค.

kubectl proxy --port=8080

Kubernetes API ํƒ์ƒ‰

ํ”„๋ก์‹œ ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰ ์ค‘์ผ ๋•Œ curl, wget ๋˜๋Š” ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ API๋ฅผ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

API ๋ฒ„์ „ ๊ฐ€์ ธ์˜ค๊ธฐ.

curl http://localhost:8080/api/

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•˜๋‹ค.

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.2.15:8443"
    }
  ]
}

ํŒŒ๋“œ ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ.

curl http://localhost:8080/api/v1/namespaces/default/pods

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•˜๋‹ค.

{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "33074"
  },
  "items": [
    {
      "metadata": {
        "name": "kubernetes-bootcamp-2321272333-ix8pt",
        "generateName": "kubernetes-bootcamp-2321272333-",
        "namespace": "default",
        "uid": "ba21457c-6b1d-11e6-85f7-1ef9f1dab92b",
        "resourceVersion": "33003",
        "creationTimestamp": "2016-08-25T23:43:30Z",
        "labels": {
          "pod-template-hash": "2321272333",
          "run": "kubernetes-bootcamp"
        },
        ...
}

๋‹ค์Œ ๋‚ด์šฉ

kubectl ํ”„๋ก์‹œ์— ๋Œ€ํ•ด ๋” ๋ฐฐ์šฐ๊ธฐ.

4 - SOCKS5 ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API์— ์ ‘๊ทผ

๊ธฐ๋Šฅ ์ƒํƒœ: Kubernetes v1.24 [stable]

์ด ๋ฌธ์„œ๋Š” SOCKS5 ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›๊ฒฉ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ์˜ API์— ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•œ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ์ ‘๊ทผํ•˜๋ ค๋Š” ํด๋Ÿฌ์Šคํ„ฐ์˜ API๋ฅผ ๊ณต์šฉ ์ธํ„ฐ๋„ท์— ์ง์ ‘ ๋…ธ์ถœํ•˜์ง€ ์•Š์œผ๋ ค๊ณ  ํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

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

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์„œ๋ฒ„์˜ ๋ฒ„์ „์€ ๋‹ค์Œ๊ณผ ๊ฐ™๊ฑฐ๋‚˜ ๋” ๋†’์•„์•ผ ํ•จ. ๋ฒ„์ „: v1.24.

๋ฒ„์ „ ํ™•์ธ์„ ์œ„ํ•ด์„œ, ๋‹ค์Œ ์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ kubectl version.

SSH ํด๋ผ์ด์–ธํŠธ ์†Œํ”„ํŠธ์›จ์–ด(ssh ๋„๊ตฌ)์™€ ์›๊ฒฉ ์„œ๋ฒ„์—์„œ ์‹คํ–‰๋˜๋Š” SSH ์„œ๋น„์Šค๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ์›๊ฒฉ ์„œ๋ฒ„์˜ SSH ์„œ๋น„์Šค์— ๋กœ๊ทธ์ธํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์ž‘์—… ๋‚ด์šฉ

๊ทธ๋ฆผ 1์€ ์ด ์ž‘์—…์—์„œ ๋‹ฌ์„ฑํ•˜๊ณ ์ž ํ•˜๋Š” ๋ชฉํ‘œ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

  • ์šฐ์„  ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API์™€ ํ†ต์‹ ์„ ์‹œ์ž‘ํ•˜๋Š” ๋กœ์ปฌ ํด๋ผ์ด์–ธํŠธ ์ปดํ“จํ„ฐ๊ฐ€ ์žˆ๋‹ค.
  • ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์„œ๋ฒ„/API๋Š” ์›๊ฒฉ ์„œ๋ฒ„์—์„œ ํ˜ธ์ŠคํŒ…๋œ๋‹ค.
  • SSH ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ ์„œ๋ฒ„์™€ ์›๊ฒฉ ์„œ๋ฒ„ ๊ฐ„์— ๋ณด์•ˆ SOCKS5 ํ„ฐ๋„์„ ์ƒ์„ฑํ•œ๋‹ค. ํด๋ผ์ด์–ธํŠธ์™€ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API ๊ฐ„์˜ HTTPS ํŠธ๋ž˜ํ”ฝ์€ SOCKS5 ํ„ฐ๋„์„ ํ†ตํ•ด ์ „์†ก๋˜๋ฉฐ, ํ„ฐ๋„์€ SSH๋ฅผ ํ†ตํ•ด ํ„ฐ๋„๋ง๋œ๋‹ค.

graph LR; subgraph local[๋กœ์ปฌ ํด๋ผ์ด์–ธํŠธ ๋จธ์‹ ] client([ํด๋ผ์ด์–ธํŠธ])-- ๋กœ์ปฌ
ํŠธ๋ž˜ํ”ฝ .-> local_ssh[๋กœ์ปฌ SSH
SOCKS5 ํ”„๋ก์‹œ]; end local_ssh[SSH
SOCKS5
ํ”„๋ก์‹œ]-- SSH ํ„ฐ๋„ -->sshd subgraph remote[์›๊ฒฉ ์„œ๋ฒ„] sshd[SSH
์„œ๋ฒ„]-- ๋กœ์ปฌ ํŠธ๋ž˜ํ”ฝ -->service1; end client([ํด๋ผ์ด์–ธํŠธ])-. ํ”„๋ก์‹œ๋œ HTTPs ํŠธ๋ž˜ํ”ฝ
ํ”„๋ก์‹œ๋ฅผ ํ†ต๊ณผ .->service1[์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API]; classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; class ingress,service1,service2,pod1,pod2,pod3,pod4 k8s; class client plain; class cluster cluster;
๊ทธ๋ฆผ 1. SOCKS5 ํŠœํ† ๋ฆฌ์–ผ ๊ตฌ์„ฑ ์š”์†Œ

ssh๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ SOCKS5 ํ”„๋ก์‹œ ์ƒ์„ฑํ•˜๊ธฐ

์•„๋ž˜ ์ปค๋งจ๋“œ(command)๋Š” ํด๋ผ์ด์–ธํŠธ ์ปดํ“จํ„ฐ์™€ ์›๊ฒฉ ์„œ๋ฒ„ ๊ฐ„์— SOCKS5 ํ”„๋ก์‹œ๋ฅผ ์‹œ์ž‘ํ•œ๋‹ค. SOCKS5 ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํด๋Ÿฌ์Šคํ„ฐ์˜ API ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

# ์•„๋ž˜ ์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ํ•œ ํ›„ SSH ํ„ฐ๋„์€ ํฌ๊ทธ๋ผ์šด๋“œ(foreground)์—์„œ ์‹คํ–‰๋œ๋‹ค.
ssh -D 1080 -q -N username@kubernetes-remote-server.example
  • -D 1080: SOCKS ํ”„๋ก์‹œ๋ฅผ ๋กœ์ปฌ ํฌํŠธ 1080์œผ๋กœ ์—ฐ๋‹ค.
  • -q: quiet ๋ชจ๋“œ. ๊ฒฝ๊ณ  ๋ฐ ์ง„๋‹จ ๋ฉ”์‹œ์ง€ ๋Œ€๋ถ€๋ถ„์„ ํ‘œ์‹œํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • -N: ์›๊ฒฉ ์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค. ํฌํŠธ ํฌ์›Œ๋”ฉ์— ์œ ์šฉ.
  • username@kubernetes-remote-server.example: ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ์‹คํ–‰ ์ค‘์ธ ์›๊ฒฉ SSH ์„œ๋ฒ„.

ํด๋ผ์ด์–ธํŠธ ํ™˜๊ฒฝ ์„ค์ •

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋จผ์ €, ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์•ž์—์„œ ๋งŒ๋“  SOCKS5 ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ์ฟผ๋ฆฌ๋ฅผ ์ „์†กํ•˜๋„๋ก ์ง€์‹œํ•ด์•ผ ํ•œ๋‹ค.

https_proxy ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ์ปค๋งจ๋“œ๋ฅผ ์ปค๋งจ๋“œ๋ผ์ธ ํˆด์— ์ „๋‹ฌํ•œ๋‹ค.

export https_proxy=socks5h://localhost:1080

https_proxy ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜๋ฉด curl๊ณผ ๊ฐ™์€ ํˆด์€ ๊ตฌ์„ฑํ•œ ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด HTTPS ํŠธ๋ž˜ํ”ฝ์„ ๋ผ์šฐํŒ…ํ•œ๋‹ค. ํˆด์ด SOCKS5 ํ”„๋ก์‹œ๋ฅผ ์ง€์›ํ•ด์•ผ ์ด ๊ธฐ๋Šฅ์ด ๋™์ž‘ํ•œ๋‹ค.

curl -k -v https://localhost:6443/api

ํ”„๋ก์‹œ์™€ ํ•จ๊ป˜ ๊ณต์‹ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋ผ์ด์–ธํŠธ kubectl์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, ~/.kube/config ํŒŒ์ผ์—์„œ ๊ด€๋ จ cluster ํ•ญ๋ชฉ์— ๋Œ€ํ•œ proxy-url ์š”์†Œ๋ฅผ ์„ค์ •ํ•œ๋‹ค. ์˜ˆ์‹œ:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LRMEMMW2 # ๊ฐ€๋…์„ฑ์„ ์œ„ํ•ด์„œ ์ถ•์•ฝํ•จ
    server: https://<API_SERVER_IP_ADRESS>:6443  # "์ฟ ๋ฒ„๋„คํ‹ฐ์Šค API" ์„œ๋ฒ„, ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค-์›๊ฒฉ-์„œ๋ฒ„์˜ IP ์ฃผ์†Œ
    proxy-url: socks5://localhost:1080   # ์œ„ ๋‹ค์ด์–ด๊ทธ๋žจ์˜ "SSH SOCKS5 ํ”„๋ก์‹œ" (SOCKS๋ฅผ ํ†ตํ•œ DNS ํ™•์ธ ๊ธฐ๋Šฅ ๋นŒํŠธ-์ธ)
  name: default
contexts:
- context:
    cluster: default
    user: default
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
  user:
    client-certificate-data: LS0tLS1CR== # ๊ฐ€๋…์„ฑ์„ ์œ„ํ•ด์„œ ์ถ•์•ฝํ•จ
    client-key-data: LS0tLS1CRUdJT=      # ๊ฐ€๋…์„ฑ์„ ์œ„ํ•ด์„œ ์ถ•์•ฝํ•จ

ํ„ฐ๋„์ด ๋™์ž‘ ์ค‘์ด๊ณ  ์ด ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปจํ…์ŠคํŠธ์—์„œ kubectl์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ํด๋Ÿฌ์Šคํ„ฐ์™€ ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ์‹œ:

kubectl get pods
NAMESPACE     NAME                                     READY   STATUS      RESTARTS   AGE
kube-system   coredns-85cb69466-klwq8                  1/1     Running     0          5m46s

์ •๋ฆฌํ•˜๊ธฐ

SSH ํฌํŠธ ํฌ์›Œ๋”ฉ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰ ์ค‘์ธ ํ„ฐ๋ฏธ๋„์—์„œ CTRL+C๋ฅผ ๋ˆŒ๋Ÿฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ค‘์ง€ํ•œ๋‹ค.

ํ„ฐ๋ฏธ๋„์— unset https_proxy๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•œ http ํŠธ๋ž˜ํ”ฝ ์ „์†ก์„ ์ค‘์ง€ํ•œ๋‹ค.

๋” ์ฝ์–ด๋ณด๊ธฐ

5 - Konnectivity ์„œ๋น„์Šค ์„ค์ •

Konnectivity ์„œ๋น„์Šค๋Š” ์ปจํŠธ๋กค ํ”Œ๋ ˆ์ธ์— ํด๋Ÿฌ์Šคํ„ฐ ํ†ต์‹ ์„ ์œ„ํ•œ TCP ์ˆ˜์ค€ ํ”„๋ก์‹œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

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

Konnectivity ์„œ๋น„์Šค ์„ค์ •

๋‹ค์Œ ๋‹จ๊ณ„์—๋Š” ์†ก์‹ (egress) ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

apiVersion: apiserver.k8s.io/v1beta1
kind: EgressSelectorConfiguration
egressSelections:
# ํด๋Ÿฌ์Šคํ„ฐ์— ๋Œ€ํ•œ ์†ก์‹ (egress) ํŠธ๋ž˜ํ”ฝ์„ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด 
# "cluster"๋ฅผ name์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ๊ธฐํƒ€ ์ง€์›๋˜๋Š” ๊ฐ’์€ "etcd" ๋ฐ "controlplane"์ด๋‹ค.
- name: cluster
  connection:
    # API ์„œ๋ฒ„์™€ Konnectivity ์„œ๋ฒ„ ๊ฐ„์˜ ํ”„๋กœํ† ์ฝœ์„
    # ์ œ์–ดํ•œ๋‹ค. ์ง€์›๋˜๋Š” ๊ฐ’์€ "GRPC" ๋ฐ "HTTPConnect"์ด๋‹ค. ๋‘ ๋ชจ๋“œ ๊ฐ„์—
    # ์ตœ์ข… ์‚ฌ์šฉ์ž๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ฐจ์ด์ ์€ ์—†๋‹ค. ๋™์ผํ•œ ๋ชจ๋“œ์—์„œ ์ž‘๋™ํ•˜๋„๋ก
    # Konnectivity ์„œ๋ฒ„๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.
    proxyProtocol: GRPC
    transport:
      # API ์„œ๋ฒ„๊ฐ€ Konnectivity ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” 
      # transport๋ฅผ ์ œ์–ดํ•œ๋‹ค. Konnectivity ์„œ๋ฒ„๊ฐ€ API ์„œ๋ฒ„์™€ ๋™์ผํ•œ ์‹œ์Šคํ…œ์— 
      # ์žˆ๋Š” ๊ฒฝ์šฐ UDS๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๋™์ผํ•œ UDS ์†Œ์ผ“์—์„œ 
      # ์ˆ˜์‹  ๋Œ€๊ธฐํ•˜๋„๋ก Konnectivity ์„œ๋ฒ„๋ฅผ ๊ตฌ์„ฑํ•ด์•ผ ํ•œ๋‹ค. 
      # ์ง€์›๋˜๋Š” ๋‹ค๋ฅธ ์ „์†ก์€ "tcp"์ด๋‹ค. TCP ์ „์†ก์„ ๋ณดํ˜ธํ•˜๋ ค๋ฉด TLS ๊ตฌ์„ฑ์„ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.
      uds:
        udsName: /etc/kubernetes/konnectivity-server/konnectivity-server.socket

Konnectivity ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ์„ ํด๋Ÿฌ์Šคํ„ฐ ๋…ธ๋“œ๋กœ ๋ณด๋‚ด๋„๋ก API ์„œ๋ฒ„๋ฅผ ๊ตฌ์„ฑํ•ด์•ผ ํ•œ๋‹ค.

  1. Service Account Token Volume Projection ๊ธฐ๋Šฅ์ด ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค v1.20๋ถ€ํ„ฐ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋‹ค.
  2. admin/konnectivity/egress-selector-configuration.yaml๊ณผ ๊ฐ™์€ ์†ก์‹  ๊ตฌ์„ฑ ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค.
  3. API ์„œ๋ฒ„์˜ --egress-selector-config-file ํ”Œ๋ž˜๊ทธ๋ฅผ API ์„œ๋ฒ„ ์†ก์‹  ๊ตฌ์„ฑ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋กœ ์„ค์ •ํ•œ๋‹ค.
  4. UDS ์—ฐ๊ฒฐ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ kube-apiserver์— ๋ณผ๋ฅจ ๊ตฌ์„ฑ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.
    spec:
      containers:
        volumeMounts:
        - name: konnectivity-uds
          mountPath: /etc/kubernetes/konnectivity-server
          readOnly: false
      volumes:
      - name: konnectivity-uds
        hostPath:
          path: /etc/kubernetes/konnectivity-server
          type: DirectoryOrCreate
    

konnectivity-server์— ๋Œ€ํ•œ ์ธ์ฆ์„œ ๋ฐ kubeconfig๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์–ป๋Š”๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด OpenSSL ์ปค๋งจ๋“œ๋ผ์ธ ํˆด์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปจํŠธ๋กค ํ”Œ๋ ˆ์ธ ํ˜ธ์ŠคํŠธ์—์„œ ํด๋Ÿฌ์Šคํ„ฐ CA ์ธ์ฆ์„œ /etc/kubernetes/pki/ca.crt๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ X.509 ์ธ์ฆ์„œ๋ฅผ ๋ฐœ๊ธ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

openssl req -subj "/CN=system:konnectivity-server" -new -newkey rsa:2048 -nodes -out konnectivity.csr -keyout konnectivity.key
openssl x509 -req -in konnectivity.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out konnectivity.crt -days 375 -sha256
SERVER=$(kubectl config view -o jsonpath='{.clusters..server}')
kubectl --kubeconfig /etc/kubernetes/konnectivity-server.conf config set-credentials system:konnectivity-server --client-certificate konnectivity.crt --client-key konnectivity.key --embed-certs=true
kubectl --kubeconfig /etc/kubernetes/konnectivity-server.conf config set-cluster kubernetes --server "$SERVER" --certificate-authority /etc/kubernetes/pki/ca.crt --embed-certs=true
kubectl --kubeconfig /etc/kubernetes/konnectivity-server.conf config set-context system:konnectivity-server@kubernetes --cluster kubernetes --user system:konnectivity-server
kubectl --kubeconfig /etc/kubernetes/konnectivity-server.conf config use-context system:konnectivity-server@kubernetes
rm -f konnectivity.crt konnectivity.key konnectivity.csr

๋‹ค์Œ์œผ๋กœ Konnectivity ์„œ๋ฒ„์™€ ์—์ด์ „ํŠธ๋ฅผ ๋ฐฐํฌํ•ด์•ผ ํ•œ๋‹ค. kubernetes-sigs/apiserver-network-proxy์—์„œ ๊ตฌํ˜„์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์ปจํŠธ๋กค ํ”Œ๋ ˆ์ธ ๋…ธ๋“œ์— Konnectivity ์„œ๋ฒ„๋ฅผ ๋ฐฐํฌํ•œ๋‹ค. ์ œ๊ณต๋œ konnectivity-server.yaml ๋งค๋‹ˆํŽ˜์ŠคํŠธ๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํด๋Ÿฌ์Šคํ„ฐ์— ์Šคํƒœํ‹ฑ ํŒŒ๋“œ(static Pod)๋กœ ๋ฐฐํฌ๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” Konnectivity ์„œ๋ฒ„๋ฅผ ๋ฐ๋ชฌ์…‹(DaemonSet)์œผ๋กœ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋‹ค.

apiVersion: v1
kind: Pod
metadata:
  name: konnectivity-server
  namespace: kube-system
spec:
  priorityClassName: system-cluster-critical
  hostNetwork: true
  containers:
  - name: konnectivity-server-container
    image: registry.k8s.io/kas-network-proxy/proxy-server:v0.0.32
    command: ["/proxy-server"]
    args: [
            "--logtostderr=true",
            # ์ด๊ฒƒ์€ egressSelectorConfiguration์— ์„ค์ •๋œ ๊ฐ’๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•œ๋‹ค.
            "--uds-name=/etc/kubernetes/konnectivity-server/konnectivity-server.socket",
            # ๋‹ค์Œ ๋‘ ์ค„์€ Konnectivity ์„œ๋ฒ„๊ฐ€ apiserver์™€ 
            # ๋™์ผํ•œ ์‹œ์Šคํ…œ์— ๋ฐฐํฌ๋˜๊ณ  API ์„œ๋ฒ„์˜ ์ธ์ฆ์„œ์™€ 
            # ํ‚ค๊ฐ€ ์ง€์ •๋œ ์œ„์น˜์— ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.
            "--cluster-cert=/etc/kubernetes/pki/apiserver.crt",
            "--cluster-key=/etc/kubernetes/pki/apiserver.key",
            # ์ด๊ฒƒ์€ egressSelectorConfiguration์— ์„ค์ •๋œ ๊ฐ’๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•œ๋‹ค.
            "--mode=grpc",
            "--server-port=0",
            "--agent-port=8132",
            "--admin-port=8133",
            "--health-port=8134",
            "--agent-namespace=kube-system",
            "--agent-service-account=konnectivity-agent",
            "--kubeconfig=/etc/kubernetes/konnectivity-server.conf",
            "--authentication-audience=system:konnectivity-server"
            ]
    livenessProbe:
      httpGet:
        scheme: HTTP
        host: 127.0.0.1
        port: 8134
        path: /healthz
      initialDelaySeconds: 30
      timeoutSeconds: 60
    ports:
    - name: agentport
      containerPort: 8132
      hostPort: 8132
    - name: adminport
      containerPort: 8133
      hostPort: 8133
    - name: healthport
      containerPort: 8134
      hostPort: 8134
    volumeMounts:
    - name: k8s-certs
      mountPath: /etc/kubernetes/pki
      readOnly: true
    - name: kubeconfig
      mountPath: /etc/kubernetes/konnectivity-server.conf
      readOnly: true
    - name: konnectivity-uds
      mountPath: /etc/kubernetes/konnectivity-server
      readOnly: false
  volumes:
  - name: k8s-certs
    hostPath:
      path: /etc/kubernetes/pki
  - name: kubeconfig
    hostPath:
      path: /etc/kubernetes/konnectivity-server.conf
      type: FileOrCreate
  - name: konnectivity-uds
    hostPath:
      path: /etc/kubernetes/konnectivity-server
      type: DirectoryOrCreate

๊ทธ๋Ÿฐ ๋‹ค์Œ ํด๋Ÿฌ์Šคํ„ฐ์— Konnectivity ์—์ด์ „ํŠธ๋ฅผ ๋ฐฐํฌํ•œ๋‹ค.

apiVersion: apps/v1
# ์—์ด์ „ํŠธ๋ฅผ Deployment(๋””ํ”Œ๋กœ์ด๋จผํŠธ)๋กœ ๋ฐฐํฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๊ฐ ๋…ธ๋“œ์— ์—์ด์ „ํŠธ๊ฐ€
# ์žˆ์„ ํ•„์š”๋Š” ์—†๋‹ค.
kind: DaemonSet
metadata:
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
    k8s-app: konnectivity-agent
  namespace: kube-system
  name: konnectivity-agent
spec:
  selector:
    matchLabels:
      k8s-app: konnectivity-agent
  template:
    metadata:
      labels:
        k8s-app: konnectivity-agent
    spec:
      priorityClassName: system-cluster-critical
      tolerations:
        - key: "CriticalAddonsOnly"
          operator: "Exists"
      containers:
        - image: us.gcr.io/k8s-artifacts-prod/kas-network-proxy/proxy-agent:v0.0.16
          name: konnectivity-agent
          command: ["/proxy-agent"]
          args: [
                  "--logtostderr=true",
                  "--ca-cert=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt",
                  # konnectivity ์„œ๋ฒ„๋Š” hostNetwork=true๋กœ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์—,
                  # ์ด๊ฒƒ์€ ๋งˆ์Šคํ„ฐ ๋จธ์‹ ์˜ IP ์ฃผ์†Œ์ด๋‹ค.
                  "--proxy-server-host=35.225.206.7",
                  "--proxy-server-port=8132",
                  "--admin-server-port=8133",
                  "--health-server-port=8134",
                  "--service-account-token-path=/var/run/secrets/tokens/konnectivity-agent-token"
                  ]
          volumeMounts:
            - mountPath: /var/run/secrets/tokens
              name: konnectivity-agent-token
          livenessProbe:
            httpGet:
              port: 8134
              path: /healthz
            initialDelaySeconds: 15
            timeoutSeconds: 15
      serviceAccountName: konnectivity-agent
      volumes:
        - name: konnectivity-agent-token
          projected:
            sources:
              - serviceAccountToken:
                  path: konnectivity-agent-token
                  audience: system:konnectivity-server

๋งˆ์ง€๋ง‰์œผ๋กœ ํด๋Ÿฌ์Šคํ„ฐ์—์„œ RBAC๊ฐ€ ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ ๊ด€๋ จ RBAC ๊ทœ์น™์„ ์ƒ์„ฑํ•œ๋‹ค.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:konnectivity-server
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: system:konnectivity-server
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: konnectivity-agent
  namespace: kube-system
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile