上一篇"通过实例快速掌握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 <none> 443/TCP 3h42m
mysql-service NodePort 10.102.253.32 <none> 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 <none> 443/TCP 31d
nginx-service LoadBalancer 10.104.228.212 <pending> 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 <none> 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: <none>
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: <none>
Message:
Source:
Type: HostPath (bare host directory volume)
Path: /tmp/hostpath-provisioner/pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa
HostPathType:
Events: <none>

查看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: <none>
AllowVolumeExpansion: <unset>
MountOptions: <none>
ReclaimPolicy: Delete
VolumeBindingMode: Immediate
Events: <none>

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

踩过的坑:

  1. 使用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虚机上了。

  2. 登录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名字。

  3. 创建重名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删掉,再重新创建新的。

请继续阅读下篇“通过搭建MySQL掌握k8s(Kubernetes)重要概念(下):参数配置

索引:

  1. 通过实例快速掌握k8s(Kubernetes)核心概念
  2. Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?
  3. Vagrant reverse port forwarding?
  4. hostPath as volume in kubernetes
  5. Volumes
  6. Kubernetes Volumes Guide
  7. Dynamic Provisioning and Storage Classes in Kubernetes

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

通过搭建MySQL掌握k8s(Kubernetes)重要概念(上):网络与持久卷的更多相关文章

  1. 通过搭建MySQL掌握k8s(Kubernetes)重要概念(下):参数配置

    本文通过搭建MySQL环境来了解k8s的重要概念,包括持久卷,网络和参数配置.这是下篇,专门讲解参数配置.如果你有些地方不能完全看明白,请先看上篇"通过搭建MySQL掌握k8s(Kubern ...

  2. K8s - Kubernetes重要概念介绍(Cluster、Master、Node、Pod、Controller、Service、Namespace)

    K8s - Kubernetes重要概念介绍(Cluster.Master.Node.Pod.Controller.Service.Namespace)       Kubernetes 是目前发展最 ...

  3. Kubeadm搭建高可用(k8s)Kubernetes v1.24.0集群

    文章转载自:https://i4t.com/5451.html 背景 Kubernetes 1.24新特性 从kubelet中移除dockershim,自1.20版本被弃用之后,dockershim组 ...

  4. 如何在Kubernetes集群动态使用 NAS 持久卷

    1. 介绍: 本文介绍的动态生成NAS存储卷的方案:在一个已有文件系统上,自动生成一个目录,这个目录定义为目标存储卷: 镜像地址:registry.cn-hangzhou.aliyuncs.com/a ...

  5. 从零开始入门 K8s | Kubernetes 网络概念及策略控制

    作者 | 阿里巴巴高级技术专家  叶磊 一.Kubernetes 基本网络模型 本文来介绍一下 Kubernetes 对网络模型的一些想法.大家知道 Kubernetes 对于网络具体实现方案,没有什 ...

  6. Kubernetes(K8s)基础概念 —— 凿壁偷光

    Kubernetes(K8s)基础概念  --  凿壁偷光 K8s是什么:全称 kubernetes  (k12345678s) 作用:用于自动部署,扩展和管理"容器化应用程序"的 ...

  7. kubernetes核心概念

    摘抄自:  https://www.cnblogs.com/zhenyuyaodidiao/p/6500720.html 1.基础架构 1.1 Master Master节点上面主要由四个模块组成:A ...

  8. Kubernetes核心概念总结

    目录贴:Kubernetes学习系列 1.基础架构 1.1 Master Master节点上面主要由四个模块组成:APIServer.scheduler.controller manager.etcd ...

  9. 01 . 容器编排简介及Kubernetes核心概念

    Kubernetes简介 Kubernetes是谷歌严格保密十几年的秘密武器-Borg的一个开源版本,是Docker分布式系统解决方案.2014年由Google公司启动. Kubernetes提供了面 ...

随机推荐

  1. CF989C A Mist of Florescence 构造 思维好题 第八题

    A Mist of Florescence time limit per test 1 second memory limit per test 256 megabytes input standar ...

  2. bzoj5072 小A的树 题解

    题意 给出一棵 n 个点的树,每个点有黑白两种颜色.q 次询问,每次 询问给出 x 和 y,问能否选出一个 x 个点的联通子图,使得其中 黑点数目为 y. 范围 n ≤ 5000,q ≤ 10^5 其 ...

  3. javascript删除数组元素的7个方法

    在JavaScript中,除了Object之外,Array类型(数组)恐怕就是最常用的类型了.与其他语言的数组相比,JavaScript中的Array非常灵活.这种灵活性有利有弊,好处是其富有创造性, ...

  4. IDEA 中用好 Lombok,撸码效率至少提升5倍!

    来 源:http://t.cn/EXhxRzV 以前的Java项目中,充斥着太多不友好的代码:POJO的getter/setter/toString:异常处理:I/O流的关闭操作等等,这些样板代码既没 ...

  5. IDEA中的各种快捷键

    1.get.set快捷键: Alt+Insert 2.idea补全返回值快捷键 比如写了一个new User(),需要补全前面的User user ctrl+alt+V 3.idea全局搜索: Ctr ...

  6. sql 增删改列名

    添加列:alter table table_name add new_column data_type [interality_codition] ALTER TABLE dbo.tb newColu ...

  7. MySQL的安装与配置——详细教程

    免安装版的Mysql MySQL关是一种关系数据库管理系统,所使用的 SQL 语言是用于访问数据库的最常用的 标准化语言,其特点为体积小.速度快.总体拥有成本低,尤其是开放源码这一特点,在 Web 应 ...

  8. LaTeX 自动避免重复内容

    在编辑自动化文档时,很容易出现在文档多处提及相同内容的情况.例如,描述某具体设备的图片,在多个工艺中都会用到,而又无法确定工艺出现顺序,或者对于不同企业,工艺不尽相同.这时我们可能会希望,latex帮 ...

  9. jinfo Java配置信息工具

    jinfo(Configuration info for Java) jinfo的作用是实时地查看和调整虚拟机各项参数. jinfo 命令格式: jinfo [ option ] pid pid是虚拟 ...

  10. Flink cep的初步使用

    一.CEP是什么 在应用系统中,总会发生这样或那样的事件,有些事件是用户触发的,有些事件是系统触发的,有些可能是第三方触发的,但它们都可以被看做系统中可观察的状态改变,例如用户登陆应用失败.用户下了一 ...