DeploymentDeployment 是 Kubernetes 提供的一种自我修复机制来解决机器故障维护的问题。 当我们单独使用 docker 部署应用时,为了应用挂了后能够重启,我们可以使用 --restart=always 参数,例如: docker run -itd --restart=always -p 666:80 nginx:latest 但是这种方式只能单纯重启容器,并不具备从机器故障中恢复的能力。 Kubernetes Deployment 是一个配置,它可以指挥 Kubernetes 如何创建和更新你部署的应用实例,创建 Deployment 后,Kubernetes master 会将应用程序调度到集群中的各个节点上。Kubernetes Deployment 提供了一种与众不同的应用程序管理方法。 Deployment 的创建,有两种方法,一种是直接使用命令创建,一种是通过 yaml,后面我们会介绍这两种创建方法。 创建 Deployment我们来部署一个 Nginx 应用。 kubectl create deployment nginx --image=nginx:latest 在 worker 节点上执行 docker ps ,可以看到: root@instance-2:~# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESfe7433f906a0 nginx "/docker-entrypoint.…" 7 seconds ago Up 6 seconds k8s_nginx_nginx-55649fd747-wdrjj_default_ea41dcc4-94fe-47f9-a804-5b5b1df703e9_0 获取所有 deployment : NAME READY UP-TO-DATE AVAILABLE AGEnginx 1/1 1 1 2m24s 使用 kubectl describe deployment nginx 可以获得更加详细的信息。 使用 kubectl get events 可以获得创建 Deployment 到部署容器过程的详细事件记录。 Successfully assigned default/nginx-55649fd747-wdrjj to instance-2Pulling image "nginx:latest"Successfully pulled image "nginx:latest" in 8.917597859sCreated container nginxStarted container nginxCreated pod: nginx-55649fd747-wdrjjScaled up replica set nginx-55649fd747 to 1 我们也可以使用 yaml 文件创建 Deployment: kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml 导出 yaml无论哪种部署方式,我们都可以从已经创建的 Deployment 导出 yaml 文件,使用 -o yaml 即可导出(-o json 导出json)。 kubectl get deployment nginx -o yaml# 保存到文件# kubectl get deployment nginx -o yaml > mynginx.yaml 然后终端会打印: apiVersion: apps/v1kind: Deploymentmetadata: annotations: deployment.kubernetes.io/revision: "1" creationTimestamp: "2021-04-21T00:37:13Z" generation: 1 labels: app: nginx name: nginx namespace: default... ... 我们可以尝试把 yaml 导出到 mynginx.yaml 文件中,然后我们删除这个 Deployment。 kubectl delete deployment ngin 然后利用导出的 mynginx.yaml 再创建一个 Deployment。 kubectl apply -f mynginx.yaml kubectl apply/create当我们创建一个 deployment 时,kubectl create 和 kubectl apply 效果是一样的,但是 apply 还具有更新(update) 的功能。 kubectl apply 会在以前的配置、提供的输入和资源的当前配置之间 找出三方差异,以确定如何修改资源,kubectl apply 命令将会把推送的版本与以前的版本进行比较,并应用你所做的更改, 但是不会自动覆盖任何你没有指定更改的属性
另外还有 kubectl replace 、kubectl edit ,kubectl replace 是破坏性更新/替换,容易导致问题;kubectl edit 可以更新 deployment。 根据 Kubernetes 官方的文档,应始终使用 kubectl apply 或 kubectl create --save-config 创建资源。 这里再说一下创建 deployment 的区别。 如果使用 create 创建,命令格式: kubectl create deployment {deployment的名字} --image={镜像名称} 如果使用 apply 命令创建,yaml 中需要指定一些信息: kind: Deployment... ...medatada: name:nginx... ... spec: containers: - image: nginx:latest 然后执行 kubectl apply -f xxx.yaml 文件。 一个是 kubectl create deployment ;另一个是 kubectl apply -f ,在 yaml 中指定 kind: Deployment 。 有时我们不知道我们的创建命令或 yaml 是否正确,可以使用 --dry-run=client ,--dry-run=client 参数来预览而不真正提交。 kubectl create deployment testnginx --image=nginx:latest --dry-run=client 在一些 k8s 认证中,我们没时间一点点写 yaml ,但是又需要定制,此时可以使用 --dry-run=client -o yaml ,既可以不生效 Deployment,又可以导出 yaml 文件。 kubectl create deployment testnginx --image=nginx:latest --dry-run=client -o yaml 除了 deployment,其它 kubernetes 对象也可以使用这种方法,格式是 kubectl {对象} {参数} --dry-run=client -o yaml 。 kubernetes 对象/资源,有 deployment、job、role、namespace 等。 还有一个地方也说一下,kubectl get xxx 时,带不带 s 都没关系,例如 kubectl get nodes / kubectl get node 都是一样的。 不过,一般从语义上,我们获取全部对象时,可以使用 kubectl get nodes ,获取具体的对象时,可以使用 kubectl get node nginx 。类似的,kubectl describe nodes 、kubectl describe node nginx 。实际上加不加 s 都一样。 网络端口映射和更新 Deployment对于 docker,我们要映射端口时,可以使用 docker ... -p 6666:80 ,那么对于 deployment 部署容器应用,我们怎么处理呢? 我们可以看一下 https://k8s.io/examples/controllers/nginx-deployment.yaml 文件, spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 这里我们不直接使用这个 yaml 文件,继续使用之前的 yaml 文件,我们首先部署一个 nginx。 kubectl apply -f mynginx.yaml 然后修改 mynginx.yaml 文件,找到 image: nginx:latest ,在后面加上端口映射。 spec: containers: - image: nginx:latest imagePullPolicy: Always name: nginx ports: - containerPort: 80 protocol: TCP... ...注:在里面加上了 ports: - containerPort: 80 protocol: TCP 这三行。 然后删除两行字段: resourceVersion: "109967" uid: e66201e3-a740-4c1c-85f5-a849db40a0fd 因为这两个字段限定了版本和 uid ,这样替换或更新的时候,可以对 nginx 的 deployment 直接操作。 查看 deployment、pod: kubectl get deployment,pod NAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/nginx 1/1 1 1 5m44sNAME READY STATUS RESTARTS AGEpod/nginx-55649fd747-9vfrx 1/1 Running 0 5m44s 然后我们创建 service。 kubectl expose deployment nginx 或者指定端口: kubectl expose deployment nginx --port=80 --target-port=8000 查看 service: NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24hnginx ClusterIP 10.101.245.225 <none> 80/TCP 5m57s 查看 端口: NAME ENDPOINTS AGEkubernetes 10.170.0.2:6443 25hnginx 192.168.56.24:80 17m 查看 Pod 信息信息: kubectl describe pod nginx | grep Node: Node: instance-2/10.170.0.4 因为 deployment 部署的 应用/pod ,不会在 master 上,不同 Node 是不能访问的。 使用 kubectl get services 或 kubectl get ep 查询的 ip ,我们可以在 worker 节点上直接访问。 例如笔者查询出来的 ip,可以在 worker 中这样访问。 curl 192.168.56.24:80curl 10.101.245.225:80 ReplicaSet我们执行 kubectl get deployments 命令,输出: NAME READY UP-TO-DATE AVAILABLE AGEnginx 1/1 1 1 38m NAME 列出了集群中 Deployment 的名称。READY 显示应用程序的可用的 副本 数。显示的模式是“就绪个数/期望个数”。UP-TO-DATE 显示为了达到期望状态已经更新的副本数。AVAILABLE 显示应用可供用户使用的副本数。AGE 显示应用程序运行的时间。
副本因为容器化应用中,根据云原生12因素的方法论和核心思想,一个 Processes 应当是无状态的,任何持久化的数据都要存储在后端服务中。因此,A 镜像,启动 N 个 docker 容器,端口为 801、802、803...,他们其实都是一样的,我们访问哪个容器,最终提供的服务都是一致的。 但是,如果我们把这些容器放到不同 Node 中,再通过 k8s ,就可以为多个实例之间分配流量,即负载均衡。 在 Deployment 中,可以通过指定 yaml 文件的 .spec.replicas 字段或者以命令参数 --replicas= 设置副本数量。 ReplicaSet“ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。 因此,它通常用来保证给定数量的、完全相同的 Pod 的可用性。” 感兴趣的读者可以看文档:https://kubernetes.io/zh/docs/concepts/workloads/controllers/replicaset/ 在前面,我们已经创建了 nginx ,接下来我们在这个 deployment 中修改副本数。 kubectl scale deployment nginx --replicas=3 然后等几秒后执行 kubectl get deployments 查看结果。 NAME READY UP-TO-DATE AVAILABLE AGEnginx 3/3 3 3 3h15m 执行 kubectl get pod -o wide 可以输出信息的 pod 信息 。 NAME READY STATUS ESTARTS AGE IP NODE NOMINATED NODE READINESS GATESnginx-581 1/1 Running 0 3h11m 192.168.56.24 instance-2 <none> <none>nginx-582 1/1 Running 0 3m30s 192.168.56.25 instance-2 <none> <none>nginx-583 1/1 Running 0 3m30s 192.168.56.26 instance-2 <none> <none># 注,笔者删除了Name的部分名称 可以看到 这几个 pod 都分配在 instance-2 这个节点上,因为我只有一台 worker 节点服务器,如果多创建几台节点服务器,k8s 会自动分配到不同的节点中。什么的输出也可以看到,每个 pod 都有自己的 ip 地址。 当我们使用 kubectl delete xxx 删除 pod 时,Deployment 会自动保持三个副本集,所以会自动启用新的 pod 。 执行 kubectl get ep 可以看到不同 pod 暴露的 端口。 NAME ENDPOINTS AGEkubernetes 10.170.0.2:6443 28hnginx 192.168.56.24:80,192.168.56.25:80,192.168.56.26:80 3h15m 下载地址: 搭建Consul服务发现与服务网格 Kubernetes控制节点的部署 |