Skip to content

Instantly share code, notes, and snippets.

@ejlp12
Last active February 24, 2021 06:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ejlp12/d35ccbcb06d52cf6e974924f6f4135ca to your computer and use it in GitHub Desktop.
Save ejlp12/d35ccbcb06d52cf6e974924f6f4135ca to your computer and use it in GitHub Desktop.
Membangun dan menjalankan EKS-D

Membangun dan menjalankan EKS-D

Di artikel ini saya ingin sedikit mengenalkan EKS-D dan bagaimana mulai membangun (instalasi) dan menjalankan EKS-D. Artikel ini bukan bermaksud EsKS-D (Sok Kenal Sok Dekat), tapi saya asumsikan kalian udah kenal dekat dengan Kubernetes, jadi saya gak akan bertele-tele menjelaskan tentang Kubernetes.

Apa itu EKS-D?

Secara singkat, EKS-D atau "EKS Distro" adalah distro (distribusi) dari Kubernetes yang dikembangkan oleh AWS dan digunakan oleh AWS untuk mejalankan Amazon EKS (Elastic Kuberntes Service). Amazon EKS adalah layanan Kubernetes cluster yang dikelola oleh AWS (managed service). EKS-D dikebangkan dengan tetap menjaga sesuai dengan aturan upsream Kubernetes dan sudah tersertifikasi (Certified Kubernetes). Saat tulisan ini dibuat, sudah ada 67 distribusi Kubernetes platform yang tersertifikasi. EKS-D menjadi salah satu distribusi yang memberikan kesempatan buat siapapun untuk secara gratis untuk dapat menjalankan Kubernetes yang sama dengan Amazon EKS di manapun, baik itu di on-premise data center, di AWS cloud, maupun di cloud provider lain di luar AWS. Kamu bisa mengunduh, menginstal dan mengelola sendiri klaster EKS-D.

EKS-D merupakan proyek open source yang inisiasi dan dipimpin oleh AWS. Setiap distro dikembangkan oleh suatu perusahaan atau organisasi memiliki fokus atau prioritas tertentu. Prioritas EKS-D adalah membuat Kubernetes yang sederhana, yang mungkin akan terkesan membosangkan (boring) tapi mengedepankan keandalan dan kemananan serta modularitas yang fleksibel. Saya sarankan kamu cek EKS-D Project Tenets untuk tau apakah EKS-D jadi distribusi yang tepat untuk kamu atau tidak. Hal lain yang bisa dipertimbangkan untuk menggunakan EKS-D ini adalah dukungan pengembangan dari tim AWS serta kecepatan rilis versi baru akan sama dengan versi EKS karena EKS-D ini dijadikan basis untuk layanan Amazon EKS.

Jika kamu pengguna AWS, EKS-D juga bisa menjadi alternatif untuk menjalankan Kubernetes cluster yang sama dengan EKS tapi kamu tidak memerlukan control plane yang high-available. Jadi kamu bisa membuat kubernetes cluster hanya dengan 1 master server saja sebagai control plane-nya. Ini mungkin jadi solusi yang cocok dan murah untuk lingkungan development atau test kamu.

Perangkat untuk instalasi EKS-D

Ada beberapa perangkat (tools) yang dapat digunakan untuk instalasi EKS-D, dan saya akan list dan sedikit jelaskan belakangan. Saya akan bahas dulu perangkat instalasi yang disediakan langsung dari project EKS-D di Github, yaitu kOps.

kOps adalah perangkat yang dapat membantu kamu membuat, menghapus, meng-upgrade dan mengelola klaster Kuberneres yang production-grade dan highly available. kOps juga apat menyiapkan sumberdaya infrastruktur pendukung di cloud untuk dapat menjalankan klaster Kubernetes, seperti VPC, Subnet, Security Group, dan lain-lain.

kOps tidak hanya bisa digunakan di AWS tapi juga di beberapa cloud provider atau platform lain seperti di DigitalOcean, GCE, OpenStack, Azure dan AliCloud. (Catatan: dukungan di cloud lain saat ini masih versi beta)

Selain kOps, beberapa perangkat untuk instalasi EKS-D lainnya adalah sebagai berikut:

Instalasi EKS-D menggunakan Kops di AWS

Saya akan jelaskan bagaimana saya pertama kali mencoba menginstal dan menjalankan klaster EKS-D dengan Kops di akun AWS saya.

