Skip to content

Latest commit

 

History

History
1966 lines (1461 loc) · 61 KB

File metadata and controls

1966 lines (1461 loc) · 61 KB

九、部署和配置 Kubernetes

在了解了 Kubernetes 的内部组件以及它们之间的交互方式之后,是时候学习如何设置它们了。手动安装 Kubernetes 集群可能是一个非常痛苦和微妙的过程,但是通过完成所需的步骤,我们可以学习和更好地理解它的内部组件。在执行手动安装之后,我们还可以探索我们有哪些其他的替代方法和工具来自动化这个过程。以下是我们将在本章中学习的内容的摘要:

  • 创建我们的计算环境
  • 引导控制平面
  • 引导工作节点
  • 配置群集网络和 DNS 设置
  • 托管 Kubernetes 服务的示例

随着每一步的进行,我们将更接近完成 Kubernetes 的完整安装,并准备在开发环境中进行测试。

基础设施部署

为了部署运行 Kubernetes 集群的基础设施,我们将使用微软 Azure。您可以通过创建免费试用版或使用任何其他公共云提供商或您自己的内部 IT 基础架构来跟进。不过,根据您的选择,步骤会有所不同。

安装 Azure 命令行界面

当您使用 Linux 时,有两种方法可以在 Azure 中部署资源:您可以从门户或通过 Azure CLI 来完成。我们将两者都使用,但是用于不同的场景。

让我们开始在我们的 Linux 工作站或 Linux 的 Windows 子系统上安装 Azure CLI。

Note that all commands are assumed to be issued by an account with root privileges or the root account itself (but this is not recommended).

对于基于 RHEL/Centos 的发行版,您需要执行以下步骤:

  1. 下载并import存储库密钥,如下命令所示:
rpm --import https://packages.microsoft.com/keys/microsoft.asc

2.创建存储库配置文件,如以下命令所示:

cat << EOF > /etc/yum.repos.d/azure-cli.repo
[azure-cli]
name=Azure CLI
baseurl=https://packages.microsoft.com/yumrepos/azure-cli
enabled=1
gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft.asc
EOF

3.使用以下命令安装azure-cli:

yum install azure-cli

4.使用以下命令登录您的 Azure 订阅:

az login

If you are not in a Desktop environment, you can use: az login --use-device-code,  because  the regular "az login" requires  a web browser to perform the login.

安装 Azure CLI 后,我们仍然需要设置一些默认值,这样我们就不必一遍又一遍地键入相同的标志选项。

配置 Azure 命令行界面

Azure 上的每个资源都生活在一个资源组和一个地理位置中。因为我们所有的资源将生活在相同的资源组和位置,让我们将它们配置为默认值。为此,请运行以下命令:

az configure --defaults location=eastus group=Kube_Deploy

对于我们的示例,我们使用east us作为位置,因为这是最接近我们所在位置的位置。组名将取决于您如何命名您的资源组,在我们的示例中为Kube_Deploy

配置了默认值后,让我们继续使用以下命令实际创建包含我们的资源的资源组:

az group create -n “Kube_Deploy”

高级设计概述

创建我们的资源组并选择我们的位置后,让我们从高层次来看一下我们将使用以下代码创建的设计:

<design picture>

我们现在需要注意的重要事项是虚拟机数量、网络架构和防火墙规则,因为这些是我们将在第一步中直接配置的要素。

在开始调配资源之前,让我们先了解一下我们的网络需求。

我们有以下要求:

  • 以下三组不同的非重叠子网:

    • 虚拟机子网
    • Pod 子网
    • 服务子网
  • 为以下资源静态分配的 IP 地址:

    • 主节点
    • 工作节点
    • 管理虚拟机
    • 负载平衡器的公共 IP
    • DNS 服务器

对于我们的虚拟机子网,我们将使用以下地址空间:

192.168.0.0/24

CIDR 的服务如下:

10.20.0.0/24

最后,我们的 POD CIDR 将稍微大一点,这样它可以分配更多的 POD,如下面的代码所示:

10.30.0.0/16

现在,让我们开始调配实现该体系结构所需的网络资源。

供应网络资源

首先,我们将创建包含虚拟机子网的虚拟网络。为此,请运行以下命令:

az network vnet create -n kube-node-vnet \
 --address-prefix 192.168.0.0/16 \
 --subnet-name node-subnet \
 --subnet-prefix 192.168.0.0/24

这个命令的两个关键点是address-prefix 旗和subnet-prefix旗。

使用address-prefix 标志,我们将指定地址空间,该空间将定义我们可以在 VNET 上放置哪些子网。例如,我们的 VNET 前缀是192.16.0.0/16。这意味着我们不能把任何地址放在这个 CIDR 之外;例如,10.0.0.0/24行不通。

子网前缀将是提供给连接到我们子网的虚拟机的地址空间。现在我们已经创建了我们的 VNET 和子网,我们需要一个静态的公共 IP 地址。在 Azure 和任何公共云提供商中,公共 IP 都是独立于虚拟机的资源。

让我们通过运行以下命令来创建我们的公共 IP:

az network public-ip create -n kube-api-pub-ip \
 --allocation-method Static \
 --sku Standard

创建后,我们可以通过运行以下查询来记录该 IP:

az network public-ip show -n kube-api-pub-ip --query "ipAddress"

由于我们的 VNET、子网和公共 IP 都已分配,我们只需要最后一个资源,即防火墙,来为我们的虚拟机提供安全性。在 Azure 中,防火墙被称为网络安全组 ( NSGs )。创建 NSG 的过程相当简单,如以下命令所示:

az network nsg create -n kube-nsg

创建 NSG 后,我们使用以下命令将 NSG 分配给我们的子网:

az network vnet subnet update -n node-subnet \
 --vnet-name kube-node-vnet \
 --network-security-group kube-nsg

调配计算资源

随着我们的网络全部建立,我们准备开始创建一些虚拟机。但是在我们创建任何虚拟机之前,我们需要创建 SSH 密钥,我们将使用它来访问我们的虚拟机。

我们将为管理虚拟机创建的第一对密钥。该虚拟机将是唯一一个可以从外部进行 SSH 访问的虚拟机。出于安全原因,我们不想暴露任何集群节点的端口22。每当我们想要访问任何节点时,我们都会从该虚拟机进行访问。

要创建 SSH 密钥,请在您的 Linux 工作站上运行ssh-keygen:

ssh-keygen

现在,让我们使用以下命令创建管理虚拟机:

az vm create -n management-vm \
 --admin-username <USERNAME> \
 --size Standard_B1s \
 --image CentOS \
 --vnet-name kube-node-vnet \
 --subnet node-subnet \
 --private-ip-address 192.168.0.99 \
 --nsg kube-nsg \
 --ssh-key-value ~/.ssh/id_rsa.pub

请记住将<USERNAME>字段替换为所需的用户名。

下一步是我们需要配置我们的第一个 NSG 规则。这条规则将允许流量从我们自己的网络通过端口22到达我们的管理虚拟机,这样我们就可以通过 SSH 进入其中。让我们使用以下命令来设置它:

az network nsg rule create --nsg-name kube-nsg \
 -n mgmt_ssh_allow \
 --direction Inbound \
 --priority 100 \
 --access Allow \
 --description "Allow SSH From Home" \
 --destination-address-prefixes '192.168.0.99' \
 --destination-port-ranges 22 \
 --protocol Tcp \
 --source-address-prefixes '<YOUR IP>' \
 --source-port-ranges '*' \
 --direction Inbound

The source-address-prefixes is your ISP provided public IP address, as this IPs can be dynamic, in the even that it changes, you can edit the IP on the Network Security Group rules in your Azure Portal.

现在让我们连接到我们的虚拟机来创建 SSH 密钥,这将允许我们连接到我们的集群虚拟机。要检索我们管理的公共 IP 地址vm,运行以下查询:

az vm show -d -n management-vm --query publicIps

现在,让我们使用之前创建的私钥将 SSH 连接到我们的虚拟机,如下所示:

ssh <username>@<public ip> -i <path to private key>

如果您使用与创建密钥对时不同的用户登录,则只需指定私钥。

现在我们在管理虚拟机中,再次运行ssh-keygen并最终退出虚拟机。

为了在 Azure 数据中心发生灾难时提供高可用性,我们的主节点将位于可用性集中。让我们创建可用性集。

如果您不记得可用性集是什么,您可以回到我们的 Gluster 章节,重新访问它的功能。

要创建可用性集,请运行以下命令:

az vm availability-set create -n control-plane \
 --platform-fault-domain-count 3 \
 --platform-update-domain-count 3

现在我们可以开始创建我们的第一个控制平面节点了。让我们先将管理的虚拟机公共 SSH 密钥保存到一个变量中,以便将密钥传递给主节点,如以下命令所示:

MGMT_KEY=$(ssh <username>@<public ip> cat ~/.ssh/id_rsa.pub)

要创建三个控制器节点,运行以下for 循环:

for i in 1 2 3; do
az vm create -n kube-controller-${i} \
 --admin-username <USERNAME> \
 --availability-set control-plane \
 --size Standard_B2s \
 --image CentOS \
 --vnet-name kube-node-vnet \
 --subnet node-subnet \
 --private-ip-address 192.168.0.1${i} \
 --public-ip-address "" \
 --nsg kube-nsg \
 --ssh-key-value ${MGMT_KEY};
done

我们在这些虚拟机上使用的大小很小,因为这只是一个测试环境,我们并不真正需要大量的计算资源。在真实环境中,我们会根据我们在第 8 章构建 Kubernetes 集群中探讨的考虑因素来调整虚拟机的大小。

最后但同样重要的是,我们使用以下命令创建工作节点:

for i in 1 2; do
az vm create -n kube-node-${i} \
 --admin-username <USERNAME>\
 --size Standard_B2s \
 --image CentOS \
 --vnet-name kube-node-vnet \
 --subnet node-subnet \
 --private-ip-address 192.168.0.2${i} \
 --public-ip-address "" \
 --nsg kube-nsg \
 --ssh-key-value ${MGMT_KEY}
done

准备管理虚拟机

创建控制器和工作节点后,我们现在可以登录管理虚拟机,开始安装和配置引导 Kubernetes 集群所需的工具。

从现在开始,我们将主要致力于管理虚拟机。让我们将 SSH 连接到虚拟机,并开始安装我们的工具集。

首先,我们需要下载工具来创建证书,我们的集群服务将使用这些证书来相互通信。

我们将首先使用以下命令安装依赖项:

johndoe@management-vm$ sudo yum install git gcc 

johndoe@management-vm$ sudo wget -O golang.tgz  https://dl.google.com/go/go1.11.1.linux-amd64.tar.gz 

johndoe@management-vm$ sudo tar -C /usr/local -xzvf golang.tgz

安装 Go lang 后,您需要更新您的PATH变量并创建一个名为GOPATH的新变量。您的 TLS 证书生成工具 CFFSL 将安装在此路径中。为此,您可以执行以下操作:

johndoe@management-vm$ sudo cat << EOF > /etc/profile.d/paths.sh
export PATH=$PATH:/usr/local/go/bin:/usr/local/bin
export GOPATH=/usr/local/
EOF

然后运行以下命令来加载当前 shell 中的变量:

johndoe@management-vm$ sudo source /etc/profile.d/paths.sh

设置好变量后,现在我们准备使用以下命令去获取我们的cffsl工具包:

johndoe@management-vm$ go get -u github.com/cloudflare/cfssl/cmd/cfssl

johndoe@management-vm$ go get -u github.com/cloudflare/cfssl/cmd/cfssljson

两个二进制文件都将保存在我们的GOPATH变量下。

生成证书

安装好 CFSSL 二进制文件并加载到我们的PATH后,我们就可以开始生成我们的证书文件了。我们将在安装的这一部分生成大量文件,因此创建一个目录结构来适当地存储它们将是一个好主意。

认证授权

我们需要生成的第一个文件是我们的证书颁发机构的文件,它将签署我们组件的其余证书。

我们将在~/certs/目录下存储我们所有的证书,但是首先我们需要创建目录。让我们使用以下命令来设置它:

johndoe@management-vm$ mkdir ~/certs

现在我们有了目录,让我们从使用以下命令生成 CA 配置文件开始,该文件将包含由我们的 CA 颁发的证书的到期日期以及 CA 将用于什么目的等信息:

johndoe@management-vm$ cd ~/certs

johndoe@management-vm$ cat << EOF > ca-config.json
{
 "signing": {
 "default": {
 "expiry": "8760h"
 },
 "profiles": {
 "kubernetes": {
 "usages": [
 "signing",
 "key encipherment",
 "server auth",
 "client auth"
 ],
 "expiry": "8760h"
 }
 }
 }
}
EOF

有了 CA 配置,我们现在可以开始发出证书签名请求了。

我们将产生的第一个企业社会责任是针对我们的认证中心的。让我们使用以下命令来设置它:

johndoe@management-vm$ cat << EOF > ca-csr.json 
{
 "CN": "Kubernetes",
 "key": {
 "algo": "rsa",
 "size": 2048
 },
 "names": [
 {
 "C": "US",
 "L": "New York",
 "O": "Kubernetes",
 "OU": "CA",
 "ST": "NY"
 }
 ]
}
EOF

现在我们已经有了我们的JSON文件,我们实际上可以使用cffsl并使用以下命令生成我们的证书:

johndoe@management-vm$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca

如下图所示,将生成三个文件:ca.csrca.pemca-key.pem。第一个ca.csr,是证书签名请求。另外两个分别是我们的公共证书和私钥:

johndoe@management-vm$ ls
ca-config.json  ca.csr ca-csr.json  ca-key.pem ca.pem

从现在开始,我们在中生成的任何证书都将是这种情况。

客户端证书

现在我们的证书颁发机构已经配置好了,并且生成了证书文件,我们可以开始为管理员用户和每个工作节点上的 kubelet 颁发证书了。

我们将要创建的过程和文件与 CA 非常相似,但是我们用来生成它们的命令略有不同。

让我们使用以下命令为我们的admin certs 创建一个目录:

johndoe@management-vm$ mkdir ~/certs/admin/

johndoe@management-vm$ cd ~/certs/admin/

首先,创建管理员用户证书。此证书供我们的管理员通过kubectl管理我们的集群。

同样,我们将使用以下命令为csr生成json:

johndoe@management-vm$ cat << EOF > admin-csr.json 
{
 "CN": "admin",
 "key": {
 "algo": "rsa",
 "size": 2048
 },
 "names": [
 {
 "C": "US",
 "L": "New York",
 "O": "system:masters",
 "OU": "Kubernetes",
 "ST": "NY"
 }
 ]
}
EOF

准备好 JSON 后,让我们现在使用以下命令签名并创建管理证书:

johndoe@management-vm$ cfssl gencert \
 -ca=../ca.pem \
 -ca-key=../ca-key.pem \
 -config=../ca-config.json \
 -profile=kubernetes \
 admin-csr.json | cfssljson -bare admin

与管理证书和证书颁发机构证书相比,创建kubelet证书的过程略有不同。kubelet证书要求我们在证书中填写主机名字段,因为这是它的识别方式。

使用以下命令创建目录:

johndoe@management-vm$ mkdir ~/certs/kubelet/

johndoe@management-vm$ cd ~/certs/kubelet/

然后使用以下命令创建json csr,其中没有太大变化:

johndoe@management-vm$ cat << EOF > kube-node-1-csr.json
{
 "CN": "system:node:kube-node-1",
 "key": {
 "algo": "rsa",
 "size": 2048
 },
 "names": [
 {
 "C": "US",
 "L": "New York",
 "O": "system:nodes",
 "OU": "Kubernetes",
 "ST": "NY"
 }
 ]
}
EOF

但是,生成certs的过程有点不同,从下面的命令可以看出:

johndoe@management-vm$ cfssl gencert \
 -ca=../ca.pem \
 -ca-key=../ca-key.pem \
 -config=../ca-config.json \
 -hostname=192.168.0.21,kube-node-1 \
 -profile=kubernetes \
 kube-node-1-csr.json | cfssljson -bare kube-node-1

如您所见,主机名字段将包含节点将拥有的任何 IP 或 FQDN。现在为每个工作节点生成一个证书,填写与您为其生成证书的节点相对应的信息。

控制平面证书

让我们开始为 kube 主组件创建证书。

与前面的步骤一样,创建一个包含主节点组件证书的目录,并以下列方式为每个组件生成证书文件:

johndoe@management-vm$ mkdir ~/certs/control-plane/

johndoe@management-vm$ cd ~/certs/control-plane/

对于kube-controller-manager,使用以下命令:

johndoe@management-vm$ cat << EOF > kube-controller-manager-csr.json
{
 "CN": "system:kube-controller-manager",
 "key": {
 "algo": "rsa",
 "size": 2048
 },
 "names": [
 {
 "C": "US",
 "L": "New York",
 "O": "system:kube-controller-manager",
 "OU": "Kubernetes",
 "ST": "NY"
 }
 ]
}
EOF

johndoe@management-vm$ cfssl gencert \
 -ca=../ca.pem \
 -ca-key=../ca-key.pem \
 -config=../ca-config.json \
 -profile=kubernetes \
 kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager

对于kube-proxy,使用以下命令:

johndoe@management-vm$ cat << EOF > kube-proxy-csr.json
{
 "CN": "system:kube-proxy",
 "key": {
 "algo": "rsa",
 "size": 2048
 },
 "names": [
 {
 "C": "US",
 "L": "New York",
 "O": "system:node-proxier",
 "OU": "Kubernetes",
 "ST": "NY"
 }
 ]
}
EOF

johndoe@management-vm$ cfssl gencert \
 -ca=../ca.pem \
 -ca-key=../ca-key.pem \
 -config=../ca-config.json \
 -profile=kubernetes \
 kube-proxy-csr.json | cfssljson -bare kube-proxy

对于kube-scheduler,使用以下命令:

johndoe@management-vm$ cat << EOF > kube-scheduler-csr.json
{
 "CN": "system:kube-scheduler",
 "key": {
 "algo": "rsa",
 "size": 2048
 },
 "names": [
 {
 "C": "US",
 "L": "New York",
 "O": "system:kube-scheduler",
 "OU": "Kubernetes",
 "ST": "NY"
 }
 ]
}
EOF

johndoe@management-vm$ cfssl gencert \
 -ca=../ca.pem \
 -ca-key=../ca-key.pem \
 -config=../ca-config.json \
 -profile=kubernetes \
 kube-scheduler-csr.json | cfssljson -bare kube-scheduler

现在我们需要创建 API 服务器。您会注意到它类似于我们使用kubelets的过程,因为这个证书需要主机名参数。但是有了kube-api证书,我们将不仅提供单个节点的主机名和 IP 地址,我们还将提供我们的应用编程接口服务器将使用的所有可能的主机名和 IP:负载平衡器公共 IP、每个主节点的 IP 和一个特殊的 FQDN,kubernetes.default。所有这些都将在一个证书中。

让我们首先使用以下命令创建一个单独的目录:

johndoe@management-vm$ mkdir ~/certs/api/

johndoe@management-vm$ cd ~/certs/api/

现在,让我们使用以下命令为主机名创建一个变量:

johndoe@management-vm$API_HOSTNAME=10.20.0.1,192.168.0.11,kube-controller-1,192.168.0.12,kube-controller-2,<PUBLIC_IP>,127.0.0.1,localhost,kubernetes.default

Note that you should replace <PUBLIC_IP> with your public IP address.

现在,让我们使用以下命令创建证书:

johndoe@management-vm$ cat << EOF > kubernetes-csr.json 
{
 "CN": "kubernetes",
 "key": {
 "algo": "rsa",
 "size": 2048
 },
 "names": [
 {
 "C": "US",
 "L": "New York",
 "O": "Kubernetes",
 "OU": "Kubernetes",
 "ST": "NY"
 }
 ]
}
EOF

johndoe@management-vm$ cfssl gencert \
 -ca=../ca.pem \
 -ca-key=../ca-key.pem \
 -config=../ca-config.json \
 -hostname=${API_HOSTNAME} \
 -profile=kubernetes \
 kubernetes-csr.json | cfssljson -bare kubernetes

此时,只缺少一个证书,即服务帐户证书。该证书不是专门针对任何普通用户或 Kubernetes 组件的。服务帐户证书由应用编程接口服务器用来签署用于服务帐户的令牌。

我们将把这些密钥对存储在与 API certs 相同的目录中,因此我们将只创建json并运行cfssl gencert命令,如下命令所示:

johndoe@management-vm$ cat << EOF > service-account-csr.json 
{
 "CN": "service-accounts",
 "key": {
 "algo": "rsa",
 "size": 2048
 },
 "names": [
 {
 "C": "US",
 "L": "New York",
 "O": "Kubernetes",
 "OU": "Kubernetes",
 "ST": "NY"
 }
 ]
}
EOF

johndoe@management-vm$ cfssl gencert \
 -ca=../ca.pem \
 -ca-key=../ca-key.pem \
 -config=../ca-config.json \
 -profile=kubernetes \
 service-account-csr.json | cfssljson -bare service-account

把我们的证书寄回家

生成所有证书后,是时候将它们移动到相应的节点了。Microsoft Azure 可以通过虚拟机名称在内部解析,因此我们可以轻松移动证书。

要将证书移动到kubelets,使用以下命令:

johndoe@management-vm$ cd ~/certs/kubelets

johndoe@management-vm$ scp ../ca.pem \
kube-node-1.pem \
kube-node-1-key.pem \
johndoe@kube-node-1:~/

对其余节点重复上述步骤。

要将证书移动到控制平面,请使用以下命令:

johndoe@management-vm$ cd ~/certs/api

johndoe@management-vm$ scp ../ca.pem \
../ca-key.pem \
kubernetes.pem \
kubernetes-key.pem \
service-account.pem \
service-account-key.pem \
johndoe@kube-controller-1:~/

对最后一个控制器重复上述步骤。

Kubeconfigs

为了能够与 Kubernetes 对话,您需要知道您的 API 在哪里。你还需要告诉 API 你是谁,你的凭证是什么。所有这些信息都有kubeconfigs提供。这些配置文件包含您联系群集并对其进行身份验证所需的所有信息。用户不仅将使用kubeconfig文件到达集群,他们还将使用它到达其他服务。这就是为什么我们将为每个组件和用户生成多个kubeconfig文件。

安装 kubectl

为了能够创建kubeconfig文件,我们需要kubectl。您将首先在管理虚拟机中安装kubectl来生成配置文件,但是稍后我们也将使用它来管理我们的集群。

首先,添加我们将从中获取kubectl的存储库,如下命令所示:

johndoe@management-vm$ sudo cat << EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

最后,我们使用yum进行安装,如下命令所示:

johndoe@management-vm$sudo yum install kubectl

控制平面 kubeconfigs

我们将生成的第一个 kubeconfigs 是针对我们的控制平面组件的。

为了维持秩序,我们将继续把我们的文件组织成目录。但是,我们所有的kubeconfigs都将进入同一个目录,如下命令所示:

johndoe@management-vm$ mkdir ~/kubeconfigs

johndoe@management-vm$ cd ~/kubeconfigs

创建目录后,让我们开始生成kubeconfigs

库贝-控制器-管理器

kube-controller-manager kubeconfig:

johndoe@management-vm$ kubectl config set-cluster kubernetes \
 --certificate-authority=../certs/ca.pem \
 --embed-certs=true \
 --server=https://127.0.0.1:6443 \
 --kubeconfig=kube-controller-manager.kubeconfig

johndoe@management-vm$ kubectl config set-credentials \
system:kube-controller-manager \
 --client-certificate=../certs/control-plane/kube-controller-manager.pem \
 --client-key=../certs/control-plane/kube-controller-manager-key.pem \
 --embed-certs=true \
 --kubeconfig=kube-controller-manager.kubeconfig

johndoe@management-vm$ kubectl config set-context default \
 --cluster=kubernetes \
 --user=system:kube-controller-manager \
 --kubeconfig=kube-controller-manager.kubeconfig

johndoe@management-vm$ kubectl config use-context default --kubeconfig=kube-controller-manager.kubeconfig

多维数据集计划程序

Kube-scheduler kubeconfig:

johndoe@management-vm$ kubectl config set-cluster kubernetes \
 --certificate-authority=../certs/ca.pem \
 --embed-certs=true \
 --server=https://127.0.0.1:6443 \
 --kubeconfig=kube-scheduler.kubeconfig

johndoe@management-vm$ kubectl config set-credentials system:kube-scheduler \
 --client-certificate=../certs/control-plane/kube-scheduler.pem \
 --client-key=../certs/control-plane/kube-scheduler-key.pem \
 --embed-certs=true \
 --kubeconfig=kube-scheduler.kubeconfig

johndoe@management-vm$ kubectl config set-context default \
 --cluster=kubernetes \
 --user=system:kube-scheduler \
 --kubeconfig=kube-scheduler.kubeconfig

johndoe@management-vm$ kubectl config use-context default --kubeconfig=kube-scheduler.kubeconfig

忽必烈 configs

对于我们的kubelets,我们将要求每个节点一个kubeconfig。为了让事情变得更简单,我们将创建一个 for 循环来为每个节点创建一个配置,如下面的命令所示。请注意,您需要将<KUBE_API_PUBLIC_IP>替换为您自己的公共 IP 地址:

johndoe@management-vm$ for i in 1 2; do
kubectl config set-cluster kubernetes \
--certificate-authority=../certs/ca.pem \
--embed-certs=true \
--server=https://<KUBE_API_PUBLIC_IP>:6443 \
--kubeconfig=kube-node-${i}.kubeconfig

kubectl config set-credentials system:node:kube-node-${i} \
--client-certificate=../certs/kubelets/kube-node-${i}.pem \
--client-key=../certs/kubelets/kube-node-${i}-key.pem \
--embed-certs=true \
--kubeconfig=kube-node-${i}.kubeconfig

kubectl config set-context default \
--cluster=kubernetes \
--user=system:node:kube-node-${i} \
--kubeconfig=kube-node-${i}.kubeconfig

kubectl config use-context default --kubeconfig=kube-node-${i}.kubeconfig
done

最后,我们的工作节点将需要的最后一个kubeconfigkube-proxy kubeconfig。我们将只生成一个,因为它不包含任何特定的节点配置,我们可以将相同的配置复制到所有节点。

立方体代理

kube-proxy kubeconfig:

 johndoe@management-vm$ kubectl config set-cluster kubernetes \
 --certificate-authority=../certs/ca.pem \
 --embed-certs=true \
 --server=https://<PUBLIC_IP>:6443 \
 --kubeconfig=kube-proxy.kubeconfig

johndoe@management-vm$ kubectl config set-credentials system:kube-proxy \
 --client-certificate=../certs/controllers/kube-proxy.pem \
 --client-key=../certs/controllers/kube-proxy-key.pem \
 --embed-certs=true \
 --kubeconfig=kube-proxy.kubeconfig

johndoe@management-vm$ kubectl config set-context default \
 --cluster=kubernetes \
 --user=system:kube-proxy \
 --kubeconfig=kube-proxy.kubeconfig

johndoe@management-vm$ kubectl config use-context default \ --kubeconfig=kube-proxy.kubeconfig

现在我们有了控制平面 kubeconfigs 和工作节点,我们现在将使用以下命令为管理员用户创建kubeconfig。这个kubeconfig文件是我们将用来连接到集群并管理其应用编程接口对象的文件:

johndoe@management-vm$ kubectl config set-cluster kubernetes \
 --certificate-authority=../certs/ca.pem \
 --embed-certs=true \
 --server=https://127.0.0.1:6443 \
 --kubeconfig=admin.kubeconfig

johndoe@management-vm$ kubectl config set-credentials admin \
 --client-certificate=../certs/admin/admin.pem \
 --client-key=../certs/admin/admin-key.pem \
 --embed-certs=true \
 --kubeconfig=admin.kubeconfig

johndoe@management-vm$ kubectl config set-context default \
 --cluster=kubernetes \
 --user=admin \
 --kubeconfig=admin.kubeconfig

johndoe@management-vm$ kubectl config use-context default \ --kubeconfig=admin.kubeconfig

四处移动配置

现在,我们的 kubeconfigs 需要转移到每个相应的虚拟机。为此,我们将遵循与移动证书相同的过程。

首先,让我们使用以下命令移动工作节点中的 kubeconfigs:

johndoe@management-vm$ scp kube-node-1.kubeconfig kube-proxy.kubeconfig johndoe@kube-node-1:~/

对每个节点重复。

在节点上放置好 kubeconfigs 后,我们现在可以使用以下命令移动kube-api服务器配置:

johndoe@management-vm$ scp admin.kubeconfig kube-controller-manager.kubeconfig \
kube-scheduler.kubeconfig johndoe@kube-controller-1:~/

对每个控制器重复。

安装控制平面

现在我们将安装控制平面所需的二进制文件。

和 CD

在这个设计中,我们决定在我们的kube-apiserver旁边运行etcd。我们将开始下载二进制文件并为我们的数据库配置systemd单元。

安装 etcd

是时候开始在我们的控制器节点中安装etcd集群了。要安装etcd,我们将从管理虚拟机 SSH 到每个控制器中,并运行以下程序。

我们将使用以下命令开始下载和提取二进制文件:

johndoe@kube-controller-1$ wget -O etcd.tgz \ 
https://github.com/etcd-io/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz

johndoe@kube-controller-1$ tar xzvf etcd.tgz

johndoe@kube-controller-1$ sudo mv etcd-v3.3.10-linux-amd64/etcd* /usr/local/bin/

johndoe@kube-controller-1$ sudo mkdir -p /etc/etcd /var/lib/etcd

提取二进制文件后,我们需要使用以下命令将 kubernetes API 和 CA 证书复制到我们的etcd目录中:

johndoe@kube-controller-1$ cp /home/johndoe/ca.pem \
/home/johndoe/kubernetes-key.pem \
/home/johndoe/kubernetes.pem /etc/etcd

在创建systemd单元文件之前,让我们设置一些变量,让事情变得简单一点。

前两个变量将是主机唯一的,如以下命令所示:

johndoe@kube-controller-1$ ETCD_NAME=$(hostname)

johndoe@kube-controller-1$ I_IP=192.168.0.11

下一个和最后一个变量在所有节点上都是相同的;它将包含我们每个ectd集群成员的主机名和 IP,如以下命令所示:

I_CLUSTER=kube-controller-1=https://192.168.0.11:2380,kube-controller-2=https://192.168.0.12:2380,kube-controller-3=https://192.168.0.13:2380

