research
devops
reliable
tutorials
HELLO, LONG TIME NO SEE I JUST BRING BACK AFTER THE BREAK STRUGGLE ISSUE ON IMPLEMENTATION AND PROVISIONING AND ALSO I JUST FINISHING THE FLAT OF CAPSTONE PROJECT FOR SCALING PROJECT. SO I JUST WRITE A BLOG FOR GIVE EXPERIENCE, TAKE A BREAK AFTER ISSUE I MET ON ALONG LAST WEEK. TERRIBLE AND STRESSFUL
So i just want a talk it hard or not maybe base on your mindset. LOL and look below for meet some mistake when i met on provision progress
az login # That step requires for getting the subscription
az account set --subscription <subscription-wherer-aks-use> # Change the subscription for your az-cli
az aks show -n <name-of-aks> -g <resource-group-of-aks> | jq -r ".storageProfile.blobCsiDriver"
az aks update --enable-blob-driver -n <name-of-aks> -g <resource-group-of-aks>
NOTICE: This Process will take a couple minutes, so don't worry just wait to see the result blob drive is enabled !
script
, you can go directly to Azure portal
and create that on Storage Account
which you wantAnonymous access level
private
NOTICE: Do not put anything this kind into the blob right know. Because it will cause failure when MySQL runs. Remmember about that (This is my mistake)
Learn More →
resource "random_string" "credentials_website" {
length = 15
min_lower = 5
min_upper = 5
min_numeric = 5
special = false
}
resource "random_uuid" "website_uuid" {
}
resource "kubernetes_secret" "credentials_website" {
metadata {
name = "credentials-website"
}
data = {
"WEBSITE_DATABASE_ROOT_PASSWORD" = random_string.credentials_website.result
}
}
resource "kubernetes_secret" "website_storage_account" {
metadata {
name = "website-storage-account"
}
data = {
"accountName" = var.remote_state.website_storage_account_name
"accountKey" = var.remote_state.website_storage_account_key
}
}
resource "kubernetes_persistent_volume" "website_mysql" {
metadata {
name = "website-mysql"
}
spec {
capacity = {
storage = "5Gi"
}
access_modes = ["ReadWriteOnce"]
storage_class_name = "azureblob"
mount_options = [
"-o allow_other", "--file-cache-timeout-in-seconds=120"
]
persistent_volume_source {
csi {
driver = "blob.csi.azure.com"
volume_handle = "website-mysql-${random_uuid.website_uuid.result}"
volume_attributes = {
"containerName" = "website-mysql"
}
node_stage_secret_ref {
name = "website-storage-account"
namespace = "default"
}
}
}
}
depends_on = [kubernetes_secret.website_storage_account]
}
resource "kubernetes_persistent_volume" "website_wp" {
metadata {
name = "website-wp"
}
spec {
capacity = {
"storage" = "5Gi"
}
access_modes = ["ReadWriteOnce"]
storage_class_name = "azureblob"
mount_options = [
"-o allow_other", "--file-cache-timeout-in-seconds=120"
]
persistent_volume_source {
csi {
driver = "blob.csi.azure.com"
volume_handle = "website-wp-${random_uuid.website_uuid.result}"
volume_attributes = {
"containerName" = "website-wp"
}
node_stage_secret_ref {
name = "website-storage-account"
namespace = "default"
}
}
}
}
depends_on = [kubernetes_secret.website_storage_account]
}
resource "kubernetes_persistent_volume_claim" "website_mysql" {
metadata {
name = "website-mysql"
}
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
"storage" = "5Gi"
}
}
volume_name = kubernetes_persistent_volume.website_mysql.metadata[0].name
storage_class_name = "azureblob"
}
wait_until_bound = true
depends_on = [kubernetes_persistent_volume.website_mysql]
}
resource "kubernetes_config_map" "website_mysql" {
metadata {
name = "website-mysql-conf"
}
data = {
"my.cnf" = "${file("${path.module}/data/my.cnf")}"
}
}
resource "kubernetes_persistent_volume_claim" "website_wp" {
metadata {
name = "website-wp"
}
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
"storage" = "5Gi"
}
}
volume_name = kubernetes_persistent_volume.website_wp.metadata[0].name
storage_class_name = "azureblob"
}
wait_until_bound = true
depends_on = [kubernetes_persistent_volume.website_wp]
}
resource "kubectl_manifest" "mysql_service" {
yaml_body = <<YAML
apiVersion: v1
kind: Service
metadata:
name: website-mysql-service
labels:
app: website-mysql-service
spec:
type: ClusterIP
selector:
app: website-mysql
ports:
- port: 3306
protocol: TCP
YAML
depends_on = [kubernetes_secret.website_storage_account, kubernetes_persistent_volume_claim.website_mysql]
}
resource "kubectl_manifest" "mysql_pod" {
yaml_body = <<YAML
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: website-mysql
spec:
selector:
matchLabels:
app: website-mysql
serviceName: website-mysql-service
replicas: 1
template:
metadata:
labels:
app: website-mysql
spec:
nodeSelector:
pool: defaultpool
containers:
- name: mysql-server
image: mysql:5.7
ports:
- name: mysql
containerPort: 3306
args:
- "--defaults-file=/mysql/conf/my.cnf"
- "--ignore-db-dir=lost+found"
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: credentials-website
key: WEBSITE_DATABASE_ROOT_PASSWORD
- name: MYSQL_DATABASE
value: "wordpress"
volumeMounts:
- name: website-mysql-data
mountPath: /mysql/website
- name: website-mysql-conf
mountPath: /mysql/conf
readOnly: true
volumes:
- name: website-mysql-data
persistentVolumeClaim:
claimName: website-mysql
- name: website-mysql-conf
configMap:
name: website-mysql-conf
items:
- key: "my.cnf"
path: "my.cnf"
YAML
depends_on = [kubernetes_secret.credentials_website, kubernetes_persistent_volume_claim.website_mysql]
}
resource "kubectl_manifest" "wp_service" {
yaml_body = <<YAML
apiVersion: v1
kind: Service
metadata:
name: website-wp-service
labels:
app: website-wp-service
spec:
type: ClusterIP
selector:
app: website-wp
ports:
- name: wp-http
protocol: TCP
port: 80
targetPort: 80
- name: wp-https
protocol: TCP
port: 443
targetPort: 443
YAML
depends_on = [kubectl_manifest.mysql_pod, kubectl_manifest.mysql_service]
}
resource "kubectl_manifest" "wp_pod" {
yaml_body = <<YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: website-wp
spec:
selector:
matchLabels:
app: website-wp
serviceName: website-wp-service
replicas: 1
template:
metadata:
labels:
app: website-wp
spec:
nodeSelector:
pool: defaultpool
containers:
- name: wordpress
image: wordpress:5.7.2-php7.4-apache
resources:
limits:
cpu: 400m
memory: 450Mi
requests:
cpu: 300m
memory: 300Mi
ports:
- containerPort: 80
name: wp-http
protocol: TCP
- containerPort: 443
name: wp-https
protocol: TCP
env:
- name: WORDPRESS_DB_HOST
value: "website-mysql-service"
- name: WORDPRESS_DB_USER
value: "root"
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
key: WEBSITE_DATABASE_ROOT_PASSWORD
name: credentials-website
- name: WORDPRESS_DB_NAME
value: "wordpress"
volumeMounts:
- name: website-wp-data
mountPath: /var/www/html
volumes:
- name: website-wp-data
persistentVolumeClaim:
claimName: website-wp
YAML
depends_on = [kubectl_manifest.mysql_pod, kubectl_manifest.mysql_service]
}
resource "kubectl_manifest" "wp_ingress" {
yaml_body = <<YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: website-wp
spec:
ingressClassName: nginx
tls:
- hosts:
- ${var.website_wp_admin}
secretName: https-certificate
rules:
- host: ${var.website_wp_admin}
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: website-wp-service
port:
number: 80
YAML
depends_on = [kubectl_manifest.mysql_pod, kubectl_manifest.mysql_service]
}
With the script i put it inhere, the step about that will go from
resource "kubernetes_storage_class" "azureblob_csi_nfs" {
metadata {
name = "azureblob"
}
storage_provisioner = "blob.csi.azure.com"
reclaim_policy = "Retain"
parameters = {
skuName = "Standard_LRS"
}
mount_options = [
"-o allow_other", "--file-cache-timeout-in-seconds=120",
"--use-attr-cache=true", "--cancel-list-on-mount-seconds=10",
"-o attr_timeout=120", "-o entry_timeout=12",
"-o negative_timeout=120", "--log-level=LOG_WARNING",
]
}
This is hard to mount_options and understand what situation for doing that. I just said some thing about information, it just shortly in side this blog and blob CSI repo for example. So you need to find exactly repo to understand theory and why they use that kind paramter and what tech is used inside. The technologies behind is blobfuse
and blobfuse 2
(some optional but this is popular)
Go for that you will need create PVC for them and PVC for them is need you to set again mount optional (Too bad for duplicate them but fact, it will not work if you don't because when you go to inside pod it will run with MySQL user but with BlobFuse it need root. Hard thing to understand if you do wrong and so focus to doing that to bypass this before the pod MySQL can go)
The curious thing will not stop in here, when you running MySQL pod in non't optional on MySQL when use BlobFuse PVC - IDK why the heck is Storage Mounting will create before the MySQL Running (Error cause in here and crashloopback container) - On Docker it not happening (Too Bad
Learn More →
"--defaults-file=/mysql/conf/my.cnf" "--ignore-db-dir=lost+found"
on config PARAM MYSQL for bypass this error when running that one with blob storage in K8s. The new my.cnf is
# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# The MySQL Server configuration file.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /mysql/website/data
secure-file-priv= NULL
default-authentication-plugin=mysql_native_password
# Custom config should go here
!includedir /etc/mysql/conf.d/
So go to running that with terraform
Notice: Easily with Docker LOL, do remember set optional for both of SC and PVC for bypass the non root work with blobfuse inside and one more thing blobfuse will be change the file to state ??? when you run ls -la for file in folder. But it oke, On container you can't erase but storage blob you can use
Learn More →
Need to rechange config for running this pods and everything will be okay, 99% i ensure about that
Learn More →
mysqldump -u <user-access-mysql> -p <database-name> > <database-name>.sql
Remember change something about URL if you need to configure HTTP - HTTPS (just optinal if you have LOL)
APACHE2 .htaccess
for about webserver configure and wp-admin
for about Wordpress configure, the default configure is okay but some kind situation you need to understand about that too.azcopy login
azcopy copy <directory-or-file-to-mount> <blob-sas-url> --recursive
You can change the route of path where you want data to mounted in before Blob SAS Token
azcopy copy <database.sql> <blob-mysql-url> --recursive
After your mount process complete:
mysql -u <user-access-mysql> -p < <database.sql>
mysql -u <user-access-mysql> -p
use wordpress;
show tables;
azcopy copy <directory-pluggin> <blob-wp-url-pluggin> --recursive
azcopy copy <directory-upload> <blob-wp-url-uploads> --recursive