如何在CoreOS集群上安装和配置Kubernetes

来自菜鸟教程
跳转至:导航、​搜索

状态: 过期

这篇文章不再是最新的。 如果您有兴趣为本文编写更新,请参阅DigitalOcean 想要发布您的技术教程

原因: 2016年12月22日,CoreOS宣布不再维护fleet。 CoreOS 建议使用 Kubernetes 来满足所有集群需求。

请参阅: 有关在没有队列的情况下在 CoreOS 上使用 Kubernetes 的指导,请参阅 CoreOS 上的 Kubernetes 文档


介绍

Kubernetes 是一个系统,旨在跨集群环境管理在 Docker 容器中构建的应用程序。 它处理容器化应用程序的整个生命周期,包括部署和扩展。

在本指南中,我们将演示如何在 CoreOS 集群上开始使用 Kubernetes。 该系统将允许我们将相关服务组合在一起,以便使用 Kubernetes 所谓的“pod”作为一个单元部署在单个主机上。 它还提供健康检查功能、高可用性和资源的有效使用。

本教程使用 Kubernetes v0.7.0 进行了测试。 请记住,此软件经常更改。 要查看您的版本,请在安装后运行:

kubecfg -version

先决条件和目标

我们将从之前的 CoreOS 指南中使用的相同基本 CoreOS 集群开始。 要启动并运行这三个成员集群,请遵循我们的 CoreOS 集群指南

这将为您提供三个要配置的服务器。 虽然每个节点在 CoreOS 级别本质上是可互换的,但在 Kubernetes 中,我们需要分配更专业的角色。 我们需要一个节点作为主节点,这将运行一些额外的服务,例如 API 服务器和控制器管理器。

对于本指南,我们将使用以下详细信息:

主机名 公共 IPv4 私有 IPv4 角色
coreos-1 192.168.2.1 10.120.0.1 掌握
coreos-2 192.168.2.2 10.120.0.2 小黄人1
coreos-3 192.168.2.3 10.120.0.3 小黄人2

在我们将遵循的配置中,master 也将是一个功能齐全的 minion 服务器,能够完成工作。 此配置的想法取自 Brian Ketelson 的关于在 CoreOS 上设置 Kubernetes 的指南。

如果您按照上述指南创建集群,则 etcdfleet 都应配置为使用每个服务器的私有 IPv4 进行通信。 公共 IP 地址可用于从本地计算机进行连接。

本指南将采用这个基本的 CoreOS 集群并在其上安装许多服务。

首先,我们将配置 flannel,这是一个网络结构层,它为每台机器提供一个单独的子网用于容器通信。 这是一个相对较新的 CoreOS 项目,很大程度上是为了适应 Kubernetes 关于网络环境的假设。

我们将配置 Docker 以使用此网络层进行部署。 在此之上,我们将设置 Kubernetes。 这涉及到许多部分。 我们需要配置一个代理服务、一个 API 层和一个名为 Kubelet 的节点级“pod”管理系统。

创建 Flannel 网络结构层

我们需要做的第一件事是配置 flannel 服务。 这是为集群中的每台机器提供单独子网的组件。 Docker 将被配置为使用它进行部署。 由于这是基本要求,因此这是一个很好的起点。

在撰写本文时,该项目没有提供 flannel 的预构建二进制文件。 由于这个事实,我们必须自己构建二进制文件并安装它。 为了节省构建时间,我们将在一台机器上构建它,然后将可执行文件传输到我们的其他节点。

像 CoreOS 的许多部分一样,Flannel 是用 Go 编程语言构建的。 我们将使用为此目的预先构建的容器,而不是设置一个完整的 Go 环境来构建包。 Google 专门为这些类型的情况维护了一个 Go 容器。

我们将安装的所有应用程序都将放置在 /opt/bin 目录中,该目录不会在 CoreOS 中自动创建。 现在创建目录:

sudo mkdir -p /opt/bin

现在我们可以使用 Go 容器构建项目。 只需运行这个 Docker 命令从 Docker Hub 拉取镜像,运行容器,然后在容器中下载和构建包:

docker run -i -t google/golang /bin/bash -c "go get github.com/coreos/flannel"

操作完成后,我们可以将编译好的二进制文件复制出容器。 首先,我们需要知道容器 ID:

docker ps -l -q

结果将是如下所示的 ID:

004e7a7e4b70

我们可以使用此 ID 指定复制操作到 /opt/bin 目录。 二进制文件已放置在容器内的 /gopath/bin/flannel 处。 由于我们的 core 用户无法写入 /opt/bin 目录,因此我们必须使用 sudo

