一、安装Mysql主从到K8s集群(离线)

参考链接:https://artifacthub.io/packages/helm/bitnami/mysql

1、下载chart包

[root@k8s-master01 ~]# mkdir helm
[root@k8s-master01 ~]# cd helm
[root@k8s-master01 helm]# helm pull oci://docker.kubeasy.com/bitnamicharts/mysql --version 12.0.1

2、解压并修改values.yaml文件

[root@k8s-master01 helm]# tar xf mysql-12.0.1.tgz 
[root@k8s-master01 helm]# cd mysql/
[root@k8s-master01 mysql]# vim values.yaml
# 修改第16行内容
  16   imageRegistry: "docker.kubeasy.com"
# 修改第22行内容
  22   defaultStorageClass: "nfs-csi"
# 修改第114行内容,将数据库模式修改为复制模式
 114 architecture: replication
# 修改第121行内容
 121   rootPassword: "123456"
# 修改第129行内容
 129   database: "zq"
# 修改第121行内容
 121   rootPassword: "zq123456"
# 修改第144行内容
 143   replicationPassword: "zq"
# 修改第1143行内容
1143   enabled: true

修改后的完整配置文件

[root@k8s-master01 mysql]# egrep -v "#|^$" values.yaml 
global:
  imageRegistry: "docker.kubeasy.com"
  imagePullSecrets: []
  defaultStorageClass: "nfs-csi"
  storageClass: ""
  compatibility:
    openshift:
      adaptSecurityContext: auto
kubeVersion: ""
nameOverride: ""
fullnameOverride: ""
namespaceOverride: ""
clusterDomain: cluster.local
commonAnnotations: {}
commonLabels: {}
extraDeploy: []
serviceBindings:
  enabled: false
diagnosticMode:
  enabled: false
  command:
    - sleep
  args:
    - infinity
image:
  registry: docker.io
  repository: bitnami/mysql
  tag: 8.4.3-debian-12-r4
  digest: ""
  pullPolicy: IfNotPresent
  pullSecrets: []
  debug: false
architecture: replication
auth:
  rootPassword: "zq123456"
  createDatabase: true
  database: "zq"
  username: ""
  password: ""
  replicationUser: replicator
  replicationPassword: "zq"
  existingSecret: ""
  usePasswordFiles: false
  customPasswordFiles: {}
  authenticationPolicy: ""
