Kubernetes (EKS) Autoscale dengan Spot Instances
Bulan April 2019, saya berkesempatan hadir dalam AWS Summit Singapore yang diselenggarakan di Changi Expo. Salah satu workshop session yang diselenggarakan adalah yang berkaitan dengan AWS managed Kubernetes Cluster, lebih sering disingkat EKS. Sessionnya sendiri tidak terlalu dalam, oleh sebab itu saya perlu lanjutkan hands-on. Berikut saya share mengenai cara Autoscale menggunakan Spot Instances.
Spot Instance
Spot Instance adalah kapasitas komputasi sisa yang dimiliki AWS, biasa ditawarkan dengan harga discount yang sangat kompetitif. Namun Spot Instance sewaktu-waktu bisa diminta kembali oleh AWS saat kapasitas komputasi dibutuhkan oleh customer lain.
Workload production kami menggunakan approach yang berbeda dalam menjalankan memanage cluster Spot Instances, dimana kami gunakan layanan 3rd party integration berupa SpotInst.
EKS
Amazon Elastic Container Service for Kubernetes (Amazon EKS) adalah layanan managed service yang memudahkan dalam menjalankan cluster Kubernetes di AWS.
Deployment EKS cluster dalam tulisan ini menggunakan eksctl, kami buat sebuah cluster di region Singapore dengan hanya 1 instance type t3.medium sebagai membernya
eksctl create cluster --name=belajar-eks --nodes=1 --node-type=t3.medium --tags Owner=Sandbox --node-ami=auto --region=ap-southeast-1
Kita tambahkan tag Owner=Sandbox
, agar memudahkan identifikasi billing yang akan muncul dari pembuatan tulisan ini. Perintah ini butuh hingga 30 menit untuk menyelesaikan task pembuatan cluster EKS yang akan kita gunakan dalam tulisan ini.
Setelah selesai kubectl
bisa kita gunakan untuk manage cluster baru ini
wisu:~/environment $ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-192-168-168-61.ap-southeast-1.compute.internal Ready <none> 34s v1.12.7
Instalasi Helm
Paket manager yang kita gunakan dalam tulisan ini adalah helm
instalasi dilakukan dengan cara
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh
chmod +x get_helm.sh
./get_helm.sh
Sebelum bisa jalankan helm init
kita perlu konfigurasi RBAC, dengan file
cat <<EoF > rbac.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
EoF
file ini bisa kita apply dengan perintah
wisu:~/environment $ kubectl apply -f rbac.yaml
serviceaccount/tiller created
clusterrolebinding.rbac.authorization.k8s.io/tiller created
baru bisa kita jalankan helm init, dengan perintah
wisu:~/environment $ helm init --service-account tiller
$HELM_HOME has been configured at /home/ec2-user/.helm.
Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Sekarang kita perlu update helm charts nya
wisu:~/environment $ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈ Happy Helming!⎈
Konfigurasi Autoscaling
Untuk autoscaling, pertama kita tambahkan Metric Server dengan cara
wisu:~/environment $ helm install stable/metrics-server \
--name metrics-server \
--version 2.0.4 \
--namespace metrics
Metrics selanjutnya bisa kita lihat melalui
wisu:~/environment $ kubectl get apiservice v1beta1.metrics.k8s.io -o yaml
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
creationTimestamp: 2019-05-12T07:41:38Z
labels:
app: metrics-server
chart: metrics-server-2.0.4
heritage: Tiller
release: metrics-server
name: v1beta1.metrics.k8s.io
resourceVersion: "3536"
selfLink: /apis/apiregistration.k8s.io/v1/apiservices/v1beta1.metrics.k8s.io
uid: 60660d3f-7489-11e9-8d29-0217022bb5fc
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: metrics
version: v1beta1
versionPriority: 100
status:
conditions:
- lastTransitionTime: 2019-05-12T07:41:45Z
message: all checks passed
reason: Passed
status: "True"
type: Available
wisu:~/environment $
Spot Instance sebagai Workers
Selanjutnya untuk konfigurasi Spot Instance sebagai worker kita perlu ketahui 2 hal, pertama INSTANCE_PROFILE_ARN
, bisa melalui perintah
INSTANCE_PROFILE_NAME=$(aws iam list-instance-profiles | jq -r '.InstanceProfiles[].InstanceProfileName' | grep belajar-eks-nodegroup) &&
INSTANCE_PROFILE_ARN=$(aws iam get-instance-profile --instance-profile-name $INSTANCE_PROFILE_NAME | jq -r '.InstanceProfile.Arn') &&
echo $INSTANCE_PROFILE_ARN
hasilnya
arn:aws:iam::986794076402:instance-profile/eksctl-belajar-eks-nodegroup-ng-dbfb886c-NodeInstanceProfile-1RFV8ZFOXIEG2
adalah Node Instance Profile ARN yang kita perlukan untuk langkah selanjutnya
Selajutnya kita perlu ketahui security group dari nodegroup kita
STACK_NAME=$(aws cloudformation describe-stacks | jq -r '.Stacks[].StackName' | grep belajar-eks-nodegroup) && SG_ID=$(aws cloudformation describe-stack-resources --stack-name $STACK_NAME --logical-resource-id SG | jq -r '.StackResources[].PhysicalResourceId') && echo $SG_ID
hasilnya
sg-0f3994a71cafbf2ce
adalah Security Group nodegroup dalam tulisan ini
selanjutnya melalui AWS Console kita gunakan cloudformation template berikut untuk membuat Auto Scaling group yang akan men-spin-up Spot Instances kita
Saat ini cluster kita sukses bertambah menjadi 4 nodes
wisu:~/environment $ kubectl get node
NAME STATUS ROLES AGE VERSION
ip-192-168-114-51.ap-southeast-1.compute.internal Ready <none> 34m v1.12.7
ip-192-168-168-61.ap-southeast-1.compute.internal Ready <none> 109m v1.12.7
ip-192-168-183-172.ap-southeast-1.compute.internal Ready <none> 34m v1.12.7
ip-192-168-52-254.ap-southeast-1.compute.internal Ready <none> 34m v1.12.7
Kita bisa inspect lebih dalam lagi mana saja yang merupakan Spot Instance
Selanjutnya kita install spot-interupt hanlder
wisu:~/environment $ wget -q https://raw.githubusercontent.com/bigwisu/belajar-eks/master/spot-interrupt-handler.yml
wisu:~/environment $ kubectl apply -f spot-interrupt-handler.yml
clusterrole.rbac.authorization.k8s.io/spot-interrupt-handler created
serviceaccount/spot-interrupt-handler created
clusterrolebinding.rbac.authorization.k8s.io/spot-interrupt-handler created
daemonset.apps/spot-interrupt-handler created
Seperti saya sudah state diatas, solusi ini kami gunakan dalam development env kami, untuk production workload, kami gunakan integrasi dengan SpotInst