mysql上k8s_通过搭建MySQL掌握k8s(Kubernetes)重要概念(上):网络与持久卷

上一篇"通过实例快速掌握k8s(Kubernetes)核心概念"讲解了k8s的核心概念,有了核心概念整个骨架就完整了,应付无状态程序已经够了,但还不够丰满。应用程序分成两种,无状态和有状态的。一般的前段和后端程序都是无状态的,而数据库是有状态的,他需要把数据存储起来,这样即使断电,数据也不会丢失。要创建有状态的程序,还需要引入另外一些k8s概念。它们虽然不是核心,但也很重要,共有三个,持久卷,网络和参数配置。掌握了这些之后,基本概念就已经做到了全覆盖,k8s就已经入门了。我们通过搭建MySQL来熟悉这些k8s概念。容器本身是无状态的,一旦出现问题它会被随时销毁,它存储的数据也就丢失了。MySQL需要一个能保存数据的持久层,在容器被销毁之后仍然存在,k8s叫它持久卷。

创建和验证MySQL镜像:

在k8s上安装MySQL之前,先用Docker验证一下MySQL镜像:

docker run --name test-mysql -p 3306:33060 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7

“root”是根(root)用户的password,这里是在创建MySQL容器时指定“root”用户的password。“test-MySQL”是容器的名字。“mysql:5.7”用的是docker库里的“MySQL”5.7版本。这次没有用最新的8.0版,因为新版跟以前的客户端不兼容,需要修改很多东西。所用的镜像是全版的Linux,因而文件比较大,有400M。

容器建好了之后,键入“docker logs test-mysql”,查看日志。

...

2019-10-03T06:18:50.439784Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.17' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.

2019-10-03T06:18:50.446543Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: '/var/run/mysqld/mysqlx.sock' bind-address: '::' port: 33060

查看容器状态。

vagrant@ubuntu-xenial:~$ docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

3b9c50420f5b mysql:latest "docker-entrypoint.s…" 11 minutes ago Up 11 minutes 3306/tcp, 33060/tcp test-mysql

为了验证MySQL,需要在虚机上安装MySQL客户端。

sudo apt-get -y -f install mysql-client

完成之后,键入“docker inspect test-mysql”找到容器IP地址, 下面显示"172.17.0.2"是容器IP地址。

vagrant@ubuntu-xenial:~$ docker inspect test-mysql

...

"Gateway": "172.17.0.1",

"IPAddress": "172.17.0.2",

"IPPrefixLen": 16,

"IPv6Gateway": "",

...

键入“mysql -h 172.17.0.2 -P 3306 --protocol=tcp -u root -p”登录到MySQL,"172.17.0.2"是MySQL的IP地址,“3306”是MySQL端口,是在创建镜像时设定的对外开放的端口,“root”是用户名,“-p”是password的参数选项。敲入命令后,系统要求输入password,输入后,显示已成功连接到MySQL。

vagrant@ubuntu-xenial:~$ mysql -h 172.17.0.2 -P 3306 --protocol=tcp -u root -p

...

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 3

Server version: 5.7.27 MySQL Community Server (GPL)

...

在k8s上安装MySQL

在k8s上安装MySQL分成三个部分,创建部署文件,创建服务文件和安装测试。

部署(Deployment)文件

下面是部署配置文件。在上一篇文章中已经详细讲解了文件格式,所有的k8s的配置文件格式都是相同的。“template”之上是部署配置,从“template”向下是Pod配置。从“containers”开始是Pod里面的容器配置。“env:”是环境变量,这里通过环境变量来设置数据库的用户名和口令,后面还会详细讲解。MySQL的端口是“3306”

apiVersion: apps/v1

kind: Deployment # 类型是部署

metadata:

name: mysql-deployment # 对象的名字

spec:

selector:

matchLabels:

app: mysql #用来绑定label是“mysql”的Pod

strategy:

type: Recreate

template: # 开始定义Pod

