云计算
云计算从狭义上讲,指IT基础设施的交付和使用模式,即通过网络以按需、易扩展的方式获取所需资源。
广义上则指服务的交付和使用模式,通过网络以按需、易扩展的方式获取所需服务。
提供资源的网络被形象地比喻成“云”,其计算能力通常是由分布式的大规模集群和虚拟化技术提供的。而“云”中的计算资源在用户看来是可以扩展,并且可以随时获取、按需使用的。
根据云计算提供服务资源的类型:
- 基础设施即服务(Infrastructure-as-a-Service,IaaS)
基础设施即服务(IaaS)通过虚拟化和分布式存储等技术,实现了对包括服务器、存储设备、网络设备等各种物理资源的抽象,从而形成了一个可扩展、可按需分配的虚拟资源池 - 平台即服务(Platform-as-a-Service,Paas)
平台即服务(PaaS)为开发者提供了应用的开发环境和运行环境,将开发者从烦琐的IT环境管理中解放出来。自动化应用的部署和运维,使开发者能够集中精力于应用业务开发,极大地提升了应用的开发效率 - 软件即服务(Software-as-a-Service,SaaS)
软件即服务(SaaS)主要面向使用软件的终端用户。一般来说,SaaS将软件功能以特定的接口形式发布,终端用户通过网络浏览器就可以使用软件功能。终端用户将只关注软件业务的使用,除此之外的工作,如软件的升级和云端实现,对终端用户来说都是透明的。
Kubernetes 的基本概念和术语
Kubernetes 的基本概念和术语大多是围绕资源对象 Resource Object 来说的,而资源对象在总体上可分为以下两类:
- 某种资源的对象,例如节点(Node) 、Pod 服务 (Service) 、存储卷(Volume)
- 与资源对象相关的事物与动作,例如标签 Label 、注解 (Annotation) 、命名空间(Namespace)、部署 (Deployment) 、HPA、PVC
资源对象一般包括几个通用属性:版本 、类 Kind 、名称、标签、注解:
(1)资源对象的名称要唯一
(2)资源对象的标签是很重要的数据,也是 Kubernetes 的一大设计特性,比如通过标签来表明资源对象 的特征 、类别,以及通过标签筛选不同的资源对象并实现对象之间的关联控制或协作功能
(3)注解可被理解为一种特殊的标签,不过更多地是与程序挂钩,通常用于实现资源对象属性的自定义扩展。
集群类
集群 (Cluster) 表示一个由 Master Node 组成的 Kubernetes 集群
- Master
Master 指的是集群的控制节点。在每个 Kubemetes 集群中都需要有一个或一组被称为Master 的节点,来负责整个集群的管理和控制。Master 通常占据一个独立的服务器(在高可用部署中建议至少使用3台服务器),是整个集群的“大脑”,如果它发生宕机或者不可用,那么对集群内容器应用的管理都将无法实施。
在Master 上运行着以下关键进程:
(1)Kubemetes API Server(kube-apiserver) :提供 HTTP RESTful API 接口的主要服务,是Kubernetes 里对所有资源进行增、删、查等操作的唯一入口,也是集群控制的入口进程。
(2)Kubernetes Controller Manager ( kube-controller-manager): Kubernetes 里所有资源对象的自动化控制中心 ,可以将其理解为资源对象的“大总管”。
(3)Kubemetes Scheduler (kube-scheduler) :负责资源调度(Pod 调度)的进程,相当千公交公司的调度室。
- Node
Kubemetes 集群中除 Mater 外的其他服务器被称为 Node, Node 在较早的版本中也被称为 Minion,和Master 一样, Node 可以是一台物理主机,也可以是一台虚拟机,Node是Kubemetes 集群中的工作负载节点,每个 Node 都会被 Master 分配一些工作负载 (Docker容器),当某个 Node 宕机时,其上的工作负载会被 Master 自动转移到其他 Node 。在每台Node 上都运行着以下关键进程:
(1)kubelet: 负责 Pod 对应容器的创建、启停等任务,同时与 Master 密切协作,实现集群管理的基本功能
(2)kube-proxy: 实现 Kubemetes Service 的通信与负载均衡机制的服务
(3)容器运行时(如 Docker ):负责本机的容器创建和管理
在默认情况下, kubelet 会向 Master 注册自己,这也是Kubernetes 推荐的 Node 管理方式 。一 Node 被纳入集群管理范畴, kubelet 进程就会定时向 Master 汇报自身的情报,例如操作系统、主机 CPU 和内存使用情况,以及当前有哪些Pod 在运行等,这样 Master 就可以获知每个 Node 的资源使用情况,并实现高效均衡的资源调度策略。而某个 Node 在超过指定时间不上报信息时,会被 Master 判定为“失联”,该Node 的状态就被标记为不可用 (Not Ready), Master 随后会触发”工作负载大转移”的自动流程
我们可以运行以下命令查看在集群中有多少个 Node:
kubectl get nodes
然后通过 kubectl describe node <node_name>命令查看某个 Node 的详细信息:
kubectl describe node k8s-node-l
在集群类里还有一个重要的基础概念一命名空间,它在很多情况下用于实现多租户的资源隔离,典型的一种思路就是给每个租户都分配 个命名空间,命名空间属于Kubernetes 集群范畴的资源对象,在一个集群里可以创建多个命名空间,每个命名空间都是相互独立的存在,属于不同命名空间的资源对象从逻辑上相互隔离,在每个 Kubernetes集群安装完成且正常运行之后, Master 会自动创建两个命名空间,一个是默认的 (default),一个是系统级的 (kube-systern), 用户创建的资源对象如果没有指定命名空间,则被存放在 default 命名空间中;而系统相关的资源对象如网络组件 DNS 组件、监控类组件等,都被安装在 kube-systern 命名空间中
定义命名空间:
apiVersion: vl
kind: Namespace
metadata:
name: development
一旦创建 命名空间 ,我们在 建资源对象 就可以指定这个资源对象属于哪个命名空间。
apiVersion: vl
kind: Pod
metadata:
name: busybox
namespace: development
spec:
containers:
- image: busybox
command:
- sleep
- " 3600 "
name: busybox
如果不加参数 kubectlet 命令将仅显示属于 default 命名空间的资源对象。
可以在 kubectl get 命令中加入-- namespace 参数来操作某个命名空间中的对象。
kubectl get pods
kubectl get pods --namespace=development
应用类
- Service Pod
应用类相关的资源对象主要是围绕 Service (服务)和 Pod 这两个核心对象展开的。
一般说来, Service 指的是无状态服务 ,通常由多个程序副本提供服务 ,在特殊情况下也可以是有状态的单实例服务,比如 MySQL 这种数据存储类的服务 与我们常规理解的服务不同, Kubernetes 里的 Service 具有一个全局唯 的虚拟 ClusterIP 地址,Service 一旦被创建, Kubernetes 就会自动为它分配一个可用的clusterIP 地址,而且在 Service 整个生命周期中,它的 clusterIP 地址都不会改变,客户端可以通过这个虚拟 IP 地址、服务的端口直接访问该服务,再通过部署 Kubernetes 集群的 DNS 服务,就可以实现 Service Name (域名)到 clusterIP 地址的 DNS 映射功能,我们只要使用服务的名称 (DNS 名称 )即可完成到目标服务的访问请求 。“ 服务发现“这个传统架构中的棘手问题在这里首次得以完美解决,同时,凭借clusterIP 地址的独特设计,kubernetes 进一 步实现了 Service 的透明负载均衡和故障自动恢复的高级特性。
Pod是与 Service 密切相关的核心资源对象,Pod是Kubernetes 中最重要的基本概念之一 ,每个 Pod 都有一个特殊的被称为“根容器"的 Pause 容器,Pause 器对应的镜像属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 都还包含一个或多个紧密相关的用户业务容器。
(1)为多进程之间的协作提供 一个抽象模型,使用 Pod 作为基本的调度、复制等管理工作的最小单位,让多个应用进程能一起有效地调度和伸缩。
(2)Pod 里的 多个业务容器共享 Pause 容器的 IP, 共享 Pause 容器挂接的 Volume, 这样既简化了密切关联的业务容器之间的通信问题,也很好地解决了它们之间的文件共享问题。
Kubernete 为每个 Pod 分配了唯一 IP 地址,称之为 Pod IP, 一个 Pod 里的 多个容器共享 Pod IP 地址,Kubernetes 要求底层网络支待集群内任意两个 Pod之间的 TCP/IP直接通信,这通常采用虚拟二层网络技术实现,例如 Flannel Open vSwitch 等,因此我们需要牢记一点在 Kubernetes 里, 一个 Pod 里的容器与另外主机上的 Pod 容器能够直接通信。
Pod 其实有两种类型:普通的 Pod 及静态 Pod (Static Pod) 。后者比较特殊,它并没被存放在 Kubernetes etcd 中,而是被存放在某个具体的 Node 上的 一个具体文件中,并且只能在此 Node 启动、运行,而普通的 Pod 一旦被创建,就会被放入 etcd 中存储,随后被Kubernetes Master 调度到某个具体的 Node 上并绑定(Binding),该Pod 技对应的Node上的 kubelet 进程实例化成一组相关的 Docker 容器并启动。在默认情况下,当 里的某个容器停止时, Kubernetes 会自动检测到这个问题并且重新启动这个 Pod (重启 Pod 里的所有容器),如果 Pod 所在的 Node 宕机,就会将这个 Node 上的所有 Pod 都重新调度到其他节点上。
Endpoint, 代表此 Pod 里的 一个服务进程的对外通信地址,一个 Pod也存在具有多个 Endpoint 的情况,比如 当我们把 Tomcat 定义为一个 Pod时,可以对外暴露管理端口与服务端口这两个 Endpoint.
- Label 与标签选择器
Label (标签)是 Kubernetes 系统中的另一个核心概念,相当于我们熟悉的”标签",一个 Label 是一个 key=value 的键值对,其中的 key value 由用户自己指定。Label 可以被附加到各种资源对象上,例如 Node、Pod、Sevice、Deployment 等,一个资源对象可以定义任意数量的 Label, 同一个 Label 也可以被添加到任意数量的资源对象上, Label 通常在资源对象定义时确定,也可以在对象创建后动态添加或者删除。我们可以通过给指定的资源对象捆绑一个或多个不同的 Label来实现多维度的资源分组管理功能,以便灵活、方便地进行资源分配、调度 、配置、部署等管理工作。
一些常用的 Label 示例如下:
版本标签: release : stable、release : canary
环境标签: environment : dev、 environment : qa、envionment : production
架构标签: tier : frontend、 tier : backend、 tier : middleware
分区标签: partition : customerA、partition : customerB
质量管控标签: track : daily、track : weekly
当前有两种 Label Selector 表达式:基于等式的Selector 表达式和基于集合的Selector 表达式。
基于等式的 Selector 表达式采用等式类表达式匹配标签:
name = redis-slave: 匹配所有具有 name=redis-slave 标签的资源对象
env 1= production: 匹配所有不具有 env=production 标签的资源对象,比如 “env=test"就是满足此条件的标签之一。
基于集合的 Selector 表达式则使用集合操作类表达式匹配标签:
name in ( redis-master,redis-slave) :匹配所有具有 name=redis-master 签或者name= redis-slave 标签的资源对象。
name not in (php-fronlend) :匹配所有不具有 name=php-frontend 标签的 资源对象。
可以通过多个 Label Selector 表达式的组合来实现复杂的条件选择 ,多个表达式之间用“,”进行分隔即可,几个条件之间是 “AND" 的关系,即同时满足多个条件,比如下面的例子:
name=redis-slave,env!=preduction
name not in (php-frontend),env !=production
- Pod Deployment
通常情况下,每个 Service 对应的 Pod 服务实例数量都是固定的,如果一个一个地手工创建Pod 实例,就太麻烦了,最好是用模板的思路,即提供一个 Pod 模板 (Template) ,然后由程序根据我们指定的模板自动创建指定数量的 Pod 实例 。这就是 Deployment 这个资源对象所要完成的事情了。
Deployment有几个很重要的属性:
replicas: Pod 的副本数量
selector: 目标 Pod 的标签选择器
template: 用于自动创建新 Pod 副本的模板
查看 Deploment 信息:
kubectl get deployments
Deployment 资源对象其实还与 ReplicaSet 资源对象密切相关, Kubernetes 内部会根据Deployment 对象自动创建相关联的ReplicaSet 对象,通过以下命令,我们可以看到它的命名与 ployment 的名称有对应关系:
kubectl get replicaset
- Service Cluster lP地址
既然每个 Pod 都会被分配一个单独的 IP 地址,而且每个 Pod 都提供了一个独立的Endpoint (Pod IP-container port) 以被客户端访问,那么现在多个 Pod 副本组成了一个集群来提供服务,客户端如何访问它们呢?传统的做法是部署一个负载均衡器(软件或硬件),为这组 Pod 启一个对外的服务端口如 8000 端口,并且将这些 Pod Endpoint表加入 8000 端口的转发列表中,客户端就可以通过负载均衡器的对外 IP地址+8000 端口访问此服务了。kubernetes 也是类似的做法, Kubernetes 内部在每个 Node 上都运行了一套全局的虚拟负载均衡器,自动注入并自动实时更新集群中所有 Service 的路由表,通过iptables 或者 IPVS 机制 ,把对 Service 的请求转发到其后端对应的某个 Pod 实例上,并在内部实现服务的负载均衡与会话保待机制。 不仅如此, Kubernetes 还采用了一种很巧妙又影响深远的设计一CluterlP 地址。我们知道, pod Endpoint 地址会随着 Pod 的销毁和重新创建而发生改变, 因为新 Pod 的IP 地址与之前旧 Pod 的不同。Service 一旦被创建,Kubernetes 就会自动为它 配一个全局唯一的虚拟 IP 地址——Cluster IP地址,而且在Service 的整个生命周期内 ClusterIP 地址不会发生改变,这样一来,每个服务就变成了具备唯一 IP 地址的通信节点,远程服务之间的通信间题就变成了基础的 TCP 网络通信问题。
服务发现只要用Sevice的Name 与ClusterIP 地址做 DNS 域名映射即可
ClusterIP 地址是一种虚拟 IP 地址,原因有以下几点:
(1)ClusterIP 地址仅仅作用于 Kubemetes Service 这个对象, 并由 Kubemetes 管理和分配IP 地址(来源于 ClusterIP 地址池),与 Node Master 所在的物理网络完全无关。
(2)因为没有一个“实体网络对象”来响应,所以 ClusterIP 地址无法被 Ping通,Cluster IP 地址只能与 Service Port 组成一个具体的服务访问端点,单独的 Cluster IP 不具备 TC IP 通信的基础。
(3)Cluster 属于 Kubernetes 集群这个封闭的空间,集群外的节点要访问这个通信端口,则需要做一些额外的工作。
kubectl get endpoints
#运行下面的命令即可看到 tomcat service 被分配的 clusterIP 地址及更多的信息
kubectl get svc tomcat-service -o yaml
还有一种特殊的 Service- Headless service ,只要在 Service的定义中设置了 ClusterIP: None 就定义了一个 Headless service, 它与普通 service 的关键区别在于它没有 ClusterIP 地址,如果解析 headless service 的DNS 域名,则返回的是该Service 对应的全部 Pod Endpoint 列表,这意味着客户端是直接与后端的Pod建立 TCP/IP连接进行通信的,没有通过虚拟 clusterIP 地址进行转发,因此通信性能最高,等同千”原生网络通信”。
很多服务都存在多个端口,通常一个端口提供业务服务,另一个端口提供管理服务,比如 Mycat、Codis 等常见中间件。 kubernetes Service 支待多个 Endpoint, 在存在多个 endpoint 的情况下,要求每个 Endpoint 都定义一个名称进行区分。
apiVersion: vl
kind: Service
metadata:
name : tomcat-service
spec :
ports:
- port: 8080
name: service-port
- port: 8005
name : shutdown-port
selector:
tier: frontend
- Service 的外网访问问题
服务的 clusterIP 地址在 Kubernetes 集群内才能被访问,那么如何让集群
外的应用访问我们的服务呢?
要弄明白这个问题的解决思路和解决方法,我们需要先弄明白 Kubernetes 的三种 IP:
(1)Node IP: Node IP 地址
Node IP Kubemetes 集群中每个节点的物理网卡的 IP 地址,是 个真实存在
的物理网络,所有属于这个网络的服务器都能通过这个网络直接通信,不管其中是否有部分节点不属于这个 Kubernetes 集群 这也表明 ubernetes 集群之外的节点访问 Kubernetes集群内的某个节点或者 TCP/I 务时,都必须通过 Node IP。
(2)Pod IP: Pod IP 地址
Pod IP 是每个 Pod IP 地址,在使用 Docker 作为容器支持引擎的情况下,它
是Docker Engine 根据 docker0 网桥的 IP 地址段进行分配的,通常是一个虚拟二层网络,前面说过, Kubemetes 要求位于不同 Node上的 Pod 能够彼此直接通信,所以 Kubemetes中一个 Pod 里的容器访问另外一个 Pod 里的容器时, 就是通过 Pod IP 所在的虚拟二层网络进行通信的,而真实的 TCP IP 流量是通过 Node IP 所在的物理网卡流出的
(3)Service IP: Service IP 地址
在Kubernetes 集群内, Service Clus terIP 地址属于集群内的地址,无法在 集群外直接使用这个地址。为了解决这个问题, Kubernetes 首先引入了 NodePort 这个概念, NodePort也是解决集群外的应用访问集群内服务的直接 有效的常见做法。
NodePort 的确功能强大且通用性强,但也存在一个问题 ,即 每个 Service 都需要在 Node上独占一个端口,而端口又是有限的物理资源,那能不能让多个 Service 共用一个对外端口呢?这就是后来增加的 Ingress 资源对象所要解决的问题。在一定程度上,我们可以把Ingress 的实现机制理解为基于 Nginx 的支持虚拟主机的 HTTP 代理
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar. com
http:
paths:
- backend:
serviceName: servicel
servicePort: 80
- host: bar.foo. com
http:
paths:
- backend:
serviceName: service2
servicePort: 80
-
有状态的应用集群
Deployme 对象是用来实现无状态 多副本自动控制功能的,那么有状态的服务,比如 ZooKeeper 集群 、MySQL 高可用集群 (3节点集群)、 Kafka 集群等是怎么实现自动部署和管理的呢?这个问题就复杂多了,这些一开始是依赖 StatefuJSet 解决的,但后来发现对于一些复杂的有状态的集群应用来说, StatefulSet 还是不够通用和强大,所有后面又出现 Kubernetes Operator。 -
批处理应用
批处理应用的特点是一个或多个进程处理一组数据(图像、文件、视频等),在这组数据都处理完成后,批处理任务自动结束。
Jobs 控制器提供了两个控制并发数的参数: completions和parallelism ,
completions表示需要运行任务数的总数, parallelism 表示并发运行的个数,例如设置parallelism 为1,则会依次运行任务 在前面的任务运行后再运行后面的任务。 Job 所控制的 Pod 副本是短暂运行的,可以将其视为 组容器,其中的每个容器都仅运行一次。当 Job 控制的所有 Pod副本都运行结束时,对应的 Job 也就结束了。 -
应用的配置问题
如何解决应用需耍在不同的环境中修改配置的问题呢?这就涉及 ConfigMap 、Secret 两个对象。
用户将配置文件的内容保存到 ConfigMap 中,文 作为 key, value 就是整个
文件的内容,多个配置文件都可被放入 一个 ConfigMap。
在 Pod 里将 ConfigMap 定义为特殊的 volume 进行挂载。在pod被调度到某个具体 Node 上时, ConfigMap 里的 配置文件会被自动还原到本地目录下,然后映射到 Pod 里指定的配置目录 ,这样用户的程序就可以无感知地读取配置了。
在ConfigMap 容发生修改后, kubernetes 会自动重新获取 ConfigMap 的内容
并在目标节点上更新对应的文件。
Secret 也用于解决应用配置的问题,不过它解决的是对敏感信息的配置问题 -
应用的运维问题
HPA ( Horizontal Pod AutoScaler ),将 HPA 理解为 Pod 横向自动扩容,即自动控制Pod数量的增加或减少。
YPA ( Vertical Pod Autoscaler) ,即垂直 Pod 自动扩缩容,它根据容器资源
使用率自动推测并设置 Pod 合理的 CPU 和内存的需求指标,从而更加精确地调度 Pod,实现整体上节省集群资源的目标,因为无须人为操作,因此也进一步提升了运维自动化的水平,VPA 目前属于比较新的特性,也不能与 HPA 共同操控同 一组目标 Pod。
存储类
存储类的资源对象主要包括 Volume 、Persistent Volume 、PVC、StorageClass。
-Volume
Volume 是Pod 中能够被多个容器访问的共享目录。
Volume 的使用也 比较简单,在大多数情况下,我们先在 Pod 上声明一个 Volume,然后在容器里引用该 Volume 并将其挂载 (Mount) 到容器里的某个目 录下。
提供三种volume类型:临时目录、宿主机目录、共享存储
(1)emptyDir
一个 emptyDir 是在 分配到 Node 时创建的。它的初始内容为空,并且无须指定宿主机上对应的目录文件,因为这是 Kubernetes 自动分配的一个目录,当Pod Node 移除时,emptyDir 中的数据也被永久移除。
在默认情况下 ernptyDi 使用的是节点的存储介质,例如磁盘或者网络存储。还可以使用 emptyDir.medium 属性,把这个属性设置为 Memory", 就可 以使用更快的基于内存的后端存储了,需要注意的是,这种情况下的 emptyDir 使用的内存会被计入容器的内存消耗,将受到资源限制和配额机制的管理
(2)hostPath
hostPath 为在 Pod 挂载宿主机上的文件或目录
动态存储管理:
Volume 属于静态管理的存储,即我们需要事先定义每个 Volume ,然后将其挂载到 Pod中去用。
Kubernetes 后面就发展了存储动态化的新机制,来实现存储的自动化管理。相关的核心对象(概念)有三个: Persistent Volume (简称 PV) 、StorageClass、PVC。
PV 表示由系统动态创建 (dynamically provisioned) 的一个存储卷,可以被理解成Kubernetes 集群中某个网络存储对应的一块存储,它与 Volume 类似,但 PV 并不是被定义在Pod 上的,而是独立于 Pod 之外定义的。
StorageClass 用来描述和定义某种存储系统的特征。
PVC正如其名,表示应用希望申请的 PV 规格,其中重要的属性包括 accessModes (存储访问模式)、storag la sName (用哪种 Storage ass 来实现动态创建)及 resources (存储的具体规格)
例子
apiVersion: apps/vl # API 版本
kind: Deployment #副本控制器 RC
metadata:
labels: #标签
app: mysql
name: mysql #对象名称,全局唯一
spec:
replicas: 1 #预期的副本数量
selector:
matchLabels:
app: mysql
template: #Pod 模板
metadata:
label:
app: mysql
spec:
containers: #定义容器
- image: rnysql:5.7
name: mysql
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456 "
创建好 mysql-deploy.yaml 文件后,为了将它发布到 Kubernetes 集群中,我们在 Master上运行如下命令:
kubectl apply -f mysql-deploy.yarnl
#运行 kubectl 命令查看刚刚创建的 Deployment:
kubectl get deploy
#查看 Pod 的创建情况
kubectl get pods
在 Kubernetes 节点的服务器上通过 docker ps 指令查看正在运行的容器,发现提供 MySQL 服务的 Po 容器巳创建且正常运行,并且 MySQL Pod 对应的容器多创建了一个 Pause 容器,该容器就是 Pod 的根容器。
docker ps | grep mysql
apiVersion: vl
kind: Service #表明是 Kubernetes Service
meadata:
name: mysql # Service 的全局唯一名称
spec:
ports:
- port: 3306 # Service 提供服务的端口号
selector: # Service 对应的 Pod 拥有这里定义的标签
app: mysql
我们通过 kubectl create 命令创建 Service 对象:
MySQL 服务被分配了一个值为 10.245.161.22 ClusterIP 地址,在 Kubemetes 集群中新创建的其他 Pod 就可以通过Service ClusterIP +端口号 3306 来连接和访问它了
kubectl create -f mysql-svc.yaml
kubectl get SVC mysql
Kubernetes 会自动将已存在的 Service 对象以环境变量的形式展现在新生成的 Pod 。
apiVersion: apps/vl
kind: Deployment
metadata:
labels:
app: myweb
name: myweb
spec:
replicas: 2
selector:
matchLabels:
app: myweb
template:
metadata:
labels:
app: myweb
spec:
containers:
- image: kubeguide/tomcat-app:vl
name: myweb
ports:
- containerPort: 8080
env:
- name: MYSQL_SERVICE_HOST
value: 10.245.161.22
"type: NodePort" “nodePort: 30001" 表明此 Service 开启了 NodePort 格式的外网访间模式。
apiVersion: vl
kind: Service
metadata:
name: nyweb
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30001
selector:
app: myweb
网友评论