Dịch vụ nằm trong không gian tên khác


107

Tôi đã cố gắng tìm cách xác định một dịch vụ trong một không gian tên liên kết đến một Pod đang chạy trong một không gian tên khác. Tôi biết rằng các vùng chứa trong Pod đang chạy trong namespaceAcó thể truy cập serviceXđược xác định trong namespaceBbằng cách tham chiếu nó trong DNS cụm serviceX.namespaceB.svc.cluster.local, nhưng tôi không muốn có mã bên trong vùng chứa cần biết về vị trí của serviceX. Đó là, tôi muốn mã chỉ cần tra cứu serviceXvà sau đó có thể truy cập nó.

Các tài liệu Kubernetes gợi ý rằng điều này là có thể. Nó nói rằng một trong những lý do mà bạn sẽ xác định dịch vụ mà không có bộ chọn là Bạn muốn trỏ dịch vụ của mình đến một dịch vụ trong Không gian tên khác hoặc trên một cụm khác .

Điều đó gợi ý cho tôi rằng tôi nên:

  1. Xác định một serviceXdịch vụ trong đó namespaceA, không có bộ chọn (vì POD tôi muốn chọn không có trong đó namespaceA).
  2. Xác định một dịch vụ (mà tôi cũng đã gọi serviceX) namespaceB, và sau đó
  3. Xác định một đối tượng thiết bị đầu cuối trong namespaceAđể trỏ đến serviceXnamespaceB.

Đây là bước thứ ba mà tôi đã không thể thực hiện được.

Đầu tiên, tôi đã thử xác định đối tượng Endpoints theo cách này:

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

Đó có vẻ là cách tiếp cận hợp lý, và rõ ràng là để làmtargetRef. Tuy nhiên, điều này dẫn đến lỗi nói rằng iptrường trong addressesmảng là bắt buộc. Vì vậy, lần thử tiếp theo của tôi là gán một địa chỉ ClusterIP cố định serviceXvào namespaceBvà đặt địa chỉ đó vào trường IP (lưu ý rằng địa chỉ đó service_cluster_ip_rangeđược định cấu hình 192.168.0.0/16192.168.1.1được gán là ClusterIP cho serviceXtrong namespaceB; serviceXtrong namespaceAđược tự động gán một ClusterIP khác trên 192.168.0.0/16mạng con) :

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

Điều đó đã được chấp nhận, nhưng quyền truy cập serviceXvào namespaceAkhông được chuyển tiếp đến Pod in namespaceB- chúng đã hết thời gian chờ. Nhìn vào thiết lập iptables, có vẻ như nó sẽ phải thực hiện định tuyến trước NAT hai lần để thực hiện điều đó.

Điều duy nhất tôi đã tìm thấy rằng làm việc - nhưng không phải là một giải pháp thỏa đáng - là để tra cứu địa chỉ IP thực tế của Pod cung cấp serviceXtrong namespaceBvà đưa địa chỉ đó trong đối tượng thiết bị đầu cuối trong namespaceA. Tất nhiên, điều đó không thỏa đáng vì địa chỉ IP của Pod có thể thay đổi theo thời gian. Đó là vấn đề mà IP dịch vụ phải giải quyết.

Vì vậy, có cách nào để đáp ứng những gì dường như là lời hứa của tài liệu rằng tôi có thể trỏ một dịch vụ trong một không gian tên đến một dịch vụ đang chạy trong một không gian tên khác không?

Một người bình luận đã đặt câu hỏi tại sao bạn muốn làm điều này - đây là một trường hợp sử dụng có ý nghĩa đối với tôi, ít nhất là:

Giả sử bạn có một hệ thống nhiều người thuê, cũng bao gồm một chức năng truy cập dữ liệu chung có thể được chia sẻ giữa những người thuê. Bây giờ hãy tưởng tượng rằng có những hương vị khác nhau của chức năng truy cập dữ liệu này với các API thông thường, nhưng các đặc điểm hiệu suất khác nhau. Một số người thuê có quyền truy cập vào một trong số chúng, những người thuê khác có quyền truy cập vào một cái khác.

Mỗi nhóm của người thuê chạy trong không gian tên riêng của họ, nhưng mỗi nhóm cần phải truy cập một trong những dịch vụ truy cập dữ liệu chung này, nhất thiết sẽ nằm trong một không gian tên khác (vì nó được nhiều người thuê truy cập). Tuy nhiên, bạn sẽ không muốn người thuê phải thay đổi mã của họ nếu đăng ký của họ thay đổi để truy cập dịch vụ có hiệu suất cao hơn.

Một giải pháp tiềm năng (giải pháp sạch nhất mà tôi có thể nghĩ đến, nếu chỉ nó hoạt động) là bao gồm định nghĩa dịch vụ trong không gian tên của mỗi đối tượng thuê cho dịch vụ truy cập dữ liệu, với mỗi giải pháp được định cấu hình cho điểm cuối thích hợp. Định nghĩa dịch vụ này sẽ được cấu hình để trỏ đến dịch vụ truy cập dữ liệu thích hợp mà mỗi người thuê được quyền sử dụng.


điểm của không gian tên là tách biệt, vì vậy tôi nghĩ nếu bạn cần đi qua không gian tên, bạn cần biết ít nhất nó nằm ở đâu!
MrE