metadata:

labels:

app: mysql #Pod的Label,用来标识Pod

spec:

containers: # 开始定义Pod里面的容器

- image: mysql:5.7

name: mysql-con

imagePullPolicy: Never

env: # 定义环境变量

- name: MYSQL_ROOT_PASSWORD # 环境变量名

value: root # 环境变量值

- name: MYSQL_USER

value: dbuser

- name: MYSQL_PASSWORD

value: dbuser

args: ["--default-authentication-plugin=mysql_native_password"]

ports:

- containerPort: 3306 # mysql端口

name: mysql

服务(Service)文件

下面是服务配置文件,这个与上一篇讲的配置基本相同,这里就不解释了。

apiVersion: v1

kind: Service

metadata:

name: mysql-service

labels:

app: mysql

spec:

type: NodePort

selector:

app: mysql

ports:

- protocol : TCP

nodePort: 30306

port: 3306

targetPort: 3306

安装测试:

有了配置文件后,下面就开始创建MySQL。在创建时要按照顺序,依次进行,先从最底层的对象开始创建。

创建部署和服务:

kubectl apply -f mysql-deployment

kubectl apply -f mysql-service.yaml

查看服务:

vagrant@ubuntu-xenial:~$ kubectl get service

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

kubernetes ClusterIP 10.96.0.1 443/TCP 3h42m

mysql-service NodePort 10.102.253.32 3306:30306/TCP 3h21m

“mysql-service”的端口(PORT(S))有两个,“3306”是k8s内部端口,“30306”是外部端口。由于“NodePort”已经打开了对外端口,这时就可以在虚拟机上通过“30306”端口访问MySQL。

vagrant@ubuntu-xenial:~$ mysql -h localhost -P 30306 --protocol=tcp -u root -p

Enter password:

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 6

Server version: 5.7.27 MySQL Community Server (GPL)

...

mysql>

这时本地虚机已经与k8s联通了,下一步就可以在宿主机( 笔记本)上用图形客户端来访问MySQL了。我是在Vagrant里设定了私有网络,设定的虚机IP地址是 "192.168.50.4”,就用这个地址和30306端口来访问MySQL。

56bb5fc31e09b2762e4b3975bd60661b.png

网络:

这里的网络有两层含义,一层是k8s网络,就是让k8s内部服务之间可以互相访问,并且从k8s集群外部可以访问它内部的服务。另一层是宿主机(笔记本)和虚机之间的网路,就是在宿主机上可以访问虚机。这两层都通了之后,就可以在宿主机直接访问k8s集群里面的MySQL。

k8s网络:

k8s的网络也有两层含义,一个是集群内部的,k8s有内部DNS,可以通过服务名进行寻址。另一个是从集群外部访问集群内部服务,一共有四种方式,详情请见“Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?”

LoadBalancer:Load Balancer不是由K8s来管理的。k8s通过Load Balancer把外部请求转发给内部服务。这种方法要求有Load Balancer,一般云环境里会提供,但自己的本地环境就没有了。不过Minikube提供了一个程序可以模拟Load Balancer。你只要键入“minikube tunnel ”,它就会模拟Load Balancer,对请求进行转发。只不过当你在使用“Load Balancer”时(在Minikube环境里),每次运行服务时产生的IP和端口是随机的,不能控制,使用起来不太方便,但在正式环境里就没有这个问题。

下面是服务信息,“EXTERNAL-IP”是"pending",说明外部网络不通。

$ kubectl get service

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

kubernetes ClusterIP 10.96.0.1 443/TCP 31d

nginx-service LoadBalancer 10.104.228.212 80:31999/TCP 45h

下面是在运行“minikube tunnel ”(在另一个窗口运行)之后的服务信息,“EXTERNAL-IP”是 “10.104.228.212”。这时Minikube的LoadBalancer已经起作用了,现在就可以通过IP地址从外部访问k8s内部的服务了,“80”是k8s内部端口,“31999”是k8s对外端口。

