本教程将指导您如何设置 Kubernetes 集群,从零开始使用 Ansible 和 Kubeadm 并在此基础上部署一个容器化的 Nginx 应用程序。
简介
Kubernetes(也称为 k8s 或 “kube”)是一个开源的容器编排平台,它将部署、管理和扩展容器化应用所涉及的许多手动过程自动化。Kubernetes 拥有一个快速增长的开源社区,积极为该项目做出贡献。看看我们的博客文章,它将向您介绍您需要了解的关于Kubernetes 平台的基础知识.
Kubeadm 是一个工具,用于配置多个集成元素、部件和组件,例如 API 服务器、控制器管理器(Controller Manager)和 Kube DNS。它还有助于自动化安装。然而,它不会创建用户,也不处理操作系统级依赖项的安装及其配置,并且无法配置您的基础设施。
Ansible 是一款用于软件配置和应用程序部署的开源工具。Saltstack 是一款由事件驱动的用于信息技术自动化的开源软件。这两个工具可以使创建额外集群或重建现有集群时更不易出错,并可用于这些初步任务。
目标:
您的集群将包括以下物理资源:
1. 一个主节点:
主节点是控制和管理一组工作节点(工作负载运行时间)的节点,类似于 Kubernetes 中的集群。它还保存节点的资源计划,以确定针对触发事件的适当操作。它运行 etcd,这是一个开源的分布式键值存储,用于在向工作节点调度工作负载的组件之间保存和管理集群数据。
例如,调度器会确定哪个工作节点将托管新调度的 POD。
2. 两个工作节点:
工作节点是在调度完成后,即使主节点宕机也能继续执行其分配工作的节点。工作节点是运行您的工作负载(即容器化应用程序和服务)的服务器。您还可以通过添加工作节点来增加集群的容量。
完成本教程后,假设集群中的服务器具有足够的 CPU 和内存资源来运行您的应用程序,您将拥有一个功能齐全的集群,随时可以运行工作负载(即容器化应用程序和服务)。成功设置集群后,您几乎可以运行任何传统的 UNIX 应用程序。它可以在您的集群上进行容器化,包括 Web 应用程序、数据库、守护进程 and 命令行工具。
集群本身在每个节点上将消耗大约 300-500MB 的内存和 10% 的 CPU。
前提条件:
- 您必须在本地 Linux 机器上拥有 SSH 密钥对,并了解如何使用 SSH 密钥。但是,如果您以前没有使用过 SSH 密钥,可以参考本教程来帮助您在本地机器上设置 SSH 密钥.
- 三台运行 Ubuntu 18.04 的服务器,每台至少配备 4GB 内存和 4 个 vCPU。您应该能够使用您的 SSH 密钥对以 root 用户身份 SSH 登录到每台服务器。请遵循本教程来安装您的 Ubuntu 服务器.
- 在本地机器上安装 Ansible。
- 您还必须熟悉 Ansible playbook。
- 您还需要了解如何从 Docker 镜像启动容器。请参阅 “第 5 步 — 在 Ubuntu 中使用 Docker 镜像”,位于 《如何在 Ubuntu 18.04 上安装和使用 Docker》(如果您需要温习的话)。
第 1 步 — 设置工作区目录和 Ansible Inventory 文件
您首先需要在本地机器上设置 Ansible。它将帮助您在远程服务器上执行命令。它还通过自动化来减轻手动部署的工作量。为此,您需要在本地机器上创建一个目录,作为您的临时数字存储区域(工作区)。
创建目录后,您将创建一个 hosts 文件,用于存储有关每个服务器的 IP 地址和组的所有信息。它将帮助您在其中存储清单信息。如前所述,将有三台服务器,一个 master 和两个 worker。master 服务器将是 master,其 IP 显示为 master_ip. 另外两台服务器将是 worker,其 IP 为 worker_1_ip 和 worker_2_ip.
您需要在本地机器的主目录下创建一个名为 ~/kube-cluster 的目录,并使用 cd 命令进入该目录:
|
1 2 |
mkdir ~/kube-cluster cd ~/kube-cluster |
The ~/kube-cluster 目录现在将作为临时数字存储区域(工作区),您将在其中运行所有本地命令,以使用 kubeadm 创建 Kubernetes 集群。该目录将包含您所有的 Ansible playbook,并将在本教程的其余部分中使用。
创建 Hosts 文件
创建一个名为 ~/kube-cluster/hosts ,使用 nano 或您最喜欢的文本编辑器:
|
1 |
nano ~/kube-cluster/hosts |
现在您需要添加以下文本,它将指定有关集群逻辑结构的信息:
|
1 2 3 4 5 6 7 8 9 |
[masters] master ansible_host=master_ip ansible_user=root [workers] worker1 ansible_host=worker_1_ip ansible_user=root worker2 ansible_host=worker_2_ip ansible_user=root [all:vars] ansible_python_interpreter=/usr/bin/python3 |
如前所述,该清单文件将帮助您存储有关服务器 IP 地址以及每个服务器所属组的所有信息。~/kube-cluster/hosts 将是您的清单文件,而 (masters 和 workers) 将是您添加到其中以指定集群逻辑结构的两个 Ansible 组。
其中 Master 组是指定 Ansible 应作为 root 用户运行远程命令的组。它还列出了 master 节点的 IP (master_ip),该 IP 可以通过名为 “master” 的服务器条目列出。同样,Workers 组有两个用于 worker 服务器的条目 (worker_1_ip 和 worker_2_ip),它们也指定了 ansible_user 为 root。
该文件的最后一行告诉 Ansible 使用远程服务器的 Python 3 解释器进行其 management 操作。最后,在添加文本后,您需要保存并关闭该文件。设置好工作区目录和 Ansible 清单文件后,让我们继续下一步:安装操作系统级别的依赖项并创建配置设置。
第 2 步 — 在所有远程服务器上创建非 Root 用户
在这一步中,您将学习如何在所有服务器上创建一个具有 sudo 特权的非 root 用户,以便您可以作为无特权用户手动 SSH 登录到这些服务器中。
这对于维护集群时经常执行的操作非常有用。此外,这一步将帮助您更准确、更不易出错地执行任务,从而减少无意中修改或删除重要文件的可能性。如果您想更改 root 拥有的文件的设置,或者使用诸如 top/htop 之类的命令查看系统信息并查看正在运行的容器列表,以下步骤将帮助您执行所有这些任务。
创建 Playbook
创建一个名为 ~/kube-cluster/initial.yml 的文件,在工作区中:
|
1 |
nano ~/kube-cluster/initial.yml |
接下来,您需要添加以下 play。Ansible 中的 play 是针对特定服务器和组执行的一系列步骤。一个 playbook 中可以有一个或多个 play。
以下 play 将创建一个非 root sudo 用户:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
- hosts: all become: yes tasks: - name: 创建 the 'ubuntu' 用户 user: name=ubuntu append=yes state=present createhome=yes shell=/bin/bash - name: 允许 'ubuntu' to 拥有 免密 sudo lineinfile: dest: /etc/sudoers line: 'ubuntu ALL=(ALL) NOPASSWD: ALL' validate: 'visudo -cf %s' - name: 设置 up 授权 密钥 为 the ubuntu 用户 authorized_key: user=ubuntu key="{{item}}" with_file: - ~/.ssh/id_rsa.pub |
以下是我们的 playbook 所做工作的分解:
- 此 playbook 将创建非 root 用户
ubuntu. - 由于您需要运行
sudo命令而无需密码提示,此 play 将配置sudoers文件以允许ubuntu用户这样做。 - 上述任务的主要目的是允许您作为
ubuntu用户通过 SSH 登录到每台服务器。此 playbook 会将您本地机器的公钥(通常是~/.ssh/id_rsa.pub)添加到远程ubuntu用户的授权密钥列表中。
现在,添加文本后,您需要保存并关闭该文件。
运行 playbook
之后,我们只需要在本地机器上运行以下命令来执行我们的 playbook,它将创建非 root 用户 ubuntu:
|
1 |
ansible-playbook -i hosts ~/kube-cluster/initial.yml |
执行此命令将需要一些时间,之后您将看到以下输出:

完成此步骤后,您可以在下一步中继续安装 Kubernetes 特定的依赖项。
第 3 步 — 安装 Kubernetes’ 依赖项
在此步骤中,您将学习如何使用 Ubuntu 的包管理器安装 Kubernetes 所需的操作系统级软件包。
这些软件包是:
- Docker:Docker 是一个用于构建、分发和运行 Docker 容器的平台和工具。您可以轻松地通过按照我们关于how to install & operate Docker on Ubuntu in the public cloud的教程来设置 Docker。然而,对其他运行时(例如 rkt)的支持在 Kubernetes 中正在积极开发中。
Kubeadm: kubeadm 是一个 CLI 工具,用于执行启动和运行最小可行集群所需的操作。这将帮助您以标准方式安装和构建集群的各种组件。kubelet: kubelet 是运行在每个节点上并处理节点级操作的主要 “节点代理”。kubectl: kubectl 也是一个 CLI 工具,用于与您的集群进行通信并通过其 API 服务器发布命令。
创建 playbook
创建一个名为 ~/kube-cluster/kube-dependencies.yml 的文件在工作区中:
|
1 |
nano ~/kube-cluster/kube-dependencies.yml |
现在您需要将以下 play 添加到文件中,以便在您的服务器上安装以下软件包:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
- hosts: all become: yes tasks: - name: 安装 Docker apt: name: docker.io state: present update_cache: true - name: 安装 APT Transport HTTPS apt: name: apt-transport-https state: present - name: 添加 Kubernetes apt-key apt_key: url: https://packages.cloud.google.com/apt/doc/apt-key.gpg validate_certs: false state: present - name: 添加 Kubernetes 的 APT 仓库 apt_repository: repo: deb http://apt.kubernetes.io/ kubernetes-xenial main state: present filename: 'kubernetes' - name: 安装 kubelet apt: name: kubelet=1.16.0-00 state: present update_cache: true - name: 安装 kubeadm apt: name: kubeadm=1.16.0-00 state: present - hosts: master become: yes tasks: - name: 安装 kubectl apt: name: kubectl=1.16.0-00 state: present force: yes |
Playbook 中的第一个 play 执行以下操作:
- 此 play 将帮助您安装操作系统级别的软件包,即 Docker – 容器运行时。
- 它安装
apt-transport-https,这允许您将外部 HTTPS 源添加到 APT 源列表中。 - 添加 Kubernetes APT 仓库的 apt-key 以进行密钥验证。
- 将 Kubernetes APT 仓库添加到远程服务器的 APT 源列表中。
- 安装
kubelet和kubeadm.
第二个 play 执行一项重要且单独的任务,包括安装 kubectl 在您的主节点上。现在,添加文本后,您需要保存并关闭文件。
运行 Playbook
之后,我们只需要在本地机器上运行以下命令来执行 Playbook:
|
1 |
ansible-playbook -i hosts ~/kube-cluster/kube-dependencies.yml |
执行此命令需要一些时间,之后您将看到以下输出:

执行后,Docker、kubeadm 和 kubelet 将安装在所有远程服务器上。kubectl 不是必需的组件,仅在执行集群命令时需要。在这种情况下,仅在主节点上安装它是合理的,因为您将仅从主节点运行 kubectl 命令。但是请注意,kubectl 命令可以从任何工作节点运行,也可以从任何可以安装并配置为指向集群的机器上运行。
所有系统依赖项现已安装。让我们设置主节点并初始化集群。
第 4 步 — 设置主节点
在这一步中,您将学习一些概念,例如 Pod 和 Pod 网络插件,因为一旦设置好主节点,您的集群将同时包含这两者。
Pod 是 Kubernetes 中最小、最基本的部署对象。Pod 包含一个或多个容器,例如 Docker 容器。当一个 Pod 运行多个容器时,这些容器将作为一个整体进行管理,并共享该 Pod’s 资源。
每个 Pod 都有自己的 IP 地址,一个节点上的 Pod 应该能够使用该 Pod’s IP 访问另一个节点上的 Pod。然而,Pod 之间的通信更为复杂。它需要一个单独的组件,能够透明地将流量从一个节点上的 Pod 路由到另一个节点上的 Pod。Pod 网络插件就是用于实现这一功能的。有许多 Pod 网络插件可用,但我们将使用 Flannel,因为它是一个稳定且高效的选择。
创建 Playbook
在本地机器上创建一个名为 master.yml 的 Ansible playbook:
|
1 |
nano ~/kube-cluster/master.yml |
此外,您需要向文件中添加以下 play 以初始化集群并安装 Flannel:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
- hosts: master become: yes tasks: - name: 初始化the 集群 shell: kubeadm init --pod-network-cidr=10.244.0.0/16 >> cluster_initialized.txt args: chdir: $HOME creates: cluster_initialized.txt become: yes become_user: root - name: 创建 .kube 目录 become: yes become_user: ubuntu file: path: $HOME/.kube state: directory mode: 0755 - name: 复制 admin.conf 到 用户'的 kube 配置 copy: src: /etc/kubernetes/admin.conf dest: /home/ubuntu/.kube/config remote_src: yes owner: ubuntu - name: 安装 Pod 网络 become: yes become_user: ubuntu shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml >> pod_network_setup.txt args: chdir: $HOME creates: pod_network_setup.txt |
以下是此 play 的分解说明:
- 此 play 中的第一个任务将通过运行以下命令来设置集群:
kubeadm init。为了指定分配给 pod IP 的私有子网,我们传递参数--pod-network-cidr=10.244.0.0/16。Flannel 默认使用上述子网。我们使用它来告诉kubeadm使用相同的子网。 - 第二个任务用于在
.kube目录,路径为/home/ubuntu。连接到集群所需的管理密钥文件以及集群的 API 地址等配置信息将保存在此目录中。 - 第三个任务用于将从
/etc/kubernetes/admin.conf生成的kubeadm init文件复制到非 root 用户的家目录。这将允许您使用kubectl来访问新创建的集群。 - 最后一个任务运行
kubectl apply来安装Flannel.kubectl apply -f descriptor.[yml|json]是告诉kubectl创建在descriptor.[yml|json]文件中描述的对象。kube-flannel.yml文件包含在集群中设置Flannel所需对象的描述。
现在,添加文本后,您需要保存并关闭文件。
运行 Playbook
之后,您只需在本地机器上运行以下命令来执行我们的 playbook:
|
1 |
ansible-playbook -i hosts ~/kube-cluster/master.yml |
执行此命令需要一些时间,之后您将看到以下输出:

现在使用以下命令通过 SSH 连接到它,以检查 master 节点的状态:
|
1 |
ssh ubuntu@master_ip |
进入 master 节点后,执行:
|
1 |
kubectl get nodes |
您现在将看到以下输出:

获得上述输出后,您可以宣告 master 节点已完成所有设置任务,并且在进入 Ready 状态后可以开始接受 worker 节点并执行任务。您现在可以从本地机器添加 worker。
第 5 步 — 设置 Worker 节点
设置好 master 节点后,我们现在可以进入下一步:设置 worker 节点。只需在每个 worker 服务器上执行一条命令,即可将 worker 节点添加到集群中。该命令中包含了重要信息,例如 master 的 API 服务器的 IP 地址、端口以及安全令牌。但您应该注意,并非所有节点都能加入集群,只有传递了安全令牌的节点才能加入集群。
创建 playbook
此命令将帮助您返回工作空间并创建一个名为 workers.yml:
|
1 |
nano ~/kube-cluster/workers.yml |
将以下文本添加到文件中,以将 worker 添加到集群中:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
- hosts: master become: yes gather_facts: false tasks: - name: 获取 join 命令 shell: kubeadm token create --print-join-command register: join_command_raw - name: 设置 join 命令 set_fact: join_command: "{{ join_command_raw.stdout_lines[0] }}" - hosts: workers become: yes tasks: - name: 加入 集群 shell: "{{ hostvars['master'].join_command }} >> node_joined.txt" args: chdir: $HOME creates: node_joined.txt |
以下是该 playbook 的作用。上述代码中有两个 play:
- 第一个 play 用于获取需要在工作节点上运行的加入命令。该命令的格式为:
kubeadm join --token sha256:<hash><token><master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash>;。该任务需要获取正确的 token 和 hash 值。一旦获取到正确的输入,该任务会将其设置为 fact,以便第二个 play 能够访问该信息。 - 第二个 play 仅用于执行一个单独的任务 – 通过在所有工作节点上运行加入命令,使这两个工作节点成为集群的一部分。
添加文本后,您需要保存并关闭该文件。
运行 playbook
之后,我们需要通过在工作节点机器上运行以下命令来执行我们的 playbook:
|
1 |
ansible-playbook -i hosts ~/kube-cluster/workers.yml |
执行此命令需要一些时间,之后您将看到以下输出:

现在,您的 Kubernetes 集群已完全建立并正常运行,工作节点已准备好运行工作负载。在进入下一步之前,让我们验证集群是否按计划工作。
第 6 步 — 验证集群
在设置过程中,可能会出现集群失败的情况。这可能是由于主节点和工作节点之间的网络错误,或者是节点问题。因此,在调度应用程序之前,我们需要验证集群并确保没有发生故障。为此,您需要从主节点检查集群的当前状态,以确保节点已准备就绪。如果节点未准备就绪或您断开了连接,可以使用以下命令重新建立连接:
|
1 |
ssh ubuntu@master_ip |
使用以下命令获取集群的状态:
|
1 |
kubectl get nodes |
执行此命令需要一些时间,之后您将看到以下输出:

您需要检查作为集群一部分的所有节点是否都处于就绪状态。如果有一些节点的 Not Ready 作为 STATUS,这表明工作节点尚未完成设置。但是,在重新运行 kubectl get nodes 并检查更新的输出之前,您应该再等待五到十分钟。如果某些节点仍然显示 Not Ready 作为其状态,您应该去验证前面的步骤并重新运行命令。只有当节点的 STATUS 值为 Ready 时,它们才是集群的一部分并准备好运行工作负载。成功执行第 6 步后,您的集群现在已通过验证。现在让我们在集群上调度一个示例 Nginx 应用程序。
第 7 步 — 在集群上运行应用程序
创建 Deployment
成功创建集群后,您可以将任何容器化应用程序部署到集群中。如果您在主节点内,可以对其他容器化应用程序使用以下命令。接下来,执行以下命令创建一个名为 nginx :
|
1 |
kubectl create deployment nginx --image=nginx |
您需要更改 Docker 镜像名称和任何相关标志(例如端口和数据卷)。为了保持熟悉度,您可以使用 deployment 和 service 来部署 Nginx,以查看如何将应用程序部署到集群中。
一个 Kubernetes 部署 是 Kubernetes 中的一个资源对象,用于为应用程序提供声明式更新。部署(Deployment)允许您描述应用程序的生命周期,例如容器镜像、副本数和更新策略。部署可确保在任何时候都有所需数量的 Pod 正在运行且可用。如果某个 Pod 在集群生命周期内崩溃,它会重新生成该 Pod。更新过程也会被完整记录并进行版本控制,并提供暂停、继续和回滚到以前版本的选项。上述创建名为 Nginx 的部署的命令将帮助您使用 Docker 注册表中的 Nginx Docker 镜像部署一个包含单个容器的 Pod。
设置 Node Port
接下来,我们需要创建一个 NodePort. NodePort 是集群中每个节点上的一个开放端口。Kubernetes 会将传入 NodePort 的流量透明地路由到您的服务,即使您的应用程序运行在另一个节点上也是如此。为此,我们可以使用此命令创建一个名为 Nginx 的 NodePort 资源,该资源将公开该应用程序:
|
1 |
kubectl expose deploy nginx --port 80 --target-port 80 --type NodePort |
服务(Service)是另一个 Kubernetes 对象,负责向这些 Pod 公开接口,从而允许从集群内部或外部进程与服务之间进行网络访问。它可以被定义为 Pod 之上的一种抽象,提供了一个单一的 IP 地址和 DNS 名称,通过它们可以访问 Pod。通过服务,可以非常轻松地管理负载均衡配置。
运行以下命令:
|
1 |
kubectl get services |
这将输出类似于以下内容的文件:

获取输出后,Kubernetes 将自动分配一个大于 30000 的随机端口,同时还会确保分配的端口未被其他服务绑定。上述输出的第三行将帮助您获取 Nginx 正在运行的端口。
要验证其是否正常工作,请通过本地计算机上的浏览器访问 http://worker_1_ip:nginx_port 或 http://worker_2_ip:nginx_port 。您将看到 Nginx 熟悉的欢迎页面。
删除部署
如果您想删除 Nginx 应用程序,您需要先从主节点删除 nginx 服务:
|
1 |
kubectl delete service nginx |
要验证应用程序是否最终被删除,您需要运行此命令:
|
1 |
kubectl get services |
您将获得以下输出:

之后,您需要使用以下命令删除部署:
|
1 |
kubectl delete deployment nginx |
您可以使用此命令来验证部署是否最终被删除:
|
1 |
kubectl get deployments |
![]()
结论:
本教程将帮助您使用 Kubeadm 和 Ansible 在 Ubuntu 18.04 上正确设置集群。现在您的集群已设置完毕,您可以轻松开始部署自己的应用程序和服务。
以下是包含更多详细信息的链接列表,这些信息将在此过程中为您提供指导:
- Docker 化应用程序 – 此链接包含指导您如何使用 Docker 加载应用程序的示例。例如 Docker 化 PostgreSQL、CouchDB 服务等。
- Pod 概述 – 此链接展示了如何使用 Pod、Pod 的运作方式以及 Pod 与其他 Kubernetes 对象的关系的详细信息。Pod 是 Kubernetes 的重要组成部分,因此了解它们将有助于您成功完成任务。
- 部署概述 – 它将帮助您了解部署。部署为 Pod 和 ReplicaSet 提供声明式更新。您将学习如何更新、轮转和回滚部署。
- 服务概述 -此链接将指导您了解服务,这是 Kubernetes 集群中另一个常用的对象。Kubernetes 中的服务是一种抽象,它定义了一组逻辑 Pod 以及访问它们的策略。了解服务的类型及其拥有的选项对于运行无状态和有状态应用程序都至关重要。
此外,请查看我们其他专注于 Docker 和 Kubernetes 的教程,您可以在我们的博客上找到:
- 了解 Kubernetes
- 清理 Docker 资源 – 镜像、容器和卷
- 如何在 CloudSigma 上运行 Docker(使用 CloudInit)已更新
- 在 CentOS 7 上安装和设置 Docker
- 如何在公共云中的 Ubuntu 上安装 & 操作 Docker
还有许多其他重要的概念,例如卷, Ingress、以及机密,您可以在部署生产应用程序时使用。
祝您计算愉快!
评论
暂无评论。发表第一条评论吧。