首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

如何快速学习网站基本搭建和服务器环境配置?

一、基本概念 实验1: 在阿里云上部署Tomcat服务器 点击详情 业务背景Tomcat为网站的服务器,每个网站在后面都有一个服务器来解析那个网页,Tomcat 对于 Java 来说它就是一个 Servlet 处理器,支持运行基于 Servlet 的 Java 程序,同时 JSP 本身也是基于 Servlet 的技术,也是支持的,像传说中的 Spring, Struts, JSF 都是基于 Servlet 的,都可以在 Tomcat 上跑起来。 技术背景Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。 实验2: 快速搭建和部署LAMP环境 点击详情 LAMP是指Linux(操作系统),ApacheHTTP服务器,MySQL(有时也指MariaDB,数据库软件)和PHP(有时也指Perl或Python)的第一个字母,一般用来建立web应用平台。虽然这些开放源代码程序,本身并不是专门设计成同另几个程序一起工作的,但由于它们的免费和开源,这个组合开始流行(大多数Linux发行版本捆绑了这些软件)。当一起使用的时候,它们表现的像一个具有活力的解决方案包。和Java/J2EE架构相比,LAMP具有Web资源丰富、轻量、快速开发等特点,微软的.NET架构相比,LAMP具有通用、跨平台、高性能、低价格的优势,因此LAMP无论是性能、质量还是价格都是企业搭建网站的首选平台。 Apache是LAMP架构最核心的Web Server,开源、稳定、模块丰富是Apache的优势。但Apache的缺点是有些臃肿,内存和CPU开销大,性能上有损耗,不如一些轻量级的Web服务器(例如nginx)高效,轻量级的Web服务器对于静态文件的响应能力来说远高于Apache服务器。Apache做为Web Server是负载PHP的最佳选择,如果流量很大的话,可以采用nginx来负载非PHP的Web请求。nginx是一个高性能的HTTP和反向代理服务器,Nginx以它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。Nginx不支持PHP和CGI等动态语言,但支持负载均衡和容错,可和Apache配合使用,是轻量级的HTTP服务器的首选。 PHP的加速使用eAccelerator加速器,eAccelerator是一个自由开放源码PHP加速器,优化和动 态内容缓存,提高了性能PHP脚本的缓存性能,使得PHP脚本在编译的状态下,对服务器的开销几乎完全消除。它还有对脚本起优化作用,以加快其执行效率。 使PHP程序代码执效率能提高1-10倍。 开源的数据库中,MySQL在性能、稳定性和功能上是首选,可以达到百万级别的数据存储,网站初期可以将MySQL和Web服务器放在一起,但是当访问量达到一定规模后,应该将MySQL数据库从Web Server上独立出来,在单独的服务器上运行,同时保持Web Server和MySQL服务器的稳定连接。 实验3: 在阿里云上部署LNMP 点击详情 LNMP简介 LNMP代表的就是:Linux系统下Nginx+MySQL+PHP这种网站服务器架构。 Linux:是一类Unix计算机操作系统的统称,是目前最流行的免费操作系统。代表版本有:debian、centos、ubuntu、fedora、gentoo等。Nginx:是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。Mysql:是一个小型关系型数据库管理系统。PHP:是一种在服务器端执行的嵌入HTML文档的脚本语言。这四种软件均为免费开源软件,组合到一起,成为一个免费、高效、扩展性强的网站服务系统。 Nginx简介和使用场景 Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,Nginx,它的发音为 “engine X”, 是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP 代理服务器.Nginx是由俄罗斯人 Igor Sysoev为俄罗斯访问量第二的 Rambler.ru站点开发的,它已经在该站点运行超过三年了。Igor Sysoev在建立的项目时,使用基于BSD许可。 为什么Nginx的性能要比Apache高得多?这得益于Nginx使用了最新的epoll(Linux 2.6内核)和kqueue(freebsd)网络I/O模型,而Apache则使用的是传统的select模型。目前Linux下能够承受高并发访问的 Squid、Memcached都采用的是epoll网络I/O模型。 处理大量的连接的读写,Apache所采用的select网络I/O模型非常低效。下面用一个比喻来解析Apache采用的select模型和Nginx采用的epoll模型进行之间的区别:假设你在大学读书,住的宿舍楼有很多间房间,你的朋友要来找你。select版宿管大妈就会带着你的朋友挨个房间去找,直到找到你为止。而epoll版 宿管大妈会先记下每位同学的房间号,你的朋友来时,只需告诉你的朋友你住在哪个房间即可,不用亲自带着你的朋友满大楼找人。如果来了10000个人,都要 找自己住这栋楼的同学时,select版和epoll版宿管大妈,谁的效率更高,不言自明。同理,在高并发服务器中,轮询I/O是最耗时间的操作之 一,select和epoll的性能谁的性能更高,同样十分明了。 在高并发连接的情况下,Nginx是Apache服务器不错的替代品。Nginx同时也可以作为7层负载均衡服务器来使用。Nginx 0.8.46 + PHP 5.2.14 (FastCGI) 可以承受3万以上的并发连接数,相当于同等环境下Apache的10倍。

优秀的个人博客,低调大师

ASP.NET Core on K8S深入学习(9)Secret & Configmap