$ kubectl get service

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

kubernetes ClusterIP 10.96.0.1 443/TCP 31d

nginx-service LoadBalancer 10.104.228.212 10.104.228.212 80:31999/TCP 45h

这是一种比较好的方式,但不能控制它的IP地址和端口,因此我暂时没有采用它。

NodePort:这种方法可以在每个Node上开放一个对外端口,每一个指向这个端口的请求都被转发给一个服务。它的好处是你可以指定一个固定的端口(端口的取值范围只能是30000–32767),这样我在笔记本上访问MySQL时就不用更换端口了。 如果你不指定,系统会随机分配一个。它的缺点是每个端口只能有一个服务,而且端口取值受限制,因此不适合生产环境。但在Windows环境,由于我用Vagrant固定了虚机的IP地址,这个问题就不存在了。因此它是最好的选择。

ClusterIP: 这个只能在k8s集群内部寻址。

Ingress: 这是推荐的方法,一般在生产环境中使用。Load balancer的问题是每一个服务都要有一个Load balancer,服务多了之后会很麻烦,这时就会用Ingress,它的缺点是配置起来比较复杂。Minikube自带了一个基于Nginx的Ingress控制器,只需运行“minikube addons enable ingress”,就行了。但Ingress的设置较复杂,因此这里没有用它。

虚拟机网络:

这里讲的是宿主机(笔记本)和虚机之间的互相访问,主要是从宿主机访问虚机。我用的是Vagrant, 因此要在Vagran的配置文件(Vagrantfile)里进行配置。它有两种方法:

端口转发:它可以把笔记本上特定端口的请求转发到虚机的指定端口,还是比较方便的。只是如果事先不知道是哪个端口,或端口是变化的,就比较麻烦。Vagrant的配置命令:“config.vm.network "forwarded_port", guest: 3306, host: 3306, auto_correct: true”

私有网络:这是一种很灵活的方式。可以给宿主机和虚机各自设定一个固定的IP地址,这样可以双向互访。任何端口都没有问题,唯一的缺点就是你要事先确定IP地址。详情请参见“Vagrant reverse port forwarding?”。Vagrant的配置命令:“config.vm.network "private_network", ip: "192.168.50.4”

当配置私有网络时,需要在笔记本的VirtualBox上配置“Host-only Adapter”,如下图所示。

a4b46c911a796fb00324be68fd20b8d0.png

但这会造成在Vagrant启动Minikube时产生如下错误:“VBoxManage.exe: error: Failed to create the host-only adapter”。这是VirtualBox的一个Bug,你可以下载一个软件解决,详见这里. 这个软件已经是四年之前的了,开始还担心是否与现在的VirtualBox版本兼容,结果很好用,而且它是一个单独运行的软件,不会与现在的软件冲突。只要在启动虚机之前,用管理员身份运行这个补丁就行了。另外一个问题是,我原来使用的是5.x版的VirtualBox,上图中只能选“NAT”,不能选“Host-only Adapter”,升级到6.X之后才能选“Host-only Adapter”。但当虚机重新启动之后,它会自动变回“NAT”,不过私有网络还是可用。

创建持久卷(PersistentVolume):

k8s卷的概念包括卷和持久卷。

卷(volume):

卷是k8s的存储概念,它依附于Pod,不能单独存在。但它不是在容器层。因此如果容器被重新启动,卷仍然在。但如果Pod重新启动,卷就丢失了。如果一个Pod里有多个容器,那么这些容器共享Pod的卷。你可以把卷看成是一个目录,里面可以存储各种文件。k8s支持各种类型的卷,例如本地文件系统和各种云存储。

持久卷(PersistentVolume):

是对卷的一个封装,目的是为了更好地管理卷。它的生命周期不需要与Pod绑定,它可以独立于Pod存在。

持久卷申请(PersistentVolumeClaim):

