<$>[note] 本文补充了关于部署和管理云中的集装箱工作负载的Webinar系列(https://go.digitalocean.com/containers-and-microservices-webinars-series)。该系列涵盖了集装箱的基本内容,包括管理集装箱生命周期,部署多集装箱应用程序,扩展工作负载,以及与Kubernetes合作。
本文补充了系列中的第四个会话, A Closer Look at Kubernetes. <$>
[youtube YI0yX1Bz6tk 480 854 ]
介绍
Kubernetes是一个开源集装箱编排工具,用于管理集装箱应用程序. 在 本系列的上一个教程中,您在DigitalOcean上配置了Kubernetes。
在本教程中,您将学习这些原始元素如何在 Kubernetes 中部署一个Pod,将其暴露为服务,并通过复制控制器扩展。
前提条件
要完成本教程,你应该先完成本系列的上一个教程, Getting Started with Kubernetes。
步骤1 - 了解Kubernetes原始
Kubernetes 揭示了客户端用于创建、扩展和终止应用程序的 API。每个操作都针对 Kubernetes 管理的更多对象之一。
以下是 Kubernetes 关键 API 对象的摘要:
- 集群:计算、存储和网络资源池
- 节点:在集群内运行的主机
- 名空间:集群的逻辑分区
- Pods:部署单位
- 标签和 选择者:用于识别和服务发现的关键值对
- 服务:属于同一应用程序的Pods集合
- 复制集合:确保可用性和可扩展性
- 部署:管理应用程序生命周期
让我们仔细看看这些。
运行 Kubernetes 集群的 Nodes 也被视为对象。 它们可以像其他任何 Kubernetes API 对象一样被管理。 为了实现应用程序的逻辑分离,Kubernetes 支持创建 _Namespaces。 例如,一个组织可以逻辑地分区一个 Kubernetes 集群进行开发、测试、阶段化和生产环境。
尽管 Kubernetes 运行 Docker 容器,但这些容器无法直接部署。相反,应用程序需要以 Kubernetes 理解的格式包装。
Kubernetes 中的包装和部署的基本单元称为 _Pod。每个 Pod 都可能包含一个或多个需要一起管理的容器。例如,一个 Web 服务器(Nginx)容器和一个缓存(Redis)容器可以作为一个 Pod 一起包装。Kubernetes 将所有属于 Pod 的容器作为一个逻辑单元处理。每次创建一个新的 Pod,它会导致在 Pod 定义中声明的所有容器的创建。Pod 中的所有容器都共享相同的背景,如 IP 地址、主机名称和存储。
一旦容器被包装并部署在Kubernetes上,则需要将其暴露给内部和外部访问。数据库和缓存等某些容器不需要暴露给外部世界。由于API和Web前端将被其他消费者和最终用户直接访问,因此必须向公众暴露。
Kubernetes 中的 Pods 通过 Services 曝光。每个服务都被宣布为内部或外部终端,以及端口和协议信息。 内部消费者,包括其他 Pods 和外部消费者,如 API 客户端,依赖 Kubernetes 服务进行基本交互。
Kubernetes 中的每个对象,例如 Pod 或服务,都与附加元数据相关联,称为 Labels 和 Selectors. 标签是与 Kubernetes 对象附加的关键/值对。 这些标签独特地识别一个或多个 API 对象。 选择者将一个 Kubernetes 对象与另一个对象相关联。 例如,在服务中定义的选择者帮助 Kubernetes 找到与选择器值相匹配的所有 Pods 标签。 这种关联允许动态发现对象。 使用相同标签运行时创建的新对象将立即被发现并与相应的选择者相关联。 该服务发现机制允许有效的动态配置,如扩展和扩展操作。
转换到容器的优点之一是快速扩展。由于容器与虚拟机相比轻量化,您可以在几秒钟内扩展它们。为了实现高度可用和可扩展的设置,您需要部署多个应用程序实例,并确保这些应用程序的最少实例总是运行。为了解决这种容器化应用程序的配置,Kubernetes 引入了 Replica Sets 的概念,这些实例旨在随时运行一个或多个Pods。当多个Pods需要在一个集群中运行时,它们将被包装为Replica Sets。Kubernetes 将确保在 Replica Set 中定义的Pods 数量始终处于运行模式。如果一个Pods由于硬件或配置问题而终止,Kubernetes 控制飞机将立即启动另一个Pods。
一个 Deployment 对象是 Pods 和 Replica 组合的组合,它为 Kubernetes 应用程序带来了类似 PaaS 的功能,允许您对现有部署进行滚动升级,且停机时间最少。
步骤2:列出Kubernetes节点和名称空间
假设您已遵循 在 DigitalOcean 中设置 Kubernetes 集群的步骤,请运行以下命令列出所有可用的节点和名称空间:
1kubectl get nodes
1[secondary_label Output]
2NAME STATUS ROLES AGE VERSION
3spc3c97hei-master-1 Ready master 10m v1.8.7
4spc3c97hei-worker-1 Ready <none> 4m v1.8.7
5spc3c97hei-worker-2 Ready <none> 4m v1.8.7
1kubectl get namespaces
1[secondary_label Output]
2NAME STATUS AGE
3default Active 11m
4kube-public Active 11m
5kube-system Active 11m
6stackpoint-system Active 4m
当没有指定名称空间时,‘kubectl’会瞄准默认的名称空间。
现在,让我们启动一个应用程序。
步骤 3 – 创建和部署一个Pod
Kubernetes 对象在 YAML 文件中声明并通过kubectl
CLI 提交给 Kubernetes. 让我们定义一个 Pod 并部署它。
创建一个名为Simple-Pod.yaml
的新 YAML 文件:
1nano Simple-Pod.yaml
添加以下代码,该代码定义了基于 Nginx Web 服务器的一个容器的 Pod. 它在 TCP 协议上的端口80
上曝光. 请注意,该定义包含标签名称
和env
。
1[label Simple-Pod.yaml]
2apiVersion: "v1"
3kind: Pod
4metadata:
5 name: web-pod
6 labels:
7 name: web
8 env: dev
9spec:
10 containers:
11 - name: myweb
12 image: nginx
13 ports:
14 - containerPort: 80
15 name: http
16 protocol: TCP
运行以下命令来创建一个Pod。
1kubectl create -f Simple-Pod.yaml
1[secondary_label Output]
2pod "web-pod" created
让我们来检查Pod的创建。
1kubectl get pods
1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3web-pod 1/1 Running 0 2m
在下一步中,我们将使这个Pod可供公共互联网使用。
步骤 4 – 通过服务曝光 Pods
服务内部或外部暴露了一组Pod。让我们定义一个服务,使 Nginx pod 公开可用。我们将通过NodePort暴露 Nginx,这是一种系统,通过群集的每个节点打开的任意端口使Pod可访问。
创建一个名为Simple-Service.yaml
的新文件,该文件包含此代码,该代码定义了 Nginx 的服务:
1[label Simple-Service.yaml]
2apiVersion: v1
3kind: Service
4metadata:
5 name: web-svc
6 labels:
7 name: web
8 env: dev
9spec:
10 selector:
11 name: web
12 type: NodePort
13 ports:
14 - port: 80
15 name: http
16 targetPort: 80
17 protocol: TCP
该服务在同一个名称空间中发现所有匹配名称:web
标签的 Pods. YAML 文件的选择器部分明确定义了这一关联。
我们指定服务是NodePort类型通过类型:NodePort声明。
然后使用 kubectl 将其提交到集群中。
1kubectl create -f Simple-Service.yml
您将看到此输出,表示该服务已成功创建:
1[secondary_label Output]
2service "web-svc" created
让我们获得Pod可用的端口。
1kubectl get services
1[secondary_label Output]
2NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
3kubernetes ClusterIP 10.3.0.1 <none> 443/TCP 28m
4web-svc NodePort 10.3.0.143 <none> 80:32097/TCP 38s
从这个输出中,我们可以看到服务在端口32097
上可用,让我们尝试连接到一个工人节点。
使用 DigitalOcean 控制台获取工作节点之一的 IP 地址。
使用curl
命令将 HTTP 请求发送到端口31930
上的一个节点。
1curl http://your_worker_1_ip_address:32097
您将看到包含 Nginx 默认主页的答案:
1[secondary_label Output]
2<!DOCTYPE html>
3<html>
4 <head>
5 <title>Welcome to nginx!</title>
6...
7 Commercial support is available at
8 <a href="http://nginx.com/">nginx.com</a>.</p>
9 <p><em>Thank you for using nginx.</em></p>
10 </body>
11</html>
你已经定义了Pod和服务,现在让我们来看看使用Replica Sets进行扩展。
步骤5 – 通过复制组扩展插件
复制组确保在集群中至少运行最少数个Pod。 让我们删除当前的Pod并通过复制组重新创建三个Pod。
首先,删除现有的Pod。
1kubectl delete pod web-pod
1[secondary_label Output]
2pod "web-pod" deleted
现在创建一个新的 Replica Set 声明. Replica Set 的定义与 Pod 相同. 关键差异是,它包含了定义需要运行的 Pod 数量的 replika 元素。
创建文件 Simple-RS.yml
,并将此代码添加到文件中:
1[label Simple-RS.yml]
2apiVersion: apps/v1beta2
3kind: ReplicaSet
4metadata:
5 name: web-rs
6 labels:
7 name: web
8 env: dev
9spec:
10 replicas: 3
11 selector:
12 matchLabels:
13 name: web
14 template:
15 metadata:
16 labels:
17 name: web
18 env: dev
19 spec:
20 containers:
21 - name: myweb
22 image: nginx
23 ports:
24 - containerPort: 80
25 name: http
26 protocol: TCP
保存并关闭文件。
现在创建复制套件:
1kubectl create -f Simple-RS.yml
1[secondary_label Output]
2replicaset "web-rs" created
然后检查Pods的数量:
1kubectl get pods
1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3web-rs-htb58 1/1 Running 0 38s
4web-rs-khtld 1/1 Running 0 38s
5web-rs-p5lzg 1/1 Running 0 38s
当我们通过 NodePort 访问服务时,请求将发送到由 Replica Set 管理的 Pods 之一。
让我们通过删除其中一个Pod来测试复制集的功能,看看会发生什么:
1kubectl delete pod web-rs-p5lzg
1[secondary_label Output]
2pod "web-rs-p5lzg" deleted
再来看看子:
1kubectl get pods
1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3web-rs-htb58 1/1 Running 0 2m
4web-rs-khtld 1/1 Running 0 2m
5web-rs-fqh2f 0/1 ContainerCreating 0 2s
6web-rs-p5lzg 1/1 Running 0 2m
7web-rs-p5lzg 0/1 Terminating 0 2m
一旦Pod被删除,Kubernetes就创建了另一个,以确保所需的计数保持。
现在让我们来看看部署。
步骤6 – 处理部署
虽然您可以部署容器,如Pod和Replica集,但部署使您的应用程序更容易升级和修补。您可以使用部署升级一个Pod,而你不能使用Replica集。
在创建部署之前,请删除现有的 replika set. 这也将删除相关的pods:
1kubectl delete rs web-rs
1[secondary_label Output]
2replicaset "web-rs" deleted
现在定义一个新的部署. 创建文件 Simple-Deployment.yaml
并添加以下代码:
1[label Simple-Deployment.yaml]
2apiVersion: apps/v1beta2
3kind: Deployment
4metadata:
5 name: web-dep
6 labels:
7 name: web
8 env: dev
9spec:
10 replicas: 3
11 selector:
12 matchLabels:
13 name: web
14 template:
15 metadata:
16 labels:
17 name: web
18 spec:
19 containers:
20 - name: myweb
21 image: nginx
22 ports:
23 - containerPort: 80
创建部署并验证创建。
1kubectl create -f Simple-Deployment.yml
1[secondary_label Output]
2deployment "web-dep" created
查看部署:
1kubectl get deployments
1[secondary_label Output]
2NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
3web-dep 3 3 3 3 1m
由于部署会导致创建 Pods,所以根据 YAML 文件中的 replika 声明,将有三个 Pods 运行。
1kubectl get pods
1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3web-dep-8594f5c765-5wmrb 1/1 Running 0 2m
4web-dep-8594f5c765-6cbsr 1/1 Running 0 2m
5web-dep-8594f5c765-sczf8 1/1 Running 0 2m
我们之前创建的服务将继续将请求路由到部署创建的Pod,这是因为标签包含与原始Pod定义相同的值。
通过删除部署和服务来清理资源。
1kubectl delete deployment web-dep
1[secondary_label Output]
2deployment "web-dep" deleted
1kubectl delete service web-svc
1[secondary_label Output]
2service "web-svc" deleted
有关部署的更多细节,请参阅 Kubernetes 文档。
结论
在本教程中,您探索了Kubernetes的基本构建块,当您使用Pod,服务,复制集和部署部署 Nginx Web 服务器。
在本系列的下一部分中,您将学习如何包装,部署,扩展和管理多容器应用程序。