lab:kubernetes_app:step_4_-_mysql_server
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
lab:kubernetes_app:step_4_-_mysql_server [2024/02/07 22:12] – [Deploying MySQL with Persistent Storage using Ansible] user | lab:kubernetes_app:step_4_-_mysql_server [2024/05/13 18:16] (current) – removed user | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Step 4 - MySQL Server ====== | ||
- | Now that we have Kubernetes up and running, we will get our MySQL container up and running. We will need storage for the SQL database so that it isn't lost the pod is deleted or recreated. We also want the MySQL container/ | ||
- | |||
- | References: | ||
- | * [[https:// | ||
- | * [[https:// | ||
- | * [[https:// | ||
- | * [[https:// | ||
- | * [[https:// | ||
- | |||
- | To Do: | ||
- | * We have the secret creation, but we need to actually use it | ||
- | * The MySQL server works with sockets, but need to prove it works over IP from another deployment' | ||
- | * had REAL difficulties with updating the /etc/my.cnf file.... | ||
- | |||
- | ====== Create MySQL Deployment ====== | ||
- | To deploy MySQL on Kubernetes, we will use a Deployment object, which is a higher-level abstraction that manages a set of replicas of a pod. The pod contains the MySQL container along with any necessary configuration. | ||
- | |||
- | At the time of writing the latest image being pulled is version 8.3.0 and runs on Oracle Linux Server 8.9. | ||
- | |||
- | There are three parts we will use | ||
- | * deployment | ||
- | * PersistentVolume | ||
- | * PersistentVolumeClaim | ||
- | |||
- | Finally, we will use Ansible to do the work. | ||
- | |||
- | ===== Deployment ===== | ||
- | <file yaml k8s-deployment-sql.yml> | ||
- | apiVersion: apps/v1 | ||
- | kind: Deployment | ||
- | metadata: | ||
- | name: mysql-deployment | ||
- | spec: | ||
- | replicas: 1 | ||
- | selector: | ||
- | matchLabels: | ||
- | app: mysql | ||
- | template: | ||
- | metadata: | ||
- | labels: | ||
- | app: mysql | ||
- | spec: | ||
- | nodeSelector: | ||
- | my-role: sql # restrict scheduling to the node with the label my-role: sql | ||
- | containers: | ||
- | - name: mysql | ||
- | image: mysql | ||
- | env: | ||
- | - name: MYSQL_ROOT_PASSWORD | ||
- | value: yourpassword | ||
- | ports: | ||
- | - containerPort: | ||
- | volumeMounts: | ||
- | - name: mysql-persistent-storage | ||
- | mountPath: / | ||
- | volumes: | ||
- | - name: mysql-persistent-storage | ||
- | persistentVolumeClaim: | ||
- | claimName: mysql-pvc | ||
- | </ | ||
- | |||
- | We can launch the deployment manually using kubectl: | ||
- | <code bash> | ||
- | kubectl apply -f k8s-deployment-sql.yml | ||
- | </ | ||
- | |||
- | What happened and what didn't happen? Examine the output of the following commands | ||
- | * kubectl get pods | ||
- | * kubectl get deployments | ||
- | * kubectl describe deployments | ||
- | |||
- | To remove it, run: | ||
- | <code bash> | ||
- | kubectl delete -f k8s-deployment-sql.yml | ||
- | </ | ||
- | |||
- | Our manifest refers to something that doesn' | ||
- | |||
- | ===== PersistentVolume ===== | ||
- | By default, the MySQL pod does not have persistent storage, which means that any data stored in the pod will be lost if the pod is deleted or recreated. We are going to create a persistent volume that pods can mount. | ||
- | <file yaml k8s-pv.yml> | ||
- | apiVersion: v1 | ||
- | kind: PersistentVolume | ||
- | metadata: | ||
- | name: my-pv | ||
- | spec: | ||
- | capacity: | ||
- | storage: 5Gi | ||
- | accessModes: | ||
- | - ReadWriteOnce | ||
- | hostPath: | ||
- | path: /data/my-pv | ||
- | </ | ||
- | |||
- | We can create the persistent volume manually using kubectl: | ||
- | <code bash> | ||
- | kubectl apply -f k8s-pv.yml | ||
- | </ | ||
- | |||
- | Examine the output of the following commands | ||
- | * kubectl get pv | ||
- | * kubectl describe pv | ||
- | |||
- | To remove it, run: | ||
- | <code bash> | ||
- | kubectl delete-f k8s-pv.yml | ||
- | </ | ||
- | |||
- | ===== PersistentVolumeClaim ===== | ||
- | Now we will create a " | ||
- | |||
- | <file yaml k8s-pvc.yml> | ||
- | apiVersion: v1 | ||
- | kind: PersistentVolumeClaim | ||
- | metadata: | ||
- | name: mysql-pvc | ||
- | spec: | ||
- | accessModes: | ||
- | - ReadWriteOnce | ||
- | resources: | ||
- | | ||
- | storage: 5Gi | ||
- | </ | ||
- | |||
- | We can create the persistent volume claim manually using kubectl (but the persistent volume needs to exist): | ||
- | <code bash> | ||
- | kubectl apply -f k8s-pvc.yml | ||
- | </ | ||
- | |||
- | Examine the output of the following commands | ||
- | * kubectl get pvc | ||
- | * kubectl describe pvc | ||
- | |||
- | To remove it, run: | ||
- | <code bash> | ||
- | kubectl delete-f k8s-pvc.yml | ||
- | </ | ||
- | |||
- | If you create all three things, the pod will come up! But for now, we want to deploy all these with Ansible. And we want to run a script to grant create a user and grant permissions. | ||
- | |||
- | ===== Exposing MySQL with a Service ===== | ||
- | The MySQL server should be accessible from other deployments in Kubernetes, but secure from outside access. By creating a Service object, we create a stable IP address and port that can be used to connect to the MySQL server. | ||
- | |||
- | <file k8s-service-sql.yml> | ||
- | apiVersion: v1 | ||
- | kind: Service | ||
- | metadata: | ||
- | name: sql-service | ||
- | spec: | ||
- | selector: | ||
- | app: mysql | ||
- | ports: | ||
- | - protocol: TCP | ||
- | port: 3306 | ||
- | targetPort: 3306 | ||
- | </ | ||
- | |||
- | < | ||
- | |||
- | ===== Deploying MySQL with Persistent Storage using Ansible ===== | ||
- | This lab deploys everything in the " | ||
- | |||
- | <file yaml deploy-sql.yml> | ||
- | --- | ||
- | - name: Deploy MySQL with persistent volume | ||
- | hosts: localhost | ||
- | connection: local | ||
- | tasks: | ||
- | - name: Create ConfigMap | ||
- | kubernetes.core.k8s: | ||
- | state: present | ||
- | namespace: default | ||
- | definition: | ||
- | apiVersion: v1 | ||
- | kind: ConfigMap | ||
- | metadata: | ||
- | name: mysql-setup-script | ||
- | data: | ||
- | grant_remote_access.sh: | ||
- | #!/bin/bash | ||
- | / | ||
- | CREATE USER ' | ||
- | CREATE USER ' | ||
- | GRANT ALL ON *.* TO ' | ||
- | GRANT ALL ON *.* TO ' | ||
- | FLUSH PRIVILEGES; | ||
- | CREATE DATABASE app_db; | ||
- | EXIT; | ||
- | EOF | ||
- | - name: Create Secret | ||
- | kubernetes.core.k8s: | ||
- | state: present | ||
- | definition: "{{ lookup(' | ||
- | namespace: default | ||
- | - name: Create Deployment | ||
- | kubernetes.core.k8s: | ||
- | state: present | ||
- | definition: "{{ lookup(' | ||
- | namespace: default | ||
- | - name: Create PersistentVolume | ||
- | kubernetes.core.k8s: | ||
- | state: present | ||
- | definition: "{{ lookup(' | ||
- | namespace: default | ||
- | - name: Create PersistentVolumeClaim | ||
- | kubernetes.core.k8s: | ||
- | state: present | ||
- | definition: "{{ lookup(' | ||
- | namespace: default | ||
- | - name: Create Service | ||
- | kubernetes.core.k8s: | ||
- | state: present | ||
- | definition: "{{ lookup(' | ||
- | namespace: default | ||
- | </ | ||
- | |||
- | Run: '' | ||
- | |||
- | Take a look at the results by running: | ||
- | * kubectl get pod, | ||
- | |||
- | Now confirm that the new MySQL pod is running on " | ||
- | * '' | ||
- | * Look for the line similar to: '' | ||
- | |||
- | ====== Testing MySQL server ====== | ||
- | Congratulations on your brand new MySQL server! In this step we are going do demonstrate that this MySQL server will retain its database across reboots, upgrades, and even deleting and re-creating the deployment. | ||
- | |||
- | ===== Connecting to the MySQL Server Pod ===== | ||
- | First, identify the pod name using | ||
- | < | ||
- | |||
- | Next, use the pod name to connect interactively. | ||
- | < | ||
- | |||
- | For example, | ||
- | < | ||
- | |||
- | ===== Login Using mysql Command ===== | ||
- | The only account existing by default is '' | ||
- | |||
- | Log in using the credentials: | ||
- | <code bash> | ||
- | mysql -uroot -pyourpassword | ||
- | </ | ||
- | |||
- | Take a look at what is there by default: (don't forget the trailing semicolon;) | ||
- | * show grants; | ||
- | * show databases; | ||
- | |||
- | Use '' | ||
- | |||
- | NOTE You can also log in with the user '' | ||
- | |||
- | ===== Demonstrating Persistence ===== | ||
- | Log back in to the pod and re-launch '' | ||
- | |||
- | Here we will: | ||
- | - create a database | ||
- | - select the new database | ||
- | - create a table in the database | ||
- | - insert a row | ||
- | - show the data we inserted | ||
- | |||
- | < | ||
- | CREATE DATABASE test; | ||
- | USE test; | ||
- | CREATE TABLE messages (message VARCHAR(255)); | ||
- | INSERT INTO messages (message) VALUES (' | ||
- | SELECT * FROM messages; | ||
- | </ | ||
- | |||
- | Now we will create an ansible playbook the remove not only the deployment but also the persistent storage. | ||
- | |||
- | <file yaml destroy-sql.yml> | ||
- | --- | ||
- | - name: Destroy MySQL with persistent volume | ||
- | hosts: localhost | ||
- | connection: local | ||
- | tasks: | ||
- | - name: Remove ConfigMap | ||
- | kubernetes.core.k8s: | ||
- | api_version: | ||
- | kind: ConfigMap | ||
- | name: mysql-setup-script | ||
- | state: absent | ||
- | namespace: default | ||
- | - name: Remove Secret | ||
- | kubernetes.core.k8s: | ||
- | state: absent | ||
- | definition: "{{ lookup(' | ||
- | namespace: default | ||
- | - name: Remove Deployment | ||
- | kubernetes.core.k8s: | ||
- | state: absent | ||
- | definition: "{{ lookup(' | ||
- | namespace: default | ||
- | - name: Remove PersistentVolume | ||
- | kubernetes.core.k8s: | ||
- | state: absent | ||
- | definition: "{{ lookup(' | ||
- | namespace: default | ||
- | - name: Remove PersistentVolumeClaim | ||
- | kubernetes.core.k8s: | ||
- | state: absent | ||
- | definition: "{{ lookup(' | ||
- | namespace: default | ||
- | - name: Remove Service | ||
- | kubernetes.core.k8s: | ||
- | state: absent | ||
- | definition: "{{ lookup(' | ||
- | namespace: default | ||
- | </ | ||
- | |||
- | See what exists before you destroy everything: | ||
- | < | ||
- | |||
- | Run the playbook '' | ||
- | |||
- | See what exists after you destroyed everything: | ||
- | < | ||
- | |||
- | Deploy again | ||
- | < | ||
- | |||
- | Watch as everything comes back up: | ||
- | < | ||
- | |||
- | Identify the new pod name using | ||
- | < | ||
- | |||
- | Connect to the new pod interactively. (again, substitute the actual pod name) | ||
- | < | ||
- | |||
- | Reconnect to mysql | ||
- | < | ||
- | |||
- | Check the outputs of these commands: | ||
- | * show databases; | ||
- | * use test; | ||
- | * show tables; | ||
- | * SELECT * FROM messages; | ||
- | |||
- | Now let's clean up the test database and table: | ||
- | * DROP TABLE messages; | ||
- | * DROP DATABASE test; | ||
- | |||
- | Use '' | ||
- | |||
- | ====== Next Step ====== | ||
- | Continue to [[Step 5 - Application Pods]] | ||
- | |||
- | Or back to [[Step 3 - Set Up Kubernetes]] or [[Start]] | ||
- | |||
- | ====== Optional ====== | ||
- | You can restore a MySQL database dump to play with. Here is the command. | ||
- | |||
- | < | ||
- | mysql -u [user name] –p [target_database_name] < [dumpfilename.sql] | ||
- | </ | ||
- | |||
- | < | ||
- | |||
- | < | ||
- | |||
- | ===== Allowing Remote Access ===== | ||
- | We created a user '' | ||
- | |||
- | < | ||
- | CREATE USER ' | ||
- | CREATE USER ' | ||
- | GRANT ALL ON *.* TO ' | ||
- | GRANT ALL ON *.* TO ' | ||
- | FLUSH PRIVILEGES; | ||
- | EXIT; | ||
- | </ | ||
- | |||
- | < | ||
- | |||
- | What ports is MySQL listening on? | ||
- | |||
- | See the configuration files at: | ||
- | * /etc/my.cnf | ||
- | * / | ||
- | * / | ||
- | |||
- | Normally you would sudo vi / | ||
- | * Locate and Modify the " | ||
- | * Find the line that says bind-address = 127.0.0.1 (which restricts connections to localhost). | ||
- | * Either: | ||
- | * Comment it out: Add a # at the beginning of the line to disable it. | ||
- | * Change it to the server' | ||
- | * Save and Restart MySQL: '' | ||
- | |||
- | Since the bind-address isn't listed, how can we double-check? | ||
- | |||
- | It looks like MySQL is only using the Unix socket, not any IP address. | ||
lab/kubernetes_app/step_4_-_mysql_server.1707343958.txt.gz · Last modified: 2024/02/07 22:12 by user