上一篇"通过实例快速掌握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。
网络:
这里的网络有两层含义,一层是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”,如下图所示。
但这会造成在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 发布!