是对持久卷资源的一个申请,你可以申请特定的存储容量的大小和访问模式,例如读写模式或只读模式。k8s会根据持久卷申请分配适合的持久卷,如果没有合适的,系统会自动创建一个。持久卷申请是对持久卷的一个抽象,就像编程里的接口(Interface),它可以有不同的具体实现(持久卷)。例如,阿里云和华为云支持的存储系统不同,它生成的持久卷也不相同。持久卷是与特定的存储实现绑定的。那你要把程序从阿里云移植到华为云,怎么保证配置文件的兼容性呢?你就用持久卷申请来做这个接口,它只规定存储容量大小和访问模式,而由阿里云和华为云自动生成各自云里满足这个接口需求的持久卷. 不过,它还有一个限制条件,那就是持久卷申请和持久卷的StorageClass需要匹配,这使它没有接口灵活。后面会详细讲解。

动态持久卷:

在这种情况下,你只需创建持久卷申请(不需要单独创建持久卷),然后把持久卷申请与部署绑定。系统会按照持久卷申请自动创建持久卷。下面是持久卷申请配置文件。其中“storage:1Gi”,是指申请的空间大小是1G。

持久卷申请配置文件:

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

name: mysql-pv-claim

labels:

app: mysql

spec:

accessModes:

- ReadWriteOnce

resources:

requests:

storage: 1Gi #持久卷的容量是 1 GB

```

**挂载持久卷申请的部署:**

下面是挂载了持久卷申请的部署配置文件。它通过把持久卷申请当做持久卷来使用,与Pod进行绑定。请阅读文件里有关持久卷的注释。

```shell

apiVersion: apps/v1

kind: Deployment

metadata:

name: mysql-deployment

spec:

selector:

matchLabels:

app: mysql

strategy:

type: Recreate

template:

metadata:

labels:

app: mysql

spec:

containers:

- image: mysql:5.7

name: mysql-con

imagePullPolicy: Never

env:

- name: MYSQL_ROOT_PASSWORD

value: root

- name: MYSQL_USER

value: dbuser

- name: MYSQL_PASSWORD

value: dbuser

args: ["--default-authentication-plugin=mysql_native_password"]

ports:

- containerPort: 3306

name: mysql

volumeMounts: # 挂载Pod上的卷到容器

- name: mysql-persistent-storage # Pod上卷的名字,与“volumes”名字匹配

mountPath: /var/lib/mysql # 挂载的Pod的目录

volumes: # 挂载持久卷到Pod

- name: mysql-persistent-storage # 持久卷名字, 与“volumMounts”名字匹配

persistentVolumeClaim:

claimName: mysql-pv-claim # 持久卷申请名字

这里只指定了Pod的挂载目录,并没有指定虚拟机(宿主机)的目录,后面会讲到如何找到虚拟机的目录(系统自动分配挂载目录)。

运行部署:

键入“kubectl apply -f mysql-volume.yaml”创建持久卷申请,在创建它的同时,系统自动创建持久卷。

查看持久卷申请

vagrant@ubuntu-xenial:~/dockerimages/kubernetes/mysql$ kubectl get pvc

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE

mysql-pv-claim Bound pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa 1Gi RWO standard 10m

查看持久卷申请详细信息

vagrant@ubuntu-xenial:/mnt$ kubectl describe pvc mysql-pv-claim

Name: mysql-pv-claim

Namespace: default

StorageClass: standard

Status: Bound

Volume: pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa

Labels: app=mysql

...

显示持久卷:

vagrant@ubuntu-xenial:/mnt$ kubectl get pv

NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE

pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa 1Gi RWO Delete Bound default/mysql-pv-claim standard 24h

键入“kubectl describe pv pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa”, 显示持久卷详细信息。从这里可以看出,虚拟机上的持久卷在如下位置:“Path: /tmp/hostpath-provisioner/pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa”。

vagrant@ubuntu-xenial:/mnt$ kubectl describe pv pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa

Name: pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa

Labels:

Annotations: hostPathProvisionerIdentity: 19948fdf-e67f-11e9-8fbd-026a5b40726f

pv.kubernetes.io/provisioned-by: k8s.io/minikube-hostpath

Finalizers: [kubernetes.io/pv-protection]

StorageClass: standard

Status: Bound

Claim: default/mysql-pv-claim

Reclaim Policy: Delete

Access Modes: RWO

VolumeMode: Filesystem

Capacity: 1Gi

Node Affinity:

Message:

Source:

Type: HostPath (bare host directory volume)

Path: /tmp/hostpath-provisioner/pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa

HostPathType:

Events:

查看MySQL目录信息:

vagrant@ubuntu-xenial:/tmp/hostpath-provisioner/pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa$ ls -al

total 188488

drwxrwxrwx 6 999 docker 4096 Oct 4 13:23 .

drwxr-xr-x 3 root root 4096 Oct 4 12:58 ..

-rw-r----- 1 999 docker 56 Oct 4 12:58 auto.cnf

-rw------- 1 999 docker 1679 Oct 4 12:59 ca-key.pem

-rw-r--r-- 1 999 docker 1107 Oct 4 12:59 ca.pem

-rw-r--r-- 1 999 docker 1107 Oct 4 12:59 client-cert.pem

-rw------- 1 999 docker 1679 Oct 4 12:59 client-key.pem

-rw-r----- 1 999 docker 668 Oct 4 13:21 ib_buffer_pool

-rw-r----- 1 999 docker 79691776 Oct 4 13:23 ibdata1

-rw-r----- 1 999 docker 50331648 Oct 4 13:23 ib_logfile0

-rw-r----- 1 999 docker 50331648 Oct 4 12:58 ib_logfile1

-rw-r----- 1 999 docker 12582912 Oct 4 13:24 ibtmp1

drwxr-x--- 2 999 docker 4096 Oct 4 12:58 mysql

drwxr-x--- 2 999 docker 4096 Oct 4 12:58 performance_schema

-rw------- 1 999 docker 1679 Oct 4 12:59 private_key.pem

-rw-r--r-- 1 999 docker 451 Oct 4 12:59 public_key.pem

-rw-r--r-- 1 999 docker 1107 Oct 4 12:59 server-cert.pem

-rw------- 1 999 docker 1675 Oct 4 12:59 server-key.pem

drwxr-x--- 2 999 docker 4096 Oct 4 13:18 service_config

drwxr-x--- 2 999 docker 12288 Oct 4 12:58 sys

持久卷的回收模式:

当持久卷和持久卷申请被删除后,它有三种回收模式。

保持(Retain):当持久卷申请被删除后,持久卷仍在。你可以手动回收持久卷里的数据。

** 删除(Delete)**:持久卷申请和持久卷都被删除,底层存储的数据也会被删除。当使用动态持久卷时,缺省的模式是Delete。当然,你可以在持久卷被创建之后修改它的回收模式。

** 回收(Recycle)**:这种方式已经不推荐使用了,建议用Retain代替。

静态持久卷:

动态持久卷的一个问题是它的缺省回收模式是“删除”,这样当虚机重新启动后,持久卷会被删除。当你重新运行部署时,k8s会创建一个新的MySQL,这样原来MySQL里的新建信息就会丢失,这是我们不愿意看到的。虽然你可以手动修改回收方式为“保持”,但还是要手动回收原来持久卷里的数据。

一个解决办法是把持久卷建在宿主机上,这样即使虚机出了问题被重新启动,MySQL里的新建信息依然不会丢失。如果是在云上,就会有专门的的存储层,如果是本地,大致有三种方式:

Local:把存储从宿主机挂载到k8s集群上. 详情请参见:"Volumes".

HostPath:也是把存储从宿主机挂载到k8s集群上,但它有许多限制,例如只支持单节点(Node),而且只支持“ReadWriteOnce”模式。详情请参见: "hostPath as volume in kubernetes".

