点击上方蓝色“Go语言中文网”关注我们,设个星标,每天学习 Go 语言

前一篇"通过实例快速掌握 k8s(Kubernetes)核心概念[1]"讲解了 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 psCONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES3b9c50420f5b        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 3Server version: 5.7.27 MySQL Community Server (GPL)...

在 k8s 上安装 MySQL

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

部署(Deployment)文件

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

apiVersion: apps/v1kind: 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: v1kind: Servicemetadata:  name: mysql-service  labels:    app: mysqlspec:  type: NodePort  selector:      app: mysql  ports:  - protocol : TCP    nodePort: 30306    port: 3306    targetPort: 3306

安装测试:

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

创建部署和服务:

kubectl apply -f mysql-deploymentkubectl apply -f mysql-service.yaml

查看服务:

vagrant@ubuntu-xenial:~$ kubectl get serviceNAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGEkubernetes      ClusterIP   10.96.0.1               443/TCP          3h42mmysql-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 -pEnter password:Welcome to the MySQL monitor.  Commands end with ; or \g.Your MySQL connection id is 6Server 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?[2]

  • 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 serviceNAME            TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGEkubernetes      ClusterIP      10.96.0.1                443/TCP        31dnginx-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 serviceNAME            TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGEkubernetes      ClusterIP      10.96.0.1                   443/TCP        31dnginx-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?”[3]。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,你可以下载一个软件解决,详见这里[4]. 这个软件已经是四年之前的了,开始还担心是否与现在的 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: v1kind: PersistentVolumeClaimmetadata:  name: mysql-pv-claim  labels:    app: mysqlspec:  accessModes:    - ReadWriteOnce  resources:    requests:      storage: 1Gi #持久卷的容量是 1 GB

挂载持久卷申请的部署:

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

apiVersion: apps/v1kind: Deploymentmetadata:  name: mysql-deploymentspec:  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 pvcNAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGEmysql-pv-claim   Bound    pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa   1Gi        RWO            standard       10m

查看持久卷申请详细信息

vagrant@ubuntu-xenial:/mnt$ kubectl describe pvc mysql-pv-claimName:          mysql-pv-claimNamespace:     defaultStorageClass:  standardStatus:        BoundVolume:        pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60faLabels:        app=mysql...

显示持久卷:

vagrant@ubuntu-xenial:/mnt$ kubectl get pvNAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   REASON   AGEpvc-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-59715a2d60faName:            pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60faLabels:          Annotations:     hostPathProvisionerIdentity: 19948fdf-e67f-11e9-8fbd-026a5b40726f                 pv.kubernetes.io/provisioned-by: k8s.io/minikube-hostpathFinalizers:      [kubernetes.io/pv-protection]StorageClass:    standardStatus:          BoundClaim:           default/mysql-pv-claimReclaim Policy:  DeleteAccess Modes:    RWOVolumeMode:      FilesystemCapacity:        1GiNode 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 -altotal 188488drwxrwxrwx 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 ibtmp1drwxr-x--- 2  999 docker     4096 Oct  4 12:58 mysqldrwxr-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.pemdrwxr-x--- 2  999 docker     4096 Oct  4 13:18 service_configdrwxr-x--- 2  999 docker    12288 Oct  4 12:58 sys

持久卷的回收模式:

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

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

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

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

静态持久卷:

动态持久卷的一个问题是它的缺省回收模式是“删除”,这样当虚机重新启动后,持久卷会被删除。当你重新运行部署时,k8s 会创建一个新的 MySQL,这样原来 MySQL 里的新建信息就会丢失,这是我们不愿意看到的。虽然你可以手动修改回收方式为“保持”,但还是要手动回收原来持久卷里的数据。一个解决办法是把持久卷建在宿主机上,这样即使虚机出了问题被重新启动,MySQL 里的新建信息依然不会丢失。如果是在云上,就会有专门的的存储层,如果是本地,大致有三种方式:

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

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

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

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

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

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

apiVersion: v1kind: PersistentVolumemetadata:  name: mysql-pvspec:  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: v1kind: PersistentVolumeClaimmetadata:  name: mysql-pv-claim  labels:    app: mysqlspec:  accessModes:    - ReadWriteOnce  # storageClassName:  # 这里的存储类型注释掉了  resources:    requests:      storage: 1Gi #1 GB

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

vagrant@ubuntu-xenial:/$ kubectl get nodeNAME       STATUS   ROLES    AGE    VERSIONminikube   Ready    master   6d3h   v1.15.2

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

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

查看是否安装了缺省的 storageClass

vagrant@ubuntu-xenial:/$ kubectl get scNAME                 PROVISIONER                AGEstandard (default)   k8s.io/minikube-hostpath   6d3hvagrant@ubuntu-xenial:/$

查看缺省的 storageClass 详细信息

vagrant@ubuntu-xenial:/$ kubectl describe scName:                  standardIsDefaultClass:        YesAnnotations:           storageclass.kubernetes.io/is-default-class=trueProvisioner:           k8s.io/minikube-hostpathParameters:            AllowVolumeExpansion:  MountOptions:          ReclaimPolicy:         DeleteVolumeBindingMode:     ImmediateEvents:                

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

踩过的坑:

  1. 使用 Hyper-V 还是 VirtualBoxHyper-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 虚机上了。

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

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

喜欢本文的朋友,欢迎关注“Go语言中文网”:

推荐阅读

  • Go语言爱好者周刊:第 12 期

  • 通过实例快速掌握k8s(Kubernetes)核心概念

  • Uber Go语言编码规范