​ 一、Secret 1.1 关于Secret 在应用启动过程中需要一些敏感信息,比如数据库用户名、密码,如果直接明文存储在容器镜像中是不安全的,K8S提供的方案是Secret。 Secret 会以密文的方式存储数据,避免了直接在配置文件中保存敏感信息。 Secret 会以 Volume 的形式被 mount 到 Pod,容器可通过文件的方式使用 Secret 中的敏感数据,也可以使用环境变量的方式使用。 1.2 创建与查看Secret 这里假设我们要创建一个包含以下信息的Secret: (1)用户名:Edison (2)密码:EDC123456* 有4种方法来创建Secret: (1)通过 --from-literal: kubectl create secret generic mysecret --from-literal=username=Edison --from-literal=password=EDC123456* PS:每个--from-literal对应一个信息条目 (2)通过 --from-file: echo -n Edison > ./username echo -n EDC123456* > ./password kubectl create secret generic mysecret --from-file=./username --from-file=./password PS:每个文件内容对应一个信息条目 (3)通过 --from-env-file: cat << EOF > env.txt username=Edison password=EDC123456* EOF kubectl create secret generic mysecret --from-env-file=env.txt PS:文件env.txt中每行 Key=Value 对应一个信息条目 (4)通过YAML配置文件创建:(推荐方式) 由于配置文件中的敏感数据必须是通过base64编码后的结果,因此需要获取base64编码后的值: 下面就是这个YAML文件的内容: apiVersion: v1 kind: Secret metadata: name: edc-secret data: username: RWRpc29u password: RURDMTIzNDU2Kg== 通过kubectl apply来创建Secret: 创建成功后,验证一下,查看一下这个Secret: kubectl get secret edc-secret // 查看存在的secret kubectl describe secret edc-secret // 查看条目的Key kubectl edit secret edc-secret // 查看条目的Value 将Value进行base64反编码,如下所示,与预期一致: 1.3 在Pod中使用Secret K8S中Pod中使用Secret有两种方式,一是Volume方式,二是环境变量的方式。 (1)Volume方式 这里我们以一个示例演示一下如何通过Volume方式使用Secret,首先定义一个Pod: apiVersion: v1 kind: Pod metadata: name: secret-demo spec: containers: - name: secret-demo-pod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy; sleep 30000 volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true volumes: - name: foo secret: secretName: edc-secret 该Pod中会使用到刚刚定义的secret(edc-secret),然后volumeMounts定义了将foo mount到容器中的路径为/etc/foo的目录下,并且指定了读写权限为只读。 通过kubectl apply创建之后,我们试着在容器中读取secret来验证一下,如下图所示: 可以看到,K8S为每条敏感数据创建了一个文件,而且其Value是以明文存放的。 当然,你也可以自定义存放数据的目录,如下配置所示: apiVersion: v1 kind: Pod metadata: name: secret-demo spec: containers: - name: secret-demo-pod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy; sleep 30000 volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true volumes: - name: foo secret: secretName: edc-secret items: - key: username path: /edc-group/username - key: password path: /edc-group/password 这时,该secret就会存放于/etc/foo/edc-group/username 和 /etc/foo/edc-group/password 两个目录下了。 (2)动态更新 以Volume方式使用Secret,其中一个优点就是支持动态更新。例如,我们将Secret更新一下,重新应用到K8S中: apiVersion: v1 kind: Secret metadata: name: edc-secret data: username: RWRpc29u password: YWJjZGVmZyo= // 换为了 abcdefg* 通过kubectl apply重新应用之后,等待一段时间后,再次进入容器中验证: 已经改为了 abcdefg*,符合预期。 (2)环境变量方式 通过Volume使用Secret看起来稍微麻烦了一点,容器必须通过文件读取数据。K8S提供了另外一种方式,那就是环境变量方式。 下面仍以上面的例子为例,修改配置文件: apiVersion: v1 kind: Pod metadata: name: secret-demo spec: containers: - name: secret-demo-pod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy; sleep 30000 env: - name: EDC_SECRET_USERNAME valueFrom: secretKeyRef: name: edc-secret key: username - name: EDC_SECRET_PASSWORD valueFrom: secretKeyRef: name: edc-secret key: password 通过kubectl apply应用之后,进入容器验证一下: 可以看到,可以方便地通过环境变量获取到Value。 _PS:_需要注意的也是,虽然通过环境变量读取Secret比较方便,但是无法支持Secret动态更新! 二、Configmap 2.1 关于Configmap 上面提到的Secret可以为Pod提供机密数据的存储,而对于一些非机密敏感的数据,像一些应用的配置信息啊神马的,则可以使用Configmap。 Configmap的创建与使用方式与Secret非常类似,不同点只在于数据以明文形式存放(不过,我觉得Secret的密文形式也并不密文,只能算得上是简单编码)。 2.2 创建Configmap 和Secret一样,可以通过 --from-literal,--from-file 和 --from-env-file来创建,这里我们跳过,直接说下我们最常用的yaml配置文件的方式。 apiVersion: v1 kind: ConfigMap metadata: name: service-configmap data: LogLevel: Error LogFile: service-timestamp.log AllowedHosts: edc.com 2.3 使用Configmap 和Secret一样,也可以通过Volume 或 环境变量两种方式来使用Configmap。 (1)Volume方式 apiVersion: v1 kind: Pod metadata: name: configmap-demo spec: containers: - name: configmap-demo-pod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy; sleep 30000 volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true volumes: - name: foo configMap: name: service-configmap (2)环境变量方式 apiVersion: v1 kind: Pod metadata: name: secret-demo spec: containers: - name: secret-demo-pod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy; sleep 30000 env: - name: SERVICE_LOG_LEVEL valueFrom: configMapKeyRef: name: service-configmap key: LogLevel - name: SERVICE_LOG_FILE valueFrom: configMapKeyRef: name: service-configmap key: LogFile - name: SERVICE_ALLOWED_HOSTS valueFrom: configMapKeyRef: name: service-configmap key: AllowedHosts 2.4 最佳实践 大多数情况下,大家建议的最佳实践是: (1)创建ConfigMap采用YAML配置方式 => 便于复用和版本管理 (2)读取ConfigMap采用Volume方式 => 便于配置动态更新 下面我们创建一个Configmap,其YAML内容如下: apiVersion: v1 kind: ConfigMap metadata: name: service-configmap data: appsettings.json: | LogHandler: NLogHandler LogLevel: Error LogFile: %hostname-%timestamp.log 这里注意别忘了:后面的 | 符号,然后创建&查看Configmap: 如果想要在Pod中使用此Configmap,可以在YAML配置如下: apiVersion: v1 kind: Pod metadata: name: configmap-demo spec: containers: - name: configmap-demo-pod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy; sleep 30000 volumeMounts: - name: configmap mountPath: "/etc/configmap" volumes: - name: configmap configMap: name: service-configmap items: - key: appsettings.json path: appsettings.json 这里将Volume mount到了容器的 /etc/configmap 目录中,下面我们验证一下: 这时我们将configmap更新一下,如下: apiVersion: v1 kind: ConfigMap metadata: name: service-configmap data: appsettings.json: | Logging: LogLevel: Default: "Error" AllowedHosts: "*" 通过kubectl apply更新一下configmap,然后再到pod中验证是否动态更新: 可以看出,已经动态更新,符合预期! 2.5 ASP.NET Core appSettings 我们在ASP.NET Core中的配置都是写在appSettings.json文件中,如何将appSettings.json转换为ConfigMap呢?圣杰已经总结归纳为了《.NET Core使用K8S Configmap的正确姿势》一文,有兴趣的读者可以参考此文。 三、小结 本文探索了在K8S中如何进行配置管理,如果需要密文配置,可以使用Secret,如果是一般应用配置,可以使用ConfigMap。虽然Secret和ConfigMap都定义了好几种定义方式,但是我们一般采用YAML配置创建和Volume方式读取,因为Volume方式可以支持动态更新。最后,通过分享圣杰的一篇文章,介绍了如何在ASP.NET Core下使用Configmap的方式,希望对你有帮助!

