Запускаем Keycloak у HA рэжыме на Kubernetes

Запускаем Keycloak у HA рэжыме на Kubernetes

TL, д-р: будзе апісанне Keycloak, сістэмы кантролю доступу з адкрытым зыходным кодам, разбор унутранай прылады, дэталі наладкі.

Увядзенне і асноўныя ідэі

У гэтым артыкуле мы ўбачым асноўныя ідэі, якія варта памятаць пры разгортванні кластара Keycloak па-над Kubernetes.

Калі жадаеце ведаць больш дэталёва пра Keycloak – звернецеся да спасылак у канцы артыкула. Для таго, каб мацней пагрузіцца ў практыку - можаце вывучыць наш рэпазітар з модулем, які рэалізуе асноўныя ідэі гэтага артыкула (кіраўніцтва па запуску там жа, у гэтым артыкуле будзе агляд прылады і налад, заўв. перакладчыка).

Keycloak – гэта комплексная сістэма, напісаная на Java і пабудаваная па-над серверамі прыкладанняў Дзікая муха. Калі коратка, гэта framework для аўтарызацыі, які дае карыстальнікам прыкладанняў федэратыўнасць і магчымасць SSO (single sign-on).

Запрашаем пачытаць афіцыйны сайт або Вікіпедыю для падрабязнага разумення.

Запуск Keycloak

Для Keycloak неабходна дзве стала захоўваемых крыніцы дадзеных для запуску:

  • База даных, якая прымяняецца для захоўвання ўстояных даных, напрыклад інфармацыі аб карыстальніках
  • Datagrid cache, які ўжываецца для кэшавання дадзеных з базы, а таксама для захоўвання некаторых караткажывучых і часта змяняных метададзеных, напрыклад карыстацкіх сесій. Рэлізуецца Infinispan, Які звычайна значна хутчэй базы дадзеных. Але ў любым выпадку якія захоўваюцца ў Infinispan дадзеныя эфемерныя – і іх не трэба куды-небудзь захоўваць пры перазапуску кластара.

Keycloak працуе ў чатырох розных рэжымах:

  • звычайны - адзін і толькі адзін працэс, наладжваецца праз файл standalone.xml
  • Звычайны кластар (высокадаступны варыянт) - усе працэсы павінны выкарыстоўваць адну і тую ж канфігурацыю, якую трэба сінхранізаваць уручную. Налады захоўваюцца ў файле standalone-ha.xml, дадаткова трэба зрабіць агульны доступ да базы дадзеных і балансавальнік нагрузкі.
  • Даменны кластар - запуск кластара ў звычайным рэжыме хутка становіцца руцінным і сумным заняткам пры росце кластара, паколькі кожны раз пры змене канфігурацыі трэба ўсе змены ўнесці на кожным вузле кластара. Даменны рэжым працы вырашае гэтае пытанне шляхам наладкі некаторага агульнага месца захоўвання і публікацыі канфігурацыі. Гэтыя наладкі захоўваюцца ў файле domain.xml
  • Рэплікацыя паміж датацэнтрамі - у выпадку, калі хочаце запусціць Keycloak ў кластары з некалькіх датацэнтраў, часцей за ўсё ў розных месцах геаграфічна. У гэтым варыянце працы кожны датацэнтр будзе мець уласны кластар Keycloak сервераў.

У гэтым артыкуле мы дэталёва разгледзім другі варыянт, гэта значыць звычайны кластар, а таксама крыху закранем тэму наконт рэплікацыі паміж датацэнтрамі, бо гэтыя два варыянты мае сэнс запускаць у Kubernetes. На шчасце ў Kubernetes няма праблемы з сінхранізацыяй налад некалькіх падоў (вузлоў Keycloak), так што даменны кластар будзе не асабліва складана зрабіць.

Таксама калі ласка звярніце ўвагу, што слова кластар да канца артыкула будзе прымяняцца выключна наконт групы вузлоў Keycloak, якія працуюць разам, няма неабходнасці спасылацца на кластар Kubernetes.

Звычайны кластар Keycloak

Для запуску Keycloak у гэтым рэжыме трэба:

  • наладзіць знешнюю агульную базу дадзеных
  • ўсталяваць балансавальнік нагрузкі
  • мець унутраную сетку з падтрымкай ip multicast

Настройку знешняй базы мы разбіраць не будзем, паколькі яна не з'яўляецца мэтай гэтага артыкула. Давайце будзем лічыць, што дзесьці ёсць працуючая база дадзеных - і ў нас да яе ёсць кропка падключэння. Мы проста дадамо гэтыя дадзеныя ў зменныя асяроддзі.

Для лепшага разумення таго, як Keycloak працуе ў абароненай ад збояў (HA) кластары, важна ведаць, як моцна гэта ўсё залежыць ад здольнасцяў Wildfly да кластарызацыі.

Wildfly ужывае некалькі падсістэм, некаторыя з іх выкарыстоўваюцца ў якасці балансавальніка нагрузкі, некаторыя - для адмоваўстойлівасці. Балансавальнік нагрузкі забяспечвае даступнасць прыкладання пры перагрузцы вузла кластара, а адмоваўстойлівасць гарантуе даступнасць прыкладання нават у выпадку адмовы часткі вузлоў кластара. Некаторыя з гэтых падсістэм:

  • mod_cluster: працуе сумесна з Apache у якасці балансавальніка HTTP, залежыць ад TCP multicast для пошуку вузлоў па змаўчанні. Можа быць заменены вонкавым балансавальнікам.

  • infinispan: размеркаваны кэш, які выкарыстоўвае каналы JGroups у якасці транспартнага ўзроўню. Дадаткова можа ўжываць пратакол HotRod для сувязі з вонкавым кластарам Infinispan для сінхранізацыі змесціва кэша.

  • jgroups: дае падтрымку сувязі груп для высокадаступных сэрвісаў на аснове каналаў JGroups. Найменныя каналы дазваляюць асобнікам прыкладання ў кластары злучацца ў групы так, што сувязь валодае такімі ўласцівасцямі, як надзейнасць, спарадкаванасць, адчувальнасць да збояў.

Балансавальнік нагрузкі

Пры ўсталёўцы балансавальніка ў якасці ingress кантролера ў кластары Kubernetes важна мець у выглядзе наступныя рэчы:

Праца Keycloak мае на ўвазе, што выдалены адрас кліента, які падключаецца па HTTP да сервера аўтэнтыфікацыі, з'яўляецца рэальным ip-адрасам кліенцкага кампутара. Налады балансавальніка і ingress павінны карэктна ўсталёўваць загалоўкі HTTP X-Forwarded-For и X-Forwarded-Proto, а таксама захоўваць першапачатковы загаловак HOST. Апошняя версія ingress-nginx (> 0.22.0) адключае гэта па змаўчанні

Актывацыя сцяга proxy-address-forwarding шляхам усталёўкі зменнай асяроддзя PROXY_ADDRESS_FORWARDING в true дае Keycloak разуменне, што ен працуе за proxy.

Таксама трэба ўключыць sticky sessions у ingress. Keycloak прымяняе размеркаваны кэш Infinispan для захавання дадзеных, звязаных з бягучай сесіяй аўтэнтыфікацыі і карыстацкай сесіяй. Кэшы працуюць з адным уладальнікам па змаўчанні, гэта значыць гэтая канкрэтная сесія захоўваецца на некаторым вузле кластара, а іншыя вузлы павінны запытваць яе выдалена, калі ім спатрэбіцца доступ да гэтай сесіі.

Канкрэтна ў нас насуперак дакументацыі не спрацавала прымацаванне сесіі з імем cookie AUTH_SESSION_ID. Keycloak зацыкліў перанакіраванне, таму мы рэкамендуем абраць іншае імя cookie для sticky session.

Таксама Keycloak прымацоўвае імя вузла, які адказаў першым, да AUTH_SESSION_ID, а паколькі кожны вузел у высокадаступным варыянце выкарыстоўвае адну і тую ж базу дадзеных, кожны з іх павінен мець асобны і ўнікальны ідэнтыфікатар вузла для кіравання транзакцыямі. Рэкамендуецца ставіць у JAVA_OPTS параметры jboss.node.name и jboss.tx.node.id унікальнымі для кожнага вузла - можна да прыкладу ставіць імя пода. Калі будзеце ставіць імя пода - не забывайце пра абмежаванне ў 23 знака для зменных jboss, так што лепш выкарыстоўваць StatefulSet, а не Deployment.

Яшчэ адны граблі - калі пад выдаляецца або перазапускаецца, яго кэш губляецца. З улікам гэтага варта ўсталяваць лік уладальнікаў кэша для ўсіх кэшаў не менш за ў два, так будзе заставацца копія кэша. Рашэнне - запусціць скрыпт для 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 multicast

Калі ўжываеце Weavenet у якасці CNI, multicast будзе працаваць адразу ж – і вашыя вузлы Keycloak будуць бачыць адзін аднаго, як толькі будуць запушчаныя.

Калі ў вас няма падтрымкі ip multicast у кластары Kubernetes, можна наладзіць 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.

️ Калі выкарыстоўваеце multicast і запускаеце два і больш кластараў Keycloak у адным кластары Kubernetes (дапусцім адзін у namespace production, другі - staging) - вузлы аднаго кластара Keycloak могуць далучыцца да іншага кластара. Абавязкова выкарыстоўвайце унікальны multicast адрас для кожнага кластара шляхам усталёўкі зменныхjboss.default.multicast.address и jboss.modcluster.multicast.address в JAVA_OPTS.

Рэплікацыя паміж датацэнтрамі

Запускаем Keycloak у HA рэжыме на Kubernetes

Сувязь

Keycloak выкарыстоўвае множныя асобныя кластара кэшаў Infinispan для кожнага датацэнтра, дзе размешчаны кластара Keycloack, складзеныя з вузлоў Keycloak. Але пры гэтым няма розніцы паміж вузламі Keycloak у розных датацэнтрах.

Вузлы Keycloak выкарыстоўваюць знешнюю Java Data Grid (сервера Infinispan) для сувязі паміж датацэнтрамі. Сувязь працуе па пратаколе Infinispan HotRod.

Кэшы Infinispan павінны быць настроены з атрыбутам remoteStore, для таго, каб дадзеныя маглі захоўвацца ў выдаленых (у іншым датацэнтры, заўв. перакладчыка) кэшах. Ёсць асобныя кластара infinispan сярод JDG сервераў, так што дадзеныя, якія захоўваюцца на JDG1 на пляцоўцы site1 будуць рэплікаваны на JDG2 на пляцоўцы site2.

Ну і нарэшце, які прымае сервер JDG апавяшчае сервера Keycloak свайго кластара праз кліенцкія злучэнні, што з'яўляецца асаблівасцю пратаколу HotRod. Вузлы Keycloak на site2 абнаўляюць свае кэшы Infinispan, і канкрэтная карыстацкая сесія становіцца таксама даступнай на вузлах Keycloak на site2.

Для некаторых кэшаў таксама магчыма не рабіць рэзервовыя копіі і поўнасцю адмовіцца ад запісу дадзеных праз сервер Infinispan. Для гэтага трэба прыбраць настройку remote-store канкрэтнаму кэшу Infinispan (у файле standalone-ha.xml), пасля чаго некаторы канкрэтны replicated-cache таксама перастане быць патрэбным на баку Infinispan сервера.

Настройка кэшаў

