K8S学习笔记之官方入门示例

本文档根据官方的示例教程编写,在本地 windows 环境中的 minikube 下进行的操作。

创建集群

Kubernetes 是一个生产级的开源平台,负责协调计算机集群内部和跨集群应用程序容器的布局(调度)和执行。

Kubernetes 集群由两种类型的资源组成:

  • 用于协调集群的 Master
  • 用于作为 worker 运行应用程序的 Node

启动集群

首先启动 minikube 。

$ minikube start

查看集群版本

可以通过 kubectl version 命令查看集群的版本,运行结果如下所示,会同时看到 client 和 server 两个版本号。其中,client 对应 kubectl 的版本,server 对应 Master 上安装的 Kubernetes 的版本。

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.3", GitCom
mit:"2d3c76f9091b6bec110a5e63777c332469e0cba2", GitTreeState:"clean", BuildDate:
"2019-08-19T11:13:54Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"windows/a
md64"}
Server Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.0", GitCom
mit:"2bd9643cee5b3b3a5ecbd3af49d09018f0773c77", GitTreeState:"clean", BuildDate:
"2019-09-18T14:27:17Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd
64"}

查看集群详情

通过 kubectl cluster-info 命令查看集群的详情。

$ kubectl cluster-info
Kubernetes master is running at https://192.168.99.109:8443
KubeDNS is running at https://192.168.99.109:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

运行 kubectl get nodes 命令查看集群中的 Node 节点,这会显示所有可用于应用程序的节点。现在我们只有一个节点,且其 status 状态是 ready,表示可以用于部署应用程序。

$ kubectl get nodes
NAME       STATUS   ROLES    AGE   VERSION
minikube   Ready    master   13m   v1.16.0

部署应用程序

部署应用

通过 kubectl run 命令在 Kubernetes 上运行我们的第一个应用,这里我们使用的镜像是 jocatalin/kubernetes-bootcamp 。

$ kubectl run kubernetes-bootcamp --image=jocatalin/kubernetes-
bootcamp:v1 --port=8080
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in
a future version. Use kubectl run --generator=run-pod/v1 or kubectl create inste
ad.
deployment.apps/kubernetes-bootcamp created

如果需要删除所有通过 kubectl run 命令创建的 Deployment,可以运行下面命令:

kubectl delete deployments --all

现在,通过创建 Deployment 已经成功部署了第一个应用。通过下面命令列出所有的 Deployment:

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/1     1            1           4m21s

查看应用

Kubernetes 中运行的 Pod 运行在私有的隔离网络中。默认情况下,Pod 仅对同一个 Kubernetes 集群中的 service 和其他 Pod 可见。当我们使用 kubectl 时,会通过 API 终端交互,实现与应用程序的通信。

kubectl 命令可以创建代理,将通信转发到集群范围的专用网络。代理可以通过 control-C 终止,并且在运行时不会显示任何输出。

打开第二个终端窗口来运行代理。

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

在浏览器中访问 http://127.0.0.1:8001 ,可以看到所有可以访问的API。

kubectl-proxy.png

API 服务器会基于 Pod 的名字自动为每个 Pod 创建一个终端,这个终端也可以通过代理访问。

先获取 pod 名称。

$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-756f66956c-hzl28   1/1     Running   0          36m

然后访问 http://localhost:8001/api/v1/namespaces/default/pods/kubernetes-bootcamp-756f66956c-hzl28/proxy/ 。

kubectl-proxy2.png

探索应用

使用 kubectl 进行故障排除时,最常见的命令包括:

  • kubectl get - 列出资源
  • kubectl describe - 显示有关资源的详细信息
  • kubectl logs - 从 Pod 中的容器打印日志
  • kubectl exec - 在 Pod 中的容器上执行命令

使用这些命令查看应用程序的部署时间、当前状态、运行位置以及配置信息。

检查应用配置

下前面部署的应用是否正在运行。使用 kubectl get 命令查看存在的 Pod:

$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-756f66956c-hzl28   1/1     Running   0          36m

如果没有运行中的 Pod,再次执行上面命令(部署需要几秒钟的时间)。

然后,查看这个 Pod 里面有哪些容器,这些容器是通过哪些镜像构建的。使用 kubectl describe pods 命令:

Name:           kubernetes-bootcamp-756f66956c-hzl28
Namespace:      default
Priority:       0
Node:           minikube/10.0.2.15
Start Time:     Mon, 13 Jan 2020 17:19:10 +0800
Labels:         pod-template-hash=756f66956c
                run=kubernetes-bootcamp
Annotations:    
Status:         Running
IP:             172.17.0.4
Controlled By:  ReplicaSet/kubernetes-bootcamp-756f66956c
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://503afe3da8a94491460f2cb4629240e3dc9cf1ca44723606030
a4800dd5cb1b3
    Image:          jocatalin/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:0d6b8
ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Mon, 13 Jan 2020 17:21:48 +0800
    Ready:          True
    Restart Count:  0
    Environment:    
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-ks2qf (ro
)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-ks2qf:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-ks2qf
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled    default-scheduler  Successfully assigned default
/kubernetes-bootcamp-756f66956c-hzl28 to minikube
  Normal  Pulling    50m        kubelet, minikube  Pulling image "jocatalin/kube
rnetes-bootcamp:v1"
  Normal  Pulled     47m        kubelet, minikube  Successfully pulled image "jo
catalin/kubernetes-bootcamp:v1"
  Normal  Created    47m        kubelet, minikube  Created container kubernetes-
bootcamp
  Normal  Started    47m        kubelet, minikube  Started container kubernetes-
bootcamp

这里会看到 Pod 中容器的详情:IP 地址,使用的端口号,和 Pod 生命周期相关的事件列表。

查看容器日志

应用程序发送到 STDOUT 的任何内容都将成为 Pod 中容器的日志。使用 kubectl logs 命令检索这些日志:

$ kubectl logs kubernetes-bootcamp-756f66956c-hzl28
Kubernetes Bootcamp App Started At: 2020-01-13T09:21:48.466Z | Running On:  kube
rnetes-bootcamp-756f66956c-hzl28

Running On: kubernetes-bootcamp-756f66956c-hzl28 | Total Requests: 1 | App Uptim
e: 2115.696 seconds | Log Time: 2020-01-13T09:57:04.163Z

在容器中执行命令

Pod 启动并运行后,可以直接在容器中执行命令。使用 exec 命令时需要指定 Pod 的名字作为参数。列出环境变量:

$ kubectl exec kubernetes-bootcamp-756f66956c-hzl28 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubernetes-bootcamp-756f66956c-hzl28
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
NPM_CONFIG_LOGLEVEL=info
NODE_VERSION=6.3.1
HOME=/root

在 Pod 的容器中开始一个 bash 会话:

$ kubectl exec -ti kubernetes-bootcamp-756f66956c-hzl28 bash

现在,在我们运行 NodeJS 应用程序的容器中开启了会话。查看应用程序的源代码文件 server.js :

root@kubernetes-bootcamp-756f66956c-hzl28:/# cat server.js
var http = require('http');
var requests=0;
var podname= process.env.HOSTNAME;
var startTime;
var host;
var handleRequest = function(request, response) {
  response.setHeader('Content-Type', 'text/plain');
  response.writeHead(200);
  response.write("Hello Kubernetes bootcamp! | Running on: ");
  response.write(host);
  response.end(" | v=1\n");
  console.log("Running On:" ,host, "| Total Requests:", ++requests,"| App Uptime
:", (new Date() - startTime)/1000 , "seconds", "| Log Time:",new Date());
}
var www = http.createServer(handleRequest);
www.listen(8080,function () {
    startTime = new Date();;
    host = process.env.HOSTNAME;
    console.log ("Kubernetes Bootcamp App Started At:",startTime, "| Running On:
 " ,host, "\n" );
});

可以通过 curl 命令确认应用程序是否启动并在运行中(这里是在 NodeJS 容器内执行命令,所以可以使用 localhost):

root@kubernetes-bootcamp-756f66956c-hzl28:/# curl localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-756f66956c-hzl28 |v=1

然后使用 exit 命令退出。

root@kubernetes-bootcamp-756f66956c-hzl28:/# exit
exit

暴露应用到外网

虽然每个 Pod 具有唯一的 IP 地址,但是如果没有 Service,这些 IP 不会暴露到集群外部。Service 允许应用程序接收流量。通过在 ServiceSpec 中指定类型,可以以不同的方式暴露 Service:

  • ClusterIP(默认) - 将 Service 公开在集群的内部 IP 上。这种类型使服务只能从集群内访问。
  • NodePort - 使用 NAT 在集群中每个选定节点的同一端口上暴露 Service。使用 : 使集群外部的服务可访问。ClusterIP 的超集。
  • LoadBalancer - 在当前云中创建外部负载平衡器(如果支持)并为服务分配固定的外部 IP。NodePort 的超集。
  • ExternalName - 使用任意名称(由规范中的externalName指定)通过返回具有名称的 CNAME 记录来暴露 Service。没有使用代理。需要 v1.7 或更高版本的 kube-dns。

创建 Service

列出集群当前运行的 Service:

$ kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1            443/TCP   25h

有一个名为 Kubernetes 的 Service,在 Minikube 启动集群时会默认创建这个服务。通过 expose 命令,使用 NodePort 参数(Minikube 暂时不支持 LoadBalancer),创建新 Service 并将其暴露到外网:

$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed

再次列出集群当前运行的 Service:

$ kubectl get services
NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)
  AGE
kubernetes            ClusterIP   10.96.0.1                443/TCP
  25h
kubernetes-bootcamp   NodePort    10.107.185.136           8080:30087/TCP
  30s

kubernetes-bootcamp 这个 Service 已经运行了。可以看到,这个 Service 有一个唯一的 CLUSTER-IP,一个内部端口号以及一个 EXTERNAL-IP(Node 节点的 IP)。

要找出开放到外部的端口(通过 NodePort 选项)是哪个,需要运行 kubectl describe service 命令:

$ kubectl describe services/kubernetes-bootcamp
Name:                     kubernetes-bootcamp
Namespace:                default
Labels:                   run=kubernetes-bootcamp
Annotations:              
Selector:                 run=kubernetes-bootcamp
Type:                     NodePort
IP:                       10.107.185.136
Port:                       8080/TCP
TargetPort:               8080/TCP
NodePort:                   30087/TCP
Endpoints:                172.17.0.4:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   

查看 minikube 的 ip。

$ minikube ip
192.168.99.109

在本机浏览器中访问 http://192.168.99.109:30087/。

kubectl-service.png

Service 暴露成功。

使用标签

Deployment 自动为 Pod 创建了一个标签。使用 kubectl describe deployment 命令,可以看到标签的名称:

$ kubectl describe deployment
Name:                   kubernetes-bootcamp
Namespace:              default
CreationTimestamp:      Mon, 13 Jan 2020 17:19:10 +0800
Labels:                 run=kubernetes-bootcamp
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               run=kubernetes-bootcamp
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavai
lable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  run=kubernetes-bootcamp
  Containers:
   kubernetes-bootcamp:
    Image:        jocatalin/kubernetes-bootcamp:v1
    Port:         8080/TCP
    Host Port:    0/TCP
    Environment:  
    Mounts:       
  Volumes:        
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  
NewReplicaSet:   kubernetes-bootcamp-756f66956c (1/1 replicas created)
Events:          

可以通过这个标签查询 Pod。使用 kubectl get pods 命令时,通过 -l 参数指定标签值:

$ kubectl get pods -l run=kubernetes-bootcamp
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-756f66956c-hzl28   1/1     Running   0          25h

查看 Service 时,也可以使用这个参数:

$ kubectl get services -l run=kubernetes-bootcamp
NAME                  TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)
 AGE
kubernetes-bootcamp   NodePort   10.107.185.136           8080:30087/TCP
 26m

可以通过 kubectl label 对象类型 对象名字 新标签 命令创建新标签:

$ kubectl get services -l run=kubernetes-bootcamp
NAME                  TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)
 AGE
kubernetes-bootcamp   NodePort   10.107.185.136           8080:30087/TCP
 26m

这会为我们的 Pod 应用一个新标签(这里将应用程序的版本固定到 Pod),可以使用 kubectl describe pod 命令检查:

$ kubectl describe pods kubernetes-bootcamp-756f66956c-hzl28
Name:           kubernetes-bootcamp-756f66956c-hzl28
Namespace:      default
Priority:       0
Node:           minikube/10.0.2.15
Start Time:     Mon, 13 Jan 2020 17:19:10 +0800
Labels:         app=v1
               pod-template-hash=756f66956c
               run=kubernetes-bootcamp
Annotations:    
Status:         Running
IP:             172.17.0.4
Controlled By:  ReplicaSet/kubernetes-bootcamp-756f66956c
Containers:
 kubernetes-bootcamp:
   Container ID:   docker://503afe3da8a94491460f2cb4629240e3dc9cf1ca44723606030
a4800dd5cb1b3
   Image:          jocatalin/kubernetes-bootcamp:v1
   Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:0d6b8
ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
   Port:           8080/TCP
   Host Port:      0/TCP
   State:          Running
     Started:      Mon, 13 Jan 2020 17:21:48 +0800
   Ready:          True
   Restart Count:  0
   Environment:    
   Mounts:
     /var/run/secrets/kubernetes.io/serviceaccount from default-token-ks2qf (ro
)
Conditions:
 Type              Status
 Initialized       True
 Ready             True
 ContainersReady   True
 PodScheduled      True
Volumes:
 default-token-ks2qf:
   Type:        Secret (a volume populated by a Secret)
   SecretName:  default-token-ks2qf
   Optional:    false
QoS Class:       BestEffort
Node-Selectors:  
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                node.kubernetes.io/unreachable:NoExecute for 300s
Events:          

看到标签附加到了 Pod 上,现在可以使用这个新标签来查询 Pod 列表了。

$ kubectl get pods -l app=v1
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-756f66956c-hzl28   1/1     Running   0          2d16h

删除 Service

通过 kubectl delete service -l your-label 命令删除 Service。

kubectl delete service -l run=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted

确认 Service 删除是否成功:

kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1            443/TCP   2d17h

这里会发现 Service 删除成功。之前暴露的 IP 地址和端口号确认路由不再暴露到外网,http://192.168.99.109:30087/ 已经无法访问。

这证明集群外部无法继续访问我们的应用程序了。可以通过在 Pod 内部执行 curl 来验证应用程序仍然在运行中:

$ kubectl exec -ti kubernetes-bootcamp-756f66956c-hzl28 curl lo
calhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-756f66956c-hzl28 |
v=1

可以看到应用仍在运行。

伸缩应用

Deployment 只创建一个 Pod 来运行我们的应用程序。当流量增加时,我们需要扩展应用以满足用户需求。应用的伸缩是通过改变 Deployment 中副本的数量来完成的。可以使用 kubectl run 命令的 --replicas 参数从头开始创建具有多个实例的Deployment。

列出 Pod:

$ kubectl get pods -o wide
NAME                                   READY   STATUS    RESTARTS   AGE     IP
         NODE       NOMINATED NODE   READINESS GATES
kubernetes-bootcamp-756f66956c-hzl28   1/1     Running   0          2d18h   172.
17.0.4   minikube              

列出 Deployment:

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/1     1            1           2d18h

这时候应该只有 1 个 Pod。各字段的解释如下:

  • DESIRED 字段显示配置的副本数量
  • CURRENT 字段显示现在有多少副本正在运行
  • UP-TO-DATE 是已更新的副本数量,在滚动更新时,这个数字会从 0 增大到 DESIRED 字段值
  • AVAILABLE 字段显示用户实际可用的副本数量

将 Deployment 扩展到 4 个副本。使用 kubectl scale 命令时,指定 Deployment 类型、名称以及所需实例的数量:

$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.apps/kubernetes-bootcamp scaled

再次列出可用的 Deployment:

kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   4/4     4            4           2d18h

更改已生效,现在应用程序有 4 个可用实例。接下来,看一下 Pod 的数量是否发生了变化:

kubectl get pods -o wide
NAME                                   READY   STATUS    RESTARTS   AGE     IP
         NODE       NOMINATED NODE   READINESS GATES
kubernetes-bootcamp-756f66956c-9lbhm   1/1     Running   0          25s     172.
17.0.6   minikube              
kubernetes-bootcamp-756f66956c-hzl28   1/1     Running   0          2d18h   172.
17.0.4   minikube              
kubernetes-bootcamp-756f66956c-lw5d7   1/1     Running   0          25s     172.
17.0.5   minikube              
kubernetes-bootcamp-756f66956c-z4bwp   1/1     Running   0          25s     172.
17.0.7   minikube              

现在有 4 个具有不同 IP 地址的 Pod。更改已在 Deployment 事件日志中注册。使用 describe 命令查看:

$ kubectl describe deployments/kubernetes-bootcamp
Name:                   kubernetes-bootcamp
Namespace:              default
CreationTimestamp:      Mon, 13 Jan 2020 17:19:10 +0800
Labels:                 run=kubernetes-bootcamp
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               run=kubernetes-bootcamp
Replicas:               4 desired | 4 updated | 4 total | 4 available | 0 unavai
lable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  run=kubernetes-bootcamp
  Containers:
   kubernetes-bootcamp:
    Image:        jocatalin/kubernetes-bootcamp:v1
    Port:         8080/TCP
    Host Port:    0/TCP
    Environment:  
    Mounts:       
  Volumes:        
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Progressing    True    NewReplicaSetAvailable
  Available      True    MinimumReplicasAvailable
OldReplicaSets:  
NewReplicaSet:   kubernetes-bootcamp-756f66956c (4/4 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  97s   deployment-controller  Scaled up replica set
kubernetes-bootcamp-756f66956c to 4

从这个命令的输出中也可以看到现在有 4 个副本。

负载均衡

再次创建 Service 暴露端口。

$ kubectl expose deployment/kubernetes-bootcamp --type="NodePor
t" --port 8080
service/kubernetes-bootcamp exposed

通过 describe 命令找出暴露的 IP 地址和端口:

$ kubectl describe services/kubernetes-bootcamp
Name:                     kubernetes-bootcamp
Namespace:                default
Labels:                   run=kubernetes-bootcamp
Annotations:              
Selector:                 run=kubernetes-bootcamp
Type:                     NodePort
IP:                       10.108.207.197
Port:                       8080/TCP
TargetPort:               8080/TCP
NodePort:                   31174/TCP
Endpoints:                172.17.0.4:8080,172.17.0.5:8080,172.17.0.6:8080 + 1 mo
re...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   

在浏览器中多次访问 http://192.168.99.109:31174/ 。

kubectl-scale1.png
kubectl-scale2.png

请求会命中不同的 Pod。这证明负载均衡生效了。

缩减应用

再次运行 kubectl scale 命令将 Service 缩减为 2 个副本:

$ kubectl scale deployment/kubernetes-bootcamp --replicas=2
deployment.apps/kubernetes-bootcamp scaled

列出 Deployment 来验证变更是否生效:

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   2/2     2            2           3d15h

期望的副本数是 2。列出 Pod 的数量:

$ kubectl get pods -o wide
NAME                                   READY   STATUS        RESTARTS   AGE
IP           NODE       NOMINATED NODE   READINESS GATES
kubernetes-bootcamp-756f66956c-9lbhm   1/1     Running       0          21h
172.17.0.6   minikube              
kubernetes-bootcamp-756f66956c-hzl28   1/1     Running       0          3d15h
172.17.0.4   minikube              
kubernetes-bootcamp-756f66956c-lw5d7   1/1     Terminating   0          21h
172.17.0.5   minikube              
kubernetes-bootcamp-756f66956c-z4bwp   1/1     Terminating   0          21h
172.17.0.7   minikube              

只剩 2 个运行中的 Pod 了。

滚动更新

用户希望应用程序随时都可以访问,而开发者希望每天能部署几个新版本。在 Kubernetes 中通过滚动更新实现这两个目的。滚动更新使用新的实例逐个更新 Pod(而不是一次全部更新),从而实现不停机对 Deployment 的更新。新 Pod 将分配到具有可用资源的节点上。

滚动更新允许执行以下操作:

  • 将应用程序从一个环境推到另一个环境(通过容器镜像更新)
  • 回退到以前的版本
  • 以零停机时间持续集成和持续交付应用程序

更新版本

执行 set image 命令,并指定 Deployment 名称及新镜像,升级应用程序的镜像到版本 2。

$ kubectl set image deployments/kubernetes-bootcamp kubernetes-
bootcamp=jocatalin/kubernetes-bootcamp:v2
deployment.apps/kubernetes-bootcamp image updated

命令通知 Deployment 为应用程序使用不同的镜像,并初始化滚动更新。检查新 Pod 的状态:

$ kubectl get pods
NAME                                   READY   STATUS        RESTARTS   AGE
kubernetes-bootcamp-756f66956c-9lbhm   1/1     Terminating   0          23h
kubernetes-bootcamp-756f66956c-hzl28   1/1     Terminating   0          3d18h
kubernetes-bootcamp-7d6f8694b6-hxw49   1/1     Running       0          19s
kubernetes-bootcamp-7d6f8694b6-lqfwl   1/1     Running       0          6s

验证升级

首先,检查应用程序是否在运行。通过 describe service 命令找出暴露的 IP 地址和端口号:

kubectl describe services/kubernetes-bootcamp
Name:                     kubernetes-bootcamp
Namespace:                default
Labels:                   run=kubernetes-bootcamp
Annotations:              
Selector:                 run=kubernetes-bootcamp
Type:                     NodePort
IP:                       10.108.207.197
Port:                       8080/TCP
TargetPort:               8080/TCP
NodePort:                   31174/TCP
Endpoints:                172.17.0.5:8080,172.17.0.7:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   

在浏览器中访问 http://192.168.99.109:31174/ 。

kubectl-update1.png

每次请求命中的 Pod 都运行最新版本(v2)。

更新也可以通过 rollout status 命令来确认:

$ kubectl rollout status deployments/kubernetes-bootcamp
deployment "kubernetes-bootcamp" successfully rolled out

通过在 Pod 上执行 describe 命令来查看应用程序当前运行的镜像的版本号:

$ kubectl describe pods
Name:           kubernetes-bootcamp-7d6f8694b6-hxw49
Namespace:      default
Priority:       0
Node:           minikube/10.0.2.15
Start Time:     Fri, 17 Jan 2020 11:25:41 +0800
Labels:         pod-template-hash=7d6f8694b6
                run=kubernetes-bootcamp
Annotations:    
Status:         Running
IP:             172.17.0.5
Controlled By:  ReplicaSet/kubernetes-bootcamp-7d6f8694b6
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://d9e2d35e01dbd9f2168fd017377df467867f4ae0c8297f3f4af
2bbe2dd49f10a
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3
ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Fri, 17 Jan 2020 11:25:53 +0800
    Ready:          True
    Restart Count:  0
    Environment:    
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-ks2qf (ro
)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-ks2qf:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-ks2qf
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:          


Name:           kubernetes-bootcamp-7d6f8694b6-lqfwl
Namespace:      default
Priority:       0
Node:           minikube/10.0.2.15
Start Time:     Fri, 17 Jan 2020 11:25:54 +0800
Labels:         pod-template-hash=7d6f8694b6
                run=kubernetes-bootcamp
Annotations:    
Status:         Running
IP:             172.17.0.7
Controlled By:  ReplicaSet/kubernetes-bootcamp-7d6f8694b6
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://a2faa786f854e9a81f7cc702d4c12291e14e06a70c9bcad6627
873477fe6aa85
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3
ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Fri, 17 Jan 2020 11:25:55 +0800
    Ready:          True
    Restart Count:  0
    Environment:    
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-ks2qf (ro
)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-ks2qf:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-ks2qf
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:          

查看 Image 字段,现在运行的是应用程序的版本 2。

回滚更新

现在执行另外一个更新,部署标记为 v10 的镜像:

$ kubectl set image deployments/kubernetes-bootcamp kubernetes-
bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10
deployment.apps/kubernetes-bootcamp image updated

查看 Deployment 的状态:

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   2/2     1            2           3d23h

查看所有的 Pod:

$ kubectl get pods
NAME                                   READY   STATUS         RESTARTS   AGE
kubernetes-bootcamp-7d6f8694b6-hxw49   1/1     Running        0          5h2m
kubernetes-bootcamp-7d6f8694b6-lqfwl   1/1     Running        0          5h2m
kubernetes-bootcamp-886577c5d-9nrxt    0/1     ErrImagePull   0          23s

发现有报错,Pod 的 describe 命令可以提供更多信息:

$ kubectl describe pods
Name:           kubernetes-bootcamp-7d6f8694b6-hxw49
Namespace:      default
Priority:       0
Node:           minikube/10.0.2.15
Start Time:     Fri, 17 Jan 2020 11:25:41 +0800
Labels:         pod-template-hash=7d6f8694b6
                run=kubernetes-bootcamp
Annotations:    
Status:         Running
IP:             172.17.0.5
Controlled By:  ReplicaSet/kubernetes-bootcamp-7d6f8694b6
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://d9e2d35e01dbd9f2168fd017377df467867f4ae0c8297f3f4af
2bbe2dd49f10a
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3
ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Fri, 17 Jan 2020 11:25:53 +0800
    Ready:          True
    Restart Count:  0
    Environment:    
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-ks2qf (ro
)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-ks2qf:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-ks2qf
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:          


Name:           kubernetes-bootcamp-7d6f8694b6-lqfwl
Namespace:      default
Priority:       0
Node:           minikube/10.0.2.15
Start Time:     Fri, 17 Jan 2020 11:25:54 +0800
Labels:         pod-template-hash=7d6f8694b6
                run=kubernetes-bootcamp
Annotations:    
Status:         Running
IP:             172.17.0.7
Controlled By:  ReplicaSet/kubernetes-bootcamp-7d6f8694b6
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://a2faa786f854e9a81f7cc702d4c12291e14e06a70c9bcad6627
873477fe6aa85
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3
ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Fri, 17 Jan 2020 11:25:55 +0800
    Ready:          True
    Restart Count:  0
    Environment:    
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-ks2qf (ro
)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-ks2qf:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-ks2qf
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:          


Name:           kubernetes-bootcamp-886577c5d-9nrxt
Namespace:      default
Priority:       0
Node:           minikube/10.0.2.15
Start Time:     Fri, 17 Jan 2020 16:27:31 +0800
Labels:         pod-template-hash=886577c5d
                run=kubernetes-bootcamp
Annotations:    
Status:         Pending
IP:             172.17.0.4
Controlled By:  ReplicaSet/kubernetes-bootcamp-886577c5d
Containers:
  kubernetes-bootcamp:
    Container ID:
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v10
    Image ID:
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Waiting
      Reason:       ErrImagePull
    Ready:          False
    Restart Count:  0
    Environment:    
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-ks2qf (ro
)
Conditions:
  Type              Status
  Initialized       True
  Ready             False
  ContainersReady   False
  PodScheduled      True
Volumes:
  default-token-ks2qf:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-ks2qf
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled            default-scheduler  Successfully assigne
d default/kubernetes-bootcamp-886577c5d-9nrxt to minikube
  Normal   Pulling    34s (x2 over 61s)  kubelet, minikube  Pulling image "gcr.i
o/google-samples/kubernetes-bootcamp:v10"
  Warning  Failed     19s (x2 over 46s)  kubelet, minikube  Failed to pull image
 "gcr.io/google-samples/kubernetes-bootcamp:v10": rpc error: code = Unknown desc
 = Error response from daemon: Get https://gcr.io/v2/: net/http: request cancele
d while waiting for connection (Client.Timeout exceeded while awaiting headers)
  Warning  Failed     19s (x2 over 46s)  kubelet, minikube  Error: ErrImagePull
  Normal   BackOff    4s (x2 over 46s)   kubelet, minikube  Back-off pulling ima
ge "gcr.io/google-samples/kubernetes-bootcamp:v10"
  Warning  Failed     4s (x2 over 46s)   kubelet, minikube  Error: ImagePullBack
Off

仓库中没有名为 v10 的镜像。现在要回到之前的可以正常工作的版本。使用 rollout undo 命令:

$ kubectl rollout undo deployments/kubernetes-bootcamp
deployment.apps/kubernetes-bootcamp rolled back

rollout 命令将 Deployment 恢复到之前已知的状态(v2 版本的镜像)。更新是版本化的,你可以恢复到任何之前知道的 Deployment 状态。再次列出 Pods:

$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-7d6f8694b6-hxw49   1/1     Running   0          5h11m
kubernetes-bootcamp-7d6f8694b6-lqfwl   1/1     Running   0          5h11m

可以看到已经回退。

你可能感兴趣的:(K8S学习笔记之官方入门示例)