Kubernetes:让容器编排管理变得容易高效

简介: 在专栏《面向WEB开发人员的Docker》介绍了容器在开发过程中的使用,虽然整个专栏还未完成,想必现有的内容可以大概了解清楚容器的概念,能够做什么。

在专栏《面向WEB开发人员的Docker》介绍了容器在开发过程中的使用,虽然整个专栏还未完成,想必现有的内容可以大概了解清楚容器的概念,能够做什么。

本文是一篇读书笔记,个人觉得内容可以进一步加深了解容器技术应用。

Kubernetes是什么?

Kubernetes(简称k8s) 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具广泛可用。

pod介绍

pod是一组并置的容器,是Kubernetes的基本构建模型。一个pod的所有容器(docker)都运行在同一个工作节点上,绝不会跨越多个工作节点。

pod是Kubernetes中最为重要的核心概念,本文主要围绕 pod 的概念、管理及使用展开。

image.png

为什么需要pod而不直接使用容器

多个容器比单个容器中包含多个进程要好,如果一个容器运行多个进程,在需要查看每个进程的运行日志将非常困难,不利于排查问题。

了解pod

pod是逻辑主机,其行为与非容器世界中的物理主机或者虚拟机非常相似。

由于不能将多个进程聚集在一个单独的容器中,因此就需要pod将容器作为一个单元进行管理。在包含容器的pod下,既可以同时运行密切相关的进程,又能保持一定的隔离。

同一个Pod中容器之间的部分隔离

同一个pod中的所有容器都在相同的network和UTS命名空间下运行,因此它们都共享相同的主机名和网络接口。当涉及文件系统时,每个容器的文件系统和其他容器是完全隔离的。

容器如何共享相同的ip和端口空间

由于一个pod中的容器运行于相同的Network命名空间中,因此他们共享相同的IP地址和端口空间,可以通过localhost与同一个pod中的其他容器通信。

对于端口,同一pod中的容器运行的多个进程绑定到相同的端口号会导致冲突,对于不同pod中的容器则永远不会出现端口冲突。

平坦pod间网络

Kubernetes集群中所有pod都在同一个共享网络地址空间中,可以通过IP地址来实现相互访问。

image.png

通过pod合理管理容器

由于pod比较轻量,可以在几乎不导致任何额外开销的前提下拥有尽可能多的pod,将应用组织到多个pod中,而每个pod只包含紧密相关的组件或进程。

  • 将多层应用分散到多个pod中:如果有一个双节点的Kubernetes集群,如果只用一个pod,始终只会用一个工作节点,而不会充分利用第二个节点上的计算资源。合理做法是前端后端分别部署在不同节点上。
  • 基于扩缩容考虑而分割到多个Pod中:pod也是扩缩容的基本单位,如果全部部署在一个pod中,扩缩容会导致所有的应用层都将受影响。如前端和后端,就无法只对后端进行扩缩容。不利于资源利用。
  • 何时在Pod中使用多个容器:应用由一个主进程和一个或多个辅助进程组成
  • 决定何时在Pod中使用多个容器:容器不应该包含多个进程,Pod也不应该包含多个并不需要运行在同一个主机上的容器

image.png

以YAML或者JSON描述文件创建Pod

使用YAML描述文件创建,可以存储在版本控制系统中,方便维护

image.png

主要部分:

* `metadata`:包括名称、命名空间、标签和关于该容器的其他信息
* `spec`:包含pod内容的实际说明,如容器、卷和其他数据
* `status`:包含运行中的pod的当前信息,如条件、描述、状态、IP等

为pod创建一个简单的YAML描述文件

apiVersion: v1
kind: Pod
metadata:
  name: kubia-manual  //pod名称
spec:
  containers:
  - image: luksa/kubia
    name: kubia
    ports:
    - containerPort: 8080  //应用监听的端口
      protocol: TCP

使用kubectl create 创建pod

kubectl create -f kubia-manual.yaml

获得运行中Pod的完整定义

  • 返回yaml格式:kubectl get po kubia-manual -o yaml
  • 返回json格式:kubectl get po kubia-manual -o json

在pod列表中查看新创建的pod

kubectl get pods

查看应用日志

使用 docker logs

容器化的应用程序会将日志记录到标准输出和标准错误流,不会写入文件,允许用户可以通过简单、标准的方式查看。

容器运行是将这些流重定向到文件,可以通过以下命令获取容器日志:

docker logs <container id>

可以通过ssh命名登录到pod正在运行的节点,并使用docker logs命令查看其日志。

使用kubectl logs

查看pod的日志,只需要在本地机器上运行以下命令:kubectl logs kubia-manual

获取多容器pod的日志

获取多容器pod的日志时需指定容器名称,使用-c <容器名称>来显式指定容器名称

kubectl logs kubia-manual -c kubia

向pod发送请求

将本地网络端口转发到pod中的端口

