Nếu bạn đã từng ở trong thế giới vùng chứa, bạn sẽ biết rằng việc áp dụng tự động hóa Kubernetes đầy đủ cho hệ thống cơ sở dữ liệu được phân nhóm là khá khó khăn, điều này thường làm tăng thêm mức độ phức tạp cho hệ thống dựa trên vùng chứa kiến trúc cho các ứng dụng trạng thái này. Đó là nơi Nhà điều hành Kubernetes có thể giúp chúng tôi giải quyết vấn đề này. Nhà điều hành Kubernetes là một loại bộ điều khiển đặc biệt được giới thiệu để đơn giản hóa các triển khai phức tạp về cơ bản mở rộng API Kubernetes với các tài nguyên tùy chỉnh. Nó được xây dựng dựa trên các khái niệm tài nguyên và bộ điều khiển Kubernetes cơ bản nhưng bao gồm kiến thức về miền hoặc ứng dụng cụ thể để tự động hóa toàn bộ vòng đời của phần mềm mà nó quản lý.
Percona XtraDB Cluster Operator là một cách đơn giản để tự động hóa các tác vụ cụ thể của Percona XtraDB Cluster như triển khai, mở rộng quy mô, sao lưu và nâng cấp trong Kubernetes, do Percona xây dựng và duy trì. Nó triển khai cụm trong StatefulSet với Khối lượng liên tục, cho phép chúng tôi duy trì danh tính nhất quán cho mỗi Pod trong cụm và dữ liệu của chúng tôi sẽ được duy trì.
Trong bài đăng trên blog này, chúng tôi sẽ kiểm tra việc triển khai Percona XtraDB Cluster 8.0 trong một môi trường được điều chỉnh bởi Nhà điều hành Percona XtraDB Cluster Kubernetes trên Google Cloud Platform.
Tạo Cụm Kubernetes trên Google Cloud
Trong hướng dẫn này, chúng tôi sẽ sử dụng cụm Kubernetes trên Google Cloud vì nó tương đối đơn giản và dễ dàng để thiết lập và chạy Kubernetes. Đăng nhập vào trang tổng quan Google Cloud Platform -> Tính toán -> Kubernetes Engine -> Tạo cụm và bạn sẽ thấy hộp thoại sau:
Chỉ cần nhập tên Cụm Kubernetes, chọn khu vực ưa thích của bạn và nhấp vào "TẠO " (ở cuối trang). Trong 5 phút nữa, một cụm Kubernetes 3 nút sẽ sẵn sàng. Bây giờ, trên máy trạm của bạn, hãy cài đặt SDK gcloud như được hiển thị trong hướng dẫn này, sau đó kéo cấu hình Kubernetes vào máy trạm của bạn:
$ gcloud container clusters get-credentials my-k8s-cluster --zone asia-northeast1-a --project s9s-qa
Fetching cluster endpoint and auth data.
kubeconfig entry generated for my-k8s-cluster.
Bạn có thể kết nối với cụm Kubernetes tại thời điểm này. Chạy lệnh sau để xác minh:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
gke-my-k8s-cluster-default-pool-b80902cd-gp09 Ready <none> 139m v1.16.13-gke.401
gke-my-k8s-cluster-default-pool-b80902cd-jdc3 Ready <none> 139m v1.16.13-gke.401
gke-my-k8s-cluster-default-pool-b80902cd-rdv8 Ready <none> 139m v1.16.13-gke.401
Kết quả trên có nghĩa là chúng ta có thể kết nối với Kubernetes master và truy xuất các nút cụm Kubernetes. Bây giờ, chúng tôi đã sẵn sàng chạy khối lượng công việc Kubernetes.
Triển khai Cụm Percona XtraDB trên Kubernetes
Để triển khai khối lượng công việc, chúng tôi sẽ làm theo các hướng dẫn như đã nêu trong tài liệu Percona XtraDB Cluster Operator. Về cơ bản, chúng tôi chạy lệnh sau trên máy trạm của mình để tạo tài nguyên tùy chỉnh, không gian tên, kiểm soát truy cập dựa trên vai trò và cả chính toán tử Kubernetes:
$ git clone -b v1.6.0 https://github.com/percona/percona-xtradb-cluster-operator
$ cd percona-xtradb-cluster-operator/
$ kubectl apply -f deploy/crd.yaml
$ kubectl create namespace pxc
$ kubectl config set-context $(kubectl config current-context) --namespace=pxc
$ kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value core/account)
$ kubectl apply -f deploy/rbac.yaml
$ kubectl apply -f deploy/operator.yaml
Tiếp theo, chúng ta phải chuẩn bị mật khẩu của mình (nó được gọi là Bí mật trong thuật ngữ Kubernetes) bằng cách cập nhật các giá trị bên trong deploy / secret.yaml ở định dạng được mã hóa base64. Bạn có thể sử dụng các công cụ trực tuyến như https://www.base64encode.org/ để tạo một hoặc sử dụng công cụ dòng lệnh như sau:
$ echo -n 'mypassword' | base64
bXlwYXNzd29yZA==
Sau đó, cập nhật triển khai / secret.yaml, như được hiển thị bên dưới:
apiVersion: v1
kind: Secret
metadata:
name: my-cluster-secrets
type: Opaque
data:
root: bXlwYXNzd29yZA==
xtrabackup: bXlwYXNzd29yZA==
monitor: bXlwYXNzd29yZA==
clustercheck: bXlwYXNzd29yZA==
proxyadmin: bXlwYXNzd29yZA==
pmmserver: bXlwYXNzd29yZA==
operator: bXlwYXNzd29yZA==
Trên đây là cách quản lý bí mật siêu đơn giản, trong đó chúng tôi đặt tất cả mật khẩu giống nhau cho tất cả người dùng. Trong sản xuất, vui lòng sử dụng mật khẩu phức tạp hơn và chỉ định một mật khẩu khác cho mọi người dùng.
Bây giờ, chúng ta có thể đẩy cấu hình bí mật sang Kubernetes:
$ kubectl apply -f deploy/secrets.yaml
Trước khi tiếp tục triển khai Percona XtraDB Cluster, chúng ta cần xem lại định nghĩa triển khai mặc định bên trong deploy / cr.yaml cho cụm. Có rất nhiều đối tượng Kubernetes được định nghĩa ở đây nhưng hầu hết chúng đều được bình luận. Đối với khối lượng công việc của chúng tôi, chúng tôi sẽ thực hiện sửa đổi như sau:
$ cat deploy/cr.yaml
apiVersion: pxc.percona.com/v1-6-0
kind: PerconaXtraDBCluster
metadata:
name: cluster1
finalizers:
- delete-pxc-pods-in-order
spec:
crVersion: 1.6.0
secretsName: my-cluster-secrets
vaultSecretName: keyring-secret-vault
sslSecretName: my-cluster-ssl
sslInternalSecretName: my-cluster-ssl-internal
allowUnsafeConfigurations: false
updateStrategy: SmartUpdate
upgradeOptions:
versionServiceEndpoint: https://check.percona.com
apply: recommended
schedule: "0 4 * * *"
pxc:
size: 3
image: percona/percona-xtradb-cluster:8.0.20-11.1
configuration: |
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
collation-server = utf8_unicode_ci
character-set-server = utf8
default_authentication_plugin = mysql_native_password
resources:
requests:
memory: 1G
affinity:
antiAffinityTopologyKey: "kubernetes.io/hostname"
podDisruptionBudget:
maxUnavailable: 1
volumeSpec:
persistentVolumeClaim:
resources:
requests:
storage: 6Gi
gracePeriod: 600
haproxy:
enabled: true
size: 3
image: percona/percona-xtradb-cluster-operator:1.6.0-haproxy
resources:
requests:
memory: 1G
affinity:
antiAffinityTopologyKey: "kubernetes.io/hostname"
podDisruptionBudget:
maxUnavailable: 1
gracePeriod: 30
backup:
image: percona/percona-xtradb-cluster-operator:1.6.0-pxc8.0-backup
storages:
fs-pvc:
type: filesystem
volume:
persistentVolumeClaim:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 6Gi
schedule:
- name: "daily-backup"
schedule: "0 0 * * *"
keep: 5
storageName: fs-pvc
Chúng tôi đã thực hiện một số sửa đổi đối với cr.yaml được cung cấp để làm cho nó hoạt động với ứng dụng của chúng tôi, như được hiển thị ở trên. Trước hết, chúng ta phải nhận xét (hoặc xóa) tất cả các dòng liên quan đến CPU, ví dụ [*]. Resources.requests.cpu:600m, để đảm bảo Kubernetes có thể lên lịch tạo nhóm chính xác trên các nút có CPU hạn chế. Sau đó, chúng tôi cần thêm một số tùy chọn tương thích cho Percona XtraDB Cluster 8.0 dựa trên MySQL 8.0, để hoạt động trơn tru với ứng dụng WordPress của chúng tôi mà chúng tôi sẽ triển khai sau này, như được hiển thị trong đoạn trích sau:
Cấu hình configuration: |
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
collation-server = utf8_unicode_ci
character-set-server = utf8
default_authentication_plugin = mysql_native_password
Ở trên sẽ khớp với bộ ký tự mặc định của máy chủ MySQL với trình điều khiển MySQLi PHP trong vùng chứa WordPress của chúng tôi. Phần tiếp theo là triển khai HAProxy, nơi nó được đặt thành "enable:true". Ngoài ra còn có một phần ProxySQL với "enable:false" - thông thường người ta sẽ chọn một trong các proxy ngược cho mọi cụm. Phần cuối cùng là cấu hình sao lưu, trong đó chúng tôi muốn sao lưu hàng ngày được lên lịch vào lúc 12:00 sáng hàng ngày và giữ 5 bản sao lưu cuối cùng đó.
Bây giờ chúng ta có thể bắt đầu triển khai Cụm Percona XtraDB 3 nút của mình:
$ kubectl apply -f deploy/cr.yaml
Quá trình tạo sẽ mất một thời gian. Người điều hành sẽ triển khai nhóm Percona XtraDB Cluster dưới dạng Stateful Set, có nghĩa là mỗi lần tạo một nhóm và mỗi Pod trong StatefulSet sẽ được gán một số nguyên, từ 0 trở lên đến N-1, là duy nhất trên tập hợp. Quá trình kết thúc khi cả người vận hành và Nhóm đều đạt đến trạng thái Đang chạy:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
cluster1-haproxy-0 2/2 Running 0 71m
cluster1-haproxy-1 2/2 Running 0 70m
cluster1-haproxy-2 2/2 Running 0 70m
cluster1-pxc-0 1/1 Running 0 71m
cluster1-pxc-1 1/1 Running 0 70m
cluster1-pxc-2 1/1 Running 0 69m
percona-xtradb-cluster-operator-79d786dcfb-6clld 1/1 Running 0 121m
Vì toán tử này là tài nguyên tùy chỉnh, chúng tôi có thể thao tác tài nguyên perconaxtradbcluster để giống tài nguyên Kubernetes tiêu chuẩn:
$ kubectl get perconaxtradbcluster
NAME ENDPOINT STATUS PXC PROXYSQL HAPROXY AGE
cluster1 cluster1-haproxy.pxc ready 3 3 27h
Bạn cũng có thể sử dụng tên tài nguyên ngắn hơn, "pxc" và thử với các lệnh sau:
$ kubectl describe pxc
$ kubectl edit pxc
Khi nhìn vào nhóm khối lượng công việc, chúng ta có thể biết rằng nhà điều hành đã tạo hai Bộ trạng thái:
$ kubectl get statefulsets -o wide
NAME READY AGE CONTAINERS IMAGES
cluster1-haproxy 3/3 26h haproxy,pxc-monit percona/percona-xtradb-cluster-operator:1.6.0-haproxy,percona/percona-xtradb-cluster-operator:1.6.0-haproxy
cluster1-pxc 3/3 26h pxc percona/percona-xtradb-cluster:8.0.20-11.2
Nhà điều hành cũng sẽ tạo các dịch vụ tương ứng sẽ kết nối cân bằng tải với các nhóm tương ứng:
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cluster1-haproxy ClusterIP 10.40.9.177 <none> 3306/TCP,3309/TCP,33062/TCP 3h27m
cluster1-haproxy-replicas ClusterIP 10.40.0.236 <none> 3306/TCP 3h27m
cluster1-pxc ClusterIP None <none> 3306/TCP,33062/TCP 3h27m
cluster1-pxc-unready ClusterIP None <none> 3306/TCP,33062/TCP 3h27m
Kết quả trên cho thấy nhà điều hành đã tạo 4 dịch vụ:
- cluster1-haproxy - Dịch vụ cho MySQL single-master (3306), giao thức Proxy (3309) và MySQL Admin (33062) - Một cổng quản trị mới được giới thiệu trong MySQL 8.0.14 trở lên. Đây là tên dịch vụ hoặc địa chỉ IP cụm mà các ứng dụng cần kết nối để có một kết nối tổng thể duy nhất với cụm Galera.
- cluster1-haproxy-replicas - Dịch vụ cho đa chủ MySQL cân bằng tải (3306). Đây là tên dịch vụ hoặc địa chỉ IP cụm mà các ứng dụng cần kết nối để có kết nối đa tổng thể với cụm Galera với thuật toán cân bằng tổng hợp.
- cluster1-pxc - Dịch vụ cho các nhóm PXC cân bằng tải, bỏ qua HAProxy. Bằng cách kết nối trực tiếp với dịch vụ này, Kubernetes sẽ định tuyến kết nối theo kiểu vòng tròn tới tất cả các nhóm PXC, tương tự như những gì cluster-haproxy-replicase cung cấp. Dịch vụ không có địa chỉ IP công cộng được chỉ định và không khả dụng bên ngoài cụm.
- cluster1-pxc-unready - Dịch vụ 'chưa sẵn sàng' là cần thiết để phát hiện địa chỉ nhóm trong quá trình khởi động ứng dụng bất kể trạng thái của nhóm. Nhóm Proxysql và pxc nên biết về nhau trước khi cơ sở dữ liệu hoạt động hoàn toàn. Dịch vụ chưa có sẵn không có địa chỉ IP công cộng được chỉ định và không khả dụng bên ngoài cụm.
Để kết nối qua máy khách MySQL, chỉ cần chạy lệnh sau:
$ kubectl run -i --rm --tty percona-client --image=percona:8.0 --restart=Never -- bash -il
Thao tác này sẽ tạo một Pod tạm thời và ngay lập tức vào môi trường vùng chứa. Sau đó, chạy lệnh máy khách mysql tiêu chuẩn với thông tin đăng nhập thích hợp:
bash-4.2$ mysql -uroot -pmypassword -h cluster1-haproxy -P3306 -e 'SELECT @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+----------------+
| @@hostname |
+----------------+
| cluster1-pxc-0 |
+----------------+
Khi chúng tôi xem xét vị trí Pod, tất cả các nhóm Percona XtraDB Cluster đều nằm trên một máy chủ Kubernetes khác:
$ kubectl get pods -o wide --selector=app.kubernetes.io/component=pxc
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cluster1-pxc-0 1/1 Running 0 67m 10.36.2.5 gke-my-k8s-cluster-default-pool-b80902cd-gp09 <none> <none>
cluster1-pxc-1 1/1 Running 0 66m 10.36.1.10 gke-my-k8s-cluster-default-pool-b80902cd-rdv8 <none> <none>
cluster1-pxc-2 1/1 Running 0 65m 10.36.0.11 gke-my-k8s-cluster-default-pool-b80902cd-jdc3 <none> <none>
Điều này chắc chắn sẽ cải thiện tính khả dụng của dịch vụ, trong trường hợp một trong các máy chủ Kubernetes gặp sự cố.
Để mở rộng quy mô lên đến 5 nhóm, chúng tôi cần chuẩn bị trước 2 nút Kubernetes mới khác để tôn trọng cấu hình mối quan hệ nhóm (mặc định là affinity.antiAffinityTopologyKey.topologyKey ="kubernetes.io/hostname"). Sau đó, chạy lệnh vá sau để mở rộng Cụm Percona XtraDB thành 5 nút:
$ kubectl patch pxc cluster1 \
--type='json' -p='[{"op": "replace", "path": "/spec/pxc/size", "value": 5 }]'
Theo dõi quá trình tạo nhóm bằng cách sử dụng lệnh kubectl get pods:
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cluster1-pxc-0 1/1 Running 0 27h 10.36.2.5 gke-my-k8s-cluster-default-pool-b80902cd-gp09 <none> <none>
cluster1-pxc-1 1/1 Running 0 27h 10.36.1.10 gke-my-k8s-cluster-default-pool-b80902cd-rdv8 <none> <none>
cluster1-pxc-2 1/1 Running 0 27h 10.36.0.11 gke-my-k8s-cluster-default-pool-b80902cd-jdc3 <none> <none>
cluster1-pxc-3 1/1 Running 0 30m 10.36.7.2 gke-my-k8s-cluster-pool-1-ab14a45e-h1pf <none> <none>
cluster1-pxc-4 1/1 Running 0 13m 10.36.5.3 gke-my-k8s-cluster-pool-1-ab14a45e-01qn <none> <none>
2 Nhóm mới khác (cluster1-pxc-3 và cluster1-pxc-4) đã được tạo trên 2 nút Kubernetes mới khác (gke-my-k8s-cluster-pool-1-ab14a45e-h1pf và gke-my-k8s-cluster-pool-1-ab14a45e-01qn). Để giảm tỷ lệ, chỉ cần thay đổi giá trị trở lại 3 trong lệnh vá ở trên. Lưu ý rằng Percona XtraDB Cluster nên chạy với một số lượng nút lẻ để ngăn chặn sự phân chia não bộ.
Triển khai ứng dụng (WordPress)
Trong ví dụ này, chúng tôi sẽ triển khai một ứng dụng WordPress trên Percona XtraDB Cluster và HAProxy của chúng tôi. Trước tiên, hãy chuẩn bị tệp định nghĩa YAML như sau:
$ cat wordpress-deployment.yaml
apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
spec:
ports:
- port: 80
selector:
app: wordpress
tier: frontend
type: LoadBalancer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wp-pv-claim
labels:
app: wordpress
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: frontend
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
tier: frontend
spec:
containers:
- image: wordpress:4.8-apache
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: cluster1-haproxy
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-cluster-secrets
key: root
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-persistent-storage
mountPath: /var/www/html
volumes:
- name: wordpress-persistent-storage
persistentVolumeClaim:
claimName: wp-pv-claim
Chú ý đến các biến môi trường WORDPRESS_DB_HOST và WORDPRESS_DB_PASSWORD. Biến trước đây mà chúng tôi đã xác định "cluster1-haproxy" là máy chủ cơ sở dữ liệu, thay vì một nút cơ sở dữ liệu riêng lẻ và đối với biến sau, chúng tôi chỉ định mật khẩu gốc bằng cách hướng dẫn Kubernetes đọc nó từ đối tượng my-cluster-secret dưới khóa "root", tương đương với "mypassword" (sau khi giá trị base64 được giải mã). Chúng tôi bỏ qua việc xác định biến môi trường WORDPRESS_DB_USER vì giá trị mặc định là "root".
Bây giờ chúng ta có thể tạo ứng dụng của mình:
$ kubectl apply -f wordpress-deployment.yaml
Kiểm tra dịch vụ:
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cluster1-haproxy ClusterIP 10.40.9.177 <none> 3306/TCP,3309/TCP,33062/TCP 4h42m
cluster1-haproxy-replicas ClusterIP 10.40.0.236 <none> 3306/TCP 4h42m
cluster1-pxc ClusterIP None <none> 3306/TCP,33062/TCP 4h42m
cluster1-pxc-unready ClusterIP None <none> 3306/TCP,33062/TCP 4h42m
wordpress LoadBalancer 10.40.13.205 35.200.78.195 80:32087/TCP 4h39m
Tại thời điểm này, chúng ta có thể kết nối với ứng dụng WordPress của mình tại http://35.200.78.195/ (địa chỉ IP bên ngoài) và bắt đầu định cấu hình ứng dụng WordPress. Tại thời điểm này, ứng dụng WordPress của chúng tôi được kết nối với một trong Percona XtraDB Cluster (kết nối một chủ) thông qua một trong các nhóm HAProxy.
Đó là nó cho bây giờ. Để biết thêm thông tin, hãy xem tài liệu Percona Kubernetes Operator cho Percona XtraDB Cluster. Chúc vui vẻ!