Jika kamu ingin mengikuti cara yang saya jelaskan disini, saya perlu ingatkan bahwa apa yang dijelaskan di artikel ini dapat menimbulkan biaya yang harus dibayar karena menggunakan sumber daya AWS.

Saya asumsikan kamu sudah punya akun AWS, dan terbiasa dengan menggunakan AWS Command Line Interface (CLI).

Persiapan

Sebagai informasi, saya menggunakan laptop Mac OS dengan aplikasi Terminal untuk bekerja. Sebelum memulai, saya sudah punya beberapa perangkat AWS CLI dan git command line dan kubectl.

Langkah pertama adalah membuat Hosted Zone di Route53. Saya membuat sebuah public sub-domain untuk klaster EKS-D dengan nama eksd.onecloud.run. Saya menggunakan public domain karena saya ingin klaster Kubernetes (EKS-D) yang akan saya instal dapat diakses dari publik atau Internet.

image

Saya menggunakan IAM user yang memiliki role dengan policy AdministratorAccess untuk mempermudah pekerjaan. Kalau kamu mau setup role yang minimal, setidaknya role tersebut perlu policy berikut:

  • AmazonEC2FullAccess
  • IAMFullAccess
  • AmazonS3FullAccess
  • AmazonRoute53FullAccess
  • AmazonVPCFullAccess

Jika kamu mau menyiapkan user dengan role yang memiliki policies seperti itu, saya sertakan skrip yang memudahkan kalian.

Saya mulai dengan mengatur (setup) AWS CLI dengan perintah berikut:

export AWS_ACCESS_KEY_ID=<aws_access_key_id_disini>
export AWS_SECRET_ACCESS_KEY=<aws_secret_key_disini>
export AWS_REGION=ap-southeast-1

Instalasi cepat dengan konfigurasi default

Langkah pertama adalah clone proyek eks-distro di GitHub.

git clone https://github.com/aws/eks-distro.git
cd eks-distro/development/kops 

Di dalam direktori eks-distro/development/kops terdapat skrip-skrip untuk menginstal klaster, menghapus klaster, menggunakan kOps. Kita akan pakai beberapa skrip tersebut.

image

Sebelum memulai menginstal, saya perlu mengatur beberapa environment variables yaitu

  • KOPS_CLUSTER_NAME yaitu nama klaster Kubernetes. Nama ini harus sama dengan nama domain yang akan kita pakai
  • KOPS_STATE_STORE yaitu nama dari bucket S3 untuk menyimpan konfigurasi kOps. Nama bucket ini harus unik jadi kamu bisa kasih postfix dengan nama kamu dan beberapa karakter random.
export KOPS_CLUSTER_NAME=eksd.onecloud.run
export KOPS_STATE_STORE=s3://kops-state-store-eryan123

Untuk mulai menginstal dan langsung menjalakan klaster EKS-D saya bisa menggunakan skrip ./run_cluster.sh tapi skrip itu akan menginstal klaster dengan konfigurasi default yaitu

  • Sebuah VPC dengan CIDR 172.20.0.0/16 dan 3 subnets /19 di 3 Availability Zones
  • Sebuah instance group untuk Kubernetes Control Plane dengan 1 EC2 instance tipe t3.medium
  • Sebuah worker node group dengan 3 EC2 instances tipe t3.medium di 3 Availability Zones

Konfigurasi tersebut mungkin cocok untuk lingkungan Development atau Test kalian, tapi kalau kamu mau menginstal dengan konfigurasi yang berbeda, silakan lihat dan pelajari skrip run_cluster.sh.

Instalasi dengan konfigurasi high-available control plane

Pada langkah-langkah selanjutnya, saya akan menjelaskan bagaimana kita coba menjalankan klaster EKS-D dengan konfigurasi yang lebih cocok untuk lingkungan Production yaitu dengan control plane yang high-available (3 master servers), dan terakhir saya jelaskan juga bagaimana menghapus (delete) klaster dan sumber daya AWS lain yang sudah dibuat pada saat instalasi.

