开个人网站怎么赚钱,贵阳建站公司模板,如何网上赚点零花钱,手机版qq电脑登录网页入口上一篇通过实例快速掌握k8s(Kubernetes)核心概念讲解了k8s的核心概念#xff0c;有了核心概念整个骨架就完整了#xff0c;应付无状态程序已经够了#xff0c;但还不够丰满。应用程序分成两种#xff0c;无状态和有状态的。一般的前段和后端程序都是无状态的通过实例快速掌握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_PASSWORDroot -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查看容器状态。vagrantubuntu-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地址。vagrantubuntu-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 --protocoltcp -u root -p”登录到MySQL172.17.0.2是MySQL的IP地址“3306”是MySQL端口是在创建镜像时设定的对外开放的端口“root”是用户名“-p”是password的参数选项。敲入命令后系统要求输入password输入后显示已成功连接到MySQL。vagrantubuntu-xenial:~$ mysql -h 172.17.0.2 -P 3306 --protocoltcp -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”的Podstrategy:type: Recreatetemplate: # 开始定义Podmetadata:labels:app: mysql #Pod的Label用来标识Podspec:containers: # 开始定义Pod里面的容器- image: mysql:5.7name: mysql-conimagePullPolicy: Neverenv: # 定义环境变量- name: MYSQL_ROOT_PASSWORD # 环境变量名value: root # 环境变量值- name: MYSQL_USERvalue: dbuser- name: MYSQL_PASSWORDvalue: dbuserargs: [--default-authentication-pluginmysql_native_password]ports:- containerPort: 3306 # mysql端口name: mysql服务(Service)文件下面是服务配置文件这个与上一篇讲的配置基本相同这里就不解释了。apiVersion: v1kind: Servicemetadata:name: mysql-servicelabels:app: mysqlspec:type: NodePortselector:app: mysqlports:- protocol : TCPnodePort: 30306port: 3306targetPort: 3306安装测试有了配置文件后下面就开始创建MySQL。在创建时要按照顺序依次进行先从最底层的对象开始创建。创建部署和服务kubectl apply -f mysql-deploymentkubectl apply -f mysql-service.yaml查看服务vagrantubuntu-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。vagrantubuntu-xenial:~$ mysql -h localhost -P 30306 --protocoltcp -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?”LoadBalancerLoad 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?”。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需要匹配这使它没有接口灵活。后面会详细讲解。动态持久卷在这种情况下你只需创建持久卷申请(不需要单独创建持久卷)然后把持久卷申请与部署绑定。系统会按照持久卷申请自动创建持久卷。下面是持久卷申请配置文件。其中“storage1Gi”是指申请的空间大小是1G。持久卷申请配置文件apiVersion: v1kind: PersistentVolumeClaimmetadata:name: mysql-pv-claimlabels:app: mysqlspec:accessModes:- ReadWriteOnceresources:requests:storage: 1Gi #持久卷的容量是 1 GB**挂载持久卷申请的部署**下面是挂载了持久卷申请的部署配置文件。它通过把持久卷申请当做持久卷来使用与Pod进行绑定。请阅读文件里有关持久卷的注释。shellapiVersion: apps/v1kind: Deploymentmetadata:name: mysql-deploymentspec:selector:matchLabels:app: mysqlstrategy:type: Recreatetemplate:metadata:labels:app: mysqlspec:containers:- image: mysql:5.7name: mysql-conimagePullPolicy: Neverenv:- name: MYSQL_ROOT_PASSWORDvalue: root- name: MYSQL_USERvalue: dbuser- name: MYSQL_PASSWORDvalue: dbuserargs: [--default-authentication-pluginmysql_native_password]ports:- containerPort: 3306name: mysqlvolumeMounts: # 挂载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”创建持久卷申请在创建它的同时系统自动创建持久卷。查看持久卷申请vagrantubuntu-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查看持久卷申请详细信息vagrantubuntu-xenial:/mnt$ kubectl describe pvc mysql-pv-claimName: mysql-pv-claimNamespace: defaultStorageClass: standardStatus: BoundVolume: pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60faLabels: appmysql...显示持久卷vagrantubuntu-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”。vagrantubuntu-xenial:/mnt$ kubectl describe pv pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60faName: pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60faLabels: Annotations: hostPathProvisionerIdentity: 19948fdf-e67f-11e9-8fbd-026a5b40726fpv.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-59715a2d60faHostPathType:Events: 查看MySQL目录信息vagrantubuntu-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.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: v1kind: PersistentVolumemetadata:name: mysql-pvspec:capacity:storage: 1GivolumeMode: FilesystemaccessModes:- ReadWriteOncestorageClassName: standard #持久卷存储类型它需要与持久卷申请的类型相匹配local:path: /home/vagrant/database/mysql #宿主机的目录nodeAffinity:required:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- minikube # Node的名字---apiVersion: v1kind: PersistentVolumeClaimmetadata:name: mysql-pv-claimlabels:app: mysqlspec:accessModes:- ReadWriteOnce# storageClassName: # 这里的存储类型注释掉了resources:requests:storage: 1Gi #1 GB如果不知道Node名字可用如下命令查看vagrantubuntu-xenial:/$ kubectl get nodeNAME STATUS ROLES AGE VERSIONminikube Ready master 6d3h v1.15.2改用静态持久卷之后只有持久卷配置文件发生了变化部署和服务的配置文件没有变。重新运行持久卷和部署成功之后即使重启虚拟机MySQL里面的新建内容也没有丢失。注意这里storageClassName的用法。k8s规定持久卷和持久卷申请的storageClassName必须匹配这时才会把持久卷分配给持久卷申请。我们这里的持久卷申请没有指定storageClassName这时系统会使用缺省的storageClass。查看是否安装了缺省的storageClassvagrantubuntu-xenial:/$ kubectl get scNAME PROVISIONER AGEstandard (default) k8s.io/minikube-hostpath 6d3hvagrantubuntu-xenial:/$查看缺省的storageClass详细信息vagrantubuntu-xenial:/$ kubectl describe scName: standardIsDefaultClass: YesAnnotations: storageclass.kubernetes.io/is-default-classtrueProvisioner: k8s.io/minikube-hostpathParameters: AllowVolumeExpansion: MountOptions: ReclaimPolicy: DeleteVolumeBindingMode: ImmediateEvents: 从这里可以看出Minikube安装了缺省的storageClass它的名字是“standard”。上面的持久卷申请里没有指定storageClass因此系统使用缺省的storageClass与之匹配而上面的持久卷的storageClassName是“standard”正好能配上。详情请见“Dynamic Provisioning and Storage Classes in Kubernetes”踩过的坑:使用Hyper-V还是VirtualBoxHyper-V和VirtualBox是不兼容的只能选一个(当然你可以在这两者之间切换但太麻烦了)。我在Windows上装了VirtualBox运行正常。进入Vagrant之后安装了“ubuntu”版的Linux。这时当你启动Minikube时可以键入“minikube start --vm-drivervirtualbox”但系统显示“This computer doesnt 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-drivernone”。幸好这个方法工作得很好。当用“minikube start --vm-drivervirtualbox”时你是先建了虚拟机再在虚拟机上运行Minikube。当用“minikube start --vm-drivernone”时是直接在宿主机上运行Minikube。但由于我的Windows版本不能直接支持k8s我已经在Windows上装了Linux虚机并用Vagrant进行管理。如果用“minikube start --vm-drivervirtualbox”就是在Linux虚机上又装了一个虚机。现在用“minikube start --vm-drivernone”表面上看是在宿主机上运行实际上已经运行在Windows的Linux虚机上了。登录k8s集群当用“minikube start --vm-drivernone”启动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 发布