การรัน Keycloak ในโหมด HA บน Kubernetes

การรัน Keycloak ในโหมด HA บน Kubernetes

TL; DR: จะมีคำอธิบายของ Keycloak, ระบบควบคุมการเข้าถึงแบบโอเพ่นซอร์ส, การวิเคราะห์โครงสร้างภายใน, รายละเอียดการกำหนดค่า

บทนำและแนวคิดหลัก

ในบทความนี้ เราจะดูแนวคิดพื้นฐานที่ควรคำนึงถึงเมื่อปรับใช้คลัสเตอร์ Keycloak บน Kubernetes

หากคุณต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับ Keycloak โปรดดูลิงก์ท้ายบทความ เพื่อที่จะได้ดื่มด่ำกับการฝึกฝนมากขึ้น คุณสามารถเรียนได้ พื้นที่เก็บข้อมูลของเรา ด้วยโมดูลที่นำแนวคิดหลักของบทความนี้ไปใช้ (มีคู่มือการเปิดตัวอยู่ที่นั่น บทความนี้จะให้ภาพรวมของอุปกรณ์และการตั้งค่า ประมาณ นักแปล).

Keycloak เป็นระบบที่ครอบคลุมที่เขียนด้วยภาษา Java และสร้างขึ้นบนแอปพลิเคชันเซิร์ฟเวอร์ แมลงวัน. กล่าวโดยสรุป คือ กรอบงานสำหรับการอนุญาตที่ให้ความสามารถในการรวมศูนย์ผู้ใช้แอปพลิเคชันและ SSO (การลงชื่อเข้าระบบครั้งเดียว)

เราขอเชิญคุณอ่านอย่างเป็นทางการ สถาน หรือ วิกิพีเดีย เพื่อความเข้าใจอย่างละเอียด

เปิดตัว Keycloak

Keycloak ต้องการแหล่งข้อมูลถาวรสองแห่งในการทำงาน:

  • ฐานข้อมูลที่ใช้จัดเก็บข้อมูลที่สร้างขึ้น เช่น ข้อมูลผู้ใช้
  • แคช Datagrid ซึ่งใช้ในการแคชข้อมูลจากฐานข้อมูล เช่นเดียวกับการจัดเก็บข้อมูลเมตาที่มีอายุสั้นและเปลี่ยนแปลงบ่อย เช่น เซสชันของผู้ใช้ ดำเนินการแล้ว อินฟินิสแปนซึ่งโดยปกติจะเร็วกว่าฐานข้อมูลอย่างมาก แต่ไม่ว่าในกรณีใด ข้อมูลที่บันทึกไว้ใน Infinispan จะเป็นข้อมูลชั่วคราว และไม่จำเป็นต้องบันทึกที่ใดเลยเมื่อรีสตาร์ทคลัสเตอร์แล้ว

Keycloak ทำงานในสี่โหมดที่แตกต่างกัน:

  • ปกติ - กระบวนการเดียวเท่านั้นที่กำหนดค่าผ่านไฟล์ แบบสแตนด์อโลน.xml
  • คลัสเตอร์ปกติ (ตัวเลือกความพร้อมใช้งานสูง) - กระบวนการทั้งหมดต้องใช้การกำหนดค่าเดียวกัน ซึ่งจะต้องซิงโครไนซ์ด้วยตนเอง การตั้งค่าจะถูกจัดเก็บไว้ในไฟล์ แบบสแตนด์อโลน-ha.xmlนอกจากนี้ คุณต้องทำการเข้าถึงฐานข้อมูลและตัวจัดสรรภาระงานร่วมกัน
  • คลัสเตอร์โดเมน — การเริ่มต้นคลัสเตอร์ในโหมดปกติจะกลายเป็นงานประจำและน่าเบื่ออย่างรวดเร็วเมื่อคลัสเตอร์เติบโตขึ้น เนื่องจากทุกครั้งที่การกำหนดค่าเปลี่ยนแปลง การเปลี่ยนแปลงทั้งหมดจะต้องดำเนินการบนแต่ละโหนดคลัสเตอร์ โหมดการดำเนินการของโดเมนแก้ไขปัญหานี้โดยการตั้งค่าตำแหน่งที่เก็บข้อมูลที่ใช้ร่วมกันและเผยแพร่การกำหนดค่า การตั้งค่าเหล่านี้จะถูกจัดเก็บไว้ในไฟล์ โดเมน.xml
  • การจำลองแบบระหว่างศูนย์ข้อมูล — หากคุณต้องการใช้งาน Keycloak ในกลุ่มศูนย์ข้อมูลหลายแห่ง ซึ่งส่วนใหญ่มักจะอยู่ในตำแหน่งทางภูมิศาสตร์ที่แตกต่างกัน ในตัวเลือกนี้ ศูนย์ข้อมูลแต่ละแห่งจะมีคลัสเตอร์เซิร์ฟเวอร์ Keycloak ของตัวเอง