NFS:网络文件系统,这种是最灵活的,但需要安装NFS服务器。详情请参见:"Kubernetes Volumes Guide".

我选择了比较简单的“Local”方式。在这种方式下,必须单独创建持久卷,不能 只创建持久卷申请而让系统自动创建持久卷。

下面是使用“Local”方式的配置文件,它把持久卷和持久卷申请写在了一个文件里。当用“Local”方式时,需要设置“nodeAffinity”部分,其中“values:- minikube” 的“Minikube”是k8s集群Node的名字,“Minikube”只支持一个Node,既是“Master Node”,又是“Worker Node”。

持久卷和申请的配置文件:

apiVersion: v1

kind: PersistentVolume

metadata:

name: mysql-pv

spec:

capacity:

storage: 1Gi

volumeMode: Filesystem

accessModes:

- ReadWriteOnce

storageClassName: standard #持久卷存储类型,它需要与持久卷申请的类型相匹配

local:

path: /home/vagrant/database/mysql #宿主机的目录

nodeAffinity:

required:

nodeSelectorTerms:

- matchExpressions:

- key: kubernetes.io/hostname

operator: In

values:

- minikube # Node的名字

---

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

name: mysql-pv-claim

labels:

app: mysql

spec:

accessModes:

- ReadWriteOnce

# storageClassName: # 这里的存储类型注释掉了

resources:

requests:

storage: 1Gi #1 GB

如果不知道Node名字,可用如下命令查看:

vagrant@ubuntu-xenial:/$ kubectl get node

NAME STATUS ROLES AGE VERSION

minikube Ready master 6d3h v1.15.2

改用静态持久卷之后,只有持久卷配置文件发生了变化,部署和服务的配置文件没有变。重新运行持久卷和部署,成功之后,即使重启虚拟机,MySQL里面的新建内容也没有丢失。

注意这里storageClassName的用法。k8s规定持久卷和持久卷申请的storageClassName必须匹配,这时才会把持久卷分配给持久卷申请。我们这里的持久卷申请没有指定storageClassName,这时系统会使用缺省的storageClass。

查看是否安装了缺省的storageClass

vagrant@ubuntu-xenial:/$ kubectl get sc

NAME PROVISIONER AGE

standard (default) k8s.io/minikube-hostpath 6d3h

vagrant@ubuntu-xenial:/$

查看缺省的storageClass详细信息

vagrant@ubuntu-xenial:/$ kubectl describe sc

Name: standard

IsDefaultClass: Yes

Annotations: storageclass.kubernetes.io/is-default-class=true

Provisioner: k8s.io/minikube-hostpath

Parameters:

AllowVolumeExpansion:

MountOptions:

ReclaimPolicy: Delete

VolumeBindingMode: Immediate

Events:

从这里可以看出,Minikube安装了缺省的storageClass,它的名字是“standard”。上面的持久卷申请里没有指定storageClass,因此系统使用缺省的storageClass与之匹配,而上面的持久卷的storageClassName是“standard”,正好能配上。详情请见“Dynamic Provisioning and Storage Classes in Kubernetes”

踩过的坑:

使用Hyper-V还是VirtualBox

Hyper-V和VirtualBox是不兼容的,只能选一个(当然你可以在这两者之间切换,但太麻烦了)。我在Windows上装了VirtualBox,运行正常。进入Vagrant之后,安装了“ubuntu”版的Linux。这时,当你启动Minikube时,可以键入“minikube start --vm-driver=virtualbox”,但系统显示“This computer doesn't have VT-X/AMD-v enabled. Enabling it in the BIOS is mandatory”。我按照网上的建议去修改BIOS的“VT-X/AMD-v”,但我的BIOS就没有这个选项。其他的方法也都试过了,没有一个成功的。但因为已经装了VirtualBox,就不能用Hyper-V了。就只能用另外一个方法,使用命令“minikube start --vm-driver=none”。幸好这个方法工作得很好。