参考资料

[1]

通过实例快速掌握k8s(Kubernetes)核心概念: https://blog.csdn.net/weixin_38748858/article/details/102132544

[2]

Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?: https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0

[3]

“Vagrant reverse port forwarding?”: https://stackoverflow.com/a/17012410

[4]

详见这里: https://www.virtualbox.org/attachment/ticket/14040/VBox-Win10-fix-14040.exe

[5]

Volumes: https://kubernetes.io/docs/concepts/storage/volumes/#local

[6]

hostPath as volume in kubernetes: https://stackoverflow.com/questions/50001403/hostpath-as-volume-in-kubernetes

[7]

Kubernetes Volumes Guide: https://matthewpalmer.net/kubernetes-app-developer/articles/kubernetes-volumes-example-nfs-persistent-volume.html

[8]

Dynamic Provisioning and Storage Classes in Kubernetes: https://kubernetes.io/blog/2017/03/dynamic-provisioning-and-storage-classes-kubernetes/

k8s service type_通过搭建MySQL掌握k8s(Kubernetes)重要概念(上):网络与持久卷...相关推荐

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

    上一篇"通过实例快速掌握k8s(Kubernetes)核心概念"讲解了k8s的核心概念,有了核心概念整个骨架就完整了,应付无状态程序已经够了,但还不够丰满.应用程序分成两种,无状态 ...

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

    上一篇"通过实例快速掌握k8s(Kubernetes)核心概念"讲解了k8s的核心概念,有了核心概念整个骨架就完整了,应付无状态程序已经够了,但还不够丰满.应用程序分成两种,无状态 ...

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

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

  4. K8s系列之:搭建高可用K8s v1.23.5集群详细步骤,3个master节点,3个Node节点

    K8s系列之:搭建高可用K8s v1.23.5集群详细步骤,3个master节点,3个Node节点 一.K8s集群节点划分 二.k8s集群环境准备 三.关闭swap 四.关闭ipv6 五.桥接IPv4 ...

  5. [k8s] 第一章 十分钟带你理解Kubernetes核心概念

    本章节主要介绍应用程序在服务器上部署方式演变以及kubernetes的概念.组件和工作原理. 应用部署方式演变 在部署应用程序的方式上,主要经历了三个时代: 传统部署:互联网早期,会直接将应用程序部署 ...

  6. k8s使用volume将ConfigMap作为文件或目录直接挂载_Kubernetes in Action 06. 卷:将磁盘挂载到容器...

    简介 P161 pod 中的每个容器都有自己独立的文件系统,因为文件系统来自容器镜像. P161 Kubernetes 中的卷是 pod 的一部分,并和 pod 共享相同的生命周期.这意味着 pod ...

  7. 基于 k8s 搭建 mysql 5.7 主从复制集群

    关于 k8s 集群环境的搭建可以参考我的另一篇博客 k8s 集群之使用 kubeadm 在 Centos8 上部署 kubernetes 1.20 关于 nfs 网络存储如何搭建和使用可以参考我的另一 ...

  8. service mysql k8s_Kubernetes/K8S基础使用方法总结【五】——Service

    Service有userspace.iptables.ipvs三种工作模式,可在配置文件/etc/sysconfig/kubelet中添加配置参数KUBE_PROXY_MODE=ipvs来改变kube ...

  9. k8s docker集群搭建

    一.Kubernetes系列之介绍篇 1.背景介绍 云计算飞速发展 - IaaS - PaaS - SaaS Docker技术突飞猛进 - 一次构建,到处运行 - 容器的快速轻量 - 完整的生态环境 ...

最新文章

  1. maven基础概念学习1
  2. python将二维数组转换为一维数组_python的set处理二维数组转一维数组的方法示例...
  3. 数据结构-单向循环链表、双向循环链表、仿真链表
  4. oracle as 不可以省略,Oracle:存储过程,存储函数
  5. centos service 无法用
  6. 北京某打工子弟学校之三
  7. eclipse 插件打包发布
  8. Oracle定时器(Job)各时间段写法汇总
  9. Java 头像剪切及上传服务器JSP 笔记
  10. 如何为Kafka挑选合适的分区数
  11. Euler 的面(Face,F)、顶(Vertex,V)、棱(Edge,E)公式
  12. PHP Overview
  13. java中程序定义book类_Java基础_0302:类和对象
  14. AtCoder Grand Contest 007 题解
  15. 算法——重构字符串使得相邻字符不同
  16. 教你修改网卡物理地址(MAC)
  17. 工厂数字化转型必备的多协议转换网关
  18. DolphinScheduler技术分析(八)
  19. [js] 网易漫画爬虫
  20. 如何高效的使用苹果产品的备忘录、提醒事项、日历?

热门文章

  1. 微信小程序文本溢出省略号(···)
  2. 解决微信调整字体大小导致Html5页面混乱
  3. Open3d之对点云进行DBSCAN 聚类
  4. centos nginx不是命令_Linux使用yum安装nginx服务教程
  5. OpenCV 直方图均衡化 equalizeHist
  6. 产品研发管理(二):使用SubVersion进行代码管理
  7. caffeine java1.7_Caffeine高性能命中率近似最优的Java缓存库
  8. asterisk php agi,asterisk AMI入门
  9. 极酷WIFI深度剖析免费WIFI
  10. td外边加div为啥不隐藏_那些不常见,但却非常实用的 css 属性