现在我们有了变量,让我们创建systemd单元文件,如下命令所示:

johndoe@kube-controller-1$sudo cat << EOF | sudo tee /etc/systemd/system/etcd.service
[Unit]
Description=etcd
Documentation=https://github.com/coreos

[Service]
ExecStart=/usr/local/bin/etcd \\
 --name ${ETCD_NAME} \\
 --cert-file=/etc/etcd/kubernetes.pem \\
 --key-file=/etc/etcd/kubernetes-key.pem \\
 --peer-cert-file=/etc/etcd/kubernetes.pem \\
 --peer-key-file=/etc/etcd/kubernetes-key.pem \\
 --trusted-ca-file=/etc/etcd/ca.pem \\
 --peer-trusted-ca-file=/etc/etcd/ca.pem \\
 --peer-client-cert-auth \\
 --client-cert-auth \\
 --initial-advertise-peer-urls https://${I_IP}:2380 \\
 --listen-peer-urls https://${I_IP}:2380 \\
 --listen-client-urls https://${I_IP}:2379,https://127.0.0.1:2379 \\
 --advertise-client-urls https://${I_IP}:2379 \\
 --initial-cluster-token etcd-cluster-0 \\
 --initial-cluster ${I_CLUSTER} \\
 --initial-cluster-state new \\
 --data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

现在,我们使用以下命令重新加载、启用并启动守护程序:

johndoe@kube-controller-1$ systemctl daemon-reload && \
systemctl enable etcd && \
systemctl start etcd && \
systemctl status etcd

对每个节点重复此过程后,您可以通过运行以下命令来检查群集的状态:

johndoe@kube-controller-3$ ETCDCTL_API=3 etcdctl member list \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/etcd/ca.pem \
--cert=/etc/etcd/kubernetes.pem \
--key=/etc/etcd/kubernetes-key.pem

加密 etcd 数据

API 服务器可以对etcd中存储的数据进行加密。为此,当我们创建kube-apiserver systemd单元文件时,我们将使用一个名为--experimental-encryption-provider-config的标志。但是在我们传递标志之前,我们需要创建一个包含我们的加密密钥的 YAML。

我们将只创建一个 YAML 定义,并将其复制到每个控制器节点。您应该从管理虚拟机执行此操作,以便可以轻松地将文件传输到所有控制器。让我们使用以下命令来设置它:

johndoe@management-vm$ CRYPT_KEY=$(head -c 32 /dev/urandom | base64)

输入 YAML 定义如下:

johndoe@management-vm$ cat << EOF > crypt-config.yml
kind: EncryptionConfig
apiVersion: v1
resources:
 - resources:
 - secrets
 providers:
 - aescbc:
 keys:
 - name: key1
 secret: ${CRYPT_KEY}
 - identity: {}
EOF

最后,将密钥移动到每个节点,如下所示:

johndoe@management-vm$ for i in 1 2 3; do
scp crypt-config.yml johndoe@kube-controller-${i}:~/
done

安装 Kubernetes 控制器二进制文件

现在etcd已经到位,我们可以开始安装kube-apiserverkube-controller-managerkube-scheduler了。

多维数据集 API 服务器

让我们首先进入第一个控制器节点,并使用以下命令下载所需的二进制文件:

johndoe@management-vm$ ssh johndoe@kube-controller-1

johndoe@kube-controller-1$ wget "https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-apiserver" \
"https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubectl["](https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubectl)

现在使用以下命令将二进制文件移动到/usr/local/bin/:

johndoe@kube-controller-1$ sudo mkdir -p /etc/kubernetes/config

johndoe@kube-controller-1$ sudo chmod +x kube*

johndoe@kube-controller-1$ sudo mv kube-apiserver kubectl /usr/local/bin/

接下来,我们将使用以下命令创建和移动 API 服务器工作所需的所有目录和证书:

johndoe@kube-controller-1$ sudo mkdir -p /var/lib/kubernetes/

johndoe@kube-controller-1$ sudo cp /home/johndoe/ca.pem \
/home/johndoe/ca-key.pem \
/home/johndoe/kubernetes-key.pem \
/home/johndoe/kubernetes.pem \
/home/johndoe/service-account-key.pem \
/home/johndoe/service-account.pem \
/home/johndoe/crypt-config.yml \
/var/lib/kubernetes/

在创建systemd单元文件之前,让我们使用以下命令声明一些变量:

johndoe@kube-controller-1$ I_IP=192.168.0.11

johndoe@kube-controller-1$ CON1_IP=192.168.0.11

johndoe@kube-controller-1$ CON2_IP=192.168.0.12

johndoe@kube-controller-1$ CON2_IP=192.168.0.13

只有I_IP变量在每个节点上是唯一的,它将取决于您正在执行该过程的节点的 IP。其他三个在所有节点上都是相同的。

现在变量已经设置好了,我们可以开始创建单元文件,如下命令所示:

johndoe@kube-controller-1$ sudo cat << EOF | sudo tee /etc/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-apiserver \\
 --advertise-address=${I_IP} \\
 --allow-privileged=true \\
 --apiserver-count=3 \\
 --audit-log-maxage=30 \\
 --audit-log-maxbackup=3 \\
 --audit-log-maxsize=100 \\
 --audit-log-path=/var/log/audit.log \\
 --authorization-mode=Node,RBAC \\
 --bind-address=0.0.0.0 \\
 --client-ca-file=/var/lib/kubernetes/ca.pem \\
 --enable-admission-plugins=Initializers,NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \\
 --enable-swagger-ui=true \\
 --etcd-cafile=/var/lib/kubernetes/ca.pem \\
 --etcd-certfile=/var/lib/kubernetes/kubernetes.pem \\
 --etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \\
 --etcd-servers=https://$CON1_IP:2379,https://$CON2_IP:2379 \\
 --event-ttl=1h \\
 --experimental-encryption-provider-config=/var/lib/kubernetes/crypt-config.yml \\
 --kubelet-certificate-authority=/var/lib/kubernetes/ca.pem \\
 --kubelet-client-certificate=/var/lib/kubernetes/kubernetes.pem \\
 --kubelet-client-key=/var/lib/kubernetes/kubernetes-key.pem \\
 --kubelet-https=true \\
 --runtime-config=api/all \\
 --service-account-key-file=/var/lib/kubernetes/service-account.pem \\
 --service-cluster-ip-range=10.20.0.0/24 \\
 --service-node-port-range=30000-32767 \\
 --tls-cert-file=/var/lib/kubernetes/kubernetes.pem \\
 --tls-private-key-file=/var/lib/kubernetes/kubernetes-key.pem \\
 --v=2 \\
 --kubelet-preferred-address-types=InternalIP,InternalDNS,Hostname,ExternalIP,ExternalDNS
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

库贝-控制器-管理器

要安装kube-controller-manager,步骤将非常相似,只是此时我们将开始使用 kubeconfigs。

首先,使用以下命令下载kube-controller-manager:

johndoe@kube-controller-1$ wget "https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-controller-manager"

johndoe@kube-controller-1$sudo chmod +x kube-controller-manager

johndoe@kube-controller-1$sudo mv kube-controller-manager /usr/local/bin/

使用以下命令移动kubeconfig并为kube-controller-manager创建单位文件:

johndoe@kube-controller-1$ sudo cp \
/home/johndoe/kube-controller-manager.kubeconfig /var/lib/kubernetes/