initdbScripts: {}
initdbScriptsConfigMap: ""
startdbScripts: {}
startdbScriptsConfigMap: ""
primary:
  name: primary
  command: []
  args: []
  lifecycleHooks: {}
  automountServiceAccountToken: false
  hostAliases: []
  enableMySQLX: false
  configuration: |-
    [mysqld]
    authentication_policy='{{- .Values.auth.authenticationPolicy | default "* ,," }}'
    skip-name-resolve
    explicit_defaults_for_timestamp
    basedir=/opt/bitnami/mysql
    plugin_dir=/opt/bitnami/mysql/lib/plugin
    port={{ .Values.primary.containerPorts.mysql }}
    mysqlx={{ ternary 1 0 .Values.primary.enableMySQLX }}
    mysqlx_port={{ .Values.primary.containerPorts.mysqlx }}
    socket=/opt/bitnami/mysql/tmp/mysql.sock
    datadir=/bitnami/mysql/data
    tmpdir=/opt/bitnami/mysql/tmp
    max_allowed_packet=16M
    bind-address=*
    pid-file=/opt/bitnami/mysql/tmp/mysqld.pid
    log-error=/opt/bitnami/mysql/logs/mysqld.log
    character-set-server=UTF8
    slow_query_log=0
    long_query_time=10.0
    [client]
    port={{ .Values.primary.containerPorts.mysql }}
    socket=/opt/bitnami/mysql/tmp/mysql.sock
    default-character-set=UTF8
    plugin_dir=/opt/bitnami/mysql/lib/plugin
    [manager]
    port={{ .Values.primary.containerPorts.mysql }}
    socket=/opt/bitnami/mysql/tmp/mysql.sock
    pid-file=/opt/bitnami/mysql/tmp/mysqld.pid
  existingConfigmap: ""
  containerPorts:
    mysql: 3306
    mysqlx: 33060
  updateStrategy:
    type: RollingUpdate
  podAnnotations: {}
  podAffinityPreset: ""
  podAntiAffinityPreset: soft
  nodeAffinityPreset:
    type: ""
    key: ""
    values: []
  affinity: {}
  nodeSelector: {}
  tolerations: []
  priorityClassName: ""
  runtimeClassName: ""
  schedulerName: ""
  terminationGracePeriodSeconds: ""
  topologySpreadConstraints: []
  podManagementPolicy: ""
  podSecurityContext:
    enabled: true
    fsGroupChangePolicy: Always
    sysctls: []
    supplementalGroups: []
    fsGroup: 1001
  containerSecurityContext:
    enabled: true
    seLinuxOptions: {}
    runAsUser: 1001
    runAsGroup: 1001
    runAsNonRoot: true
    allowPrivilegeEscalation: false
    capabilities:
      drop: ["ALL"]
    seccompProfile:
      type: "RuntimeDefault"
    readOnlyRootFilesystem: true
  resourcesPreset: "small"
  resources: {}
  livenessProbe:
    enabled: true
    initialDelaySeconds: 5
    periodSeconds: 10
    timeoutSeconds: 1
    failureThreshold: 3
    successThreshold: 1
  readinessProbe:
    enabled: true
    initialDelaySeconds: 5
    periodSeconds: 10
    timeoutSeconds: 1
    failureThreshold: 3
    successThreshold: 1
  startupProbe:
    enabled: true
    initialDelaySeconds: 15
    periodSeconds: 10
    timeoutSeconds: 1
    failureThreshold: 10
    successThreshold: 1
  customLivenessProbe: {}
  customReadinessProbe: {}
  customStartupProbe: {}
  extraFlags: ""
  extraEnvVars: []
  extraEnvVarsCM: ""
  extraEnvVarsSecret: ""
  extraPodSpec: {}
  extraPorts: []
  persistence:
    enabled: true
    existingClaim: ""
    subPath: ""
    storageClass: ""
    annotations: {}
    accessModes:
      - ReadWriteOnce
    size: 8Gi
    selector: {}
  persistentVolumeClaimRetentionPolicy:
    enabled: false
    whenScaled: Retain
    whenDeleted: Retain
  extraVolumes: []
  extraVolumeMounts: []
  initContainers: []
  sidecars: []
  service:
    type: ClusterIP
    ports:
      mysql: 3306
      mysqlx: 33060
    nodePorts:
      mysql: ""
      mysqlx: ""
    clusterIP: ""
    loadBalancerIP: ""
    externalTrafficPolicy: Cluster
    loadBalancerSourceRanges: []
    extraPorts: []
    annotations: {}
    sessionAffinity: None
    sessionAffinityConfig: {}
    headless:
      annotations: {}
  pdb:
    create: true
    minAvailable: ""
    maxUnavailable: ""
  podLabels: {}