当用“minikube start --vm-driver=virtualbox”时,你是先建了虚拟机,再在虚拟机上运行Minikube。当用“minikube start --vm-driver=none”时,是直接在宿主机上运行Minikube。但由于我的Windows版本不能直接支持k8s,我已经在Windows上装了Linux虚机,并用Vagrant进行管理。如果用“minikube start --vm-driver=virtualbox”,就是在Linux虚机上又装了一个虚机。现在用“minikube start --vm-driver=none”,表面上看是在宿主机上运行,实际上已经运行在Windows的Linux虚机上了。

登录k8s集群

当用“minikube start --vm-driver=none”启动Minikube时,不能用“minikube ssh”登录k8s集群,因为这时已经没有虚机了,是直接安装在宿主机上,因此不需要“minikube ssh”。但你可以登录到Pod上,可用如下命令:" kubectl exec -ti mysql-deployment-56c9cf5857-fffth -- /bin/bash"。其中“mysql-deployment-56c9cf5857-fffth”是Pod名字。

创建重名PV或PVC

当原来的PV或PVC还在,而你又创建了一个新的PV, 并与原来的重名,则会得到如下错误:The persistentvolumeclaim "mysql-pv-claim" is invalid: spec: forbidden: is immutable after creation except resources.requests for bound claims. 这时,你需要将原来的PV或PVC删掉,再重新创建新的。

索引:

本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/427815.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python简单笔记

Remarks:python中注意缩进(Tab键或者4个空格) print(输出) 格式:print(values) 字符串、数字、变量等都可以输出: 实例: print(1)->1 print(11)->2 a …

mysql字符集latin1_mysql的latin1字符集支持所有字符集

1. 先来看看latin1 (参考百度百科)Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符&#…

latex参考文献bib基本格式_在Latex中利用.bib进行参考文献管理

使用bibtex与jabref简化论文写作中的文献管理和引用bibtex是latex(中文Ctex可在www.ctex.org找到)的一个组件,用于文献引用。.bib是文献引用信息文件。1. IEEEtran包(Package)的下载打开WinEdt。选择Accessories->MiKTex->MiKTex Package Manager,…

BZOJ2302 [HAOI2011]Problem c 【dp】

题目 给n个人安排座位,先给每个人一个1~n的编号,设第i个人的编号为ai(不同人的编号可以相同),接着从第一个人开始,大家依次入座,第i个人来了以后尝试坐到ai,如果ai被占据了&#xff…

mysql 3_mysql3

回顾字段类型(列类型): 数值型, 时间日期型和字符串类型数值型: 整型和小数型(浮点型和定点型)时间日期型: datetime, date,time,timestamp, year字符串类型: 定长, 变长, 文件字符串(text和blob), 枚举和集合Mysql记录长度: 65535个字节, varchar达不到理论长度, NULL占用一个…

H5+App开发框架汇总

MUI:http://dcloudio.github.io/mui/(使用H5app模式,号称是最接近原生,但是目前在手机和电脑浏览器无法使用) app-framework:http://app-framework-software.intel.com/ (有Android、iOS等主题样…

C#-interface

接口成员不能有访问修饰符,默认为public。接口成员只能给出签名,不能有具体实现。继承接口的类必须全部实现接口成员。接口是多继承的。实现继承的过程中,基类必须放在所有接口的最前面。接口不能实例化对象。接口是引用类型。转载于:https:/…

【Alpha阶段】第一次Scrum Meeting

PS:因为安装android的SDK插件出现问题,在eclipse和android studio中安装都不成功,项目不能运行,且一直在下载一些插件,安装了3天都没有成功,按照网上的解决办法进行解决都没有成功,导致项目不能…

mysql galera 下载_Mysql-Galera Cluster

