Kubernetes

3 天前

Kubernetes

Kubernetes 部署

构建 Pod

尽管Kubernetes可以编排和运行容器,但这些容器不得不被包装在一个叫Pod的Kubernetes结构中。就把Pod想象成一个围绕容器的轻量级包装器。事实上,我们有时会互换使用容器和Pod这两个术语。现在,你只需要知道Kubernetes在Pod中运行容器。

要部署的Pod是在一个叫pod.yml的YAML文件中定义的

apiVersion: v1
kind: Pod 
metadata:
  name: first-pod
  labels:
    project: qsk-book 
spec:
  containers:
  - name: web 
    image: nigelpoulton/qsk-book:1.0 
    ports:
- containerPort: 8080

查询运行的Pod

kubectl get pods

部署Pod

$ kubectl apply -f pod.yml
pod/first-pod created
 
$ kubectl get pods 
NAME          READY       STATUS    RESTARTS      AGE
first-pod     1/1         Running       0         10s

kubectl提供了get和describe两个命令来查询对象的配置和状态

kubectl describe pod first-pod
kubectl get pod first-pod

提示: 尽管Pod已经启动,应用正在运行,但你还需要另一个Kubernetes对象才能在网络上连接到该应用

连接到Pod

连接到Pod中的应用需要一个独立的对象,称为Service(服务)。Service对象的唯一用途是提供到与Pod中运行的应用的稳定网络连通性。

svc-cloud.yml文件定义了一个Service对象,以便在你的集群在云中时提供连接

apiVersion: v1
kind: Service
metadata:
  name: cloud-lb
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  selector:
project: qsk-book

spec.type:LoadBalancer字段告诉Kubernetes在底层云平台上配置一个面向互联网的负载均衡器。该负载均衡器将在80端口接收流量,并转发到任何带有project: qsk-book标记的Pod的8080端口。

部署Service

同样的也是通过apply来部署Service

$ kubectl apply -f svc-local.yml
service/svc-local created

使用下面的命令来验证该Service已经启动和运行

$ kubectl get svc
NAME      TYPE     CLUSTER-IP    EXTERNAL-IP PORT(S)       AGE
svc-local NodePort 10.108.72.184 <none>      80:31111/TCP  11s
  • CLUSTER-IP值是内部Kubernetes Pod网络上的一个IP地址,被集群上运行的其他Pod和应用使用。

清理kubernetes

清理Service

$ kubectl delete svc cloud-lb
service "cloud-lb" deleted

清理Pod

$ kubectl delete pod first-pod 
pod "first-pod" deleted

自我修复

https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/

有另一个称为Deployment的专用对象,用于提供自我修复(self-healing)。事实上,Deployment也可以实现扩缩容和滚动更新。Deployment 用于管理运行一个应用负载的一组 Pod,通常适用于不保持状态的负载。

image

  1. 容器提供操作系统和其他应用依赖。
  2. Pod提供元数据和其他结构,以便容器在Kubernetes上运行。
  3. Deployment提供云原生功能,包括自我修复。

有两个元素对Deployment的工作很重要:

  1. Deployment对象:是定义Pod和容器的YAML配置。它还定义了要部署多少个Pod副本等事项。
  2. Deployment控制器:是一个运行在控制面板上的进程,它始终在监控集群,确保所有的Deployment对象都按规定运行。

假设你在Kubernetes的Deployment清单中定义了一个应用。它定义了名为zephyr-one的Pod的5个副本。你使用kubectl将其发送给Kubernetes,Kubernetes将5个Pod调度到集群上。在这一点上,观察到的状态(observed state)与期望状态(desired state)一致。这是专业的说法,说的是集群正在运行你要求它运行的内容。但是,假设一个节点发生故障了,名为zephyr-one的Pod数量下降到4个。观察到的状态不再与期望状态相匹配,此时就出现了问题。但不要紧张,Deployment控制器监视着集群,并将看到这一变化。它知道你想要5个Pod,但它只能观察到4个。因此,它将启动第5个Pod,使观察到的状态重新与期望状态保持一致,这个过程对应的技术术语是和解(reconciliation),但我们经常称其为自我修复。

kind: Deployment         <<== 被定义的对象的类型
apiVersion: apps/v1      <<== 要部署的对象的版本
metadata:
  name: qsk-deploy            
spec:
  replicas: 5            <<== 要部署多少个Pod副本
  selector:
    matchLabels:         <<== 告诉Deployment控制器
      project: qsk-book  <<== 管理哪些Pod
  template:
    metadata:
      labels:
        project: qsk-book <<== Pod标签
    spec:   
      containers:
      - name: qsk-pod
        imagePullPolicy: Always  <<== 永远不使用本地镜像
        ports:
        - containerPort: 8080             <<== 网络端口
image: nigelpoulton/qsk-book:1.0  <<== 要使用的镜像

查询Deployments

kubectl get deployments

部署Deployments

$ kubectl apply -f deploy.yml
deployment.apps/qsk-deploy created

Pod和它们运行的应用有可能崩溃或发生故障。Kubernetes可以通过启动一个新的Pod来替代失败的Pod,从而尝试自我修复这样的情况。

应用扩缩容

应用扩容

扩缩容的单位是Pod,因此扩容将增加Pod副本,而缩容将删除Pod副本。

手动编辑Deployment YAML文件,将副本的数量增加到10个,并重新将其发送给Kubernetes

检查当前的副本数量

$ kubectl get deployment qsk-deploy
NAME          READY   UP-TO-DATE   AVAILABLE   AGE
qsk-deploy    5/5     5            5           16h

编辑deploy.yml文件,将spec.replicas字段设置为10,并保存修改:

apiVersion: apps/v1
kind: Deployment 
metadata:
  name: qsk-deploy 
spec:
  replicas: 5           <<== 将这里改成10
  selector: 
    matchLabels: 
      project: qsk-book 
<Snip>

使用kubectl将更新的文件重新发送给Kubernetes。当Kubernetes收到该文件时,它将把期望状态从5个副本改为10个。Deployment控制器将观察集群上的5个副本,并注意到它不符合新的期望状态。它将调度5个新副本,使观察到的状态与期望状态一致。

应用缩容

应用缩容在本节中,你将使用kubectl scale命令将Pod的数量缩减回5个。这种方法被称为命令式方法,不像声明式方法那样常见

$ kubectl scale --replicas 5 deployment/qsk-deploy
deployment.apps/qsk-deploy scaled

注意:用kubectl scale命令式地完成扩缩容操作会很危险。

滚动更新

即使Kubernetes以有条不紊的方式每次更新1个副本,直到5个副本都运行新版本。

更新deploy.yml文件

1 apiVersion: apps/v1
2 kind: Deployment 
3 metadata:
4   name: qsk-deploy 
5 spec:
6   replicas: 5 
7   selector:
8     matchLabels:
9       project: qsk-book 
10  minReadySeconds: 20            <<== 添加这一行
11  strategy:                      <<== 添加这一行
12    type: RollingUpdate          <<== 添加这一行
13    rollingUpdate:               <<== 添加这一行
14      maxSurge: 1                <<== 添加这一行
15      maxUnavailable: 0          <<== 添加这一行
16  template:
17    metadata:
18      labels:
19        project: qsk-book 
20    spec:
21      containers:
22      - name: hello-pod 
23        imagePullPolicy: Always 
24        ports:
25        - containerPort: 8080 
26        image: nigelpoulton/qsk-book:1.1 <<== 设置为1.1
  • minReadySeconds: 20:告诉Kubernetes在更新每个副本后要等待20秒。

提示: Kubernetes实际上没有更新副本,它所做的是删除现有的副本,并用一个运行新版本的全新副本来代替它们

  • 更新类型为RollingUpdate:以滚动更新的方式执行对此Deployment的所有更新
  • 第14行和第15行强制Kubernetes一次更新一个Pod,运行机制是:第14行中maxSurge=1允许Kubernetes在更新操作中增加一个额外的Pod,期望状态需要5个Pod,所以Kubernetes可以在更新期间将其增加到6个;第15行中maxUnavailable=0防止Kubernetes在更新期间减少Pod的数量,期望状态还是需要5个Pod,所以Kubernetes不允许比这更少。结合起来,第14行和第15行迫使Kubernetes删除运行旧版本的副本的同时增加运行新版本的第六个副本。这个过程一直重复,直到5个副本全都在运行需要的版本。

当更新完毕deploy.yml后可以使用apply命令进行部署,然后使用如下命令进行监听

$ kubectl rollout status deployment qsk-deploy
Waiting for rollout to finish: 1 out of 5 have been updated...
Waiting for rollout to finish: 1 out of 5 have been updated...
Waiting for rollout to finish: 2 out of 5 have been updated...
Waiting for rollout to finish: 2 out of 5 have been updated...
Waiting for rollout to finish: 3 out of 5 have been updated...
Waiting for rollout to finish: 3 out of 5 have been updated...
Waiting for rollout to finish: 4 out of 5 have been updated...
Waiting for rollout to finish: 4 out of 5 have been updated...
Waiting for rollout to finish: 2 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
deployment "qsk-deploy" successfully rolled out