
Jika Anda membaca ini, Anda mungkin pernah mendengar sesuatu tentang Kubernetes (dan jika tidak, bagaimana Anda bisa sampai di sini?) Tapi apa sebenarnya Kubernetes itu? Apakah ini "Orkestrasi Kontainer Kelas Industri" ? Atau "Sistem Operasi Cloud-Native" ? Apa artinya ini?
Sejujurnya, saya tidak 100% yakin. Tapi menurut saya menarik untuk menggali internal dan melihat apa yang sebenarnya terjadi di Kubernetes di bawah banyak lapisan abstraksinya. Jadi hanya untuk bersenang-senang, mari kita lihat seperti apa sebenarnya βcluster Kubernetesβ minimal. (Ini akan jauh lebih mudah daripada Kubernetes The Hard Way .)
Saya berasumsi bahwa Anda memiliki pengetahuan dasar tentang Kubernetes, Linux, dan container. Semua yang akan kita bicarakan di sini hanya untuk penelitian / studi, jangan menjalankan semua ini dalam produksi!
Gambaran
Kubernetes mengandung banyak komponen. Menurut wikipedia , arsitekturnya terlihat seperti ini:

Setidaknya ada delapan komponen yang ditampilkan di sini, tetapi kami akan mengabaikan sebagian besar dari mereka. Saya ingin menyatakan bahwa hal terkecil yang bisa disebut Kubernetes memiliki tiga komponen utama:
- kubelet
- kube-apiserver (yang bergantung pada etcd - database-nya)
- runtime kontainer (dalam hal ini Docker)
Mari kita lihat apa yang dikatakan dokumentasi tentang masing-masing ( Rusia , Inggris ). Pertama kubelet :
Agen yang berjalan pada setiap node di cluster. Dia memastikan bahwa kontainernya berjalan di dalam pod.
Kedengarannya cukup sederhana. Bagaimana dengan runtime container (runtime container)?
Runtime kontainer adalah program yang dirancang untuk menjalankan kontainer.
Sangat informatif. Tetapi jika Anda terbiasa dengan Docker, maka Anda harus memiliki pemahaman dasar tentang apa yang dilakukannya. (Rincian pemisahan kekhawatiran antara runtime container dan kubelet sebenarnya cukup halus dan saya tidak akan membahasnya di sini.)
Dan API server ?
Server API - Komponen dasbor Kubernetes yang mewakili API Kubernetes. Server API adalah ujung depan dasbor Kubernetes.
Siapapun yang pernah melakukan sesuatu dengan Kubernetes harus berinteraksi dengan API baik secara langsung atau melalui kubectl. Inilah inti dari apa yang membuat Kubernetes Kubernetes - otak yang mengubah pegunungan YAML yang kita semua kenal dan cintai (?) Menjadi infrastruktur yang berfungsi. Tampaknya jelas bahwa API harus ada dalam konfigurasi minimal kami.
Prasyarat
- Mesin virtual atau fisik Linux yang di-root (Saya menggunakan Ubuntu 18.04 di mesin virtual).
- Dan itu semua!
Instalasi yang membosankan
Docker perlu diinstal pada mesin yang akan kita gunakan. (Saya tidak akan menjelaskan secara rinci tentang cara kerja Docker dan container; ada artikel bagus di luar sana jika Anda tertarik ). Mari kita instal dengan
apt
:
$ sudo apt install docker.io
$ sudo systemctl start docker
Setelah itu, kita perlu mendapatkan binari Kubernetes. Sebenarnya, untuk peluncuran awal "cluster" kami, kami hanya perlu
kubelet
, karena kami dapat menggunakan untuk meluncurkan komponen server lainnya kubelet
. Untuk berinteraksi dengan cluster kami setelah itu aktif dan berjalan, kami juga akan menggunakan kubectl
.
$ curl -L https://dl.k8s.io/v1.18.5/kubernetes-server-linux-amd64.tar.gz > server.tar.gz
$ tar xzvf server.tar.gz
$ cp kubernetes/server/bin/kubelet .
$ cp kubernetes/server/bin/kubectl .
$ ./kubelet --version
Kubernetes v1.18.5
Apa yang terjadi jika kita baru saja meluncurkannya
kubelet
?
$ ./kubelet
F0609 04:03:29.105194 4583 server.go:254] mkdir /var/lib/kubelet: permission denied
kubelet
harus dijalankan sebagai root. Ini cukup logis, karena dia perlu mengelola seluruh node. Mari kita lihat parameternya:
$ ./kubelet -h
< , >
$ ./kubelet -h | wc -l
284
Wah, banyak sekali pilihannya! Untungnya, kami hanya membutuhkan beberapa saja. Berikut adalah salah satu parameter yang kami minati:
--pod-manifest-path string
Jalur ke direktori yang berisi file untuk pod statis, atau jalur ke file yang mendeskripsikan pod statis. File yang dimulai dengan titik akan diabaikan. (BERLAKU LAGI:. Parameter ini harus ditetapkan dalam file konfigurasi diteruskan ke Kubelet melalui opsi --config Untuk informasi lebih lanjut lihat kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file .)
Parameter ini memungkinkan kita untuk menjalankan statis Pod - Pod yang tidak dikelola melalui Kubernetes API. Pod statis jarang digunakan, tetapi sangat nyaman untuk meningkatkan cluster dengan cepat, dan inilah yang kami butuhkan. Kami akan mengabaikan peringatan keras ini (sekali lagi, jangan menjalankan ini dalam produksi!) Dan lihat apakah kami dapat berjalan di bawah.
Pertama, kita akan membuat direktori untuk pod statis dan menjalankan
kubelet
:
$ mkdir pods
$ sudo ./kubelet --pod-manifest-path=pods
Kemudian di jendela terminal / tmux lain / di tempat lain, kita akan membuat manifes pod:
$ cat <<EOF > pods/hello.yaml
apiVersion: v1
kind: Pod
metadata:
name: hello
spec:
containers:
- image: busybox
name: hello
command: ["echo", "hello world!"]
EOF
kubelet
mulai menulis beberapa peringatan dan sepertinya tidak ada yang terjadi. Tapi bukan ini masalahnya! Mari kita lihat Docker:
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c8a35e26663 busybox "echo 'hello world!'" 36 seconds ago Exited (0) 36 seconds ago k8s_hello_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_4
68f670c3c85f k8s.gcr.io/pause:3.2 "/pause" 2 minutes ago Up 2 minutes k8s_POD_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_0
$ sudo docker logs k8s_hello_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_4
hello world!
kubelet
membaca manifes pod dan menginstruksikan Docker untuk menjalankan beberapa container sesuai spesifikasi kami. (Jika Anda penasaran dengan container "pause", ini adalah peretasan Kubernetes - lihat blog ini untuk detailnya .) Kubelet akan meluncurkan container kami busybox
dengan perintah yang ditentukan dan memulai ulang tanpa batas hingga pod statis dihapus.
Beri selamat pada diri sendiri. Kami baru saja menemukan salah satu cara paling rumit untuk menampilkan teks ke terminal!
Jalankan etcd
Tujuan utama kami adalah menjalankan Kubernetes API, tetapi untuk itu kami harus menjalankan etcd terlebih dahulu . Mari kita mulai cluster etcd minimal dengan menempatkan pengaturannya di direktori pods (misalnya
pods/etcd.yaml
):
apiVersion: v1
kind: Pod
metadata:
name: etcd
namespace: kube-system
spec:
containers:
- name: etcd
command:
- etcd
- --data-dir=/var/lib/etcd
image: k8s.gcr.io/etcd:3.4.3-0
volumeMounts:
- mountPath: /var/lib/etcd
name: etcd-data
hostNetwork: true
volumes:
- hostPath:
path: /var/lib/etcd
type: DirectoryOrCreate
name: etcd-data
Jika Anda pernah bekerja dengan Kubernetes, file-file YAML ini sudah tidak asing lagi bagi Anda. Hanya ada dua hal yang perlu diperhatikan di sini:
Kami memasang folder host
/var/lib/etcd
di pod sehingga data etcd disimpan setelah restart (jika ini tidak dilakukan, maka status cluster akan dihapus setiap kali pod di-restart, yang akan menjadi buruk bahkan untuk instalasi Kubernetes minimal).
Kami telah menginstal
hostNetwork: true
. Opsi ini, tidak mengherankan, mengonfigurasi etcd untuk menggunakan jaringan host daripada jaringan internal pod (ini akan mempermudah server API untuk menemukan kluster etcd).
Pemeriksaan sederhana menunjukkan bahwa etcd memang berjalan di localhost dan menyimpan data ke disk:
$ curl localhost:2379/version
{"etcdserver":"3.4.3","etcdcluster":"3.4.0"}
$ sudo tree /var/lib/etcd/
/var/lib/etcd/
βββ member
βββ snap
β βββ db
βββ wal
βββ 0.tmp
βββ 0000000000000000-0000000000000000.wal
Meluncurkan Server API
Memulai Server API Kubernetes jauh lebih mudah. Satu-satunya parameter yang perlu diteruskan
--etcd-servers
, melakukan apa yang Anda harapkan:
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
namespace: kube-system
spec:
containers:
- name: kube-apiserver
command:
- kube-apiserver
- --etcd-servers=http://127.0.0.1:2379
image: k8s.gcr.io/kube-apiserver:v1.18.5
hostNetwork: true
Tempatkan file YAML ini di direktori
pods
dan server API akan mulai. Verifikasi dengan bantuan curl
menunjukkan bahwa Kubernetes API mendengarkan pada port 8080 dengan akses terbuka penuh - tidak diperlukan otentikasi!
$ curl localhost:8080/healthz
ok
$ curl localhost:8080/api/v1/pods
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/pods",
"resourceVersion": "59"
},
"items": []
}
(Sekali lagi, jangan jalankan ini dalam produksi! Saya sedikit terkejut bahwa pengaturan default sangat tidak aman. Tapi saya rasa ini untuk kemudahan pengembangan dan pengujian.)
Dan, untungnya, kubectl bekerja di luar kotak tanpa tambahan apapun. pengaturan!
$ ./kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:47:41Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:39:24Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
$ ./kubectl get pod
No resources found in default namespace.
Masalah
Tetapi jika Anda menggali lebih dalam, sepertinya ada yang tidak beres:
$ ./kubectl get pod -n kube-system
No resources found in kube-system namespace.
Pod statis yang kami buat telah hilang! Faktanya, node kubelet kita tidak muncul sama sekali:
$ ./kubectl get nodes
No resources found in default namespace.
Apa masalahnya? Jika Anda ingat, beberapa paragraf yang lalu kami memulai kubelet dengan seperangkat parameter baris perintah yang sangat sederhana, jadi kubelet tidak tahu bagaimana menghubungi server API dan memberitahukan statusnya. Setelah memeriksa dokumentasi, kami menemukan tanda yang sesuai:
--kubeconfig string
Jalur ke file
kubeconfig
, yang menunjukkan cara menyambung ke server API. Kehadiran --kubeconfig
mengaktifkan mode server API, ketidakhadiran --kubeconfig
mengaktifkan mode offline.
Selama ini, tanpa disadari, kami menjalankan kubelet dalam "mode offline". (Jika kita bertele-tele, kita bisa menganggap mode kubelet standalone sebagai βKubernetes minimum yang layak,β tapi itu akan sangat membosankan). Agar konfigurasi "nyata" berfungsi, kita perlu meneruskan file kubeconfig ke kubelet sehingga ia tahu bagaimana berkomunikasi dengan server API. Untungnya, ini cukup mudah (karena kami tidak memiliki masalah dengan otentikasi atau sertifikat):
apiVersion: v1
kind: Config
clusters:
- cluster:
server: http://127.0.0.1:8080
name: mink8s
contexts:
- context:
cluster: mink8s
name: mink8s
current-context: mink8s
Simpan ini sebagai
kubeconfig.yaml
, matikan proses kubelet
dan mulai ulang dengan parameter yang diperlukan:
$ sudo ./kubelet --pod-manifest-path=pods --kubeconfig=kubeconfig.yaml
(Ngomong-ngomong, jika Anda mencoba mengakses API dengan curl ketika kubelet tidak berfungsi, Anda akan menemukan bahwa itu masih berfungsi! Kubelet bukanlah "induk" dari pod-nya, seperti Docker, ini lebih seperti "daemon kontrol". Kontainer yang dikelola oleh kubelet akan berjalan sampai kubelet menghentikannya.)
Setelah beberapa menit,
kubectl
akan ditunjukkan kepada kita pod dan node, seperti yang kita harapkan:
$ ./kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
default hello-mink8s 0/1 CrashLoopBackOff 261 21h
kube-system etcd-mink8s 1/1 Running 0 21h
kube-system kube-apiserver-mink8s 1/1 Running 0 21h
$ ./kubectl get nodes -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
mink8s Ready <none> 21h v1.18.5 10.70.10.228 <none> Ubuntu 18.04.4 LTS 4.15.0-109-generic docker://19.3.6
Mari kita benar-benar memberi selamat pada diri kita sendiri kali ini (saya tahu saya sudah memberi selamat) - kami memiliki "cluster" Kubernetes minimal yang bekerja dengan API yang berfungsi penuh!
Jalankan di bawah
Sekarang mari kita lihat kemampuan API. Mari kita mulai dengan pod nginx:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
Di sini kita mendapatkan kesalahan yang cukup menarik:
$ ./kubectl apply -f nginx.yaml
Error from server (Forbidden): error when creating "nginx.yaml": pods "nginx" is
forbidden: error looking up service account default/default: serviceaccount
"default" not found
$ ./kubectl get serviceaccounts
No resources found in default namespace.
Di sini kita melihat betapa tidak lengkapnya lingkungan Kubernetes kita - kita tidak memiliki akun layanan. Mari coba lagi dengan membuat akun layanan secara manual dan lihat apa yang terjadi:
$ cat <<EOS | ./kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: default
EOS
serviceaccount/default created
$ ./kubectl apply -f nginx.yaml
Error from server (ServerTimeout): error when creating "nginx.yaml": No API
token found for service account "default", retry after the token is
automatically created and added to the service account
Meskipun kami membuat akun layanan secara manual, tidak ada token autentikasi yang dibuat. Saat kami terus bereksperimen dengan "cluster" minimalis kami, kami akan menemukan bahwa sebagian besar hal berguna yang biasanya terjadi secara otomatis akan hilang. Server API Kubernetes cukup minimalis, dengan sebagian besar perubahan otomatis yang berat terjadi di berbagai pengontrol dan pekerjaan latar belakang yang belum berjalan.
Kami dapat mengatasi masalah ini dengan menetapkan opsi
automountServiceAccountToken
untuk akun layanan (karena kami tidak perlu menggunakannya):
$ cat <<EOS | ./kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: default
automountServiceAccountToken: false
EOS
serviceaccount/default configured
$ ./kubectl apply -f nginx.yaml
pod/nginx created
$ ./kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 0/1 Pending 0 13m
Akhirnya, under muncul! Namun nyatanya, ini tidak akan dimulai, karena kita tidak memiliki scheduler (penjadwal) - komponen penting lainnya Kubernetes. Sekali lagi, kita dapat melihat bahwa Kubernetes API ternyata sangat bodoh - ketika Anda membuat sebuah pod di API, ia mendaftarkannya, tetapi tidak mencoba untuk mencari tahu di node mana untuk menjalankannya.
Anda sebenarnya tidak membutuhkan penjadwal untuk menjalankan pod. Anda dapat menambahkan node secara manual ke manifes di parameter
nodeName
:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
nodeName: mink8s
(Ganti
mink8s
dengan nama host.) Setelah menghapus dan menerapkan, kita melihat bahwa nginx telah dimulai dan sedang mendengarkan di alamat IP internal:
$ ./kubectl delete pod nginx
pod "nginx" deleted
$ ./kubectl apply -f nginx.yaml
pod/nginx created
$ ./kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 30s 172.17.0.2 mink8s <none> <none>
$ curl -s 172.17.0.2 | head -4
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
Untuk memverifikasi bahwa jaringan antar pod berfungsi dengan benar, kita dapat menjalankan curl dari pod lain:
$ cat <<EOS | ./kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: curl
spec:
containers:
- image: curlimages/curl
name: curl
command: ["curl", "172.17.0.2"]
nodeName: mink8s
EOS
pod/curl created
$ ./kubectl logs curl | head -6
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
Cukup menyenangkan untuk menggali lingkungan ini dan melihat apa yang berhasil dan yang tidak. Saya menemukan bahwa ConfigMap dan Secret berfungsi seperti yang diharapkan, tetapi Service dan Deployment tidak.
Keberhasilan!
Posting ini semakin besar, jadi saya akan mengumumkan kemenangan dan menyatakan bahwa ini adalah konfigurasi yang layak untuk memanggil "Kubernetes". Singkatnya: empat biner, lima parameter baris perintah, dan "hanya" 45 baris YAML (tidak banyak menurut standar Kubernetes) dan kami memiliki banyak hal yang berfungsi:
- Pod dikelola menggunakan Kubernetes API biasa (dengan beberapa peretasan)
- Anda dapat mengunggah dan mengelola gambar kontainer publik
- Pod tetap hidup dan dimulai ulang secara otomatis
- Jaringan antar pod dalam satu node bekerja dengan cukup baik
- ConfigMap, Rahasia, dan pemasangan repositori yang paling sederhana berfungsi seperti yang diharapkan
Tetapi sebagian besar hal yang membuat Kubernetes sangat berguna masih belum ada, misalnya:
- Perencana Pod
- Otentikasi / Otorisasi
- Beberapa node
- Jaringan layanan
- DNS Internal Berkelompok
- Pengontrol untuk akun layanan, penerapan, integrasi penyedia cloud, dan sebagian besar barang lain yang dibawa Kubernetes
Jadi, apa yang sebenarnya kita dapatkan? Kubernetes API, yang bekerja sendiri, sebenarnya hanyalah platform otomatisasi container . Itu tidak berbuat banyak - ini berfungsi untuk berbagai pengontrol dan operator yang menggunakan API - tetapi menyediakan kerangka kerja yang konsisten untuk otomatisasi.
Pelajari lebih lanjut tentang kursus ini di webinar gratis.
Baca lebih banyak:
- Mengapa sysadmin, pengembang, dan penguji mempelajari praktik DevOps?
- Thanos β Prometheus
- QA- GitLab GitLab Performance Tool
- Loki β , Prometheus
- DevOps