Konsep

Edit This Page

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 menjadi Always.
  • 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 admin
  • DOCKER_PASSWORD: kata sandi dari service principal, atau kata sandi dari pengguna admin
  • DOCKER_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 bagian auths 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 mengatur HOME=/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:

  1. Jalankan docker login [server] untuk setiap set kredensial yang ingin kamu gunakan. Ini akan memperbarui $HOME/.docker/config.json.
  2. Lihat $HOME/.docker/config.json menggunakan editor untuk memastikan sudah berisi kredensial yang ingin kamu gunakan.
  3. 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}')
  4. 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

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.

  1. 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.
  2. 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.
  3. 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.
  4. 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.

Masukan