sudo docker cp 004e7a7e4b70:/gopath/bin/flannel /opt/bin/

现在我们的第一台机器上可以使用法兰绒。 稍后,我们将把它复制到我们的其他机器上。

构建 Kubernetes 二进制文件

Kubernetes 由很多不同的应用程序和分层技术组成。 目前,该项目不包含我们需要的各种组件的预构建二进制文件。 我们将自己建造它们。

我们只会在我们服务器的 一个 上完成此过程。 由于我们的服务器本质上是统一的,我们可以通过简单地传输我们将生成的二进制文件来避免不必要的构建时间。

第一步是从其 GitHub 存储库中克隆项目。 我们将它克隆到我们的主目录中:

cd ~
git clone https://github.com/GoogleCloudPlatform/kubernetes.git

接下来,我们将进入存储库中的构建目录。 从这里,我们可以使用包含的脚本构建二进制文件:

cd kubernetes/build
./release.sh

这个过程将需要相当长的时间。 它将启动一个 Docker 容器来构建必要的二进制包。

构建过程完成后,您将能够在 ~/kubernetes/_output/dockerized/bin/linux/amd64 目录中找到二进制文件:

cd ~/kubernetes/_output/dockerized/bin/linux/amd64
ls
e2e          kube-apiserver           kube-proxy      kubecfg  kubelet
integration  kube-controller-manager  kube-scheduler  kubectl  kubernetes

我们将这些转移到我们之前创建的 /opt/bin 目录:

sudo cp * /opt/bin

我们的第一台机器现在拥有我们项目所需的所有二进制文件。 我们现在可以专注于在我们的其他服务器上获取这些应用程序。

将可执行文件传输到您的其他服务器

我们的第一台机器拥有启动 Kubernetes 集群所需的所有组件。 我们需要将这些复制到我们的其他机器上,但在此之前它将起作用。

由于 Kubernetes 不是统一安装(有一个 master 和多个 minions),每个主机不需要所有的二进制文件。 每个 minion 服务器只需要 scheduler、docker、proxy、kubelet 和 flannel 可执行文件。

但是,传输所有可执行文件为我们提供了更大的灵活性。 它也更容易。 我们将转移本指南中的所有内容。

当您连接到您的第一台机器时,您应该已经通过使用 -A 标志(在启动代理并添加您的密钥之后)连接来转发您的 SSH 代理信息。 这是重要的一步。 如果您之前没有通过此标志,请断开并重新连接。

在连接 [X157X ]。

首先进入我们放置二进制文件的目录:

cd /opt/bin

现在,我们可以将此目录中的文件复制到我们的其他主机。 我们将通过将可执行文件直接压缩到 shell 的标准输出来做到这一点。 然后,我们将把它通过管道传输到我们的 SSH 命令中,我们将在其中连接到我们的其他主机之一。

我们将使用的 SSH 命令将在我们的另一台主机上创建 /opt/bin 目录,切换到该目录,然后解压缩它通过 SSH 隧道接收到的信息。 整个命令如下所示:

tar -czf - . | ssh core@192.168.2.2 "sudo mkdir -p /opt/bin; cd /opt/bin; sudo tar xzvf -"

这会将所有可执行文件传输到您指定的 IP 地址。 使用您的第三台主机再次运行该命令:

tar -czf - . | ssh core@192.168.2.3 "sudo mkdir -p /opt/bin; cd /opt/bin; sudo tar xzvf -"

现在,您的三台机器上的所有可执行文件都已就位。

设置主特定服务

下一步是设置我们的 systemd 单元文件以正确配置和启动我们的新应用程序。 我们将从处理仅在我们的主服务器上运行的应用程序开始。

我们将把这些文件放在 /etc/systemd/system 目录中。 现在搬到那里:

cd /etc/systemd/system

