Dieses Tutorial zeigt detaillierte Schritte zum Bereitstellen von MySQL auf Kubernetes. Ich werde hier minikube verwenden, um Kubernetes-MySQL-Beispiele zu demonstrieren.
Wir alle wissen um die große Bedeutung der Datenpersistenz und fast alle unsere Anwendungen verlassen sich in hohem Maße auf eine Art Datenbankmanagementsystem (DBMS). Das Einrichten eines DBMS auf Kubernetes hilft dem DevOps-Team und den Datenbankadministratoren, die Datenbank einfach zu nutzen und zu skalieren.
Bereiten Sie die Umgebung vor
Folgen Sie diesem Tutorial, damit Minikube auf Ihrem Ubuntu Linux installiert ist.
Sie können mit dem folgenden Befehl überprüfen, ob der Minikube erfolgreich gestartet wurde:
$ minikube status
Ausgabe:
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
Geheimnis für MySQL erstellen
Kubernetes verwendet Secret
um sensible Informationen wie Passwörter, SSH-Schlüssel und OAuth-Token zu speichern und zu verwalten. In diesem Tutorial verwenden wir base64
codiert, um ‘MYSQL_ROOT_PASSWORD’ zu speichern. Für example:
$ echo -n 'admin' | base64
Ausgabe:
YWRtaW4=
Ein … kreieren mysql-secret.yaml
Datei für MySQL, die wie folgt als Umgebungsvariable abgebildet wird:
apiVersion: v1
kind: Secret
metadata:
name: mysql-pass
type: Opaque
data:
password: YWRtaW4=
Wenden Sie das Manifest an:
$ kubectl create -f mysql-secret.yaml
secret/mysql-pass created
Stellen Sie sicher, dass die Secret
wurde gerade erfolgreich erstellt:
$ kubectl get secrets
NAME TYPE DATA AGE
default-token-l7t7b kubernetes.io/service-account-token 3 4h24m
mysql-pass Opaque 1 1m
MySQL bereitstellen
Erstellen Sie die mysql-pod.yaml
Datei zum Bereitstellen eines MySQL-Pods auf einem Kubernetes-Cluster:
apiVersion: v1
kind: Pod
metadata:
name: k8s-mysql
labels:
name: lbl-k8s-mysql
spec:
containers:
- name: mysql
image: mysql:latest
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
ports:
- name: mysql
containerPort: 3306
protocol: TCP
volumeMounts:
- name: k8s-mysql-storage
mountPath: /var/lib/mysql
volumes:
- name: k8s-mysql-storage
emptyDir: {}
Wenden Sie die Manifestdatei an:
$ kubectl create -f mysql-pod.yaml
pod/k8s-mysql created
Überprüfen Sie, ob der Pod ausgeführt wird:
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
k8s-mysql 1/1 Running 0 30s
Jetzt können wir uns mit dem verbinden k8s-mysql
unter:
$ kubectl exec k8s-mysql -it -- bash
root@k8s-mysql:/# echo $MYSQL_ROOT_PASSWORD
admin
root@k8s-mysql:/# mysql --user=root --password=$MYSQL_ROOT_PASSWORD
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or g.
Your MySQL connection id is 11
Server version: 8.0.22 MySQL Community Server - GPL
Copyright (c) 2000, 2020, 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> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql>
Kubernetes-Verwendung Service
um Pods anderen Pods oder externen Systemen zugänglich zu machen. Wir werden die folgende Manifestdatei verwenden mysql-service.yaml
um das zu machen k8s-mysql
Pod erreichbar sein:
apiVersion: v1
kind: Service
metadata:
name: mysql-service
labels:
name: lbl-k8s-mysql
spec:
ports:
- port: 3306
selector:
name: lbl-k8s-mysql
type: ClusterIP
Wenden Sie das Manifest an, um den Dienst zu erstellen:
$ kubectl create -f mysql-service.yaml
service/mysql-service created
Überprüfen Sie, ob der Dienst erfolgreich erstellt wurde:
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 5h4m
mysql-service ClusterIP 10.110.22.182 3306/TCP 30s
Erstellen einer NodeJS-API für mysql
Um von einem anderen Pod aus eine Verbindung zu mysql herstellen zu können, benötigen wir die IP
Adresse unseres Pods, die Sie verwenden können:
$ kubectl get pod k8s-mysql -o template --template={{.status.podIP}}
172.17.0.5
Okay, jetzt erstelle ich ein Beispiel NodeJS
app, um eine Reihe von Nachrichten in der Tabelle MESSAGES der Datenbank zu speichern, hat die App zwei Endpunkte:
- ‘/ping’: um den Serverzustand zu überprüfen
- ‘/msg-api/all’: um alle gespeicherten Nachrichten abzurufen
Der Einfachheit halber hat die Tabelle nur eine Spalte namens TEXT.
Das Wichtigste zuerst, Knoten-App:
// api.js -> Endpunkte geht hier
var express = require('express')
var mysql = require('mysql')
var Router = express.Router();
var ConnPool = mysql.createPool({
host: '172.17.0.5',
user: 'root',
password: 'admin',
database: 'k8smysqldb'
})
// create database and MESSAGE table if not exist
ConnPool.query('CREATE DATABASE IF NOT EXISTS k8smysqldb', function (err) {
if (err) throw Error('nt **** error creating database **** ' + err)
console.log('nt ==== database k8smysqldb created !! ====')
ConnPool.query('USE k8smysqldb', function (err) {
if (err) throw Error('nt **** error using database **** ' + err);
console.log('nt ==== database k8smysqldb switched !! ====')
ConnPool.query('CREATE TABLE IF NOT EXISTS messages('
+ 'id INT NOT NULL AUTO_INCREMENT,'
+ 'PRIMARY KEY(id),'
+ 'text VARCHAR(100)'
+ ')', function (err) {
if (err) throw Error('nt **** error creating table **** ' + err);
})
})
})
/**
* /all
*/
Router.get('/all', function (req, res) {
ConnPool.getConnection(function (errConn, conn) {
if (errConn) throw Error('error get connection : ' + errConn)
conn.query('SELECT * FROM messages', function (errSelect, rows) {
if (errSelect) throw Error('error selecting messages : ' + errSelect)
res.writeHead(200, {
'Content-Type': 'application/json'
});
var result = {
success: true,
rows: rows.length,
}
res.write(JSON.stringify(rows));
res.end();
})
})
})
module.exports = Router
// server.js -> Expressjs-Server feuern
var express = require('express')
var msgApi = require('./api')
var app = express()
app.use('/msg-api', msgApi)
app.get('/ping', function (req, res) {
res.write("hello there! I m up and running!");
res.end();
})
app.listen(8080, function () {
console.log('nt ==== Message API listening on 8080! ====')
})
// Dockerfile -> Docker-Image für unsere App bündeln
FROM node:latest
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app/package.json
RUN npm i
COPY . /usr/src/app/
EXPOSE 8080
CMD [ "node", "server.js" ]
Jetzt können wir unsere Docker-Images aus dem Dockerfile erstellen:
$ docker build -t linoxide/msg-api:v0.0.3 . --no-cache=true
Sending build context to Docker daemon 5.12kB
Step 1/8 : FROM node:latest
---> 2d840844f8e7
Step 2/8 : RUN mkdir -p /usr/src/app
---> Using cache
---> 1c29cda3dcd8
Step 3/8 : WORKDIR /usr/src/app
...
Und übertragen Sie das erstellte Image an Docker Hub:
$ docker push linoxide/msg-api:v0.0.3
The push refers to a repository [docker.io/linoxide/msg-api]
c4477a160652: Pushed
32c1bac97782: Pushed
3d629e3d2e5a: Pushed
...
v1: digest: sha256:dba64e7ff64561f4af866fbbb657555cad7621688c7f312975943f5baf89efa2 size: 2628
Jetzt können wir einen Pod unserer NodeJS-App erstellen, die folgende Spezifikationsdatei msg-api-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: k8s-msg-api
labels:
name: lbl-msg-api
spec:
containers:
- name: msg-api
image: linoxide/msg-api:v0.0.1
ports:
- name: msg-api
Wenden Sie das Manifest an:
$ kubectl create -f msg-api-pod.yaml
pod/k8s-msg-api created
Stellen Sie sicher, dass der Pod ausgeführt wird, indem Sie den Status überprüfen:
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
k8s-msg-api 1/1 Running 0 22s
k8s-mysql 1/1 Running 0 1h
Auf dieser Ebene müssen wir den erstellten Pod freigeben, damit er von außen darauf zugreifen kann. Dieses Mal mache ich es nur mit der Befehlszeile und nicht mit einer Spezifikationsdatei:
$ kubectl expose pod k8s-msg-api --port=8080 --name=k8s-srv-msg-api --type=NodePort
service/k8s-srv-msg-api exposed
Abrufen von Daten aus der MySQL-Datenbank mithilfe von nodejs api
Auf dieser Ebene muss ich auf einige wichtige Dinge hinweisen. Um alle Teile zu verstehen, fassen wir zuerst zusammen, was wir bisher gemacht haben. Wir haben einen MySQL-Pod erstellt und ihn über einen zu erstellenden Dienst bereitgestellt es ist für andere Pods zugänglich, zweitens haben wir eine Beispiel-Nodejs-App erstellt, wir nannten sie eine Messaging-API, damit wir sie verwenden können, um den MySQL-Pod zu erreichen. Um auf die Messaging-API zugreifen zu können, müssen wir sie über einen Dienst bereitstellen. Ich hoffe, dass bis hierher alles klar ist!
Die Frage ist nun, wie wir unsere Messaging-API von außerhalb unseres Clusters hauptsächlich Minikube aufrufen können. Dazu benötigen wir die IP-Adresse unseres Knotens, da ich Minikube verwende, die nur einen Knoten erstellen, damit die IP-Adresse aufgelöst wird, ist die Minikube-IP-Adresse selbst, einfach ausführen:
$ minikube ip
192.168.99.100
Und was ist mit dem Hafen? Na gute Frage! Lassen Sie uns unseren Messaging-API-Dienst beschreiben, um das zu überprüfen:
$ kubectl describe service k8s-srv-msg-api
Name: k8s-srv-msg-api
Namespace: default
Labels: name=lbl-msg-api
Selector: name=lbl-msg-api
Type: NodePort
IP: 10.0.0.170
Port: <unset> 8080/TCP
NodePort: <unset> 30887/TCP
Endpoints: 172.17.0.6:8080
Session Affinity: None
No events.
Wir haben also Port, den Port unseres Messaging-API-Dienstes. NodePort ist der Port, auf dem der exponierte Dienst verfügbar (zugänglich) ist, dh der Dienst ist verfügbar auf NodeIP:NodePort
Probieren wir das aus:
$ curl 192.168.99.100:30887/ping
hello there! I m up and running!%
$ curl 192.168.99.100:30887/msg-api/all
[]%
Sehr schön, soweit wir in der Lage sind, unsere MySQL-Datenbank zu erreichen, fügen wir einige Daten mit dem Terminal in unsere Datenbank ein.
$ kubectl exec k8s-mysql -it -- bash
root@k8s-mysql:/# mysql --user=root --password=$MYSQL_ROOT_PASSWORD
mysql: [Warning] Using a password on the command line interface can be insecure.
...
mysql> use k8smysqldb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+----------------------+
| Tables_in_k8smysqldb |
+----------------------+
| messages |
+----------------------+
1 row in set (0.01 sec)
mysql> insert into messages(text) values ('this is the first msg!');
Query OK, 1 row affected (0.01 sec)
mysql> insert into messages(text) values ('this is the second msg!');
Query OK, 1 row affected (0.01 sec)
Lassen Sie uns diese Daten über unsere nodejs-API abrufen, indem Sie curl:
$ curl 192.168.99.100:30887/msg-api/all
[{"id":1,"text":"this is the first msg!"},{"id":2,"text":"this is the second msg!"}]%
Fazit
Die Containerisierung der MySQL-Datenbank und das Ausführen von DBMS auf einem Kubernetes-Cluster bringt dem DevOps-Team viele Vorteile, wie z.
Vielen Dank fürs Lesen und hinterlassen Sie bitte Ihren Vorschlag im Kommentarbereich unten.