Kubernetes允许配置端口转发到该pod,如将本地端口8888转发到kubia-manual pod的端口8080。这样就可以通过本地端口连接到pod。

kubectl port-forward kubia-manual 8888:8080

通过端口转发连接到pod

在另外的终端上,可以通过运行localhost:8888上的代理,向pod发送一个Http请求:

curl localhost:8888

image.png

使用标签组织pod

在实际运营中,随着Pod数量的增加,使用标签可以有效的组织。

举例:微服务架构

部署的微服务数量可以很轻松就超过20个,在实际运营过程中面临版本发布、快速扩容等,很容易导致混乱。如图:

image.png

很明显需要一种方式,可以通过一次操作对所有或者某些pod进行操作,而不必要为每个pod执行操作。

因此就需要使用标签来组织pod,标签是Kubernetes的一种简单却强大的特征,可以组织pod,也可以组织其他资源。

还是上面的示例,为pod添加两个标签:

  • app:指定pod属于那些应用、组件或者微服务
  • rel:指定pod中运行的应用所属的版本,如stable、beta

image.png

创建pod时指定标签

kubia-manual-with-labels.yaml

apiVersion: v1
kind: Pod
metadata:
  name: kubia-manual-v2
  labels:  //附加标签到pod上
    creation_method: manual
    env: prod
spec:
  containers:
  - image: luksa/kubia
    name: kubia
    ports:
    - containerPort: 8080
      protocol: TCP

执行命令创建:kubectl create -f kubia-manual-with-labels.yaml

默认不会列出任何标签,需要执行下面命令来查看:

执行命令:kubectl get po --show labels

如果需要筛选某些标签,可以使用-L选项来指定,如:

kubectl get po -L creation_method,env

修改现有pod的标签

标签可以在现有的pod上进行添加和修改,下面通过命令为kubia-manual添加标签:

kubectl label po kubia-manual creation_method=manual

将名为kubia-manual-v2的pod的标签env=prod更改为env=debug,更改现有标签需要使用--overwrite选项。

kubectl label po kubia-manual-v2 env=debug --overwrite

通过标签选择器列出pod子集

前面我们了解了标签的使用,现在我们来介绍标签选择器,实际使用过程中标签要与标签选择器结合使用才能发挥其作用。

使用标签选择器列出pod

  • 列出包含creation_method标签并且标签值为manual的pod:kubectl get po -l creation_method=manual
  • 列出包含env标签的pod:kubectl get po -l env
  • 列出没有env标签的pod:kubectl get po -l '!env'
  • 其他选择条件:
  • creation_method!=manual:选择带有creation_method标签并且值不等于manual的pod
  • env in (prod,devel):选择带有env标签且值为prod或者devel的pod
  • env notin (prod,devel):选择带有env标签,但其值不是pord或者devel的pod

在标签选择器中使用多个条件

标签选择器中同时使用多个条件,每个条件使用逗号分隔,选择的pod或者资源需要全部匹配才算。

kubectl get po -l app=pc,rel=beta

使用标签和选择器来约束pod的调度

由于Kubernetes将集群中的所有节点抽象为一个整体的大型部署平台,对于pod实际调度到哪个节点无关紧要。对于每个pod,获得所请求的确切数量的计算资源(CPU、内存等)及其他pod的可访问性,不受该pod所调度到的节点的影响。

在实际情况中,我们有将那些pod调度到哪里的需求,不需要特别说明pod应该调度到哪个节点上,这会使应用程序与基础架构强耦合,违背了Kubernetes对运行在其上的应用程序隐藏实际的基础架构的构想。因此这时可以对节点使用标签和标签选择器,使Kubernetes选择符合一定条件的节点。

使用标签分类工作节点

加入集群中有一个用于通用GPU计算的GPU,希望向节点添加标签来标记这个功能特征,通过将标签gpu=true来实现。

kubectl label node gke-kubia-85f6-node-orrx gpu=true

现在就可以使用标签选择器来列出节点:

kubectl get nodes -l gpu=true

将pod调度到特定节点

现在创建一个需要执行GPU的新pod,为了让调度器只在提供适当GPU的节点进行选择,在YAML文件中添加一个节点选择器

apiVersion: v1
kind: Pod
metadata:
  name: kubia-gpu
spec:
  nodeSelector:
    gpu: "true"   //只将pod部署到包含标签gpu=true的节点上
  containers:
  - image: luksa/kubia
    name: kubia

调度到一个特定的节点

同样,可以将pod调度到某个确定的节点,使用键值:kubernetes.io/hostname,即节点实际主机名。不建议pod调度到按个节点上,而应该通过标签选择器来选择特定的逻辑节点组。

注解pod

除标签外,pod和其他对象还可以包含注解,也是键值对,本质和标签相似。不同的是注解不能像标签一样用于分组。