优秀的个人博客,低调大师

ASP.NET Core on K8S深入学习(8)数据管理

​ 在Docker中我们知道,要想实现数据的持久化(所谓Docker的数据持久化即_数据不随着Container的结束而结束_),需要将数据从宿主机挂载到容器中,常用的手段就是Volume数据卷。在K8S中,也提供了存储模型Volume,支持我们将应用中的数据持久化存储到容器中。 一、Volume 1.1 关于K8S Volume 为了持久化保存容器的数据,我们可以使用K8S Volume,其本质上也是一个目录,与Docker Volume没有什么区别。 需要注意的是:K8S Volume的生命周期独立于容器,Pod中的容器可能被销毁和重建,但Volume会被保留。 当Volume被mount到Pod中,Pod中的的所有容器都可以访问这个Volume。在K8S中,支持多种backend类型,例如emptyDir, hostPath, NFS, Ceph以及一些云服务商提供的存储服务等等。对Pod来说,它不需要关心到底数据会被存储在本地文件系统中还是远程云端硬盘中,它认为所有类型的Volume都只是一个目录而已。 1.2 使用K8S Volume (1)emptyDir 作为K8S最基础的Volume类型,emptyDir提供了最基础的持久化方案,但是这个方案不怎么好。因为,emptyDir对于Pod来说并非持久的(它对于容器来说是持久化的),因为当Pod从节点删除时,Volume的内容也会被删除。但如果只是容器被销毁而Pod还在,则Volume不会受影响。 换句话说:emptyDir Volume的生命周期与Pod一致。鉴于此特性,不建议在实际中使用此类型Volume。 (2)hostPath 相对于emptyDir,hotPath则克服了其生命周期的弱点,如果Pod被销毁,hostPath对应的目录还是会被保留。不过,如果一旦Host崩溃,hostPath也就无法访问了。因为,hostPath是将Docker Host文件系统中已经存在的目录mount给Pod的容器,所以会依赖于Host。 在K8S中,那些需要访问K8S或Docker内部数据(配置文件和二进制库)的应用需要使用到hostPath,比如kube-apiserver和kube-controller-manager这样的应用。下面的配置就是kube-apiserver的持久化设置,其定义了3个hostPath:ca-certs, etc-pki以及k8s-certs,分别对应Host目录为/etc/ssl/certs, /etc/pki 以及 /etc/kubernetes/pki。 volumeMounts: - mountPath: /etc/ssl/certs name: ca-certs readOnly: true - mountPath: /etc/pki name: etc-pki readOnly: true - mountPath: /etc/kubernetes/pki name: k8s-certs readOnly: true dnsPolicy: ClusterFirst enableServiceLinks: true hostNetwork: true nodeName: k8s-master priority: 2000000000 nodeName: k8s-master priority: 2000000000 priorityClassName: system-cluster-critical restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 tolerations: - effect: NoExecute operator: Exists volumes: - hostPath: path: /etc/ssl/certs type: DirectoryOrCreate name: ca-certs - hostPath: path: /etc/pki type: DirectoryOrCreate name: etc-pki - hostPath: path: /etc/kubernetes/pki type: DirectoryOrCreate name: k8s-certs (3)外部Storage Povider 如果我们的K8S是部署在AWS、GCE、Azure等公有云上,那么可以直接使用云硬盘做为Volume。这里由于我没有使用,所以跳过,有使用的朋友可以直接参考各云服务提供商的参考文档进行配置。 二、PersistentVolume与PersistentVolumeClaim 2.1 关于PersistentVolume与PersistentVolumeClaim 前面提到的几种方案在可管理性上均有不足,特别是当集群规模较大的时候,效率和安全性均有待提高。因此,K8S提供了一个解决方案:PersistentVolume 和 PersistentVolumeClaim,以下简称PV和PVC。 PV是外部存储系统中的一块存储空间,由管理员创建和维护。与Volume一样,PV具有持久性,生命周期独立于Pod。 PVC则是对PV的申请(Claim),PVC通常由普通用户创建和维护。当需要为Pod分配存储资源的时候,用户就可以创建一个PVC,指明存储资源的容量大小和访问方式(比如ReadOnly)等信息,K8S会查找并提供满足条件的PV。 了解ASP.NET Identity的童鞋应该对Claim这个词不陌生,如果把我们的认证信息看成一个Claims,那么其中的一个一个的键值对就是Claim。我们常用的ClaimTypes如下图所示,我们可以通过Claim定位到认证信息中的Value。 同理,我们知道了Claim也就可以定位到我们要使用的哪个PV的地址。 与K8S Volume一样,K8S PersistentVolume也支持多种类型的存储,比如NFS、AWS EBS、Ceph等等。 2.2 NFS PV的使用 NFS是网络文件系统 (Network File System), 它允许系统将本地目录和文件共享给网络上的其他系统。通过 NFS,用户和应用程序可以访问远程系统上的文件,就象它们是本地文件一样。 关于如何为CentOS配置NFS,请参考这一篇文章《CentOS7安装NFS服务》。 这里假设已经为我们的k8s-master节点搭建了一个NFS服务器,目录为/edc/k8s/nfsdata,如下图所示: (1)创建一个PV 接下来我们就来创建一个PV,其yaml配置文件如下: apiVersion: v1 kind: PersistentVolume metadata: name: edc-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: nfs nfs: path: /edc/k8s/nfsdata/edc-pv server: 192.168.2.100 其中: capacity指定了PV的容量为1GB accessModes指定访问模式为ReadWriteOnce,表示PV能够以Read-Write模式mount到单个节点。此外,还支持ReadOnlyMany和ReadWriteMany,分别代表PV能以Read-Only模式或者Read-Write模式mount到多个节点。这里ReadWriteOnce只mount到单个节点,即k8s-master(192.168.2.100)。 persistentVolumeReclaimPolicy指定了此PV的回收策略为Recycle,表示清除PV中的数据。此外,还支持Retain和Delete,Retain表示需要管理员手动回收,类似于你用C/C++还需要手动写free代码释放空间。而Delete呢,表示删除Storage Provider中的对应存储资源,如果你使用的是外部云服务提供商的存储空间的话。 storageClassName指定了PV的class为nfs。 nfs配置项指定了PV在NFS服务器上对应的目录,如果没有可以事先创建一下。 理解了其中的配置项,我们创建该PV,可以看到其状态Status变为了Available,表示可以被PVC申请啦。 (2)创建一个PVC 与创建PV不同,创建PVC只需指定PV容量、访问模式以及class即可: apiVersion: v1 kind: PersistentVolumeClaim metadata: name: edc-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: nfs 有了配置文件,就可以创建PVC了: 可以看到,edc-pvc已经Bound到edc-pv了,申请PV成功。 申请成功之后,我们就可以在Pod中使用了,下面是一个示例Pod的配置文件: apiVersion: v1 kind: Pod metadata: name: edc-pv-pod spec: containers: - name: edc-pv-pod image: busybox args: - /bin/sh - -c - sleep 30000 volumeMounts: - mountPath: "/mydata" name: mydata volumes: - name: mydata persistentVolumeClaim: claimName: edc-pvc 通过kubectl创建该pod,如下所示: 接下来验证一下PV是否可用: 可以看到,在Pod中创建的文件/mydata/hello已经保存到了NFS服务器目录的edc-pv目录下了。 2.2 NFS PV的回收 当我们不再需要某个PV时,也可以使用PVC来回收PV,如下所示: kubectl delete pvc edc-pvc 当edc-pvc被删除后,我们会发现K8S启动了一个新Pod,这个Pod就是用来清除edc-pv的数据的。数据的清理需要一个过程,完成后edc-pv的状态会重新恢复为Available,此时可以被新的PVC申请。 此外,由于我们设置的回收策略为Recycle,所以Pod中的数据也被清除了: 如果希望能够保留这些数据,那么我们需要将回收策略改为Retain: apiVersion: v1 kind: PersistentVolume metadata: name: edc-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: /edc/k8s/nfsdata/edc-pv server: 192.168.2.100 这里就不再验证Retain的效果了。 三、MySQL持久化存储案例 3.1 准备工作 这里我们来演示一个MySQL持久化存储的案例: (1)创建PV和PVC 准备PV和PVC的yaml: -- mysql-pv apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: /edc/k8s/nfsdata/mysql-pv server: k8s-master -- mysql-pvc apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: nfs 通过kubectl apply创建PV和PVC: kubectl apply -f mysql-pv.yaml kubectl apply -f mysql-pvc.yaml 可以看到,mysql-pvc已经申请到了mysql-pv。 (2)部署MySQL 准备yaml配置文件: apiVersion: v1 kind: Service metadata: name: mysql-service spec: ports: - port: 3306 selector: app: mysql --- apiVersion: apps/v1 kind: Deployment metadata: name: mysql spec: selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - image: mysql:5.6 name: mysql env: - name: MYSQL_ROOT_PASSWORD value: password ports: - containerPort: 3306 name: mysql-container volumeMounts: - name: mysql-storage mountPath: /var/lib/mysql volumes: - name: mysql-storage persistentVolumeClaim: claimName: mysql-pvc 重点关注其中的volumeMounts和volumes配置,其中mysql-pvc申请Bound的mysql-pv将会被mount到MySQL的数据目录/var/lib/mysql下。 通过kubectl创建MySQL: kubectl apply -f mysql-service.yaml kubectl get pod -o wide 可以看到,MySQL被部署到了k8s-node1节点上。 (3)客户端访问MySQL 下面我们在k8s-master上通过客户端访问MySQL Service: kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql-service -ppassword 如下图所示,进入了MySQL数据库: 接下来我们更新一下数据库,如下图所示: 新建了一张表edc_test,插入了一行数据1110. 3.2 快速验证 (1)模拟k8s-node1故障 接下来我们模拟一下k8s-node1宕机,这样在k8s-node1上运行的MySQL服务就会受到影响,不过根据之前的了解,K8S会帮我们将MySQL迁移到k8s-node2上从而保证服务可用。 首先,关闭k8s-node1: shutdown now 其次,验证K8S迁移MySQL: (2)验证数据一致性 虽然k8s-node1挂了,但是K8S帮我们迁移了MySQL到k8s-node2,而且数据也是完好无损,如下图所示: (3)验证数据持久性 如果我们将部署的Service和Deployment删掉,那么其Pod也会停止被删除,但是由于我们的PV的回收策略是Retain,因此其数据不会被清除: 四、小结 本文探索了K8S的数据管理方案Volume,其中普通类型的Volume如emptyDir和hostPath虽然使用方便,但是可持久性不强,而外部云存储Volume Provider则提供了更好的持久化存储。PV和PVC的模式,更加适合于我们使用在实际环境中,最后还通过了一个MySQL持久化案例演示了如何应用PV和PVC实现持久化。