secondary:
  name: secondary
  replicaCount: 1
  automountServiceAccountToken: false
  hostAliases: []
  command: []
  args: []
  lifecycleHooks: {}
  enableMySQLX: false
  configuration: |-
    [mysqld]
    authentication_policy='{{- .Values.auth.authenticationPolicy | default "* ,," }}'
    skip-name-resolve
    explicit_defaults_for_timestamp
    basedir=/opt/bitnami/mysql
    plugin_dir=/opt/bitnami/mysql/lib/plugin
    port={{ .Values.secondary.containerPorts.mysql }}
    mysqlx={{ ternary 1 0 .Values.secondary.enableMySQLX }}
    mysqlx_port={{ .Values.secondary.containerPorts.mysqlx }}
    socket=/opt/bitnami/mysql/tmp/mysql.sock
    datadir=/bitnami/mysql/data
    tmpdir=/opt/bitnami/mysql/tmp
    max_allowed_packet=16M
    bind-address=*
    pid-file=/opt/bitnami/mysql/tmp/mysqld.pid
    log-error=/opt/bitnami/mysql/logs/mysqld.log
    character-set-server=UTF8
    slow_query_log=0
    long_query_time=10.0
    [client]
    port={{ .Values.secondary.containerPorts.mysql }}
    socket=/opt/bitnami/mysql/tmp/mysql.sock
    default-character-set=UTF8
    plugin_dir=/opt/bitnami/mysql/lib/plugin
    [manager]
    port={{ .Values.secondary.containerPorts.mysql }}
    socket=/opt/bitnami/mysql/tmp/mysql.sock
    pid-file=/opt/bitnami/mysql/tmp/mysqld.pid
  existingConfigmap: ""
  containerPorts:
    mysql: 3306
    mysqlx: 33060
  updateStrategy:
    type: RollingUpdate
  podAnnotations: {}
  podAffinityPreset: ""
  podAntiAffinityPreset: soft
  nodeAffinityPreset:
    type: ""
    key: ""
    values: []
  affinity: {}
  nodeSelector: {}
  tolerations: []
  priorityClassName: ""
  runtimeClassName: ""
  schedulerName: ""
  terminationGracePeriodSeconds: ""
  topologySpreadConstraints: []
  podManagementPolicy: ""
  podSecurityContext:
    enabled: true
    fsGroupChangePolicy: Always
    sysctls: []
    supplementalGroups: []
    fsGroup: 1001
  containerSecurityContext:
    enabled: true
    seLinuxOptions: {}
    runAsUser: 1001
    runAsGroup: 1001
    runAsNonRoot: true
    allowPrivilegeEscalation: false
    capabilities:
      drop: ["ALL"]
    seccompProfile:
      type: "RuntimeDefault"
    readOnlyRootFilesystem: true
  resourcesPreset: "small"
  resources: {}
  livenessProbe:
    enabled: true
    initialDelaySeconds: 5
    periodSeconds: 10
    timeoutSeconds: 1
    failureThreshold: 3
    successThreshold: 1
  readinessProbe:
    enabled: true
    initialDelaySeconds: 5
    periodSeconds: 10
    timeoutSeconds: 1
    failureThreshold: 3
    successThreshold: 1
  startupProbe:
    enabled: true
    initialDelaySeconds: 15
    periodSeconds: 10
    timeoutSeconds: 1
    failureThreshold: 15
    successThreshold: 1
  customLivenessProbe: {}
  customReadinessProbe: {}
  customStartupProbe: {}
  extraFlags: ""
  extraEnvVars: []
  extraEnvVarsCM: ""
  extraEnvVarsSecret: ""
  extraPodSpec: {}
  extraPorts: []
  persistence:
    enabled: true
    existingClaim: ""
    subPath: ""
    storageClass: ""
    annotations: {}
    accessModes:
      - ReadWriteOnce
    size: 8Gi
    selector: {}
  persistentVolumeClaimRetentionPolicy:
    enabled: false
    whenScaled: Retain
    whenDeleted: Retain
  extraVolumes: []
  extraVolumeMounts: []
  initContainers: []
  sidecars: []
  service:
    type: ClusterIP
    ports:
      mysql: 3306
      mysqlx: 33060
    nodePorts:
      mysql: ""
      mysqlx: ""
    clusterIP: ""
    loadBalancerIP: ""
    externalTrafficPolicy: Cluster
    loadBalancerSourceRanges: []
    extraPorts: []
    annotations: {}
    sessionAffinity: None
    sessionAffinityConfig: {}
    headless:
      annotations: {}
  pdb:
    create: true
    minAvailable: ""
    maxUnavailable: ""
  podLabels: {}
serviceAccount:
  create: true
  name: ""
  annotations: {}
  automountServiceAccountToken: false
rbac:
  create: false
  rules: []
networkPolicy:
  enabled: true
  allowExternal: true
  allowExternalEgress: true
  extraIngress: []
  extraEgress: []
  ingressNSMatchLabels: {}
  ingressNSPodMatchLabels: {}
passwordUpdateJob:
  enabled: true
  backoffLimit: 10
  command: []
  args: []
  extraCommands: ""
  previousPasswords:
    rootPassword: ""
    password: ""
    replicationPassword: ""
    existingSecret: ""
  containerSecurityContext:
    enabled: true
    seLinuxOptions: {}
    runAsUser: 1001
    runAsGroup: 1001
    runAsNonRoot: true
    privileged: false
    readOnlyRootFilesystem: true
    allowPrivilegeEscalation: false
    capabilities:
      drop: ["ALL"]
    seccompProfile:
      type: "RuntimeDefault"
  podSecurityContext:
    enabled: true
    fsGroupChangePolicy: Always
    sysctls: []
    supplementalGroups: []
    fsGroup: 1001
  extraEnvVars: []
  extraEnvVarsCM: ""
  extraEnvVarsSecret: ""
  extraVolumes: []
  extraVolumeMounts: []
  initContainers: []
  resourcesPreset: "micro"
  resources: {}
  customLivenessProbe: {}
  customReadinessProbe: {}
  customStartupProbe: {}
  automountServiceAccountToken: false
  hostAliases: []
  annotations: {}
  podLabels: {}
  podAnnotations: {}
volumePermissions:
  enabled: false
  image:
    registry: docker.io
    repository: bitnami/os-shell
    tag: 12-debian-12-r33
    digest: ""
    pullPolicy: IfNotPresent
    pullSecrets: []
  resourcesPreset: "nano"
  resources: {}