johndoe@kube-controller-1$ cat << EOF | sudo tee \ /etc/systemd/system/kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-controller-manager \\
 --address=0.0.0.0 \\
 --cluster-cidr=10.30.0.0/16 \\
 --cluster-name=kubernetes \\
 --cluster-signing-cert-file=/var/lib/kubernetes/ca.pem \\
 --cluster-signing-key-file=/var/lib/kubernetes/ca-key.pem \\
 --kubeconfig=/var/lib/kubernetes/kube-controller-manager.kubeconfig \\
 --leader-elect=true \\
 --root-ca-file=/var/lib/kubernetes/ca.pem \\
 --service-account-private-key-file=/var/lib/kubernetes/service-account-key.pem \\
 --service-cluster-ip-range=10.20.0.0/24 \\
 --use-service-account-credentials=true \\
 --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

多维数据集计划程序

最后安装在控制平面的部件是kube-scheduler。有了调度器,除了创建systemd单元文件,我们还将创建一个包含调度器基本配置的 YAML 文件。

首先,让我们下载二进制文件。使用以下命令下载kube-scheduler并将其移动到/usr/local/bin/:

johndoe@kube-controller-1$ wget \
"https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-scheduler"

johndoe@kube-controller-1$ chmod +x kube-scheduler

johndoe@kube-controller-1$ sudo mv kube-scheduler /usr/local/bin/

我们使用以下命令将kubeconfig文件移动到kubernetes文件夹:

johndoe@kube-controller-1$sudo cp /home/johndoe/kube-scheduler.kubeconfig /var/lib/kubernetes/

kube-scheduler.yml给出如下:

johndoe@kube-controller-1$sudo cat << EOF | sudo tee /etc/kubernetes/config/kube-scheduler.yml
apiVersion: componentconfig/v1alpha1
kind: KubeSchedulerConfiguration
clientConnection:
 kubeconfig: "/var/lib/kubernetes/kube-scheduler.kubeconfig"
leaderElection:
 leaderElect: true
EOF

kube-scheduler.service给出如下:

johndoe@kube-controller-1$ sudo cat << EOF | sudo tee /etc/systemd/system/kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
ExecStart=/usr/local/bin/kube-scheduler \\
 --config=/etc/kubernetes/config/kube-scheduler.yml \\
 --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

在继续下一步之前,在每个控制器节点上重复安装控制平面部分中的所有步骤。

启动控制平面

在每个控制器节点上完成每个组件的安装后,我们就可以开始测试服务了。

为此,我们将首先使用以下命令启用并启动所有systemd单元:

johndoe@kube-controller-1$ sudo systemctl daemon-reload

johndoe@kube-controller-1$ sudo systemctl enable kube-apiserver kube-controller-manager kube-scheduler

johndoe@kube-controller-1$ sudo systemctl start kube-apiserver kube-controller-manager kube-scheduler

johndoe@kube-controller-1$ sudo systemctl status kube-apiserver kube-controller-manager kube-scheduler

最后,为了能够自己使用kubectl,我们需要设置我们想要连接的集群的上下文,并将kubeconfig admin 设置为我们的默认设置。我们的kubeconfig管理员目前被设置为指向localhost作为kube-apiserver端点。这暂时没问题,因为我们只想测试我们的组件。

在您的kube-controller-1中输入以下命令:

johndoe@kube-controller-1$ mkdir /home/johndoe/.kube/

johndoe@kube-controller-1$ cat /home/johndoe/admin.kubeconfig > /home/johndoe/.kube/config

johndoe@kube-controller-1$ kubectl get cs

输出应该如下所示:

NAME                       STATUS     MESSAGE              ERROR
controller-manager         Healthy     ok
scheduler                  Healthy     ok
etcd-0                     Healthy     {"health": "true"}
etcd-1                     Healthy     {"health": "true"}
etcd-2                     Healthy     {"health": "true"}

正在为 kubelets 设置 RBAC 权限。

我们的应用编程接口服务器需要权限才能与kubelets应用编程接口对话。为了实现这一点,我们创建将绑定到 Kubernetes 用户的集群角色。我们将只在一个控制器节点上这样做,因为我们将使用kubectl,并且更改将应用于整个集群。

集群角色

使用以下命令创建包含权限的群集角色:

johndoe@kube-controller-1$ cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
 annotations:
 rbac.authorization.kubernetes.io/autoupdate: "true"
 labels:
 kubernetes.io/bootstrapping: rbac-defaults
 name: system:kube-apiserver-to-kubelet
rules:
 - apiGroups:
 - ""
 resources:
 - nodes/proxy
 - nodes/stats
 - nodes/log
 - nodes/spec
 - nodes/metrics
 verbs:
 - "*"
EOF

群集角色绑定

现在使用以下命令将角色绑定到 Kubernetes 用户:

johndoe@kube-controller-1$ cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
 name: system:kube-apiserver
 namespace: ""
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: ClusterRole
 name: system:kube-apiserver-to-kubelet
subjects:
 - apiGroup: rbac.authorization.k8s.io
 kind: User
 name: kubernetes
EOF

负载平衡器设置

我们需要对所有 kube 控制器节点的请求进行负载平衡。因为我们在云上运行,所以我们可以创建一个负载平衡器对象,它将在我们所有的节点上对请求进行负载平衡。不仅如此,我们还可以配置健康探测器来监控控制器节点的状态,看它们是否可以接收请求。

创建负载平衡器

负载均衡器是我们一直保存公共 IP 的目的。LB 将成为我们从外部访问集群的入口。我们将需要创建健康检查端口80的规则,并将kubectl请求重定向到6443

让我们通过以下步骤来实现这一点。

Azure 负载平衡器

我们将不得不返回安装了 Azure CLI 的工作站,完成下一组步骤。

要在工作站中创建负载平衡器并为其分配公共 IP,请运行以下命令:

az network lb create -n kube-lb \
--sku Standard \
--public-ip-address kube-api-pub-ip

既然我们已经创建了负载平衡器,我们还需要配置三个东西:

  • 后端池
  • 健康探测器
  • 负载平衡规则

后端池

到目前为止,我们已经通过 Azure CLI 完成了与 Azure 相关的所有工作。让我们通过 Azure 门户完成以下步骤,以便您也能熟悉门户:

要创建后端池,请导航到 kube-lb 对象,如下图所示:

当您在负载平衡器对象中时,导航到后端池并单击添加,如下图所示:

当您单击添加时,将出现一个菜单。命名您的后端池kube-lb-backend,并确保您选择了所有 kube 控制器节点及其各自的 IP,如下图所示:

Example

单击添加完成。我们已成功设置后端虚拟机。

健康探测器

在我们可以创建负载平衡规则之前,我们需要创建健康探测器,它将告诉我们的 LB 哪些节点可以接收流量。因为在编写本章时,Azure 中的负载平衡器不支持 HTTPS 健康探测器,所以我们需要通过 HTTP 公开/healthz端点。为此,我们将在控制器节点中安装 Nginx,并将来自端口80的代理请求传递到端口6443

SSH 回到您的控制器节点,并在每个节点中执行以下步骤:

johndoe@kube-controller-1$ sudo yum install epel-release && yum install nginx

一旦安装了 Nginx,用以下内容替换/etc/nginx/nginx.conf中的server条目:

server {
 listen 80;
 server_name kubernetes.default.svc.cluster.local;

 location /healthz {
 proxy_pass https://127.0.0.1:6443/healthz;
 proxy_ssl_trusted_certificate /var/lib/kubernetes/ca.pem;
 }
}

因为我们运行的是基于 RHEL 的发行版,所以 SELINUX 默认情况下是启用的;因此,它将阻止 Nginx 访问端口6443上的 TCP 套接字。为了允许这种行为,我们需要运行以下命令。

首先,我们安装管理 SELINUX 所需的包,如以下命令所示:

johndoe@kube-controller-1$ sudo yum install policycoreutils-python

一旦软件包安装完毕,我们运行以下命令以允许连接到端口6443:

johndoe@kube-controller-1$ sudo semanage port -a -t http_port_t -p tcp 6443

最后,我们使用以下命令启动nginx:

johndoe@kube-controller-1$ sudo systemctl daemon-reload && \
systemctl enable nginx --now

