Kubernetes์—์„œ HA ๋ชจ๋“œ๋กœ Keycloak ์‹คํ–‰

Kubernetes์—์„œ HA ๋ชจ๋“œ๋กœ Keycloak ์‹คํ–‰

TL; DR: ์˜คํ”ˆ์†Œ์Šค ์ ‘๊ทผํ†ต์ œ ์‹œ์Šคํ…œ์ธ Keycloak์— ๋Œ€ํ•œ ์„ค๋ช…๊ณผ ๋‚ด๋ถ€ ๊ตฌ์กฐ ๋ถ„์„, ๊ตฌ์„ฑ ์„ธ๋ถ€์‚ฌํ•ญ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์†Œ๊ฐœ ๋ฐ ํ•ต์‹ฌ ์•„์ด๋””์–ด

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” Kubernetes ์œ„์— Keycloak ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ๋ฐฐํฌํ•  ๋•Œ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•  ๊ธฐ๋ณธ ์•„์ด๋””์–ด๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Keycloak์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด ๊ธฐ์‚ฌ ๋งˆ์ง€๋ง‰์— ์žˆ๋Š” ๋งํฌ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. ์‹ค๋ฌด์— ๋”์šฑ ๋ชฐ์ž…ํ•˜๊ธฐ ์œ„ํ•ด ๊ณต๋ถ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ์ €์žฅ์†Œ ์ด ๋ฌธ์„œ์˜ ์ฃผ์š” ์•„์ด๋””์–ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ชจ๋“ˆ ํฌํ•จ(์‹คํ–‰ ๊ฐ€์ด๋“œ๊ฐ€ ์žˆ์œผ๋ฉฐ ์ด ๋ฌธ์„œ์—์„œ๋Š” ์žฅ์น˜ ๋ฐ ์„ค์ •์— ๋Œ€ํ•œ ๊ฐœ์š”๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์•ฝ. ์—ญ์ž).

Keycloak์€ Java๋กœ ์ž‘์„ฑ๋˜๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„ ์œ„์— ๊ตฌ์ถ•๋œ ํฌ๊ด„์ ์ธ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ์•ผ์ƒํ™”. ๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‚ฌ์šฉ์ž์—๊ฒŒ ์—ฐํ•ฉ ๋ฐ SSO(Single Sign-On) ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ์ธ์ฆ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค.

๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์›น ์‚ฌ์ดํŠธ ๋˜๋Š” ์œ„ํ‚คํ”ผ๋””์•„ ์ž์„ธํ•œ ์ดํ•ด๋ฅผ ์œ„ํ•ด.

ํ‚คํด๋กœํฌ ์‹คํ–‰

Keycloak์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๋‘ ๊ฐœ์˜ ์˜๊ตฌ ๋ฐ์ดํ„ฐ ์†Œ์Šค๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

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

Keycloak์€ ๋„ค ๊ฐ€์ง€ ๋ชจ๋“œ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

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

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ๋‘ ๋ฒˆ์งธ ์˜ต์…˜, ์ฆ‰ ์ผ๋ฐ˜ ํด๋Ÿฌ์Šคํ„ฐ๊ทธ๋ฆฌ๊ณ  Kubernetes์—์„œ ์ด ๋‘ ๊ฐ€์ง€ ์˜ต์…˜์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ด๋ฏ€๋กœ ๋ฐ์ดํ„ฐ ์„ผํ„ฐ ๊ฐ„ ๋ณต์ œ ์ฃผ์ œ์— ๋Œ€ํ•ด์„œ๋„ ์กฐ๊ธˆ ๋‹ค๋ฃฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹คํ–‰ํžˆ Kubernetes์—์„œ๋Š” ์—ฌ๋Ÿฌ Pod(Keycloak ๋…ธ๋“œ)์˜ ์„ค์ •์„ ๋™๊ธฐํ™”ํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๋„๋ฉ”์ธ ํด๋Ÿฌ์Šคํ„ฐ ๋ณ„๋กœ ์–ด๋ ต์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ ์ด ๋‹จ์–ด์— ์ฃผ๋ชฉํ•ด์ฃผ์„ธ์š”. ํด๋Ÿฌ์Šคํ„ฐ ๊ธฐ์‚ฌ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” Keycloak ๋…ธ๋“œ ๊ทธ๋ฃน์—๋งŒ ์ ์šฉ๋˜๋ฏ€๋กœ Kubernetes ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์ฐธ์กฐํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜ Keycloak ํด๋Ÿฌ์Šคํ„ฐ