metrics:
  enabled: false
  image:
    registry: docker.io
    repository: bitnami/mysqld-exporter
    tag: 0.16.0-debian-12-r2
    digest: ""
    pullPolicy: IfNotPresent
    pullSecrets: []
  containerSecurityContext:
    enabled: true
    seLinuxOptions: {}
    runAsUser: 1001
    runAsGroup: 1001
    runAsNonRoot: true
    allowPrivilegeEscalation: false
    capabilities:
      drop: ["ALL"]
    seccompProfile:
      type: "RuntimeDefault"
    readOnlyRootFilesystem: true
  containerPorts:
    http: 9104
  service:
    type: ClusterIP
    port: 9104
    clusterIP: ""
    annotations:
      prometheus.io/scrape: "true"
      prometheus.io/port: "{{ .Values.metrics.service.port }}"
  extraArgs:
    primary: []
    secondary: []
  resourcesPreset: "nano"
  resources: {}
  livenessProbe:
    enabled: true
    initialDelaySeconds: 120
    periodSeconds: 10
    timeoutSeconds: 1
    successThreshold: 1
    failureThreshold: 3
  readinessProbe:
    enabled: true
    initialDelaySeconds: 30
    periodSeconds: 10
    timeoutSeconds: 1
    successThreshold: 1
    failureThreshold: 3
  serviceMonitor:
    enabled: false
    namespace: ""
    jobLabel: ""
    interval: 30s
    scrapeTimeout: ""
    relabelings: []
    metricRelabelings: []
    selector: {}
    honorLabels: false
    labels: {}
    annotations: {}
  prometheusRule:
    enabled: false
    namespace: ""
    additionalLabels: {}
    rules: []

3、安装主从复制模式的mysql

[root@k8s-master01 mysql]# helm install mysql . -n helm-test

验证查看

# 查看pod
[root@k8s-master01 mysql]# kgp -n helm-test
NAME                READY   STATUS    RESTARTS   AGE
mysql-primary-0     1/1     Running   0          114s
mysql-secondary-0   1/1     Running   0          114s

# 查看pvc
[root@k8s-master01 ~]# kg pvc -n helm-test
NAME                     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
data-mysql-primary-0     Bound    pvc-38bf293e-cdee-47ee-99e3-e07a297c2ddb   8Gi        RWO            nfs-csi        <unset>                 3m28s
data-mysql-secondary-0   Bound    pvc-489af11b-93af-41c8-88dd-a8a07f296e03   8Gi        RWO            nfs-csi        <unset>                 3m28s

4、登录主数据库,创建数据库zq123

[root@k8s-master01 mysql]# k exec -it mysql-secondary-0   -n helm-test -- bash
I have no name!@mysql-primary-0:/$ mysql -uroot -pzq123456
mysql> show databases like 'zq';
+---------------+
| Database (zq) |
+---------------+
| zq            |
+---------------+
1 row in set (0.00 sec)
mysql> create database zq123;

5、登录从库,查看数据库是否同步,观察到从库数据同步完成

[root@k8s-master01 mysql]# k exec -it mysql-primary-0   -n helm-test -- bash
I have no name!@mysql-primary-0:/$ mysql -uroot -pzq123456
mysql> show databases like 'zq123';
+------------------+
| Database (zq123) |
+------------------+
| zq123            |
+------------------+
1 row in set (0.00 sec)

# 查看从库同步状态
mysql> SHOW REPLICA STATUS\G
*************************** 1. row ***************************
             Replica_IO_State: Waiting for source to send event
                  Source_Host: mysql-primary
                  Source_User: replicator
                  Source_Port: 3306
                Connect_Retry: 10
              Source_Log_File: mysql-bin.000003
          Read_Source_Log_Pos: 346
               Relay_Log_File: mysql-relay-bin.000006
                Relay_Log_Pos: 563
        Relay_Source_Log_File: mysql-bin.000003
           Replica_IO_Running: Yes
          Replica_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Source_Log_Pos: 346
              Relay_Log_Space: 991
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Source_SSL_Allowed: No
           Source_SSL_CA_File: 
           Source_SSL_CA_Path: 
              Source_SSL_Cert: 
            Source_SSL_Cipher: 
               Source_SSL_Key: 
        Seconds_Behind_Source: 0
Source_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Source_Server_Id: 378
                  Source_UUID: f66c6bb6-0a3f-11f0-ba80-b67032ef6627
             Source_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
    Replica_SQL_Running_State: Replica has read all relay log; waiting for more updates
           Source_Retry_Count: 10
                  Source_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Source_SSL_Crl: 
           Source_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Source_TLS_Version: 
       Source_public_key_path: 
        Get_Source_public_key: 1
            Network_Namespace: 
1 row in set (0.00 sec)

6、环境复原

[root@k8s-master01 mysql]# helm delete mysql -n helm-test
[root@k8s-master01 mysql]# k delete pvc data-mysql-primary-0  data-mysql-secondary-0  -n helm-test