优秀的个人博客,低调大师

深度学习在高德驾车导航历史速度预测中的探索与实践

导读 驾车导航服务是数字地图提供的核心功能。通常而言,用户在发起导航之前会对比高德前端展示的三条路线(如下图),以决定按照哪条路线行驶。 而预估到达时间是用户参考的最为重要的指标之一。给定一条路线,对应的预估到达时间的计算需要两组信息输入,分别是实时路况信息和历史速度信息(历史速度信息指的是对应的平均通行时间)。其中实时路况信息,对短时(例如60分钟以内)路况预测帮助较大;而历史速度信息对长时(例如60分钟以上)路况预测帮助较大。一般来说,对于未来2小时以上的路况预测而言,当前时刻的路况信息帮助十分有限,也可以理解为历史速度信息基本处于绝对主导的地位。 因此在长距离路线的预估到达时间计算中,历史速度至关重要,其预测的准确性直接影响预估到达时间,进而影响用户选择及体验。我们希望能够通过建模的方式提高历史速度的预测准确率。 历史平均法的不足 以

优秀的个人博客,低调大师

ASP.NET Core on K8S深入学习(3-1)Deployment

上一篇《部署过程解析与安装Dashboard》中我们了解K8S的部署过程,这一篇我们来了解一下K8S为我们提供的几种应用运行方式:Deployment、DaemonSet与Job,它们是Kubernetes最重要的核心功能提供者。考虑到篇幅和更新速度,我将其分为两篇文章,本篇会主要介绍Deployment,主要参考自CloudMan《每天5分钟玩转Kubernetes》,也推荐大家购买阅读。 一、创建资源的两种方式 K8S支持两种创建资源的方式,分别是 使用kubectl命令直接创建 与 通过配置文件+kubectl apply创建,下面以上一篇中的ASP.NET Core示例来分别介绍下这两种方式。 1.1 Kubectl命令直接创建 第一种是通过kubectl命令直接创建: kubectl run k8s-demo-deployment --image=edisonsaonian/k8s-demo:latest --replicas=2 --namespace=aspnetcore 这样我们就部署了一个具有2个副本的k8s-demo(一个ASP.NET Core API示例)。 1.2 YAML配置文件创建 第二种是通过配置文件+kubectl apply(kubectl create也可以)创建: apiVersion: apps/v1 kind: Deployment metadata: name: k8s-demo-deployment namespace: aspnetcore spec: replicas: 2 template: spec: containers: - name: k8s-demo image: edisonsaonian/k8s-demo ports: - containerPort: 80 不过,上面的配置文件可能并不能直接运行,因为默认情况下K8S还有一些必填项的验证,完整你可以参考下面这段配置: apiVersion: apps/v1 kind: Deployment metadata: name: k8s-demo-deployment namespace: aspnetcore spec: replicas: 2 selector: matchLabels: app: aspnetcore_webapi template: metadata: labels: app: aspnetcore_webapi spec: containers: - name: k8s-demo image: edisonsaonian/k8s-demo ports: - containerPort: 80 更多yaml文件的语法基础,可以参考这一篇文章:https://www.kubernetes.org.cn/1414.html 如上所示,我们将资源的属性都写在了一个yaml格式的配置文件中,有了这个配置文件,我们只需要执行一句: kubectl apply -f k8s-demo-deployment.yaml 1.3 相关补充 如果要删除deployment,也只需要执行一句: kubectl delete deployment k8s-demo-deployment 或者是下面这一句: kubectl delete -f k8s-demo-deployment.yaml 执行之后,K8S会自动帮我们删除相关Deployment、ReplicaSet(副本集)以及Pod。 可以看出,直接通过kubectl创建会比较省力和快捷,但是它无法做到很好的管理,不适合正式的、规模化的部署,因此我们一般会更加倾向于采用配置文件的方式,但是使用配置文件要求我们熟悉yaml的语法,如果存在类似制表符之类的特殊字符都是无法成功执行的。 二、Deployment必知必会 2.1 Deployment类型应用运行 这里我们仍以上面提到的k8s-demo示例项目为例,通过下面这个配置文件来创建资源: apiVersion: apps/v1 kind: Deployment metadata: name: k8s-demo-deployment namespace: aspnetcore spec: replicas: 2 selector: matchLabels: app: aspnetcore_webapi template: metadata: labels: app: aspnetcore_webapi spec: containers: - name: k8s-demo image: edisonsaonian/k8s-demo ports: - containerPort: 80 通过下面的命令创建资源: kubectl apply -f k8s-demo-deployment.yaml 下面我们来看看K8S到底为我们做了些什么工作: (1)查看k8s-demo-deployment状态 kubectl get deployment k8s-demo-deployment -n aspnetcore 可以看到,对于我们的这个deployment,生成了2个副本且正常运行。 如果想要获得更加相信的信息,可以使用下面这句: kubectl describe deployment k8s-demo-deployment -n aspnetcore 从deployment的日志中,可以看到如下图所示的信息: 可以看到,K8S的Deployment-Controller为k8s-demo创建了一个ReplicaSet名叫k8s-demo-deployment-54d5c97fb7,后面的Pod就是由这个ReplicaSet来管理的。 (2)查看ReplicaSet的状态 kubectl describe replicaset -n aspnetcore 会得到以下两个图所示的信息: 从上图可以看出,这个ReplicaSet是由Deployment k8s-demo-deployment 创建的。 从上图中的日志(Events代表日志)可以看出,两个副本Pod是由ReplicaSet-Controller创建的,且创建成功。 (3)查看Pod的状态 kubectl describe pod -n aspnetcore 同样,也会得到如下图所示的两个信息: 可以看出,此Pod是由ReplicaSet k8s-demo-deployment-54d5c97fb7创建的。下图的日志记录了Pod的启动过程: 从日志中可以看到Pod的启动过程,如果启动过程中发生了异常(比如拉取镜像失败),都可以通过输出的错误信息查看原因。 下图是整个Deployment的部署过程,即kubectl→Deployment→ReplicaSet→Pod,也可以看出对象的命名方式的规则: 2.2 伸缩Scale 所谓伸缩,是指在线实时增加或减少Pod的副本数量。在刚刚的部署中,我们在配置文件中定义的是2个副本,如下图所示: 可以看到,两个副本分别位于k8s-node1 和 k8s-node2上面。一般默认情况下,K8S不会将Pod调度到Master节点上,虽然Master节点也是可以作为Node节点晒用的。 这时,如果我们想要扩展副本数量从2到3,只需要修改配置文件: apiVersion: apps/v1 kind: Deployment metadata: name: k8s-demo-deployment namespace: aspnetcore spec: replicas: 3 ...... 然后再次apply: kubectl apply -f k8s-demo-deployment.yaml 最终结果如下图所示: 同理,如果想缩小副本数量,也是如上所述的步骤,不再赘述。 2.3 故障转移FailOver 所谓K8S中的故障转移(FailOver),就是当某个Node节点失效或宕机时,会将该Node上所运行的所有Pod转移到其他健康的Node节点上继续运行。 这里继续上例,我们有两个Pod都运行在k8s-node2上,那么我们这里模拟k8s-node2故障,强制关闭该节点: halt -h 等待一段时间后(放心,不会很快),当K8S检测到k8s-node2不可用,会将k8s-node2上的Pod最终标记为Terminating状态,并在k8s-node1上新建两个Pod,维持副本总数量为3。 当然,也可以从Dashboard中直观的看到: 当k8s-node2恢复后,Terminating的Pod会自动被删除,不过已经运行在k8s-node1的Pod是不会重新调度回k8s-node2的。 2.4 善用label控制Pod位置 默认情况下,K8S的Scheduler会均衡调度Pod到所有可用的Node节点,但是有些时候希望将指定的Pod部署到指定的Node节点。例如,一个I/O密集型的Pod可以尽量部署在配置了SSD的Node节点,又或者一个需要GPU的Pod可以尽量部署在配置了GPU的Node节点上。 不用担心,K8S为我们提供了label来实现这个功能,label是一个key/value对,可以灵活设置各种自定义的属性。比如,我们这里假设我们的k8s-demo示例项目是一个I/O密集型的API,还假设k8s-node1是一个配置了SSD的Node节点: kubectl label node k8s-node1 disktype=ssd kubectl get node --show-labels 显示结果如下:可以看到,现在k8s-node多了一个label => disktype=ssd 接下来,我们就可以在配置文件中为要部署的应用指定label了: apiVersion: apps/v1 kind: Deployment metadata: name: k8s-demo-deployment namespace: aspnetcore spec: replicas: 3 selector: matchLabels: app: aspnetcore_webapi template: metadata: labels: app: aspnetcore_webapi spec: containers: - name: k8s-demo image: edisonsaonian/k8s-demo ports: - containerPort: 80 nodeSelector: disktype: ssd 然后,再次apply创建资源: kubectl apply -f k8s-demo-deployment.yaml 验证一下,所有的k8s-demo的Pod全都调度到了k8s-node1上面,符合预期: 如果k8s-node1不再是配置SSD了,那么我们就可以为其删掉这个label了: kubectl label node k8s-node1 disktype- 注意,这里的 - 就代表删除,而且此时Pod不会重新部署,除非你删除配置文件中的配置然后再次apply。 三、小结 本文介绍了K8S中创建资源的两种方式及对比,然后重点介绍了一下Deployment这个Controller,把玩了Deployment类型的应用运行、伸缩、故障转移以及使用label来控制Pod的位置。运行应用是K8S最核心的功能,下一篇会继续研究DaemonSet和Job这两个Controller的应用方式和场景。当然,笔者也还是初学,有很多不足之处,也请多包涵。对于催更的童鞋,请耐心等待。 参考资料 (1)CloudMan,《每天5分钟玩转Kubernetes》 (2)李振良,《一天入门Kubernets教程》 (3)马哥(马永亮),《Kubernetes快速入门》

