Image
Kamu membuat Docker image dan mengunduhnya ke sebuah registri sebelum digunakan di dalam Kubernetes Pod.
Properti image
dari sebuah Container mendukung sintaksis yang sama seperti perintah docker
, termasuk registri privat dan tag.
Memperbarui Image
Kebijakan pull default adalah IfNotPresent
yang membuat Kubelet tidak
lagi mengunduh (pull) sebuah image jika sudah ada terlebih dahulu. Jika kamu ingin agar
selalu diunduh, kamu bisa melakukan salah satu dari berikut:
- mengatur
imagePullPolicy
dari Container menjadiAlways
. - buang
imagePullPolicy
dan gunakan:latest
tag untuk image yang digunakan. - buang
imagePullPolicy
dan juga tag untuk image. - aktifkan AlwaysPullImages admission controller.
Harap diingat kamu sebaiknya hindari penggunaan tag :latest
, lihat panduan konfigurasi untuk informasi lebih lanjut.
Membuat Image Multi-arsitektur dengan Manifest
Docker CLI saat ini mendukung perintah docker manifest
dengan anak perintah create
, annotate
, dan push
. Perintah-perintah ini dapat digunakan
untuk membuat (build) dan mengunggah (push) manifes. Kamu dapat menggunakan perintah docker manifest inspect
untuk membaca manifes.
Lihat dokumentasi docker di sini: https://docs.docker.com/edge/engine/reference/commandline/manifest/
Lihat contoh-contoh bagaimana kami menggunakan ini untuk proses build harness: https://cs.k8s.io/?q=docker%20manifest%20(create%7Cpush%7Cannotate)&i=nope&files=&repos=
Perintah-perintah ini bergantung pada Docker CLI, dan diimplementasi hanya di sisi CLI. Kamu harus mengubah $HOME/.docker/config.json
dan mengatur key experimental
untuk mengaktifkan
atau cukup dengan mengatur DOCKER_CLI_EXPERIMENTAL
variabel environment menjadi enabled
ketika memanggil perintah-perintah CLI.
Catatan:
Gunakan Docker 18.06 ke atas, versi-versi di bawahnya memiliki bug ataupun tidak mendukung perintah eksperimental. Contohnya https://github.com/docker/cli/issues/1135 yang menyebabkan masalah di bawah containerd.Kalau kamu terkena masalah ketika mengunggah manifes-manifes yang rusak, cukup bersihkan manifes-manifes yang lama di $HOME/.docker/manifests
untuk memulai dari awal.
Untuk Kubernetes, kami biasanya menggunakan image-image dengan sufiks -$(ARCH)
. Untuk kompatibilitas (backward compatibility), lakukan generate image-image yang lama dengan sufiks. Idenya adalah men-generate, misalnya pause
image yang memiliki manifes untuk semua arsitektur dan misalnya pause-amd64
yang punya kompatibilitas terhadap konfigurasi-konfigurasi lama atau berkas-berkas YAML yang bisa saja punya image-image bersufiks yang di-hardcode.
Menggunakan Registri Privat (Private Registry)
Biasanya kita memerlukan key untuk membaca image-image yang tersedia pada suatu registri privat. Kredensial ini dapat disediakan melalui beberapa cara:
- Menggunakan Google Container Registry
- per-klaster
- konfigurasi secara otomatis pada Google Compute Engine atau Google Kubernetes Engine
- semua Pod dapat membaca registri privat yang ada di dalam proyek
- Menggunakan Amazon Elastic Container Registry (ECR)
- menggunakan IAM role dan policy untuk mengontrol akses ke repositori ECR
- secara otomatis refresh kredensial login ECR
- Menggunakan Oracle Cloud Infrastructure Registry (OCIR)
- menggunakan IAM role dan policy untuk mengontrol akses ke repositori OCIR
- Menggunakan Azure Container Registry (ACR)
- Menggunakan IBM Cloud Container Registry
- menggunakan IAM role dan policy untuk memberikan akses ke IBM Cloud Container Registry
- Konfigurasi Node untuk otentikasi registri privat
- semua Pod dapat membaca registri privat manapun
- memerlukan konfigurasi Node oleh admin klaster
- Pra-unduh image
- semua Pod dapat menggunakan image apapun yang di-cached di dalam sebuah Node
- memerlukan akses root ke dalam semua Node untuk pengaturannya
- Mengatur ImagePullSecrets dalam sebuah Pod
- hanya Pod-Pod yang menyediakan key sendiri yang dapat mengakses registri privat
Masing-masing opsi dijelaskan lebih lanjut di bawah ini.
Menggunakan Google Container Registry
Kubernetes memiliki dukungan native untuk Google Container Registry (GCR), ketika dijalankan pada Google Compute Engine (GCE). Jika kamu menjalankan klaster pada GCE atau Google Kubernetes Engine, cukup gunakan nama panjang image (misalnya gcr.io/my_project/image:tag).
Semua Pod di dalam klaster akan memiliki akses baca image di registri ini.
Kubelet akan melakukan otentikasi GCR menggunakan service account yang dimiliki
instance Google. Service acccount pada instance akan memiliki sebuah https://www.googleapis.com/auth/devstorage.read_only
,
sehingga dapat mengunduh dari GCR di proyek yang sama, tapi tidak untuk unggah.
Menggunakan Amazon Elastic Container Registry
Kubernetes memiliki dukungan native untuk Amazon Elastic Container Registry, ketika Node adalah AWS EC2 instance.
Cukup gunakan nama panjang image (misalnya ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag
) di dalam definisi Pod.
Semua pengguna klaster yang dapat membuat Pod akan bisa menjalankan Pod yang dapat menggunakan image-image di dalam registri ECR.
Kubelet akan mengambil dan secara periodik memperbarui kredensial ECR, yang memerlukan permission sebagai berikut:
ecr:GetAuthorizationToken
ecr:BatchCheckLayerAvailability
ecr:GetDownloadUrlForLayer
ecr:GetRepositoryPolicy
ecr:DescribeRepositories
ecr:ListImages
ecr:BatchGetImage
Persyaratan:
- Kamu harus menggunakan versi kubelet
v1.2.0
atau lebih (misal jalankan/usr/bin/kubelet --version=true
). - Jika Node yang kamu miliki ada di region A dan registri kamu ada di region yang berbeda misalnya B, kamu perlu versi
v1.3.0
atau lebih. - ECR harus tersedia di region kamu.
Cara troubleshoot:
- Verifikasi semua persyaratan di atas.
- Dapatkan kredensial $REGION (misalnya
us-west-2
) pada workstation kamu. Lakukan SSH ke dalam host dan jalankan Docker secara manual menggunakan kredensial tersebut. Apakah berhasil? - Tambahkan verbositas level log kubelet paling tidak 3 dan periksa log kubelet (misal
journalctl -u kubelet
) di baris-baris yang seperti ini:aws_credentials.go:109] unable to get ECR credentials from cache, checking ECR API
aws_credentials.go:116] Got ECR credentials from ECR API for <AWS account ID for ECR>.dkr.ecr.<AWS region>.amazonaws.com
Menggunakan Azure Container Registry (ACR)
Ketika menggunakan Azure Container Registry kamu dapat melakukan otentikasi menggunakan pengguna admin maupun sebuah service principal. Untuk keduanya, otentikasi dilakukan melalui proses otentikasi Docker standar. Instruksi-instruksi ini menggunakan perangkat azure-cli.
Kamu pertama perlu membuat sebuah registri dan men-generate kredensial, dokumentasi yang lengkap tentang hal ini dapat dilihat pada dokumentasi Azure container registry.
Setelah kamu membuat registri, kamu akan menggunakan kredensial berikut untuk login:
DOCKER_USER
: service principal, atau pengguna adminDOCKER_PASSWORD
: kata sandi dari service principal, atau kata sandi dari pengguna adminDOCKER_REGISTRY_SERVER
:${some-registry-name}.azurecr.io
DOCKER_EMAIL
:${some-email-address}
Ketika kamu sudah memiliki variabel-variabel di atas, kamu dapat mengkonfigurasi sebuah Kubernetes Secret dan menggunakannya untuk deploy sebuah Pod.
Menggunakan IBM Cloud Container Registry
IBM Cloud Container Registry menyediakan sebuah registri image privat yang multi-tenant, dapat kamu gunakan untuk menyimpan dan membagikan image-image secara aman. Secara default, image-image di dalam registri privat kamu akan dipindai (scan) oleh Vulnerability Advisor terintegrasi untuk deteksi isu keamanan dan kerentanan (vulnerability) yang berpotensi. Para pengguna di dalam akun IBM Cloud kamu dapat mengakses image, atau kamu dapat menggunakan IAM role dan policy untuk memberikan akses ke namespace di IBM Cloud Container Registry.
Untuk instalasi plugin CLI di IBM Cloud Containerr Registry dan membuat sebuah namespace untuk image-image kamu, lihat Mulai dengan IBM Cloud Container Registry.
Jika kamu menggunakan akun dan wilayah (region) yang sama, kamu dapat melakukan deploy image-image yang disimpan di dalam IBM Cloud Container Registry ke dalam namespace default dari klaster IBM Cloud Kubernetes Service yang kamu miliki tanpa konfigurasi tambahan, lihat Membuat kontainer dari image. Untuk opsi konfigurasi lainnya, lihat Bagaimana cara mengotorasi klaster untuk mengunduh image dari sebuah registri.
Konfigurasi Node untuk Otentikasi ke sebuah Registri Privat
Catatan:
Jika kamu jalan di Google Kubernetes Engine, akan ada.dockercfg
pada setiap Node dengan kredensial untuk Google Container Registry. Kamu tidak bisa menggunakan cara ini.Catatan:
Jika kamu jalan di AWS EC2 dan menggunakan EC2 Container Registry (ECR), kubelet pada setiap Node akan dapat mengatur dan memperbarui kredensial login ECR. Kamu tidak bisa menggunakan cara ini.Catatan:
Cara ini cocok jika kamu dapat mengontrol konfigurasi Node. Cara ini tidak akan bekerja dengan baik pada GCE, dan penyedia layanan cloud lainnya yang tidak melakukan penggantian Node secara otomatis.Catatan:
Kubernetes pada saat ini hanya mendukung bagianauths
dan HttpHeaders
dari konfigurasi docker. Hal ini berarti bantuan kredensial (credHelpers
atau credsStore
) tidak didukung.Docker menyimpan key untuk registri privat pada $HOME/.dockercfg
atau berkas $HOME/.docker/config.json
. Jika kamu menempatkan berkas yang sama
pada daftar jalur pencarian (search path) berikut, kubelet menggunakannya sebagai penyedia kredensial saat mengunduh image.
{--root-dir:-/var/lib/kubelet}/config.json
{cwd of kubelet}/config.json
${HOME}/.docker/config.json
/.docker/config.json
{--root-dir:-/var/lib/kubelet}/.dockercfg
{cwd of kubelet}/.dockercfg
${HOME}/.dockercfg
/.dockercfg
Catatan:
Kamu mungkin harus mengaturHOME=/root
secara eksplisit pada berkas environment kamu untuk kubelet.Berikut langkah-langkah yang direkomendasikan untuk mengkonfigurasi Node kamu supaya bisa menggunakan registri privat. Pada contoh ini, coba jalankan pada desktop/laptop kamu:
- Jalankan
docker login [server]
untuk setiap set kredensial yang ingin kamu gunakan. Ini akan memperbarui$HOME/.docker/config.json
. - Lihat
$HOME/.docker/config.json
menggunakan editor untuk memastikan sudah berisi kredensial yang ingin kamu gunakan. - Dapatkan daftar Node, contohnya:
- jika kamu ingin mendapatkan nama:
nodes=$(kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}')
- jika kamu ingin mendapatkan IP:
nodes=$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')
- jika kamu ingin mendapatkan nama:
- Salin
.docker/config.json
yang ada di lokal kamu pada salah satu jalur pencarian di atas.- contohnya:
for n in $nodes; do scp ~/.docker/config.json root@$n:/var/lib/kubelet/config.json; done
- contohnya:
Verifikasi dengana membuat sebuah Pod yanag menggunakan image privat, contohnya:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: private-image-test-1
spec:
containers:
- name: uses-private-image
image: $PRIVATE_IMAGE_NAME
imagePullPolicy: Always
command: [ "echo", "SUCCESS" ]
EOF
pod/private-image-test-1 created
Jika semuanya berjalan dengan baik, maka setelah beberapa lama, kamu dapat menjalankan:
kubectl logs private-image-test-1
dan lihat pada keluaran perintah:
SUCCESS
Jika kamu mencurigai ada perintah yang gagal, kamu dapat menjalankan:
kubectl describe pods/private-image-test-1 | grep 'Failed'
Pada kasus gagal, keluarannya mirip seperti:
Fri, 26 Jun 2015 15:36:13 -0700 Fri, 26 Jun 2015 15:39:13 -0700 19 {kubelet node-i2hq} spec.containers{uses-private-image} failed Failed to pull image "user/privaterepo:v1": Error: image user/privaterepo:v1 not found
Kamu harus memastikan semua Node di dalam klaster memiliki .docker/config.json
yang sama. Jika tidak, Pod-Pod
akan jalan pada beberapa Node saja dan gagal di Node lainnya. Contohnya, jika kamu menggunakan Node autoscaling, maka
setiap templat instance perlu untuk mempunyai .docker/config.json
atau mount sebuah penyimpanan yang berisi berkas tersebut.
Semua Pod memiliki akses baca (read) untuk image-image di registri privat manapun ketika
key registri privat ditambahkan pada .docker/config.json
.
Image Pra-unduh
Catatan:
Jika kamu jalan di Google Kubernetes Engine, maka akan ada.dockercfg
pada setiap Node dengan kredensial untuk Google Container Registry. Kamu dapat menggunakan cara ini.Catatan:
Cara ini cocok jika kamu dapat mengontrol konfigurasi Node. Cara ini tidak akan bisa berjalan dengan baik pada GCE, dan penyedia cloud lainnya yang tidak menggantikan Node secara otomatis.Secara default, kubelet akan mencoba untuk mengunduh setiap image dari registri yang dispesifikasikan.
Hanya saja, jika properti imagePullPolicy
diatur menjadi IfNotPresent
atau Never
, maka
sebuah image lokal digunakan.
Jika kamu ingin memanfaatkan image pra-unduh sebagai pengganti untuk otentikasi registri, kamu harus memastikan semua Node di dalam klaster memiliki image pra-unduh yang sama.
Cara ini bisa digunakan untuk memuat image tertentu untuk kecepatan atau sebagai alternatif untuk otentikasi untuk sebuah registri privat.
Semua Pod akan mendapatkan akses baca ke image pra-unduh manapun.
Tentukan ImagePullSecrets pada sebuah Pod
Catatan:
Cara ini merupakan cara yang direkomendasikan saat ini untuk Google Kubernetes Engine, GCE, dan penyedia cloud lainnya yang secara otomatis dapat membuat Node.Kubernetes mendukung penentuan key registri pada sebuah Pod.
Membuat sebuah Secret dengan Docker Config
Jalankan perintah berikut, ganti nilai huruf besar dengan yang tepat:
kubectl create secret docker-registry <name> --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
Jika kamu sudah memiliki berkas kredensial Docker, daripada menggunakan perintah di atas,
kamu dapat mengimpor berkas kredensial sebagai Kubernetes Secret.
Membuat sebuah Secret berbasiskan pada kredensial Docker yang sudah ada menjelaskan bagaimana mengatur ini.
Cara ini berguna khususnya jika kamu menggunakan beberapa registri kontainer privat,
perintah kubectl create secret docker-registry
akan membuat sebuah Secret yang akan
hanya bekerja menggunakan satu registri privat.
Catatan:
Pod-Pod hanya dapat mengacu pada imagePullSecrets di dalam namespace, sehingga proses ini perlu untuk diselesaikan satu kali setiap namespace.Mengacu pada imagePullSecrets di dalam sebuah Pod
Sekarang, kamu dapat membuat Pod yang mengacu pada Secret dengan menambahkan bagian imagePullSecrets
untuk sebuah definisi Pod.
cat <<EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey
EOF
cat <<EOF >> ./kustomization.yaml
resources:
- pod.yaml
EOF
Cara ini perlu untuk diselesaikan untuk setiap Pod yang mengguunakan registri privat.
Hanya saja, mengatur field ini dapat diotomasi dengan mengatur imagePullSecrets di dalam sumber daya serviceAccount. Periksa Tambahan ImagePullSecrets untuk sebuah Service Account untuk instruksi yang lebih detail.
Kamu dapat menggunakan cara ini bersama .docker/config.json
pada setiap Node. Kredensial-kredensial
akan dapat di-merged. Cara ini akan dapat bekerja pada Google Kubernetes Engine.
Kasus-Kasus Penggunaan (Use Case)
Ada beberapa solusi untuk konfigurasi registri privat. Berikut beberapa kasus penggunaan dan solusi yang disarankan.
- Klaster yang hanya menjalankan image non-proprietary (misalnya open-source). Tidak perlu unutuk menyembunyikan image.
- Gunakan image publik pada Docker hub.
- Tidak ada konfigurasi yang diperlukan.
- Pada GCE/Google Kubernetes Engine, sebuah mirror lokal digunakan secara otomatis untuk meningkatkan kecepatan dan ketersediaan.
- Gunakan image publik pada Docker hub.
- Klaster yang menjalankan image proprietary yang seharusnya disembunyikan dari luar perusahaan, tetapi bisa terlihat oleh pengguna klaster.
- Gunakan sebuah privat registri Docker yang hosted.
- Bisa saja di-host pada Docker Hub, atau lainnya.
- Konfigurasi
.docker/config.json
secara manual pada setiap Node seperti dijelaskan di atas.
- Atau, jalankan sebuah registri privat internal di belakang firewall kamu dengan akses baca terbuka.
- Tidak ada konfigurasi Kubernetes yang diperlukan.
- Atau, ketika pada GCE/Google Kubernetes Engine, menggunakan Google Container Registry yang ada di proyek.
- Hal ini bisa bekerja baik dengan autoscaling klaster dibandingkan konfigurasi Node manual.
- Atau, pada sebuah klaster dimana mengubah konfigurasi Node tidak nyaman, gunakan
imagePullSecrets
.
- Gunakan sebuah privat registri Docker yang hosted.
- Klaster dengan image proprietary, beberapa memerlukan akses kontrol yang lebih ketat.
- Pastikan AlwaysPullImages admission controller aktif. Sebaliknya, semua Pod berpotensi memiliki akses ke semua image.
- Pindahkan data sensitif pada sumber daya "Secret", daripada mengemasnya menjadi sebuah image.
- Sebuah klaster multi-tenant dimana setiap tenant memerlukan registri privatnya masing-masing.
- Pastikan AlwaysPullImages admission controller aktif. Sebaliknya, semua Pod dari semua tenant berpotensi memiliki akses pada semua image.
- Jalankan sebuah registri privat dimana otorisasi diperlukan.
- Men-generate kredensial registri uuntuk setiap tenant, masukkan ke dalam secret uuntuk setiap namespace tenant.
- Tenant menambahkan secret pada imagePullSecrets uuntuk setiap namespace.
Jika kamu memiliki akses pada beberapa registri, kamu dapat membuat satu secret untuk setiap registri.
Kubelet akan melakukan merge imagePullSecrets
manapun menjadi sebuah virtual .docker/config.json
.