บริการที่อยู่ในเนมสเปซอื่น


125

ฉันพยายามหาวิธีกำหนดบริการในเนมสเปซเดียวที่ลิงก์ไปยัง Pod ที่ทำงานในเนมสเปซอื่น ฉันรู้ว่าคอนเทนเนอร์ใน Pod ที่ทำงานอยู่namespaceAสามารถเข้าถึงที่serviceXกำหนดnamespaceBโดยการอ้างอิงใน DNS คลัสเตอร์เป็นserviceX.namespaceB.svc.cluster.localแต่ฉันไม่อยากมีรหัสภายในคอนเทนเนอร์ที่จำเป็นต้องรู้เกี่ยวกับตำแหน่งของserviceX . นั่นคือฉันต้องการให้โค้ดค้นหาserviceXจากนั้นจึงจะสามารถเข้าถึงได้

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

นั่นชี้ให้ฉันทราบว่าฉันควร:

  1. กำหนดserviceXบริการในnamespaceAโดยไม่มีตัวเลือก (เนื่องจาก POD ที่ฉันต้องการเลือกไม่อยู่ในnamespaceA)
  2. กำหนดบริการ (ซึ่งฉันเรียกว่าserviceX) ในnamespaceBแล้ว
  3. กำหนดวัตถุปลายทางในnamespaceAการชี้ไปในserviceXnamespaceB

นี่เป็นขั้นตอนที่สามที่ฉันไม่สามารถทำได้สำเร็จ

ก่อนอื่นฉันลองกำหนดวัตถุปลายทางด้วยวิธีนี้:

kind: Endpoints
apiVersion: v1
metadata:
  name: serviceX
  namespace: namespaceA
subsets:
  - addresses:
      - targetRef:
          kind: Service
          namespace: namespaceB
          name: serviceX
          apiVersion: v1
    ports:
      - name: http
        port: 3000

นั่นดูเหมือนเป็นวิธีการเชิงตรรกะและชัดเจนว่าtargetRefมีไว้เพื่ออะไร แต่สิ่งนี้นำไปสู่ข้อผิดพลาดที่บอกว่าจำเป็นต้องกรอกipฟิลด์ในaddressesอาร์เรย์ ดังนั้นความพยายามครั้งต่อไปของฉันคือกำหนดที่อยู่ ClusterIP คงที่ให้serviceXในnamespaceBและใส่ไว้ในฟิลด์ IP (โปรดทราบว่าservice_cluster_ip_rangeมีการกำหนดค่าเป็น192.168.0.0/16และ192.168.1.1ถูกกำหนดเป็น ClusterIP สำหรับserviceXin namespaceB; serviceXin namespaceAถูกกำหนด ClusterIP ที่แตกต่างกันโดยอัตโนมัติบน192.168.0.0/16เครือข่ายย่อย) :

kind: Endpoints
apiVersion: v1
metadata:
  name: serviceX
  namespace: namespaceA
subsets:
  - addresses:
        - ip: 192.168.1.1
          targetRef:
            kind: Service
            namespace: namespaceB
            name: serviceX
            apiVersion: v1
    ports:
      - name: http
        port: 3000

สิ่งนี้ได้รับการยอมรับ แต่การเข้าถึงserviceXในnamespaceAไม่ได้รับการส่งต่อไปยัง Pod innamespaceB - หมดเวลา เมื่อดูการตั้งค่า iptables ดูเหมือนว่าจะต้องทำการกำหนดเส้นทางล่วงหน้าของ NAT สองครั้งเพื่อให้บรรลุเป้าหมายนั้น

สิ่งเดียวที่ฉันพบว่าใช้งานได้ - แต่ไม่ใช่วิธีแก้ปัญหาที่น่าพอใจ - คือการค้นหาที่อยู่ IP จริงของ Pod ที่ให้มา serviceXในnamespaceBและวางอยู่ว่าในปลายทางวัตถุในnamespaceAและวางอยู่ว่าในปลายทางวัตถุในแน่นอนว่าไม่น่าพอใจเพราะที่อยู่ IP ของ Pod อาจมีการเปลี่ยนแปลงเมื่อเวลาผ่านไป นั่นคือ IP ของบริการที่มีปัญหาเพื่อแก้ปัญหา

ดังนั้นมีวิธีใดบ้างที่จะตอบสนองสิ่งที่ดูเหมือนจะเป็นสัญญาของเอกสารที่ฉันสามารถชี้บริการในเนมสเปซเดียวไปยัง บริการทำงานในเนมสเปซอื่นได้

