k8s的pod分类

  • pod分为两类:自主式pod与控制器管理的pod
  • 自主式pod由k8s管理器进行管理,而static pod由kubelet进行创建与管理

自主式pod

  1. 自主式pod总是在前台运行,同时接受k8s管理与调度,当集群当中的pod因为某种原因停止,k8s会根据其副本的数量,重新的生成对应的pod
  2. .自我管理的pod,创建以后仍然需要提交给apiserver,由apiserver接收以后借助于调度器将其调度至指定的node节点,由node启动此pod
  3. 如果此pod出现故障,需要重启容器则由kubelet来完成
  4. 如果node节点故障了,那么此pod将会消失。其无法实现全局调度。所以不推荐使用此种pod

控制器管理的pod

常见的pod控制器:

  1. ReplicationController:当启动一个pod时。这个pod如果不够用可以再启个副本,而后由控制器来管理同一类pod的各种副本与对象。一旦副本少了就会自动增加。采取多退少补的规则,精确符合我们所定义的期望。支持滚动更新
  2. ReplicaSet:由一个名叫Deployment的声明式更新的控制器来管理
  3. Deployment:Deployment只能管理无状态的应用
  4. stateFulSet:有状态副本集,可以管理有状态的应用
  5. DaemonSet:如果需要在每个node上运行一个副本的时候可以用DaemonSet

核心组件

HPA

  • Deployment还支持二级控制器
    HPA(HorizontalPodAutoscaler,水平pod自动伸缩控制器)
  • —般情况下我们可以确保一个node上有2个pod在运行,万一用户访问流量增加,2个pod不足以承载这么多访问量怎么办?此时我们就应该要增加pod资源,那么到底应该加几个?
  • HPA控制器可自动监控pod、自动进行扩展。

service

  • 假如有2个pod,pod有其生命周期,万一pod所在的节点宕机了,那么此pod将应该要在其他的节点上重建,而重建完的pod与原来的pod已经不是同一个pod了,只是两者都是运行的同一个服务而已。且每个容器都有其IP地址,重建的pod中的容器其P地址与之前的pod中容器的IP地址是不一样的,如此一来就会存在一个问题,客户端如何访问这些pod中的容器呢?
  • 措施:服务发现:就比如集贸市场的注册摊位和声明地址,注册摊位就是买东西的摊位,有一天这个摊位的商贩换地方了,就会在原来的摊位上留下一个摊位声明告诉顾客自己换地方了,但是它出售的商品还是一样的。只是换个地方买而已,这就是服务发现
  • pod是有生命周期的,一个pod随时都有可能离去,随时都有可能会有其他pod加进来,假如它们提供的是同―种服务,客户端是无法通过固定的手段来访问这些pod的,因为pod本身是不固定的,它们随时可能被替换掉,无论使用主机名还是IP地址,都随时会被替换掉。
  • 为了尽可能的降低客户端与pod间协调的复杂度,k8s为每一组提供同类服务的pod和其客户端之间添加了一个中间层,这个中间层是固定的,这个中间层就叫service
  • service只要不被删除,其地址与名称皆是固定的,当客户端需要在其配置文件中写上访问某个服务时,它不再需要自动发现,只需要在配置文件中写明service的名称即可,而这个service是个调度器,其不但能够提供一个稳定的访问入口,还可以做反向代理,当service接收到客户端的请求后,会将其代理到后端的pod之上,一旦pod宕机了会立即新建一个pod,这个新建的pod会立即被service关联上,作为service后端的可用pod之一
  • 客户端程序访问服务都是通过IP+端口或者主机名+端口的方式来实现的。而service关联后端的pod不是靠它的lIP和主机名,而是靠pod的标签选择器。只要创建的pod的label是统一的,无论P地址和主机如何改变,其都能被service所识别。如此一来,只要pod属于标签选择器,只要其在service的管理范围之内,则其就会被关联到service中,当这个动态的pod关联到service中之后,再进行动态的探测此pod的IP地址、端口,再将其作为自己后端可调度的可用服务器主机对象。因此,客户端的请求发送到service,然后由service代理到后端真实的pod中的容器进行响应。
  • service不是一个程序,也不是一个组件,它只是一个iptables的dnat规则
  • service作为k8s的对象,有其自身的名称,而service的名称相当于服务的名称,而这个名称可以被解析。

AddOns附件

  • 装完k8s后第一件事就需要在k8s集群上部署一个dns pod,以确保各service的名称能够被解析
  • 可以动态改变,包括动态创建、动态删除、动态修改
  • 比如把service的名称改了,dnspod会自动触发,将dns解析记录中的名称也给改掉;假如我们手动把service的ip地址给改了,改完以后会自动触发,将dns服务中的解析记录给改掉。
  • 如此一来,客户端去访问pod资源的时候可以直接访问service的名称,然后由集群中专用的dns服务来负责解析。
  • 这种pod是k8s自身的服务就需要用到的pod,所以我们把它称为基础性的系统架构级的pod对象,而且它们也被称为集群附件

K8s的三种网络模型

节点网络

service集群网络

pod网络

kubectl常用操作

[root@master ~]# kubectl --help
kubectl controls the Kubernetes cluster manager.

 Find more information at: https://kubernetes.io/docs/reference/kubectl/overview/

Basic Commands (Beginner):
  create        Create a resource from a file or from stdin.
  expose        使用 replication controller, service, deployment 或者 pod 并暴露它作为一个 新的 Kubernetes Service
  run           在集群中运行一个指定的镜像
  set           为 objects 设置一个指定的特征

Basic Commands (Intermediate):
  explain       查看资源的文档
  get           显示一个或更多 resources
  edit          在服务器上编辑一个资源
  delete        Delete resources by filenames, stdin, resources and names, or by resources and label selector

Deploy Commands:
  rollout       Manage the rollout of a resource
  scale         Set a new size for a Deployment, ReplicaSet or Replication Controller
  autoscale     自动调整一个 Deployment, ReplicaSet, 或者 ReplicationController 的副本数量

Cluster Management Commands:
  certificate   修改 certificate 资源.
  cluster-info  显示集群信息
  top           Display Resource (CPU/Memory/Storage) usage.
  cordon        标记 node 为 unschedulable
  uncordon      标记 node 为 schedulable
  drain         Drain node in preparation for maintenance
  taint         更新一个或者多个 node 上的 taints

Troubleshooting and Debugging Commands:
  describe      显示一个指定 resource 或者 group 的 resources 详情
  logs          输出容器在 pod 中的日志
  attach        Attach 到一个运行中的 container
  exec          在一个 container 中执行一个命令
  port-forward  Forward one or more local ports to a pod
  proxy         运行一个 proxy 到 Kubernetes API server
  cp            复制 files 和 directories 到 containers 和从容器中复制 files 和 directories.
  auth          Inspect authorization
  debug         Create debugging sessions for troubleshooting workloads and nodes

Advanced Commands:
  diff          Diff live version against would-be applied version
  apply         通过文件名或标准输入流(stdin)对资源进行配置
  patch         Update field(s) of a resource
  replace       通过 filename 或者 stdin替换一个资源
  wait          Experimental: Wait for a specific condition on one or many resources.
  kustomize     Build a kustomization target from a directory or a remote url.

Settings Commands:
  label         更新在这个资源上的 labels
  annotate      更新一个资源的注解
  completion    Output shell completion code for the specified shell (bash or zsh)

Other Commands:
  api-resources Print the supported API resources on the server
  api-versions  Print the supported API versions on the server, in the form of "group/version"
  config        修改 kubeconfig 文件
  plugin        Provides utilities for interacting with plugins.
  version       输出 client 和 server 的版本信息

Usage:
  kubectl [flags] [options]

Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).

create命令

语法:kubectl create deployment NAME --image=image – [COMMAND] [args…]

创建一个busybox镜像名为test1的容器 
[root@master ~]# kubectl create deployment test1 --image busybox
deployment.apps/test1 created
[root@master ~]# kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
nginx-6799fc88d8-fzdd4   1/1     Running   0          37h
test1-78d64fd9b9-bhtmz   0/1     Pending   0          10s

// 创建3个nginx镜像容器
[root@master ~]# kubectl create deployment nginx-1 --image=nginx --replicas=3
deployment.apps/nginx-1 created
[root@master ~]# kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
nginx-1-6664c49886-5zxq9   0/1     Pending   0          9s
nginx-1-6664c49886-mcnsr   0/1     Pending   0          9s
nginx-1-6664c49886-zjpg6   0/1     Pending   0          9s
nginx-6799fc88d8-fzdd4     1/1     Running   0          37h
test1-78d64fd9b9-bhtmz     0/1     Pending   0          13m

[root@master ~]# kubectl create deployment web01 --image nginx --port=80
deployment.apps/web01 created
[root@master ~]# kubectl get pods -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
nginx-1-6664c49886-5zxq9   0/1     Pending   0          74s   <none>       <none>   <none>           <none>
nginx-1-6664c49886-mcnsr   0/1     Pending   0          74s   <none>       <none>   <none>           <none>
nginx-1-6664c49886-zjpg6   0/1     Pending   0          74s   <none>       <none>   <none>           <none>
nginx-6799fc88d8-fzdd4     1/1     Running   0          37h   10.244.1.2   node1    <none>           <none>
test1-78d64fd9b9-bhtmz     0/1     Pending   0          147m   <none>       <none>   <none>           <none>
web01-59859fb9db-km28p     0/1     Pending   0          7s    <none>

get命令

[root@master ~]# kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
nginx-1-6664c49886-5zxq9   0/1     Pending   0          7m59s
nginx-1-6664c49886-mcnsr   0/1     Pending   0          7m59s
nginx-1-6664c49886-zjpg6   0/1     Pending   0          7m59s
nginx-6799fc88d8-fzdd4     1/1     Running   0          37h
test1-78d64fd9b9-bhtmz     0/1     Pending   0          20m
web01-59859fb9db-km28p     0/1     Pending   0          6m52s
[root@master ~]# kubectl get deployment web01
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
web01   0/1     1            0           7m4s
[root@master ~]#  kubectl get pods -o wide
NAME                       READY   STATUS    RESTARTS   AGE     IP           NODE     NOMINATED NODE   READINESS GATES
nginx-1-6664c49886-5zxq9   0/1     Pending   0          8m18s   <none>       <none>   <none>           <none>
nginx-1-6664c49886-mcnsr   0/1     Pending   0          8m18s   <none>       <none>   <none>           <none>
nginx-1-6664c49886-zjpg6   0/1     Pending   0          8m18s   <none>       <none>   <none>           <none>
nginx-6799fc88d8-fzdd4     1/1     Running   0          37h     10.244.1.2   node1    <none>           <none>
test1-78d64fd9b9-bhtmz     0/1     Pending   0          21m     <none>       <none>   <none>           <none>
web01-59859fb9db-km28p     0/1     Pending   0          7m11s   <none>

expose命令

[root@master ~]# kubectl expose deployment nginx --port 8080 --target-port 80
service/nginx exposed
[root@master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    27h
nginx        ClusterIP   10.102.213.63   <none>        8080/TCP   20s

[root@master ~]# curl 10.102.213.63:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

delete命令

[root@master ~]#  kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
nginx-1-6664c49886-5zxq9   0/1     Pending   0          13m
nginx-1-6664c49886-mcnsr   0/1     Pending   0          13m
nginx-1-6664c49886-zjpg6   0/1     Pending   0          13m
nginx-6799fc88d8-fzdd4     1/1     Running   0          37h
test1-78d64fd9b9-bhtmz     0/1     Pending   0          26m
web01-59859fb9db-km28p     0/1     Pending   0          12m

// 删除指定名称的pod
[root@master ~]# kubectl delete deployment test1
deployment.apps "test1" deleted

[root@master ~]# kubectl delete deployment web01
deployment.apps "web01" deleted

// 删除所有pod
[root@master ~]# kubectl delete pods --all 

// 强制删除pod节点
[root@master ~]# kubectl delete pod foo --force

run命令

// 启动一个 nginx pod
[root@master ~]#  kubectl run nginx --image nginx

// 详细信息
[root@master ~]# kubectl describe pod nginx 
Name:         nginx
Namespace:    default
Priority:     0
Node:         node1/192.168.1477.133
Start Time:   Sun, 19 Dec 2021 23:48:10 +0800
Labels:       aap=nginx
              env=prod
Annotations:  <none>
Status:       Running
IP:           10.244.1.17
IPs:
  IP:  10.244.1.17
Containers:
  nginx:
    Container ID:   docker://462f5b21hfef36c00e0e082sdf6bd0889620971e2964b2d1a57faf7b3b6ff8xg
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:dsaz2864dd661dcadfd9958f9e0de192a1fdda2c162a35668461242b465f003
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Sun, 19 Dec 2021 23:48:10 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-ck7n4 (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-ck7n4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-ck7n4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  44s   default-scheduler  Successfully assigned default/nginx to node1
  Normal  Pulling    45s   kubelet            Pulling image "nginx"
  Normal  Pulled     43s   kubelet            Successfully pulled image "nginx" in 1.286464367s
  Normal  Created    43s   kubelet            Created container nginx
  Normal  Started    43s   kubelet            Started container nginx

explain

用法:kubectl explain RESOURCE

// 获取资源及其字段的文档
[root@master ~]# kubectl explain pods
KIND:     Pod
VERSION:  v1

DESCRIPTION:
     Pod is a collection of containers that can run on a host. This resource is
     created by clients and scheduled onto hosts.

FIELDS:
   apiVersion   <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

   kind <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

   metadata     <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   spec <Object>
     Specification of the desired behavior of the pod. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

   status       <Object>
     Most recently observed status of the pod. This data may not be up to date.
     Populated by the system. Read-only. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

edit

更改数据
// 使用edit命令编辑
[root@master ~]# kubectl edit deployment nginx
......
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: "2021-12-20T10:33:49Z"
  generation: 1
  labels:
    app: nginx
    name: mkf	#添加name: mkf
.....

scale

扩展pod

// 使用scale扩展
[root@master ~]# kubectl scale --replicas 3 deployment/nginx
deployment.apps/nginx scaled
[root@master ~]# kubectl get deployment
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
nginx     0/3     3            0           2d22h

autoscale

自动扩展,给定一个范围,自动根据业务的访问量增加或减少

// 最少3个最大5个,当不满足条件时会自动创建
[root@master ~]# kubectl autoscale deployment/nginx --min 3 --max=5
horizontalpodautoscaler.autoscaling/nginx autoscaled
[root@master ~]#  kubectl get hpa
NAME    REFERENCE          TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
nginx   Deployment/nginx   <unknown>/80%   3         5         0          6s

cordon

可调度

[root@master ~]# kubectl cordon node1
node/node1 cordoned
[root@master ~]# kubectl get node
NAME     STATUS                        ROLES                  AGE     VERSION
master   Ready                         control-plane,master   2d23h   v1.20.0
node1    NotReady,SchedulingDisabled   <none>                 2d22h   v1.20.0
node2    NotReady                      <none>                 2d22h   v1.20.0

uncordon

[root@master ~]# kubectl uncordon node1
node/node1 uncordoned
[root@master ~]# kubectl get node
NAME     STATUS     ROLES                  AGE     VERSION
master   Ready      control-plane,master   2d23h   v1.20.0
node1    NotReady   <none>                 2d22h   v1.20.0
node2    NotReady   <none>                 2d22h   v1.20.0

describe

显示指定pod的详细信息
[root@master ~]# kubectl describe pod nginx
Name:         nginx
Namespace:    default
Priority:     0
Node:         <none>
Labels:       run=nginx
Annotations:  <none>
Status:       Pending
IP:           
IPs:          <none>
......

logs

// 查看nginx的日志
[root@master ~]# kubectl logs deployment/nginx
Found 5 pods, using pod/nginx-6799fc88d8-dwrsh
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2021/12/20 147:147:43 [notice] 1#1: using the "epoll" event method
2021/12/20 147:147:43 [notice] 1#1: nginx/1.21.4
2021/12/20 147:147:43 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 
2021/12/20 147:147:43 [notice] 1#1: OS: Linux 4.18.0-257.el8.x86_64
2021/12/20 147:147:43 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2021/12/20 147:147:43 [notice] 1#1: start worker processes
2021/12/20 147:147:43 [notice] 1#1: start worker process 32
2021/12/20 147:147:43 [notice] 1#1: start worker process 33

attach

附加在一个容器里

[root@master ~]# kubectl attach nginx
Defaulting container name to nginx.
Use 'kubectl describe pod/nginx -n default' to see all of the containers in this pod.
If you don't see a command prompt, try pressing enter.

exec

进到容器内执行一个命令

[root@master ~]# kubectl exec deployment/nginx date
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
Mon Dec 20 10:10:30 UTC 2021

cp

拷贝文件或目录到容器中,或者从容器内向外拷贝

[root@master ~]# kubectl cp anaconda-ks.cfg nginx-6799fc88d8-5tsjt:/opt

滚动更新和回滚

[root@master httpd]# vim Dockerfile
FROM busybox

RUN mkdir  /data && \
    echo "test page on mkf1" > /data/index.html
ENTRYPOINT ["/bin/httpd","-f","-h","/data"]

[root@master httpd]# docker build -t 147501476910/httpd:v1 .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM busybox
 ---> 66e9d417cz4g
Step 2/3 : RUN mkdir  /data &&     echo "test page on mkf1" > /data/index.html
 ---> Running in 9554a276c622
Removing intermediate container 9554a276c622
 ---> 15655bd6a4xh
Step 3/3 : ENTRYPOINT ["/bin/httpd","-f","-h","/data"]
 ---> Running in sd4ecc49sdzf
Removing intermediate container sd4ecc49sdzf
 ---> zsfd3c5c8fe2
Successfully built zsfd3c5c8fe2
Successfully tagged 147501476910/httpd:v1

//制作第二版镜像
[root@master httpd]# vim Dockerfile 
[root@master httpd]# cat Dockerfile 
FROM busybox

RUN mkdir  /data && \
    echo "test page on mkf2" > /data/index.html
ENTRYPOINT ["/bin/httpd","-f","-h","/data"]


[root@master httpd]# docker build -t 147501476910/httpd:v2 .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM busybox
 ---> dfe9d4sfc3zf
Step 2/3 : RUN mkdir  /data &&     echo "test page on mkf2" > /data/index.html
 ---> Running in fza32c0z6fze
Removing intermediate container fza32c0z6fze
 ---> zz110fc3fmbc
Step 3/3 : ENTRYPOINT ["/bin/httpd","-f","-h","/data"]
 ---> Running in j4dd849a5gg9
Removing intermediate container j4dd849a5gg9
 ---> ads6b22zf632
Successfully built ads6b22zf632
Successfully tagged 147501476910/httpd:v2

[root@master ~]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: 147501476910
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

[root@master ~]# docker push 147501476910/httpd:v1
The push refers to repository [docker.io/147501476910/httpd]
5237189456ad: Pushed 
61cac9naf0za: Mounted from library/busybox 
v1: digest: sha256:53e1476ca01daf76043ccad9cb5ece9eaede66ceaa2fdf9c1afdb29fcaa95ba7c size: 734
[root@master ~]# docker push 147501476910/httpd:v2
The push refers to repository [docker.io/147501476910/httpd]
kgdd343cf27e: Layer already exists 
3bcac9eaf0da: Layer already exists 
v2: digest: sha256:65c39d6e8db89e89efff912164ed1c309c98ea363b75c54c74afbfbd1530eb60 size: 734

// 用k8s基于httpd:v1镜像运行镜像3个pod
[root@master httpd]# kubectl create deploy httpd --image 147501476910/httpd:v1 --replicas 3
deployment.apps/httpd created

// 更新
[root@master ~]# kubectl set image deploy/httpd httpd=147501476910/httpd:v2
deployment.apps/httpd image updated

# 创建一个新pod,删除一个旧pod。直到更新完成

// 回滚
[root@master ~]# kubectl rollout undo deploy/httpd
deployment.apps/httpd rolled back

[root@master ~]# curl 10.103.23.15
test page on mkf1

// 回滚到上一个版本
[root@master ~]# kubectl rollout undo deploy/httpd 
deployment.apps/httpd rolled back
[root@master ~]# curl 10.103.23.15
test page on mkf2