control_plane_ip: 主节点ip(例如172.19.33.41)
worker_1_ip: 从节点ip
worker_2_ip:从节点ip
第 1 步 — 设置工作区目录和 Ansible 库存文件
在本节中,您将在本地计算机上创建一个目录作为您的工作区。您将在本地配置 Ansible,以便它可以与远程服务器通信并在远程服务器上执行命令。完成后,您将创建一个hosts
包含库存信息的文件,例如服务器的 IP 地址和每个服务器所属的组。
在您的三台服务器中,一台是控制平面,其 IP 显示为control_plane_ip
. 另外两台服务器将是工作服务器,并将拥有 IPworker_1_ip
和worker_2_ip
.
~/kube-cluster
在本地计算机的主目录中创建一个名为的目录并将cd
其放入:
mkdir
cd
复制
该目录将成为本教程其余部分的工作区,并将包含您的所有 Ansible 剧本。它也将是您将在其中运行所有本地命令的目录。
创建一个~/kube-cluster/hosts
使用nano
或您喜欢的文本编辑器命名的文件:
nano
复制
将以下文本添加到文件中,该文件将指定有关集群逻辑结构的信息:
~/kube-cluster/主机
[control_plane]
control1 ansible_host=control_plane_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
复制
您可能还记得Ansible 中的清单文件用于指定服务器信息,例如 IP 地址、远程用户和服务器组,以作为执行命令的单个单元。~/kube-cluster/hosts
将是您的清单文件,并且您已向其中添加了两个 Ansible 组(控制平面和工作人员),指定了集群的逻辑结构。
在控制平面组中,有一个名为“control1”的服务器条目,它列出了控制平面的 IP ( control_plane_ip
),并指定 Ansible 应以 root 用户身份运行远程命令。
同样,在工作组中,工作服务器有两个条目 (worker_1_ip
和worker_2_ip
),它们也指定ansible_user
为 root。
该文件的最后一行告诉 Ansible 使用远程服务器的 Python 3 解释器进行管理操作。
添加文本后保存并关闭文件。如果您正在使用nano
,请按Ctrl+X
,然后在出现提示时按 ,Y
然后按Enter
。
使用组设置服务器清单后,让我们继续安装操作系统级别的依赖项并创建配置设置。
第 2 步 — 在所有远程服务器上创建非根用户
在本节中,您将在所有服务器上创建一个具有 sudo 权限的非 root 用户,以便您可以作为非特权用户手动 SSH 到它们。例如,如果您想使用命令查看系统信息top/htop
、查看正在运行的容器列表或更改 root 拥有的配置文件,这将很有用。这些操作是在集群维护期间例行执行的,使用非 root 用户执行此类任务可以最大限度地降低修改或删除重要文件或无意执行其他危险操作的风险。
在工作区中创建一个名为的文件~/kube-cluster/initial.yml
:
nano
复制
接下来,将以下播放添加到文件中,以在所有服务器上创建一个具有 sudo 权限的非 root 用户。Ansible 中的 play 是针对特定服务器和组的要执行的步骤的集合。以下播放将创建一个非 root sudo 用户:
~/kube-cluster/initial.yml
---
- hosts: all
become: yes
tasks:
- name: create the 'ubuntu' user
user: name=ubuntu append=yes state=present createhome=yes shell=/bin/bash
- name: allow 'ubuntu' to have passwordless sudo
lineinfile:
dest: /etc/sudoers
line: 'ubuntu ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
- name: set up authorized keys for the ubuntu user
authorized_key: user=ubuntu key="{{item}}"
with_file:
- ~/.ssh/id_rsa.pub
复制
以下是该剧本的功能细分:
- 创建非 root 用户
ubuntu
。 - 配置
sudoers
文件以允许ubuntu
用户在没有密码提示的情况下运行sudo
命令。 - 将本地计算机(通常
~/.ssh/id_rsa.pub
)中的公钥添加到远程ubuntu
用户的授权密钥列表中。这将允许您以ubuntu
用户身份通过 SSH 连接到每个服务器。
添加文本后保存并关闭文件。
接下来,在本地运行 playbook:
ansible-playbook -i hosts ~/kube-cluster/initial.yml
复制
该命令将在两到五分钟内完成。完成后,您将看到类似于以下内容的输出:
Output
PLAY [all] **** TASK [Gathering Facts] **** ok: [control1] ok: [worker1] ok: [worker2] TASK [create the 'ubuntu' user] **** changed: [control1] changed: [worker1] changed: [worker2] TASK [allow 'ubuntu' user to have passwordless sudo] **** changed: [control1] changed: [worker1] changed: [worker2] TASK [set up authorized keys for the ubuntu user] **** changed: [worker1] => (item=ssh-rsa AAAAB3...) changed: [worker2] => (item=ssh-rsa AAAAB3...) changed: [control1] => (item=ssh-rsa AAAAB3...) PLAY RECAP **** control1 : ok=4 changed=3 unreachable=0 failed=0 worker1 : ok=4 changed=3 unreachable=0 failed=0 worker2 : ok=4 changed=3 unreachable=0 failed=0
现在初步设置已完成,您可以继续安装 Kubernetes 特定的依赖项。
第 3 步 — 安装 Kubernetes 的依赖项
在本节中,您将使用 Ubuntu 的包管理器安装 Kubernetes 所需的操作系统级包。这些软件包是:
- Docker - 一个容器运行时。它是运行容器的组件。Kubernetes 支持其他运行时,但 Docker 仍然是一种流行且直接的选择。
kubeadm
- 一个 CLI 工具,它将以标准方式安装和配置集群的各种组件。kubelet
- 在所有节点上运行并处理节点级操作的系统服务/程序。kubectl
- 一个 CLI 工具,用于通过其 API 服务器向集群发出命令。
在工作区中创建一个名为的文件~/kube-cluster/kube-dependencies.yml
:
nano
复制
将以下播放添加到文件中以将这些软件包安装到您的服务器:
~/kube-cluster/kube-dependencies.yml
---
- hosts: all
become: yes
tasks:
- name: create Docker config directory
file: path=/etc/docker state=directory
- name: changing Docker to systemd driver
copy:
dest: "/etc/docker/daemon.json"
content: |
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
- name: install Docker
apt:
name: docker.io
state: present
update_cache: true
- name: install APT Transport HTTPS
apt:
name: apt-transport-https
state: present
- name: add Kubernetes apt-key
apt_key:
url: https://packages.cloud.google.com/apt/doc/apt-key.gpg
state: present
- name: add Kubernetes' APT repository
apt_repository:
repo: deb http://apt.kubernetes.io/ kubernetes-xenial main
state: present
filename: 'kubernetes'
- name: install kubelet
apt:
name: kubelet=1.22.4-00
state: present
update_cache: true
- name: install kubeadm
apt:
name: kubeadm=1.22.4-00
state: present
- hosts: control_plane
become: yes
tasks:
- name: install kubectl
apt:
name: kubectl=1.22.4-00
state: present
force: yes
复制
playbook 中的第一个 play 执行以下操作:
- 安装 Docker、容器运行时并配置兼容性设置。
- 安装
apt-transport-https
,允许您将外部 HTTPS 源添加到 APT 源列表。 - 添加 Kubernetes APT 存储库的 apt-key 用于密钥验证。
- 将 Kubernetes APT 存储库添加到远程服务器的 APT 源列表。
- 安装
kubelet
和kubeadm
.
kubectl
第二个游戏由安装在您的控制平面节点上的单个任务组成。
注意:虽然 Kubernetes 文档建议您为您的环境使用 Kubernetes 的最新稳定版本,但本教程使用特定版本。这将确保您可以成功执行这些步骤,因为 Kubernetes 变化很快,并且最新版本可能不适用于本教程。虽然“xenial”是 Ubuntu 16.04 的名称,而且本教程是针对 Ubuntu 20.04 的,但 Kubernetes 仍然默认指的是 Ubuntu 16.04 的包源,并且在这种情况下它们在 20.04 上是支持的。
完成后保存并关闭文件。
接下来,使用以下命令在本地运行 playbook:
ansible-playbook -i hosts ~/kube-cluster/kube-dependencies.yml
复制
完成后,您将收到类似于以下内容的输出:
Output
PLAY [all] **** TASK [Gathering Facts] **** ok: [worker1] ok: [worker2] ok: [control1] TASK [create Docker config directory] **** changed: [control1] changed: [worker1] changed: [worker2] TASK [changing Docker to systemd driver] **** changed: [control1] changed: [worker1] changed: [worker2] TASK [install Docker] **** changed: [control1] changed: [worker1] changed: [worker2] TASK [install APT Transport HTTPS] ***** ok: [control1] ok: [worker1] changed: [worker2] TASK [add Kubernetes apt-key] ***** changed: [control1] changed: [worker1] changed: [worker2] TASK [add Kubernetes' APT repository] ***** changed: [control1] changed: [worker1] changed: [worker2] TASK [install kubelet] ***** changed: [control1] changed: [worker1] changed: [worker2] TASK [install kubeadm] ***** changed: [control1] changed: [worker1] changed: [worker2] PLAY [control1] ***** TASK [Gathering Facts] ***** ok: [control1] TASK [install kubectl] ****** changed: [control1] PLAY RECAP **** control1 : ok=11 changed=9 unreachable=0 failed=0 worker1 : ok=9 changed=8 unreachable=0 failed=0 worker2 : ok=9 changed=8 unreachable=0 failed=0
运行此 playbook 后,Docker、kubeadm
和kubelet
将安装在所有远程服务器上。kubectl
不是必需的组件,仅用于执行集群命令。在这种情况下,仅将其安装在控制平面节点上是有意义的,因为您将kubectl
仅从控制平面运行命令。但是请注意,kubectl
命令可以从任何工作节点或任何可以安装和配置为指向集群的机器上运行。
现在已安装所有系统依赖项。让我们设置控制平面节点并初始化集群。
第 4 步 — 设置控制平面节点
在本节中,您将设置控制平面节点。然而,在创建任何剧本之前,有必要了解一些概念,例如Pods和Pod Network Plugins,因为您的集群将同时包含这两者。
Pod 是运行一个或多个容器的原子单元。这些容器共享资源,例如文件卷和网络接口。Pod 是 Kubernetes 中调度的基本单元:一个 pod 中的所有容器都保证在该 pod 被调度的同一节点上运行。
每个 pod 都有自己的 IP 地址,一个节点上的 pod 应该能够使用 pod 的 IP 访问另一个节点上的 pod。单个节点上的容器可以通过本地接口轻松通信。然而,pod 之间的通信更加复杂,并且需要一个单独的网络组件,该组件可以透明地将流量从一个节点上的 pod 路由到另一个节点上的 pod。
此功能由 pod 网络插件提供。对于此集群,您将使用Flannel,这是一个稳定且高性能的选项。
创建一个control-plane.yml
在本地机器上命名的 Ansible playbook:
nano
复制
在文件中添加以下 play 来初始化集群并安装 Flannel:
~/kube-cluster/control-plane.yml
---
- hosts: control_plane
become: yes
tasks:
- name: initialize the cluster
shell: kubeadm init --pod-network-cidr=10.244.0.0/16 >> cluster_initialized.txt
args:
chdir: $HOME
creates: cluster_initialized.txt
- name: create .kube directory
become: yes
become_user: ubuntu
file:
path: $HOME/.kube
state: directory
mode: 0755
- name: copy admin.conf to user's kube config
copy:
src: /etc/kubernetes/admin.conf
dest: /home/ubuntu/.kube/config
remote_src: yes
owner: ubuntu
- name: install Pod network
become: yes
become_user: ubuntu
shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml >> pod_network_setup.txt
args:
chdir: $HOME
creates: pod_network_setup.txt
复制
以下是这部剧的详细介绍:
- 第一个任务通过运行初始化集群
kubeadm init
。传递参数--pod-network-cidr=10.244.0.0/16
指定将从中分配 pod IP 的私有子网。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:
ansible-playbook -i hosts ~/kube-cluster/control-plane.yml
复制
完成后,您将看到类似于以下内容的输出:
Output
PLAY [control1] **** TASK [Gathering Facts] **** ok: [control1] TASK [initialize the cluster] **** changed: [control1] TASK [create .kube directory] **** changed: [control1] TASK [copy admin.conf to user's kube config] ***** changed: [control1] TASK [install Pod network] ***** changed: [control1] PLAY RECAP **** control1 : ok=5 changed=4 unreachable=0 failed=0
如果出现
error execution phase upload-config/kubelet: Error writing Crisocket information for the control-plane node: timed out waiting for the condition
To see the stack trace of this error execute with --v=5 or higher
说明iptables 有问题,执行如下操作
swapoff -a
kubeadm reset
systemctl daemon-reload
systemctl restart kubelet
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
然后从新执行
ansible-playbook -i hosts ~/kube-cluster/control-plane.yml
要检查控制平面节点的状态,请使用以下命令通过 SSH 连接到它:
ssh
复制
进入控制平面节点后,执行:
kubectl get nodes
复制
您现在将看到以下输出:
Output
NAME STATUS ROLES AGE VERSION control1 Ready control-plane,master 51s v1.22.4
注意:从 Ubuntu 20.04 开始,kubernetes 正在更新他们的旧术语。control-plane
我们在本教程中提到的节点过去称为master
节点,有时您会看到 kubernetes 出于兼容性原因同时分配两个角色。
输出表明control-plane
节点已完成所有初始化任务,并处于Ready
可以开始接受工作节点并执行发送到 API Server 的任务的状态。您现在可以从本地计算机添加工作人员。
第 5 步 — 设置工作节点
将工作人员添加到集群涉及在每个工作人员上执行单个命令。该命令包括必要的集群信息,例如控制平面的 API 服务器的 IP 地址和端口,以及安全令牌。只有传入安全令牌的节点才能加入集群。
导航回您的工作区并创建一个名为的剧本workers.yml
:
nano
复制
将以下文本添加到文件中以将工作人员添加到集群:
~/kube-cluster/workers.yml
---
- hosts: control_plane
become: yes
gather_facts: false
tasks:
- name: get join command
shell: kubeadm token create --print-join-command
register: join_command_raw
- name: set join command
set_fact:
join_command: "{{ join_command_raw.stdout_lines[0] }}"
- hosts: workers
become: yes
tasks:
- name: join cluster
shell: "{{ hostvars['control1'].join_command }} >> node_joined.txt"
args:
chdir: $HOME
creates: node_joined.txt
复制
这是剧本的作用:
- 第一次播放获取需要在工作节点上运行的连接命令。该命令将采用以下格式:
kubeadm join --token <token> <control-plane-ip>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>
. 一旦它获得具有正确令牌和哈希值的实际命令,该任务将其设置为事实,以便下一次播放将能够访问该信息。 - 第二个游戏有一个任务,在所有工作节点上运行 join 命令。完成此任务后,两个工作节点将成为集群的一部分。
完成后保存并关闭文件。
使用以下命令在本地运行 playbook:
ansible-playbook -i hosts ~/kube-cluster/workers.yml
复制
完成后,您将看到类似于以下内容的输出:
Output
PLAY [control1] **** TASK [get join command] **** changed: [control1] TASK [set join command] ***** ok: [control1] PLAY [workers] ***** TASK [Gathering Facts] ***** ok: [worker1] ok: [worker2] TASK [join cluster] ***** changed: [worker1] changed: [worker2] PLAY RECAP ***** control1 : ok=2 changed=1 unreachable=0 failed=0 worker1 : ok=2 changed=1 unreachable=0 failed=0 worker2 : ok=2 changed=1 unreachable=0 failed=0
随着工作节点的添加,您的集群现在已完全设置并正常运行,工作人员已准备好运行工作负载。在调度应用程序之前,让我们验证集群是否按预期工作。
第 6 步 — 验证集群
集群有时会在设置过程中失败,因为节点已关闭或控制平面和工作人员之间的网络连接无法正常工作。让我们验证集群并确保节点正常运行。
您需要从控制平面节点检查集群的当前状态,以确保节点已准备就绪。如果您与控制平面节点断开连接,您可以使用以下命令通过 SSH 重新连接到该节点:
ssh
复制
然后执行以下命令获取集群的状态:
kubectl get nodes
复制
您将看到类似于以下内容的输出:
Output
NAME STATUS ROLES AGE VERSION control1 Ready control-plane,master 3m21s v1.22.0 worker1 Ready <none> 32s v1.22.0 worker2 Ready <none> 32s v1.22.0
如果您的所有节点都具有 的值Ready
,STATUS
则表示它们是集群的一部分并准备好运行工作负载。
但是,如果一些节点具有NotReady
,STATUS
则可能意味着工作节点尚未完成设置。等待大约五到十分钟,然后重新运行kubectl get nodes
并检查新输出。如果有几个节点仍然NotReady
处于状态,您可能需要验证并重新运行前面步骤中的命令。
现在您的集群已成功验证,让我们在集群上安排一个示例 Nginx 应用程序。
第 7 步 — 在集群上运行应用程序
您现在可以将任何容器化应用程序部署到您的集群。为了保持熟悉,让我们使用部署和服务来部署 Nginx ,以探索如何将这个应用程序部署到集群中。您也可以将以下命令用于其他容器化应用程序,前提是您更改 Docker 映像名称和任何相关标志(例如ports
和volumes
)。
确保您已登录到控制平面节点,然后运行以下命令来创建名为 的部署nginx
:
kubectl create deployment nginx --image=nginx
复制
部署是一种 Kubernetes 对象,可确保始终基于定义的模板运行指定数量的 pod,即使 pod 在集群的生命周期内崩溃。上述部署将从 Docker 注册表的Nginx Docker Image创建一个带有一个容器的 pod 。
接下来,运行以下命令来创建一个名为的服务,该服务nginx
将公开公开应用程序。它将通过NodePort执行此操作,该方案将使 pod 可以通过在集群的每个节点上打开的任意端口访问:
kubectl expose deploy nginx --port 80 --target-port 80
复制
服务是另一种类型的 Kubernetes 对象,它向内部和外部客户端公开集群内部服务。它们还能够对多个 pod 的请求进行负载平衡,并且是 Kubernetes 中不可或缺的组件,经常与其他组件交互。
运行以下命令:
kubectl get services
复制
此命令将输出类似于以下内容的文本:
Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d nginx NodePort 10.109.228.209 <none> 80:nginx_port/TCP 40m
从上面输出的突出显示的行中,您可以检索 Nginx 正在运行的端口。Kubernetes 将分配一个大于30000
自动的随机端口,同时确保该端口尚未被其他服务绑定。
要测试一切是否正常,请访问或通过本地计算机上的浏览器。你会看到 Nginx 熟悉的欢迎页面。http://worker_1_ip:nginx_port
http://worker_2_ip:nginx_port
如果您想删除 Nginx 应用程序,请先nginx
从控制平面节点中删除该服务:
kubectl delete service
复制
运行以下命令以确保服务已被删除:
kubectl get services
复制
您将看到以下输出:
Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d
然后删除部署:
kubectl delete deployment nginx
复制
运行以下命令以确认这是否有效:
kubectl get deployments
复制