ผู้แสดงความคิดเห็นถามว่าทำไมคุณถึงต้องการทำสิ่งนี้ - นี่คือกรณีการใช้งานที่สมเหตุสมผลสำหรับฉันอย่างน้อย:

สมมติว่าคุณมีระบบผู้เช่าหลายระบบซึ่งรวมถึงฟังก์ชันการเข้าถึงข้อมูลทั่วไปที่สามารถใช้ร่วมกันระหว่างผู้เช่าได้ ทีนี้ลองนึกดูว่าฟังก์ชันการเข้าถึงข้อมูลนี้มีรสชาติที่แตกต่างกันกับ API ทั่วไป แต่มีลักษณะการทำงานที่แตกต่างกัน ผู้เช่าบางรายสามารถเข้าถึงหนึ่งในนั้นผู้เช่ารายอื่นสามารถเข้าถึงอีกรายหนึ่งได้

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

วิธีแก้ปัญหาที่เป็นไปได้ (วิธีที่สะอาดที่สุดที่ฉันคิดได้ถ้ามันใช้งานได้) คือการรวมคำจำกัดความของบริการไว้ในเนมสเปซของผู้เช่าแต่ละรายสำหรับบริการการเข้าถึงข้อมูลโดยแต่ละรายการได้รับการกำหนดค่าสำหรับปลายทางที่เหมาะสม ข้อกำหนดบริการนี้จะถูกกำหนดค่าให้ชี้ไปที่บริการเข้าถึงข้อมูลที่เหมาะสมที่ผู้เช่าแต่ละรายมีสิทธิ์ใช้


จุดสำคัญของเนมสเปซคือการแยกดังนั้นฉันคิดว่าถ้าคุณต้องการข้ามเนมสเปซคุณต้องรู้อย่างน้อยว่ามันอยู่ที่ไหน!
MrE

ดังนั้นเอกสารหมายความว่าอย่างไรเมื่อแนะนำให้คุณกำหนดบริการที่กำหนดในเนมสเปซเดียวเพื่อเข้าถึงบริการในเนมสเปซอื่นโดยไม่กำหนดตัวเลือก - และโดยนัยที่กำหนดจุดสิ้นสุด มีกรณีการใช้งานที่ถูกต้องสำหรับกรณีนี้ซึ่งเป็นหนึ่งในกรณีที่ฉันได้เพิ่มเข้าไปในคำถาม เอกสารนี้ทำให้เข้าใจผิดหรือมีวิธีดำเนินการที่ฉันยังไม่ทราบหรือไม่
David McKinley

ฉันไม่แน่ใจขอโทษ สิ่งที่ฉันรู้คือฉันเข้าถึงบริการในหลายเนมสเปซโดยใช้ fqdn ฉันทำสิ่งนี้โดยเฉพาะกับ vpn เนื่องจากฉันมี 1 vpn pod และฉันเชื่อมต่อผ่านบริการทั้งหมดจากมัน อย่างไรก็ตามคุณต้องรู้เนมสเปซและระบุ fqdn ฉันขอแนะนำให้คุณถามเกี่ยวกับช่องหย่อน
MrE

การใช้ fqdn เป็นวิธีแก้ปัญหาที่ฉันกำลังใช้อยู่ อย่างไรก็ตามกรณีการใช้งานของฉันจะได้รับการบริการที่ดีกว่า (ตอนนี้ถูกเพิ่มเข้าไปในคำถาม) หากไม่จำเป็น
David McKinley

ฉันยังสงสัยว่าเอกสารนี้อ้างถึงอะไรเช่นกันอย่างไรก็ตามฉันสามารถใช้ fqdn เป็นโซลูชันที่น่าพอใจสำหรับกรณีการใช้งานของฉัน
Vincent De Smet

คำตอบ:


249

ฉันสะดุดกับปัญหาเดียวกันและพบวิธีแก้ปัญหาที่ดีซึ่งไม่ต้องการการกำหนดค่า IP แบบคงที่:

คุณสามารถเข้าถึงบริการผ่านชื่อ DNS (ตามที่คุณกล่าวถึง): servicename.namespace.svc.cluster.local

คุณสามารถใช้ชื่อ DNS นั้นเพื่ออ้างอิงในเนมสเปซอื่นผ่านบริการในพื้นที่ :

kind: Service
apiVersion: v1
metadata:
  name: service-y
  namespace: namespace-a
spec:
  type: ExternalName
  externalName: service-x.namespace-b.svc.cluster.local
  ports:
  - port: 80

2
นี่เป็นทางออกที่ยอดเยี่ยม! ฉันไม่แน่ใจว่าประเภท "ชื่อภายนอก" พร้อมใช้งานสำหรับบริการเมื่อฉันถามคำถามครั้งแรกหรือไม่ แต่ตอนนี้รองรับแล้วและแก้ไขปัญหาได้อย่างเรียบร้อย ขอบคุณพอล
David McKinley