使用Galera Cluster需要下载包含wsrep补丁的mysql版本;官网下载地址:http://galeracluster.com/downloads/安装前要卸载之前安装的mariadb或者mysql;或者迁移也可以,不过就是另一套操作了!具体的安装过程官网描述的很完…

ext4fs error mysql_请教一个 Linux 挂在磁盘阵列报错 EXT4-fs error 问题

从昨天开始 linux 通过光纤直接连接磁盘阵列,会出现磁盘阵列掉了的情况,然后机器会重启,本来重启后,rose ha 会自动挂载磁盘阵列,现在由于 rose ha 也出了点问题,导致不切换备用服务器,主服务器…

hashtable和hashmap的区别?

相同点: 1.都实现了map接口 2.都是键值对的方式存储 3.都是通过单链表解决冲突的 4. 都实现了Serializable接口和Cloneable接口,因此它支持序列化和被克隆。 不同点: 1.hashtable不支持键-值为null,而hashmap支持。 2.hashmap是线程不安全&am…

mysql数据库的各种锁_关于MySQL各类锁的总结

想要用好 MySQL,索引与锁是一个绕不开的话题。最近一直在维护以前的业务系统,线上频繁报出数据库死锁的异常警告,为了排查以及规避死锁的问题,因此对 MySQL 的锁(Innodb引擎)做了一个比较深入学习,顺便加深自己对 MySQ…

581. Shortest Unsorted Continuous Subarray连续数组中的递增异常情况

[抄题]: Given an integer array, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order, too. You need to find the shortest suc…

python enumerate函数返回值_python中enumerate函数用法实例分析

本文实例讲述了python中enumerate函数用法。分享给大家供大家参考。具体分析如下:今日发现一个新函数 enumerate 。一般情况下对一个列表或数组既要遍历索引又要遍历元素时,会这样写: for i in range (0,len(list)):print i ,list[i]但是这种…

Java异常处理原则与技巧总结

一 处理原则 Java异常代码中我们使用异常的目的是让异常的异常类型来提示“什么”被抛出了--- 即出了什么问题;用异常的栈打印信息来跟踪异常在“哪里”抛出 --- 即哪里出了问题; 异常提示信息来提示“为什么”会抛出 --- 即出问题的原因。在对异常进行…

python三阶魔方_三阶魔方自动求解及动态可视化matlab代码

三阶魔方自动求解及动态可视化matlab代码思路与步骤三阶魔方有6个面,每个面有333\times333小块,用一个6336\times3\times3633的矩阵来保存魔方的状态;定义412种魔方旋转行为:整体旋转(左右上下共4种方式AaCc),侧面(6个…

Qt 常用类——QStandardItemModel

转载:落叶知秋时 类QabstractItemModel,QabstractListModel,QAbstractTableModel不保存数据,用户需要从这些类派生出子类,并在子类中定义某种数据结构来保存数据。 与此不同,类QStandardItemModel负责保存数…

thinkphp mysql 中文_耗时5天解决thinkphp连接mysql中文乱码的问题

坑大,或者不大,它就在那里,等着你进。先前修改成熟的一个基于thinkphp3.1.2的后台框架,里面有我的autoCode,本来在新项目上不想再用这么落后的版本,但考虑到后台项目不对外使用,重点是autoCode是…

bzoj3203: [Sdoi2013]保护出题人

我三分这么好吗居然1A啦???提交的时候只是想着先WA一次的。。。。 这题真的很妙啊 首先第一步,就是把僵尸的生命值取一个前缀和,这样造成伤害的时候,可以视为同时对所有僵尸造成伤害。 那么就可以得到一个柿…

ad19原理图标注_AD19中原理图的模板如何进行编辑?

我们在进行原理图设计的时候,有时候不想去用软件自带默认的模板,想要用自己设计的模板,就涉及到我们的模板怎么去编辑的呢?我们应该如何去编辑原理图自己设计的模板?操作步骤是怎么的呢?我们今天就以AD19为…