现在我们可以开始构建我们的服务文件了。 我们将仅在 master 上创建两个文件,在 minions 上创建五个文件。 所有这些文件都将在 /etc/systemd/system/*.service 中。

主文件:

  • apiserver.service
  • controller-manager.service

所有服务器的 Minion 文件:

  • scheduler.service
  • flannel.service
  • docker.service
  • proxy.service
  • kubelet.service

创建 API 服务器单元文件

我们将配置的第一个文件是 API 服务器的单元文件。 API 服务器用于提供有关集群的信息、处理发布请求以更改信息、安排每个服务器上的工作以及同步共享信息。

为简单起见,我们将调用此单元文件 apiserver.service。 现在创建并打开该文件:

sudo vim apiserver.service

在这个文件中,我们将从关于我们服务的基本元数据开始。 我们需要确保在 etcd 和 Docker 服务启动并运行之前不会启动此单元:

[Unit]
Description=Kubernetes API Server
After=etcd.service
After=docker.service
Wants=etcd.service
Wants=docker.service

接下来,我们将完成 [Service] 部分。 这将主要用于使用一些描述我们环境的参数来启动 API 服务器。 我们还将设置重启条件:

[Unit]
Description=Kubernetes API Server
After=etcd.service
After=docker.service
Wants=etcd.service
Wants=docker.service

[Service]
ExecStart=/opt/bin/kube-apiserver \
-address=127.0.0.1 \
-port=8080 \
-etcd_servers=http://127.0.0.1:4001 \
-portal_net=10.100.0.0/16 \
-logtostderr=true
ExecStartPost=-/bin/bash -c "until /usr/bin/curl http://127.0.0.1:8080; do echo \"waiting for API server to come online...\"; sleep 3; done"
Restart=on-failure
RestartSec=5

上面的部分建立了服务器将运行的网络地址和端口,以及 etcd 正在侦听的位置。 portal_net 参数给出了 flannel 服务将使用的网络范围。

启动服务后,我们检查它是否已启动并循环运行。 这确保了服务实际上能够在依赖服务启动之前接受连接。 没有这个可能会导致需要手动重新启动的依赖服务中的错误。

最后,我们将不得不安装这个单元。 我们可以使用 [Install] 部分来做到这一点,它会告诉我们的主机在机器完全启动时启动此服务:

[Unit]
Description=Kubernetes API Server
After=etcd.service
After=docker.service
Wants=etcd.service
Wants=docker.service

[Service]
ExecStart=/opt/bin/kube-apiserver \
-address=127.0.0.1 \
-port=8080 \
-etcd_servers=http://127.0.0.1:4001 \
-portal_net=10.100.0.0/16 \
-logtostderr=true
ExecStartPost=-/bin/bash -c "until /usr/bin/curl http://127.0.0.1:8080; do echo \"waiting for API server to come online...\"; sleep 3; done"
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

完成后,关闭文件。

创建控制器管理器单元文件

Kubernetes 需要的下一个部件是 Controller Manager 服务器。 该组件用于在集群单元之间执行数据复制。

在同一目录中打开一个名为 controller-manager.service 的文件:

sudo vim controller-manager.service

我们将再次从基本元数据开始。 这将遵循与上一个文件相同的格式。 除了其他依赖之外,这个服务必须在我们刚刚配置的 API server 单元之后启动:

[Unit]
Description=Kubernetes Controller Manager
After=etcd.service
After=docker.service
After=apiserver.service
Wants=etcd.service
Wants=docker.service
Wants=apiserver.service

对于该文件的 [Service] 部分,我们只需将一些参数传递给可执行文件。 主要是,我们将应用程序指向我们的 API 服务器的位置。 在这里,我们传入了每台机器的私有 IP 地址,用逗号分隔。 修改这些值以反映您自己的配置。 同样,我们将确保该单元在失败时重新启动,因为我们的 Kubernetes 集群需要它才能正常运行:

[Unit]
Description=Kubernetes Controller Manager
After=etcd.service
After=docker.service
After=apiserver.service
Wants=etcd.service
Wants=docker.service
Wants=apiserver.service

[Service]
ExecStart=/opt/bin/kube-controller-manager \
-master=http://127.0.0.1:8080 \
-machines=10.120.0.1,10.120.0.2,10.120.0.3
Restart=on-failure
RestartSec=5

我们还将使用相同的安装说明,以便该单元也可以在启动时启动:

[Unit]
Description=Kubernetes Controller Manager
After=etcd.service
After=docker.service
After=apiserver.service
Wants=etcd.service
Wants=docker.service
Wants=apiserver.service

[Service]
ExecStart=/opt/bin/kube-controller-manager \
-master=http://127.0.0.1:8080 \
-machines=10.120.0.1,10.120.0.2,10.120.0.3
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

完成后保存并关闭文件。

设置集群服务

现在我们已经配置了特定于主服务器的服务,我们可以配置需要存在于我们机器的 all 上的单元文件。 这意味着您应该将这些文件添加到主服务器和从属服务器并相应地配置它们。

这五个文件应该在所有机器上创建,在 /etc/systemd/system/*.service 中。

  • scheduler.service
  • flannel.service
  • docker.service
  • proxy.service
  • kubelet.service

创建调度程序单元文件

下一个组件是调度程序。 调度程序决定在哪个 minion 上运行工作负载并进行通信以确保发生这种情况。

现在为此单元创建并打开一个文件:

sudo vim scheduler.service

这个单元的开始方式与上一个单元大致相同。 它依赖于所有相同的服务:

[Unit]
Description=Kubernetes Scheduler
After=etcd.service
After=docker.service
After=apiserver.service
Wants=etcd.service
Wants=docker.service
Wants=apiserver.service

服务部分本身非常简单。 我们只需要将可执行文件指向 API 服务器所在的网络地址和端口。 同样,我们将在出现故障时重新启动服务。

安装部分反映了我们迄今为止看到的其他部分:

[Unit]
Description=Kubernetes Scheduler
After=etcd.service
After=docker.service
After=apiserver.service
Wants=etcd.service
Wants=docker.service
Wants=apiserver.service

[Service]
ExecStart=/opt/bin/kube-scheduler -master=127.0.0.1:8080
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

完成后,保存并关闭文件。

创建法兰绒单元文件

我们需要启动和运行的下一个组件是 flannel,我们的网络结构层。 这将用于为每个节点提供其自己的 Docker 容器子网。

同样,在您的每台机器上,切换到 systemd 配置目录:

cd /etc/systemd/system

在文本编辑器中创建并打开 flannel 单元文件:

sudo vim flannel.service

在这个文件中,我们将从元数据信息开始。 由于这个服务需要etcd注册子网信息,所以我们需要在etcd之后启动这个:

[Unit]
Description=Flannel network fabric for CoreOS
Requires=etcd.service
After=etcd.service

对于 [Service] 部分,我们首先要获取 /etc/environment 文件,以便我们可以访问主机的私有 IP 地址。

下一步将放置一个 ExecStartPre= 行,该行尝试使用 etcd 注册子网范围。 它将不断尝试向 etcd 注册,直到成功。 我们将在本指南中使用 10.100.0.0/16 范围。

然后,我们将使用从环境文件中获取的私有 IP 地址启动 flannel

之后,我们要检查 flannel 是否已将其信息写入其文件(以便 Docker 稍后可以读取),如果没有则休眠。 这确保了 Docker 服务在文件可用之前不会尝试读取文件(这可能发生在第一台上线的服务器上)。 我们将使用常用参数配置重启并再次使用 multi-user.target 安装单元:

[Unit]
Description=Flannel network fabric for CoreOS
Requires=etcd.service
After=etcd.service

[Service]
EnvironmentFile=/etc/environment
ExecStartPre=-/bin/bash -c "until /usr/bin/etcdctl set /coreos.com/network/config '{\"Network\": \"10.100.0.0/16\"}'; do echo \"waiting for etcd to become available...\"; sleep 5; done"
ExecStart=/opt/bin/flannel -iface=${COREOS_PRIVATE_IPV4}
ExecStartPost=-/bin/bash -c "until [ -e /run/flannel/subnet.env ]; do echo \"waiting for write.\"; sleep 3; done"
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

完成后保存并关闭文件。 在其他主机上创建相同的文件。

创建 Docker 单元文件

我们将创建的下一个文件实际上与 /opt/bin 目录中的可执行文件无关。 我们需要创建一个 Docker 服务文件,以便在了解我们刚刚配置的 flannel 网络覆盖的情况下启动该服务。

使用文本编辑器创建适当的单元文件:

sudo vim docker.service

从通常的元数据开始。 我们需要在 flannel 服务配置并联机后启动它:

[Unit]
Description=Docker container engine configured to run with flannel
Requires=flannel.service
After=flannel.service

对于 [Service] 部分,我们需要获取 flannel 用于存储它正在创建的环境变量的文件。 这将具有当前主机的子网信息。

然后,如果当前 docker0 桥接接口正在运行,我们将其关闭并将其删除。 这使我们能够以全新的方式重新启动 Docker。 该过程将使用 flannel 网络信息配置 docker0 接口。

我们使用与其他单位相同的重启和 [Install] 详细信息:

[Unit]
Description=Docker container engine configured to run with flannel
Requires=flannel.service
After=flannel.service

[Service]
EnvironmentFile=/run/flannel/subnet.env
ExecStartPre=-/usr/bin/ip link set dev docker0 down
ExecStartPre=-/usr/sbin/brctl delbr docker0
ExecStart=/usr/bin/docker -d -s=btrfs -H fd:// --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU}
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

完成后保存并关闭文件。 在每个主机上创建相同的文件。

创建代理单元文件

下一个要讨论的逻辑单元是每个集群成员运行的代理服务器。 Kubernetes 代理服务器用于路由和转发进出容器的流量。

使用文本编辑器打开代理单元文件:

sudo vim proxy.service

对于元数据部分,我们需要定义对 etcd 和 Docker 的依赖。 对于 [Service] 部分,我们只需要使用本地 etcd 服务器的地址启动可执行文件。 重启配置和安装细节将镜像我们之前的服务文件:

[Unit]
Description=Kubernetes proxy server
After=etcd.service
After=docker.service
Wants=etcd.service
Wants=docker.service

[Service]
ExecStart=/opt/bin/kube-proxy -etcd_servers=http://127.0.0.1:4001 -logtostderr=true
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

完成后保存文件。 在每个主机上创建相同的文件。

创建 Kubelet 单元文件

现在,我们将创建 Kubelet 单元文件。 该组件用于管理容器部署。 它确保容器处于它们应该处于的状态,并监视系统以了解所需部署状态的变化。

在文本编辑器中创建并打开文件:

sudo vim kubelet.service

元数据部分将包含关于 etcd 和 Docker 的相同依赖信息:

[Unit]
Description=Kubernetes Kubelet
After=etcd.service
After=docker.service
Wants=etcd.service
Wants=docker.service

对于 [Service] 部分,我们必须再次获取 /etc/environment 文件才能访问主机的私有 IP 地址。 然后我们将调用 kubelet 可执行文件,设置其地址和端口。 我们还覆盖主机名以使用相同的私有 IP 地址并将服务指向本地 etcd 实例。 我们提供了与我们一直在使用的相同的重新启动和安装详细信息:

[Unit]
Description=Kubernetes Kubelet
After=etcd.service
After=docker.service
Wants=etcd.service
Wants=docker.service

[Service]
EnvironmentFile=/etc/environment
ExecStart=/opt/bin/kubelet \
-address=${COREOS_PRIVATE_IPV4} \
-port=10250 \
-hostname_override=${COREOS_PRIVATE_IPV4} \
-etcd_servers=http://127.0.0.1:4001 \
-logtostderr=true
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

完成后保存并关闭文件。

启用服务

现在您已经启动了所有服务文件,您可以启用这些单元。 这样做会处理每个单元的 [Install] 部分中的信息。

由于我们的单位说他们是多用户目标想要的,这意味着当系统试图使服务器进入多用户模式时,我们所有的服务都会自动启动。

为此,请转到您的 /etc/systemd/system 目录:

cd /etc/systemd/system

从这里,我们可以启用所有脚本:

sudo systemctl enable *

这将创建一个 multi-user.target.wants 目录,其中包含指向我们的单元文件的符号链接。 该目录将在引导过程结束时由 systemd 处理。

在每台服务器上重复此步骤。

现在我们启用了服务,我们可以依次重新启动服务器。

我们将从主服务器开始,但您可以按任何顺序进行。 虽然不需要重新启动来启动这些服务,但这样做可以确保我们的单元文件以允许无缝依赖链的方式编写:

sudo reboot

一旦 master 重新上线,您可以重新启动您的 minion 服务器:

sudo reboot

一旦您的所有服务器都在线,请确保您的服务正确启动。 您可以通过键入以下内容进行检查:

systemctl status service_name

或者您可以通过键入以下内容来查看日志:

journalctl -b -u service_name

寻找服务正常运行的迹象。 如果有任何问题,重新启动特定服务可能会有所帮助:

sudo systemctl restart service_name

完成后,您应该能够从主服务器查看您的机器。 登录到您的主服务器后,通过键入以下内容检查所有服务器是否可用:

kubecfg list minions
Minion identifier
----------
10.200.0.1
10.200.0.2
10.200.0.3

在以后的指南中,我们将讨论如何使用 Kubernetes 来调度和控制您的 CoreOS 集群上的服务。

结论

您现在应该在您的 CoreOS 集群中设置了 Kubernetes。 这为您提供了一个出色的管理和调度界面,用于处理逻辑分组中的服务。

您可能注意到上述步骤导致了一个非常手动的过程。 其中很大一部分是因为我们在机器上构建了二进制文件。 如果您要将二进制文件托管在您的专用网络中可访问的 Web 服务器上,您可以下载二进制文件并通过制作特殊的云配置文件来自动配置它们。

Cloud-config 文件足够灵活,您可以在不进行任何修改的情况下注入大部分单元文件(apiserver.service 文件除外,它需要访问每个节点的 IP)并将它们作为 CoreOS 启动节点已启动。 这超出了本指南的范围,但在自动化过程方面是一个很好的下一步。