优秀的个人博客,低调大师

【个人学习JAVA---学后的梳理】 一、从外,观识JAVA

认识Java语言 横看成岭侧成峰,远近高低各不同... 1. Java的历史 Java来自于Sun公司的一个Green项目,它期望能与家用电器进行信息交流,一开始是准备采用C++,不过C++太复杂,安全性差,于是最后基于C++开发了一种新语言Oak(Java的前身),该语言是一种用于网络的精巧而安全的语言。 2. Java的现状 Java是Sun公司推出的新一代面向对象程序设计语言,特别适用于Internet应用程序开发。它具有平台无关的特性(Java开发环境有JDK与JRE)。 2.1:Java的技术分支 Java主要有3类技术分支:(它们前身的前缀名为J2 ,05年后均改为JAVA ) JAVA SE:Java2Platform,StandardEdition;(标准版) JAVA EE: Java2Platform,EnterpriseEdition;(企业版) JAVA ME: Java2Platform,MicroEdition; 以上三个分支,不管如何划分,都是以JAVA SE为核心,那么掌握JAVA SE最为重要。 3. Java的特点 JAVA是一种简单的、面向对象的、分布式的、解释性的、可移植的、多线程的、动态的程序设计语言。 3.1:Java语言的关键特性说明: 简洁有效 Java语言是一种相当简洁的程序设计语言。它省略了C++语言中所有难以理解、容易混淆的特性,例如头文件、指针、结构、单元、运算符重载、虚拟基础类等。所以它更加严谨、简洁。 可移植同操作系统平台无关的特性,使得Java应用程序可以在配备了Java解释器和运行环境的任何计算机操作系统上运行,这就是Java应用软件便于移植的良好基础。而且,Java的基本数据类型设计不依赖具体实现,它通过定义独立于平台的基本数据类型及其运算,使得Java数据得以在任何的硬件平台上保持一致。 面向对象 Java语言的设计完全是面向对象的,不支持类似C语言那样的面向过程的程序设计技术。Java支持静态和动态风格的代码继承和重用。 解释型Java语言是一种解释性语言,相对于C/C++语言来说,Java程序的效率低,执行速度慢。 适合分布式计算Java语言具有强大的、易于使用的联网能力,非常适合开发分布式计算的程序。Java应用程序能像访问本地文件系统那样,通过URL访问远程对象。它十分使用于公共网关接口(GGI)脚本的开发,另外还能使用Java小应用程序(Applet)、Java服务器页面(Java Server Page,JSP)和Servlet等手段来构建更丰富的网页。 4. Java虚拟机(JVM) 虚拟机,即在机器和编译程序间加入了一层抽象的虚拟的机器。它能够在任何平台上都提供给编译程序一个共同的接口。编译程序只需要面向虚拟机,编译生成虚拟机可以理解的代码,然后由解释器将虚拟机代码转换为特定系统的机器码执行。 那么在Java中,虚拟机能理解的代码叫做字节码(Byte Code)。 每一种平台的解释器是不同,但实现的虚拟机相同。 Java源程序(代码存在.java文件)经过编译器编译后变成了字节码(代码存在.claa文件),字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上执行。 Java虚拟机也具有一个指令集,并使用不同的存储区域。它负责执行指令,还要治理数据、内存和寄存器。 图1-Java源文件编译运行过程图 结束

