原文网址:K8S和Docker的关系_IT利刃出鞘的博客-CSDN博客
说明
本文介绍K8S,包括:K8S和Docker的关系、不同的部署方式之间的区别。
官网
Github:https://github.com/kubernetes/kubernetes
Docker
Docker是用于构建、分发、运行容器的平台和工具。
K8S
K8S是一个使用 Docker 容器进行编排的系统,主要围绕 pods 进行工作。 Pods 是 k8s 生态中最小的调度单位,可以包含一个或多个容器。
K8S使用Docker进行编排,也可以使用其他容器管理工具,例如:RunC、Containerted 等。
K8S解决了裸跑 Docker 的若干痛点:
说明
应用有如下几种部署方式:
示例
我们看一个简单的场景,来理解为什么编排能力才是我们更看重的东西。
我们以部署一个wordpress博客网站进行示例。
你需要安装配置mysql, 安装nginx服务器,以及wordpress程序等等…
仅仅部署几个应用,你就能觉得它的复杂,配置的繁琐。可以想象,如果是几十上百个应用,自动化的过程不可避免。
#1.拉取镜像
docker pull mysql
docker pull wordpress
#2.启动mysql
docker run --name w-mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql
#3.启动wordpress,并连接mysql
docker run --name w-wordpress --link w-mysql:db -p 80:80 -d wordpress:latest
可以看到,安装过程只需要拉取镜像,启动即可,而不用关心软件的配置,版本等信息。简化了不少,但是还是手动去启动,拉取镜像等,如果容器很多,工作量依然很大,这只是个博客系统比较简单,真实的业务场景下,容器应用间的依赖关系,网络通信,数据持久化,状态等等我们关心的问题非常复杂,用这种方式处理起来非常棘手。
示例
定义一个docker-compose-wordpress.yml
version: '3.3'
services:
db:
image: mysql:5.7
container_name: mysql
security_opt:
- seccomp:unconfined
ports:
- 3306:3306
volumes:
- /opt/module/mysql/conf:/etc/mysql/conf.d
- /opt/module/mysql/data:/var/lib/mysql
- /opt/module/mysql/logs:/var/log/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "80:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: 123456
WORDPRESS_DB_NAME: wordpress
这里的配置文件虽然看着很多,其实它的层次很清楚。services我们可以认为是一组应用,是一种抽象,具体到这里可以认为是博客服务。
博客服务需要mysql和wordpress两个容器配合,所以紧接着db(名称可以自定义)指的就是mysql,在后边则描述了对应的镜像,端口等信息。
而wordpress,有一个关键字depends_on,则描述了它和db的依赖关系。通过这样一个描述文件。
这样一个文件,用的语法就是yaml文件的语法,相信开发过java微服务的肯定很熟悉,我们的配置文件大多都是用这种方式配置。
然后我们只需要执行如下命令,即可启动对应的容器,并且相互关联:
#docker-compose指令
docker-compose -f docker-compose-wordpress.yml up -d
此时查看容器运行情况:
[root@VM_0_13_centos module]# docker-compose ps
Name Command State Ports
-----------------------------------------------------------------------------------------------
module_wordpress_1 docker-entrypoint.sh apach ... Up 0.0.0.0:80->80/tcp
mysql docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp, 33060/tcp
或者直接用docker命令查看:
[root@VM_0_13_centos module]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
64153ac017a3 wordpress:latest "docker-entrypoint..." 3 weeks ago Up 3 weeks 0.0.0.0:80->80/tcp module_wordpress_1
fde105317ddd mysql:5.7 "docker-entrypoint..." 3 weeks ago Up 7 days 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
可以看到docker-compose其实为我们做了三件事
从上边这个例子,我们可以看到,面对复杂的容器运维工作,你只需要告诉编排工具你需要什么(定义yaml)其他的工作就交给等编排工具去做就行。当然部署一个wordpress这样一个轻量级的应用,用docker或者docker-compose就完全够用,如果用k8s去做,又是怎样一番场景,我们继续往下看。
从前面的例子,我们看到docker-compose其实就是在以容器为基本单位,帮我们部署应用。但在K8S里,编排调度的最小单位并不是容器,而是Pod。有了Docker容器,为什么还需要一个Pod? 前面我们说Docker容器就好比云计算操作系统中的应用,K8S相当于操作系统,那Pod就是进程组:即Pod是对一组容器(一个或多个)的抽象。之所以做这样一层抽象,是因为在 Borg 项目的开发和实践过程中,Google 公司的工程师们发现,他们部署的应用,往往都存在着类似于“进程和进程组”的关系。在同一个Pod中,可以直接通过localhost通信,并且可以共享网络栈和Volume。
如果用Pod描述上面的博客应用,yaml如下:
apiVersion: v1
kind: Pod
metadata:
name: wordpress
namespace: blog
spec:
containers:
- name: wordpress
image: wordpress
ports:
- containerPort: 80
name: wdport
env:
- name: WORDPRESS_DB_HOST
value: localhost:3306
- name: WORDPRESS_DB_USER
value: root
- name: WORDPRESS_DB_PASSWORD
value: root@123
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
args: # 新版本镜像有更新,需要使用下面的认证插件环境变量配置才会生效
- --default_authentication_plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
ports:
- containerPort: 3306
name: dbport
env:
- name: MYSQL_ROOT_PASSWORD
value: root@123
- name: MYSQL_DATABASE
value: wordpress
- name: MYSQL_USER
value: wordpress
- name: MYSQL_PASSWORD
value: wordpress
volumeMounts:
- name: db
mountPath: /var/lib/mysql
volumes:
- name: db
hostPath:
path: /var/lib/mysql
像这样的一个 YAML 文件,对应到 Kubernetes 中,就是一个 API Object(API 对象),K8s是面向API编程,Pod是最基本的一个API对象。Pod是 Kubernetes 项目中的最小编排单位。将这个设计落实到 API 对象上,容器(Container)就成了 Pod 属性里的一个普通的字段。
这个Pod里 containers字段就是来定义容器的。volumes:定义了一个数据卷,指向了宿主机的/var/lib/mysql,而容器里则用volumeMounts字段来做关联挂载。
Deployment是更高层次的一种API对象,它可以直接控制Pod。在K8S中,这种用一种对象控制另一种对象的方式,就是控制器模式,也是面向API编程的直观体现。比如:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
这里我们定义了一个Deployment对象,它控制的Pod数量是两个,而Pod的具体属性,又通过template这个模板去生成。即描述的是一个Nginx。这样K8S通过控制循环,始终保证有两个nginx Pod实例运行。
所谓 Deployment,是一个定义多副本应用(即多个副本 Pod)的对象。Deployment 扮演的正是 Pod 的控制器的角色。这样的每一个 API 对象都有一个叫作 Metadata 的字段,这个字段就是 API 对象的“标识”,即元数据,它也是我们从 Kubernetes 里找到这个对象的主要依据。这其中最主要使用到的字段是 Labels。
像 Deployment 这样的控制器对象,就可以通过这个 Labels 字段从 Kubernetes 中过滤出它所关心的被控制对象。比如,在上面这个 YAML 文件中,Deployment 会把所有正在运行的、携带“app: nginx”标签的 Pod 识别为被管理的对象,并确保这些 Pod 的总数严格等于两个。
这个过滤规则的定义,是在 Deployment 的“spec.selector.matchLabels”字段。我们一般称之为:Label Selector。
一个 Kubernetes 的 API 对象的定义,大多可以分为 Metadata 和 Spec 两个部分。前者存放的是这个对象的元数据,对所有 API 对象来说,这一部分的字段和格式基本上是一样的;而后者存放的,则是属于这个对象独有的定义,用来描述它所要表达的功能。
我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年
我想合并多个事件记录关系例如,apple_companies=Company.where("namelike?","%apple%")banana_companies=Company.where("namelike?","%banana%")我想结合这两个关系。不是合并,合并是apple_companies.merge(banana_companies)=>Company.where("namelike?andnamelike?","%apple%","%banana%")我要Company.where("名字像?还是名字像?","%apple%","%banana%")之后,我会写代
我有一个简单的问题,与关联有关。我有一个书的模型,它有_onereservation。预订属于_书本。我想在预订Controller的创建方法中确保在预订时没有预订一本书。换句话说,我需要检查该书是否存在任何其他预订。我该怎么做?编辑:Aaa我做到了,感谢大家的提示,学到了一些新东西。当我尝试提供的解决方案时,出现no_method错误或nil_class等。这让我开始思考,我尝试处理的对象根本不存在。Krule给了我使用book.find的想法,所以我尝试使用它。最终我得到了它的工作:book=Book.find_by_id(reservation_params[:book_id])
我有一组名为Tasks和Posts的资源,它们之间存在has_and_belongs_to_many(HABTM)关系。还有一个连接它们的值的连接表。create_table'posts_tasks',:id=>falsedo|t|t.column:post_id,:integert.column:task_id,:integerend所以我的问题是如何检查特定任务的ID是否存在于从@post.tasks创建的数组中?irb(main):011:0>@post=Post.find(1)=>#@post.tasks=>[#,#]所以我的问题是,@post.tasks中是否存在"@task
根据我目前的理解,如果我必须描述Rails应用程序的各个组件如何协同工作以响应请求,我会说以下内容:1)路由确定哪些请求URL映射到哪些Controller方法。2)Controller方法从模型中获取信息并将该信息(以全局变量的形式)传递给相应的View模板。3)View模板使用存储在全局变量中的数据来构造最终响应。在上面的解释中,几个组件之间的关系是明确的,不可否认的;即:1)路由和Controller方法2)Controller方法和View模板其实上面的关系是一对一的。但是,模型类与其相邻组件类型(即Controller)的关系并不明确。是的,Controller从模型中检索信
我正在尝试使用docker运行一个Rails应用程序。通过github的sshurl安装的gem很少,如下所示:Gemfilegem'swagger-docs',:git=>'git@github.com:xyz/swagger-docs.git',:branch=>'my_branch'我在docker中添加了keys,它能够克隆所需的repo并从git安装gem。DockerfileRUNmkdir-p/root/.sshCOPY./id_rsa/root/.ssh/id_rsaRUNchmod700/root/.ssh/id_rsaRUNssh-keygen-f/root/.ss
我在目录“/home/enterprise/pkg”中有一个本地gem(enterprise-0.0.1.gem)。它依赖于active_directorygem(v1.5.5),这是在它的enterprise.gemspec文件中指定的,如下所示:-gem.add_dependency("active_directory")在我的应用程序的Gemfile中,我添加了以下行:-gem'enterprise','0.0.1',path=>'/home/enterprise/pkg'当我做的时候bundleinstall在我的应用程序的源目录中,只安装了企业gem。因此,我遇到了引用act
我正在构建这个图书馆应用程序,它有3个类。国家、图书馆和书籍。国家有许多图书馆,图书馆属于一个国家。图书馆有很多书,书是嵌入图书馆的。但是,当我执行此auto_pick_job时,我们到达top_free_book并调用library.state。由于某种原因,library.state为nil。我希望恢复状态但没有骰子。我调用和创建库的方式如下。所以图书馆将永远属于一个现有的国家。state=Stats.find(x)library=state.libaries.new(info)library.save_optimistic!我也很感激使用Struct的关系帮助。classStat