使用Kubernetes管理Docker集群
使用Kubernetes管理Docker集群

什么是Kubernetes集群?

Kubernetes是一个来管理容器化应用程序的开源平台。如果您使用Docker将应用部署到多个服务器节点上,Kubernetes集群就可以管理您的服务器和应用,包括扩展、部署和滚动更新等操作。

Kubernetes集群由至少一个主节点和多个工作节点组成。主节点运行API服务器、调度程序和控制器管理器,并在集群中动态部署应用程序。

系统要求

要完成本指南的操作,您需要三台运行Ubuntu 16.04 LTS的服务器,每台服务器内存需在4GB以上。

开始前的准备

本文需要您首先完成如何在Kubernetes集群上安装,配置和部署NGINX指南的相关操作,并按照其中的步骤配置一个主节点和两个工作节点。

设置三台服务器主机名如下:

  • 主节点:kube-master
  • 第一个工作节点:kube-worker-1
  • 第二个工作节点:kube-worker-2

除非另有说明,否则以下的所有命令都将在kube-master节点上执行。

Kubernetes Pods

每个Pod由一个或多个紧密耦合的容器组成,这些容器共享存储和网络等资源。Pod中的容器以Pod为单位启动、停止或复制。

Kubernetes Pods
Kubernetes Pods

创建部署

部署(Deployments)是可以管理Pod创建的高级对象,并支持声明性扩展和滚动升级等功能。

1.在文本编辑器中,创建nginx.yaml配置文件并添加以下内容。

~/nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-server
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.13-alpine
        ports:
        - containerPort: 80

该文件包含了定义一个部署所需的所有必要信息,包括要使用的Docker镜像、副本数量以及容器端口。要了解关于配置部署的更多信息,请参阅官方文档

2.创建您的第一个部署:

kubectl create -f nginx.yaml --record

3.查看部署列表:

kubectl get deployments
NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-server   1         1         1            1           13s

4.检查Pod状态:

kubectl get pods
NAME                           READY     STATUS    RESTARTS   AGE
nginx-server-b9bc6c6b5-d2gqv   1/1       Running   0          58

5.要查看部署的创建节点,请添加-o wide参数:

kubectl get pods -o wide
NAME                           READY     STATUS    RESTARTS   AGE       IP                NODE
nginx-server-b9bc6c6b5-d2gqv   1/1       Running   0          1m        192.168.255.197   kube-worker-02

扩展部署

Kubernetes可以轻松扩展部署以添加或删除副本。

1.将副本的数量增加到8:

kubectl scale deployment nginx-server --replicas=8

2.检查新副本的可用性:

kubectl get pods -o wide
NAME                           READY     STATUS    RESTARTS   AGE       IP               NODE
nginx-server-b9bc6c6b5-4mdf6   1/1       Running   0          41s       192.168.180.10   kube-worker-1
nginx-server-b9bc6c6b5-8mvrd   1/1       Running   0          3m        192.168.180.9    kube-worker-1
nginx-server-b9bc6c6b5-b99pt   1/1       Running   0          40s       192.168.180.12   kube-worker-1
nginx-server-b9bc6c6b5-fjg2c   1/1       Running   0          40s       192.168.127.12   kube-worker-2
nginx-server-b9bc6c6b5-kgdq5   1/1       Running   0          41s       192.168.127.11   kube-worker-2
nginx-server-b9bc6c6b5-mhb7s   1/1       Running   0          40s       192.168.180.11   kube-worker-1
nginx-server-b9bc6c6b5-rlf9w   1/1       Running   0          41s       192.168.127.10   kube-worker-2
nginx-server-b9bc6c6b5-scwgj   1/1       Running   0          40s       192.168.127.13   kube-worker-2

3.可以使用同样的命令减少副本的数量:

kubectl scale deployment nginx-server --replicas=3

滚动更新