优秀的个人博客,低调大师

【个人学习JAVA---学后的梳理】二、关于JAVA程序的语法

认识Java程序 1. Java的一些基本规则和用法 程序的框架自然需要遵守该语言的特定规则,规则包括对于一条语句的,代码块的,变量的命名等。 符号的使用以西式字符为准,尽量少使用中式输入法输入符号。 1.1:大括号、段和主体 类的主体,以左大括号'{'为开始标记、'}'右大括号为结束标记;其中每个命令语句的结束,必须以分号';'做结尾;而某个命令的语句需要数行才能完成时,则被'{}'所包括起来,此表示一个代码块(代码块分种类,括起来的意义各不相同)。 1.2:标识符 标识符就是包、类、方法、参数、和变量的名字。它可以由任意顺序的大小写字母、数字、下划线和美元符号($,不建议开发者使用此来命名)等组成。注意:标识符是不能以数字作开头,不能是Java中的保留关键字。如: 0name、class。 1.3:Java的注释 注释,是程序中添加的非编译运行信息,开发者可以此解释程序某一处的作用、意义,提高程序的可读性。 注释分为3种: 注释类型 格式 例子 说明 单行注释 //注释内容 int x;//声明一个整数 适用简短信息的一行提示 多行注释 /* 注释内容 */ /* 第一行;第二行 */ 需要描述较多语句 文档注释 /** 注释内容 */ 此注释的内容将会被解释城程序的正式文档 1.4:变量 变量命名就是标识符的命名,对于各种类型数据、对象、类、方法的命名通俗规则,这些类型的变量命名会有不同。 1.5:Java的数据类型 Java提供多种数据类型,Java的数据类型除了可以是基本数据类型之外,还有引用类型。数据类型的总结在以后有专门归纳... 结束

