Docker: rutekan satu kontainer lewat VPN dan biarkan yang lain langsung
Beri terowongan kontainernya sendiri, biarkan hanya layanan yang membutuhkannya berbagi ruang nama itu, lalu perhitungkan apa yang mengikuti pemiliknya: port, localhost, DNS.
Satu host, dua beban kerja, dan satu persyaratan yang memisahkan keduanya: klien unduhan yang harus keluar melalui VPN komersial, dan antarmuka manajemen yang harus tetap memakai koneksi host. Memasang klien VPN di host langsung menggagalkan persyaratan itu, karena kedua beban kerja lalu berbagi satu jalan keluar. Pola yang benar-benar berhasil adalah memindahkan terowongan ke kontainernya sendiri dan hanya membiarkan beban kerja yang membutuhkannya bergabung dengan ruang nama jaringan kontainer tersebut. Semua yang lain tetap memakai jalur Docker biasa, dan detail berikutnya adalah konsekuensi dari siapa yang memiliki ruang nama itu.
Mengapa ruang nama bersama mengubah aturannya
Kontainer yang bergabung dengan ruang nama kontainer lain tidak mendapat tumpukan jaringannya sendiri. Ia melihat antarmuka yang sama, tabel perutean yang sama, dan loopback yang sama dengan kontainer yang diikutinya, dan itulah sebabnya pola ini berguna: beban kerja menyelesaikan dan menghubungkan diri secara normal, dan terowongan di bawahnya menangkap lalu lintasnya tanpa diketahui aplikasi. Biayanya adalah setiap pengaturan berbau jaringan kini punya satu pemilik, dan kontainer yang bergabung bukanlah pemilik itu.
Aturan kepemilikan itu menjawab sebagian besar pertanyaan konfigurasi sebelum ditanyakan. Jika suatu pengaturan hidup di tumpukan jaringan, ia milik kontainer pendamping. Jika ia menjelaskan prosesnya, ia tetap pada beban kerja.
Loopback adalah bagian yang mengejutkan orang. Di dalam kontainer yang bergabung, localhost diselesaikan ke loopback kontainer pendamping, bukan ke loopback pribadinya sendiri, sehingga layanan yang mengikat ke 127.0.0.1 dan mengharapkan isolasi kini berbagi alamat itu dengan kontainer terowongan.
Publikasikan port pada kontainer yang memiliki ruang nama
Pemetaan port milik pemilik ruang nama meskipun proses yang mendengarkan berjalan di kontainer lain. Deklarasikan pemetaan itu pada kontainer pendamping, dan biarkan beban kerja mempertahankan konfigurasi prosesnya sendiri tanpa disentuh. Pemetaan pada layanan yang bergabung tidak dapat berlaku, entah mesin menolaknya atau diam-diam mengabaikannya tergantung bagaimana kontainer dijalankan, dan itulah sebabnya antarmuka yang tadinya dapat dijangkau menghilang begitu pola ini diterapkan.
services:
gluetun:
image: qmcgaw/gluetun
cap_add: [NET_ADMIN]
ports: ["8080:8080"]
client-vpn:
image: example/client
network_mode: "service:gluetun"
client-direct:
image: example/client
ports: ["8081:8080"]Bacalah blok itu sebagai tiga keputusan, bukan tiga layanan. Kontainer pendamping memiliki terowongan dan port yang dipublikasikan; klien yang bergabung tidak mendeklarasikan jaringan apa pun; klien langsung mempertahankan pemetaannya sendiri di jaringan default. Kemampuan NET_ADMIN itulah yang memungkinkan kontainer pendamping membuat antarmuka dan mengubah rute, dan itulah sebabnya kontainer ini membutuhkan lebih banyak hak istimewa daripada beban kerja yang dilayaninya.
Layanan yang tetap langsung mempertahankan jaringannya sendiri
Beban kerja yang tidak boleh melewati terowongan mempertahankan bridge default atau jaringan yang ditentukan pengguna miliknya sendiri, dengan port yang dipublikasikan dan jalan keluarnya sendiri. Menggoda untuk menempelkannya ke jaringan kontainer pendamping agar kedua kontainer bisa saling bicara berdasarkan nama, tetapi satu langkah itu diam-diam memindahkan lalu lintasnya ke terowongan. Jika keduanya perlu saling menjangkau, bangun jaringan terpisah yang ditentukan pengguna, tempelkan keduanya ke sana, dan biarkan kontainer pendamping menjadi satu-satunya jalan keluar.
Pisahkan kedua pertanyaan: kontainer mana yang dapat saling menjangkau, dan mana yang keluar dari mana. Menggabungkannya adalah cara paling umum desain ini kembali menjadi VPN untuk seluruh host.
Matriks kegagalan untuk jam pertama
Sebagian besar percobaan pertama gagal dengan salah satu dari empat cara, dan masing-masing punya penyebab berbeda. Periksa dalam urutan ini, karena dua yang pertama menjelaskan hampir semua laporan.
| Symptom | Likely cause |
|---|---|
| Web UI unreachable after the change | Port mapping declared on the joining container instead of the sidecar |
| Both containers show the provider's exit address | The direct service was attached to the sidecar network |
| Internal names stop resolving | Resolver settings live on the host, not in the shared namespace |
| Health check fails but the app works | The check probes localhost, which now means the sidecar |
Baris keempat adalah yang orang salah diagnosis sebagai bug aplikasi. Pemeriksaan yang ditulis terhadap loopback beban kerja sendiri kini menguji kontainer terowongan, jadi ia gagal atau melaporkan layanan yang sepenuhnya salah.
Ketika satu nama host membutuhkan terowongan
Kadang terowongan penuh terlalu berlebihan: satu nama internal harus melewati VPN perusahaan sementara soket lokal atau koneksi tampilan tetap bekerja. Terowongan penuh di dalam kontainer memutus jalur itu dan semua yang dialamatkan ke host, jadi rutekan hanya prefiks yang membutuhkannya. Pembungkus perutean terbagi di sekitar klien melakukannya, mengirim nama host yang disebutkan melewati terowongan dan membiarkan rute sebelumnya tidak tersentuh untuk semua yang lain.
Pilih ini ketika Anda hanya perlu menjangkau satu layanan dan tidak berusaha memindahkan seluruh lalu lintas kontainer. Ini alat yang berbeda dari kontainer pendamping dan menjawab pertanyaan yang berbeda.
Verifikasi, lalu buat ia bertahan dari restart
Tanyakan kepada setiap kontainer dari alamat mana ia tampak datang. Yang di terowongan seharusnya mencetak alamat penyedia dan yang langsung mencetak jalan keluar host. Jawaban yang identik berarti layanan langsung mewarisi ruang nama yang salah atau VPN tingkat host masih menangkap semuanya, dan kedua perbaikan itu berbeda. Jalankan pemeriksaan lagi setelah setiap suntingan compose, karena satu blok layanan yang tersalin sudah cukup untuk mengembalikan masalahnya.
Tiga hal cenderung rusak kemudian. DNS mengikuti pemilik ruang nama, jadi pengaturan resolver dan domain pencarian ada pada kontainer pendamping, bukan host. VPN dengan penerusan port mengubah port pendengarannya saat menyambung ulang, jadi port yang diteruskan penyedia dan port pendengar di sisi kontainer harus ditulis kembali ke konfigurasi klien atau ke pemetaan port, biasanya oleh pembaru kecil yang membaca API penyedia. Dan pemeriksaan apa pun yang ditulis terhadap localhost kini menanyakan kontainer terowongan, bukan beban kerja.
Tuliskan pola ini, termasuk kontainer mana yang memiliki ruang nama dan port mana yang menjadi miliknya. Orang berikutnya akan menambahkan layanan, menyalin blok yang salah, dan mereproduksi kegagalan pertama dalam artikel ini.