K8s in Action 阅读笔记——【2】First steps with Docker and Kubernetes

news2024/10/5 11:23:38

K8s in Action 阅读笔记——【2】First steps with Docker and Kubernetes

2.1 Creating, running, and sharing a container image

2.1.1 Installing Docker and running a Hello World container

在电脑上安装好Docker环境后,执行如下命令,

$ docker run busybox echo "Hello world"
# Unable to find image 'busybox:latest' locally
# latest: Pulling from library/busybox
# 325d69979d33: Pull complete
# Digest: 
# sha256:560af6915bfc8d7630e50e212e08242d37b63bd5c1ccf9bd4acccf116e262d5b
# Status: Downloaded newer image for busybox:latest
# Hello world

这看起来并不是很令人印象深刻,但考虑到整个“应用程序”是一个命令下载并执行的,而不必安装任何应用程序或其他依赖项,这十分不错。在此例中,该应用程序是一个单独的可执行文件(busybox),但也可以是具有许多依赖项的非常复杂的应用程序。设置和运行整个应用程序的过程将完全相同。此外,该应用程序在容器内运行,与计算机上运行的其他进程完全隔离。

UNDERSTANDING WHAT HAPPENS BEHIND THE SCENES

图2.1展示了当你执行docker run命令时发生的情况。首先,Docker检查本地计算机上是否已经存在busybox:latest镜像。由于它不存在,Docker从http://docker.io的Docker Hub镜像库中拉取该镜像。在镜像下载到你的机器之后,Docker从该镜像创建一个容器,并在其中运行命令。echo命令将文本打印到STDOUT,然后该进程终止,容器停止运行。

image-20230521163948586

RUNNING OTHER IMAGES

运行其他已存在的容器镜像和你运行busybox镜像一样简单。实际上,它通常更加简单,因为通常你无需像示例中那样指定要执行的命令(echo “Hello world”)。应该执行的命令通常已经嵌入到镜像本身中,但如果你想的话,也可以进行覆盖。在浏览公共可用镜像的http://hub.docker.com或其他公共仓库之后,你可以像这样告诉Docker运行该镜像:

$ docker run <image>

VERSIONING CONTAINER IMAGES

Docker支持在同一名称下拥有同一个镜像的多个版本或变量。每个变体必须具有唯一的标签。当引用镜像时没有明确指定标签,Docker将会假定你正在引用所谓的最新标签。要运行不同版本的镜像,你可以像下面这样在镜像名称中指定标签:

$ docker run <image>:<tag>

2.1.2 Creating a trivial Node.js app

接下来构建一个简单的Node.js Web 应用程序,并将其打包成一个容器镜像。该应用程序将接受HTTP请求并响应运行它的机器的主机名。这样,你将看到在容器内运行的应用程序能够看到自己的主机名,而不是宿主机的主机名,即使它像其他进程一样在主机上运行。当你在Kubernetes上部署并缩放该应用程序时(横向扩展;即运行多个应用程序实例),这将非常有用。你将看到你的HTTP请求命中应用程序的不同实例。

const http = require('http');
const os = require('os');

console.log("Kubia server starting...");

var handler = function (request, response) {
    console.log("Received request from " + request.connection.remoteAddress);
    response.writeHead(200);
    response.end("You've hit " + os.hostname() + "\n");
};

var www = http.createServer(handler);
www.listen(8080);

这段代码的作用很明显。它在8080端口上启动一个HTTP服务器。服务器回应HTTP响应状态码200 OK,并在每个请求中返回文本“ You’ve hit ”。请求处理程序还将客户端的IP地址记录到标准输出,此后会需要这个记录。

2.1.3 Creating a Dockerfile for the image

要将你的应用程序封装成一个镜像,你首先需要创建一个名为 Dockerfile 的文件,它将包含 Docker 在构建镜像时执行的一系列操作指令。Dockerfile 需要在与 app.js 文件相同的文件夹中,并且应包含以下代码清单中的命令。

FROM node:7 
ADD app.js /app.js 
ENTRYPOINT ["node", "app.js"]

FROM 行定义了你将用作起点的容器镜像(你所构建的基础镜像)。在这种情况下,你使用了 node 容器镜像,标签为 7。在第二行中,你将本地目录中的 app.js 文件添加到镜像的根目录下,名称相同(app.js)。最后,在第三行中,你定义了当有人运行镜像时应执行的命令。在你的例子中,命令是 node app.js

2.1.4 Building the container image

现在,你已经拥有了 Dockerfile 和 app.js 文件,你拥有了构建镜像所需的一切。要构建它,请运行以下 Docker 命令:

$ docker build -t kubia .

图2.2展示了构建过程中发生了什么。你告诉 Docker 基于当前目录的内容构建一个名为 kubia 的镜像(请注意构建命令末尾的句点)。Docker 将在目录中查找 Dockerfile,并根据文件中的指令构建镜像。

image-20230521214807961

UNDERSTANDING HOW AN IMAGE IS BUILT

构建过程不是由Docker客户端执行的。相反,整个目录的内容都被上传到Docker守护进程中并在那里构建镜像。客户端和守护进程不需要在同一台机器上。如果您在非Linux操作系统上使用Docker,客户端位于主机操作系统上,但守护进程在虚拟机内运行。由于构建目录中的所有文件都被上传到守护进程中,如果包含许多大文件并且守护进程未在本地运行,则上传可能需要更长时间。

不要在构建目录中包含任何不必要的文件,因为它们会拖慢构建过程,特别是当Docker守护进程在远程计算机上运行时。

UNDERSTANDING IMAGE LAYERS

镜像不是一个单一的大二进制块,而是由多个层组成的。不同的镜像可能共享多个层,这使得存储和传输镜像更加高效。例如,如果您基于相同的基础镜像(如示例中的node:7)创建多个镜像,则所有层组成的基础镜像只会被存储一次。此外,在拉取镜像时,Docker将逐个下载每个层。因为你的计算机上可能已经存储了多个图层,所以Docker只会下载那些不包含的层。

你可能认为每个Dockerfile只创建一个新的层,但实际情况并非如此。在构建镜像时,每个Dockerfile中的每个单独命令都会创建一个新的层。在构建图像期间,在拉取基础镜像的所有层之后,Docker会在它们的顶部创建一个新的层,并将app.js文件添加到其中。然后,它将创建另一个层,指定当运行镜像时应执行的命令。最后一个层将被标记为kubia:latest。这在图2.3 中显示,图中还显示了一个名为other:latest的不同镜像如何使用与自己的镜像相同的Node.js镜像的层。

image-20230521221312855

可以查看本地计算机上有哪些镜像

$ docker images
# REPOSITORY                                TAG       IMAGE ID       CREATED          SIZE
# kubia                                     latest    30b8a5def3f5   21 minutes ago   660MB
# busybox                                   latest    8135583d97fe   42 hours ago     4.86MB

2.1.5 Running the container image

运行已经构建的镜像

$ docker run --name kubia-container -p 8080:8080 -d kubia
# 7d6e488c7431a1e690eb99d48d40a0b330f8d16de7a941c84e8d0d4ee241cedc

这条命令告诉 Docker 从 kubia镜像中运行一个名为 kubia-container 的新容器。容器将与控制台分离(-d标志),这意味着它将在后台运行。本地机器上的8080端口将映射到容器内部的8080端口(-p 8080:8080选项),这样你就可以通过 http://localhost:8080 访问应用程序。

yjq@DESKTOP-NKBDBDM:~$ curl http://localhost:8080/
# You've hit 7d6e488c7431

这是你应用程序的响应。你的小型应用程序现在在容器内运行,并与其他所有内容隔离开来。正如你所看到的,它返回的主机名是 7d6e488c7431,而不是你主机的实际主机名。这个十六进制数是 Docker 容器的 ID。

可以查看已经运行的容器的信息:

$ docker ps
CONTAINER ID   IMAGE   COMMAND   CREATED       STATUS         PORTS          NAMES
7d6e488c7431   kubia     "node app.js"   3 minutes ago   Up 3 minutes   0.0.0.0:8080->8080/tcp   kubia-container

docker ps 命令仅显示有关容器的最基本信息。要查看附加信息,可以使用 docker inspect

这会输出一系列json信息。

2.1.6 Exploring the inside of a running container

上文使用的Node.js镜像包含 bash shell,因此你可以像这样在容器内运行 shell:

$ docker exec -it kubia-container bash

这会在已有的 kubia-container 容器中运行 bash。bash 这个进程将拥有与主容器进程相同的 Linux 命名空间,这样就可以从容器内部探索。

-it选项代表两个选项的缩写:

  • -i,确保 STDIN 保持打开状态,因为这样才能输入 shell 命令;
  • -t,则配一个伪终端(TTY)。

如果想像平常一样使用 shell,那么两者都是必需的。(如果将第一个选项省略,则无法输入任何命令;如果将第二个选项省略,命令提示符将无法显示,并且有些命令会提示 TERM 变量未设置。)

$ docker exec -it kubia-container bash
root@7d6e488c7431:/# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.2  0.1 614436 25316 ?        Ssl  02:57   0:00 node app.js
root        18  0.2  0.0  20248  3188 pts/0    Ss   02:57   0:00 bash
root        24  0.0  0.0  17504  2048 pts/0    R+   02:57   0:00 ps aux

容器内部进程的 ID 和主机上不一样。容器使用自己的 PID Linux 命名空间,并具有完全隔离的进程树,有自己的数字序列。

就像具有独立的进程树一样,每个容器也具有独立的文件系统。列出容器内部根目录的内容将只显示容器中的文件,其中包括镜像中的所有文件和容器运行时创建的任何文件(如日志文件和类似文件),如下面的列表所示。

root@7d6e488c7431:/# ls
app.js  bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

该文件夹包含了 app.js 文件和其他系统目录,这些都是正在使用的 node:7 基础镜像的一部分。要退出容器,需要运行 exit 命令退出 shell,并返回到主机机器。

root@7d6e488c7431:/# exit
exit

2.1.7 Stopping and removing a container

停止一个容器:

$ docker stop kubia-container
kubia-container

这将停止容器中运行的主进程,进而停止容器,因为容器内没有其他进程正在运行。容器本身仍然存在,可以使用 docker ps -a 命令查看它。-a 选项打印出所有容器,包括正在运行和已停止的容器。要真正删除一个容器,需要使用 docker rm 命令进行删除。

$ docker ps -a
CONTAINER ID   IMAGE  COMMAND   CREATED  STATUS   PORTS       NAMES
7d6e488c7431   kubia  "node app.js"  13 hours ago  Exited (137) About a minute ago        kubia-container
docker rm kubia-container

2.1.8 Pushing the image to an image registry

你构建的镜像目前只能在本地机器上使用。为了让你在任何其他机器上运行它,你需要将该镜像推送到外部镜像注册表中可以将镜像推送到 Docker Hub(http://hub.docker.com),这是一个公共可用的镜像仓库之一。其他广泛使用的镜像仓库包括 Quay.io 和 Google Container Registry。

先将镜像打上自己仓库的tag:docker tag kubia yijunquan/kubia

这不是对标签进行重命名,而是为同一镜像创建了一个附加标签。

$ docker images
REPOSITORY               TAG       IMAGE ID       CREATED         SIZE
kubia                   latest    30b8a5def3f5   13 hours ago    660MB
yijunquan/kubia         latest    30b8a5def3f5   13 hours ago    660MB

kubia和luksa/kubia都指向相同的镜像ID,因此它们实际上是具有两个标签的同一个镜像。

使用docker login命令登录账号后,可以使用如下命令进行推送:

$ docker push yijunquan/kubia
Using default tag: latest
The push refers to repository [docker.io/yijunquan/kubia]
8c6ceb8d582a: Pushed
ab90d83fa34a: Mounted from library/node
8ee318e54723: Mounted from library/node
e6695624484e: Mounted from library/node
da59b99bbd3b: Mounted from library/node
5616a6292c16: Mounted from library/node
f3ed6cb59ab0: Mounted from library/node
654f45ecb7e3: Mounted from library/node
2c40c66f7667: Mounted from library/node
latest: digest: sha256:bf61996e401e52a9b054844ee7026c2d27c40ba33b7eb5bee2ae8f9cd1118419 size: 2213

在将镜像推送到 Docker Hub 后,该镜像将可供所有人使用。

2.2 Setting up a Kubernetes cluster

可以参考如下教程

https://blog.csdn.net/Lingoesforstudy/article/details/122554937(ubuntu18)

https://www.cnblogs.com/renshengdezheli/p/16686769.html(centos7)

2.3 Running your first app on Kubernetes

2.3.1 Deploying your Node.js app

部署你的应用程序最简单的方法是使用kubectl run命令,它将创建所有必要的组件,而无需处理JSON或YAML。尝试运行之前创建并推送到Docker Hub的镜像:

root@yjq-k8s1:~# kubectl run kubia --image=yijunquan/kubia --port=8080 -n k8s-in-action
pod/kubia created

INTRODUCING PODS

Kubernetes并不是直接处理单个容器。相反,它使用多个共同存在的容器,这组容器称为Pod。

Pod是一组一个或多个紧密相关的容器,它们将始终在同一工作节点和相同的Linux命名空间中一起运行。每个Pod就像一个独立的逻辑机器,具有自己的IP、主机名、进程等,运行一个单一的应用程序。该应用程序可以是一个单独的进程,运行在一个单独的容器中,也可以是一个主应用程序进程和其他支持进程,每个进程都在它自己的容器中运行。Pod中的所有容器看起来都在同一个逻辑机器上运行,而其他Pod中的容器,即使它们在同一工作节点上运行,也看起来是在不同的机器上运行。

由下图可知,每个Pod都有自己的IP,并包含一个或多个容器,每个容器运行着一个应用程序进程。Pod分布在不同的工作节点上。

image-20230522114438684

LISTING PODS

列出刚才所创建的Pod:

root@yjq-k8s1:~# kubectl get pod -n k8s-in-action
NAME    READY   STATUS    RESTARTS   AGE
kubia   1/1     Running   0          6m45s

要查看有关Pod的更多信息,你也可以使用kubectl describe pod命令。

UNDERSTANDING WHAT HAPPENED BEHIND THE SCENES

为了更好地理解在 Kubernetes 中运行容器镜像的步骤,请看图2.6。其中显示了执行此操作的两个步骤。首先,构建镜像并将其推送到 Docker Hub 是必需的,因为只有在本地构建的镜像只能在本地机器上使用,但是你需要使其可以被运行在工作节点上的 Docker 守护程序访问。当运行 kubectl 命令时,它向 Kubernetes API 服务器发送 REST HTTP请求以在集群中创建一个新的 ReplicationController 对象。然后,ReplicationController 创建一个新的 Pod,Scheduler 将其调度到工作节点之一上。该节点上的 Kubelet 发现 Pod已被调度到该节点上并指示 Docker 从注册表中拉取所需的镜像,因为该镜像在本地不可用。等镜像下载完成后,Docker创建并运行容器。其他两个节点的显示仅是为了提供上下文,它们并不在过程中扮演任何角色,因为Pod未被调度到它们上面。

image-20230522115157850

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/560452.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

真会玩:莫言用ChatGPT为余华写了一篇获奖词

5月16日&#xff0c;《收获》杂志65周年庆典暨新书发布活动在上海舞蹈中心举行。 典礼现场&#xff0c;余华凭借《文城》获得收获文学榜2021年长篇小说榜榜首。 作为老友&#xff0c;莫言在颁奖时故意卖了个关子&#xff1a;“这次获奖的是一个了不起的人物&#xff0c;当然了&…

OMA通道-2

1 简介 本文档中指定的 API 使移动应用程序能够访问移动设备中的不同 SE&#xff0c;例如 SIM 或嵌入式 SE。 本规范提供了接口定义和 UML 图&#xff0c;以允许在各种移动平台和不同的编程语言中实现。 如果编程语言支持命名空间&#xff0c;则它应为 org.simalliance.openmob…

Foxit PDF SDK OCR Add-on Library (C++, Windows)-Crk

OCR文档扫描--Crack version 使用Foxit PDF SDK OCR Add-on的光学字符识别&#xff08;OCR&#xff09;软件将扫描的文档转换为可搜索的文本PDF。专为扫描、归档和数字化而设计&#xff0c;我们的插件输出13种不同的文件格式&#xff0c;包括PDF和PDF/A。 在不投资数据输入人员…

Linux 禁用23端口

禁用23端口 前言 23端口是用于Telnet服务的默认端口。Telnet是一种早期的网络协议&#xff0c;允许用户使用一个远程终端连接到远程计算机上&#xff0c;以便在远程计算机上执行命令和操作。通过输入用于Telnet服务器的IP地址和端口号&#xff0c;用户可以在本地计算机上打开一…

【Java|golang】1090. 受标签影响的最大值---关联数组排序问题以及切片排序失败

我们有一个 n 项的集合。给出两个整数数组 values 和 labels &#xff0c;第 i 个元素的值和标签分别是 values[i] 和 labels[i]。还会给出两个整数 numWanted 和 useLimit 。 从 n 个元素中选择一个子集 s : 子集 s 的大小 小于或等于 numWanted 。 s 中 最多 有相同标签的 …

数据结构初阶--栈和队列OJ题

目录 前言有效的括号思路分析代码实现 用队列实现栈思路分析代码实现 用栈实现队列思路分析代码实现 设计循环队列思路分析代码实现 前言 本篇文章将对部分栈和队列综合运用题进行讲解&#xff0c;以对栈和队列有一个更深层次的理解。 有效的括号 先来看题 思路分析 这里…

优秀的流程图应该怎么设计呢?

优秀的流程图应该怎么绘制呢&#xff1f; 本文将带大家学习优秀流程图的绘制要点和技巧&#xff0c;以及讲解流程图与UML活动图、BPMN图之间的关系和区别。 1、认识流程图 流程图简单讲就是用图描述流程&#xff0c;这种流程可以是一种有先后顺序的操作组成&#xff0c;可以…

2024王道数据结构考研丨第六篇:查找、排序

到此&#xff0c;2024王道数据结构考研笔记专栏“基础知识”部分已更新完毕&#xff0c;其他内容持续更新中&#xff0c;欢迎 点此 订阅&#xff0c;共同交流学习… 文章目录 第七章 查找7.1查找表相关概念 第八章 排序8.1排序的基本概念8.2 插入排序8.2.1直接插入排序8.2.2折半…

使用Maven管理项目、导入依赖、测试打包项目、常用依赖

使用Maven管理项目 文章目录 使用Maven管理项目Maven项目结构Maven依赖导入Maven依赖作用域Maven可选依赖Maven排除依赖Maven继承关系Maven常用命令Maven测试项目Maven打包项目 Maven 翻译为"专家"、“内行”&#xff0c;是 Apache 下的一个纯 Java 开发的开源项目。…

hive函数03

自定义函数 Hive 自带了一些函数&#xff0c;比如&#xff1a;max/min等&#xff0c;但是数量有限&#xff0c;自己可以通过自定义UDF来方便的扩展。 在企业中处理数据的时候&#xff0c;对于敏感数据往往需要进行脱敏处理。比如手机号。我们常见的处理方式是将手机号中间4位…

MySQL表设计原则

前言 这里简单整理一些常用的数据库表设计原则以及常用字段的使用范围。 表的设计准则 1、命名规范 表名、字段名必须使用小写字母或者数字&#xff0c;禁止使用数字开头&#xff0c;禁止使用拼音&#xff0c;并且一般不使用英文缩写。主键索引名为 pk_字段名&#xff1b;唯…

SSL/TLS认证握手过程

一: SSL/TLS介绍 什么是SSL,什么是TLS呢&#xff1f;官话说SSL是安全套接层(secure sockets layer)&#xff0c;TLS是SSL的继任者&#xff0c;叫传输层安全(transport layer security)。说白点&#xff0c;就是在明文的上层和TCP层之间加上一层加密&#xff0c;这样就保证上层信…

ACP(MaxCompute篇)-MaxCompute开发工具

创建MaxCompute项目 第一种创建项目方式 1.知道MaxCompute服务。 2.创建项目。 3.创建成功。 第二种创建项目的方式 1.进入DataWorks控制台。 2.创建工作空间。 3.创建的类型。 4.创建计算方式。 5.自定义选择。 6.创建成功。 MaxCompute开发工具简介 Odpscmd 安装配置 下…

java boot项目认识一下三种格式的配置文件

之前我们在 application.properties 中写了很多配置 但boot并不是只有这种配置方式 boot提供了三种配置方式给我们 话不多说 直接上代码 我们先将 resources下的 application.properties给他干掉 然后在下面创建一个 application.yml 在下面编写代码如下 server:port: 81这…

Hystrix底层核心原理

1、Hystrix资源隔离技术 hystrix github 官方文档&#xff1a;Home Netflix/Hystrix Wiki GitHub hystrix可以完成隔离、限流、熔断、降级这些常用保护功能。 hystrix的隔离分为线程池隔离和信号量隔离 1.1、信号量隔离 信号量隔离就是hystrix的限流功能。虽然名字叫隔离…

企业应该如何选择一个靠谱的软件测试供应商?

人们的生活越来越离不开软件产品&#xff0c;随着选择越多&#xff0c;产品质量愈发重要&#xff0c;因此企业选择一个靠谱的软件测试供应商是一项关键任务&#xff0c;因为测试结果将直接影响到产品的质量、用户的体验和公司的声誉。以下是一些选择靠谱的软件测试供应商的技巧…

C++常用的支持中文的GUI库Qt 6之二:项目的结构、资源文件的使用

C常用的支持中文的GUI库Qt 6之二&#xff1a;项目的结构、资源文件的使用 上一篇Qt 6的下载、安装与简单使用https://mp.csdn.net/mp_blog/creation/editor/130730203&#xff0c;本文介绍Qt 6的项目的结构、资源文件的使用与发布。 基础 这一部分&#xff0c;初学时不明白是…

交通 | 考虑网络效应的共享出行差异化定价

封面图来源&#xff1a; https://www.pexels.com/zh-cn/photo/210182/ 编者按&#xff1a; 本文考虑了单程式共享汽车的定价问题&#xff0c;在考虑顾客需求网络效应以及实现影响的场景下&#xff0c;根据空间以及时间确定汽车租赁的单价以实现系统利润最大化。 1.引言 在过…

【C++】unordered_map unordered_set 练习题

文章目录 unordered系列关联式容器unordered_mapunordered_map的文档介绍unordered_map的构造接口使用: unordered_multimapunorder_map&&unorder_multimap对比:unordered_setunordered_set的文档介绍unordered_set的构造接口使用 unordered_multisetOJ练习961.在长度2…

( 回溯算法) 27. 移除元素 ——【Leetcode每日一题】

❓27. 移除元素 难度&#xff1a;简单 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以…