Layanan terletak di namespace lain

108

Saya telah mencoba menemukan cara untuk mendefinisikan sebuah layanan dalam satu namespace yang terhubung ke sebuah Pod yang berjalan di namespace lain. Saya tahu bahwa container di dalam Pod yang berjalan namespaceAdapat mengakses yang serviceXdidefinisikan namespaceBdengan mereferensikannya di DNS cluster sebagai serviceX.namespaceB.svc.cluster.local, tetapi saya lebih suka tidak memiliki kode di dalam container yang perlu diketahui tentang lokasinya serviceX. Artinya, saya ingin kodenya hanya mencari serviceXdan kemudian dapat mengaksesnya.

The dokumentasi Kubernetes menunjukkan bahwa ini adalah mungkin. Dikatakan bahwa salah satu alasan Anda akan menentukan layanan tanpa pemilih adalah karena Anda ingin mengarahkan layanan Anda ke layanan di Namespace atau cluster lain .

Itu menunjukkan kepada saya bahwa saya harus:

  1. Tentukan serviceXlayanan masuk namespaceA, tanpa pemilih (karena POD yang ingin saya pilih tidak ada namespaceA).
  2. Tentukan layanan (yang juga saya panggil serviceX) namespaceB, lalu
  3. Mendefinisikan suatu objek Endpoint di namespaceAtitik ke serviceXdalam namespaceB.

Ini adalah langkah ketiga yang belum bisa saya capai.

Pertama, saya mencoba mendefinisikan objek Endpoints dengan cara ini:

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

Tampaknya itu pendekatan yang logis, dan jelas untuk apa targetRef. Tapi, ini menyebabkan kesalahan yang mengatakan bahwa ipbidang dalam addressesarray itu wajib. Jadi, percobaan saya selanjutnya adalah menetapkan alamat ClusterIP tetap ke serviceXin namespaceB, dan memasukkannya ke dalam bidang IP (perhatikan bahwa service_cluster_ip_rangedikonfigurasi sebagai 192.168.0.0/16, dan 192.168.1.1ditetapkan sebagai ClusterIP untuk serviceXin namespaceB; serviceXin namespaceAsecara otomatis menetapkan ClusterIP yang berbeda di 192.168.0.0/16subnet) :

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

Itu diterima, tetapi akses ke serviceXmasuk namespaceAtidak diteruskan ke Pod masuk namespaceB- waktu habis. Melihat pengaturan iptables, sepertinya itu harus melakukan pra-routing NAT dua kali untuk mencapai itu.

Satu-satunya hal yang saya lakukan menemukan bahwa bekerja - tapi bukan merupakan solusi yang memuaskan - adalah untuk pencarian alamat IP sebenarnya dari Pod menyediakan serviceXdalam namespaceBdan memasukkan alamat yang di objek Endpoint di namespaceA. Itu tidak memuaskan, tentu saja, karena alamat IP Pod dapat berubah seiring waktu. Itulah IP layanan masalah yang ada untuk dipecahkan.

Jadi, adakah cara untuk memenuhi janji dokumentasi bahwa saya dapat mengarahkan layanan dalam satu namespace ke layanan yang berjalan di namespace berbeda?

Seorang pemberi komentar mempertanyakan mengapa Anda ingin melakukan ini - berikut adalah kasus penggunaan yang masuk akal bagi saya, setidaknya:

Katakanlah Anda memiliki sistem multi-tenant, yang juga menyertakan fungsi akses data umum yang dapat dibagikan di antara penyewa. Sekarang bayangkan bahwa ada ragam yang berbeda dari fungsi akses data ini dengan API umum, tetapi karakteristik kinerja yang berbeda. Beberapa penyewa mendapatkan akses ke salah satunya, penyewa lain memiliki akses ke yang lain.

Setiap pod tenant berjalan di namespace mereka sendiri, tetapi masing-masing perlu mengakses salah satu layanan akses data umum ini, yang tentunya akan berada di namespace lain (karena diakses oleh beberapa tenant). Namun, Anda tidak ingin penyewa harus mengubah kode mereka jika langganan mereka berubah untuk mengakses layanan yang berperforma lebih tinggi.

Solusi potensial (yang paling bersih yang dapat saya pikirkan, jika hanya berhasil) adalah dengan menyertakan definisi layanan di namespace setiap penyewa untuk layanan akses data, dengan masing-masing dikonfigurasi untuk titik akhir yang sesuai. Definisi layanan ini akan dikonfigurasi untuk menunjuk ke layanan akses data yang tepat yang berhak digunakan setiap penyewa.

David McKinley
sumber
inti dari ruang nama adalah untuk mengisolasi, jadi saya pikir jika Anda perlu pergi melintasi ruang nama Anda perlu tahu setidaknya di mana lokasinya!
MrE
Jadi, apa yang dimaksud dengan dokumentasi saat menyarankan Anda dapat mengarahkan layanan yang ditentukan dalam satu namespace untuk mengakses layanan di namespace yang berbeda dengan tidak menentukan pemilih - dan dengan implikasi mendefinisikan titik akhir? Tentu ada kasus penggunaan yang valid untuk ini - salah satunya saya tambahkan ke pertanyaan. Apakah dokumentasinya hanya menyesatkan, atau apakah ada cara untuk melakukannya yang belum saya ketahui?
David McKinley
saya tidak yakin, maaf. yang saya tahu adalah bahwa saya mengakses layanan di beberapa namespace menggunakan fqdn mereka. Saya melakukan ini terutama dengan vpn, karena saya memiliki 1 vpn pod dan saya terhubung melalui semua layanan darinya. namun Anda perlu mengetahui namespace dan menyediakan fqdn. saya sarankan Anda bertanya di saluran kendur.
MrE
Menggunakan fqdn adalah solusi yang saya gunakan saat ini. Kasus penggunaan saya akan lebih baik disajikan, (sekarang ditambahkan ke pertanyaan) jika itu tidak perlu.
David McKinley
Saya juga bertanya-tanya apa yang dirujuk oleh dokumentasi juga, namun saya dapat menggunakan fqdn sebagai solusi yang memuaskan untuk kasus penggunaan saya.
Vincent De Smet

Jawaban:

224

Saya tersandung masalah yang sama dan menemukan solusi bagus yang tidak memerlukan konfigurasi ip statis:

Anda dapat mengakses layanan melalui itu nama DNS-nya (seperti yang Anda sebutkan): servicename.namespace.svc.cluster.local

Anda dapat menggunakan nama DNS itu untuk mereferensikannya di namespace lain melalui layanan lokal :

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
Paul
sumber
2
Ini adalah solusi yang bagus! Saya tidak yakin apakah jenis "ExternalName" tersedia untuk layanan ketika saya awalnya mengajukan pertanyaan, tetapi sekarang didukung, dan memecahkan masalah dengan rapi. Terima kasih, Paul.
David McKinley
1
Apakah ini berhasil? saya ragu. Adakah yang bisa memastikan apakah ini benar-benar berhasil, tidak berhasil untuk saya.
debianmaster
2
Ya, itu benar. Ini berfungsi untuk satu pod untuk berbicara dengan layanan di namespace lain, tetapi tidak untuk loadbalancer masuk.
Paul
karena perbaikan pencarian CNAME kubernetes dalam cluster , versi lama mungkin tidak berfungsi.
赵浩翔
1
Akankah / haruskah ini berfungsi untuk layanan di namespace sistem kube juga?
Nabheet
10

Sangat mudah untuk melakukannya

jika Anda ingin menggunakannya sebagai host dan ingin menyelesaikannya

Jika Anda menggunakan duta besar ke gateway API lain untuk layanan yang terletak di namespace lain, selalu disarankan untuk menggunakan:

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

itu akan menjadi seperti: servicename.namespacename.svc.cluster.local

ini akan mengirimkan permintaan ke layanan tertentu di dalam namespace yang telah Anda sebutkan.

contoh:

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

Di sini ganti <servicename>dan<namespace> dengan nilai yang sesuai.

Di Kubernetes, namespace digunakan untuk membuat lingkungan virtual tetapi semuanya terhubung satu sama lain.

Harsh Manvar
sumber
6
Bisakah Anda menjelaskan bagaimana jawaban ini berbeda dari jawaban Paulus yang diberikan hampir 2 tahun sebelumnya?
Oliver
2
@ Oliver tidak ada perbedaan tetapi saya baru saja menentukan apa yang harus diganti nama layanan dan namespace di tempat tertentu. sementara dia telah menggunakan namespace-a jadi terlihat membingungkan saya.
Harsh Manvar
7
Trik praktis pada SO adalah menambahkan komentar pada jawaban dan membuat klarifikasi yang diperlukan.
Oliver
4
Saya akan menyebut ini sebagai solusi terbaik karena .svc.cluster.localsecara default didukung untuk menyelesaikan layanan secara internal.
DrKNa
1
terbangun untukku juga. terima kasih
vimal prakash
0

Anda dapat mencapainya dengan menerapkan sesuatu pada lapisan yang lebih tinggi daripada Layanan dengan namespace, seperti layanan loadbalancer https://github.com/kubernetes/contrib/tree/master/service-loadbalancer . Jika Anda ingin membatasinya ke satu namespace, gunakan argumen "--namespace = ns" (defaultnya ke semua namespace: https://github.com/kubernetes/contrib/blob/master/service-loadbalancer/service_loadbalancer.go # L715 ). Ini bekerja dengan baik untuk L7, tetapi sedikit berantakan untuk L4.

Prashanth B
sumber
3
Proyek ini tidak berlaku lagi sekarang (Agustus 2018)
Nicola Ben
1
@Prashanth B: Bisakah Anda memperbarui jawaban Anda sesuai dengan itu!
chaosguru