如果你想测试这个,你总是可以在localhost上运行一个curl,就像这样:

johndoe@kube-controller-1$ curl -v http://localhost/healthz

如果一切配置正确,将生成以下输出:

* About to connect() to localhost port 80 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /healthz HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost
> Accept: */* < HTTP/1.1 200 OK
< Server: nginx/1.12.2
< Date: Sun, 28 Oct 2018 05:44:35 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 2
< Connection: keep-alive
<
* Connection #0 to host localhost left intact
Ok

请记住对每个控制器节点重复所有这些过程。

既然健康端点已经公开,我们就可以在负载平衡器中创建健康探测规则了。

回到kube-lb菜单,在设置下——我们配置后端池的地方——选择健康探测器,然后点击添加。

菜单出现后,填写字段,如下图所示:

负载平衡规则

我们已经准备好创建负载平衡规则,并准备好使用我们的负载平衡器。

这个过程与我们使用后端池和健康探测器的过程相同。转到 kube-lb 下的设置菜单,并选择负载平衡规则。点击添加并填写出现的对话框,如下图所示:

一旦准备好了,我们只需要打开我们的网络安全组,允许端口6443上的连接。

在您的 Azure CLI 工作站上,运行以下命令来创建规则:

az network nsg rule create --nsg-name kube-nsg \
 -n pub_https_allow \
 --direction Inbound \
 --priority 110 \
 --access Allow \
 --description "Allow HTTPS" \
 --destination-address-prefixes '*' \
 --destination-port-ranges 6443 \
 --protocol Tcp \
 --source-address-prefixes '*' \
 --source-port-ranges '*' \
 --direction Inbound

几分钟后生效,然后在浏览器中导航至https://<LB_IP>:6443/version

您应该会看到如下内容:

{
 "major": "1",
 "minor": "12",
 "gitVersion": "v1.12.0",
 "gitCommit": "0ed33881dc4355495f623c6f22e7dd0b7632b7c0",
 "gitTreeState": "clean",
 "buildDate": "2018-09-27T16:55:41Z",
 "goVersion": "go1.10.4",
 "compiler": "gc",
 "platform": "linux/amd64"
}

这将表明您可以通过 LB 访问应用编程接口服务器。

工作节点设置

是时候配置和安装我们的工作节点了。在这些中,我们将安装kubelet、kube 代理、容器运行时和容器网络接口插件。

SSH 进入管理虚拟机的第一个工作节点,如以下命令所示:

johndoe@management-vm$ ssh johndoe@kube-node-1

下载和准备二进制文件

在配置任何服务之前,我们需要下载任何依赖项并设置所需的存储库。之后,我们可以开始下载二进制文件,并将它们移动到各自的位置。

添加 Kubernetes 存储库

我们需要配置的存储库是 Kubernetes 存储库。有了这个,我们就可以下载kubectl。让我们使用以下命令来设置它:

johndoe@kube-node-1$ sudo cat << EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

安装依赖项和 kubectl

配置好repo后,我们就可以开始下载kubectl以及我们将要下载的二进制文件所需的任何依赖项。让我们使用以下命令来设置它:

johndoe@kube-node-1$ sudo yum install -y kubectl socat conntrack ipset libseccomp

下载和存储工人二进制文件

现在我们已经准备好了依赖项,我们可以使用以下命令下载所需的工作二进制文件:

johndoe@kube-node-1$ wget \
https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.12.0/crictl-v1.12.0-linux-amd64.tar.gz \
https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubelet \
https://github.com/containernetworking/plugins/releases/download/v0.6.0/cni-plugins-amd64-v0.6.0.tgz \
https://github.com/opencontainers/runc/releases/download/v1.0.0-rc5/runc.amd64 \
https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-proxy \
https://github.com/containerd/containerd/releases/download/v1.1.2/containerd-1.1.2.linux-amd64.tar.gz

现在,让我们使用以下命令为最近下载的二进制文件创建文件夹结构:

johndoe@kube-node-1$ sudo mkdir -p \
/etc/cni/net.d \
/opt/cni/bin \
/var/lib/kube-proxy \
/var/lib/kubelet \
/var/lib/kubernetes \
/var/run/kubernetes

为了使用方便和符合惯例,我们将名称改为runc,如下命令所示:

johndoe@kube-node-1$ mv runc.amd64 runc

我们使用以下命令向其余二进制文件授予可执行权限:

johndoe@kube-node-1$ chmod +x kube-proxy kubelet runc

在赋予它们可执行权限后,我们可以使用以下命令将它们移动到/usr/local/bin/:

johndoe@kube-node-1$ sudo mv kube-proxy kubelet runc /usr/local/bin/

一些下载的文件是 TAR 档案,我们需要将其untar并使用以下命令存储在它们各自的位置:

johndoe@kube-node-1$ tar xvzf crictl-v1.12.0-linux-amd64.tar.gz

johndoe@kube-node-1$ sudo mv crictl /usr/local/bin/

johndoe@kube-node-1$ sudo tar xvzf cni-plugins-amd64-v0.6.0.tgz -C /opt/cni/bin/

johndoe@kube-node-1$ tar xvzf containerd-1.1.2.linux-amd64.tar.gz

johndoe@kube-node-1$ sudo mv ./bin/* /bin/

容器设置

我们现在准备开始配置每个服务。第一个是containerd

让我们使用以下命令创建配置目录:

johndoe@kube-node-1$ sudo mkdir -p /etc/containerd/

现在我们创建toml配置文件,它将告诉containerd使用什么容器运行时。让我们使用以下命令来设置它:

johndoe@kube-node-1$ sudo cat << EOF | sudo tee /etc/containerd/config.toml
[plugins]
[plugins.cri.containerd]
snapshotter = "overlayfs"
[plugins.cri.containerd.default_runtime]
runtime_type = "io.containerd.runtime.v1.linux"
runtime_engine = "/usr/local/bin/runc"
runtime_root = ""
EOF

最后,让我们使用以下命令设置systemd单元文件:

johndoe@kube-node-1$ sudo cat << EOF | sudo tee /etc/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target

[Service]
ExecStartPre=/sbin/modprobe overlay
ExecStart=/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
OOMScoreAdjust=-999
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity

[Install]
WantedBy=multi-user.target
EOF

库布雷人

我们在工人节点的主要服务是kubelet。让我们创建它的配置文件。

首先,我们需要使用以下命令将kubelet证书移动到它们的位置:

johndoe@kube-node-1$ sudo mv /home/johndoe/${HOSTNAME}-key.pem /home/johndoe/${HOSTNAME}.pem /var/lib/kubelet/

johndoe@kube-node-1$ sudo mv /home/johndoe/${HOSTNAME}.kubeconfig /var/lib/kubelet/kubeconfig

johndoe@kube-node-1$ sudo mv /home/johndoe/ca.pem /var/lib/kubernetes/

现在我们创建 YAML 配置文件,它将包含诸如 DNS 服务器 IP 地址、集群域和证书文件的位置等内容。让我们使用以下命令来设置它:

johndoe@kube-node-1$ sudo cat << EOF | sudo tee /var/lib/kubelet/kubelet-config.yaml
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
 anonymous:
 enabled: false
 webhook:
 enabled: true
 x509:
 clientCAFile: "/var/lib/kubernetes/ca.pem"
authorization:
 mode: Webhook
clusterDomain: "cluster.local"
clusterDNS: 
 - "10.20.0.10"
runtimeRequestTimeout: "15m"
tlsCertFile: "/var/lib/kubelet/${HOSTNAME}.pem"
tlsPrivateKeyFile: "/var/lib/kubelet/${HOSTNAME}-key.pem"
EOF

最后,我们使用以下命令创建服务单元文件:

johndoe@kube-node-1$ sudo cat << EOF | sudo tee /etc/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=containerd.service
Requires=containerd.service

[Service]
ExecStart=/usr/local/bin/kubelet \\
 --config=/var/lib/kubelet/kubelet-config.yaml \\
 --container-runtime=remote \\
 --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \\
 --image-pull-progress-deadline=2m \\
 --kubeconfig=/var/lib/kubelet/kubeconfig \\
 --network-plugin=cni \\
 --register-node=true \\
 --v=2 \\
 --hostname-override=${HOSTNAME} \\
 --allow-privileged=true
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

立方体代理

下一个要创建的服务是kube-proxy

我们使用以下命令移动先前创建的kubeconfigs:

johndoe@kube-node-1$ sudo mv /home/johndoe/kube-proxy.kubeconfig /var/lib/kube-proxy/kubeconfig

kubelet一样,kube-proxy也需要一个配置YAML,该配置具有集群 CIDR 和kube-proxy将运行的模式。让我们使用以下命令来设置它:

johndoe@kube-node-1$ sudo cat << EOF | sudo tee /var/lib/kube-proxy/kube-proxy-config.yaml
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
clientConnection:
 kubeconfig: "/var/lib/kube-proxy/kubeconfig"
mode: "iptables"
clusterCIDR: "10.30.0.0/16"
EOF

最后,我们使用以下命令为kube-proxy创建一个单位文件:

johndoe@kube-node-1$ sudo cat << EOF | sudo tee /etc/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-proxy \\
 --config=/var/lib/kube-proxy/kube-proxy-config.yaml
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

启动服务

在所有 kube 节点上完成这些过程后,可以使用以下命令在每个节点上启动服务:

johndoe@kube-node-1$ sudo systemctl daemon-reload && \
systemctl enable containerd kubelet kube-proxy && \
systemctl start containerd kubelet kube-proxy && \
systemctl status containerd kubelet kube-proxy

不可思议的网络

我们在集群中还有几件事要做:我们需要安装一个网络提供商并配置域名系统。

准备好节点

我们的节点必须能够转发数据包,这样我们的吊舱才能与外界通话。Azure 虚拟机没有现成的 IP 转发功能,因此我们必须手动启用。

为此,请转到您的 Azure CLI 工作站并运行以下命令:

for i in 1 2; do 
az network nic update \
-n $(az vm show --name kube-node-${i} --query [networkProfile.networkInterfaces[*].id] --output tsv | sed 's:.*/::') \
--ip-forwarding true
done

