作者选择了自由和开源基金 ,作为Write for DOnations计划的一部分,获得200美元的捐赠。
介绍
Kubernetes是一个容器管理系统,可以按比例管理容器。 Kubernetes最初是由谷歌根据其在生产中运行容器的经验开发的,它是开源的,由全球社区积极开发。
Kubeadm自动安装和配置Kubernetes组件,例如API服务器,Controller Manager和Kube DNS。 但是,它不会创建用户或处理操作系统级别依赖关系及其配置的安装。 对于这些初步任务,可以使用Ansible或SaltStack等配置管理工具。 使用这些工具可以创建更多的群集或重新创建现有群集,从而更简单,更不容易出错。
在本指南中,您将使用Ansible和Kubeadm从零开始设置Kubernetes集群,然后将容器化的Nginx应用程序部署到它。
目标
您的群集将包含以下物理资源:
- 一个主节点
主节点(Kubernetes中的一个节点指服务器)负责管理群集的状态。 它运行Etcd ,它在将工作负载调度到工作节点的组件之间存储集群数据。
- 两个工人节点
工作者节点是工作负载 (即容器化的应用程序和服务)将运行的服务器。 一旦工作分配完毕,工作人员将继续运行您的工作负载,即使主人在调度完成后出现故障。 通过增加工作人员可以增加集群的容量。
完成本指南后,您将拥有一个可以运行容器化应用程序的集群,前提是集群中的服务器具有足够的CPU和RAM资源供您的应用程序使用。 几乎任何传统的Unix应用程序,包括Web应用程序,数据库,守护进程和命令行工具都可以容器化并在集群上运行。 集群本身将消耗约300-500MB的内存和每个节点上10%的CPU。
集群设置完成后,您将部署Web服务器Nginx ,以确保它正确运行工作负载。
先决条件
本地Linux / Mac OS / BSD机器上的SSH密钥对。 如果您之前没有使用过SSH密钥,您可以按照以下有关如何在本地计算机上设置SSH密钥的说明,了解如何设置它们。
运行Ubuntu 16.04的三台服务器至少有1GB RAM。 您应该能够以SSH用户身份通过SSH密钥对以SSH身份进入每台服务器。
Ansible安装在本地机器上。 如果您将Ubuntu 16.04作为您的操作系统运行,请按照如何安装和配置Ubuntu 16.04上的Ansible以安装Ansible中的“第1步 - 安装Ansible”一节。 有关Mac OS X或CentOS等其他平台上的安装说明,请按照正式的Ansible安装文档 。
熟悉Ansible的手册。 如需查看,请查看配置管理101:编写Ansible Playbooks 。
了解如何从Docker镜像启动容器。 如果您需要进行复习,请参阅如何在Ubuntu 16.04上安装和使用Docker中的“第5步 - 运行Docker容器”。
第1步 - 设置工作区目录和Ansible清单文件
在本节中,您将在本地机器上创建一个目录作为您的工作区。 您将在本地配置Ansible,以便它可以与您的远程服务器进行通信并执行命令。 完成之后,您将创建一个包含清单信息的hosts
文件,例如服务器的IP地址和每个服务器所属的组。
在你的三台服务器中,将有一台主机的IP显示为master_ip
。 其他两台服务器将是工作人员,并且将具有IP worker_1_ip
和worker_2_ip
。
在本地机器的主目录中创建一个名为~/kube-cluster
的目录,然后cd
进入它:
mkdir ~/kube-cluster
cd ~/kube-cluster
该目录将成为本教程其余部分的工作空间,并将包含所有Ansible Playbook。 它也将是您将运行所有本地命令的目录。
使用nano
或您最喜爱的文本编辑器创建一个名为~/kube-cluster/hosts
文件:
nano ~/kube-cluster/hosts
将以下文本添加到文件中,该文件将指定有关群集逻辑结构的信息:
[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
您可能会记得,Ansible中的库存文件用于指定服务器信息,例如IP地址,远程用户和服务器组,以作为执行命令的单个单元。 ~/kube-cluster/hosts
将成为您的清单文件,并且您已向其添加了两个Ansible组( 主人和工作人员 ),以指定您的群集的逻辑结构。
在主服务器组中,有一个名为“master”的服务器条目,其中列出主节点的IP( master_ip
)并指定Ansible应以root用户身份运行远程命令。
同样,在工作组中,工作服务器有两个条目( worker_1_ip
和worker_2_ip
),它们也将root用户指定为ansible_user
。
该文件的最后一行告诉Ansible使用远程服务器的Python 3解释器进行管理操作。
添加文本后保存并关闭文件。
使用组设置服务器清单后,让我们继续安装操作系统级别依赖关系并创建配置设置。
第2步 - 在所有远程服务器上创建非root用户
在本节中,您将在所有服务器上创建一个具有sudo权限的非root用户,以便您可以以非特权用户的身份手动进行SSH连接。 例如,如果您希望通过诸如top/htop
命令查看系统信息,查看正在运行的容器的列表或更改由root拥有的配置文件,这会非常有用。 这些操作在集群维护期间定期执行,使用非root用户执行此类任务可最大限度地降低修改或删除重要文件或无意执行其他危险操作的风险。
在工作区中创建一个名为~/kube-cluster/initial.yml
的文件:
nano ~/kube-cluster/initial.yml
接下来,将以下播放添加到该文件,以在所有服务器上创建具有sudo权限的非root用户。 Ansible中的剧本是针对特定服务器和组执行的一系列步骤。 以下玩法将创建一个非root用户sudo用户:
- 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
(通常为~/.ssh/id_rsa.pub
)添加到远程ubuntu
用户的授权密钥列表中。 这将允许您以ubuntu
用户身份ubuntu
到每台服务器。
添加文本后保存并关闭文件。
接下来,通过本地运行执行剧本:
ansible-playbook -i hosts ~/kube-cluster/initial.yml
该命令将在两到五分钟内完成。 完成后,您将看到类似于以下内容的输出:
OutputPLAY [all] ****
TASK [Gathering Facts] ****
ok: [master]
ok: [worker1]
ok: [worker2]
TASK [create the 'ubuntu' user] ****
changed: [master]
changed: [worker1]
changed: [worker2]
TASK [allow 'ubuntu' user to have passwordless sudo] ****
changed: [master]
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: [master] => (item=ssh-rsa AAAAB3...
PLAY RECAP ****
master : ok=5 changed=4 unreachable=0 failed=0
worker1 : ok=5 changed=4 unreachable=0 failed=0
worker2 : ok=5 changed=4 unreachable=0 failed=0
现在初步设置已完成,您可以继续安装Kubernetes特定的依赖项。
第3步 - 安装Kubernetetes的依赖关系
在本节中,您将使用Ubuntu的软件包管理器安装Kubernetes所需的操作系统级别的软件包。 这些软件包是:
Docker - 一个容器运行时。 它是运行你的容器的组件。 Kubernetes正在积极开发其他运行库,如rkt。
kubeadm
- 一种CLI工具,它将以标准方式安装和配置集群的各种组件。kubelet
- 一种在所有节点上运行并处理节点级操作的系统服务/程序。kubectl
- 用于通过API服务器向集群发出命令的CLI工具。
在工作区中创建一个名为~/kube-cluster/kube-dependencies.yml
的文件:
nano ~/kube-cluster/kube-dependencies.yml
将以下内容添加到文件中以将这些软件包安装到您的服务器上:
- hosts: all
become: yes
tasks:
- 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
state: present
update_cache: true
- name: install kubeadm
apt:
name: kubeadm
state: present
- hosts: master
become: yes
tasks:
- name: install kubectl
apt:
name: kubectl
state: present
剧本中的第一个剧本做了以下工作:
安装Docker,容器运行时。
安装
apt-transport-https
,允许您将外部HTTPS源添加到APT源列表中。为密钥验证添加Kubernetes APT存储库的apt-key。
将Kubernetes APT存储库添加到远程服务器的APT源列表中。
安装
kubelet
和kubeadm
。
第二个游戏包含一个在您的主节点上安装kubectl
任务。
完成后保存并关闭文件。
接下来,通过本地运行执行剧本:
ansible-playbook -i hosts ~/kube-cluster/kube-dependencies.yml
完成后,您将看到类似于以下内容的输出:
OutputPLAY [all] ****
TASK [Gathering Facts] ****
ok: [worker1]
ok: [worker2]
ok: [master]
TASK [install Docker] ****
changed: [master]
changed: [worker1]
changed: [worker2]
TASK [install APT Transport HTTPS] *****
ok: [master]
ok: [worker1]
changed: [worker2]
TASK [add Kubernetes apt-key] *****
changed: [master]
changed: [worker1]
changed: [worker2]
TASK [add Kubernetes' APT repository] *****
changed: [master]
changed: [worker1]
changed: [worker2]
TASK [install kubelet] *****
changed: [master]
changed: [worker1]
changed: [worker2]
TASK [install kubeadm] *****
changed: [master]
changed: [worker1]
changed: [worker2]
PLAY [master] *****
TASK [Gathering Facts] *****
ok: [master]
TASK [install kubectl] ******
ok: [master]
PLAY RECAP ****
master : ok=9 changed=5 unreachable=0 failed=0
worker1 : ok=7 changed=5 unreachable=0 failed=0
worker2 : ok=7 changed=5 unreachable=0 failed=0
执行后,Docker, kubeadm
和kubelet
将安装在所有远程服务器上。 kubectl
不是必需的组件,仅用于执行群集命令。 由于您只能从主服务器运行kubectl
命令,因此仅在主节点上安装它才有意义。 但是,请注意, kubectl
命令可以从任何工作节点运行,也可以从可以安装并配置为指向集群的任何计算机上运行。
现在安装了所有系统依赖关系。 我们设置主节点并初始化集群。
第4步 - 设置主节点
在本节中,您将设置主节点。 但是,在创建任何剧本之前,值得介绍一些概念,例如Pod和Pod网络插件 ,因为您的群集将包含这两个概念。
一个容器是一个运行一个或多个容器的原子单元。 这些容器共享文件卷和网络接口等资源。 豆荚是Kubernetes中的基本调度单元:豆荚中的所有容器都保证与该豆荚所在的同一节点上运行。
每个吊舱都有自己的IP地址,并且一个节点上的吊舱应该能够使用吊舱的IP访问另一个节点上的吊舱。 单个节点上的容器可以通过本地接口轻松进行通信。 但是,Pod之间的通信更为复杂,并且需要一个独立的网络组件,可以将流量从一个节点上的pod透明地路由到另一个节点上的pod。
该功能由pod网络插件提供。 对于这个集群,你将使用Flannel ,一个稳定和高性能的选项。
在本地机器上创建一个名为master.yml
的Ansible手册:
nano ~/kube-cluster/master.yml
将以下播放添加到文件以初始化群集并安装Flannel:
- hosts: master
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/v0.9.1/Documentation/kube-flannel.yml >> pod_network_setup_complete.txt
args:
chdir: $HOME
creates: pod_network_setup.txt
这是这个游戏的细节:
第一个任务通过运行
kubeadm init
初始化群集。 传递参数--pod-network-cidr=10.244.0.0/16
指定将从中分配pod IP的专用子网。 Flannel默认使用上面的子网; 我们告诉kubeadm
使用相同的子网。第二个任务在
/home/ubuntu
创建一个.kube
目录。 该目录将保存配置信息,例如连接到群集所需的管理密钥文件以及群集的API地址。第三个任务将从
kubeadm init
生成的/etc/kubernetes/admin.conf
文件复制到非root用户的主目录。 这将允许您使用kubectl
访问新创建的群集。运行
kubectl apply
的最后一个任务kubectl apply
于安装Flannel
。kubectl apply -f descriptor.[yml|json]
是告诉kubectl
创建描述descriptor.[yml|json]
文件中descriptor.[yml|json]
的对象的语法。kube-flannel.yml
文件包含在集群中设置Flannel
所需的对象的描述。
完成后保存并关闭文件。
运行以下命令在本地执行剧本:
ansible-playbook -i hosts ~/kube-cluster/master.yml
完成后,您将看到类似于以下内容的输出:
Output
PLAY [master] ****
TASK [Gathering Facts] ****
ok: [master]
TASK [initialize the cluster] ****
changed: [master]
TASK [create .kube directory] ****
changed: [master]
TASK [copy admin.conf to user's kube config] *****
changed: [master]
TASK [install Pod network] *****
changed: [master]
PLAY RECAP ****
master : ok=5 changed=4 unreachable=0 failed=0
要检查主节点的状态,请使用以下命令进入SSH:
ssh ubuntu@master_ip
一旦进入主节点,执行:
kubectl get nodes
您现在将看到以下输出:
OutputNAME STATUS ROLES AGE VERSION
master Ready master 1d v1.10.1
输出表明master
节点已完成所有初始化任务并处于Ready
状态,可以从该状态开始接受工作节点并执行发送到API服务器的任务。 您现在可以从本地机器添加工人。
第5步 - 设置工作节点
将工作人员添加到群集涉及对每个群集执行单个命令。 该命令包含必要的群集信息,例如主API服务器的IP地址和端口以及安全令牌。 只有通过安全令牌的节点才能加入群集。
导航回您的工作区并创建一个名为workers.yml
的剧本:
nano ~/kube-cluster/workers.yml
将以下文本添加到文件中以将工作人员添加到群集:
- hosts: master
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['master'].join_command }} >> node_joined.txt"
args:
chdir: $HOME
creates: node_joined.txt
以下是剧本的作用:
第一次播放获取需要在工作节点上运行的连接命令。 该命令将采用以下格式:
kubeadm join --token <token> <master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash>
。 一旦它获得了具有适当的令牌和散列值的实际命令,该任务将其设置为事实,以便下一次播放将能够访问该信息。第二次播放有一个单一的任务,在所有工作节点上运行连接命令。 完成此任务后,这两个工作节点将成为群集的一部分。
完成后保存并关闭文件。
通过本地运行执行剧本:
ansible-playbook -i hosts ~/kube-cluster/workers.yml
完成后,您将看到类似于以下内容的输出:
OutputPLAY [master] ****
TASK [get join command] ****
changed: [master]
TASK [set join command] *****
ok: [master]
PLAY [workers] *****
TASK [Gathering Facts] *****
ok: [worker1]
ok: [worker2]
TASK [join cluster] *****
changed: [worker1]
changed: [worker2]
PLAY RECAP *****
master : 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 ubuntu@master_ip
然后执行以下命令以获取群集的状态:
kubectl get nodes
您将看到类似于以下内容的输出:
OutputNAME STATUS ROLES AGE VERSION
master Ready master 1d v1.10.1
worker1 Ready <none> 1d v1.10.1
worker2 Ready <none> 1d v1.10.1
如果所有节点的值都为Ready
for STATUS
,则表示它们是群集的一部分,并且已准备好运行工作负载。
但是,如果少数节点具有NotReady
作为STATUS
,则可能意味着工作节点尚未完成设置。 等待大约五到十分钟后,重新运行kubectl get node
并检查新的输出。 如果少数节点仍然具有NotReady
状态,则可能需要验证并重新运行先前步骤中的命令。
现在你的集群已经被成功验证了,让我们在集群上安排一个示例Nginx应用程序。
第7步 - 在群集上运行应用程序
您现在可以将任何容器化的应用程序部署到您的集群。 为了保持熟悉,我们使用Deployments and Services部署Nginx,以了解如何将此应用程序部署到群集。 如果您更改Docker映像名称和任何相关标志(例如ports
和volumes
),则也可以将其他容器化应用程序的以下命令用于其他应用程序。
仍然在主节点中,执行以下命令来创建名为nginx
的部署:
kubectl run nginx --image=nginx --port 80
部署是一种Kubernetes对象,即使群集的生命周期中的pod崩溃,也可以确保始终基于定义的模板运行指定数量的pod。 上述部署将使用Docker注册表的Nginx Docker Image创建一个容器。
接下来,运行以下命令创建名为nginx
的服务,该服务将公开地公开该应用程序。 它将通过一个NodePort来实现 ,一个可以通过群集中每个节点上打开的任意端口访问pod的方案:
kubectl expose deploy nginx --port 80 --target-port 80 --type NodePort
服务是另一种类型的Kubernetes对象,它向集客内部和外部的客户提供集群内部服务。 它们还能够将请求负载平衡到多个Pod,并且是Kubernetes中不可或缺的组件,通常与其他组件进行交互。
运行以下命令:
kubectl get services
这将输出类似于以下内容的文本:
OutputNAME 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
的随机端口,同时确保该端口尚未被其他服务绑定。
要测试一切正常,请通过本地计算机上的浏览器访问http:// worker_1_ip : nginx_port
或http:// worker_2_ip : nginx_port
。 您将看到Nginx的熟悉欢迎页面。
如果您想删除Nginx应用程序,请首先从主节点删除nginx
服务:
kubectl delete service nginx
运行以下命令以确保服务已被删除:
kubectl get services
您将看到以下输出:
OutputNAME 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
OutputNo resources found.
结论
在本指南中,您已经使用Kubeadm和Ansible在Ubuntu 16.04上成功建立了一个Kubernetes集群以实现自动化。
如果您想知道如何设置集群,那么下一步就是将自己的应用程序和服务部署到集群上。 以下链接列表可提供进一步信息,可以指导您在此过程中:
Dockerizing应用程序 - 列举了详细说明如何使用Docker容器化应用程序的示例。
Pod概述 - 详细描述Pods如何工作以及它们与其他Kubernetes对象的关系。 豆荚在Kubernetes中无处不在,因此理解它们将有助于您的工作。
部署概述 - 这提供了部署的概述。 了解控制器(如部署)如何工作是非常有用的,因为它们在无状态应用程序中经常用于扩展和自动修复不健康的应用程序。
服务概述 - 这包括服务,这是Kubernetes集群中另一个经常使用的对象。 了解服务类型和选项对于运行无状态和有状态的应用程序至关重要。
其他可供您研究的重要概念是Volumes , Ingress和Secrets ,所有这些概念在部署生产应用程序时都会派上用场。
Kubernetes提供了许多功能和特性。 Kubernetes官方文档是了解概念,查找任务特定指南以及查找各种对象的API参考的最佳位置。