ในบทความนี้เราจะพิจารณารายละเอียดตัวเลือกที่สองนั่นคือ คลัสเตอร์ปกติและเราจะพูดถึงหัวข้อการจำลองแบบระหว่างศูนย์ข้อมูลอีกเล็กน้อย เนื่องจากเป็นการเหมาะสมที่จะเรียกใช้ตัวเลือกทั้งสองนี้ใน Kubernetes โชคดีที่ไม่มีปัญหาในการซิงโครไนซ์การตั้งค่าของพ็อดต่างๆ ใน ​​Kubernetes (โหนด Keycloak) ดังนั้น คลัสเตอร์โดเมน มันจะไม่ยากมากที่จะทำ

โปรดสังเกตด้วยว่าคำว่า คลัสเตอร์ สำหรับส่วนที่เหลือของบทความจะนำไปใช้กับกลุ่มของโหนด Keycloak ที่ทำงานร่วมกันเท่านั้น ไม่จำเป็นต้องอ้างถึงคลัสเตอร์ Kubernetes

คลัสเตอร์ Keycloak ปกติ

หากต้องการรัน Keycloak ในโหมดนี้ คุณต้องมี:

  • กำหนดค่าฐานข้อมูลที่ใช้ร่วมกันภายนอก
  • ติดตั้งโหลดบาลานเซอร์
  • มีเครือข่ายภายในพร้อมรองรับ IP multicast

เราจะไม่หารือเกี่ยวกับการตั้งค่าฐานข้อมูลภายนอก เนื่องจากไม่ใช่วัตถุประสงค์ของบทความนี้ สมมติว่ามีฐานข้อมูลที่ใช้งานได้ที่ไหนสักแห่ง และเรามีจุดเชื่อมต่อกับฐานข้อมูลนั้น เราจะเพิ่มข้อมูลนี้ลงในตัวแปรสภาพแวดล้อม

เพื่อให้เข้าใจได้ดีขึ้นว่า Keycloak ทำงานอย่างไรในคลัสเตอร์เฟลโอเวอร์ (HA) สิ่งสำคัญคือต้องรู้ว่าทั้งหมดนี้ขึ้นอยู่กับความสามารถในการจัดคลัสเตอร์ของ Wildfly มากเพียงใด

Wildfly ใช้ระบบย่อยหลายระบบ บางส่วนใช้เป็นโหลดบาลานเซอร์ บางส่วนใช้สำหรับความทนทานต่อข้อผิดพลาด ตัวโหลดบาลานซ์ช่วยให้มั่นใจถึงความพร้อมใช้งานของแอปพลิเคชันเมื่อโหนดคลัสเตอร์โอเวอร์โหลด และความทนทานต่อข้อผิดพลาดช่วยให้มั่นใจถึงความพร้อมใช้งานของแอปพลิเคชัน แม้ว่าโหนดคลัสเตอร์บางโหนดจะล้มเหลวก็ตาม ระบบย่อยบางส่วนเหล่านี้:

  • mod_cluster: ทำงานร่วมกับ Apache เป็นตัวโหลดบาลานเซอร์ HTTP โดยขึ้นอยู่กับมัลติคาสต์ 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 ไม่ซ้ำกันสำหรับแต่ละโหนด - คุณสามารถใส่ชื่อของพ็อดได้ หากคุณใส่ชื่อพ็อด อย่าลืมเกี่ยวกับขีดจำกัดอักขระ 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 มัลติคาสต์จะทำงานทันที และโหนด 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.

️ หากคุณใช้มัลติคาสต์และรันคลัสเตอร์ Keycloak สองคลัสเตอร์ขึ้นไปในคลัสเตอร์ Kubernetes เดียว (สมมติว่ามีหนึ่งคลัสเตอร์ในเนมสเปซ production, ที่สอง - staging) - โหนดของคลัสเตอร์ Keycloak หนึ่งสามารถเข้าร่วมคลัสเตอร์อื่นได้ ตรวจสอบให้แน่ใจว่าใช้ที่อยู่มัลติคาสต์ที่ไม่ซ้ำกันสำหรับแต่ละคลัสเตอร์โดยการตั้งค่าตัวแปรjboss.default.multicast.address и jboss.modcluster.multicast.address в JAVA_OPTS.

การจำลองแบบระหว่างศูนย์ข้อมูล

การรัน Keycloak ในโหมด HA บน Kubernetes

ลิงค์

Keycloak ใช้คลัสเตอร์แคช Infinispan แยกกันหลายคลัสเตอร์สำหรับศูนย์ข้อมูลแต่ละแห่งซึ่งมีคลัสเตอร์ Keycloack ที่ประกอบด้วยโหนด Keycloak ตั้งอยู่ แต่ไม่มีความแตกต่างระหว่างโหนด Keycloak ในศูนย์ข้อมูลต่างๆ

โหนด Keycloak ใช้ Java Data Grid (เซิร์ฟเวอร์ Infinispan) ภายนอกเพื่อการสื่อสารระหว่างศูนย์ข้อมูล การสื่อสารทำงานตามระเบียบการ อินฟินิสแปน ฮอทร็อด.

แคช Infinispan ต้องได้รับการกำหนดค่าด้วยแอตทริบิวต์ remoteStoreเพื่อให้สามารถจัดเก็บข้อมูลระยะไกลได้ (ในศูนย์ข้อมูลอื่น ประมาณ นักแปล) แคช มีคลัสเตอร์ Infinispan ที่แยกจากกันระหว่างเซิร์ฟเวอร์ JDG ดังนั้นข้อมูลที่จัดเก็บไว้ใน JDG1 บนไซต์ site1 จะถูกจำลองแบบไปยัง JDG2 บนเว็บไซต์ site2.

และสุดท้าย เซิร์ฟเวอร์ JDG ที่รับจะแจ้งเซิร์ฟเวอร์ Keycloak ของคลัสเตอร์ผ่านการเชื่อมต่อไคลเอ็นต์ ซึ่งเป็นคุณลักษณะของโปรโตคอล HotRod โหนด Keycloak เปิดอยู่ site2 อัปเดตแคช Infinispan และเซสชันผู้ใช้เฉพาะจะพร้อมใช้งานบนโหนด Keycloak ด้วย site2.

สำหรับแคชบางตัว อาจเป็นไปได้ที่จะไม่ทำการสำรองข้อมูลและหลีกเลี่ยงการเขียนข้อมูลผ่านเซิร์ฟเวอร์ Infinispan โดยสิ้นเชิง ในการดำเนินการนี้ คุณจะต้องลบการตั้งค่าออก remote-store แคช Infinispan เฉพาะ (ในไฟล์ แบบสแตนด์อโลน-ha.xml) หลังจากนั้นมีความเฉพาะเจาะจงบางอย่าง replicated-cache จะไม่จำเป็นอีกต่อไปบนฝั่งเซิร์ฟเวอร์ Infinispan

การตั้งค่าแคช

แคชใน Keycloak มีสองประเภท:

  • ท้องถิ่น. ตั้งอยู่ถัดจากฐานข้อมูลและทำหน้าที่ลดภาระในฐานข้อมูลตลอดจนลดเวลาแฝงในการตอบสนอง แคชประเภทนี้จะจัดเก็บขอบเขต ไคลเอนต์ บทบาท และข้อมูลเมตาของผู้ใช้ แคชประเภทนี้จะไม่ถูกจำลองแบบ แม้ว่าแคชจะเป็นส่วนหนึ่งของคลัสเตอร์ Keycloak ก็ตาม หากรายการในแคชเปลี่ยนแปลง ข้อความเกี่ยวกับการเปลี่ยนแปลงจะถูกส่งไปยังเซิร์ฟเวอร์ที่เหลืออยู่ในคลัสเตอร์ หลังจากนั้นรายการจะถูกแยกออกจากแคช ดูคำอธิบาย work ดูด้านล่างสำหรับคำอธิบายโดยละเอียดเพิ่มเติมของขั้นตอน

  • จำลองแบบแล้ว ประมวลผลเซสชันผู้ใช้ โทเค็นออฟไลน์ และยังตรวจสอบข้อผิดพลาดในการเข้าสู่ระบบเพื่อตรวจจับความพยายามในการฟิชชิงรหัสผ่านและการโจมตีอื่นๆ ข้อมูลที่จัดเก็บไว้ในแคชเหล่านี้เป็นข้อมูลชั่วคราว โดยจัดเก็บไว้ใน RAM เท่านั้น แต่สามารถจำลองแบบข้ามคลัสเตอร์ได้

แคช Infinispan

เซสชั่น - แนวคิดใน 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" />

คุณต้องกำหนดค่าและเริ่มต้นคลัสเตอร์ 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.

ลิงค์และเอกสารเพิ่มเติม

บทความนี้ได้รับการแปลและจัดทำขึ้นสำหรับ Habr โดยพนักงาน ศูนย์ฝึกสเลอร์ม — หลักสูตรเข้มข้น หลักสูตรวิดีโอ และการฝึกอบรมระดับองค์กรจากผู้เชี่ยวชาญด้านการฝึกปฏิบัติ (Kubernetes, DevOps, Docker, Ansible, Ceph, SRE)

ที่มา: will.com

เพิ่มความคิดเห็น