优秀的个人博客,低调大师

【个人学习JAVA---学后的梳理】五、JAVA的核心所在

Java的核心 问渠哪得清如许,为有源头活水来... 语言的特性就是突出提示了它的核心关键所在。 众所周知,Java语言是面向对象的程序设计语言。那么,对象是什么。。。 1. 面向对象程序设计 对象,即某一类事物的一个具体的实体。有着完全相同特征的一群对象即一类事物。所以面向对象的程序设计是:程序 = 对象 + 消息。 对象的特征分为静态特征与动态特征。静态特征:指对象的外观、性质、属性等。动态特征:指其具有的功能、行为动作等。所以面向对象程序设计语言将两者分别抽象为了:属性与方法。所以在面向对象程序语言中,一个对象是由一组属性和一组方法(其对属性进行操作)所构成。-------------------------------------------------------------------------------------------------------------------------------------------类:是具有相同属性和方法的一组对象。类就是一种抽象的数据类型,对象是具体的,所以由抽象的类实例化而来,就是调用类的构造方法后,获得了一个对象。 1.1: 面向对象的语言特性 封装性:尽可能对外界公布一个有限的界面,将细节隐藏,与其他对象的相互作用只通过该界面进行。 继承性:类之间的继承、接口间的继承。继承的特征有: 继承关系是传递的。 它简化了事物的描述,能清晰体现相关类间的层次结构关系。 提供软件复用功能。 通过增强一致性来减少模块间的接口和界面,大大增加程序的易维护性。 只能多重继承(传递)。一个类只能一次继承一个父类。 多态性:Java语言存在多态的形式有,方法重载与成员方法覆写,以及对象间的向上向下转型。 方法的重载:针对于一个类中,相同名字的方法,返回类型可不同,只要重载的方法的参数列表不同,就是实现了该方法的重载。 成员方法的覆写:是针对父类与其子类。子类要想覆写父类的方法,其只能修改方法内部的具体实现,其余(如方法名、返回类型、参数列表)均不能更改。 结束 2019年8月6日 18:35:55

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册