k8s入门篇-资源管理
Kubernetes入门
一、为什么需要Kubernetes
1.1 传统的容器编排痛点
容器技术虽然解决了应用和基础设施异构的问题,让应用可以做到一次构建,多次部署,但在复杂的微服务场景,单靠 Docker 技术还不够,它仍然有以下问题没有解决:
- 集成和编排微服务模块
- 提供按需自动扩容,缩容能力
- 故障自愈
- 集群内的通信
1.2 Kubernetes 能解决的问题
- 按需的垂直扩容,新的服务器(node)能够轻易的增加或删除
- 按需的水平扩容,容器实例能够轻松扩容,缩容
- 副本控制器,你不用担心副本的状态
- 服务发现和路由
- 自动部署和回滚,如果应用状态错误,可以实现自动回滚
1.3 什么时候使用 Kubernetes?
- 应用是微服务架构
- 开发者需要快速部署自己的新功能到测试环境进行验证
- 降低硬件资源成本,提高使用率
1.4 什么时候不适合使用 Kubernetes
- 应用是轻量级的单体应用,没有高并发的需求
- 团队文化不适应变革
二、Kubernetes的发展
- 2014年6月 谷歌云计算专家Eric Brewer在旧金山的发布会为这款新的开源工具揭牌。
- 2015年7月22日K8S迭代到 v 1.0并在OSCON大会上正式对外公布。为了建立容器编排领域的标准和规范,Google、RedHat 等开源基础设施领域玩家们,在 2015 年共同牵头发起了名为 CNCF(Cloud Native Computing Foundation)的基金会。Kubernetes 成为 CNCF 最核心的项目。
发起成员:AT&T, Box, Cisco, Cloud Foundry Foundation, CoreOS, Cycle Computing, Docker, eBay, Goldman Sachs, Google, Huawei, IBM, Intel, Joyent, Kismatic, Mesosphere, Red Hat, Switch SUPERNAP, Twitter, Univa, VMware and Weaveworks。
- 2018年,超过 1700 开发者成为 Kubernetes 项目社区贡献者,全球有 500 多场沙龙。国内出现大量基于 Kubernetes 的创业公司。
- 2020 年,Kubernetes 项目已经成为贡献者仅次于 Linux 项目的第二大开源项目。成为了业界容器编排的事实标准,各大厂商纷纷宣布支持 Kubernetes 作为容器编排的方案。
三、kubernetes组成
3.1 Master节点
- Kube-APIServer:集群的控制中枢,各个模块之间信息交互都需要经过Kube-APIServer,同时它也是集群管理、资源配额、整个集群安全机制的入口。【信息交互,大脑】
- Controller-Manager:集群的状态管理器,保证Pod或其他资源达到期望值,也是需要和APIServer进行通信,在需要的时候创建、更新或删除它所管理的资源。【资源管理,控制】
- Scheduler:集群的调度中心,它会根据指定的一系列条件,选择一个或一批最佳的节点,然后部署我们的Pod。【资源分配,调度】
- Etcd:键值数据库,保存一些集群的信息,一般生产环境中建议部署三个以上节点(奇数个)。【数据存储,存储】
3.2 Node工作节点
Worker、node节点、minion节点
- Kubelet:负责监听节点上Pod的状态,同时负责上报节点和节点上面Pod的状态,负责与Master节点通信,并管理节点上面的Pod。
- Kube-proxy:负责Pod之间的通信和负载均衡,将指定的流量分发到后端正确的机器上。
查看Kube-proxy工作模式:curl 127.0.0.1:10249/proxyMode
Ipvs:监听Master节点增加和删除service以及endpoint的消息,调用Netlink接口创建相应的IPVS规则。通过IPVS规则,将流量转发至相应的Pod上。
Iptables:监听Master节点增加和删除service以及endpoint的消息,对于每一个Service,他都会创建一个iptables规则,将service的clusterIP代理到后端对应的Pod。
3.3 其他组件
- Calico:符合CNI标准的网络插件,给每个Pod生成一个唯一的IP地址,并且把每个节点当做一个路由器。最新Cilium插件,可关注
- CoreDNS:用于Kubernetes集群内部Service的解析,可以让Pod把Service名称解析成IP地址,然后通过Service的IP地址进行连接到对应的应用上。
- Docker:容器引擎,负责对容器的管理。
四、Pod
4.1 Pod是什么
Pod是Kubernetes中最小的单元,它由一组、一个或多个容器组成,每个Pod还包含了一个Pause容器,Pause容器是Pod的父容器,主要负责僵尸进程的回收管理,通过Pause容器可以使同一个Pod里面的多个容器共享存储、网络、PID、IPC等。
4.2 Pod定义
apiVersion: v1 # 必选,API的版本号 kind: Pod # 必选,类型Pod metadata: # 必选,元数据 name: nginx # 必选,符合RFC 1035规范的Pod名称 namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace labels: # 可选,标签选择器,一般用于过滤和区分Pod app: nginx role: frontend # 可以写多个 annotations: # 可选,注释列表,可以写多个 app: nginx #格式要求不是很严格 spec: # 必选,用于定义容器的详细信息 initContainers: # 初始化容器,在容器启动之前执行的一些初始化操作 - command: - sh - -c - echo "I am InitContainer for init some configuration" image: busybox imagePullPolicy: IfNotPresent name: init-container containers: # 必选,容器列表 - name: nginx # 必选,符合RFC 1035规范的容器名称 image: nginx:latest # 必选,容器所用的镜像的地址 imagePullPolicy: Always # 可选,镜像拉取策略 command: # 可选,容器启动执行的命令 - nginx - -g - "daemon off;" workingDir: /usr/share/nginx/html # 可选,容器的工作目录 volumeMounts: # 可选,存储卷配置,可以配置多个 - name: webroot # 存储卷名称 mountPath: /usr/share/nginx/html # 挂载目录 readOnly: true # 只读 ports: # 可选,容器需要暴露的端口号列表 - name: http # 端口名称 containerPort: 80 # 端口号 protocol: TCP # 端口协议,默认TCP env: # 可选,环境变量配置列表 - name: TZ # 变量名 value: Asia/Shanghai # 变量的值 - name: LANG value: en_US.utf8 resources: # 可选,资源限制和资源请求限制 limits: # 最大限制设置 cpu: 1000m memory: 1024Mi requests: # 启动所需的资源 cpu: 100m memory: 512Mi # startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。 # httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 # path: /api/successStart # 检查路径 # port: 80 readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。 httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 path: / # 检查路径 port: 80 # 监控端口 livenessProbe: # 可选,健康检查 #exec: # 执行容器命令检测方式 #command: #- cat #- /health #httpGet: # httpGet检测方式 # path: /_health # 检查路径 # port: 8080 # httpHeaders: # 检查的请求头 # - name: end-user # value: Jason tcpSocket: # 端口检测方式 port: 80 initialDelaySeconds: 60 # 初始化时间 timeoutSeconds: 2 # 超时时间 periodSeconds: 5 # 检测间隔 successThreshold: 1 # 检查成功为2次表示就绪 failureThreshold: 2 # 检测失败1次表示未就绪 lifecycle: postStart: # 容器创建完成后执行的指令, 可以是exec httpGet TCPSocket exec: command: - sh - -c - 'mkdir /data/ ' preStop: httpGet: path: / port: 80 # exec: # command: # - sh # - -c # - sleep 9 restartPolicy: Always # 可选,默认为Always #nodeSelector: # 可选,指定Node节点 # region: subnet7 imagePullSecrets: # 可选,拉取镜像使用的secret,可以配置多个 - name: default-dockercfg-86258 hostNetwork: false # 可选,是否为主机模式,如是,会占用主机端口 volumes: # 共享存储卷列表 - name: webroot # 名称,与上述对应 emptyDir: {} # 挂载目录 #hostPath: # 挂载本机目录 # path: /etc/hosts
4.3 零宕机必备之Pod探针
- StartupProbe:k8s1.16版本后新加的探测方式,用于判断容器内应用程序是否已经启动。如果配置了startupProbe,就会先禁止其他的探测,直到它成功为止,成功后将不在进行探测。【判断容器内的程序是否正常提供服务】
- LivenessProbe:用于探测容器是否运行,如果探测失败,kubelet会根据配置的重启策略进行相应的处理。若没有配置该探针,默认就是success。【判断容器是否运行或者判断容器是否需要重启】
- ReadinessProbe:一般用于探测容器内的程序是否健康,它的返回值如果为success,那么久代表这个容器已经完成启动,并且程序已经是可以接受流量的状态。【判断容器内的程序是否健康】
4.3.1 Pod探针的检测方式
- ExecAction:在容器内执行一个命令,如果返回值为0,则认为容器健康。
- TCPSocketAction:通过TCP连接检查容器内的端口是否是通的,如果是通的就认为容器健康。
- HTTPGetAction:通过应用程序暴露的API地址来检查程序是否是正常的,如果状态码为200~400之间,则认为容器健康。
4.3.2 探针使用场景
- LivenessProbe探针
如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活态探针; kubelet
将根据 Pod 的 restartPolicy
自动执行修复操作。
如果你希望容器在探测失败时被杀死并重新启动,那么请指定一个存活态探针, 并指定 restartPolicy
为 "Always
" 或 "OnFailure
"。
- ReadinessProbe探针
如果要仅在探测成功时才开始向 Pod 发送请求流量,请指定就绪态探针。 在这种情况下,就绪态探针可能与存活态探针相同,但是规约中的就绪态探针的存在意味着 Pod 将在启动阶段不接收任何数据,并且只有在探针探测成功后才开始接收数据。
如果你希望容器能够自行进入维护状态,也可以指定一个就绪态探针, 检查某个特定于就绪态的因此不同于存活态探测的端点。
如果你的应用程序对后端服务有严格的依赖性,你可以同时实现存活态和就绪态探针。 当应用程序本身是健康的,存活态探针检测通过后,就绪态探针会额外检查每个所需的后端服务是否可用。 这可以帮助你避免将流量导向只能返回错误信息的 Pod。
如果你的容器需要在启动期间加载大型数据、配置文件或执行迁移, 你可以使用启动探针。 然而,如果你想区分已经失败的应用和仍在处理其启动数据的应用,你可能更倾向于使用就绪探针。
- StartupProbe探针
对于所包含的容器需要较长时间才能启动就绪的 Pod 而言,启动探针是有用的。 你不再需要配置一个较长的存活态探测时间间隔,只需要设置另一个独立的配置选定, 对启动期间的容器执行探测,从而允许使用远远超出存活态时间间隔所允许的时长。
如果你的容器启动时间通常超出 initialDelaySeconds + failureThreshold × periodSeconds
总值,你应该设置一个启动探测,对存活态探针所使用的同一端点执行检查。 periodSeconds
的默认值是 10 秒。你应该将其 failureThreshold
设置得足够高, 以
便容器有充足的时间完成启动,并且避免更改存活态探针所使用的默认值。 这一设置有助于减少死锁状况的发生。
4.3.3 探针参数
# initialDelaySeconds: 60 # 初始化时间,容器初始化的时间
# timeoutSeconds: 2 # 超时时间
# periodSeconds: 5 # 检测间隔
# successThreshold: 1 # 检查成功为1次表示就绪
# failureThreshold: 2 # 检测失败2次表示未就绪
探针整体设计思路:
由于有些程序可能启动时间比较长,所以新增了StartupProbe探针。一旦启用了StartupProbe探针,其他2个就禁用了,等StartupProbe探针检测完成后,再进行容器存活和容器ready检测。
4.4 pod的退出流程
pod退出的流程,当用户执行删除pod操作时:
1、pod的状态变为terminating
2、endpoint中删除该pod的ip
3、执行prestop命令,进行pod退出前的一些清理操作
优雅退出默认时间:30s
terminationGracePeriodSeconds: 30
如果我们希望更长,可以进行配置;或者命令行 kubectl delete pod nginx --grace-period=40
4.5 pod实践
定义一个pod
apiVersion: v1 # 必选,API的版本号 kind: Pod # 必选,类型Pod metadata: # 必选,元数据 name: nginx # 必选,符合RFC 1035规范的Pod名称 namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace labels: # 可选,标签选择器,一般用于过滤和区分Pod app: nginx role: frontend # 可以写多个 annotations: # 可选,注释列表,可以写多个 app: nginx spec: # 必选,用于定义容器的详细信息 containers: # 必选,容器列表 - name: nginx # 必选,符合RFC 1035规范的容器名称 image: nginx:1.15.2 # 必选,容器所用的镜像的地址 imagePullPolicy: IfNotPresent # 可选,镜像拉取策略, IfNotPresent: 如果宿主机有这个镜像,那就不需要拉取了. Always: 总是拉取, Never: 不管是否存储都不拉去 command: # 可选,容器启动执行的命令 ENTRYPOINT, arg --> cmd - nginx - -g - "daemon off;" workingDir: /usr/share/nginx/html # 可选,容器的工作目录 ports: # 可选,容器需要暴露的端口号列表 - name: http # 端口名称 containerPort: 80 # 端口号 protocol: TCP # 端口协议,默认TCP env: # 可选,环境变量配置列表 - name: TZ # 变量名 value: Asia/Shanghai # 变量的值 - name: LANG value: en_US.utf8 #exec: # 执行容器命令检测方式 #command: #- cat #- /health startupProbe: tcpSocket: port: 80
创建pod
[root@k8s-master01 ~]# kubectl apply -f nginx-pod.yaml pod/nginx created
查看pod
[root@k8s-master01 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 32s
查看pod实时动态
kubectl get pod -w
kubectl
五、RC和RS
Replication Controller(复制控制器,RC)和ReplicaSet(复制集,RS)是两种简单部署Pod的方式。因为在生产环境中,主要使用更高级的Deployment等方式进行Pod的管理和部署,所以本节只对Replication Controller和Replica Set的部署方式进行简单介绍。
5.1 Replication Controller
Replication Controller(简称RC)可确保Pod副本数达到期望值,也就是RC定义的数量。换句话说,Replication Controller可确保一个Pod或一组同类Pod总是可用。
如果存在的Pod大于设定的值,则Replication Controller将终止额外的Pod。如果太小,Replication Controller将启动更多的Pod用于保证达到期望值。与手动创建Pod不同的是,用Replication Controller维护的Pod在失败、删除或终止时会自动替换。因此即使应用程序只需要一个Pod,也应该使用Replication Controller或其他方式管理。Replication Controller类似于进程管理程序,但是Replication Controller不是监视单个节点上的各个进程,而是监视多个节点上的多个Pod。
定义一个Replication Controller的示例如下。
apiVersion: v1 kind: ReplicationController metadata: name: nginx spec: replicas: 3 selector: app: nginx template: metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80
5.2 ReplicaSet
ReplicaSet是支持基于集合的标签选择器的下一代Replication Controller,它主要用作Deployment协调创建、删除和更新Pod,和Replication Controller唯一的区别是,ReplicaSet支持标签选择器。在实际应用中,虽然ReplicaSet可以单独使用,但是一般建议使用Deployment来自动管理ReplicaSet,除非自定义的Pod不需要更新或有其他编排等。
定义一个ReplicaSet的示例如下:
apiVersion: apps/v1 kind: ReplicaSet metadata: name: frontend labels: app: guestbook tier: frontend spec: # modify replicas according to your case replicas: 3 selector: matchLabels: tier: frontend matchExpressions: - {key: tier, operator: In, values: [frontend]} template: metadata: labels: app: guestbook tier: frontend spec: containers: - name: php-redis image: gcr.io/google_samples/gb-frontend:v3 resources: requests: cpu: 100m memory: 100Mi env: - name: GET_HOSTS_FROM value: dns # If your cluster config does not include a dns service, then to # instead access environment variables to find service host # info, comment out the 'value: dns' line above, and uncomment the # line below. # value: env ports: - containerPort: 80
Replication Controller和ReplicaSet的创建删除和Pod并无太大区别,Replication Controller目前几乎已经不在生产环境中使用,ReplicaSet也很少单独被使用,都是使用更高级的资源Deployment、DaemonSet、StatefulSet进行管理Pod。
六、Deployment
用于部署无状态的服务,这个最常用的控制器。一般用于管理维护企业内部无状态的微服务,比如configserver、zuul、springboot。他可以管理多个副本的Pod实现无缝迁移、自动扩容缩容、自动灾难恢复、一键回滚等功能。
6.1 创建一个Deployment
手动创建:
kubectl create deployment nginx --image=nginx:1.15.2
从文件创建:
# cat nginx-deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "1" creationTimestamp: "2020-09-19T02:41:11Z" generation: 1 labels: app: nginx name: nginx namespace: default spec: progressDeadlineSeconds: 600 replicas: 2 #副本数 revisionHistoryLimit: 10 # 历史记录保留的个数 selector: matchLabels: app: nginx strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx:1.15.2 imagePullPolicy: IfNotPresent name: nginx resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30
从文件创建:
kubelet apply -f nginx-deploy.yaml
查看deployment
[root@k8s-master01 ~/k8s]# kubectl get deploy -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR nginx 2/2 2 2 3m42s nginx nginx:1.15.2 app=nginx
- NAME: Deployment名称
- READY:Pod的状态,已经Ready的个数
- UP-TO-DATE:已经达到期望状态的被更新的副本数
- AVAILABLE:已经可以用的副本数
- AGE:显示应用程序运行的时间
- CONTAINERS:容器名称
- IMAGES:容器的镜像
- SELECTOR:管理的Pod的标签
可以直接通过修改replicas数量来动态调整pod的数量,pod创建后,不可动态修改labels,需要删掉pod后,重建pod才行。
6.2 Deployment的更新
更改deployment的镜像并记录:
kubectl set image deploy nginx nginx=nginx:1.15.3 –record
查看更新过程:
# kubectl rollout status deploy nginx deployment "nginx" successfully rolled out [root@k8s-master01 ~]# kubectl rollout status deploy nginx Waiting for deployment "nginx" rollout to finish: 1 out of 2 new replicas have been updated... Waiting for deployment "nginx" rollout to finish: 1 out of 2 new replicas have been updated... Waiting for deployment "nginx" rollout to finish: 1 out of 2 new replicas have been updated... Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination... deployment "nginx" successfully rolled out
或者使用describe查看:
# kubectl describe deploy nginx Normal ScalingReplicaSet 25m deployment-controller Scaled up replica set nginx-66bbc9fdc5 to 1 Normal ScalingReplicaSet 18m (x2 over 23m) deployment-controller Scaled up replica set nginx-66bbc9fdc5 to 2 Normal ScalingReplicaSet 7m7s deployment-controller Scaled up replica set nginx-5dfc8689c6 to 1 Normal ScalingReplicaSet 6m28s (x2 over 23m) deployment-controller Scaled down replica set nginx-66bbc9fdc5 to 1 Normal ScalingReplicaSet 6m27s deployment-controller Scaled up replica set nginx-5dfc8689c6 to 2 Normal ScalingReplicaSet 5m58s deployment-controller Scaled down replica set nginx-66bbc9fdc5 to 0 Normal ScalingReplicaSet 4m19s deployment-controller Scaled up replica set nginx-6cdd5dd489 to 1 Normal ScalingReplicaSet 3m44s deployment-controller Scaled down replica set nginx-5dfc8689c6 to 1 Normal ScalingReplicaSet 3m44s deployment-controller Scaled up replica set nginx-6cdd5dd489 to 2 Normal ScalingReplicaSet 3m6s deployment-controller Scaled down replica set nginx-5dfc8689c6 to 0
6.3 Deployment的回滚
# 执行更新操作
模拟操作一个不存在或者错误的镜像:
[root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:787977da --record deployment.apps/nginx image updated [root@k8s-master01 ~]# kubectl get po NAME READY STATUS RESTARTS AGE nginx-6cdd5dd489-lv28z 1/1 Running 0 7m12s nginx-6cdd5dd489-nqqz7 1/1 Running 0 6m37s nginx-7d79b96f68-x7t67 0/1 ContainerCreating 0 19s
查看历史版本
[root@k8s-master01 ~]# kubectl rollout history deploy nginx deployment.apps/nginx REVISION CHANGE-CAUSE 1 <none> 2 kubectl set image deploy nginx nginx=nginx:1.15.3 --record=true 3 kubectl set image deploy nginx nginx=nginx:1.15.4 --record=true 4 kubectl set image deploy nginx nginx=nginx:787977da --record=true
回滚到上一个版本
[root@k8s-master01 ~]# kubectl rollout undo deploy nginx deployment.apps/nginx rolled back
查看回滚结果
[root@k8s-master01 ~]# kubectl get po NAME READY STATUS RESTARTS AGE nginx-6cdd5dd489-lv28z 1/1 Running 0 9m8s nginx-6cdd5dd489-nqqz7 1/1 Running 0 8m33s [root@k8s-master01 ~]# kubectl get deploy nginx -oyaml | grep nginx kubernetes.io/change-cause: kubectl set image deploy nginx nginx=nginx:1.15.4 app: nginx k:{"name":"nginx"}: k:{"name":"nginx"}: name: nginx selfLink: /apis/apps/v1/namespaces/default/deployments/nginx app: nginx app: nginx - image: nginx:1.15.4 name: nginx message: ReplicaSet "nginx-6cdd5dd489" has successfully progressed.
进行多次更新
[root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:787977da --record deployment.apps/nginx image updated [root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:787977dadaa --record deployment.apps/nginx image updated [root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:787977xxxxxdadaa --record deployment.apps/nginx image updated [root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:787977dadxxxxxdadaa --record deployment.apps/nginx image updated [root@k8s-master01 ~]# # 查看历史记录 [root@k8s-master01 ~]# kubectl rollout history deploy nginx deployment.apps/nginx REVISION CHANGE-CAUSE 1 <none> 2 kubectl set image deploy nginx nginx=nginx:1.15.3 --record=true 5 kubectl set image deploy nginx nginx=nginx:1.15.4 --record=true 6 kubectl set image deploy nginx nginx=nginx:787977da --record=true 7 kubectl set image deploy nginx nginx=nginx:787977dadaa --record=true 8 kubectl set image deploy nginx nginx=nginx:787977xxxxxdadaa --record=true 9 kubectl set image deploy nginx nginx=nginx:787977dadxxxxxdadaa --record=true
查看指定版本的详细信息
[root@k8s-master01 ~]# kubectl rollout history deploy nginx --revision=5 deployment.apps/nginx with revision #5 Pod Template: Labels: app=nginx pod-template-hash=6cdd5dd489 Annotations: kubernetes.io/change-cause: kubectl set image deploy nginx nginx=nginx:1.15.4 --record=true Containers: nginx: Image: nginx:1.15.4 Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none>
回滚到任意指定版本
[root@k8s-master01 ~]# kubectl rollout undo deploy nginx --to-revision=5 deployment.apps/nginx rolled back
查看deploy状态
[root@k8s-master01 ~]# kubectl get deploy -oyaml
6.4 Deployment的暂停
Deployment 暂停功能
[root@k8s-master01 ~]# kubectl rollout pause deployment nginx deployment.apps/nginx paused
暂停后多次配置
第一次配置
修改deploy镜像
[root@k8s-master01 ~]# kubectl set image deploy nginx nginx=nginx:1.15.3 --record deployment.apps/nginx image updated
第二次配置
暂停后添加内存CPU配置
[root@k8s-master01 ~]# kubectl set resources deploy nginx -c nginx --limits=cpu=200m,memory=128Mi --requests=cpu=10m,memory=16Mi deployment.apps/nginx resource requirements updated [root@k8s-master01 ~]# kubectl get deploy nginx -oyaml apiVersion: apps/v1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "11" kubernetes.io/change-cause: kubectl set image deploy nginx nginx=nginx:1.15.3 --record=true creationTimestamp: "2020-09-19T02:41:11Z" generation: 18 labels: app: nginx name: nginx namespace: default resourceVersion: "2660534" selfLink: /apis/apps/v1/namespaces/default/deployments/nginx uid: 1d9253a5-a36c-48cc-aefe-56f95967db66 spec: paused: true progressDeadlineSeconds: 600 replicas: 2 revisionHistoryLimit: 10 selector: matchLabels: app: nginx strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx:1.15.3 imagePullPolicy: IfNotPresent name: nginx resources: limits: cpu: 200m memory: 128Mi requests: cpu: 10m memory: 16Mi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 status: availableReplicas: 2 conditions: - lastTransitionTime: "2020-09-19T03:26:50Z" lastUpdateTime: "2020-09-19T03:26:50Z" message: Deployment has minimum availability. reason: MinimumReplicasAvailable status: "True" type: Available - lastTransitionTime: "2020-09-19T03:30:15Z" lastUpdateTime: "2020-09-19T03:30:15Z" message: Deployment is paused reason: DeploymentPaused status: Unknown type: Progressing observedGeneration: 18 readyReplicas: 2 replicas: 2
查看pod是否被更新
[root@k8s-master01 ~]# kubectl get po NAME READY STATUS RESTARTS AGE nginx-6cdd5dd489-lv28z 1/1 Running 0 30m nginx-6cdd5dd489-nqqz7 1/1 Running 0 30m
6.5 Deployment的恢复
[root@k8s-master01 ~]# kubectl rollout resume deploy nginx deployment.apps/nginx resumed [root@k8s-master01 ~]# kubectl get rs NAME DESIRED CURRENT READY AGE nginx-5475c49ffb 0 0 0 21m nginx-5dfc8689c6 0 0 0 33m nginx-66bbc9fdc5 0 0 0 52m nginx-68db656dd8 1 1 0 15s nginx-6cdd5dd489 2 2 2 31m nginx-799b8478d4 0 0 0 21m nginx-7d79b96f68 0 0 0 24m nginx-f974656f7 0 0 0 21m
6.6 Deployment的扩缩容
kubectl scale --replicas=1 deploy nginx
扩缩容不会增加rs,因为他只是增加或减少某个rs下的pod数量。
6.7 Deployment的配置项
- .spec.revisionHistoryLimit:设置保留RS旧的revision的个数,设置为0的话,不保留历史数据
- .spec.minReadySeconds:可选参数,指定新创建的Pod在没有任何容器崩溃的情况下视为Ready最小的秒数,默认为0,即一旦被创建就视为可用。
滚动更新的策略:
.spec.strategy.type:更新deployment的方式,默认是RollingUpdate
- RollingUpdate:滚动更新,可以指定maxSurge和maxUnavailable
maxUnavailable:指定在回滚或更新时最大不可用的Pod的数量,可选字段,默认25%,可以设置成数字或百分比,如果该值为0,那么maxSurge就不能0。
maxSurge:可以超过期望值的最大Pod数,可选字段,默认为25%,可以设置成数字或百分比,如果该值为0,那么maxUnavailable不能为0
假如副本4个,如果最大不可用设置成0,最大期望也是0,那就没法滚动了。最大不可用至少为1,最大期望值可以是0或者以上的值,才能进行滚动;
同理,最大期望如果设置成0,则最大不可用至少必须设置1,才能进行滚动。
- Recreate:重建,先删除旧的Pod,再创建新的Pod
七、StatefulSet
StatefulSet(有状态集,缩写为sts)常用于部署有状态的且需要有序启动的应用程序,比如在进行SpringCloud项目容器化时,Eureka的部署是比较适合用StatefulSet部署方式的,可以给每个Eureka实例创建一个唯一且固定的标识符,并且每个Eureka实例无需配置多余的Service,其余Spring Boot应用可以直接通过Eureka的Headless Service即可进行注册。
Eureka的statefulset的资源名称是eureka,eureka-0 eureka-1 eureka-2 Service:headless service,没有ClusterIP eureka-svc Eureka-0.eureka-svc.NAMESPACE_NAME eureka-1.eureka-svc.NAMESPACE_NAME eureka-N-1.eureka-svc......
7.1 StatefulSet的基本概念
StatefulSet主要用于管理有状态应用程序的工作负载API对象。比如在生产环境中,可以部署ElasticSearch集群、MongoDB集群或者需要持久化的RabbitMQ集群、Redis集群、Kafka集群和ZooKeeper集群等。
和Deployment类似,一个StatefulSet也同样管理着基于相同容器规范的Pod。不同的是,StatefulSet为每个Pod维护了一个粘性标识。这些Pod是根据相同的规范创建的,但是不可互换,每个Pod都有一个持久的标识符,在重新调度时也会保留,一般格式为StatefulSetName-Number。比如定义一个名字是Redis-Sentinel的StatefulSet,指定创建三个Pod,那么创建出来的Pod名字就为Redis-Sentinel-0、Redis-Sentinel-1、Redis-Sentinel-2。而StatefulSet创建的Pod一般使用Headless Service(无头服务)进行通信,和普通的Service的区别在于Headless Service没有ClusterIP,它使用的是Endpoint进行互相通信,Headless一般的格式为:
statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local。
说明:
- serviceName为Headless Service的名字,创建StatefulSet时,必须指定Headless Service名称;
- 0..N-1为Pod所在的序号,从0开始到N-1;
- statefulSetName为StatefulSet的名字;
- namespace为服务所在的命名空间;
- .cluster.local为Cluster Domain(集群域)。
假如公司某个项目需要在Kubernetes中部署一个主从模式的Redis,此时使用StatefulSet部署就极为合适,因为StatefulSet启动时,只有当前一个容器完全启动时,后一个容器才会被调度,并且每个容器的标识符是固定的,那么就可以通过标识符来断定当前Pod的角色。
比如用一个名为redis-ms的StatefulSet部署主从架构的Redis,第一个容器启动时,它的标识符为redis-ms-0,并且Pod内主机名也为redis-ms-0,此时就可以根据主机名来判断,当主机名为redis-ms-0的容器作为Redis的主节点,其余从节点,那么Slave连接Master主机配置就可以使用不会更改的Master的Headless Service,此时Redis从节点(Slave)配置文件如下:
port 6379 slaveof redis-ms-0.redis-ms.public-service.svc.cluster.local 6379 tcp-backlog 511 timeout 0 tcp-keepalive 0 ……
其中redis-ms-0.redis-ms.public-service.svc.cluster.local是Redis Master的Headless Service,在同一命名空间下只需要写redis-ms-0.redis-ms即可,后面的public-service.svc.cluster.local可以省略。
7.2 StatefulSet注意事项
一般StatefulSet用于有以下一个或者多个需求的应用程序:
- 需要稳定的独一无二的网络标识符。
- 需要持久化数据。
- 需要有序的、优雅的部署和扩展。
- 需要有序的自动滚动更新。
StatefulSet注意事项
- 如果应用程序不需要任何稳定的标识符或者有序的部署、删除或者扩展,应该使用无状态的控制器部署应用程序,比如Deployment或者ReplicaSet。
- StatefulSet是Kubernetes 1.9版本之前的beta资源,在1.5版本之前的任何Kubernetes版本都没有。
- Pod所用的存储必须由PersistentVolume Provisioner(持久化卷配置器)根据请求配置StorageClass,或者由管理员预先配置,当然也可以不配置存储。
- 为了确保数据安全,删除和缩放StatefulSet不会删除与StatefulSet关联的卷,可以手动选择性地删除PVC和PV(关于PV和PVC请参考2.2.12节)。
- StatefulSet目前使用Headless Service(无头服务)负责Pod的网络身份和通信,需要提前创建此服务。
- 删除一个StatefulSet时,不保证对Pod的终止,要在StatefulSet中实现Pod的有序和正常终止,可以在删除之前将StatefulSet的副本缩减为0。
7.3 创建一个StatefulSet
[root@k8s-master01 ~/k8s]# cat nginx-sts.yaml apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: serviceName: "nginx" replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.15.2 ports: - containerPort: 80 name: web
创建statefulset
[root@k8s-master01 ~/k8s]# kubectl apply -f nginx-sts.yaml service/nginx created statefulset.apps/web created
查看statefulset的svc
web-1 1/1 Running 0 10s [root@k8s-master01 ~/k8s]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 192.168.0.1 <none> 443/TCP 21d nginx ClusterIP None <none> 80/TCP 18s
新创建的statefulset的svc是一个无头服务,也就是他没有ep,直接可以通过svc进行访问服务,这样就少了一层代理。
我们直接通过服务访问后端pod,启动一个busybox:
cat<<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: busybox namespace: default spec: containers: - name: busybox image: busybox:1.28 command: - sleep - "3600" imagePullPolicy: IfNotPresent restartPolicy: Always EOF
对服务进程访问
[root@k8s-master01 ~/k8s]# kubectl get pods -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES busybox 1/1 Running 0 38s 172.17.125.14 k8s-node01 <none> <none> nginx 1/1 Running 0 120m 172.25.244.200 k8s-master01 <none> <none> nginx-5dfc8689c6-bdxk7 1/1 Running 0 65m 172.27.14.195 k8s-node02 <none> <none> web-0 1/1 Running 0 3m53s 172.25.92.71 k8s-master02 <none> <none> web-1 1/1 Running 0 3m52s 172.17.125.13 k8s-node01 <none> <none> [root@k8s-master01 ~/k8s]# kubectl exec -it busybox sh kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. / # ping web-0.nginx.default PING web-0.nginx.default (172.25.92.71): 56 data bytes 64 bytes from 172.25.92.71: seq=0 ttl=62 time=0.244 ms
可以看到,我们通过statefulset-name-0.svc-name.namespace.svc.cluster.local进行服务访问。
7.4 statefulset特征
1、启动的时候,一定是web-0启动成功后,才会启动web-1;同样,删除的时候,是从最后一个开始删,删除最后一个后,再删除倒数第二个。
7.5 statfulset更新
apiVersion: apps/v1 kind: StatefulSet metadata: annotations: name: web namespace: default spec: replicas: 2 revisionHistoryLimit: 10 selector: matchLabels: app: nginx serviceName: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx:1.15.2 imagePullPolicy: IfNotPresent name: nginx ports: - containerPort: 80 name: web protocol: TCP resources: limits: cpu: 1000m memory: 100Mi requests: cpu: 10m memory: 10Mi dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 updateStrategy: rollingUpdate: partition: 0 type: RollingUpdate
更新策略:滚动更新
7.6 statfulset灰度发布
partition参数设置
apiVersion: apps/v1 kind: StatefulSet metadata: annotations: name: web namespace: default spec: replicas: 5 revisionHistoryLimit: 10 selector: matchLabels: app: nginx serviceName: nginx template: metadata: labels: app: nginx type: statefulset spec: containers: - image: nginx:1.15.2 imagePullPolicy: IfNotPresent name: nginx ports: - containerPort: 80 name: web protocol: TCP resources: limits: cpu: 1000m memory: 100Mi requests: cpu: 10m memory: 10Mi dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 updateStrategy: rollingUpdate: partition: 3 # 从第三个pod开始更新 type: RollingUpdate
7.7 statfulset删除和级联删除
级联删除:删除statefulset的同时删除pod(默认)
kubectl delete sts web
非级联删除:删除statefulset的同时不删除pod
kubectl delete sts web --cascade=false
这样删除会出现孤儿pod,即pod无法管理了,删除pod后就没了。
7.8 statfulset更新和回滚
statefulset更新:
kubectl set image sts web nginx=nginx:1.15.1 --record=true
statefulset回滚:
#查看历史版本 kubectl rollout history sts web #回滚到上一个版本 kubectl rollout undo sts web
statefulset回滚到任意指定版本:
#查看历史版本 kubectl rollout history sts web #查看当前镜像 kubectl get pods -l type=statefulset -o yaml|grep image #回滚到指定版本 kubectl rollout undo sts web --to-revision=14 #查看当前镜像 kubectl get pods -l type=statefulset -o yaml|grep image
九、DaemoSet
9.1 DaemonSet是什么?
DaemonSet:守护进程集,缩写为ds,在所有节点或者是匹配的节点上都部署一个Pod。
使用DaemonSet的场景
- 运行集群存储的daemon,比如ceph或者glusterd
- 节点的CNI网络插件,calico
- 节点日志的收集:fluentd或者是filebeat
- 节点的监控:node exporter
- 服务暴露:部署一个ingress nginx
9.2 定义一个DaemonSet
apiVersion: apps/v1 kind: DaemonSet metadata: annotations: name: web namespace: default spec: selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: nodeSelector: ds: "true" containers: - image: nginx:1.15.2 imagePullPolicy: IfNotPresent name: nginx ports: - containerPort: 80 name: web protocol: TCP resources: limits: cpu: 1000m memory: 100Mi requests: cpu: 10m memory: 10Mi dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30
其中:nodeSelector用于节点选择。
kubectl label node k8s-node01 ds=true
节点打上标签后就会在上面创建对应的pod。
9.3 DaemonSet更新和回滚
Daemonset更新
Daemonset回滚
9.4 DaemonSet更新策略
#滚动更新 updateStrategy: rollingUpdate: maxSurge: 0 maxUnavailable: 1 type: RollingUpdate #即使删除 updateStrategy: rollingUpdate: maxSurge: 0 maxUnavailable: 1 type: OnDelete
建议使用OnDelete方式,删除某个pod后,进行更新,查看没问题后,全部更新。【灰度更新方式】
十、HPA(水平pod扩缩容)
10.1 HPA实践
DaemonSet无法自动扩缩容,他的初衷就是每个node部署一个。
1、创建deloyment
kubectl create deployment nginx-server-hpa --image=nginx:1.15.2 --port=80 --dry-run=client -o yaml>hpa-deloy.yaml
2、增加reources
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx-server-hpa name: nginx-server-hpa spec: replicas: 1 selector: matchLabels: app: nginx-server-hpa strategy: {} template: metadata: creationTimestamp: null labels: app: nginx-server-hpa spec: containers: - image: nginx:1.15.2 name: nginx ports: - containerPort: 80 resources: requests: cpu: 10m status: {}
3、暴露服务
[root@k8s-master01 ~/k8s]# kubectl expose deployment nginx-server-hpa --port=80 service/nginx-server-hpa exposed
4、查看服务并访问
[root@k8s-master01 ~/k8s]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 192.168.0.1 <none> 443/TCP 24d nginx ClusterIP None <none> 80/TCP 2d13h nginx-server-hpa ClusterIP 192.168.166.198 <none> 80/TCP 5s
5、创建hpa
[root@k8s-master01 ~/k8s]# kubectl autoscale deployment nginx-server-hpa --cpu-percent=10 --min=1 --max=10 horizontalpodautoscaler.autoscaling/nginx-server-hpa autoscaled
查看hpa
[root@k8s-master01 ~/k8s]# kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE nginx-server-hpa Deployment/nginx-server-hpa <unknown>/10% 1 10 0 6s
再次查看
[root@k8s-master01 ~/k8s]# kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE nginx-server-hpa Deployment/nginx-server-hpa 0%/10% 1 10 1 78s
10.2 HPA注意事项
注意事项: 1、必须安装metrics-server或其他自定义metrics-server 2、必须配置requests参数 3、不能扩容无法缩放的对象,比如DaemonSet 4、要考虑压力的根本原因,假如是后端的瓶颈,我们扩容front,是没有作用的。 此时,需要后端提供压力接口才能进行扩缩容。
十一、服务发布
11.1 label和selector
Label:对k8s中各种资源进行分类、分组,添加一个具有特别属性的一个标签。
Selector:通过一个过滤的语法进行查找到对应标签的资源
11.2 label操作
#创建标签 kubectl label pods nginx unhealthy=true #修改标签 kubectl label --overwrite pods nginx status=unhealthy #删除标签 kubectl label pods nginx app- #过滤资源 kubectl get pods -l 'app in (nginx,nginx-server-hpa)' -owide --show-labels kubectl get pods -l 'app in (nginx,nginx-server-hpa)',controller-revision-hash!=web-cdd4c789b -owide --show-labels
11.3 service
在k8s中,service用于东西流量的实现,而南北流量则是通过ingress实现。
11.3.1 service定义
Service可以简单的理解为逻辑上的一组Pod。一种可以访问Pod的策略,而且其他Pod可以通过这个Service访问到这个Service代理的Pod。相对于Pod而言,它会有一个固定的名称,一旦创建就固定不变。
service创建后,同时会创建一个同名的EP(endpoint),也就是podIP:port的记录,记录了service调度到后端的信息。
11.3.2 创建一个service
# cat nginx-svc.yaml apiVersion: v1 kind: Service metadata: labels: app: nginx-svc name: nginx-svc spec: ports: - name: http # Service端口的名称 port: 80 # Service自己的端口, servicea --> serviceb http://serviceb, http://serviceb:8080 protocol: TCP # UDP TCP SCTP default: TCP targetPort: 80 # 后端应用的端口 - name: https port: 443 protocol: TCP targetPort: 443 selector: app: nginx sessionAffinity: None type: ClusterIP
11.3.3 为什么要有service?
访问服务时,我们可以通过svc直接访问后端的pod,因为pod经常创建和删除,为了保证服务一直连接,而不关心后端pod,所以引进了svc。
service ==> endpoint ==> pod
11.3.4 使用Service代理k8s外部应用
使用场景:
- 希望在生产环境中使用某个固定的名称而非IP地址进行访问外部的中间件服务
- 希望Service指向另一个Namespace中或其他集群中的服务
- 某个项目正在迁移至k8s集群,但是一部分服务仍然在集群外部,此时可以使用service代理至k8s集群外部的服务
通过service反代外部服务,我们可以统一配置文件,即使从外部迁移到容器内部,也不需要修改配置文件,只需要修改EP的地址!非常方便。
# cat nginx-svc-external.yaml apiVersion: v1 kind: Service metadata: labels: app: nginx-svc-external name: nginx-svc-external spec: ports: - name: http # Service端口的名称 port: 80 # Service自己的端口, servicea --> serviceb http://serviceb, http://serviceb:8080 protocol: TCP # UDP TCP SCTP default: TCP targetPort: 8081 # 后端应用的端口 sessionAffinity: None type: ClusterIP #创建好了svc后,ep不会自动创建,需要我们手动创建一个ep,指向后端代理的服务。我们这里使用baidu的地址来测试。 # cat nginx-ep-external.yaml apiVersion: v1 kind: Endpoints metadata: labels: app: nginx-svc-external name: nginx-svc-external namespace: default subsets: - addresses: - ip: 140.205.94.189 ports: - name: http port: 8081 protocol: TCP
测试:
11.3.5 使用Service代理域名
apiVersion: v1 kind: Service metadata: labels: app: nginx-externalname name: nginx-externalname spec: type: ExternalName externalName: www.baidu.com
注意:说明: ExternalName 服务接受 IPv4 地址字符串,但作为包含数字的 DNS 名称,而不是 IP 地址。实测下来,这里使用IP地址不行
11.3.6 service的常见类型
- ClusterIP:在集群内部使用,也是默认值。
- ExternalName:通过返回定义的CNAME别名。一定要使用域名!
- NodePort:在所有安装了kube-proxy的节点上打开一个端口,此端口可以代理至后端Pod,然后集群外部可以使用节点的IP地址和NodePort的端口号访问到集群Pod的服务。NodePort端口范围默认是30000-32767。
- LoadBalancer:使用云提供商的负载均衡器公开服务。
11.4 Ingress
11.4.1 Ingress安装
通俗来讲,ingress和之前提到的Service、Deployment,也是一个k8s的资源类型,ingress用于实现用域名的方式访问k8s内部应用。
首先安装helm管理工具:https://helm.sh/docs/intro/install/
使用helm安装ingress:https://kubernetes.github.io/ingress-nginx/deploy/#using-helm
添加ingress的helm仓库(课程讲解的版本已经上传至百度网盘)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
下载ingress的helm包至本地
helm pull ingress-nginx/ingress-nginx
tar xf ingress-nginx-3.6.0.tgz cd ingress-nginx vim values.yaml
更改对应的配置
- a) Controller和admissionWebhook的镜像地址,需要将公网镜像同步至公司内网镜像仓库(和课程不一致的版本,需要自行同步gcr镜像的,可以百度查一下使用阿里云同步gcr的镜像,也可以参考这个连接https://blog.csdn.net/weixin_39961559/article/details/80739352,或者参考这个连接: https://blog.csdn.net/sinat_35543900/article/details/103290782)
- b) hostNetwork设置为true
- c) dnsPolicy设置为 ClusterFirstWithHostNet
- d) NodeSelector添加ingress: "true"部署至指定节点
- e) 类型更改为kind: DaemonSet
部署ingress
给需要部署ingress的节点上打标签
kubectl label node k8s-master03 ingress=true kubectl create ns ingress-nginx helm install ingress-nginx -n ingress-nginx .
- 将ingress controller部署至Node节点(ingress controller不能部署在master节点,需要安装视频中的步骤将ingress controller部署至Node节点,生产环境最少三个ingress controller,并且最好是独立的节点)
kubectl label node k8s-node01 ingress=true
kubectl label node k8s-master03 ingress-
11.4.2 Ingress入门使用
apiVersion: networking.k8s.io/v1beta1 # networking.k8s.io/v1 / extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: "nginx" name: example spec: rules: # 一个Ingress可以配置多个rules - host: foo.bar.com # 域名配置,可以不写,匹配*, *.bar.com http: paths: # 相当于nginx的location配合,同一个host可以配置多个path / /abc - backend: serviceName: nginx-svc servicePort: 80 path: / - host: foo2.bar.com # 域名配置,可以不写,匹配*, *.bar.com http: paths: # 相当于nginx的location配合,同一个host可以配置多个path / /abc - backend: serviceName: nginx-externalname servicePort: 80 path: /test
说明:
- 配置了2个主机,一个后端服务是nginx-svc,另一个后端服务是nginx-externalname
- 确保后端服务都是可用的
- 本地测试,在本机上写hosts,hosts为ingress的主机ip
#ingress-nginx所在机器的ip
10.10.2.129 foo.bar.com 10.10.2.129 foo2.bar.com
验证:
集群级别的资源,没有命名空间隔离。
classrole
classrolebinding
storageclass
ingressclass