Vì vậy, tài liệu có ý nghĩa gì khi nó gợi ý bạn có thể hướng một dịch vụ được xác định trong một không gian tên để truy cập một dịch vụ trong một không gian tên khác bằng cách không xác định bộ chọn - và bằng cách xác định một điểm cuối? Chắc chắn có những trường hợp sử dụng hợp lệ cho việc này - một trong số đó tôi đã thêm vào câu hỏi. Có phải tài liệu chỉ là sai lệch, hoặc có cách nào để làm điều đó mà tôi chưa tìm ra?
David McKinley

Tôi không chắc, xin lỗi. những gì tôi biết là tôi truy cập các dịch vụ trong nhiều không gian tên bằng cách sử dụng fqdn của chúng. Tôi làm điều này đặc biệt với vpn, vì tôi có 1 vpn pod và tôi kết nối thông qua tất cả các dịch vụ từ nó. tuy nhiên bạn cần biết không gian tên và cung cấp fqdn. tôi sẽ đề nghị bạn hỏi trên kênh slack.
MrE

Sử dụng fqdn là giải pháp hiện tôi đang sử dụng. Tuy nhiên, trường hợp sử dụng của tôi sẽ được phục vụ tốt hơn (bây giờ được thêm vào câu hỏi) nếu điều đó không cần thiết.
David McKinley

Tôi cũng tự hỏi tài liệu đang đề cập đến điều gì, tuy nhiên tôi có thể sử dụng fqdn như một giải pháp thỏa đáng cho trường hợp sử dụng của mình.
Vincent De Smet

Câu trả lời:


221

Tôi tình cờ gặp vấn đề tương tự và tìm thấy một giải pháp tuyệt vời mà không cần bất kỳ cấu hình ip tĩnh nào:

Bạn có thể truy cập một dịch vụ thông qua tên DNS của nó (như bạn đã đề cập): servicename.namespace.svc.cluster.local

Bạn có thể sử dụng tên DNS đó để tham chiếu nó trong một không gian tên khác thông qua một dịch vụ cục bộ :

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
Đây là một giải pháp tuyệt vời! Tôi không chắc liệu loại "Tên bên ngoài" có khả dụng cho các dịch vụ khi tôi đặt câu hỏi ban đầu hay không, nhưng hiện tại nó đã được hỗ trợ và giải quyết vấn đề một cách gọn gàng. Cảm ơn, Paul.
David McKinley

1
Điều này có hiệu quả không? tôi nghi ngờ. bất cứ ai có thể xác nhận nếu điều này thực sự làm việc, không làm việc cho tôi.
debianmaster,

2
Đúng vậy. Nó hoạt động đối với một nhóm để nói chuyện với một dịch vụ trong một không gian tên khác, nhưng không hoạt động đối với một trình cân bằng tải xâm nhập.
Paul

sửa chữa kubernetes tra cứu CNAME trong cụm , phiên bản cũ có thể không hoạt động.
赵浩翔

1
Liệu điều này có hoạt động cho các dịch vụ trong không gian tên hệ thống kube không?
Nabheet

10

Nó rất đơn giản để làm điều đó

nếu bạn muốn sử dụng nó làm máy chủ lưu trữ và muốn giải quyết nó

Nếu bạn đang sử dụng sứ giả cho bất kỳ cổng API nào khác cho dịch vụ nằm trong không gian tên khác, nó luôn được đề xuất sử dụng:

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

nó sẽ giống như: servicename.namespacename.svc.cluster.local

điều này sẽ gửi yêu cầu đến một dịch vụ cụ thể bên trong không gian tên mà bạn đã đề cập.

thí dụ:

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

Ở đây thay thế <servicename><namespace>bằng giá trị thích hợp.

Trong Kubernetes, không gian tên được sử dụng để tạo môi trường ảo nhưng tất cả đều kết nối với nhau.


6
Bạn có thể giải thích câu trả lời này có gì khác so với câu trả lời của Paul được cung cấp gần 2 năm trước đó không?
Oliver

2
@Oliver không có sự khác biệt nhưng tôi vừa chỉ định những gì để thay thế tên dịch vụ và không gian tên tại nơi cụ thể. trong khi anh ấy đã sử dụng không gian tên-a nên có vẻ khó hiểu với tôi.
Harsh Manvar

6
Một mẹo hữu ích trên SO là thêm nhận xét về câu trả lời và làm rõ cần thiết.
Oliver

4
Tôi gọi đây là giải pháp tốt nhất vì .svc.cluster.localđược hỗ trợ theo mặc định để giải quyết dịch vụ nội bộ.
DrKNa

1
cũng thích thú cho tôi. thankyou
vimal prakash

0

Bạn có thể đạt được điều này bằng cách triển khai thứ gì đó ở lớp cao hơn Dịch vụ có không gian tên, như bộ tải dịch vụ https://github.com/kubernetes/contrib/tree/master/service-loadbalancer . Nếu bạn muốn giới hạn nó trong một vùng tên duy nhất, hãy sử dụng đối số "--namespace = ns" (nó mặc định cho tất cả các vùng tên: https://github.com/kubernetes/contrib/blob/master/service-loadbalancer/service_loadbalancer.go # L715 ). Điều này hoạt động tốt cho L7, nhưng hơi lộn xộn cho L4.


3
Dự án này hiện không được dùng nữa (
Nicola Ben

1
@Prashanth B: Bạn có thể cập nhật câu trả lời của mình cho phù hợp không!
messguru
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.