์ด ๋ชจ๋“œ์—์„œ Keycloak์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๋‹ค์Œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  • ์™ธ๋ถ€ ๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌ์„ฑ
  • ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ ์„ค์น˜
  • IP ๋ฉ€ํ‹ฐ์บ์ŠคํŠธ๋ฅผ ์ง€์›ํ•˜๋Š” ๋‚ด๋ถ€ ๋„คํŠธ์›Œํฌ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์™ธ๋ถ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค์ •์€ ์ด ๋ฌธ์„œ์˜ ๋ชฉ์ ์ด ์•„๋‹ˆ๋ฏ€๋กœ ๋…ผ์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์–ด๋”˜๊ฐ€์— ์ž‘๋™ ์ค‘์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์žˆ๊ณ  ์ด์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ ์ง€์ ์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐ์ดํ„ฐ๋ฅผ ํ™˜๊ฒฝ ๋ณ€์ˆ˜์— ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์žฅ์•  ์กฐ์น˜(HA) ํด๋Ÿฌ์Šคํ„ฐ์—์„œ Keycloak์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์„ ๋” ์ž˜ ์ดํ•ดํ•˜๋ ค๋ฉด Wildfly์˜ ํด๋Ÿฌ์Šคํ„ฐ๋ง ๊ธฐ๋Šฅ์— ์–ผ๋งˆ๋‚˜ ์˜์กดํ•˜๋Š”์ง€ ์•„๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

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

  • mod_cluster: HTTP ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ๋กœ Apache์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋ฉฐ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ˜ธ์ŠคํŠธ๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด TCP ๋ฉ€ํ‹ฐ์บ์ŠคํŠธ์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ ๋ฐธ๋Ÿฐ์„œ๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • infinispan: JGroups ์ฑ„๋„์„ ์ „์†ก ๊ณ„์ธต์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ถ„์‚ฐ ์บ์‹œ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ HotRod ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์™ธ๋ถ€ Infinispan ํด๋Ÿฌ์Šคํ„ฐ์™€ ํ†ต์‹ ํ•˜์—ฌ ์บ์‹œ ์ฝ˜ํ…์ธ ๋ฅผ ๋™๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • jgroups: JGroups ์ฑ„๋„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ณ ๊ฐ€์šฉ์„ฑ ์„œ๋น„์Šค์— ๋Œ€ํ•œ ๊ทธ๋ฃน ํ†ต์‹  ์ง€์›์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ช…๋ช…๋œ ํŒŒ์ดํ”„๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํด๋Ÿฌ์Šคํ„ฐ์˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ทธ๋ฃน์œผ๋กœ ์—ฐ๊ฒฐํ•˜์—ฌ ํ†ต์‹ ์ด ์‹ ๋ขฐ์„ฑ, ์งˆ์„œ ๋ฐ ์˜ค๋ฅ˜ ๋ฏผ๊ฐ๋„์™€ ๊ฐ™์€ ์†์„ฑ์„ ๊ฐ–๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ

Kubernetes ํด๋Ÿฌ์Šคํ„ฐ์— ์ˆ˜์‹  ์ปจํŠธ๋กค๋Ÿฌ๋กœ ๋ฐธ๋Ÿฐ์„œ๋ฅผ ์„ค์น˜ํ•  ๋•Œ ๋‹ค์Œ ์‚ฌํ•ญ์„ ์—ผ๋‘์— ๋‘๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

Keycloak์€ HTTP๋ฅผ ํ†ตํ•ด ์ธ์ฆ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์›๊ฒฉ ์ฃผ์†Œ๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ปดํ“จํ„ฐ์˜ ์‹ค์ œ IP ์ฃผ์†Œ๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ถ„์‚ฐ๊ธฐ ๋ฐ ์ˆ˜์‹  ์„ค์ •์€ HTTP ํ—ค๋”๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. X-Forwarded-For ะธ X-Forwarded-Proto, ์›๋ž˜ ์ œ๋ชฉ๋„ ์ €์žฅ HOST. ์ตœ์‹  ๋ฒ„์ „ ingress-nginx (>0.22.0) ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด๊ฒƒ์„ ๋น„ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค

ํ”Œ๋ž˜๊ทธ ํ™œ์„ฑํ™” proxy-address-forwarding ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์—ฌ PROXY_ADDRESS_FORWARDING ะฒ true Keycloak์€ ํ”„๋ก์‹œ ๋’ค์—์„œ ์ž‘๋™ํ•˜๊ณ  ์žˆ์Œ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ณ ์ • ์„ธ์…˜ ์ง„์ž… ์ค‘. Keycloak์€ ๋ถ„์‚ฐํ˜• Infinispan ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ˜„์žฌ ์ธ์ฆ ์„ธ์…˜ ๋ฐ ์‚ฌ์šฉ์ž ์„ธ์…˜๊ณผ ๊ด€๋ จ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์บ์‹œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹จ์ผ ์†Œ์œ ์ž๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ํ•ด๋‹น ํŠน์ • ์„ธ์…˜์€ ํด๋Ÿฌ์Šคํ„ฐ์˜ ์ผ๋ถ€ ๋…ธ๋“œ์— ์ €์žฅ๋˜๊ณ  ๋‹ค๋ฅธ ๋…ธ๋“œ๋Š” ํ•ด๋‹น ์„ธ์…˜์— ์•ก์„ธ์Šคํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์›๊ฒฉ์œผ๋กœ ์ฟผ๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํŠนํžˆ ๋ฌธ์„œ์™€๋Š” ๋‹ฌ๋ฆฌ ์ด๋ฆ„์ด ์ฟ ํ‚ค์ธ ์„ธ์…˜์„ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ์ž‘๋™ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. AUTH_SESSION_ID. Keycloak์—๋Š” ๋ฆฌ๋””๋ ‰์…˜ ๋ฃจํ”„๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๊ณ ์ • ์„ธ์…˜์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ์ฟ ํ‚ค ์ด๋ฆ„์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

Keycloak์€ ๋˜ํ•œ ๊ฐ€์žฅ ๋จผ์ € ์‘๋‹ตํ•œ ๋…ธ๋“œ์˜ ์ด๋ฆ„์„ ์ฒจ๋ถ€ํ•ฉ๋‹ˆ๋‹ค. AUTH_SESSION_ID๊ณ ๊ฐ€์šฉ์„ฑ ๋ฒ„์ „์˜ ๊ฐ ๋…ธ๋“œ๋Š” ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๊ฐ ๋…ธ๋“œ๋Š” ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ๋ณ„๋„์˜ ๊ณ ์œ ํ•œ ๋…ธ๋“œ ์‹๋ณ„์ž์ž…๋‹ˆ๋‹ค. ๋„ฃ์–ด๋‘๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค JAVA_OPTS ๋งค๊ฐœ ๋ณ€์ˆ˜ jboss.node.name ะธ jboss.tx.node.id ๊ฐ ๋…ธ๋“œ๋งˆ๋‹ค ๊ณ ์œ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํฌ๋“œ ์ด๋ฆ„์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Pod ์ด๋ฆ„์„ ์ž…๋ ฅํ•  ๋•Œ jboss ๋ณ€์ˆ˜์˜ 23์ž ์ œํ•œ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”. ๋”ฐ๋ผ์„œ ๋ฐฐํฌ๋ณด๋‹ค๋Š” StatefulSet์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋˜ ๋‹ค๋ฅธ ๋ ˆ์ดํฌ - ํฌ๋“œ๊ฐ€ ์‚ญ์ œ๋˜๊ฑฐ๋‚˜ ๋‹ค์‹œ ์‹œ์ž‘๋˜๋ฉด ์บ์‹œ๊ฐ€ ์†์‹ค๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ๋ชจ๋“  ์บ์‹œ์— ๋Œ€ํ•œ ์บ์‹œ ์†Œ์œ ์ž ์ˆ˜๋ฅผ ์ตœ์†Œ XNUMX๋ช…์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ์บ์‹œ ๋ณต์‚ฌ๋ณธ์ด ์œ ์ง€๋˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ํ•ด๊ฒฐ์ฑ…์€ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Wildfly์šฉ ์Šคํฌ๋ฆฝํŠธ ํฌ๋“œ๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋ฐฐ์น˜ /opt/jboss/startup-scripts ์ปจํ…Œ์ด๋„ˆ์—์„œ:

์Šคํฌ๋ฆฝํŠธ ๋‚ด์šฉ

embed-server --server-config=standalone-ha.xml --std-out=echo
batch

echo * Setting CACHE_OWNERS to "${env.CACHE_OWNERS}" in all cache-containers

/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions:write-attribute(name=owners, value=${env.CACHE_OWNERS:1})
/subsystem=infinispan/cache-container=keycloak/distributed-cache=authenticationSessions:write-attribute(name=owners, value=${env.CACHE_OWNERS:1})
/subsystem=infinispan/cache-container=keycloak/distributed-cache=actionTokens:write-attribute(name=owners, value=${env.CACHE_OWNERS:1})
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions:write-attribute(name=owners, value=${env.CACHE_OWNERS:1})
/subsystem=infinispan/cache-container=keycloak/distributed-cache=clientSessions:write-attribute(name=owners, value=${env.CACHE_OWNERS:1})
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineClientSessions:write-attribute(name=owners, value=${env.CACHE_OWNERS:1})
/subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures:write-attribute(name=owners, value=${env.CACHE_OWNERS:1})

run-batch
stop-embedded-server

๊ทธ๋Ÿฐ ๋‹ค์Œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์„ค์ •ํ•˜์‹ญ์‹œ์˜ค. CACHE_OWNERS ํ•„์ˆ˜์—.

IP ๋ฉ€ํ‹ฐ์บ์ŠคํŠธ๋ฅผ ์ง€์›ํ•˜๋Š” ๊ฐœ์ธ ๋„คํŠธ์›Œํฌ

Weavenet์„ CNI๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๋ฉ€ํ‹ฐ์บ์ŠคํŠธ๊ฐ€ ์ฆ‰์‹œ ์ž‘๋™ํ•˜๊ณ  Keycloak ๋…ธ๋“œ๊ฐ€ ์‹œ์ž‘๋˜์ž๋งˆ์ž ์„œ๋กœ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Kubernetes ํด๋Ÿฌ์Šคํ„ฐ์— IP ๋ฉ€ํ‹ฐ์บ์ŠคํŠธ ์ง€์›์ด ์—†์œผ๋ฉด ๋‹ค๋ฅธ ํ”„๋กœํ† ์ฝœ๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•˜์—ฌ ๋…ธ๋“œ๋ฅผ ์ฐพ๋„๋ก JGroups๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ์˜ต์…˜์€ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. KUBE_DNS์‚ฌ์šฉํ•˜๋Š” headless service Keycloak ๋…ธ๋“œ๋ฅผ ์ฐพ์œผ๋ ค๋ฉด ๋…ธ๋“œ๋ฅผ ์ฐพ๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์„œ๋น„์Šค ์ด๋ฆ„์„ JGroups์— ์ „๋‹ฌํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋˜ ๋‹ค๋ฅธ ์˜ต์…˜์€ ๋‹ค์Œ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. KUBE_PING, API์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜์—ฌ ๋…ธ๋“œ๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค(๊ตฌ์„ฑํ•ด์•ผ ํ•จ). serviceAccount ๊ถŒ๋ฆฌ๊ฐ€ ์žˆ๋Š” list ะธ get์„ ํด๋ฆญํ•œ ๋‹ค์Œ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํฌ๋“œ๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. serviceAccount).

JGroups๊ฐ€ ๋…ธ๋“œ๋ฅผ ์ฐพ๋Š” ๋ฐฉ์‹์€ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์—ฌ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. JGROUPS_DISCOVERY_PROTOCOL ะธ JGROUPS_DISCOVERY_PROPERTIES. ์— KUBE_PING ์š”์ฒญํ•˜์—ฌ ํฌ๋“œ๋ฅผ ์„ ํƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. namespace ะธ labels.

๏ธ ๋ฉ€ํ‹ฐ์บ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ํ•˜๋‚˜์˜ Kubernetes ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ๋‘ ๊ฐœ ์ด์ƒ์˜ Keycloak ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ(๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ํ•˜๋‚˜๋ผ๊ณ  ๊ฐ€์ •) production, ๋‘๋ฒˆ์งธ - staging) - ํ•˜๋‚˜์˜ Keycloak ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋…ธ๋“œ๊ฐ€ ๋‹ค๋ฅธ ํด๋Ÿฌ์Šคํ„ฐ์— ํ•ฉ๋ฅ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์—ฌ ๊ฐ ํด๋Ÿฌ์Šคํ„ฐ์— ๊ณ ์œ ํ•œ ๋ฉ€ํ‹ฐ์บ์ŠคํŠธ ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.jboss.default.multicast.address ะธ jboss.modcluster.multicast.address ะฒ JAVA_OPTS.

๋ฐ์ดํ„ฐ ์„ผํ„ฐ ๊ฐ„ ๋ณต์ œ

Kubernetes์—์„œ HA ๋ชจ๋“œ๋กœ Keycloak ์‹คํ–‰

ะกะฒัะทัŒ

Keycloak์€ Keycloak ๋…ธ๋“œ๋กœ ๊ตฌ์„ฑ๋œ Keycloack ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ์œ„์น˜ํ•œ ๊ฐ ๋ฐ์ดํ„ฐ ์„ผํ„ฐ์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐœ๋ณ„ Infinispan ์บ์‹œ ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ์„ผํ„ฐ์˜ Keycloak ๋…ธ๋“œ ๊ฐ„์—๋Š” ์ฐจ์ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

Keycloak ๋…ธ๋“œ๋Š” ๋ฐ์ดํ„ฐ ์„ผํ„ฐ ๊ฐ„ ํ†ต์‹ ์„ ์œ„ํ•ด ์™ธ๋ถ€ Java Data Grid(Infinispan ์„œ๋ฒ„)๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ†ต์‹ ์€ ํ”„๋กœํ† ์ฝœ์— ๋”ฐ๋ผ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ธํ”ผ๋‹ˆ์ŠคํŒฌ ํ•ซ๋กœ๋“œ.

Infinispan ์บ์‹œ๋Š” ๋‹ค์Œ ์†์„ฑ์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. remoteStore, ๋ฐ์ดํ„ฐ๋ฅผ ์›๊ฒฉ์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก(๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ์„ผํ„ฐ, ์•ฝ. ์—ญ์ž) ์บ์‹œ. JDG ์„œ๋ฒ„ ์‚ฌ์ด์—๋Š” ๋ณ„๋„์˜ infinispan ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ์‚ฌ์ดํŠธ์˜ JDG1์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋Š” site1 ์‚ฌ์ดํŠธ์˜ JDG2์— ๋ณต์ œ๋ฉ๋‹ˆ๋‹ค. site2.

๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ ์ˆ˜์‹  JDG ์„œ๋ฒ„๋Š” HotRod ํ”„๋กœํ† ์ฝœ์˜ ๊ธฐ๋Šฅ์ธ ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ์„ ํ†ตํ•ด ํด๋Ÿฌ์Šคํ„ฐ์˜ Keycloak ์„œ๋ฒ„์— ์•Œ๋ฆฝ๋‹ˆ๋‹ค. Keycloak ๋…ธ๋“œ ์ผœ์ง site2 Infinispan ์บ์‹œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ํŠน์ • ์‚ฌ์šฉ์ž ์„ธ์…˜์ด Keycloak ๋…ธ๋“œ์—์„œ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค. site2.

์ผ๋ถ€ ์บ์‹œ์˜ ๊ฒฝ์šฐ ๋ฐฑ์—…์„ ํ•˜์ง€ ์•Š๊ณ  ์ธํ”ผ๋‹ˆ์ŠคํŒฌ ์„œ๋ฒ„๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ์“ฐ๊ธฐ๋ฅผ ์™„์ „ํžˆ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด ์„ค์ •์„ ์ œ๊ฑฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. remote-store ํŠน์ • Infinispan ์บ์‹œ(ํŒŒ์ผ์—์„œ ๋…๋ฆฝํ˜•-ha.xml), ๊ทธ ์ดํ›„์—๋Š” ํŠน์ • replicated-cache Infinispan ์„œ๋ฒ„ ์ธก์—์„œ๋„ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์บ์‹œ ์„ค์ •

Keycloak์—๋Š” ๋‘ ๊ฐ€์ง€ ์œ ํ˜•์˜ ์บ์‹œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

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

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

์ธํ”ผ๋‹ˆ์ŠคํŒฌ ์บ์‹œ

์„ธ์…˜ - Keycloak์˜ ๊ฐœ๋…์œผ๋กœ ๋ณ„๋„์˜ ์บ์‹œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. authenticationSessions, ํŠน์ • ์‚ฌ์šฉ์ž์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์บ์‹œ์˜ ์š”์ฒญ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์•„๋‹Œ ๋ธŒ๋ผ์šฐ์ € ๋ฐ Keycloak ์„œ๋ฒ„์— ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ณ ์ • ์„ธ์…˜์— ๋Œ€ํ•œ ์˜์กด์„ฑ์ด ์ž‘์šฉํ•˜๋Š” ์ง€์ ์ด๋ฉฐ Active-Active ๋ชจ๋“œ์˜ ๊ฒฝ์šฐ์—๋„ ์ด๋Ÿฌํ•œ ์บ์‹œ ์ž์ฒด๋ฅผ ๋ณต์ œํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

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

์ €์žฅ๋œ ๋ฐ์ดํ„ฐ์˜ ์บ์‹ฑ ๋ฐ ์—์ด์ง• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ถ€ํ•˜๋ฅผ ์™„ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ์บ์‹ฑ์€ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค์ง€๋งŒ ๋ช…๋ฐฑํ•œ ๋ฌธ์ œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ Keycloak ์„œ๋ฒ„๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒฝ์šฐ ์บ์‹œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋„๋ก ๋‹ค๋ฅธ ์„œ๋ฒ„์— ์•Œ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค. Keycloak์€ ๋กœ์ปฌ ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. realms, users ะธ authorization ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์บ์‹ฑํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

์‚ฌ์šฉ์ž ์„ธ์…˜. ์ด๋ฆ„์ด ์žˆ๋Š” ์บ์‹œ sessions, clientSessions, offlineSessions ะธ offlineClientSessions๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ดํ„ฐ ์„ผํ„ฐ ๊ฐ„์— ๋ณต์ œ๋˜๋ฉฐ ์‚ฌ์šฉ์ž๊ฐ€ ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ™œ์„ฑ ์ƒํƒœ์ธ ๋™์•ˆ ํ™œ์„ฑํ™”๋œ ์‚ฌ์šฉ์ž ์„ธ์…˜์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์บ์‹œ๋Š” ์ตœ์ข… ์‚ฌ์šฉ์ž์˜ HTTP ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋ฏ€๋กœ ๊ณ ์ • ์„ธ์…˜๊ณผ ์—ฐ๊ฒฐ๋˜๋ฉฐ ๋ฐ์ดํ„ฐ ์„ผํ„ฐ ๊ฐ„์— ๋ณต์ œ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฌด์ฐจ๋ณ„ ๋Œ€์ž… ๋ณดํ˜ธ. ์€๋‹‰์ฒ˜ loginFailures ์‚ฌ์šฉ์ž๊ฐ€ ์ž˜๋ชป๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•œ ํšŸ์ˆ˜์™€ ๊ฐ™์€ ๋กœ๊ทธ์ธ ์˜ค๋ฅ˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด ์บ์‹œ์˜ ๋ณต์ œ๋Š” ๊ด€๋ฆฌ์ž์˜ ์ฑ…์ž„์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ •ํ™•ํ•œ ๊ณ„์‚ฐ์„ ์œ„ํ•ด์„œ๋Š” ๋ฐ์ดํ„ฐ ์„ผํ„ฐ ๊ฐ„ ๋ณต์ œ๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฐ˜๋ฉด์— ์ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์ œํ•˜์ง€ ์•Š์œผ๋ฉด ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋˜๋ฉฐ, ์ด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋ณต์ œ๊ฐ€ ํ™œ์„ฑํ™”๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Infinispan ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ๋กค์•„์›ƒํ•  ๋•Œ ์„ค์ • ํŒŒ์ผ์— ์บ์‹œ ์ •์˜๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

<replicated-cache-configuration name="keycloak-sessions" mode="ASYNC" start="EAGER" batching="false">
</replicated-cache-configuration>

<replicated-cache name="work" configuration="keycloak-sessions" />
<replicated-cache name="sessions" configuration="keycloak-sessions" />
<replicated-cache name="offlineSessions" configuration="keycloak-sessions" />
<replicated-cache name="actionTokens" configuration="keycloak-sessions" />
<replicated-cache name="loginFailures" configuration="keycloak-sessions" />
<replicated-cache name="clientSessions" configuration="keycloak-sessions" />
<replicated-cache name="offlineClientSessions" configuration="keycloak-sessions" />

Keycloak ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— Infinispan ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ตฌ์„ฑํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค remoteStore Keycloak ์บ์‹œ์šฉ. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์ด์ „ ์Šคํฌ๋ฆฝํŠธ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ˆ˜ํ–‰๋˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. CACHE_OWNERS, ํŒŒ์ผ๋กœ ์ €์žฅํ•˜๊ณ  ๋””๋ ‰ํ† ๋ฆฌ์— ๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. /opt/jboss/startup-scripts:

์Šคํฌ๋ฆฝํŠธ ๋‚ด์šฉ

embed-server --server-config=standalone-ha.xml --std-out=echo
batch

echo *** Update infinispan subsystem ***
/subsystem=infinispan/cache-container=keycloak:write-attribute(name=module, value=org.keycloak.keycloak-model-infinispan)

echo ** Add remote socket binding to infinispan server **
/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=remote-cache:add(host=${remote.cache.host:localhost}, port=${remote.cache.port:11222})

echo ** Update replicated-cache work element **
/subsystem=infinispan/cache-container=keycloak/replicated-cache=work/store=remote:add( 
    passivation=false, 
    fetch-state=false, 
    purge=false, 
    preload=false, 
    shared=true, 
    remote-servers=["remote-cache"], 
    cache=work, 
    properties={ 
        rawValues=true, 
        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory, 
        protocolVersion=${keycloak.connectionsInfinispan.hotrodProtocolVersion} 
    } 
)

/subsystem=infinispan/cache-container=keycloak/replicated-cache=work:write-attribute(name=statistics-enabled,value=true)

echo ** Update distributed-cache sessions element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions/store=remote:add( 
    passivation=false, 
    fetch-state=false, 
    purge=false, 
    preload=false, 
    shared=true, 
    remote-servers=["remote-cache"], 
    cache=sessions, 
    properties={ 
        rawValues=true, 
        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory, 
        protocolVersion=${keycloak.connectionsInfinispan.hotrodProtocolVersion} 
    } 
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions:write-attribute(name=statistics-enabled,value=true)

echo ** Update distributed-cache offlineSessions element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions/store=remote:add( 
    passivation=false, 
    fetch-state=false, 
    purge=false, 
    preload=false, 
    shared=true, 
    remote-servers=["remote-cache"], 
    cache=offlineSessions, 
    properties={ 
        rawValues=true, 
        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory, 
        protocolVersion=${keycloak.connectionsInfinispan.hotrodProtocolVersion} 
    } 
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions:write-attribute(name=statistics-enabled,value=true)

echo ** Update distributed-cache clientSessions element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=clientSessions/store=remote:add( 
    passivation=false, 
    fetch-state=false, 
    purge=false, 
    preload=false, 
    shared=true, 
    remote-servers=["remote-cache"], 
    cache=clientSessions, 
    properties={ 
        rawValues=true, 
        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory, 
        protocolVersion=${keycloak.connectionsInfinispan.hotrodProtocolVersion} 
    } 
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=clientSessions:write-attribute(name=statistics-enabled,value=true)

echo ** Update distributed-cache offlineClientSessions element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineClientSessions/store=remote:add( 
    passivation=false, 
    fetch-state=false, 
    purge=false, 
    preload=false, 
    shared=true, 
    remote-servers=["remote-cache"], 
    cache=offlineClientSessions, 
    properties={ 
        rawValues=true, 
        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory, 
        protocolVersion=${keycloak.connectionsInfinispan.hotrodProtocolVersion} 
    } 
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineClientSessions:write-attribute(name=statistics-enabled,value=true)

echo ** Update distributed-cache loginFailures element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures/store=remote:add( 
    passivation=false, 
    fetch-state=false, 
    purge=false, 
    preload=false, 
    shared=true, 
    remote-servers=["remote-cache"], 
    cache=loginFailures, 
    properties={ 
        rawValues=true, 
        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory, 
        protocolVersion=${keycloak.connectionsInfinispan.hotrodProtocolVersion} 
    } 
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures:write-attribute(name=statistics-enabled,value=true)

echo ** Update distributed-cache actionTokens element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=actionTokens/store=remote:add( 
    passivation=false, 
    fetch-state=false, 
    purge=false, 
    preload=false, 
    shared=true, 
    cache=actionTokens, 
    remote-servers=["remote-cache"], 
    properties={ 
        rawValues=true, 
        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory, 
        protocolVersion=${keycloak.connectionsInfinispan.hotrodProtocolVersion} 
    } 
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=actionTokens:write-attribute(name=statistics-enabled,value=true)

echo ** Update distributed-cache authenticationSessions element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=authenticationSessions:write-attribute(name=statistics-enabled,value=true)

echo *** Update undertow subsystem ***
/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=proxy-address-forwarding,value=true)

run-batch
stop-embedded-server

์„ค์น˜ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์„ธ์š” JAVA_OPTS HotRod๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ Keycloak ๋…ธ๋“œ์˜ ๊ฒฝ์šฐ: remote.cache.host, remote.cache.port ๋ฐ ์„œ๋น„์Šค ์ด๋ฆ„ jboss.site.name.

๋งํฌ ๋ฐ ์ถ”๊ฐ€ ๋ฌธ์„œ

์ด ๊ธฐ์‚ฌ๋Š” ์ง์›๋“ค์ด Habr์„ ์œ„ํ•ด ๋ฒˆ์—ญํ•˜๊ณ  ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค. ์Šฌ๋Ÿผ ํŠธ๋ ˆ์ด๋‹ ์„ผํ„ฐ โ€” ์‹ค๋ฌด ์ „๋ฌธ๊ฐ€(Kubernetes, DevOps, Docker, Ansible, Ceph, SRE)์˜ ์ง‘์ค‘ ๊ณผ์ •, ๋น„๋””์˜ค ๊ณผ์ • ๋ฐ ๊ธฐ์—… ๊ต์œก

์ถœ์ฒ˜ : habr.com

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