通过实例快速掌握k8s(Kubernetes)核心概念
容器技术是微服务技术的核心技术之一,并随着微服务的流行而迅速成为主流。Docker是容器技术的先驱和奠基者,它出现之后迅速占领市场,几乎成了容器的代名词。但它在开始的时候并没有很好地解决容器的集群问题。Kubernetes抓住了这个机遇,以容器编排者(Container Orchestration)的身份出现,对容器集群进行管理和调度,现在已经打败了Docker成为了容器技术事实上的标准。当然K8s内部还是需要Docker的,但它的功能范围被大大压缩了,只是负责底层的容器引擎和镜像(Docker Image)管理,成为了容器体系中不可缺少, 但没有存在感的一部分。而绝大部分的对外接口都是由k8s来负责。
K8s核心对象:
相对于简单易学的Docker来说,k8s系统庞杂而且概念众多,同一个功能有很多不同方法来完成,让你无所适从,学习起来要困难的多。对于普通码农来讲不需要建立完整的生产环境,只需要搭建一个本地开发环境,这时你只需要了解k8s的核心概念就够了,这样可以大大缩短学习时间。k8s的一切都是对象(Object),它的核心概念一共只有4个,Pod,部署(Deployment),服务(Service)和节点(Node)。另外再加上一个容器镜像(Docker Image),这个是Docker引擎的核心。掌握了这五个核心概念,就对容器技术有了基本了解,打下了扎实的基础。
Windows安装环境:
Windows10的Windows 10企业版, 专业版, 和教育版是可以支持直接安装K8s的,但电脑是要支持Hyper-V的, 详见这里。由于我的Windows是家庭版,只能先安装虚拟机(VirtualBox),再在虚拟机上安装k8s。我用的k8s是Minikube,是k8s的简化版。另外还安装了Vagrant(它是管理虚拟机的一个软件)作为界面来管理VirtualBox。
容器镜像(Docker Image):
任何程序都在容器中运行,k8s支持多种容器,其中Docker是最流行的。容器镜像(Docker Image)是一个以文件形式存在的运行环境,它的里面是分层的,每一层都在上一层的基础上不断叠加新的功能。容器镜像是由Dockerfile创建的。Dockerfile是一个文件,里面包含一组已经定义好的Docker命令(与Linux命令比较相似)。当运行Dockerfile时,里面的命令被依次执行,最后生成需要的容器镜像。你再调用Docker命令(Docker run)运行容器镜像来生成Docker容器,完成之后,应用程序就已经在容器里部署好了。这种方式能够保证每次得到的环境都是一样的。容器比虚拟机强的地方在于,它占用系统资源更少,生成时间更短。创建一个容器的耗时一般是秒级的,而虚拟机是分钟级的。容器镜像的创建效率取决于它的大小,一般来讲容器镜像越小,它的生成时间越短。
下面就是一个“nginx”的Dockerfile示例。
FROM alpine:3.2
EXPOSE 80 443
RUN apk add --update nginx && \
rm -rf /var/cache/apk/* && \
mkdir -p /tmp/nginx/client-body
COPY ./nginx.conf /etc/nginx/nginx.conf
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d"]
CMD ["nginx", "-g", "daemon off;"]
任何Dockerfile的第一句总是“FROM 。。。”,就是要创建一个Linux的运行环境。一般有以下几种:
- FROM ubuntu:18.04: 按照Linux的具体版本来创建镜像,这样的Linux运行环境是比较完整的,镜像的大小是百兆级别的。
- FROM alpine:latest : alpine是一个 精简了的Linux运行环境,它的大小是十兆级别的。
- FROM scratch : scratch是最小Linux运行环境,创建非常快,但它的问题是你不能通过shell登录到容器内部,因此我一般不用它。
当用Vagrant管理虚拟机时,可以先用Vagrant命令启动虚拟机,然后敲入vagrant ssh,进入虚拟机,系统显示:
PS E:\app2\kub> vagrant ssh
Last login: Sat Sep 28 06:56:11 2019 from 10.0.2.2
然后键入“docker run --name docker-nginx -p 8001:80 nginx”运行Nginx镜像。"docker-nginx"是容器的名字,“--name”是名字的参数选项。“-p”表示端口映射,把虚拟机的“8001”端口映射到容器的“80”端口(Nginx的缺省端口)。“nginx”是镜像的名字,如果本地没有找到“Nginx”镜像,系统会自动从Docker镜像库里下载Nginx镜像到本地,然后再运行,这个镜像有比较完整的Linux系统,因此文件比较大(100M),但也可以凑活着用。命令运行之后,显示:
vagrant@ubuntu-xenial:~$ docker run --name docker-nginx -p 8001:80 nginx
这时Nginx已经运行,但还没有任何请求,控制台没有输出。如果名字为“docker-nginx”的容器以前已经被运行,那么你需要删除原来的,再运行上面命令。可以先敲入“docker ps -a”找到所有运行过的容器,再敲入“docker rm 1ec2e3d63537”进行删除,其中“ 1ec2e3d63537”是容器ID.
切换到另一个虚拟机窗口,敲入curl localhost:8001,显示:
vagrant@ubuntu-xenial:/usr/bin$ curl localhost:8001
...
<h1>Welcome to nginx!</h1>
...
这时就出现了Nginx的首页,表示Docker容器中的Nginx已经正常运行。
换回原容器显示窗口,这时有了请求,控制台输出Nginx日志。
vagrant@ubuntu-xenial:~$ docker run --name docker-nginx -p 8001:80 nginx
172.17.0.1 - - [28/Sep/2019:07:02:25 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
这时已验证Docker镜像是好的,敲入“CTRL-C”退出。
Pod:
Pod是k8是的最基本概念,你可以把它看成是对容器(container)的一个封装,用来管理容器。一个Pod里可以管理有一个或多个容器,但一般是一个。Pod里的所有容器都共享Pod的资源和网络。当一个Pod不能满足用户需求时,你可以把Pod作为复制的最小单元来复制出一个同样的Pod来处理用户请求。Pod支持多种容器,不过一般是用Docker。你可以用单独的Pod配置文件创建Pod, 也可以把Pod的配置信息放在其他的对象(例如Deployment)的配置文件里面,并与其他对象一起创建,后者更为常见。每一个Pod都有一个唯一的IP地址,Pod一旦生成就可以通过IP地址进行访问。但一般不这么做,而是通过服务(Service)去间接地去访问。下面就是Pod的配置文件。它的解释放在后面的Deployment里面。
kind: Pod
apiVersion: v1
metadata:
labels:
app: nginx-app
spec:
containers:
- name: nginx-container
image: nginx:latest
restartPolicy: Never
Pod模板(Pod Templates)
Pod模板是嵌入在其他K8s对象(Object)中的Pod的配置说明,例如Replication Controllers, Jobs, 和DaemonSets. 这时,Pod不是单独创建的,而是由其它对象来创建,其中最常用的是Deployment。
部署(Deployment):
Deployment是比Pod更高一层的对象,它的主要作用是管理Pod集群,它里面可以有一个或多个Pod, 每一个Pod在功能上都是等同的。一般在Deployment里配置多个Pod以实现负载均衡和容错。在配置Deployment时,你需要指定Pod拷贝的个数,Deployment会自动管理它里面的Pod。当某个Pod宕机时,Deployment能自动复制一个新的Pod并替换宕机的Pod,
下面就是Deployment的配置文件(nginx-deployment.yaml)。在正方形灰框内(从template开始)的是嵌入在Deployment里的Pod的设置,灰框上面的是部署(Deployment)的设置。当你运行这个配置文件时,它会创建一个Deployment,同时也会创建嵌入在里面的Pod。这就是为什么我们一般不需要单独的Pod的配置文件,因为已经把它嵌入在了Deployment里了。
键入“kubectl create -f nginx-deployment.yaml”来运行这个部署,显示:
vagrant@ubuntu-xenial:~/dockerimages/kubernetes/nginx$ kubectl create -f nginx-deployment.yaml
deployment.apps/nginx-deployment created
这时部署已经成功,现在就可以访问它了。每个Pod都有自己的k8s集群内部IP地址,我们这时只能在K8s内部用IP地址进行访问。键入下面命令查看Pod地址,里面有两个“Nginx”Pod,因为Deployment里面是两个Pod的集群。
vagrant@ubuntu-xenial:~/nginx$ kubectl get pods -o=custom-columns=NAME:.metadata.name,IP:.status.podIP
NAME IP
hello-minikube-856979d68c-74c65 172.17.0.3
nginx-deployment-77fff558d7-bhbbt 172.17.0.10
nginx-deployment-77fff558d7-v6zqw 172.17.0.9
打开另一个窗口,连入虚拟机,然后键入以下命令“kubectl exec -ti hello-minikube-856979d68c-74c65 -- /bin/sh”登录到k8s集群内部,就能访问Nginx了。这里“hello-minikube-856979d68c-74c65”是"Minikube"Pod的名字。“172.17.0.10”是其中一个Pod的内部IP地址。
vagrant@ubuntu-xenial:~$ kubectl exec -ti hello-minikube-856979d68c-74c65 -- /bin/sh
# curl 172.17.0.10
服务(Service):
Service是最上层的k8s的对象,可以看成我们平常说的微服务。对服务来讲最重要的就是服务注册和发现。在k8s中,Service就是用来实现这个功能的。下面就是Service的配置文件(nginx-service.yaml)。一般来说调用服务需要知道三个东西,IP地址,协议和端口,例如"http://10.0.2.1:80". 但我们不想用IP,而是用名字来寻址,这就需要DNS。DNS在k8s集群内部实现了基于服务名的寻址。下面是Service的配置文件。Service通过“selector”来与Pod进行绑定,这里它把请求转发给标签“app”是“nginx-app”的Pod。“nodePort”给服务创建了一个外部可以访问的端口,这样在虚拟机上就可以直接访问服务,而不必登录到k8s集群里。
运行以下命令“kubectl create -f nginx-service.yaml”创建服务。
vagrant@ubuntu-xenial:~/$ kubectl create -f nginx-service.yaml
service/nginx-service created
服务创建完成之后,调用以下命令显示当前的所有服务, 现在就有了“nginx-service”服务。“80”是服务的内部端口,“30163”是服务的外部端口。
vagrant@ubuntu-xenial:~/$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 35d
nginx-service NodePort 10.109.7.249 <none> 80:30163/TCP 18s
因为已经通过“NodePort”对外开放了端口,现在不必登录到k8s内部,在虚拟机上就可以访问服务了. 你可以键入“localhost”
curl localhost:30163
Service 和Deployment的区别:
Deployment是用来管理集群的,与Pod绑定,但你不能直接访问Deployment。服务(Service)是为了方便用名字(而不是IP地址)访问。但这也只是在集群内部。你可以登录k8s集群内部,然后键入下面命令访问服务,但在虚拟机上(k8s外面)就不行, 这时只能用IP地址。因为DNS只是在k8s内部才起作用。
# curl nginx-service
节点(Node):
Node刚开始接触时容易和Pod搞混,但它相当于虚拟机或物理机,而Pod相当于容器。所有的的Pod或容器都是部署在Node上面。Minikube只支持单Node,但你可以在它里面部署多个Pod。下面是Node示意图。
k8s核心概念之间的关系:
对象间关系:
下面是k8s的一个简单结构图:
图中每个菱形是一个Node,中间的Node是Master Node,其余三个是Worker Node。Master Node负责管理Worker Node。 Worker Node是真正干活的Node。Master Node里有各种控制器,Deployment就是由控制器来管理的,它在中间的管理Node里,他里面有两个部署,A和B,分别对应服务A和服务B。“服务A”部署在最下面的Node里,它里面只有一个Pod。“服务B”部署在上面的两个Node里,左边的Node只有一个Pod,右边的Node有两个Pod,这是一个有三个Pod的集群。当一个部署里有多个Pod时,一般是把它们部署在不同的Node上,这样即使一个Node宕机,Deployment仍然可用。
对象绑定:
下图是介绍对象之间如何绑定的关系图。
每个对象都有多个标签(Label),“app”就是一个用来标识Pod对象的标签。图里有两个Pod,它们的“app”标签的值分别为“A”和“B”,其中Pod “B”是集群,而Pod “A”不是。服务(Service)和部署(Deployment)都通过标签选择器(Label Selector)来绑定与之匹配的Pod。
附录:
你最好是已经安装了k8s和Docker环境,那就可以依次运行本文中的示例。如果你没有环境,新建一个也不难。如果你不愿意创建环境, k8s的官网有一个练习环境,可以直接用来运行命令,详见这里
索引:
通过实例快速掌握k8s(Kubernetes)核心概念的更多相关文章
- Kubernetes 核心概念
什么是Kubernetes? Kubernetes(k8s)是自动化容器操作的开源平台,这些操作包括部署,调度和节点集群间扩展.如果你曾经用过Docker容器技术部署容器,那么可以将Docker看成K ...
- 十分钟带你理解Kubernetes核心概念
什么是Kubernetes? Kubernetes(k8s)是自动化容器操作的开源平台,这些操作包括部署,调度和节点集群间扩展.如果你曾经用过Docker容器技术部署容器,那么可以将Docker看成K ...
- Kubernetes核心概念简介
本文将会简单介绍Kubernetes的核心概念.因为这些定义可以在Kubernetes的文档中找到,所以文章也会避免用大段的枯燥的文字介绍.相反,我们会使用一些图表(其中一些是动画)和示例来解释这些概 ...
- 后端技术杂谈11:十分钟理解Kubernetes核心概念
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 本文转自 https://github.com/h2pl/Java-Tutorial 喜欢的 ...
- 01 . 容器编排简介及Kubernetes核心概念
Kubernetes简介 Kubernetes是谷歌严格保密十几年的秘密武器-Borg的一个开源版本,是Docker分布式系统解决方案.2014年由Google公司启动. Kubernetes提供了面 ...
- [转]十分钟带你理解Kubernetes核心概念
本文将会简单介绍 Kubernetes的核心概念.因为这些定义可以在Kubernetes的文档中找到,所以文章也会避免用大段的枯燥的文字介绍.相反,我们会使用一些图表(其中一些是动画)和示例来解释这些 ...
- 第3 章 : Kubernetes 核心概念
Kubernetes 核心概念 本文整理自 CNCF 和阿里巴巴联合举办的云原生技术公开课的课时 3:Kubernetes 核心概念.本次课程中,阿里巴巴资深技术专家.CNCF 9个 TCO 之一 李 ...
- K8s - Kubernetes重要概念介绍(Cluster、Master、Node、Pod、Controller、Service、Namespace)
K8s - Kubernetes重要概念介绍(Cluster.Master.Node.Pod.Controller.Service.Namespace) Kubernetes 是目前发展最 ...
- k8s kubernetes 核心笔记 镜像仓库 项目k8s改造(含最新k8s v1.16.2版本)
k8s kubernetes 核心笔记 镜像仓库 项目k8s改造 2019/10/24 Chenxin 一 基本资料 一 参考: https://kubernetes.io/ 官网 https://k ...
随机推荐
- HTTP首部字段完全解析
http协议是前端开发人员最常接触到的网络协议.在开发过程中,尤其是调试过程中避免不了需要去分析http请求的详细信息.在这其中头部字段提供的信息最多,比如通过响应状态码我们可以直观的看到响应的大致状 ...
- Mysql相关:navicat for mysql 加注释
在 navicat 中有三种注释的书写方式: 以 # 开头的字符串,可以多个 # 连续以 – 开头的字符串,注意:只能是 – ,而且 – 后面需要加一个半角空格以 /* */ 包围的字符串,类似于 J ...
- yzoj P2044 数字游戏 题解
题意 dfs骗了30分,一开始想的距离正解差一点啊,贪心加dp就可以过的水题,真正太蒻了 解析 代码 #include<bits/stdc++.h> using namespace std ...
- 深度递归必须知道的尾调用(Lambda)
引导语 本文从一个递归栈溢出说起,像大家介绍一下如何使用尾调用解决这个问题,以及尾调用的原理,最后还提供一个解决方案的工具类,大家可以在工作中放心用起来. 递归-发现栈溢出 现在我们有个需求,需要计算 ...
- 牛客网暑期ACM多校训练营(第三场)---A.PACM Team
链接:https://www.nowcoder.com/acm/contest/141/A 来源:牛客网 题目描述 Eddy was a contestant participating in ACM ...
- 【Offer】[28] 【对称的二叉树】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 请实现一个函数,用来判断一-棵二叉树是不是对称的.如果一棵二叉树和它的镜像一样,那么它是对称的.  牛客网刷题地址 思路分析 利用前序 ...
- CentOS 7 下网络无法访问 Failed to start LSB: Bring up/.
[root@localhost Desktop]# ping 192.168.2.1PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data.64 byt ...
- 云开发数据库VS传统数据库丨云开发101
云开发数据库与传统数据库的不同 在小程序·云开发中,最核心的便是三大组件:数据库.云存储和云函数,从今天开始,我们将开始隔日更的专栏文章,云开发101,在第一周,我们将从最最核心的数据库开始说起. 云 ...
- Android开发教程:开发框架基本原理
1.提供应用程序框架(Framework) 开发者可以遵照这些框架搭建应用程序读者可以结合J2SE平台的Applet框架或J2ME平台的移动信息设备套件框架来理解Android平台的应用程序框架. 每 ...
- gemfire基本使用以及spring-data-gemfire的使用
1.安装程序的使用 locator 启动locator gfsh>start locator --name=locator1 指定端口启动 gfsh>start locator --nam ...