Sebelum menjalankan langkah-langkah dibawah ini, pastikan kamu ada di direktori eks-distro/development/kops

  1. Jalankan skrip ./install_requirements.sh

    image

  2. Jalankan skrip ./create_values.sh.

    image

    Skrip ini akan membuat sebuah file values.yaml di direktori eks-distro/development/kops/eksd.onecloud.run yang berisi container image repository URL dari komponen-komponen Kubernetes EKS-D

    image

  3. Ubah file eks-d.tpl. Ini adalah file template konfigurasi dari klaster yang akan diinstal.

    Jika kamu mau menginstal klaster dengan konfigurasi default maka kamu bisa langsung menjalankan script ./create_configuration.sh, tanpa harus mengubah file eks-d.tpl.

    Saya sertakan file yang sudah saya ubah agar kamu bisa langsung unduh. Beberapa perubahan yang saya lakukan adalah

    • Menambahkan etcdMembers untuk klaster etcd main maupun events agar dijalankan di 3 instanceGroup yang ada di 3 AZ yang berbeda
    • Menambahkan dua InstanceGroup untuk control plane yaitu control-plane-{{.awsRegion}}b dan control-plane-{{.awsRegion}}c masing-masing untuk AZ {{.awsRegion}}b dan {{.awsRegion}}c
    • Mengubah machineType pada InstanceGroup control-plane menjad m5a.large
  4. Jalankan skrip ./create_configuration.sh

    image

    Skrip tersebut akan membuat beberapa file yaitu aws-iam-authenticator.yaml, eksd.onecloud.run.yaml dan env.sh.

  5. Jalankan script ./create_cluster.sh untuk memulai proses instalasi di belakang layar. Proses ini akan membutuhkan waktu beberapa lama.

  6. Jalankan script ./cluster_wait.sh untuk mengecek proses istalasi sampai klaster berjalan (running). Tunggu sampai skrip ini menghasilkan keluaran

    Your cluster eksd.onecloud.run is ready
    
  7. Verifikasi hasil instalasi dengan perintah berikut

    kubectl get po --all-namespaces -o json | jq -r '.items[].spec.containers[].image' | sort -u
    

    Kamu akan mendapatkan keluaran seperti berikut:

    image

Selesai!

Klaster Kubernetes EK-D saya sudah siap. Saya bisa liat semua EC2 instances yang dibuat oleh k0ps seperti ini:

image

Saya juga bisa lihat k0ps sudah membuat dua buah hostname sebagai endpoint dari Kubernetes API Server:

image

Untuk menghapus klaster dan semua sumberdaya yang dibuat oleh k0ps, kita bisa gunakan script ./delete_cluster.sh.

What's next?

Pertanyaan selanjutnya, apakah konfigurasi seperti ini sudah "mirip banget" dengan konfigurasi control plane dari Amazon EKS? Apakah saya sudah percaya diri untuk menggunakan klaster ini untuk lingkungan Produksi? Jawaban kedua pertanyaan itu adalah "Tidak", sebab untuk membuat control plane yang akan saya gunakan untuk lingkungan Produksi, bukan hanya sekedar tentang high-availability tapi saya juga perlu memperhatikan banyak hal, seperti keamanan dari AMI yang digunakan, kinerja (performance) dan juga observabilitas dari sistem, biaya dan lain-lain. Dibagian selanjutnya saya akan menjelaskan apa saja yang mungkin perlu kamu lakukan untuk membuat control plane EKS-D kamu semakin siap untuk digunakan di lingkungan Produksi.

Membuat Control Plane yang siap untuk lingkungan Produksi

Apa yang saya jelaskan diatas adalah cara untuk membuat Kuberneres cluster menggunakan EKS Distro, artinya komponen-komponen EKS yang digunakan yaitu kubeAPIServer, kubeControllerManager, kubeProxy dan juga komponen tambahannya seperti metricsServer, authentication (aws-iam-authenticator) dan coreDNS, semua menggunakan komponen dari EKS-D yang juga komponen yang sama yang digunakan di Amazon EKS. Tetapi selain komponen tersebut, ada komponen lain dan konfigurasi lain yang kita perlu kiat persiapkan supaya control plane menjadi lebih baik.

Sebagai contoh, pada template konfigurasi k0ps yang saya gunakan diatas atau template default bawaan dari proyek EKS-D, kita bisa lihat bahwa ia menggunakan Ubuntu (099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20201026) sebagai sistem operasi setiap node. Ini salah satu hal yang perlu kamu pertimbangkan untuk diubah dengan alasan tim operasional di organisasi kamu mungkin tidak biasa mengelola sistem operasi tersebut.

Berikut saya daftarkan hal-hal yang perlu kita pertimbangkan untuk membuat template kOps yang lebih baik yang akan menghasilkan control plane yang berkinerja lebih baik dan lebih aman.

  • Memilih image yang digunakan pada instanceGroup (OS yang digunakan untuk node)
  • Memilih tipe disk volume yang tepat untuk node yang akan digunakan oleh etcd. Default tipe volume yang digunakan adalah gp2, saat ini AWS memiliki tipe EBS volume yang lebih baik yaitu gp3
  • Mengubah ukuran volume untuk etcd (default ukuran adalah 20GB)
  • Mengubah konfigurasi cpuRequest& memoryRequest dari etcd pod
  • Mengekspos metrik untuk monitoring komponen etcd
  • Menentukan konfigurasi durasi backup retention
  • Gunakan Load Balancer didepan master nodes dan konfigurasikan DNS untuk mengarahkan ke nodes tersebut
  • Persiapkan Load Balancer minimal di 2 Availability Zones
  • Gunakan SSL Certificate pada Load Balancer untuk mengamankan lalu-lintas
  • Membatasi akses ke LB dan master nodes dengan menggunakan Security Group
  • Menambahkan beberapa flag/parameter konfigurasi untuk Kubelet, KubeAPIServer, KubeProxy, KubeControllerManager, CloudControllerManager, KubeScheduler

Masih banyak lagi konfigurasi yang bisa ditambahkan di template k0ps, kamu dapat melihat spesifikasi konfigurasi klaster atau kode sumber componentconfig.go sebagai referensi.

Selain itu node pada instaceGoup juga perlu kita persiapkan dengan lebih baik, misalnya:

  • Menginstal software tambahan seperti monitoring agent di node misalnya agent untuk memonitor utilitas memori dan disk
  • Melakukan upgrade komponen dalam node seperti Docker
  • Melakukan penyetelan (tuning) parameter kernel untuk meningkatkan kinerja dari node
  • Melakukan hardening OS pada node agar lebih aman

Semua persiapan pada node tersebut dapat dilakukan dengan nenambahakan fragmen addtionalUserData di template.

Berikut saya beri contoh beberapa template klaster yang lebih detil yang saya temukan di internet, yang bisa kamu jadikan contoh untuk membuat control plane yang lebih baik:

Penutup

Kalian bisa lihat dari langkah-langkah diatas bahwa untuk menginstal klaster EKS-D cukup mudah, tetapi membangun klaster Kubernetes yang baik memerlukan pengetahuan yang banyak tentang opsi-opsi konfigurasi dan tidak gampang untuk dimengerti. Konfigurasi tersebut juga harus disesuaikan dengan beban kerja klaster kamu, ditijau kembali serta diubah (tuning) secara berkala.

KOps dapat mempermudah instalasi, konfigurasi, upgrade dan menghapus klaster tapi alat yang mempermudah tentu saja menjadi tidak terlalu flexibel. Walaupun demikian kOps sudah banyak digunakan oleh organisasi atau perusahaan untuk membuat klaster Kubernetes skala produksi yang besar, jadi menurut saya kOps sudah sangat cukup untuk kita gunakan sebagai alat bantu untuk membuat klaster Kubernetes/EKS-D yang baik.

Semoga tulisan ini bermanfaat.

apiVersion: kops.k8s.io/v1alpha2
kind: Cluster
metadata:
name: {{ .clusterName }}
spec:
api:
dns: {}
authorization:
rbac: {}
channel: stable
cloudProvider: aws
configBase: {{ .configBase }}
containerRuntime: docker
etcdClusters:
- cpuRequest: 200m
etcdMembers:
- instanceGroup: control-plane-{{.awsRegion}}a
name: a
- instanceGroup: control-plane-{{.awsRegion}}b
name: b
- instanceGroup: control-plane-{{.awsRegion}}c
name: c
memoryRequest: 100Mi
name: main
- cpuRequest: 100m
etcdMembers:
- instanceGroup: control-plane-{{.awsRegion}}a
name: a
- instanceGroup: control-plane-{{.awsRegion}}b
name: b
- instanceGroup: control-plane-{{.awsRegion}}c
name: c
memoryRequest: 100Mi
name: events
iam:
allowContainerRegistry: true
legacy: false
kubernetesApiAccess:
- 0.0.0.0/0
kubernetesVersion: {{ .kubernetesVersion }}
masterPublicName: api.{{ .clusterName }}
networkCIDR: 172.20.0.0/16
networking:
kubenet: {}
nonMasqueradeCIDR: 100.64.0.0/10
sshAccess:
- 0.0.0.0/0
subnets:
- cidr: 172.20.32.0/19
name: {{.awsRegion}}a
type: Public
zone: {{.awsRegion}}a
- cidr: 172.20.64.0/19
name: {{.awsRegion}}b
type: Public
zone: {{.awsRegion}}b
- cidr: 172.20.96.0/19
name: {{.awsRegion}}c
type: Public
zone: {{.awsRegion}}c
topology:
dns:
type: Public
masters: public
nodes: public
kubeAPIServer:
image: {{ .kube_apiserver.repository }}:{{ .kube_apiserver.tag }}
kubeControllerManager:
image: {{ .kube_controller_manager.repository }}:{{ .kube_controller_manager.tag }}
kubeScheduler:
image: {{ .kube_scheduler.repository }}:{{ .kube_scheduler.tag }}
kubeProxy:
image: {{ .kube_proxy.repository }}:{{ .kube_proxy.tag }}
# Metrics Server will be supported with kops 1.19
metricsServer:
enabled: true
image: {{ .metrics_server.repository }}:{{ .metrics_server.tag }}
authentication:
aws:
image: {{ .awsiamauth.repository }}:{{ .awsiamauth.tag }}
kubeDNS:
provider: CoreDNS
coreDNSImage: {{ .coredns.repository }}:{{ .coredns.tag }}
externalCoreFile: |
.:53 {
errors
health {
lameduck 5s
}
kubernetes cluster.local. in-addr.arpa ip6.arpa {
pods insecure
#upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
loop
cache 30
loadbalance
reload
}
masterKubelet:
podInfraContainerImage: {{ .pause.repository }}:{{ .pause.tag }}
# kubelet might already be defined, append the following config
kubelet:
podInfraContainerImage: {{ .pause.repository }}:{{ .pause.tag }}
anonymousAuth: false
---
apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
labels:
kops.k8s.io/cluster: {{.clusterName}}
name: control-plane-{{.awsRegion}}a
spec:
{{- if .controlPlaneInstanceProfileArn }}
iam:
profile: {{ .controlPlaneInstanceProfileArn }}
{{- end }}
image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20201026
machineType: m5a.large
maxSize: 1
minSize: 1
nodeLabels:
kops.k8s.io/instancegroup: control-plane-{{.awsRegion}}a
role: Master
subnets:
- {{.awsRegion}}a
---
apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
labels:
kops.k8s.io/cluster: {{.clusterName}}
name: control-plane-{{.awsRegion}}b
spec:
{{- if .controlPlaneInstanceProfileArn }}
iam:
profile: {{ .controlPlaneInstanceProfileArn }}
{{- end }}
image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20201026
machineType: m5a.large
maxSize: 1
minSize: 1
nodeLabels:
kops.k8s.io/instancegroup: control-plane-{{.awsRegion}}b
role: Master
subnets:
- {{.awsRegion}}b
---
apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
labels:
kops.k8s.io/cluster: {{.clusterName}}
name: control-plane-{{.awsRegion}}c
spec:
{{- if .controlPlaneInstanceProfileArn }}
iam:
profile: {{ .controlPlaneInstanceProfileArn }}
{{- end }}
image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20201026
machineType: m5a.large
maxSize: 1
minSize: 1
nodeLabels:
kops.k8s.io/instancegroup: control-plane-{{.awsRegion}}c
role: Master
subnets:
- {{.awsRegion}}c
---
apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
labels:
kops.k8s.io/cluster: {{.clusterName}}
name: nodes
spec:
{{- if .nodeInstanceProfileArn }}
iam:
profile: {{ .nodeInstanceProfileArn }}
{{- end }}
image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20201026
machineType: t3.medium
maxSize: 3
minSize: 3
nodeLabels:
kops.k8s.io/instancegroup: nodes
role: Node
subnets:
- {{.awsRegion}}a
- {{.awsRegion}}b
- {{.awsRegion}}c
aws iam create-group --group-name kops
aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonEC2FullAccess --group-name kops
aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonRoute53FullAccess --group-name kops
aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess --group-name kops
aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/IAMFullAccess --group-name kops
aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonVPCFullAccess --group-name kops
aws iam create-user --user-name kops
aws iam add-user-to-group --user-name kops --group-name kops
# Simpan baik-baik output (SecretAccessKey & AccessKeyID) dari perintah berikut
aws iam create-access-key --user-name kops
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment