Docker Kubenetes 微服务教程(二)
四、使用 MySQL 数据库
MySQL 数据库是最常用的开源数据库。Docker 映像“mysql”可用于创建运行 MySQL 数据库实例的 Docker 容器。为单个 MySQL 实例或多个实例单独运行 Docker 缺乏调度多个实例、伸缩和为外部客户机提供服务的功能。在本章中,我们将讨论如何使用 Kubernetes 容器集群管理器来克服所有这些缺陷。
- 设置环境
- 创建服务
- 创建复制控制器
- 列出 POD
- 列出日志
- 描述服务
- 启动交互式 Shell
- 启动 MySQL CLI
- 创建数据库表
- 退出 MySQL CLI 和交互式 Shell
- 缩放副本
- 删除复制控制器
设置环境
本章需要以下软件。
- -Docker 引擎(最新版本)
- -库服务器群集管理器 1.01 版
- -Kubernetes(1.01 版)
- -MySQL dock image(最新版本)
我们使用了从 AMI Ubuntu Server 14-04 LTS (HVM)创建的 Amazon EC2 实例,SSD 卷类型- ami-d05e75b8 来安装所需的软件。安装 Docker、Kubernetes 和 Kubectl 的过程在第一章中讨论。获取 Amazon EC2 实例的公共 IP 地址,如图 4-1 所示。
图 4-1。
Obtaining the Public IP Address
SSH 使用公共 IP 地址登录 Ubuntu 实例,对于不同的用户,这个地址是不同的。
sh -i "docker.pem" ubuntu@52.90.43.0
启动 Docker 引擎并验证其状态。
sudo service docker start
sudo service docker status
Docker 引擎应被列为“正在运行”,如图 4-2 所示。
图 4-2。
Starting Docker and Verifying Its Status
创建服务
在本节中,我们将使用一个定义文件创建一个 Kubernetes 服务。我们使用了 YAML 格式的定义文件,但是也可以使用 JSON。创建一个名为mysql-service.yaml的服务定义文件,并将下面的清单复制到该文件中。在服务的spec字段映射中,“选择器”表达式被设置为app: "mysql-app,",它被翻译为服务选择器 app=mysql-app,这意味着服务将流量路由到标签为app=mysql-app的 pod。如果selector表达式为空,则选择所有窗格。在端口列表中,公开服务的端口被设置为 3306。并且该服务有一个标签app: "mysql-app"。kind field映射必须有值“服务”
apiVersion: v1
kind: Service
metadata:
-name: "mysql"
-labels:
app: "mysql-app"
spec:
-ports:
# the port that this service should serve on
- port: 3306
-# label keys and values that must match in order to receive traffic for this service
-selector:
app: "mysql-app"
服务模式在 http://kubernetes.io/v1.1/docs/api-reference/v1/definitions.html#_v1_service 可用。将 YAML 定义文件中的selector字段设置为app: "mysql-app"意味着所有具有 YAML 定义文件标签设置app: "mysql-app"的 pod 都由该服务管理。使用定义文件和kubectl create命令创建服务。
kubectl create -f mysql-service.yaml
创建了mysql服务,输出是“服务/mysql ”,如图 4-3 所示。
图 4-3。
Creating a Service for MySQL Database
使用以下命令列出服务。
kubectl get services
mysql服务列表如图 4-4 所示。
图 4-4。
Listing the mysql Service
创建复制控制器
在本节中,我们将创建一个复制控制器,该控制器由上一节中创建的服务管理。创建一个名为mysql-rc.yaml的复制控制器定义文件,并将下面/下一个清单复制到该文件中。kind字段映射必须具有值“ReplicationController”复制控制器在metadata字段映射中有一个标签app: "mysql-app"。如果标签为空,则默认为复制控制器管理的单元的标签。"spec"字段映射定义了复制控制器,并包括用于要创建的副本数量的"replicas"字段映射。在下面/下一个清单中,replicas被设置为 1。默认的副本数量也是 1。spec包括一个名为app: "mysql-app,"的selector field映射,它选择所有标签为app: "mysql-app"的 pod,供复制控制器管理并计入“副本”设置。除了选择器之外,Pod 还可以有其他标签,但是必须包括要由复制控制器管理的复制控制器的选择器表达式。类似地,复制控制器可以管理不以复制控制器定义文件启动的 pod。
YAML 定义文件中的标签和选择器表达式设置并不这样使用,而是通过用“=”替换“:”来转换为标签/选择器。比如服务/复制控制器选择器设置 app:“MySQL-app”变成选择器 app = mysql-app 选择器和标签设置 app:“MySQL-app”变成标签 app = mysql-app。
如果未指定selector,模板上的标签将用于匹配 pod,并计入“副本”设置。"template"字段映射定义了由复制控制器管理的 Pod。在template字段中的spec字段映射指定了 Pod 的行为。在"spec"字段中的"containers"字段映射定义了要创建的容器的集合/列表,包括映像、环境变量(如果有的话)以及用于每个容器的端口。
我们需要为 MySQL 数据库复制控制器使用一个环境变量。Docker 映像“mysql”需要(强制)环境变量MYSQL_ROOT_PASSWORD来运行 MySQL 数据库的 Docker 容器。变量MYSQL_ROOT_PASSWORD为root用户设置密码。环境变量通过containers字段列表中的"env"映射来设置。一个env映射由一个name映射和一个value映射组成。环境变量MYSQL_ROOT_PASSWORD的设置如下所示。"ports"字段集合包括端口 3306 的containerPort映射。YAML 文件中的缩进和连字符必须格式良好,下面的列表应被复制并在 YAML Lint ( http://www.yamllint.com/ )中进行语法验证。YAML lint 只验证语法,不验证 pod 定义字段是否符合 Pod 的模式。Pod 模式在 http://kubernetes.io/v1.1/docs/api-reference/v1/definitions.html#_v1_podspec 可用。
---
apiVersion: v1
kind: ReplicationController
metadata:
labels:
app: "mysql-app"
spec:
replicas: 1
selector:
app: "mysql-app"
template:
metadata:
labels:
app: "mysql-app"
spec:
containers:
-
env:
-
name: "MYSQL_ROOT_PASSWORD"
value: "mysql"
image: "mysql"
name: "mysql"
ports:
-
containerPort: 3306
可以在 vi 编辑器中创建mysql-rc.yaml定义文件,并用:wq 命令保存,如图 4-5 所示。
图 4-5。
Definition File for Replication Controller
用kubectl create命令从服务定义文件创建一个复制控制器。
kubectl create -f mysql-rc.yaml
如图 4-6 中的输出所示,mysql复制控制器被创建。
图 4-6。
Creating a Replication Controller for MySQL Database
使用以下命令列出复制。
kubectl get rc
mysql复制控制器包括容器名、映像名、选择器表达式(app=mysql-app)和副本数量,如图 4-7 所示。
图 4-7。
Listing the MySQL Replication Controller
要描述mysql复制控制器,运行以下命令。
kubectl describe rc mysql
复制控制器名称、命名空间、映像、选择器、标签、副本、pod 状态和事件会被列出,如图 4-8 所示。
图 4-8。
Describing the MySQL Replication Controller
列出 POD
可以使用以下命令列出创建的 pod。
kubectl get pods
如图 4-9 所示,复制控制器创建的 2 个副本被列出。最初,pod 可能不会被列为就绪 1/1。几秒钟后运行前面的命令,如果需要可以多次运行,以列出所有准备就绪的单元。
图 4-9。
Listing the Pod/s for MySQL Database
列出日志
使用以下命令列出一个 pod 的 Pod 日志:例如,mysql-wuo7x pod。
kubectl logs mysql-wuo7x
Pod 日志列表如图 4-10 所示。
图 4-10。
Listing the Logs generated by the Pod for MySQL Database
如图 4-11 所示,MySQL 服务器被列为已启动并“准备连接”。
图 4-11。
Listing mysqld as Ready for Connections
描述服务
要描述mysql服务,请运行以下命令。
kubectl describe svc mysql
服务名称、命名空间、标签、选择器、类型、Ip、端口和端点都会列出。因为副本数量设置为 1,所以仅列出一个端点,如图 4-12 所示。
图 4-12。
Describing the MySQL Service
启动交互式 Shell
Bash 是随 Linux 和 GNU 操作系统(OS)发布的 Bourne shell 的免费版本。对于在Dockerfile中的FROM指令中指定的以 Linux OS 映像作为基础映像的 Docker 映像,可以使用 Bash shell 访问 Docker 容器中运行的软件。"mysql" Docker 映像基于"debian"映像,因此支持通过 bash 交互式 shell 访问 Docker 容器中运行的软件。
接下来,我们将启动一个交互式 shell 来启动 MySQL CLI。但是首先我们需要获得一个运行 MySQL 的容器的容器 id。运行以下命令列出 Docker 容器。
sudo docker ps
图 4-13 中列出了mysql映像的 Docker 容器。
图 4-13。
Listing the Docker Containers
使用前面命令输出中的 Docker 容器 id,启动一个交互式 shell。
sudo docker exec -it 526f5d5f6c2e bash
交互式 shell 或 tty 启动,如图 4-14 所示。
图 4-14。
Starting the Interactive Terminal
启动 MySQL CLI
在交互式 shell 中运行以下命令,以 root 用户身份启动 MySQL CLI。
mysql –u root –p
当提示输入密码时:将密码设置为环境变量MYSQL_ROOT_PASSWORD的值,在mysql-rc.yaml定义文件中设置为“mysql”。MySQL CLI 启动,如图 4-15 所示。
图 4-15。
Starting the MySQL CLI Shell
使用以下命令列出数据库。
show databases;
图 4-16 中显示的默认数据库包括"mysql"数据库,我们将用它来创建一个数据库表。其他数据库是系统数据库,不应用于用户表。
图 4-16。
Listing the Databases
使用以下命令将数据库“mysql”设置为当前数据库。
use mysql
如图 4-17 中的“数据库已更改”输出所示,数据库被设置为mysql。
图 4-17。
Setting the Database
创建数据库表
接下来,用下面的 SQL 语句创建一个名为Catalog的数据库表。
CREATE TABLE Catalog(CatalogId INTEGER PRIMARY KEY,Journal VARCHAR(25),Publisher VARCHAR(25),Edition VARCHAR(25),Title VARCHAR(45),Author VARCHAR(25));
使用下面的 SQL 语句向Catalog表添加一行数据。
INSERT INTO Catalog VALUES('1','Oracle Magazine','Oracle Publishing','November December 2013','Engineering as a Service','David A. Kelly');
创建Catalog表并添加一行数据,如图 4-18 所示。
图 4-18。
Creating a MySQL Database Table
随后运行以下 SQL 语句来查询数据库表Catalog。
SELECT * FROM Catalog;
添加的单行数据被列出,如图 4-19 所示。
图 4-19。
Querying the Database Table
退出 MySQL CLI 和交互式 Shell
使用“quit”命令退出 MySQL CLI。
quit
使用“退出”命令退出交互终端。
exit
前面命令的输出如图 4-20 所示。
图 4-20。
Exiting the MySQL CLI Shell and Docker Container Interactive Shell
缩放副本
Kubernetes 的主要优势之一是能够扩展集群中 MySQL 实例的数量。运行下面的kubectl scale命令将副本从 1 扩展到 4。
kubectl scale rc mysql --replicas=4
随后运行以下命令来列出窗格。
kubectl get pods
MySQL 数据库的 Pods 数量增加到 4 个,如图 4-21 所示。一些吊舱可能被列为就绪- > 0/1,这意味着吊舱尚未就绪。当 READY 变为 1/1 时,可以访问 Pod。0/1 值意味着箱中的 1 个 Docker 容器中的 0 个准备好了,类似地,1/1 值意味着 1 个容器中的 1 个准备好了。如果 Pod 中的所有 n 个容器都在运行,则就绪列值的一般语法是 n/n 形式。Pod 的状态必须是“正在运行”才能被视为可用。
图 4-21。
Scaling the Pod Replicas to Four
要描述mysql服务,运行以下命令。
kubectl describe svc mysql
服务描述与之前相同,只是端点的数量增加到了 4 个,如图 4-22 所示。
图 4-22。
Describing the MySQL Service After Scaling the Pod Replicas
命令“scale”还允许我们为所需的缩放操作指定一个或多个前提条件。支持以下(表 4-1 )前提条件。
表 4-1。
Preconditions for the ‘kubernetes scale’ command
| 前提 | 描述 | | --- | --- | | -当前副本 | 要执行的缩放的当前副本数。 | | -资源-版本 | 与要执行的缩放匹配的资源版本。 |删除复制控制器
要删除复制控制器mysql,请运行以下命令。
kubectl delete rc mysql
复制控制器被删除,如图 4-23 所示。每当用于创建或删除工件(Pod、服务或复制控制器)的kubectl命令输出具有工件类型/工件名称的形式时,这意味着该命令已经成功创建/删除了 Pod/服务/复制控制器。
图 4-23。
Deleting the Replication Controller
随后运行以下命令来获取复制控制器。mysql rc 未列出,如图 4-24 所示。
图 4-24。
Describing the Service after Deleting the Replication Controllers
kubectl get rc
用下面的命令再次描述服务mysql。
kubectl describe svc mysql
没有如图 4-24 所示的“端点”被列出,因为当管理它们的复制控制器被删除时,所有的 pod 也被删除。
摘要
在本章中,我们讨论了使用 Kubernetes 集群管理器编排 MySQL 数据库集群。我们创建了一个 Kubernetes 服务来代表一个基于 MySQL 的 Pod。“MySQL”Docker 映像用于创建一个 Pod。我们使用复制控制器为 MySQL base Pods 创建副本。最初,副本的数量设置为 1。我们使用一个运行 MySQL 实例的 Docker 容器来启动 MySQL CLI 并创建一个数据库表。随后,我们使用复制控制器将副本数量扩展到 4 个。缩放后,副本的数量以及 MySQL 实例的数量变为 4。复制控制器在复制失败或复制被用户关闭时维持复制级别。本章还演示了环境变量的使用。运行 Docker 映像“mysql”的容器需要使用MYSQL_ROOT_PASSWORD环境变量,我们在复制控制器的 Pod 规范中设置了MYSQL_ROOT_PASSWORD环境变量。在下一章,我们将讨论使用另一个开源数据库,PostgreSQL 数据库。
五、使用 PostgreSQL 数据库
PostgreSQL 是一个开源的对象关系数据库。PostgreSQL 在数据量和并发用户数量方面都是可伸缩的。PostgreSQL 在多个 Apache Hadoop 生态系统项目(如 Apache Sqoop)中受支持,并可用于 Apache Hive Metastore。PostgreSQL 9.5 提供了几个新特性,比如支持UPSERT、BRIN索引、更快的排序,以及用于获取大型表的统计样本的TABLESAMPLE子句。在本章中,我们将讨论使用 Kubernetes 集群管理器创建 PostgreSQL 9.5 集群。我们将讨论创建和扩展 PostgreSQL 集群的命令式方法和声明式方法。本章包括以下几节。
- 设置环境
- 以声明方式创建 PostgreSQL 集群
- 强制创建 PostgreSQL 集群
设置环境
我们在本章中使用了与其他章节相同类型的 Amazon EC2 实例,一个基于 Ubuntu Server 14.04 LTS (HVM),SSD 卷类型- ami-d05e75b8 AMI 的实例。本章需要以下软件。
- -Docker 引擎(最新版本)
- -库服务器群集管理器 1.01 版
- -Kubernetes(1.01 版)
- -Docker 映像“postgres”(最新版本)
安装所需软件、启动 Docker 引擎和 Kubernetes 集群管理器的过程将在第一章中讨论。要安装软件,首先我们需要登录 Amazon EC2 实例。获取 Amazon EC2 实例的公共 IP 地址,如图 5-1 所示。
图 5-1。
Obtaining the Public IP Address
使用公共 IP 地址 SSH 登录到 Ubuntu 实例。
ssh -i "docker.pem" ubuntu@52.91.60.182
启动 Docker 引擎并验证其状态。
sudo service docker start
sudo service docker status
如图 5-2 所示,Docker 应显示为“正在运行”。
图 5-2。
Starting Docker
使用以下命令列出服务。
kubectl get services
kubernetes 服务应该被列出,如图 5-3 所示。
图 5-3。
Listing the Kubernetes Services
以声明方式创建 PostgreSQL 集群
在下面的小节中,我们将以声明的方式创建和管理 PostgreSQL 集群,这意味着我们将使用定义文件。定义文件可以基于 YAML 格式或 JSON 格式。我们将使用 YAML 格式。建议首先创建服务,以便随后创建的任何 pod 都有一个服务来代表它们。如果首先创建 RC(复制控制器),则在创建服务之前,pod 不可用。
创建服务
创建一个服务定义文件postgres-service.yaml,并将下面的清单复制到该文件中。服务的"spec"字段映射指定了服务的行为。服务公开的端口在"ports"字段映射中定义。只有端口 5432 是公开的,因为 PostgreSQL 在端口 5432 上运行。selector表达式被设置为app: "postgres"。所有带有标签app=postgres的 pod 都由该服务管理。
apiVersion: v1
kind: Service
metadata:
name: "postgres"
labels:
app: "postgres"
spec:
ports:
- port: 5432
selector:
app: "postgres"
可以使用 vi 编辑器创建postgres-service.yaml文件,并使用:wq 命令保存,如图 5-4 所示。
图 5-4。
Service Definition File postgres-service.yaml
使用带有postgres-service.yaml定义文件的kubectl create命令创建服务。
kubectl create -f postgres-service.yaml
随后列出服务。
kubectl get services
也列出 POD。
kubectl get pods
第一个命令的输出services/postgres表示服务已经创建。第二个命令列出了在端口 5432 运行的postgres服务,如图 5-5 所示。还列出了服务的 IP 地址。单独创建一个服务并不会单独创建一个 Pod,只会列出 Kubernetes 的 Pod。一个服务只管理或提供一个 pod 接口,该 pod 的标签与服务中的selector表达式相匹配。
图 5-5。
Creating a Service and listing the Service
用下面的命令描述服务postgres。
kubectl describe svc postgres
服务名、名称空间、标签、选择器、类型、IP 地址、公开的端口和端点都会列出。因为没有 Pods 最初与服务相关联,所以没有列出端点,如图 5-6 所示。
图 5-6。
Describing the postgres Service
创建复制控制器
在本节中,我们将为复制控制器创建一个定义文件。创建一个名为postgres-rc.yaml的定义文件。定义文件具有表 5-1 中讨论的字段。
表 5-1。
Replication Controller Definition File postgres-rc.yaml
| 田 | 价值 | 描述 | | --- | --- | --- | | apiVersion(堆叠版本) | 第五颅神经的眼支 | API 版本。 | | 种类 | 复制控制器 | 将文件定义为复制控制器。 | | 元数据 | | 复制控制器的元数据。 | | 元数据->名称 | | 复制控制器的名称。必须指定名称或 generateName 字段。generateName 字段是在自动生成的名称中使用的前缀。 | | 投机 | | 复制控制器的规格。 | | 规格->副本 | Two | 要创建的 Pod 副本的数量。 | | 模板 | | 为复制控制器管理的 Pod 指定模板。 | | 模板->元数据 | | Pod 的元数据,包括标签。标签用于选择由复制控制器管理的 Pod,并且如果服务要表示 Pod,则必须管理服务定义文件中的选择器表达式。 | | 模板->规格 | | Pod 规格或配置。 | | 模板->规格->容器 | | POD 里的容器。可以指定多个容器,但本章只指定了 PostgreSQL 的容器。 | | 模板->规格->容器->映像模板->规格->容器->名称 | | 要在容器中运行的 Docker 映像。对于 PostgreSQL,映像是“postgres”名称字段指定容器名称。 |可选地,可以指定复制控制器的selector字段映射。selector中的键:值映射必须与模板- >元数据字段映射中的标签相匹配,以便复制控制器管理模板中的 Pod。如果没有指定,selector字段映射默认为模板- >元数据- > labels字段映射。在下面的列表中,selector是斜体,不包括在使用的定义文件中。Pod 的模板- >元数据- >标签字段映射指定了一个表达式app: "postgres", which translates to Pod label app=postgres。对于管理 Pod 的服务来说,labels字段表达式必须与服务定义文件中的"selector"字段表达式相同,这在上一节中已经讨论过。
apiVersion: v1
kind: ReplicationController
metadata:
name: "postgres"
spec:
replicas: 2
selector:
- app: "postgres"
template:
metadata:
labels:
app: "postgres"
spec:
containers:
-
image: "postgres"
name: "postgres"
将前面的清单复制到postgres-rc.yaml文件中。可以在 vi 编辑器中打开postgres-rc.yaml文件,并用:wq 保存,如图 5-7 所示。
图 5-7。
Replication Controller Definition File
使用定义文件postgres-rc.yaml创建一个复制控制器。
kubectl create -f postgres-rc.yaml
随后列出复制控制器。
kubectl get rc
如图 5-8 所示的第一个命令的输出replicationcontrollers/postgres表示复制控制器postgres已经创建。第二个命令列出了postgres复制控制器。如前所述,复制控制器选择器列设置为与 Pod 标签相同的值,app=postgres。
图 5-8。
Creating and listing the Replication Controller for PostgreSQL Database
用下面的命令描述复制控制器postgres。
kubectl describe rc postgres
复制控制器的名称、命名空间、与 rc 相关联的映像、选择器(如果有)、标签、副本数量、pod 状态和事件会被列出,如图 5-9 所示。
图 5-9。
Describing the Replication Controller for PostgreSQL Database
拿到 POD
要获取并列出窗格,请运行以下命令。
kubectl get pods
由复制控制器创建的两个 pod 被列出,如图 5-10 所示。pod 应处于运行状态,并且就绪列值为 1/1。
图 5-10。
Listing the Pods for PostgreSQL Database
启动交互式命令外壳
为了能够创建 PostgreSQL 表,我们需要启动一个交互式 bash shell 来访问 Docker 容器中运行的 PostgreSQL 服务器,并为 PostgreSQL 启动 psql SQL shell。但是,首先我们需要找到运行 PostgreSQL 数据库的 Docker 容器的容器 id。运行以下命令列出 Docker 容器。
sudo docker ps
其中两个 Docker 容器基于“postgres”映像,如图 5-11 所示。从容器 id 列中复制第一个 Docker 容器的容器 ID。
图 5-11。
Listing the Docker Containers
使用容器 id 启动交互式 shell。
sudo docker exec -it a786960b2cb6 bash
交互外壳启动,如图 5-12 所示。
图 5-12。
Starting an Interactive Shell
启动 PostgreSQL SQL 终端
接下来,为 PostgreSQL 启动 psql SQL shell。将用户设置为postgres。
su –l postgres
使用以下命令启动 psql 命令行 shell。
psql postgres
psql 应如图 5-13 所示启动。
图 5-13。
Starting the psql CLI Shell
关于psql命令的一般命令语法,请参考 http://www.postgresql.org/docs/9.5/static/app-psql.html 。
创建数据库表
在 psql shell 中运行以下 sql 语句,创建一个名为wlslog的数据库表,并向该表添加数据。
CREATE TABLE wlslog(time_stamp VARCHAR(255) PRIMARY KEY,category VARCHAR(255),type VARCHAR(255),servername VARCHAR(255),code VARCHAR(255),msg VARCHAR(255));
INSERT INTO wlslog(time_stamp,category,type,servername,code,msg) VALUES('Apr-8-2014-7:06:16-PM-PDT','Notice','WebLogicServer','AdminServer','BEA-000365','Server state changed to STANDBY');
INSERT INTO wlslog(time_stamp,category,type,servername,code,msg) VALUES('Apr-8-2014-7:06:17-PM-PDT','Notice','WebLogicServer','AdminServer','BEA-000365','Server state changed to STARTING');
INSERT INTO wlslog(time_stamp,category,type,servername,code,msg) VALUES('Apr-8-2014-7:06:18-PM-PDT','Notice','WebLogicServer','AdminServer','BEA-000360','Server started in RUNNING mode');
创建数据库表wlslog并添加一行数据,如图 5-14 所示。
图 5-14。
Creating a Database Table
运行以下 SQL 语句来查询数据库表wlslog。
SELECT * FROM wlslog;
添加的 3 行数据被列出,如图 5-15 所示。
图 5-15。
Querying the Database Table
退出交互式命令外壳
要退出 psql shell,请运行以下命令。
\q
要退出交互式终端,请运行以下命令。
exit
psql 外壳和交互外壳退出,如图 5-16 所示。
图 5-16。
Exiting the psql Shell and Docker Container Interactive Shell
扩展 PostgreSQL 集群
Kubernetes 集群管理器的主要优点之一是能够根据需要扩展集群。最初,我们创建了两个副本。例如,要将 PostgreSQL 实例的数量增加到 4 个,请运行以下命令。
kubectl scale rc postgres --replicas=4
前一个命令的“scaled”输出表明集群已经被缩放,如图 5-17 所示。
图 5-17。
Scaling the number of Pod Replicas to 4
随后使用以下命令列出 pod。
kubectl get pods
如图 5-18 所示,列出 4 个吊舱。最初,一些容器可能被列为未“运行”和/或未处于就绪(1/1)状态。
图 5-18。
Listing the Pods after Scaling
几秒钟后再次运行前面的命令。
kubectl get pods
如图 5-19 所示,添加到集群中的新单元也被列为“正在运行”并处于就绪状态 1/1。
图 5-19。
Listing all the Pods as running and ready
再次描述一下postgres服务。
kubectl describe svc postgres
最初,当服务最初启动时,没有端点被列为与服务相关联。4 个 pod 运行时,列出 4 个端点,如图 5-20 所示。
图 5-20。
Describing the postgres Service
列出日志
要列出 Pod 的日志数据,例如 postgres-v0k42 Pod,请运行以下命令。
kubectl logs postgres-v0k42
图 5-21 中的输出列出了 PostgreSQL 启动。
图 5-21。
Listing the Logs for a Pod running PostgreSQL Database
当 PostgreSQL 数据库完全启动时,“数据库系统已准备好接受连接”的消息会输出,如图 5-22 所示。
图 5-22。
PostgreSQL Database listed as Started and subsequently Shutdown in the Logs
删除复制控制器
要删除复制控制器postgres并因此删除由复制控制器管理的所有 pod,请运行以下命令。
kubectl delete rc postgres
postgres复制控制器被删除,如图 5-23 中的replicationcontrollers/postgres输出所示。随后,运行以下命令列出复制控制器。
图 5-23。
Deleting a Replication Controller
kubectl get rc
postgres复制控制器未列出,如图 5-23 所示。删除复制控制器不会删除管理复制控制器的服务。要演示,请列出服务。
kubectl get services
postgres服务仍在列表中,如图 5-23 所示。
停止服务
要停止服务postgres,请运行以下命令。
kubectl stop service postgres
随后再次运行以下命令。
kubectl get services
postgres服务未列出,如图 5-24 所示。
图 5-24。
Stopping the postgres Service
强制创建 PostgreSQL 集群
对定义文件使用声明性方法可以更好地控制服务和复制控制器。但是复制控制器和服务也可以在命令行上用kubectl命令创建。在下面的小节中,我们将创建一个复制控制器和一个服务。
创建复制控制器
要为映像“postgres”创建名为postgres的复制控制器,副本数量为 2,Post as 为 5432,请运行以下命令。
kubectl run postgres --image=postgres --replicas=2 --port=5432
带有映像postgres和selector表情run=postgres的 Pod 的 2 个副本的postgres复制控制器被创建,如图 5-25 所示。
图 5-25。
Creating a Replication Controller Imperatively
使用以下命令列出复制控制器。
kubectl get rc
postgres复制控制器列表如图 5-26 所示。
图 5-26。
Listing the Replication Controllers
拿到 POD
要列出由复制控制器管理的 pod,请运行以下命令。
kubectl get pods
如图 5-27 所示,两个吊舱被列出。最初,一些 pod 可能被列为未就绪,如 0/1 就绪列值所示。再次运行前面的命令,列出就绪列值为 1/1 的窗格。
图 5-27。
Listing the Pods
创建服务
要创建服务,我们需要运行kubectl expose命令。最初只有kubernetes服务在运行。要进行演示,请运行以下命令。
kubectl get services
如图 5-28 所示,只列出了kubernetes服务。
图 5-28。
Listing the “kubernetes” Service
要为复制控制器"postgres"创建服务,请运行以下命令,其中–port参数指定服务公开的端口。服务类型设置为LoadBalancer。
kubectl expose rc postgres --port=5432 --type=LoadBalancer
随后列出服务。
kubectl get services
postgres 服务被列出,如图 5-29 所示。
图 5-29。
Creating a Service exposed at Port 5432
创建数据库表
创建数据库表的过程与前面针对声明性部分所讨论的过程相同,在本部分中只简单讨论一下。用下面的命令列出 Docker 容器。
sudo docker ps
如图 5-30 所示,其中两个 Docker 容器的映像列为postgres。从容器 id 列中复制这些列之一的容器 ID。
图 5-30。
Listing the Docker Containers
使用以下命令启动交互式 shell。
sudo docker exec -it af0ac629b0e7d bash
交互终端启动,如图 5-31 所示。
图 5-31。
Starting the TTY
将用户设置为postgres。
su –l postgres
启动psql命令行外壳。
psql postgres
psql壳体如图 5-32 所示。
图 5-32。
Starting the psql Shell
运行以下 SQL 语句创建一个名为wlslog的数据库表,并向该表添加数据。
CREATE TABLE wlslog(time_stamp VARCHAR(255) PRIMARY KEY,category VARCHAR(255),type VARCHAR(255),servername VARCHAR(255),code VARCHAR(255),msg VARCHAR(255));
INSERT INTO wlslog(time_stamp,category,type,servername,code,msg) VALUES('Apr-8-2014-7:06:16-PM-PDT','Notice','WebLogicServer','AdminServer','BEA-000365','Server state changed to STANDBY');
INSERT INTO wlslog(time_stamp,category,type,servername,code,msg) VALUES('Apr-8-2014-7:06:17-PM-PDT','Notice','WebLogicServer','AdminServer','BEA-000365','Server state changed to STARTING');
INSERT INTO wlslog(time_stamp,category,type,servername,code,msg) VALUES('Apr-8-2014-7:06:18-PM-PDT','Notice','WebLogicServer','AdminServer','BEA-000360','Server started in RUNNING mode');
数据库表wlslog被创建,如图 5-33 所示。
图 5-33。
Creating a Database Table
运行以下 SQL 语句来查询wlslog表。
SELECT * FROM wlslog;
添加的三行数据被列出,如图 5-34 所示。
图 5-34。
Querying the wlslog Database Table
要退出运行 PostgreSQL 的 Docker 容器的psql shell 和交互式 shell,请运行以下命令。
\q
exit
psql shell 和 tty 退出,如图 5-35 所示。
图 5-35。
Exiting the Shells
扩展 PostgreSQL 集群
最初创建集群时,我们将副本数设置为 2。如下列出 pod。
kubectl get pods
仅列出两个吊舱,如图 5-36 所示。
图 5-36。
Listing the Pods
使用以下命令将集群扩展到 4 个副本。
kubectl scale rc postgres --replicas=4
如图 5-37 所示的“已缩放”输出表明该集群已被缩放。
图 5-37。
Scaling the Pod Replicas to 4
随后列出 POD。
kubectl get pods
如图 5-38 所示,前面的命令可能需要运行多次才能将所有的 pod 列为“运行中”并处于就绪状态 1/1。
图 5-38。
Listing the Pods in various states of starting
删除复制控制器
要删除复制控制器,请运行以下命令。
kubectl delete rc postgres
删除 rc 后列出 pod。
kubectl get pods
列出服务。
kubectl get services
如图 5-39 所示,postgres复制控制器被删除并且没有在后面列出。图 5-39 中也显示了postgres服务仍然被列出。
图 5-39。
Deleting the Replication Controller
停止服务
要停止该服务,请运行以下命令。
kubectl stop service postgres
postgres服务停止,如图 5-40 所示。随后运行以下命令。
图 5-40。
Stopping the Service
kubectl get services
postgres服务也没有列出,如图 5-40 所示。
摘要
在本章中,我们使用 Kubernetes 集群管理器来启动和管理 PostgreSQL 服务器集群。我们演示了在命令行上强制创建集群和使用定义文件以声明方式创建集群。我们使用复制控制器扩展集群,并使用 Kubernetes 服务公开集群的服务。在下一章中,我们将讨论创建和管理 Oracle 数据库集群。
六、使用 Oracle 数据库
Oracle 数据库是最常用的关系数据库(RDBMS)。安装和配置 Oracle 数据库通常包括下载软件、设置内核参数、安装和配置软件,所有这些都非常复杂。使用与 Kubernetes 相协调的 Docker 容器使得安装、配置和编排 Oracle 数据库集群的任务变得更加容易。由多个实例组成的 Oracle 数据库集群可以受益于 Kubernetes 容器集群管理器的可调度性、可伸缩性、分布性和故障转移特性。在本章中,我们将使用数据库的 Docker 映像来安装 Oracle 数据库。我们将使用复制控制器创建数据库 Pod 的多个副本,并将数据库作为服务公开。本章包括以下几节。
- 设置环境
- 强制创建 Oracle 数据库实例
- 以声明方式创建 Oracle 数据库实例
- 保持复制级别
- 扩展数据库
- 启动交互式 Shell
- 连接到数据库
- 创建用户
- 创建数据库表
- 退出交互式外壳
设置环境
本章需要以下软件。
- -Docker 引擎(最新版本)
- -Kubernetes(1.01 版)
- -Kubernetes(1.01 版)
- -Oracle 数据库的 Docker 映像(Oracle 数据库 XE 11g)
如果尚未安装,请按照第一章所述安装 Docker 引擎、Kubernetes 和 Kubectl。使用 EC2 实例的公共 IP 地址 SSH 登录 Amazon EC2 上的 Ubuntu 实例。
ssh -i "docker.pem" ubuntu@52.90.115.30
使用以下命令启动 Docker 实例并验证其状态。
sudo service docker start
sudo service docker status
图 6-1 中显示对接器正在运行。
图 6-1。
Starting Docker and verifying its Status
列出正在运行的服务。
kubectl get services
在图 6-2 中,只有kubernetes服务被列为正在运行。
图 6-2。
Listing the Kubernetes Service
强制创建 Oracle 数据库实例
在本节中,我们将在命令行上使用kubectl创建一个 Oracle 数据库集群。Oracle 数据库有几种 Docker 映像,我们将使用sath89/oracle-xe-11g映像( https://hub.docker.com/r/sath89/oracle-xe-11g/ )。运行下面的kubectl命令创建一个 Oracle 数据库集群,该集群包含 2 个副本,端口设置为 1521。
kubectl run oradb --image=sath89/oracle-xe-11g --replicas=2 --port=1521
图 6-3 中命令的输出列出了一个名为oradb的复制控制器,一个名为oradb的 Docker 容器,一个用于选择包含复制控制器副本的 pod 的选择器(run=oradb,以及副本的数量(2)。Pod 标签也被设置为run=oradb。
图 6-3。
Creating a Replication Controller and Pod Replicas for Oracle Database
使用以下命令列出复制控制器。
kubectl get rc
图 6-4 所示的oradb复制控制器上市。
图 6-4。
Listing the Replication Controllers
使用以下命令列出窗格。
kubectl get pods
除了 Kubernetes Pod k8s-master-127.0.0.1之外,Oracle 数据库还列出了另外两个 Pod,如图 6-5 所示。最初,pod 可能被列为“未准备好”,如图 6-5 所示。在几秒钟后运行前面的命令,如果需要,可以多次运行,以列出两个 pod 正在运行并准备就绪(1/1)。
图 6-5。
Listing the Pods in various stages of running
使用以下命令获取节点。
kubectl get nodes
并使用下面的命令获得 Kubernetes 服务。
kubectl get services
只有kubernetes服务被列出,如图 6-6 所示,因为我们还没有为 Oracle 数据库创建服务。
图 6-6。
Creating a Replication Controller does not create a Service
列出日志
使用以下命令列出其中一个 pod 的日志。
kubectl logs oradb-ea57r
由一个已启动的 Oracle 数据库实例生成的日志得到如图 6-7 所示的输出。Oracle Net 监听程序显示为已启动。
图 6-7。
Listing Logs for a Pod
创建服务
接下来,在端口 1521 上公开复制控制器oradb作为 Kubernetes 服务。随后列出 Kubernetes 服务。
kubectl expose rc oradb --port=1521 --type=LoadBalancer
kubectl get services
前面两个命令中的第一个启动了oradb服务。随后,服务被列出,如图 6-8 所示。服务选择器是 run=oradb,它与复制控制器选择器相同。
图 6-8。
Creating a Service Imperatively
用下面的命令描述服务。
kubectl describe svc oradb
服务名称、名称空间、标签、选择器、类型、IP、端口、节点端口和端点被列出,如图 6-9 所示。
图 6-9。
Describing the oradb Service
扩展数据库
运行kubectl scale命令来缩放副本。例如,将副本数量减少到 1。
kubectl scale rc oradb --replicas=1
“已缩放”的输出表示复制品已被缩放,如图 6-10 所示。
图 6-10。
Scaling the Replicas to 1
随后列出正在运行的 pod。
kubectl get pods
仅列出一个 Oracle 数据库 Pod,因为另一个已停止,以将复制级别降至一级,如图 6-11 所示。随后,描述服务。
图 6-11。
Listing and Describing the Single Pod
kubectl describe svc oradb
因为集群已经缩减到一个副本,所以端点的数量也减少到一个,如图 6-11 所示。
删除复制控制器和服务
在后续部分中,我们将使用定义文件以声明方式创建一个 Oracle 数据库实例集群。因为我们将使用相同的配置参数,所以用下面的命令删除"oradb"复制控制器和"oradb"服务。
kubectl delete rc oradb
kubectl delete svc oradb
复制控制器和服务都被删除,如图 6-12 所示。
图 6-12。
Deleting the Replication Controller and Service
以声明方式创建 Oracle 数据库实例
在本节中,我们将使用 Pod、复制控制器和服务的定义文件以声明方式创建 Oracle 数据库集群。我们在定义文件中使用了 YAML 格式,但是也可以使用 JSON 格式。
创建 Pod
为名为oradb.yaml的 Pod 创建一个定义文件。复制下面的清单,其中定义了一个名为“oradb”的 Pod,标签设置为name: "oradb",转换为 Pod label name=oradb。容器映像设置为“sath89/oracle-xe-11g”,容器端口设置为 1521。
apiVersion: v1
kind: Pod
metadata:
name: "oradb"
labels:
name: "oradb"
spec:
containers:
-
image: "sath89/oracle-xe-11g"
name: "oradb"
ports:
-
containerPort: 1521
restartPolicy: Always
可以在 vi 编辑器中创建oradb.yaml文件,并用:wq 命令保存,如图 6-13 所示。
图 6-13。
Pod Definition File
使用定义文件oradb.yaml和kubectl create命令创建一个 Pod。
kubectl create -f oradb.yaml --validate
图 6-14 中“Pod/oradb”的输出表明oradb Pod 已经创建。
图 6-14。
Creating a Pod from a Definition File
随后,使用以下命令列出正在运行的 pod。
kubectl get pods
单个吊舱oradb被列出,如图 6-15 所示。最初,oradb Pod 可以在启动的不同阶段列出,例如映像“准备好,容器正在创建”或者就绪值可以是 0/1,表示 Pod 尚未准备好。当状态栏变为“正在运行”且就绪栏变为 1/1 时,Pod 启动并就绪。前面的命令可能需要运行多次才能将 Pod 列为正在运行和就绪。
图 6-15。
Listing the Pod/s, which could initially be not Running and not Ready
创建服务
接下来,为 Oracle 数据库集群创建一个服务。该服务不指定有多少 Oracle 数据库映像实例(副本)正在运行或应该运行。副本由复制控制器控制。该服务只定义了一个用于公开服务的端口、一个用于服务的标签和一个用于匹配由该服务管理的 pod 的选择器。选择器设置是 app:“oradb”,翻译过来就是服务选择器 app=oradb。创建一个服务定义文件oradb-service.yaml,并将下面的清单复制到定义文件中。
apiVersion: v1
kind: Service
metadata:
name: "oradb"
labels:
app: "oradb"
spec:
ports:
-
port: 1521
selector:
app: "oradb"
可以在 vi 编辑器中创建oradb-service.yaml定义文件,并用:wq 保存,如图 6-16 所示。
图 6-16。
Service Definition File
运行以下命令从服务定义文件创建服务。
kubectl create -f oradb-service.yaml
如图 6-17 中的“服务/oradb”输出所示,oradb服务被创建。随后列出服务。
图 6-17。
Creating a Service from a Service Definition File
kubectl get services
oradb服务列表如图 6-17 所示。
用下面的命令描述oradb服务。
kubectl describe svc oradb
没有列出如图 6-18 所示的服务端点,因为服务选择器与已经运行的 Pod 上的标签不匹配。服务选择器 app=oradb 必须与 Pod 标签相匹配,服务才能管理 Pod。在下一节中,我们将创建一个带有匹配标签的复制控制器。
图 6-18。
Describing a Service for Oracle Database
创建复制控制器
创建一个名为oradb-rc.yaml的复制控制器定义文件,并将下面定义复制控制器的清单复制到定义文件中。为了让复制控制器管理在 spec 字段中定义的 Pod,复制控制器中选择器的 key:value 表达式必须与 Pod 模板映射中的标签相匹配。oradb-rc.yaml中省略了selector,但是必须指定规格- >模板- >元数据- >标签。选择器默认为与spec->template->metadata->labels相同的设置。template->spec->containers 映射定义了 Pod 中的容器。仅定义了 Oracle 数据库容器“sath89/oracle-xe-11g”。
apiVersion: v1
kind: ReplicationController
metadata:
name: "oradb"
labels:
app: "oradb"
spec:
replicas: 2
template:
metadata:
labels:
app: "oradb"
spec:
containers:
-
image: "sath89/oracle-xe-11g"
name: "oradb"
可以在 vi 编辑器中编辑oradb-rc.yaml文件,并用:wq 命令保存,如图 6-19 所示。
图 6-19。
Replication Controller Definition File
接下来,运行下面的命令,从定义文件oradb-rc.yaml创建一个复制控制器。
kubectl create -f oradb-rc.yaml
复制控制器的创建如图 6-20 所示。使用以下命令列出复制控制器。
图 6-20。
Creating and listing a Replication Controller from a Definition File
kubectl get rc
oradb复制控制器被创建,如图 6-20 所示。
由复制控制器创建的 pod 用以下命令列出。
kubectl get pods
如图 6-21 所示,列出了三个 Oracle 数据库单元。为什么即使复制控制器副本设置为 2,也会列出三个 pod?因为开始使用 Pod 定义文件oradb.yaml的 Pod 不包括与复制控制器中的选择器相匹配的标签。复制控制器选择器是app: "oradb",而盒上的标签是name: "oradb"。两个副本由复制控制器启动,一个 pod 由 Pod 定义文件提前启动。
图 6-21。
Listing the Pod Replicas
用下面的命令描述服务oradb。
kubectl describe svc oradb
服务端点被列出,如图 6-22 所示。只列出了两个端点,因为服务选择器应用:“oradb”与复制控制器中的 Pod 标签匹配,有两个副本。先前创建的 Pod 不包含与选择器表达式匹配的标签。
图 6-22。
Describing the Service after creating the Replication Controller
保持复制级别
复制控制器的任务是维护 pod 的复制级别。因为复制控制器规范中的replicas字段映射为 2,所以在复制控制器运行时,Pod 规范中配置的 Pod 的两个副本必须一直运行。要证明复制级别保持不变,请删除一个单元。
kubectl delete pod oradb-5ntnj
随后列出正在运行的 pod。
kubectl get pods
两个副本中的一个被kubectl delete pod 命令删除,但另一个副本在图 6-23 中被列为开始。副本可能需要几秒钟才能达到复制级别。多次运行上述命令,将复制副本列为正在运行。复制品的数量回到 2。
图 6-23。
Maintaining the Replication Level
"oradb" Pod 与复制控制器没有关联,因此它不被算作复制控制器管理的副本之一。复制控制器不管理oradb箱,因为如前所述,oradb箱上的标签与复制控制器上的标签不匹配。为了证明oradb pod 不受复制控制器管理,请删除该 pod。
kubectl delete pod oradb
随后列出正在运行的 pod。
kubectl get pods
如图 6-24 所示,oradb Pod 被删除,替换 Pod 未启动,也未在运行 Pod 中列出。
图 6-24。
The oradb Pod is not managed by the Replication Controller
扩展数据库
复制控制器可用于扩展为 Oracle 数据库运行的 pod 的数量。例如,将 Pod 副本的数量从 2 个增加到 3 个。
kubectl scale rc oradb --replicas=3
“缩放”输出表示副本已被缩放。随后运行以下命令,如果需要可以多次运行,以将新的 Pod 复制副本列为正在运行和就绪。
kubectl get pods
如图 6-25 所示,列出了 Pod 的三个副本。
图 6-25。
Scaling the Cluster to 3 Replicas
再次描述服务。
kubectl describe svc oradb
如图 6-26 所示,列出了三个端点,而不是两个。该服务只有一个 IP 地址。
图 6-26。
Listing the 3 Endpoints in the Service
启动交互式 Shell
在本节中,我们将启动一个交互式 tty (shell)来连接软件,该软件是 Oracle 数据库,运行在由 Kubernetes 启动和管理的 Docker 容器中。首先,用下面的命令列出 Docker 容器。
sudo docker ps
复制sath89/oracle-xe-11g映像的一个 Docker 容器的容器 id,如图 6-27 所示。
图 6-27。
Copying the Container Id for a Docker Container
使用容器 id,通过以下命令启动一个交互式 shell。
sudo docker exec -it 9f74a82d4ea0 bash
交互外壳启动,如图 6-28 所示。
图 6-28。
Starting an Interactive Shell
连接到数据库
在交互式 tty 中,将用户改为“oracle”
su -l oracle
su oracle和su - oracle的区别在于,后者使用oracle用户的环境变量登录,并将当前目录设置为 oracle 主目录,而前者使用oracle登录,但环境变量和当前目录保持不变。
随后启动 SQL*Plus。使用/nolog选项不会建立与数据库的初始连接。
sqlplus /nolog
运行以下命令将SYS连接为SYSDBA。
CONNECT SYS AS SYSDBA
出现提示时,将密码指定为“oracle”。启动 SQL*Plus 和连接SYS的上述命令的输出如图 6-29 所示。建立了一个连接。
图 6-29。
Starting SQL*Plus
创建用户
要创建一个名为 OE 的用户,并向该用户授予CONNECT和RESOURCE角色,请运行以下命令。
CREATE USER OE QUOTA UNLIMITED ON SYSTEM IDENTIFIED BY OE;
GRANT CONNECT, RESOURCE TO OE;
用户OE被创建,角色被授予,如图 6-30 所示。
图 6-30。
Connecting as SYSDBA and creating a User
创建数据库表
用下面的 SQL 语句创建一个名为OE.Catalog的数据库表。
CREATE TABLE OE.Catalog(CatalogId INTEGER PRIMARY KEY,Journal VARCHAR2(25),Publisher VARCHAR2(25),Edition VARCHAR2(25),Title VARCHAR2(45),Author VARCHAR2(25));
向 OE 添加一行数据。包含以下 SQL 语句的目录表。
INSERT INTO OE.Catalog VALUES('1','Oracle Magazine','Oracle Publishing','November December 2013','Engineering as a Service','David A. Kelly');
创建OE.Catalog表并添加一行数据,如图 6-31 所示。
图 6-31。
Creating a Database Table
运行以下 SQL 语句来查询OE.CATALOG表。
SELECT * FROM OE.CATALOG;
添加的单行数据被列出,如图 6-32 所示。
图 6-32。
Querying the Database Table
退出交互式外壳
使用“退出”命令退出 SQL*Plus 命令,使用“退出”命令退出“oracle”用户,使用“退出”命令退出交互终端,也如图 6-33 所示。
图 6-33。
Exiting the Interactive Shell
摘要
在本章中,我们使用 Kubernetes 创建和编排了一个 Oracle 数据库集群。我们讨论了创建和管理集群的命令式和声明式方法。使用命令式方法,可以直接使用kubectl命令而无需定义文件来创建复制控制器和服务。对于 Pod 的声明性方法定义文件,必须使用复制控制器和服务。我们演示了如何扩展集群。我们还使用 Docker 容器登录到 SQL*Plus 并创建一个数据库表。在下一章中,我们将讨论在 Kubernetes 中使用 MongoDB。
七、使用 MongoDB 数据库
MongoDB 是一个灵活的模式模型 NoSQL 数据存储,最常用的 NoSQL 数据存储。MongoDB 基于 BSON(二进制 JSON)存储模型。文档存储在集合中。作为一个无模式的数据存储,就 BSON 文档中的字段而言,没有两个文档需要是相同的。在大规模集群中,可能会运行几个 MongoDB 实例,并且可能会出现几个问题。
- -MongoDB 实例调度
- -扩展 MongoDB 集群
- -负载均衡
- -提供 MongoDB 即服务
虽然 Docker 使提供容器即服务(CaaS)变得可行,但它本身并不提供前面列出的任何功能。在本章中,我们将讨论使用 Kubernetes 容器集群管理器来管理和编排运行 MongoDB 的 Docker 容器集群。本章包括以下几节。
- 设置环境
- 以声明方式创建 MongoDB 集群
- 强制创建 MongoDB 集群
设置环境
本章需要以下软件。
- -Docker 引擎(最新版本)
- -Kubernetes(1.01 版)
- -Kubernetes(1.01 版)
- MongoDB 的 Docker 映像(最新版本)
在运行 Ubuntu 14 的 Amazon EC2 实例上安装所需软件;与其他章节中使用的 AMI 相同。SSH 使用公共 IP 地址登录 Ubuntu 实例,对于不同的用户,这个地址是不同的。
ssh -i "docker.pem" ubuntu@52.91.190.195
Ubuntu 实例被登录,如图 7-1 所示。
图 7-1。
Logging into Ubuntu Instance on Amazon EC2
第一章讨论了安装程序。要验证 Docker 是否正在运行,请运行以下命令。
sudo service docker start
Docker 应被列为运行中,如图 7-2 所示。
图 7-2。
Starting Docker
使用以下命令列出 pod。
kubectl get pods
并使用以下命令列出节点。
kubectl get nodes
Kubernetes Pod 被列出,节点也被列出,如图 7-3 所示。
图 7-3。
Listing Kubernetes Pod and the single Node
要列出服务,请运行以下命令。
kubectl get services
“kubernetes”服务被列出,如图 7-4 所示。
图 7-4。
Listing the Kubernetes Service
以声明方式创建 MongoDB 集群
在下面的小节中,我们将为 MongoDB 集群创建一个 Kubernetes 服务和复制控制器。我们将扩展群集,并演示使用卷和主机端口等功能。我们将创建一个 MongoDB 集合,并在 Docker 容器 tty(交互式终端或 shell)中运行的 Mongo shell 中将文档添加到集合中。
创建服务
创建服务定义文件mongo-service-yaml。在定义文件中添加以下(表 7-1 )字段映射。
表 7-1。
Service Definition File mongo-service-yaml File Fields
| 田 | 价值 | 描述 | | --- | --- | --- | | apiVersion(堆叠版本) | 第五颅神经的眼支 | API 版本。 | | 种类 | 服务 | 将定义文件指定为服务。 | | 元数据 | | 服务元数据。 | | 元数据->标签 | 名称:mongo | | | 元数据->名称 | 蒙戈 | 标签映射。标签可以添加多次,不会产生错误,也没有额外的意义。 | | 投机 | | 服务规范。 | | 规格->端口 | | 公开服务的端口。 | | 规格->端口->端口 | Twenty-seven thousand and seventeen | 托管服务的端口。 | | 规格>连接埠>目标连接埠 | Twenty-seven thousand and seventeen | 传入端口映射到的端口。targetPort 字段是可选的,默认为与 Port 字段相同的值。如果服务要在不破坏客户端设置的情况下发展,targetPort 可能是有用的。例如,targetPort 可以设置为后端 Pod 的字符串端口名称,它保持不变。并且后端 Pod 暴露的实际端口号可以变化,而不会影响客户端的设置。 | | 选择器 | 名称:mongo | 用于选择窗格的服务选择器。标签表达式与选择器相同的窗格由服务管理。 |将下面的清单复制到mongo-service.yaml。
apiVersion: v1
kind: Service
metadata:
labels:
name: mongo
name: mongo
spec:
ports:
- port: 27017
targetPort: 27017
selector:
name: mongo
vi 编辑器可用于创建mongo-service.yaml文件,并使用:wq 命令保存,如图 7-5 所示。
图 7-5。
Service Definition File in vi Editor
默认服务类型是ClusterIp,它仅使用集群内部 IP。如图 7-6 所示,可以将类型设置为LoadBalancer,以便在集群中的每个节点上公开服务,并请求云提供商提供负载均衡器。
图 7-6。
Setting the Service Type
要从定义文件创建服务,请运行以下命令。
kubectl create -f mongo-service.yaml
使用以下命令列出服务。
kubectl get services
mongo服务列表如图 7-7 所示。
图 7-7。
Creating the Service from the Definition File
创建复制控制器
在本节中,我们将创建一个复制控制器。创建一个定义文件mongo-rc.yaml。将以下(表 7-2 )字段映射添加到定义文件中。
表 7-2。
Replication Controller Definition File Fields
| 田 | 价值 | 描述 | | --- | --- | --- | | apiVersion(堆叠版本) | 第五颅神经的眼支 | API 版本。 | | 种类 | 复制控制器 | 指定复制控制器的定义文件。 | | 元数据 | | 指定复制控制器的元数据。 | | 元数据->标签 | 名称:mongo | 复制控制器的标签映射。 | | 元数据->名称 | 蒙戈-rc | 复制控制器的名称。 | | 投机 | | 复制控制器规范。 | | 规格->副本 | Two | 始终要保留的副本数量。 | | 规格->模板 | | Pod 的模板。 | | 规格->模板->元数据 | | Pod 的元数据。 | | 规格->模板->元数据->标签 | | POD 标签。复制控制器和服务使用这些标签来选择要管理的 pod。复制控制器和服务中的选择器必须与用于管理 Pod 的复制控制器和服务的 Pod 标签相匹配。 | | 规格->模板->元数据->标签->名称 | 蒙戈 | 在 label 下方。 | | 规格->模板->规格 | | Pod 的规格。 | | 规格->模板->规格->容器 | | POD 里的容器。可以指定多个容器,但我们只配置了一个容器。 | | 规格->模板->规格->容器->映像 | 蒙戈 | “mongo”Docker 映像的容器。 | | 规格->模板->规格->容器->名称 | 蒙戈 | 容器名称。 | | 规格->模板->规格->容器->端口 | | 要预订的容器港口。 | | 规格->模板->规格->容器->端口->名称 | 蒙戈 | 端口名称。 | | 规格->模板->规格->容器->端口->容器端口 | Twenty-seven thousand and seventeen | 容器端口号。 |每个 Pod、服务和复制控制器都在单独的 YAML 映射文件中定义。mongo-rc.yaml已列出。
apiVersion: v1
kind: ReplicationController
metadata:
labels:
name: mongo
name: mongo-rc
spec:
replicas: 2
template:
metadata:
labels:
name: mongo
spec:
containers:
-
image: mongo
name: mongo
ports:
-
containerPort: 27017
name: mongo
mongo-rc.yaml文件可以在 vi 编辑器中编辑,用:wq 保存,如图 7-8 所示。
图 7-8。
Replication Controller Definition File
若要从定义文件创建复制控制器,请运行以下命令。
kubectl create -f mongo-rc.yaml
mongo-rc复制控制器被创建,如图 7-9 所示。
图 7-9。
Creating the Replication Controller
运行以下命令列出复制容器。
kubectl get rc
mongo-rc复制控制器列表如图 7-10 所示。
图 7-10。
Creating and isting Replication Controllers
创建卷
Kubernetes 支持卷。卷是 Pod 中的目录,Pod 中的容器可以访问该目录,这些容器为卷提供卷挂载。只要包含卷的 Pod 存在,卷就会一直存在。卷可用于以下目的。
- -跨容器崩溃保存数据。当装载卷的容器崩溃时,卷中的数据不会被删除,因为卷不在容器上,而是在 Pod 上。
- -卷中的数据可以由装载该卷的多个容器共享。
Pod 中的体积由“规格->体积”字段指定。一个容器装载一个带有spec.containers.volumeMounts字段的卷。支持几种类型的卷,其中一些在表 7-3 中讨论。
表 7-3。
Types of Volumes
| 卷类型 | 描述 | | --- | --- | | emptyDir 先生 | Pod 中的空目录,可用于保存一个或多个容器使用的一些文件。空目录也可以用于检查点。 | | 主机路径 | 将目录从主机节点装载到 Pod 中。 | | gcePersistentDisk | 将一个谷歌计算引擎永久磁盘安装到 Pod 中。 | | awsElasticBlockStore | 将 Amazon Web Services EBS 卷装入 Pod。 | | 吉卜赛人 | 将 git repo 装载到 pod 中。 | | 弗勒加 | 将 Flocker 数据集装载到 pod 中。 | | 网络文件系统 | 将网络文件系统装入 Pod。 |接下来,我们将把类型为emptyDir的卷添加到复制控制器定义文件mongo-rc.yaml中。一种改良版的mongo-rc.yaml上市了。
apiVersion: v1
kind: ReplicationController
metadata:
labels:
name: mongo
name: mongo-rc
spec:
replicas: 2
template:
metadata:
labels:
name: mongo
spec:
containers:
-
image: mongo
name: mongo
ports:
-
containerPort: 27017
name: mongo
volumeMounts:
-
mountPath: /mongo/data/db
name: mongo-storage
volumes:
-
emptyDir: {}
name: mongo-storage
前面的定义文件包括类型为emptyDir的名为mongo-storage的卷的以下卷配置。
volumes:
-
emptyDir: {}
name: mongo-storage
该卷存在于 Pod 中,Pod 中的单个容器可以使用字段spec->containers->volumeMounts装载该卷。修改后的mongo-rc.yaml包括以下用于mongo容器的卷挂载。
volumeMounts:
-
mountPath: /mongo/data/db
name: mongo-storage
前面的配置在容器中的挂载路径或目录路径/mongo/data/db为mongo-storage卷添加了一个卷挂载。在容器内,可以在/mongo/data/db访问卷。例如,在一个交互终端中为一个容器把目录(cd)改为/mongo/data/db目录。
cd /mongo/data/db
列出/mongo/data/db目录中的文件和目录。
ls -l
该目录是空的,因为它最初应该如图 7-11 所示。
图 7-11。
Empty Directory
不要将该卷与 MongoDB 服务器的数据目录混淆。默认情况下,数据目录在/data/db创建,并在运行 MongoDB 服务器实例的每个 Docker 容器中创建。/mongo/data/db是所有 Docker 容器共有的,而/data/db存在于每个 Docker 容器中。
列出日志
启动复制控制器后,使用以下命令列出 pod。
kubectl get pods
如图 7-12 所示,两个吊舱被列出。
图 7-12。
Listing the Pods
可以使用以下命令列出 Pod 的日志,例如,mongo-rc-4t43s Pod。
kubectl logs mongo-rc-4t43s
Pod 日志显示 MongoDB 服务器启动,如图 7-13 所示。
图 7-13。
Listing the Pod Logs
当 MongoDB 服务器启动时,输出消息“等待端口 27017 上的连接”,如图 7-14 所示。
图 7-14。
MongoDB Running on Port 27017
启动 Docker 容器的交互式外壳
在这一节中,我们将为 MongoDB 服务器启动一个交互式终端或 bash shell,为此我们需要运行 MongoDB 服务器的 Docker 容器的容器 id。列出 Docker 容器。
sudo docker ps
复制映像为“mongo”的容器的容器 id,如图 7-15 所示。
图 7-15。
Copying Docker Container ID
因为“mongo”Docker 映像基于 FROM 指令中指定的“debian”Docker 映像,所以我们能够启动一个 bash shell 来与基于“mongo”映像的 Docker 容器中运行的 MongoDB 服务器进行交互。使用以下命令启动交互式 bash shell。
sudo docker exec -it 00c829e0a89d bash
如图 7-16 所示,启动一个交互式外壳。
图 7-16。
Starting an Interactive Shell
启动 Mongo Shell
用下面的命令启动 Mongo shell。
mongo
Mongo shell 启动如图 7-17 所示。
图 7-17。
Mongo Shell
创建数据库
在 Mongo shell 中使用以下命令列出数据库。
show dbs
当使用或设置数据库时,数据库被隐式地创建。比如设置数据库使用为mongodb,没有和show dbs一起列出,还不存在。
use mongodb
但是,将数据库设置为用作mongodb并不会创建数据库mongodb,直到数据库被使用。运行以下命令列出数据库。
show dbs
mongodb数据库没有被列出,如图 7-19 所示。要创建mongodb数据库,调用数据库上的一些操作,比如用下面的命令创建一个名为catalog的集合。
db.createCollection("catalog")
随后再次列出数据库。
show dbs
mongodb数据库被列出,如图 7-18 所示。要列出集合,请运行以下命令。
图 7-18。
Creating and Listing a MongoDB Database
show collections
catalog系列上市。
创建收藏
在上一节中,catalog集合是使用db.createCollection方法创建的。再举一个例子,使用下面的命令创建一个名为catalog_capped的封顶集合:封顶集合是一个固定大小的集合,支持基于插入顺序添加和获取文档的高吞吐量操作。
db.createCollection("catalog_capped", {capped: true, autoIndexId: true, size: 64 * 1024, max: 1000} )
如图 7-19 所示,添加一个加盖的集合。最初,集合是空的。使用以下命令获取catalog集合中的文档。
图 7-19。
Creating a Capped Collection
db.catalog.count()
文档数被列为 0,因为我们尚未添加任何文档。
添加文档
在本节中,我们将向目录集合中添加文档。为要添加的文档指定 JSON。存储在 MongoDB 中的每个文档都需要_id字段。可以像在doc2文档中一样明确地添加_id字段。如果文件 JSON 中没有提供,则自动生成_id。
doc1 = {"catalogId" : "catalog1", "journal" : 'Oracle Magazine', "publisher" : 'Oracle Publishing', "edition" : 'November December 2013',"title" : 'Engineering as a Service',"author" : 'David A. Kelly'}
doc2 = {"_id": ObjectId("507f191e810c19729de860ea"), "catalogId" : "catalog1", "journal" : 'Oracle Magazine', "publisher" : 'Oracle Publishing', "edition" : 'November December 2013',"title" : 'Engineering as a Service',"author" : 'David A. Kelly'};
doc1 和 doc2 如图 7-20 所示。
图 7-20。
Documents doc1 and doc2
要将文档添加到catalog集合,请运行以下命令。
db.catalog.insert([doc1, doc2], { writeConcern: { w: "majority", wtimeout: 5000 }, ordered:true })
如图 7-21 中 JSON 结果的nInserted字段所示,文件被添加。
图 7-21。
Adding Documents
查找文档
要查询目录,调用find()方法。要列出catalog集合中的所有文档,运行以下命令。
db.catalog.find()
添加的两个文件列表如图 7-22 所示。对于其中一个文档,会自动生成_id字段。
图 7-22。
Finding Documents
查找单个文档
要从catalog集合中找到一个文档,运行下面的命令来调用findOne()方法。
db.catalog.findOne()
单个文档被列出,如图 7-23 所示。
图 7-23。
Finding a Single Document
在单个文档中查找特定字段
例如,要仅从单个文档中获取特定字段edition, title和author,请运行以下命令。
db.catalog.findOne(
{ },
{ edition: 1, title: 1, author: 1 }
)
只列出单个文档中的特定字段,如图 7-24 所示。_id字段总是被列出。
图 7-24。
Finding Selected Fields in a Document
删除收藏
要删除catalog集合,请运行以下命令。
db.catalog.drop()
随后使用以下命令列出集合。
show collections
catalog集合没有被列出,只有catalog_capped集合被列出,如图 7-25 所示。
图 7-25。
Dropping the catalog Collection
退出 Mongo Shell 和交互式 Shell
要退出 Mongo shell,运行以下命令。
exit
要退出交互式终端,请运行以下命令。
exit
Mongo shell 和交互终端退出,如图 7-26 所示。
图 7-26。
Exiting the Shells
扩展集群
要扩展 Mongo 集群,运行kubectl scale命令。例如,以下命令将群集扩展到 4 个复制副本。
kubectl scale rc mongo --replicas=4
如图 7-27 所示的“缩放”输出将集群缩放至 4 个副本。
图 7-27。
Scaling a Replication Controller
缩放后列出窗格。
kubectl get pods
四个 POD 被列出。最初,一些容器可能被列为未就绪(1/1)状态。多次运行上述命令,列出所有正在运行并准备就绪的吊舱,如图 7-28 所示。
图 7-28。
Listing the Pods after Scaling
删除复制控制器
要删除复制控制器mongo-rc,请运行以下命令。
kubectl delete replicationcontroller mongo-rc
由复制控制器管理的所有 pod 也会被删除。随后运行以下命令来列出窗格。
kubectl get pods
mongo吊舱不会如图 7-29 所示列出。
图 7-29。
Deleting a Replication Controller
删除服务
要删除名为mongo的服务,运行以下命令。
kubectl delete service mongo
mongo服务未列出,如图 7-30 所示。
图 7-30。
Deleting the mongo Service
使用主机端口
Pod 中的容器规范有配置主机端口的规定。主机端口是映射到主机的容器端口,意味着指定的主机端口被保留给单个容器。hostPort字段应该用于单个机器容器。指定了hostPort的类型的多个容器无法启动,因为主机端口只能由一个容器保留。然而,其他没有指定hostPort字段的 pod 可以在运行具有hostPort字段映射的容器的同一台机器上运行。作为我们之前使用的复制控制器的变体,在 spec- > containers- > ports 字段中添加了一个hostPort字段。修改后的mongo-rc.yaml被列出。
---
apiVersion: v1
kind: ReplicationController
metadata:
labels:
name: mongo
name: mongo-rc
spec:
replicas: 2
template:
metadata:
labels:
name: mongo
spec:
containers:
-
image: mongo
name: mongo
ports:
-
containerPort: 27017
hostPort: 27017
name: mongo
运行以下命令创建复制控制器。
kubectl create -f mongo-rc.yaml
使用以下命令列出复制控制器。
kubectl get rc
mongo-rc复制控制器被创建并列出,如图 7-31 所示。
图 7-31。
Creating a Replication Controller from a Definition File
使用以下命令列出 pod。
kubectl get pods
两个复制副本中只有一个列为正在运行和就绪(1/1)。即使前面的命令运行多次,也只有一个副本被列为正在运行,如图 7-32 所示。
图 7-32。
Listing the Pods after creating a Replication Controller
使用以下命令将 MongoDB 集群扩展到 4 个副本。
kubectl scale rc mongo --replicas=4
尽管该命令的输出被“缩放”并创建了 4 个 Pod,但在任何特定时间只有一个 Pod 处于就绪(1/1)状态,如图 7-33 所示。
图 7-33。
Scaling the Replication Controller to 4 Replicas
即使单个运行的 Pod 停止,也只有一个新的 Pod 启动。要进行演示,请停止单个运行的 Pod。
kubectl stop pod mongo-rc-laqpl
该单元被移除,但会创建一个替换单元来保持复制级别 1,如图 7-34 所示。
图 7-34。
Another Pod gets created when the single running Pod is stopped
几秒钟后再次列出 Pod,只有一个 Pod 被列出,如图 7-35 所示。
图 7-35。
Only a single Pod is Running and Ready
不建议使用hostPort字段,除非使用单个容器机器或者只需要将单个容器映射到主机端口。
强制创建 MongoDB 集群
在接下来的小节中,我们将在命令行上使用 kubectl 为 MongoDB 集群创建一个 Kubernetes 复制控制器和服务。
创建复制控制器
要为具有 2 个副本和端口 27017 的 Docker 映像“mongo”创建复制控制器,请运行以下命令。
kubectl run mongo --image=mongo --replicas=2 --port=27017
复制控制器的创建如图 7-36 所示。
图 7-36。
Creating a Replication Controller Imperatively
使用以下命令列出 pod。
kubectl get rc
mongo -rc 列表如图 7-37 所示。
图 7-37。
Listing the Replication Controllers
列出 POD
使用以下命令列出 pod。
kubectl get pods
为 MongoDB get 启动的两个 Pods 列表如图 7-38 所示。最初,pod 可能会被列为未运行。
图 7-38。
Listing the Pods with some of the pods not Running yet
如图 7-39 所示,如果需要将 pod 列为正在运行,请多次运行以下程序。
图 7-39。
Listing all the Pods as Running
列出日志
使用以下命令列出 Pod 的日志。mongo-56850是 Pod 名称。
kubectl logs mongo-56850
Pod 日志列表如图 7-40 所示。
图 7-40。
Listing Pod Logs
MongoDB 被列为已启动,如图 7-41 所示。在服务器上运行的命令也会得到输出。
图 7-41。
Listing MongoDB Server as running and waiting for connections on port 27017
创建服务
要为mongo复制控制器创建一个服务,运行下面的命令在端口 27017 上公开一个类型为LoadBalancer的服务,这在前面已经讨论过了。
kubectl expose rc mongo --port=27017 --type=LoadBalancer
mongo服务被创建,如图 7-42 所示。
图 7-42。
Creating a Service Imperatively
使用以下命令列出服务。
kubectl get services
在图 7-43 中mongo服务被列为正在运行。
图 7-43。
Listing the Services including the mongo Service
交互式终端和 Mongo shell 可以开始创建 MongoDB 数据库和集合,以便在集合中添加和查询文档,正如在以声明方式创建 MongoDB 集群时所讨论的那样。
扩展集群
例如,要将群集扩展到 4 个副本,请运行以下命令。
kubectl scale rc mongo --replicas=4
输出“scaled”表示集群已被缩放,如图 7-44 所示。
图 7-44。
Scaling the Cluster created Imperatively
随后得到 POD。
kubectl get pods
列出四个吊舱,如图 7-45 所示。最初,一些 pod 可能显示为未运行或就绪。
图 7-45。
Listing Pods after Scaling
要描述mongo服务,请运行以下命令。
kubectl describe svc mongo
除了服务端点之外,服务描述还包括服务标签、选择器,如图 7-46 所示,四个 pod 各有一个。
图 7-46。
Describing the Service mongo after Scaling
删除服务和复制控制器
可以使用以下命令删除mongo服务和mongo复制控制器。
kubectl delete service mongo
kubectl delete rc mongo
“mongo”服务和“mongo”复制控制器被删除,如图 7-47 所示。删除一个不会删除另一个;复制控制器与服务的分离是一个适合于发展一个而不必修改另一个的特性。
图 7-47。
Deleting the Service and the Replication Controller
摘要
在本章中,我们使用 Kubernetes 集群管理器来创建和编排一个 MongoDB 集群。我们强制性地和声明性地创建了一个复制控制器和一个服务。我们还演示了如何扩展集群。我们介绍了 Kubernetes 复制控制器的另外两个特性:卷和主机端口。这一章是关于在 MongoDB 中使用 Kubernetes 的,重点不是在 MongoDB 上;但如果要更详细地探究 MongoDB,请参考 Apress 的书 Pro MongoDB Development(http://www.apress.com/9781484215999?gtmf=s)。在下一章,我们将讨论另一个 NoSQL 数据库,Apache Cassandra。