通过部署来管理Pod允许您使用滚动更新(Rolling Upgrades)的功能。滚动更新是一种允许您在不停机的情况下更新应用程序版本的机制。Kubernetes确保至少有25%的Pod可随时提供服务,并会在删除旧Pod之前先创建新的Pod。

1.将容器的NGINX版本从 1.13 升级到 1.13.8:

kubectl set image deployment/nginx-server nginx=nginx:1.13.8-alpine

与扩展过程类似,set命令使用声明性方法:您只需指定所需的目标状态,控制器会管理完成该目标所需的所有任务。

2.检查更新状态:

kubectl rollout status deployment/nginx-server
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
deployment "nginx-server" successfully rolled out

3.你可以使用describe命令手动检查应用程序版本:

kubectl describe pod <pod-name>

4.如果发生错误,回滚(Rollout)将被挂起,系统将强制要求用户输入 CTRL + C 以取消更新。通过设置无效的NGINX版本来测试:

kubectl set image deployment/nginx-server nginx=nginx:1.18.

5.查看当前Pod状态:

kubectl get pods -o wide
NAME                            READY     STATUS             RESTARTS   AGE       IP               NODE
nginx-server-76976d4555-7nv6z   1/1       Running            0          3m        192.168.127.15   kube-worker-2
nginx-server-76976d4555-wg785   1/1       Running            0          3m        192.168.180.13   kube-worker-1
nginx-server-76976d4555-ws4vf   1/1       Running            0          3m        192.168.127.14   kube-worker-2
nginx-server-7ddd985dd6-mpn9h   0/1       ImagePullBackOff   0          2m        192.168.180.16   kube-worker-1

可以看到名为nginx-server-7ddd985dd6-mpn9h的Pod正在试图将NGINX更新到一个不存在的版本。

6.检查此Pod以获取该错误的更多详细信息:

kubectl describe pod nginx-server-7ddd985dd6-mpn9h

7.由于在创建部署时使用了--record参数,您可以通过以下命令检索完整的历史记录:

kubectl rollout history deployment/nginx-server
REVISION  CHANGE-CAUSE
1         kubectl scale deployment nginx-server --replicas=3
2         kubectl set image deployment/nginx-server nginx=nginx:1.13.8-alpine
3         kubectl set image deployment/nginx-server nginx=nginx:1.18

8.您可以使用undo命令回滚到之前的工作版本:

kubectl rollout undo deployment/nginx-server

9.要回滚到特定的版本,请使用--to-revision选项以指定要回滚的目标版本:

kubectl rollout undo deployment/nginx-server --to-revision=1

Kubernetes服务

您现在已经有了一个运行三个Pod的部署,每个Pod都运行了一个NGINX应用。要将Pod发布到互联网,您需要创建一个 服务。在Kubernetes中,服务是一种抽象,允许随时访问Pod。服务会自动处理IP更改,更新以及扩展,因此在启用该服务后,只要运行的Pod保持活动状态,就可通过互联网访问您的应用程序。

1.配置一个测试服务。

~/nginx-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    run: nginx
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: nginx

2.创建服务:

kubectl create -f nginx-service.yaml

3.检查新服务的状态:

kubectl get services
NAME            TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.96.0.1             443/TCP        2d
nginx-service   NodePort    10.97.41.31           80:31738/TCP   38m

服务正在运行并接受31738端口上的连接。

4.测试服务:

curl <MASTER_LINODE_PUBLIC_IP_ADDRESS>:<PORT(S)>

5.使用describe命令查看此服务的其他信息:

kubectl describe service nginx-service
Name:                     nginx-service
Namespace:                default
Labels:                   run=nginx
Annotations:               
Selector:                 app=nginx
Type:                     NodePort
IP:                       10.97.41.31
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  31738/TCP
Endpoints:                192.168.127.14:80,192.168.127.15:80,192.168.180.13:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                    

Kubernetes命名空间