1
มันใช้ได้ไหม? ฉันสงสัย. ใครสามารถยืนยันได้ว่าสิ่งนี้ได้ผลจริงไม่ได้ผลสำหรับฉัน
debianmaster

3
ใช่. ใช้งานได้กับพ็อดหนึ่งเพื่อพูดคุยกับบริการในเนมสเปซอื่น แต่ไม่ใช่สำหรับโหลดบาลานซ์ขาเข้า
พอล

เนื่องจากการแก้ไข kubernetes ในคลัสเตอร์การค้นหา CNAMEเวอร์ชันเก่าอาจใช้งานไม่ได้
赵浩翔

1
สิ่งนี้จะใช้ได้กับบริการในเนมสเปซระบบ kube ด้วยหรือไม่
Nabheet

15

มันง่ายมากที่จะทำ

หากคุณต้องการใช้เป็นโฮสต์และต้องการแก้ไข

หากคุณใช้ทูตไปยังเกตเวย์ API อื่นสำหรับบริการที่อยู่ในเนมสเปซอื่นขอแนะนำให้ใช้เสมอ:

            Use : <service name>
            Use : <service.name>.<namespace name>
            Not : <service.name>.<namespace name>.svc.cluster.local

มันจะเป็นเช่น: servicename.namespacename.svc.cluster.local

สิ่งนี้จะส่งคำขอไปยังบริการเฉพาะภายในเนมสเปซที่คุณกล่าวถึง

ตัวอย่าง:

kind: Service
apiVersion: v1
metadata:
  name: service
spec:
  type: ExternalName
  externalName: <servicename>.<namespace>.svc.cluster.local

ที่นี่แทนที่<servicename>และ<namespace>ด้วยค่าที่เหมาะสม

ใน Kubernetes มีการใช้เนมสเปซเพื่อสร้างสภาพแวดล้อมเสมือนจริง แต่ทั้งหมดเชื่อมต่อถึงกัน


6
คุณช่วยอธิบายได้ไหมว่าคำตอบนี้แตกต่างจากที่ Paul ให้ไว้เมื่อเกือบ 2 ปีก่อนหน้านี้อย่างไร
Oliver

2
@ โอลิเวอร์ไม่มีความแตกต่าง แต่ฉันเพิ่งระบุสิ่งที่จะแทนที่ชื่อบริการและเนมสเปซที่สถานที่เฉพาะ ในขณะที่เขาใช้เนมสเปซ - เอก็ดูสับสนสำหรับฉัน
Harsh Manvar

8
เคล็ดลับที่มีประโยชน์สำหรับ SO คือการเพิ่มความคิดเห็นเกี่ยวกับคำตอบและให้คำชี้แจงที่จำเป็น
Oliver

4
ฉันจะเรียกสิ่งนี้ว่าเป็นทางออกที่ดีที่สุดเพราะ.svc.cluster.localโดยค่าเริ่มต้นได้รับการสนับสนุนสำหรับการแก้ไขบริการภายใน
DrKNa

1

ในการเข้าถึงบริการในสองเนมสเปซที่แตกต่างกันคุณสามารถใช้ url ดังนี้:

HTTP://<your-service-name>.<namespace-with-that-service>.svc.cluster.local

ในการแสดงรายการเนมสเปซทั้งหมดของคุณคุณสามารถใช้:

kubctl get namespace

และสำหรับบริการในเนมสเปซนั้นคุณสามารถใช้:

kubctl get services -n <namespace-name>

สิ่งนี้จะช่วยคุณได้


0

คุณสามารถบรรลุนี้โดยการปรับใช้บางสิ่งบางอย่างที่เป็นชั้นที่สูงกว่าบริการ namespaced เช่น loadbalancer บริการ https://github.com/kubernetes/contrib/tree/master/service-loadbalancer หากคุณต้องการ จำกัด เฉพาะเนมสเปซเดียวให้ใช้อาร์กิวเมนต์ "--namespace = ns" (ค่าเริ่มต้นสำหรับเนมสเปซทั้งหมด: https://github.com/kubernetes/contrib/blob/master/service-loadbalancer/service_loadbalancer.go # L715 ). สิ่งนี้ใช้ได้ดีกับ L7 แต่ค่อนข้างยุ่งสำหรับ L4


3
โครงการนี้เลิกใช้แล้ว (
Nicola Ben

1
@Prashanth B: คุณช่วยอัพเดทคำตอบของคุณได้ไหม!
Chaosguru
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.