这将在虚拟机的网卡上启用 IP 转发功能。

现在我们必须在工作节点上启用 IP 转发内核参数。

通过 SSH 从管理虚拟机进入每个工作节点,并使用以下命令启用 IPv4 转发:

johndoe@kube-node-1$ sudo sysctl net.ipv4.conf.all.forwarding=1

johndoe@kube-node-1$ sudo echo "net.ipv4.conf.all.forwarding=1" | tee -a /etc/sysctl.conf

配置远程访问

现在,为了从您的管理虚拟机运行kubectl命令,我们需要创建一个kubeconfig,它使用管理证书和我们集群的公共 IP 地址。让我们使用以下命令来设置它:

johndoe@management-vm$ kubectl config set-cluster kube \
 --certificate-authority=/home/johndoe/certs/ca.pem \
 --embed-certs=true \
 --server=https://104.45.174.96:6443

johndoe@management-vm$ kubectl config set-credentials admin \
 --client-certificate=/home/johndoe/certs/admin/admin.pem \
 --client-key=~/certs/admin/admin-key.pem

johndoe@management-vm$ kubectl config set-context kube \
 --cluster=kube \
 --user=admin

johndoe@management-vm$ kubectl config use-context kube

安装编织网

配置了管理虚拟机上的远程访问后,我们现在可以运行kubectl命令,而无需登录控制器节点。

要安装编织网,请从管理虚拟机运行以下kubectl命令:

johndoe@management-vm$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')&env.IPALLOC_RANGE=10.30.0.0/16"

随着编织网的安装,现在我们的豆荚将有知识产权分配。

DNS 服务器

现在我们将提供我们的域名系统服务器,它将由核心域名系统提供,这是一个基于插件的开源域名系统服务器。让我们使用以下命令来设置它:

johndoe@management-vm$ kubectl create -f https://raw.githubusercontent.com/dsalamancaMS/CoreDNSforKube/master/coredns.yaml

使用以下命令检查域名系统盒:

johndoe@management-vm$  kubectl get pods -n kube-system

随着域名系统服务器吊舱的创建,我们已经成功完成了我们的 Kubernetes 集群的安装。如果需要,您可以创建以下部署来再次测试群集:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deployment
 labels:
 app: nginx
spec:
 replicas: 3
 selector:
 matchLabels:
 app: nginx
 template:
 metadata:
 labels:
 app: nginx
 spec:
 containers:
 - name: nginx
 image: nginx:1.7.9
 ports:
 - containerPort: 80

现在,我们已经看到了从头开始创建集群所需的步骤,我想谈一谈托管 Kubernetes 解决方案。

管理云上的 Kubernetes

正如您在本章中看到的那样,安装并使 Kubernetes 集群可用并准备投入生产是一个非常漫长而复杂的过程。如果任何一步出错,您的整个部署可能都没有用。正因为如此,许多云提供商都在提供托管的 Kubernetes 解决方案——某种程度上是 Kubernetes 即服务。在这种类型的托管解决方案中,云提供商或服务提供商将管理集群的主节点,包括所有的 Kubernetes 控制器、API 服务器,甚至etcd数据库。这是一个主要优势,因为使用托管服务意味着您不必担心主节点的维护,因此您不必担心以下问题:

  • 续订 SSL 证书
  • 更新/升级etcd数据库
  • 更新/升级每个主节点二进制文件
  • 向集群注册额外的节点
  • 出现问题时缺乏支持
  • 与云基础设施的透明集成
  • 操作系统修补和维护

通过忘记这些,我们可以专注于重要的事情,例如在我们的集群上配置 pod 和创建工作负载。有了托管服务,学习曲线大大缩短,因为我们的员工可以主要关注 Kubernetes 的功能,而不是它如何工作,以便维护它。

在撰写本文时,一些值得一提的托管 Kubernetes 服务来自以下三大云提供商:

  • 蔚蓝库伯内斯服务 ( AKS )
  • 亚马逊网络服务库本内斯弹性容器服务 ( EKS )
  • 谷歌库引擎 ( GKE

除了托管的 Kubernetes 服务,还有几个基于 Kubernetes 的开源项目和非开源项目。这些项目不是完全被管理的,而是在后端使用 Kubernetes 来实现它们的目标。以下是一些比较知名的项目:

  • 红帽的上游社区项目
  • Red Hat OpenShift
  • SUSE 集装箱即服务(Caas)T5】平台
  • 中间层 Kubernetes 发动机

摘要

在本章中,我们学习了配置 Kubernetes 集群的基本步骤。我们还学习了 Azure 命令行界面以及如何在 Azure 中调配资源。我们还在整个部署中尝试了不同的工具,例如 CFSSL 和 Nginx。

我们了解并提供了kubectl配置文件,使我们能够访问我们的集群,并部署了一个虚拟部署来测试我们的集群。最后,我们研究了运行托管集群的好处,以及在主要公共云提供商中可以找到的不同类型的托管服务。

下一章将解释每个组件的功能。读者将了解不同的组件及其用途。

问题

  1. 你怎么安装忽必烈?
  2. 什么是kubeconfig
  3. 我们如何创建 SSL 证书?
  4. 什么是 AKS?
  5. 我们如何使用 Azure 命令行界面?
  6. 我们如何在 Azure 中配置资源组?
  7. 我们如何安装etcd

进一步阅读

参考书目/来源: