Menjalankan MySQL di Kubernetes

abdul malik karim
Grow at Warung Pintar
6 min readJun 24, 2020

Persyaratan

Membuat Namespace untuk MySQL

Namespace dibuat untuk digunakan di environment dengan banyak pengguna yang berada di dalam beberapa tim ataupun proyek. Untuk sebuah cluster dengan beberapa pengguna saja, kamu tidak harus membuat ataupun memikirkan tentang namespace. Mulai gunakan namespace saat kamu membutuhkan fitur dari namespace itu sendiri.

Membuat Namespace Baru

Buat satu file YML dengan nama namespace.yml.

apiVersion: v1
kind: Namespace
metadata:
name: medium-demo
labels:
name : development

Lalu, apply file di atas ke dalam cluster kita.

kubectl apply -f namespace.yml

Pastikan bahwa namespace sudah aktif.

amka@Abduls-MacBook-Pro:~$ kubectl get namespaceNAME                   STATUS   AGE
default Active 17d
medium-demo Active 20s

Membuat PersistentVolumeClaims untuk menyimpan data MySQL

Selanjutnya, kita perlu membuat 1 PVC untuk menyimpan data di dalam direktori /var/lib/mysql.

PVC untuk MySQL

Buat satu file YML dengan nama mysql-vc.yml dengan isinya.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-volumeclaim
namespace: medium-demo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi

Lalu, apply file mysql-vc.yml ke dalam cluster kita.

amka@Abduls-MacBook-Pro:~$ kubectl apply -f mysql-vc.ymlpersistentvolumeclaim/mysql-volumeclaim created

Pastikan PVC sudah berhasil dibuat dengan namespace.

amka@Abduls-MacBook-Pro:~$ kubectl get pvc -n medium-demo
  • -n adalah singkatan dari namespace, karena semua services MySQL di-deploy dalam namespace medium-demo.

Membuat Secret untuk Menyimpan MySQL Password

Kita perlu membuat 2 Secret, Karena MySQL memerlukan root password dan user

Secret MySQL untuk Root Password

secret-mysql-password.ymlapiVersion: v1
kind: Secret
metadata:
name: mysql-root-password
namespace: medium-demo
type: Opaque
stringData:
password: KuB3D3m0db

Secret MySQL untuk User

secret-mysql-user.ymlapiVersion: v1
kind: Secret
metadata:
name: mysql-user-creds
namespace: medium-demo
type: Opaque
stringData:
MYSQL_USER: user
MYSQL_ROOT_PASSWORD: KuB3D3m0db
MYSQL_PASSWORD: mediumdemomysql

Apply file Secret.

kubectl apply -f secret-mysql-password.ymlkubectl apply -f secret-mysql-user.yml

Pastikan Secret yang sudah dibuat masuk ke dalam namespace medium-demo.

amka@Abduls-MacBook-Pro:~$ kubectl get secret -n medium-demo 

NAME TYPE DATA AGE
mysql-root-password Opaque 1 2m13s
mysql-user-creds Opaque 3 2m45s

Membuat ConfigMap untuk Menyimpan Konfigurasi MySQL

Kita perlu membuat direktori dengan nama mysql-config untuk konfigurasi MySQL yang akan di-mount ke direktori /etc/mysql/conf.d.

letak file

Setelah masuk ke dalam direktori, tahap selanjutnya adalah pembuatan file konfigurasi MySQL dengan nama max_allowed_packet.cnf.

[mysqld]max_allo
wed_packet = 64M

Membuat ConfigMap

Siapkan mysql-conf.yml.

mysql-conf.ymlapiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
namespace: medium-demo
data:
max_allowed_packet.cnf: |
[mysqld]
max_allowed_packet = 32M

Apply file ConfigMap.

kubectl apply -f mysql-conf.yml

Pastikan ConfigMap sudah masuk ke dalam namespace.

amka@Abduls-MacBook-Pro:~$ kubectl get configmap -n medium-demoNAME           DATA   AGE
mysql-config 1 10s

Membuat Deployment MySQL

Setelah PVC, Secret, dan ConfigMap, kita siap untuk menggunakan file YML berikut.

Pertama, siapkan mysql-cluster.yml.

Sebagai referensi, berikut adalah isi file mysql-cluster.yml yang menggunakan private registry.

apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: mysql-db
name: mysql-db
namespace: medium-demo
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 25%
selector:
matchLabels:
app: mysql-db
template:
metadata:
annotations:
sidecar.istio.io/inject: "false"
labels:
app: mysql-db
spec:
terminationGracePeriodSeconds: 30
containers:
- name: mysql-db
image: asia.gcr.io/[Nama Projek]/[Nama direktori]/[image]
imagePullPolicy: Always
env:
- name: RELEASE_DATE
value: '30MEI2020'
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-root-password
key: password
- name: MYSQL_USER
value: user
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-user-creds
key: MYSQL_PASSWORD
- name: MYSQL_DATABASE
value: mysql
ports:
- containerPort: 3306
protocol: TCP
volumeMounts:
- mountPath: /var/lib/mysql
subPath: "mysql"
name: mysql-presistent-storage
- mountPath: /etc/mysql/conf.d
name: mysql-config
imagePullSecrets:
- name:
gcr-registry-json
volumes:
- name: mysql-presistent-storage
persistentVolumeClaim:
claimName: mysql-volumeclaim
- name: mysql-config
configMap:
name: mysql-config
items:
- key: max_allowed_packet.cnf
path: max_allowed_packet.cnf

Untuk yang tidak menggunakan private registry, bisa menggunakan isi di bawah ini.

apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: mysql-db
name: mysql-db
namespace: medium-demo
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 25%
selector:
matchLabels:
app: mysql-db
template:
metadata:
annotations:
sidecar.istio.io/inject: "false"
labels:
app: mysql-db
spec:
terminationGracePeriodSeconds: 30
containers:
- name: mysql-db
image: mysql:5.7
imagePullPolicy: Always
env:
- name: RELEASE_DATE
value: '30MEI2020'
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-root-password
key: password
- name: MYSQL_USER
value: user
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-user-creds
key: MYSQL_PASSWORD
- name: MYSQL_DATABASE
value: mysql
ports:
- containerPort: 3306
protocol: TCP
volumeMounts:
- mountPath: /var/lib/mysql
subPath: "mysql"
name: mysql-presistent-storage
- mountPath: /etc/mysql/conf.d
name: mysql-config
volumes:
- name: mysql-presistent-storage
persistentVolumeClaim:
claimName: mysql-volumeclaim
- name: mysql-config
configMap:
name: mysql-config
items:
- key: max_allowed_packet.cnf
path: max_allowed_packet.cnf

Beberapa komentar tentang YAML,

  • Menggunakan MySQL versi 5.7 untuk menyamakan dengan versi MySQL di CloudSQL,
  • Menggunakan variabel untuk mengambil root password yang ada pada Secret,
  • Jika menggunakan private registry, tambahkan,

    imagePullSecrets:
    — name: gcr-registry-json
amka@Abduls-MacBook-Pro:~$ kubectl apply -f mysql-cluster.yml
deployment.extensions/mysql-db created
amka@Abduls-MacBook-Pro:~$ kubectl get pods -n medium-demoNAME READY STATUS RESTARTS AGE
mysql-db-5695d96446-rqxz6 1/1 Running 0 5m

Selanjutnya, kita dapat memeriksa log dari pod MySQL untuk menentukan apakah layanan sudah berjalan.

amka@Abduls-MacBook-Pro:~$ kubectl logs -f mysql-db-5695d96446-rqxz6 -n medium-demo2020-05-30 13:11:04+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.30-1debian10 started.
2020-05-30 13:11:05+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2020-05-30 13:11:05+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.30-1debian10 started.
2020-05-30T13:11:06.257500Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2020-05-30T13:11:06.295230Z 0 [Note] mysqld (mysqld 5.7.30) starting as process 1 ...
2020-05-30T13:11:06.300079Z 0 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
2020-05-30T13:11:06.303065Z 0 [Note] InnoDB: PUNCH HOLE support available
2020-05-30T13:11:06.303119Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2020-05-30T13:11:06.303137Z 0 [Note] InnoDB: Uses event mutexes
2020-05-30T13:11:06.303154Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier

Publish MySQL via Kubernetes Service

Setelah MySQL aktif dan berjalan, kita perlu membuat endpoint publik untuk mengakses MySQL.

Dimulai dengan membuat 2 file YML dengan nama mysql-service-lb.yml dan mysql-service.yml.

mysql-service-lb.ymlapiVersion: v1
kind: Service
metadata:
name: mysql-cluster-lb
namespace: medium-demo
spec:
type: LoadBalancer
ports:
- port: 3306
name: mysql-cluster
selector:
app: mysql-db

File mysql-service.yml untuk mendapatkan ClusterIP local dari MySQL.

mysql-service.ymlapiVersion: v1
kind: Service
metadata:
name: mysql
namespace: medium-demo
spec:
ports:
- port: 3306
name: mysql-cluster
clusterIP: None
selector:
app: mysql-db

Apply file mysql-service-lb.yml dan mysql-service.yml untuk membuat Service dan pastikan Service tersebut sudah ter-deploy di dalam namespace medium-demo.

amka@Abduls-MacBook-Pro:~$ kubectl apply -f mysql-service-lb.yml
service/mysql-cluster-lb created
amka@Abduls-MacBook-Pro:~$ kubectl apply -f mysql-service.yml
service/mysql created
amka@Abduls-MacBook-Pro:~$ kubectl get svc -n medium-demoNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEmysql-cluster-lb LoadBalancer 10.125.6.143 35.225.133.182 3306:31496/TCP 16d
mysql ClusterIP None <none> 3306/TCP 16d

Lalu, gunakan ClusterIP untuk mengakses MySQL melalui CLI.

amka@Abduls-MacBook-Pro:~$ kubectl exec -ti mysql-db-5695d96446-rqxz6 -n medium-demo bashroot@mysql-db-5695d96446-rqxz6:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 47302
Server version: 5.7.30 MySQL Community Server (GPL)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql>

Setelah mencoba mengakses melalui CLI, kita dapat pula menggunakan endpoint publik EXTERNAL-IP untuk mengakses MySQL dari database client.

Itu dia! Setelah mengikuti tahapan tersebut, kita memiliki MySQL yang berjalan di Kubernetes. Jika salah satu node gagal, pod akan secara otomatis dipindahtugaskan ke node yang sehat.

Di Warung Pintar, kami selalu berupaya untuk merevolusi warung di seluruh Indonesia mengingat masih banyak orang yang berdagang dengan cara yang sama seperti 50 tahun lalu. Banyak hal yang perlu kita benahi, banyak masalah pula yang masih harus kita selesaikan. Untuk itu, bagi kalian yang tertarik untuk memajukan warung di seluruh Indonesia dengan teknologi,
mari bergabung bersama kami di https://warungpintar.co.id/karir!

--

--