命名空间是是一个逻辑环境,可以灵活的在多个团队或用户之间划分集群资源。

1.查看可用的命名空间:

kubectl get namespaces
default       Active        7h
kube-public   Active        7h
kube-system   Active        7h

顾名思义,如果未指定其他的命名空间,则您的部署将会放置在default命名空间下。kube-system为Kubernetes创建的对象保留,而kube-public则对所有用户可用。命名空间可以通过.json文件创建,也可以直接在命令行创建。

2.为 development 环境新建名为dev-namespace.json的文件。

~/home/dev-namespace.json

{
  "kind": "Namespace",
  "apiVersion": "v1",
  "metadata": {
    "name": "development",
    "labels": {
      "name": "development"
    }
  }
}

3.在集群中创建命名空间:

kubectl create -f dev-namespace.json

4.再次查看命名空间:

kubectl get namespaces

上下文

要使用命名空间,您需要定义使用命名空间的 上下文(Context)。Kubernetes上下文保存在kubectl配置文件中。

1.查看当前的配置:

kubectl config view

2.检查您当前正在使用的上下文:

kubectl config current-context

3.使用以下命令添加dev上下文:

kubectl config set-context dev --namespace=development \
--cluster=kubernetes \
--user=kubernetes-admin

4.切换至dev上下文/命名空间:

kubectl config use-context dev

5.验证更改是否生效:

kubectl config current-context

6.查看新的配置:

kubectl config view

7.命名空间中的Pod对其他命名空间不可见。列出您的Pod来检查该特性:

kubectl get pods

系统提示“No resources found”,是因为您未在此命名空间中创建Pod或部署,不过您仍然可以添加--all-namespaces参数来查看这些对象:

kubectl get services --all-namespaces

标签

Kubernetes中的任何对象都可以添加标签。标签是一组键值对,可以帮助用户基于各种特征更加轻松的组织、过滤并选择对象。

1.在此命名空间中创建一个测试部署,此部署将包含nginx标签。

~/my-app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.12-alpine
        ports:
        - containerPort: 80

2.创建部署:

kubectl create -f my-app.yaml --record

3.如果您只需在集群中查找特定的Pod,而不是列出所有Pod,那么在命令中添加-l选项以按标签搜索通常更有效率:

kubectl get pods --all-namespaces -l app=nginx

这里仅列出了defaultdevelopment命名空间中的Pod,因为它们的定义中包含nginx标签。

Kubernetes节点

Kubernetes节点可以是物理机或虚拟机。可以将节点视为Kubernetes抽象模型中的最高级别。

1.列出您当前的节点:

kubectl get nodes
NAME             STATUS    ROLES     AGE       VERSION
kube-master      Ready     master    21h       v1.9.2
kube-worker-1    Ready         19h       v1.9.2
kube-worker-2    Ready         17h       v1.9.2

2.要查看更多信息,添加-o参数:

kubectl get nodes -o wide

3.显示的信息大部分是自解释的,对于检查全部节点是否准备就绪而言非常有用。您可以使用describe命令以获取特定节点的详细信息:

kubectl describe node kube-worker-1

节点维护

Kubernetes提供了一种非常直接的办法使节点安全离线。

1.返回您正在运行NGINX服务的默认命名空间:

kubectl config use-context kubernetes-admin@kubernetes

2.检查您的Pod:

kubectl get pods -o wide

3.在kube-worker-2节点上禁止新Pod的创建:

kubectl cordon kube-worker-2

4.检查您的节点状态:

kubectl get nodes
NAME             STATUS                     ROLES     AGE       VERSION
kube-master      Ready                      master    4h        v1.9.2
kube-worker-1    Ready                          4h        v1.9.2
kube-worker-2    Ready,SchedulingDisabled       4h        v1.9.2

5.要测试Kubernetes控制器和调度程序,请扩展您的部署:

kubectl scale deployment nginx-server --replicas=10

6.再次查看您的Pod:

kubectl get pods -o wide
NAME                           READY     STATUS    RESTARTS   AGE       IP                NODE
nginx-server-b9bc6c6b5-2pnbk   1/1       Running   0          11s       192.168.188.146   kube-worker-1
nginx-server-b9bc6c6b5-4cls5   1/1       Running   0          11s       192.168.188.148   kube-worker-1
nginx-server-b9bc6c6b5-7nw5m   1/1       Running   0          3d        192.168.255.220   kube-worker-2
nginx-server-b9bc6c6b5-7s7w5   1/1       Running   0          44s       192.168.188.143   kube-worker-1
nginx-server-b9bc6c6b5-88dvp   1/1       Running   0          11s       192.168.188.145   kube-worker-1
nginx-server-b9bc6c6b5-95jgr   1/1       Running   0          3d        192.168.255.221   kube-worker-2
nginx-server-b9bc6c6b5-md4qd   1/1       Running   0          3d        192.168.188.139   kube-worker-1
nginx-server-b9bc6c6b5-r5krq   1/1       Running   0          11s       192.168.188.144   kube-worker-1
nginx-server-b9bc6c6b5-r5nd6   1/1       Running   0          44s       192.168.188.142   kube-worker-1
nginx-server-b9bc6c6b5-ztgmr   1/1       Running   0          11s       192.168.188.147   kube-worker-1

现在总共有10个Pod,但新Pod只在第一个节点中创建。

7.通知kube-worker-2节点停止其运行的Pod:

kubectl drain kube-worker-2 --ignore-daemonsets
node "kube-worker-2" already cordoned
WARNING: Ignoring DaemonSet-managed pods: calico-node-9mgc6, kube-proxy-2v8rw
pod "my-app-68845b9f68-wcqsb" evicted
pod "nginx-server-b9bc6c6b5-7nw5m" evicted
pod "nginx-server-b9bc6c6b5-95jgr" evicted
pod "my-app-68845b9f68-n5kpt" evicted
node "kube-worker-2" drained

8.检查上述命令对您Pod产生的效果:

kubectl get pods -o wide
NAME                           READY     STATUS    RESTARTS   AGE       IP                NODE
nginx-server-b9bc6c6b5-2pnbk   1/1       Running   0          9m        192.168.188.146   kube-worker-1
nginx-server-b9bc6c6b5-4cls5   1/1       Running   0          9m        192.168.188.148   kube-worker-1
nginx-server-b9bc6c6b5-6zbv6   1/1       Running   0          3m        192.168.188.152   kube-worker-1
nginx-server-b9bc6c6b5-7s7w5   1/1       Running   0          9m        192.168.188.143   kube-worker-1
nginx-server-b9bc6c6b5-88dvp   1/1       Running   0          9m        192.168.188.145   kube-worker-1
nginx-server-b9bc6c6b5-c2c5c   1/1       Running   0          3m        192.168.188.150   kube-worker-1
nginx-server-b9bc6c6b5-md4qd   1/1       Running   0          3d        192.168.188.139   kube-worker-1
nginx-server-b9bc6c6b5-r5krq   1/1       Running   0          9m        192.168.188.144   kube-worker-1
nginx-server-b9bc6c6b5-r5nd6   1/1       Running   0          9m        192.168.188.142   kube-worker-1
nginx-server-b9bc6c6b5-ztgmr   1/1       Running   0          9m        192.168.188.147   kube-worker-1

9.您现在已经可以在不中断服务的情况下安全关闭kube-worker-2节点。

10.完成维护后,通知控制器此节点可以再次进行调度:

kubectl uncordon kube-worker-2

参考资料

  1. Manage a Docker Cluster with Kubernetes | Linode
  2. 使用Kubernetes管理Docker集群 | 腾讯云+社区
  3. Kubernetes Handbook | Gitbook
  4. Kubernetes官方文档
  5. Calico官方文档