TL; DR: ์คํ์์ค ์ ๊ทผํต์ ์์คํ ์ธ Keycloak์ ๋ํ ์ค๋ช ๊ณผ ๋ด๋ถ ๊ตฌ์กฐ ๋ถ์, ๊ตฌ์ฑ ์ธ๋ถ์ฌํญ์ ๋ํด ์ค๋ช ํฉ๋๋ค.
์๊ฐ ๋ฐ ํต์ฌ ์์ด๋์ด
์ด ๊ธฐ์ฌ์์๋ Kubernetes ์์ Keycloak ํด๋ฌ์คํฐ๋ฅผ ๋ฐฐํฌํ ๋ ์ผ๋์ ๋์ด์ผ ํ ๊ธฐ๋ณธ ์์ด๋์ด๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
Keycloak์ ๋ํด ๋ ์์ธํ ์๊ณ ์ถ๋ค๋ฉด ๊ธฐ์ฌ ๋ง์ง๋ง์ ์๋ ๋งํฌ๋ฅผ ์ฐธ์กฐํ์ธ์. ์ค๋ฌด์ ๋์ฑ ๋ชฐ์
ํ๊ธฐ ์ํด ๊ณต๋ถํ ์ ์์ต๋๋ค.
Keycloak์ Java๋ก ์์ฑ๋๊ณ ์ ํ๋ฆฌ์ผ์ด์
์๋ฒ ์์ ๊ตฌ์ถ๋ ํฌ๊ด์ ์ธ ์์คํ
์
๋๋ค.
๊ณต์ ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์๊ธฐ ๋ฐ๋๋๋ค.
ํคํด๋กํฌ ์คํ
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๋ช
์ผ๋ก ์ค์ ํ์ฌ ์บ์ ๋ณต์ฌ๋ณธ์ด ์ ์ง๋๋๋ก ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ํด๊ฒฐ์ฑ
์ ์คํํ๋ ๊ฒ์
๋๋ค. /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
.
๋ฐ์ดํฐ ์ผํฐ ๊ฐ ๋ณต์
ะกะฒัะทั
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
.
๋งํฌ ๋ฐ ์ถ๊ฐ ๋ฌธ์
https://www.keycloak.org/docs/latest/server_installation/index.html https://docs.wildfly.org/17/High_Availability_Guide.html#cluster-configuration https://infinispan.org/docs/9.4.x/user_guide/user_guide.html https://hub.docker.com/r/jboss/keycloak https://hub.docker.com/r/jboss/infinispan
์ด ๊ธฐ์ฌ๋ ์ง์๋ค์ด Habr์ ์ํด ๋ฒ์ญํ๊ณ ์ค๋นํ์ต๋๋ค.
์ถ์ฒ : habr.com