Ёсць два тыпу кэшаў у Keycloak:

  • Лакальны. Ён размешчаны побач з базай, служыць для памяншэння нагрузкі на базу даных, а таксама для зніжэння затрымкі адказу. У гэтым тыпе кэша захоўваецца realm, кліенты, ролі і прыстасаваныя метададзеныя. Гэты тып кэша не рэплікуецца, нават калі гэты кэш - частка кластара Keycloak. Калі змяняецца некаторы запіс у кэшы - астатнім серверам у кластары адпраўляецца паведамленне аб змене, пасля чаго запіс выключаецца з кэша. Глядзіце апісанне work далей, для больш дэталёвага апісання працэдуры.

  • Рэпліцыруемы. Апрацоўвае карыстацкія сесіі, offline токены, а таксама сочыць за памылкамі ўваходу для вызначэння спроб фішынгу пароляў і іншых нападаў. Захоўныя дадзеныя ў гэтым кэшах - часовыя, захоўваюцца толькі ў аператыўнай памяці, але могуць быць рэплікаваны па кластары.

Кэшы Infinispan

Сесіі - канцэпцыя ў Keycloak, асобныя кэшы, якія называюцца authenticationSessions, прымяняюцца для захоўвання дадзеных канкрэтных карыстальнікаў. Запыты з гэтых кэшаў звычайна патрэбныя браўзэру і серверам Keycloak, не прыкладанням. Тут і выяўляецца залежнасць ад sticky sessions, а самі такія кэшы не трэба рэплікаваць, нават і ў выпадку Active-Active рэжыму.

Такены дзеянні. Чарговая канцэпцыя звычайна ўжываецца для розных сцэнараў, калі, да прыкладу, карыстач павінен зрабіць нешта асінхронна па пошце. Напрыклад, падчас працэдуры forget password кэш actionTokens ужываецца для адсочвання метададзеных злучаных токенаў - да прыкладу токен ужо выкарыстаны, і не можа быць актываваны паўторна. Гэты тып кэша звычайна павінен рэпліцыравацца паміж датацэнтрамі.

Кэшаванне і састарванне захоўваемых дадзеных працуе для таго, каб зняць нагрузку з базы даных. Падобнае кэшаванне паляпшае прадукцыйнасць, але дадае відавочную праблему. Калі адзін сервер Keycloak абнаўляе дадзеныя, астатнія серверы павінны быць абвешчаныя аб гэтым, каб яны маглі правесці актуалізацыю дадзеных у сваіх кэшах. Keycloak выкарыстоўвае лакальныя кэшы realms, users и authorization для кэшавання дадзеных з базы.

Таксама ёсць асобны кэш work, які рэплікуецца па ўсіх датацэнтрах. Сам ён не захоўвае якіх-небудзь дадзеных з базы, а служыць для адпраўкі паведамленняў аб састарэнні дадзеных вузлам кластара паміж датацэнтрамі. Іншымі словамі, як толькі дадзеныя абнаўляюцца, вузел Keycloak пасылае паведамленне іншым вузлам у сваім датацэнтры, а таксама вузлам іншых датацэнтраў. Пасля атрымання такога паведамлення кожны вузел праводзіць чыстку адпаведных дадзеных у сваіх лакальных кэшах.

Карыстальніцкія сесіі. Кэшы з імёнамі sessions, clientSessions, offlineSessions и offlineClientSessions, звычайна рэпліцыруюцца паміж датацэнтрамі і служаць для захоўвання дадзеных аб карыстацкіх сесіях, якія актыўныя падчас актыўнасці карыстальніка ў браўзэры. Гэтыя кэшы працуюць з дадаткам, які апрацоўвае запыты HTTP ад канчатковых карыстальнікаў, так што яны звязаны з sticky sessions і павінны рэпліцыравацца паміж датацэнтрамі.

Абарона ад перабору грубай сілай. Кэш 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" />

Неабходна наладзіць і запусціць кластар Infinispan перад запускам кластара Keycloak

Затым трэба наладзіць 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 для вузлоў Keycloak для працы HotRod: remote.cache.host, remote.cache.port і імя сэрвісу jboss.site.name.

Спасылкі і дадатковая дакументацыя

Артыкул перакладзены і падрыхтаваны для Хабра супрацоўнікамі навучальнага цэнтра Слёрм - Інтэнсіўы, видеокурсы і карпаратыўнае навучанне ад практыкуючых спецыялістаў (Kubernetes, DevOps, Docker, Ansible, Ceph, SRE)

Крыніца: habr.com

Дадаць каментар