注解可以容纳更多的信息,大量使用注解可以为每个pod或者其他API对象添加说明,方便使用者协作。

使用命名空间对资源进行分组

如果将对象分割成完全独立且不重叠的组时,可以考虑命名空间。Kubernetes命名空间简单的为对象名称提供了一个作用域。

命名空间的需求

使用多个命名空间的前提下,可以将包含大量组件的复杂系统拆分为更小的不同组,这些不同组也可以用于在多租户环境中分配资源,如生产、开发、测试环境等。资源名称只需在命名空间内保持唯一即可。

发现其他命名空间及其pod

列出集群中所有命名空间:kubectl get ns

使用kubectl get命令列出资源时,默认只列出default命名空间下的对象。

列出命名空间kube-system的pod:kubectl get po --namespace kube-system

命名空间可以将不属于一组的资源分到不重叠的组中,并为资源名称提供了一个作用域。

创建一个命名空间

命名空间是一种和其他资源一样的Kubernetes资源,因此也可以通过YAML文件来创建。

从YAML文件创建命名空间:

custom-namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: custom-namespace

执行命令:kubectl create -f custom-namespace.yaml

使用kubectl create namespace命令创建命名空间

命名空间名称规则:比附符合域名中规定的命名规范,但不允许包含点号,即只能包含字母、数字、横杆(-)

创建:kubectl create namespace custom-namespace

管理其他命名空间中的对象

在指定命名空间中创建资源:

kubectl create -f kubia-manual.yaml -n custom-namespace

命名空间提供的隔离

命名空间将对象分隔到不同的组,只允许对属于特定命名空间的对象进行操作,但实际上并不提供正在运行的对象的任何隔离。命名空间之间是否提供网络隔离取决于Kubernetes所使用的网络解决方案。

停止和移除pod

按名称删除pod

删除pod的过程,是先终止pod所有容器

删除单个:kubectl delete po kubia-gpu

删除多个:kubectl delete po pod1 pod2

使用标签选择器删除pod

kubectl delete po -l create_method=manual

通过删除整个命名空间来删除pod

kubectl delete ns custom-namespace

删除命名空间中的所有pod,但保留命名空间

对于使用kubectl run命名创建的pod,如果需要全部删除掉,需要删除ReplicationCcontroller

删除命名空间中的(几乎)所有资源

kubectl delete all --all

使用该命令可以删除当前命名空间中的所有资源,也可以删除ReplicationCcontroller。当然还是会有些资源会被保留下来,如Secret。


相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
7月前
|
Kubernetes Docker Python
Docker 与 Kubernetes 容器化部署核心技术及企业级应用实践全方案解析
本文详解Docker与Kubernetes容器化技术,涵盖概念原理、环境搭建、镜像构建、应用部署及监控扩展,助你掌握企业级容器化方案,提升应用开发与运维效率。
1102 108
|
6月前
|
Kubernetes Devops Docker
Kubernetes 和 Docker Swarm:现代 DevOps 的理想容器编排工具
本指南深入解析 Kubernetes 与 Docker Swarm 两大主流容器编排工具,涵盖安装、架构、网络、监控等核心维度,助您根据团队能力与业务需求精准选型,把握云原生时代的技术主动权。
621 115
|
6月前
|
存储 Kubernetes 网络安全
关于阿里云 Kubernetes 容器服务(ACK)添加镜像仓库的快速说明
本文介绍了在中国大陆地区因网络限制无法正常拉取 Docker 镜像的解决方案。作者所在的阿里云 Kubernetes 集群使用的是较旧版本的 containerd(1.2x),且无法直接通过 SSH 修改节点配置,因此采用了一种无需更改 Kubernetes 配置文件的方法。通过为 `docker.io` 添加 containerd 的镜像源,并使用脚本自动修改 containerd 配置文件中的路径错误(将错误的 `cert.d` 改为 `certs.d`),最终实现了通过多个镜像站点拉取镜像。作者还提供了一个可重复运行的脚本,用于动态配置镜像源。虽然该方案能缓解镜像拉取问题,
716 2
|
8月前
|
NoSQL Redis Docker
使用Docker Compose工具进行容器编排的教程
以上就是使用Docker Compose进行容器编排的基础操作。这能帮你更有效地在本地或者在服务器上部署和管理多容器应用。
699 11
|
12月前
|
存储 运维 Kubernetes
容器数据保护:基于容器服务 Kubernetes 版(ACK)备份中心实现K8s存储卷一键备份与恢复
阿里云ACK备份中心提供一站式容器化业务灾备及迁移方案,减少数据丢失风险,确保业务稳定运行。
|
8月前
|
存储 监控 测试技术
如何将现有的应用程序迁移到Docker容器中?
如何将现有的应用程序迁移到Docker容器中?
643 57

相关产品

  • 容器服务Kubernetes版
  • 推荐镜像

    更多