使用部署工具安装 Kubernetes
1 - 使用 kubeadm 引导集群
1.1 - 安装 kubeadm
本页面显示如何安装 kubeadm
工具箱。
有关在执行此安装过程后如何使用 kubeadm 创建集群的信息,请参见
使用 kubeadm 创建集群 页面。
准备开始
- 一台兼容的 Linux 主机。Kubernetes 项目为基于 Debian 和 Red Hat 的 Linux 发行版以及一些不提供包管理器的发行版提供通用的指令
- 每台机器 2 GB 或更多的 RAM (如果少于这个数字将会影响你应用的运行内存)
- 2 CPU 核或更多
- 集群中的所有机器的网络彼此均能相互连接(公网和内网都可以)
- 节点之中不可以有重复的主机名、MAC 地址或 product_uuid。请参见这里了解更多详细信息。
- 开启机器上的某些端口。请参见这里 了解更多详细信息。
- 禁用交换分区。为了保证 kubelet 正常工作,你 必须 禁用交换分区。
确保每个节点上 MAC 地址和 product_uuid 的唯一性
- 你可以使用命令
ip link
或ifconfig -a
来获取网络接口的 MAC 地址 - 可以使用
sudo cat /sys/class/dmi/id/product_uuid
命令对 product_uuid 校验
一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。 Kubernetes 使用这些值来唯一确定集群中的节点。 如果这些值在每个节点上不唯一,可能会导致安装 失败。
检查网络适配器
如果你有一个以上的网络适配器,同时你的 Kubernetes 组件通过默认路由不可达,我们建议你预先添加 IP 路由规则,这样 Kubernetes 集群就可以通过对应的适配器完成连接。
允许 iptables 检查桥接流量
确保 br_netfilter
模块被加载。这一操作可以通过运行 lsmod | grep br_netfilter
来完成。若要显式加载该模块,可执行 sudo modprobe br_netfilter
。
为了让你的 Linux 节点上的 iptables 能够正确地查看桥接流量,你需要确保在你的
sysctl
配置中将 net.bridge.bridge-nf-call-iptables
设置为 1。例如:
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system
更多的相关细节可查看网络插件需求页面。
检查所需端口
控制平面节点
协议 | 方向 | 端口范围 | 作用 | 使用者 |
---|---|---|---|---|
TCP | 入站 | 6443 | Kubernetes API 服务器 | 所有组件 |
TCP | 入站 | 2379-2380 | etcd 服务器客户端 API | kube-apiserver, etcd |
TCP | 入站 | 10250 | Kubelet API | kubelet 自身、控制平面组件 |
TCP | 入站 | 10251 | kube-scheduler | kube-scheduler 自身 |
TCP | 入站 | 10252 | kube-controller-manager | kube-controller-manager 自身 |
工作节点
协议 | 方向 | 端口范围 | 作用 | 使用者 |
---|---|---|---|---|
TCP | 入站 | 10250 | Kubelet API | kubelet 自身、控制平面组件 |
TCP | 入站 | 30000-32767 | NodePort 服务† | 所有组件 |
† NodePort 服务 的默认端口范围。
使用 * 标记的任意端口号都可以被覆盖,所以你需要保证所定制的端口是开放的。
虽然控制平面节点已经包含了 etcd 的端口,你也可以使用自定义的外部 etcd 集群,或是指定自定义端口。
你使用的 Pod 网络插件 (见下) 也可能需要某些特定端口开启。由于各个 Pod 网络插件都有所不同, 请参阅他们各自文档中对端口的要求。
安装 runtime
为了在 Pod 中运行容器,Kubernetes 使用 容器运行时(Container Runtime)。
默认情况下,Kubernetes 使用 容器运行时接口(Container Runtime Interface,CRI) 来与你所选择的容器运行时交互。
如果你不指定运行时,则 kubeadm 会自动尝试检测到系统上已经安装的运行时, 方法是扫描一组众所周知的 Unix 域套接字。 下面的表格列举了一些容器运行时及其对应的套接字路径:
运行时 | 域套接字 |
---|---|
Docker | /var/run/dockershim.sock |
containerd | /run/containerd/containerd.sock |
CRI-O | /var/run/crio/crio.sock |
如果同时检测到 Docker 和 containerd,则优先选择 Docker。 这是必然的,因为 Docker 18.09 附带了 containerd 并且两者都是可以检测到的, 即使你仅安装了 Docker。 如果检测到其他两个或多个运行时,kubeadm 输出错误信息并退出。
kubelet 通过内置的 dockershim
CRI 实现与 Docker 集成。
参阅容器运行时 以了解更多信息。
安装 kubeadm、kubelet 和 kubectl
你需要在每台机器上安装以下的软件包:
kubeadm
:用来初始化集群的指令。kubelet
:在集群中的每个节点上用来启动 Pod 和容器等。kubectl
:用来与集群通信的命令行工具。
kubeadm 不能 帮你安装或者管理 kubelet
或 kubectl
,所以你需要
确保它们与通过 kubeadm 安装的控制平面的版本相匹配。
如果不这样做,则存在发生版本偏差的风险,可能会导致一些预料之外的错误和问题。
然而,控制平面与 kubelet 间的相差一个次要版本不一致是支持的,但 kubelet
的版本不可以超过 API 服务器的版本。
例如,1.7.0 版本的 kubelet 可以完全兼容 1.8.0 版本的 API 服务器,反之则不可以。
有关安装 kubectl
的信息,请参阅安装和设置 kubectl文档。
警告:这些指南不包括系统升级时使用的所有 Kubernetes 程序包。这是因为 kubeadm 和 Kubernetes 有特殊的升级注意事项。
关于版本偏差的更多信息,请参阅以下文档:
- Kubernetes 版本与版本间的偏差策略
- Kubeadm 特定的版本偏差策略
更新
apt
包索引并安装使用 Kubernetesapt
仓库所需要的包:sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl
下载 Google Cloud 公开签名秘钥:
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
添加 Kubernetes
apt
仓库:echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
更新
apt
包索引,安装 kubelet、kubeadm 和 kubectl,并锁定其版本:sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
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
exclude=kubelet kubeadm kubectl
EOF
# 将 SELinux 设置为 permissive 模式(相当于将其禁用)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
请注意:
通过运行命令
setenforce 0
和sed ...
将 SELinux 设置为 permissive 模式 可以有效地将其禁用。 这是允许容器访问主机文件系统所必需的,而这些操作时为了例如 Pod 网络工作正常。你必须这么做,直到 kubelet 做出对 SELinux 的支持进行升级为止。
如果你知道如何配置 SELinux 则可以将其保持启用状态,但可能需要设定 kubeadm 不支持的部分配置
安装 CNI 插件(大多数 Pod 网络都需要):
CNI_VERSION="v0.8.2"
sudo mkdir -p /opt/cni/bin
curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-amd64-${CNI_VERSION}.tgz" | sudo tar -C /opt/cni/bin -xz
定义要下载命令文件的目录。
说明:
DOWNLOAD_DIR
变量必须被设置为一个可写入的目录。 如果你在运行 Flatcar Container Linux,可将DOWNLOAD_DIR
设置为/opt/bin
。
DOWNLOAD_DIR=/usr/local/bin
sudo mkdir -p $DOWNLOAD_DIR
安装 crictl(kubeadm/kubelet 容器运行时接口(CRI)所需)
CRICTL_VERSION="v1.17.0"
curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-amd64.tar.gz" | sudo tar -C $DOWNLOAD_DIR -xz
安装 kubeadm
、kubelet
、kubectl
并添加 kubelet
系统服务:
RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
cd $DOWNLOAD_DIR
sudo curl -L --remote-name-all https://storage.googleapis.com/kubernetes-release/release/${RELEASE}/bin/linux/amd64/{kubeadm,kubelet,kubectl}
sudo chmod +x {kubeadm,kubelet,kubectl}
RELEASE_VERSION="v0.4.0"
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubelet/lib/systemd/system/kubelet.service" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /etc/systemd/system/kubelet.service
sudo mkdir -p /etc/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
激活并启动 kubelet
:
systemctl enable --now kubelet
说明:Flatcar Container Linux 发行版会将
/usr/
目录挂载为一个只读文件系统。 在启动引导你的集群之前,你需要执行一些额外的操作来配置一个可写入的目录。 参见 kubeadm 故障排查指南 以了解如何配置一个可写入的目录。
kubelet 现在每隔几秒就会重启,因为它陷入了一个等待 kubeadm 指令的死循环。
在控制平面节点上配置 kubelet 使用的 cgroup 驱动程序
使用 Docker 时,kubeadm 会自动为其检测 cgroup 驱动并在运行时对
/var/lib/kubelet/kubeadm-flags.env
文件进行配置。
如果你在使用不同的 CRI,你必须为 kubeadm init
传递 cgroupDriver
值,像这样:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: <value>
进一步的相关细节,可参阅 使用配置文件来执行 kubeadm init 以及 KubeletConfiguration。
请注意,你只需要在你的 cgroup 驱动程序不是 cgroupfs
时这么做,
因为它已经是 kubelet 中的默认值。
说明:由于 kubelet 已经弃用了
--cgroup-driver
标志,如果你在配置文件/var/lib/kubelet/kubeadm-flags.env
或者/etc/default/kubelet
(对于 RPM 而言是/etc/sysconfig/kubelet
)包含此设置,请将其删除 并使用 KubeletConfiguration 作为替代(默认存储于/var/lib/kubelet/config.yaml
文件中)。
自动检测其他容器运行时(例如 CRI-O 和 containerd)的 cgroup 驱动的相关 工作扔在进行中。
故障排查
如果你在使用 kubeadm 时遇到困难,请参阅我们的 故障排查文档。
接下来
1.2 - 对 kubeadm 进行故障排查
与任何程序一样,你可能会在安装或者运行 kubeadm 时遇到错误。 本文列举了一些常见的故障场景,并提供可帮助你理解和解决这些问题的步骤。
如果你的问题未在下面列出,请执行以下步骤:
如果你认为问题是 kubeadm 的错误:
- 转到 github.com/kubernetes/kubeadm 并搜索存在的问题。
- 如果没有问题,请 打开 并遵循问题模板。
如果你对 kubeadm 的工作方式有疑问,可以在 Slack 上的 #kubeadm 频道提问, 或者在 StackOverflow 上提问。 请加入相关标签,例如
#kubernetes
和#kubeadm
,这样其他人可以帮助你。
在安装过程中没有找到 ebtables
或者其他类似的可执行文件
如果在运行 kubeadm init
命令时,遇到以下的警告
[preflight] WARNING: ebtables not found in system path
[preflight] WARNING: ethtool not found in system path
那么或许在你的节点上缺失 ebtables
、ethtool
或者类似的可执行文件。
你可以使用以下命令安装它们:
- 对于 Ubuntu/Debian 用户,运行
apt install ebtables ethtool
命令。 - 对于 CentOS/Fedora 用户,运行
yum install ebtables ethtool
命令。
在安装过程中,kubeadm 一直等待控制平面就绪
如果你注意到 kubeadm init
在打印以下行后挂起:
[apiclient] Created API client, waiting for the control plane to become ready
这可能是由许多问题引起的。最常见的是:
网络连接问题。在继续之前,请检查你的计算机是否具有全部联通的网络连接。
kubelet 的默认 cgroup 驱动程序配置不同于 Docker 使用的配置。 检查系统日志文件 (例如
/var/log/message
) 或检查journalctl -u kubelet
的输出。 如果你看见以下内容:error: failed to run Kubelet: failed to create kubelet: misconfiguration: kubelet cgroup driver: "systemd" is different from docker cgroup driver: "cgroupfs"
有两种常见方法可解决 cgroup 驱动程序问题:
按照 此处 的说明再次安装 Docker。
更改 kubelet 配置以手动匹配 Docker cgroup 驱动程序,你可以参考 在主节点上配置 kubelet 要使用的 cgroup 驱动程序
控制平面上的 Docker 容器持续进入崩溃状态或(因其他原因)挂起。你可以运行
docker ps
命令来检查以及docker logs
命令来检视每个容器的运行日志。
当删除托管容器时 kubeadm 阻塞
如果 Docker 停止并且不删除 Kubernetes 所管理的所有容器,可能发生以下情况:
sudo kubeadm reset
[preflight] Running pre-flight checks
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Removing kubernetes-managed containers
(block)
一个可行的解决方案是重新启动 Docker 服务,然后重新运行 kubeadm reset
:
sudo systemctl restart docker.service
sudo kubeadm reset
检查 docker 的日志也可能有用:
journalctl -ul docker
Pods 处于 RunContainerError
、CrashLoopBackOff
或者 Error
状态
在 kubeadm init
命令运行后,系统中不应该有 pods 处于这类状态。
在
kubeadm init
命令执行完后,如果有 pods 处于这些状态之一,请在 kubeadm 仓库提起一个 issue。coredns
(或者kube-dns
) 应该处于Pending
状态, 直到你部署了网络解决方案为止。如果在部署完网络解决方案之后,有 Pods 处于
RunContainerError
、CrashLoopBackOff
或Error
状态之一,并且coredns
(或者kube-dns
)仍处于Pending
状态, 那很可能是你安装的网络解决方案由于某种原因无法工作。你或许需要授予它更多的 RBAC 特权或使用较新的版本。请在 Pod Network 提供商的问题跟踪器中提交问题, 然后在此处分类问题。如果你安装的 Docker 版本早于 1.12.1,请在使用
systemd
来启动dockerd
和重启docker
时, 删除MountFlags=slave
选项。 你可以在/usr/lib/systemd/system/docker.service
中看到 MountFlags。 MountFlags 可能会干扰 Kubernetes 挂载的卷, 并使 Pods 处于CrashLoopBackOff
状态。 当 Kubernetes 不能找到var/run/secrets/kubernetes.io/serviceaccount
文件时会发生错误。
coredns
(或 kube-dns
)停滞在 Pending
状态
这一行为是 预期之中 的,因为系统就是这么设计的。
kubeadm 的网络供应商是中立的,因此管理员应该选择 安装 pod 的网络解决方案。
你必须完成 Pod 的网络配置,然后才能完全部署 CoreDNS。
在网络被配置好之前,DNS 组件会一直处于 Pending
状态。
HostPort
服务无法工作
此 HostPort
和 HostIP
功能是否可用取决于你的 Pod 网络配置。请联系 Pod 解决方案的作者,
以确认 HostPort
和 HostIP
功能是否可用。
已验证 Calico、Canal 和 Flannel CNI 驱动程序支持 HostPort。
有关更多信息,请参考 CNI portmap 文档.
如果你的网络提供商不支持 portmap CNI 插件,你或许需要使用
NodePort 服务的功能
或者使用 HostNetwork=true
。
无法通过其服务 IP 访问 Pod
许多网络附加组件尚未启用 hairpin 模式 该模式允许 Pod 通过其服务 IP 进行访问。这是与 CNI 有关的问题。 请与网络附加组件提供商联系,以获取他们所提供的 hairpin 模式的最新状态。
如果你正在使用 VirtualBox (直接使用或者通过 Vagrant 使用),你需要 确保
hostname -i
返回一个可路由的 IP 地址。默认情况下,第一个接口连接不能路由的仅主机网络。 解决方法是修改/etc/hosts
,请参考示例 Vagrantfile。
TLS 证书错误
以下错误指出证书可能不匹配。
# kubectl get pods
Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
验证
$HOME/.kube/config
文件是否包含有效证书,并 在必要时重新生成证书。在 kubeconfig 文件中的证书是 base64 编码的。 该base64 -d
命令可以用来解码证书,openssl x509 -text -noout
命令 可以用于查看证书信息。使用如下方法取消设置
KUBECONFIG
环境变量的值:unset KUBECONFIG
或者将其设置为默认的
KUBECONFIG
位置:export KUBECONFIG=/etc/kubernetes/admin.conf
另一个方法是覆盖
kubeconfig
的现有用户 "管理员" :mv $HOME/.kube $HOME/.kube.bak mkdir $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
在 Vagrant 中使用 flannel 作为 pod 网络时的默认 NIC
以下错误可能表明 Pod 网络中出现问题:
Error from server (NotFound): the server could not find the requested resource
如果你正在 Vagrant 中使用 flannel 作为 pod 网络,则必须指定 flannel 的默认接口名称。
Vagrant 通常为所有 VM 分配两个接口。第一个为所有主机分配了 IP 地址
10.0.2.15
,用于获得 NATed 的外部流量。这可能会导致 flannel 出现问题,它默认为主机上的第一个接口。这导致所有主机认为它们具有 相同的公共 IP 地址。为防止这种情况,传递
--iface eth1
标志给 flannel 以便选择第二个接口。
容器使用的非公共 IP
在某些情况下 kubectl logs
和 kubectl run
命令或许会返回以下错误,即便除此之外集群一切功能正常:
Error from server: Get https://10.19.0.41:10250/containerLogs/default/mysql-ddc65b868-glc5m/mysql: dial tcp 10.19.0.41:10250: getsockopt: no route to host
这或许是由于 Kubernetes 使用的 IP 无法与看似相同的子网上的其他 IP 进行通信的缘故, 可能是由机器提供商的政策所导致的。
Digital Ocean 既分配一个共有 IP 给
eth0
,也分配一个私有 IP 在内部用作其浮动 IP 功能的锚点, 然而kubelet
将选择后者作为节点的InternalIP
而不是公共 IP使用
ip addr show
命令代替ifconfig
命令去检查这种情况,因为ifconfig
命令 不会显示有问题的别名 IP 地址。或者指定的 Digital Ocean 的 API 端口允许从 droplet 中 查询 anchor IP:curl http://169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address
解决方法是通知
kubelet
使用哪个--node-ip
。当使用 Digital Ocean 时,可以是公网IP(分配给eth0
的), 或者是私网IP(分配给eth1
的)。私网 IP 是可选的。 kubadmNodeRegistrationOptions
结构的KubeletExtraArgs
部分 被用来处理这种情况。然后重启
kubelet
:systemctl daemon-reload systemctl restart kubelet
coredns
pods 有 CrashLoopBackOff
或者 Error
状态
如果有些节点运行的是旧版本的 Docker,同时启用了 SELinux,你或许会遇到 coredns
pods 无法启动的情况。
要解决此问题,你可以尝试以下选项之一:
升级到 Docker 的较新版本。
修改
coredns
部署以设置allowPrivilegeEscalation
为true
:
kubectl -n kube-system get deployment coredns -o yaml | \
sed 's/allowPrivilegeEscalation: false/allowPrivilegeEscalation: true/g' | \
kubectl apply -f -
CoreDNS 处于 CrashLoopBackOff
时的另一个原因是当 Kubernetes 中部署的 CoreDNS Pod 检测
到环路时。有许多解决方法
可以避免在每次 CoreDNS 监测到循环并退出时,Kubernetes 尝试重启 CoreDNS Pod 的情况。
警告: 禁用 SELinux 或设置allowPrivilegeEscalation
为true
可能会损害集群的安全性。
etcd pods 持续重启
如果你遇到以下错误:
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "process_linux.go:110: decoding init error from pipe caused \"read parent: connection reset by peer\""
如果你使用 Docker 1.13.1.84 运行 CentOS 7 就会出现这种问题。 此版本的 Docker 会阻止 kubelet 在 etcd 容器中执行。
为解决此问题,请选择以下选项之一:
回滚到早期版本的 Docker,例如 1.13.1-75
yum downgrade docker-1.13.1-75.git8633870.el7.centos.x86_64 docker-client-1.13.1-75.git8633870.el7.centos.x86_64 docker-common-1.13.1-75.git8633870.el7.centos.x86_64
安装较新的推荐版本之一,例如 18.06:
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install docker-ce-18.06.1.ce-3.el7.x86_64
无法将以逗号分隔的值列表传递给 --component-extra-args
标志内的参数
kubeadm init
标志例如 --component-extra-args
允许你将自定义参数传递给像
kube-apiserver 这样的控制平面组件。然而,由于解析 (mapStringString
) 的基础类型值,此机制将受到限制。
如果你决定传递一个支持多个逗号分隔值(例如
--apiserver-extra-args "enable-admission-plugins=LimitRanger,NamespaceExists"
)参数,
将出现 flag: malformed pair, expect string=string
错误。
发生这种问题是因为参数列表 --apiserver-extra-args
预期的是 key=value
形式,
而这里的 NamespacesExists
被误认为是缺少取值的键名。
一种解决方法是尝试分离 key=value
对,像这样:
--apiserver-extra-args "enable-admission-plugins=LimitRanger,enable-admission-plugins=NamespaceExists"
但这将导致键 enable-admission-plugins
仅有值 NamespaceExists
。
已知的解决方法是使用 kubeadm 配置文件。
在节点被云控制管理器初始化之前,kube-proxy 就被调度了
在云环境场景中,可能出现在云控制管理器完成节点地址初始化之前,kube-proxy 就被调度到新节点了。 这会导致 kube-proxy 无法正确获取节点的 IP 地址,并对管理负载平衡器的代理功能产生连锁反应。
在 kube-proxy Pod 中可以看到以下错误:
server.go:610] Failed to retrieve node IP: host IP unknown; known addresses: []
proxier.go:340] invalid nodeIP, initializing kube-proxy with 127.0.0.1 as nodeIP
一种已知的解决方案是修补 kube-proxy DaemonSet,以允许在控制平面节点上调度它, 而不管它们的条件如何,将其与其他节点保持隔离,直到它们的初始保护条件消除:
kubectl -n kube-system patch ds kube-proxy -p='{ "spec": { "template": { "spec": { "tolerations": [ { "key": "CriticalAddonsOnly", "operator": "Exists" }, { "effect": "NoSchedule", "key": "node-role.kubernetes.io/master" } ] } } } }'
此问题的跟踪在这里。
NodeRegistration.Taints 字段在编组 kubeadm 配置时丢失
注意:这个 问题 仅适用于操控 kubeadm 数据类型的工具(例如,YAML 配置文件)。它将在 kubeadm API v1beta2 修复。
默认情况下,kubeadm 将 node-role.kubernetes.io/master:NoSchedule
污点应用于控制平面节点。
如果你希望 kubeadm 不污染控制平面节点,并将 InitConfiguration.NodeRegistration.Taints
设置成空切片,则应在编组时省略该字段。
如果省略该字段,则 kubeadm 将应用默认污点。
至少有两种解决方法:
使用
node-role.kubernetes.io/master:PreferNoSchedule
污点代替空切片。 除非其他节点具有容量,否则将在主节点上调度 Pods。在 kubeadm init 退出后删除污点:
kubectl taint nodes NODE_NAME node-role.kubernetes.io/master:NoSchedule-
1.3 - 使用 kubeadm 创建集群
使用 kubeadm
,你
能创建一个符合最佳实践的最小化 Kubernetes 集群。事实上,你可以使用 kubeadm
配置一个通过 Kubernetes 一致性测试 的集群。
kubeadm
还支持其他集群生命周期功能,
例如 启动引导令牌 和集群升级。
kubeadm 工具很棒,如果你需要:
- 一个尝试 Kubernetes 的简单方法。
- 一个现有用户可以自动设置集群并测试其应用程序的途径。
- 其他具有更大范围的生态系统和/或安装工具中的构建模块。
你可以在各种机器上安装和使用 kubeadm
:笔记本电脑,
一组云服务器,Raspberry Pi 等。无论是部署到云还是本地,
你都可以将 kubeadm
集成到预配置系统中,例如 Ansible 或 Terraform。
准备开始
要遵循本指南,你需要:
- 一台或多台运行兼容 deb/rpm 的 Linux 操作系统的计算机;例如:Ubuntu 或 CentOS。
- 每台机器 2 GB 以上的内存,内存不足时应用会受限制。
- 用作控制平面节点的计算机上至少有2个 CPU。
- 集群中所有计算机之间具有完全的网络连接。你可以使用公共网络或专用网络。
你还需要使用可以在新集群中部署特定 Kubernetes 版本对应的 kubeadm
。
Kubernetes 版本及版本倾斜支持策略 适用于 kubeadm
以及整个 Kubernetes。
查阅该策略以了解支持哪些版本的 Kubernetes 和 kubeadm
。
该页面是为 Kubernetes v1.20 编写的。
kubeadm
工具的整体功能状态为一般可用性(GA)。一些子功能仍在积极开发中。
随着工具的发展,创建集群的实现可能会略有变化,但总体实现应相当稳定。
说明: 根据定义,在kubeadm alpha
下的所有命令均在 alpha 级别上受支持。
目标
- 安装单个控制平面的 Kubernetes 集群
- 在集群上安装 Pod 网络,以便你的 Pod 可以相互连通
操作指南
在你的主机上安装 kubeadm
查看 "安装 kubeadm"。
说明:如果你已经安装了kubeadm,执行
apt-get update && apt-get upgrade
或yum update
以获取 kubeadm 的最新版本。升级时,kubelet 每隔几秒钟重新启动一次, 在 crashloop 状态中等待 kubeadm 发布指令。crashloop 状态是正常现象。 初始化控制平面后,kubelet 将正常运行。
初始化控制平面节点
控制平面节点是运行控制平面组件的机器, 包括 etcd (集群数据库) 和 API Server (命令行工具 kubectl 与之通信)。
- (推荐)如果计划将单个控制平面 kubeadm 集群升级成高可用,
你应该指定
--control-plane-endpoint
为所有控制平面节点设置共享端点。 端点可以是负载均衡器的 DNS 名称或 IP 地址。 - 选择一个Pod网络插件,并验证是否需要为
kubeadm init
传递参数。 根据你选择的第三方网络插件,你可能需要设置--pod-network-cidr
的值。 请参阅 安装Pod网络附加组件。 - (可选)从版本1.14开始,
kubeadm
尝试使用一系列众所周知的域套接字路径来检测 Linux 上的容器运行时。 要使用不同的容器运行时, 或者如果在预配置的节点上安装了多个容器,请为kubeadm init
指定--cri-socket
参数。 请参阅安装运行时。 - (可选)除非另有说明,否则
kubeadm
使用与默认网关关联的网络接口来设置此控制平面节点 API server 的广播地址。 要使用其他网络接口,请为kubeadm init
设置--apiserver-advertise-address=<ip-address>
参数。 要部署使用 IPv6 地址的 Kubernetes 集群, 必须指定一个 IPv6 地址,例如--apiserver-advertise-address=fd00::101
- (可选)在
kubeadm init
之前运行kubeadm config images pull
,以验证与 gcr.io 容器镜像仓库的连通性。
要初始化控制平面节点,请运行:
kubeadm init <args>
关于 apiserver-advertise-address 和 ControlPlaneEndpoint 的注意事项
--apiserver-advertise-address
可用于为控制平面节点的 API server 设置广播地址,
--control-plane-endpoint
可用于为所有控制平面节点设置共享端点。
--control-plane-endpoint
允许 IP 地址和可以映射到 IP 地址的 DNS 名称。
请与你的网络管理员联系,以评估有关此类映射的可能解决方案。
这是一个示例映射:
192.168.0.102 cluster-endpoint
其中 192.168.0.102
是此节点的 IP 地址,cluster-endpoint
是映射到该 IP 的自定义 DNS 名称。
这将允许你将 --control-plane-endpoint=cluster-endpoint
传递给 kubeadm init
,并将相同的 DNS 名称传递给 kubeadm join
。
稍后你可以修改 cluster-endpoint
以指向高可用性方案中的负载均衡器的地址。
kubeadm 不支持将没有 --control-plane-endpoint
参数的单个控制平面集群转换为高可用性集群。
更多信息
有关 kubeadm init
参数的更多信息,请参见 kubeadm 参考指南。
要使用配置文件配置 kubeadm init
命令,请参见带配置文件使用 kubeadm init。
要自定义控制平面组件,包括可选的对控制平面组件和 etcd 服务器的活动探针提供 IPv6 支持,请参阅自定义参数。
要再次运行 kubeadm init
,你必须首先卸载集群。
如果将具有不同架构的节点加入集群, 请确保已部署的 DaemonSet 对这种体系结构具有容器镜像支持。
kubeadm init
首先运行一系列预检查以确保机器
准备运行 Kubernetes。这些预检查会显示警告并在错误时退出。然后 kubeadm init
下载并安装集群控制平面组件。这可能会需要几分钟。
完成之后你应该看到:
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a Pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
要使非 root 用户可以运行 kubectl,请运行以下命令,
它们也是 kubeadm init
输出的一部分:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
或者,如果你是 root
用户,则可以运行:
export KUBECONFIG=/etc/kubernetes/admin.conf
记录 kubeadm init
输出的 kubeadm join
命令。
你需要此命令将节点加入集群。
令牌用于控制平面节点和加入节点之间的相互身份验证。
这里包含的令牌是密钥。确保它的安全,
因为拥有此令牌的任何人都可以将经过身份验证的节点添加到你的集群中。
可以使用 kubeadm token
命令列出,创建和删除这些令牌。
请参阅 kubeadm 参考指南。
安装 Pod 网络附加组件
注意:本节包含有关网络设置和部署顺序的重要信息。 在继续之前,请仔细阅读所有建议。
你必须部署一个基于 Pod 网络插件的 容器网络接口 (CNI),以便你的 Pod 可以相互通信。 在安装网络之前,集群 DNS (CoreDNS) 将不会启动。
- 注意你的 Pod 网络不得与任何主机网络重叠: 如果有重叠,你很可能会遇到问题。 (如果你发现网络插件的首选 Pod 网络与某些主机网络之间存在冲突, 则应考虑使用一个合适的 CIDR 块来代替, 然后在执行
kubeadm init
时使用--pod-network-cidr
参数并在你的网络插件的 YAML 中替换它)。
- 默认情况下,
kubeadm
将集群设置为使用和强制使用 RBAC(基于角色的访问控制)。 确保你的 Pod 网络插件支持 RBAC,以及用于部署它的 manifests 也是如此。
- 如果要为集群使用 IPv6(双协议栈或仅单协议栈 IPv6 网络), 请确保你的Pod网络插件支持 IPv6。 IPv6 支持已在 CNI v0.6.0 版本中添加。
说明: 目前 Calico 是 kubeadm 项目中执行 e2e 测试的唯一 CNI 插件。 如果你发现与 CNI 插件相关的问题,应在其各自的问题跟踪器中记录而不是在 kubeadm 或 kubernetes 问题跟踪器中记录。
一些外部项目为 Kubernetes 提供使用 CNI 的 Pod 网络,其中一些还支持网络策略。
请参阅实现 Kubernetes 网络模型 的附加组件列表。
你可以使用以下命令在控制平面节点或具有 kubeconfig 凭据的节点上安装 Pod 网络附加组件:
kubectl apply -f <add-on.yaml>
每个集群只能安装一个 Pod 网络。
安装 Pod 网络后,您可以通过在 kubectl get pods --all-namespaces
输出中检查 CoreDNS Pod 是否 Running
来确认其是否正常运行。
一旦 CoreDNS Pod 启用并运行,你就可以继续加入节点。
如果您的网络无法正常工作或CoreDNS不在“运行中”状态,请查看 kubeadm
的故障排除指南。
控制平面节点隔离
默认情况下,出于安全原因,你的集群不会在控制平面节点上调度 Pod。 如果你希望能够在控制平面节点上调度 Pod, 例如用于开发的单机 Kubernetes 集群,请运行:
kubectl taint nodes --all node-role.kubernetes.io/master-
输出看起来像:
node "test-01" untainted
taint "node-role.kubernetes.io/master:" not found
taint "node-role.kubernetes.io/master:" not found
这将从任何拥有 node-role.kubernetes.io/master
taint 标记的节点中移除该标记,
包括控制平面节点,这意味着调度程序将能够在任何地方调度 Pods。
加入节点
节点是你的工作负载(容器和 Pod 等)运行的地方。要将新节点添加到集群,请对每台计算机执行以下操作:
- SSH 到机器
- 成为 root (例如
sudo su -
) - 运行
kubeadm init
输出的命令。例如:
kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>
如果没有令牌,可以通过在控制平面节点上运行以下命令来获取令牌:
kubeadm token list
输出类似于以下内容:
TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
8ewj1p.9r9hcjoqgajrj4gi 23h 2018-06-12T02:51:28Z authentication, The default bootstrap system:
signing token generated by bootstrappers:
'kubeadm init'. kubeadm:
default-node-token
默认情况下,令牌会在24小时后过期。如果要在当前令牌过期后将节点加入集群, 则可以通过在控制平面节点上运行以下命令来创建新令牌:
kubeadm token create
输出类似于以下内容:
5didvk.d09sbcov8ph2amjw
如果你没有 --discovery-token-ca-cert-hash
的值,则可以通过在控制平面节点上执行以下命令链来获取它:
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
输出类似于以下内容:
8cb2de97839780a412b93877f8507ad6c94f73add17d5d7058e91741c9d5ec78
说明: 要为<control-plane-host>:<control-plane-port>
指定 IPv6 元组,必须将 IPv6 地址括在方括号中,例如:[fd00::101]:2073
输出应类似于:
[preflight] Running pre-flight checks
... (log output of join workflow) ...
Node join complete:
* Certificate signing request sent to control-plane and response
received.
* Kubelet informed of new secure connection details.
Run 'kubectl get nodes' on control-plane to see this machine join.
几秒钟后,当你在控制平面节点上执行 kubectl get nodes
,你会注意到该节点出现在输出中。
(可选)从控制平面节点以外的计算机控制集群
为了使 kubectl 在其他计算机(例如笔记本电脑)上与你的集群通信, 你需要将管理员 kubeconfig 文件从控制平面节点复制到工作站,如下所示:
scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf get nodes
说明:上面的示例假定为 root 用户启用了SSH访问。如果不是这种情况, 你可以使用
scp
将 admin.conf 文件复制给其他允许访问的用户。admin.conf 文件为用户提供了对集群的超级用户特权。 该文件应谨慎使用。对于普通用户,建议生成一个你为其授予特权的唯一证书。 你可以使用
kubeadm alpha kubeconfig user --client-name <CN>
命令执行此操作。 该命令会将 KubeConfig 文件打印到 STDOUT,你应该将其保存到文件并分发给用户。 之后,使用kubectl create (cluster)rolebinding
授予特权。
(可选)将API服务器代理到本地主机
如果要从集群外部连接到 API 服务器,则可以使用 kubectl proxy
:
scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf proxy
你现在可以在本地访问API服务器 http://localhost:8001/api/v1
清理
如果你在集群中使用了一次性服务器进行测试,则可以关闭这些服务器,而无需进一步清理。你可以使用 kubectl config delete-cluster
删除对集群的本地引用。
但是,如果要更干净地取消配置群集, 则应首先清空节点并确保该节点为空, 然后取消配置该节点。
删除节点
使用适当的凭证与控制平面节点通信,运行:
kubectl drain <node name> --delete-local-data --force --ignore-daemonsets
在删除节点之前,请重置 kubeadm
安装的状态:
kubeadm reset
重置过程不会重置或清除 iptables 规则或 IPVS 表。如果你希望重置 iptables,则必须手动进行:
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
如果要重置 IPVS 表,则必须运行以下命令:
ipvsadm -C
现在删除节点:
kubectl delete node <node name>
如果你想重新开始,只需运行 kubeadm init
或 kubeadm join
并加上适当的参数。
清理控制平面
你可以在控制平面主机上使用 kubeadm reset
来触发尽力而为的清理。
有关此子命令及其选项的更多信息,请参见kubeadm reset
参考文档。
下一步
- 使用 Sonobuoy 验证集群是否正常运行
- 有关使用kubeadm升级集群的详细信息,请参阅升级 kubeadm 集群。
- 在kubeadm 参考文档中了解有关高级
kubeadm
用法的信息 - 了解有关Kubernetes概念和
kubectl
的更多信息。 - 有关Pod网络附加组件的更多列表,请参见集群网络页面。
- 请参阅附加组件列表以探索其他附加组件, 包括用于 Kubernetes 集群的日志记录,监视,网络策略,可视化和控制的工具。
- 配置集群如何处理集群事件的日志以及 在Pods中运行的应用程序。 有关所涉及内容的概述,请参见日志架构。
反馈
- 有关 bugs, 访问 kubeadm GitHub issue tracker
- 有关支持, 访问 #kubeadm Slack 频道
- General SIG 集群生命周期开发 Slack 频道: #sig-cluster-lifecycle
- SIG 集群生命周期 SIG information
- SIG 集群生命周期邮件列表: kubernetes-sig-cluster-lifecycle
版本倾斜政策
版本 v1.24 的kubeadm 工具可以使用版本 v1.24 或 v1.23 的控制平面部署集群。kubeadm v1.24 还可以升级现有的 kubeadm 创建的 v1.23 版本的集群。
由于没有未来,kubeadm CLI v1.24 可能会或可能无法部署 v1.25 集群。
这些资源提供了有关 kubelet 与控制平面以及其他 Kubernetes 组件之间受支持的版本倾斜的更多信息:
局限性
集群弹性
此处创建的集群具有单个控制平面节点,运行单个 etcd 数据库。 这意味着如果控制平面节点发生故障,你的集群可能会丢失数据并且可能需要从头开始重新创建。
解决方法:
- 定期备份 etcd。
kubeadm 配置的 etcd 数据目录位于控制平面节点上的
/var/lib/etcd
中。
平台兼容性
kubeadm deb/rpm 软件包和二进制文件是为 amd64,arm (32-bit),arm64,ppc64le 和 s390x 构建的遵循多平台提案。
从 v1.12 开始还支持用于控制平面和附加组件的多平台容器镜像。
只有一些网络提供商为所有平台提供解决方案。请查阅上方的 网络提供商清单或每个提供商的文档以确定提供商是否 支持你选择的平台。
故障排除
如果你在使用 kubeadm 时遇到困难,请查阅我们的故障排除文档。
1.4 - 使用 kubeadm 定制控制平面配置
Kubernetes 1.12 [stable]
kubeadm ClusterConfiguration
对象公开了 extraArgs
字段,它可以覆盖传递给控制平面组件(如 APIServer、ControllerManager 和 Scheduler)的默认参数。各组件配置使用如下字段定义:
apiServer
controllerManager
scheduler
extraArgs
字段由 key: value
对组成。
要覆盖控制平面组件的参数:
- 将适当的字段添加到配置中。
- 向字段添加要覆盖的参数值。
- 用
--config <YOUR CONFIG YAML>
运行kubeadm init
。
有关配置中的每个字段的详细信息,您可以导航到我们的 API 参考页面。
说明:您可以通过运行
kubeadm config print init-defaults
并将输出保存到您选择的文件中,以默认值形式生成ClusterConfiguration
对象。
APIServer 参数
有关详细信息,请参阅 kube-apiserver 参考文档。
使用示例:
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
apiServer:
extraArgs:
advertise-address: 192.168.0.103
anonymous-auth: "false"
enable-admission-plugins: AlwaysPullImages,DefaultStorageClass
audit-log-path: /home/johndoe/audit.log
ControllerManager 参数
有关详细信息,请参阅 kube-controller-manager 参考文档。
使用示例:
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
controllerManager:
extraArgs:
cluster-signing-key-file: /home/johndoe/keys/ca.key
bind-address: 0.0.0.0
deployment-controller-sync-period: "50"
Scheduler 参数
有关详细信息,请参阅 kube-scheduler 参考文档。
使用示例:
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
scheduler:
extraArgs:
bind-address: 0.0.0.0
config: /home/johndoe/schedconfig.yaml
kubeconfig: /home/johndoe/kubeconfig.yaml
1.5 - 高可用拓扑选项
本页面介绍了配置高可用(HA) Kubernetes 集群拓扑的两个选项。
您可以设置 HA 集群:
- 使用堆叠(stacked)控制平面节点,其中 etcd 节点与控制平面节点共存
- 使用外部 etcd 节点,其中 etcd 在与控制平面不同的节点上运行
在设置 HA 集群之前,您应该仔细考虑每种拓扑的优缺点。
说明: kubeadm 静态引导 etcd 集群。 阅读 etcd 集群指南以获得更多详细信息。
堆叠(Stacked) etcd 拓扑
堆叠(Stacked) HA 集群是一种这样的拓扑,其中 etcd 分布式数据存储集群堆叠在 kubeadm 管理的控制平面节点上,作为控制平面的一个组件运行。
每个控制平面节点运行 kube-apiserver
,kube-scheduler
和 kube-controller-manager
实例。
kube-apiserver
使用负载均衡器暴露给工作节点。
每个控制平面节点创建一个本地 etcd 成员(member),这个 etcd 成员只与该节点的 kube-apiserver
通信。这同样适用于本地 kube-controller-manager
和 kube-scheduler
实例。
这种拓扑将控制平面和 etcd 成员耦合在同一节点上。相对使用外部 etcd 集群,设置起来更简单,而且更易于副本管理。
然而,堆叠集群存在耦合失败的风险。如果一个节点发生故障,则 etcd 成员和控制平面实例都将丢失,并且冗余会受到影响。您可以通过添加更多控制平面节点来降低此风险。
因此,您应该为 HA 集群运行至少三个堆叠的控制平面节点。
这是 kubeadm 中的默认拓扑。当使用 kubeadm init
和 kubeadm join --control-plane
时,在控制平面节点上会自动创建本地 etcd 成员。
外部 etcd 拓扑
具有外部 etcd 的 HA 集群是一种这样的拓扑,其中 etcd 分布式数据存储集群在独立于控制平面节点的其他节点上运行。
就像堆叠的 etcd 拓扑一样,外部 etcd 拓扑中的每个控制平面节点都运行 kube-apiserver
,kube-scheduler
和 kube-controller-manager
实例。同样, kube-apiserver
使用负载均衡器暴露给工作节点。但是,etcd 成员在不同的主机上运行,每个 etcd 主机与每个控制平面节点的 kube-apiserver
通信。
这种拓扑结构解耦了控制平面和 etcd 成员。因此,它提供了一种 HA 设置,其中失去控制平面实例或者 etcd 成员的影响较小,并且不会像堆叠的 HA 拓扑那样影响集群冗余。
但是,此拓扑需要两倍于堆叠 HA 拓扑的主机数量。
具有此拓扑的 HA 集群至少需要三个用于控制平面节点的主机和三个用于 etcd 节点的主机。
接下来
1.6 - 利用 kubeadm 创建高可用集群
本文讲述了使用 kubeadm 设置一个高可用的 Kubernetes 集群的两种不同方式:
- 使用堆控制平面节点。这种方法所需基础设施较少。etcd 成员和控制平面节点位于同一位置。
- 使用外部集群。这种方法所需基础设施较多。控制平面的节点和 etcd 成员是分开的。
在下一步之前,您应该仔细考虑哪种方法更好的满足您的应用程序和环境的需求。 这是对比文档 讲述了每种方法的优缺点。
如果您在安装 HA 集群时遇到问题,请在 kubeadm 问题跟踪里向我们提供反馈。
您也可以阅读 升级文件
注意: 这篇文档没有讲述在云提供商上运行集群的问题。在云环境中,此处记录的方法不适用于类型为 LoadBalancer 的服务对象,或者具有动态的 PersistentVolumes。
准备开始
对于这两种方法,您都需要以下基础设施:
- 配置三台机器 kubeadm 的最低要求 给主节点
- 配置三台机器 kubeadm 的最低要求 给工作节点
- 在集群中,所有计算机之间的完全网络连接(公网或私网)
- 所有机器上的 sudo 权限
- 每台设备对系统中所有节点的 SSH 访问
- 在所有机器上安装
kubeadm
和kubelet
,kubectl
是可选的。
仅对于外部 etcd 集群来说,您还需要:
- 给 etcd 成员使用的另外三台机器
这两种方法的第一步
为 kube-apiserver 创建负载均衡器
说明: 使用负载均衡器需要许多配置。您的集群搭建可能需要不同的配置。下面的例子只是其中的一方面配置。
创建一个名为 kube-apiserver 的负载均衡器解析 DNS。
在云环境中,应该将控制平面节点放置在 TCP 后面转发负载平衡。 该负载均衡器将流量分配给目标列表中所有运行状况良好的控制平面节点。健康检查 apiserver 是在 kube-apiserver 监听端口(默认值
:6443
)上的一个 TCP 检查。不建议在云环境中直接使用 IP 地址。
负载均衡器必须能够在 apiserver 端口上与所有控制平面节点通信。它还必须允许其监听端口的传入流量。
确保负载均衡器的地址始终匹配 kubeadm 的
ControlPlaneEndpoint
地址。阅读软件负载平衡选项指南以获取更多详细信息。
添加第一个控制平面节点到负载均衡器并测试连接:
nc -v LOAD_BALANCER_IP PORT
- 由于 apiserver 尚未运行,预期会出现一个连接拒绝错误。然而超时意味着负载均衡器不能和控制平面节点通信。 如果发生超时,请重新配置负载均衡器与控制平面节点进行通信。
将其余控制平面节点添加到负载均衡器目标组。
使用堆控制平面和 etcd 节点
控制平面节点的第一步
初始化控制平面:
sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certs
- 您可以使用
--kubernetes-version
标志来设置要使用的 Kubernetes 版本。建议将 kubeadm、kebelet、kubectl 和 Kubernetes 的版本匹配。 - 这个
--control-plane-endpoint
标志应该被设置成负载均衡器的地址或 DNS 和端口。 - 这个
--upload-certs
标志用来将在所有控制平面实例之间的共享证书上传到集群。如果正好相反,你更喜欢手动地通过控制平面节点或者使用自动化 工具复制证书,请删除此标志并参考如下部分证书分配手册。
- 您可以使用
说明: 标志kubeadm init
、--config
和--certificate-key
不能混合使用,因此如果您要使用kubeadm 配置,您必须在相应的配置文件(位于InitConfiguration
和JoinConfiguration: controlPlane
)添加certificateKey
字段。
说明: 一些 CNI 网络插件如 Calico 需要 CIDR 例如192.168.0.0/16
和一些像 Weave 没有。参考 CNI 网络文档。 通过传递--pod-network-cidr
标志添加 pod CIDR,或者您可以使用 kubeadm 配置文件,在ClusterConfiguration
的networking
对象下设置podSubnet
字段。
命令完成后,您应该会看到类似以下内容:
... 现在,您可以通过在根目录上运行以下命令来加入任意数量的控制平面节点: kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07 请注意,证书密钥可以访问集群内敏感数据,请保密! 为了安全起见,将在两个小时内删除上传的证书; 如有必要,您可以使用 kubeadm 初始化上传证书阶段,之后重新加载证书。 然后,您可以通过在根目录上运行以下命令来加入任意数量的工作节点: kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
将此输出复制到文本文件。 稍后您将需要它来将控制平面节点和辅助节点加入集群。
当
--upload-certs
与kubeadm init
一起使用时,主控制平面的证书被加密并上传到kubeadm-certs
密钥中。要重新上传证书并生成新的解密密钥,请在已加入集群节点的控制平面上使用以下命令:
sudo kubeadm init phase upload-certs --upload-certs
您还可以在
init
期间指定自定义的--certificate-key
,以后可以由join
使用。 要生成这样的密钥,可以使用以下命令:kubeadm alpha certs certificate-key
说明:kubeadm-certs
密钥和解密密钥会在两个小时后失效。
注意: 正如命令输出中所述,证书密钥可访问群集敏感数据,并将其保密!
应用您选择的 CNI 插件: 请遵循以下指示 安装 CNI 提供程序。如果适用,请确保配置与 kubeadm 配置文件中指定的 Pod CIDR 相对应。
在此示例中,我们使用 Weave Net:
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
输入以下内容,并查看 pods 的控制平面组件启动:
kubectl get pod -n kube-system -w
其余控制平面节点的步骤
说明: 从 kubeadm 1.15 版本开始,您可以并行加入多个控制平面节点。 在此版本之前,您必须在第一个节点初始化后才能依序的增加新的控制平面节点。
对于每个其他控制平面节点,您应该:
执行先前由第一个节点上的
kubeadm init
输出提供给您的 join 命令。 它看起来应该像这样:sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
- 这个
--control-plane
命令通知kubeadm join
创建一个新的控制平面。 --certificate-key ...
将导致从集群中的kubeadm-certs
秘钥下载控制平面证书并使用给定的密钥进行解密。
- 这个
外部 etcd 节点
使用外部 etcd 节点设置集群类似于用于堆叠 etcd 的过程, 不同之处在于您应该首先设置 etcd,并在 kubeadm 配置文件中传递 etcd 信息。
设置 ectd 集群
按照 这些指示 去设置 etcd 集群。
设置 SSH 在 这描述。
将以下文件从集群中的任何 etcd 节点复制到第一个控制平面节点:
export CONTROL_PLANE="ubuntu@10.0.0.7" scp /etc/kubernetes/pki/etcd/ca.crt "${CONTROL_PLANE}": scp /etc/kubernetes/pki/apiserver-etcd-client.crt "${CONTROL_PLANE}": scp /etc/kubernetes/pki/apiserver-etcd-client.key "${CONTROL_PLANE}":
- 用第一台控制平面机的
user@host
替换CONTROL_PLANE
的值。
- 用第一台控制平面机的
设置第一个控制平面节点
用以下内容创建一个名为
kubeadm-config.yaml
的文件:apiVersion: kubeadm.k8s.io/v1beta2 kind: ClusterConfiguration kubernetesVersion: stable controlPlaneEndpoint: "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" etcd: external: endpoints: - https://ETCD_0_IP:2379 - https://ETCD_1_IP:2379 - https://ETCD_2_IP:2379 caFile: /etc/kubernetes/pki/etcd/ca.crt certFile: /etc/kubernetes/pki/apiserver-etcd-client.crt keyFile: /etc/kubernetes/pki/apiserver-etcd-client.key
说明: 这里堆 etcd 和外部 etcd 之前的区别在于设置外部 etcd 需要一个etcd
的external
对象下带有 etcd 端点的配置文件。 如果是堆 etcd 技术,是自动管理的。
在您的集群中,将配置模板中的以下变量替换为适当值:
LOAD_BALANCER_DNS
LOAD_BALANCER_PORT
ETCD_0_IP
ETCD_1_IP
ETCD_2_IP
以下的步骤与设置堆集群是相似的:
在节点上运行
sudo kubeadm init --config kubeadm-config.yaml --upload-certs
命令。编写输出联接命令,这些命令将返回到文本文件以供以后使用。
应用您选择的 CNI 插件。 给定以下示例适用于 Weave Net:
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
其他控制平面节点的步骤
步骤与设置堆 etcd 相同:
- 确保第一个控制平面节点已完全初始化。
- 使用保存到文本文件的连接命令将每个控制平面节点连接在一起。建议一次加入一个控制平面节点。
- 不要忘记默认情况下,
--certificate-key
中的解密秘钥会在两个小时后过期。
列举控制平面之后的常见任务
安装工作节点
您可以使用之前存储的命令将工作节点加入集群中
作为 kubeadm init
命令的输出:
sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
手动证书分发
如果您选择不将 kubeadm init
与 --upload-certs
命令一起使用,
则意味着您将必须手动将证书从主控制平面节点复制到
将要加入的控制平面节点上。
有许多方法可以实现这种操作。在下面的例子中我们使用 ssh
和 scp
:
如果要在单独的一台计算机控制所有节点,则需要 SSH。
在您的主设备上启动 ssh-agent,要求该设备能访问系统中的所有其他节点:
eval $(ssh-agent)
将 SSH 身份添加到会话中:
ssh-add ~/.ssh/path_to_private_key
检查节点间的 SSH 以确保连接是正常运行的
SSH 到任何节点时,请确保添加
-A
标志:ssh -A 10.0.0.7
当在任何节点上使用 sudo 时,请确保环境完善,以便使用 SSH 转发任务:
sudo -E -s
在所有节点上配置 SSH 之后,您应该在运行过
kubeadm init
命令的第一个控制平面节点上运行以下脚本。 该脚本会将证书从第一个控制平面节点复制到另一个控制平面节点:在以下示例中,用其他控制平面节点的 IP 地址替换
CONTROL_PLANE_IPS
。USER=ubuntu # 可自己设置 CONTROL_PLANE_IPS="10.0.0.7 10.0.0.8" for host in ${CONTROL_PLANE_IPS}; do scp /etc/kubernetes/pki/ca.crt "${USER}"@$host: scp /etc/kubernetes/pki/ca.key "${USER}"@$host: scp /etc/kubernetes/pki/sa.key "${USER}"@$host: scp /etc/kubernetes/pki/sa.pub "${USER}"@$host: scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host: scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host: scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key done
注意: 只需要复制上面列表中的证书。kubeadm 将负责生成其余证书以及加入控制平面实例所需的 SAN。 如果您错误地复制了所有证书,由于缺少所需的 SAN,创建其他节点可能会失败。
然后,在每个连接控制平面节点上,您必须先运行以下脚本,然后再运行
kubeadm join
。 该脚本会将先前复制的证书从主目录移动到/etc/kubernetes/pki
:USER=ubuntu # 可自己设置 mkdir -p /etc/kubernetes/pki/etcd mv /home/${USER}/ca.crt /etc/kubernetes/pki/ mv /home/${USER}/ca.key /etc/kubernetes/pki/ mv /home/${USER}/sa.pub /etc/kubernetes/pki/ mv /home/${USER}/sa.key /etc/kubernetes/pki/ mv /home/${USER}/front-proxy-ca.crt /etc/kubernetes/pki/ mv /home/${USER}/front-proxy-ca.key /etc/kubernetes/pki/ mv /home/${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt mv /home/${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
1.7 - 使用 kubeadm 创建一个高可用 etcd 集群
说明:在本指南中,当 kubeadm 用作为外部 etcd 节点管理工具,请注意 kubeadm 不计划支持此类节点的证书更换或升级。对于长期规划是使用 etcdadm 增强工具来管理这方面。
默认情况下,kubeadm 运行单成员的 etcd 集群,该集群由控制面节点上的 kubelet 以静态 Pod 的方式进行管理。由于 etcd 集群只包含一个成员且不能在任一成员不可用时保持运行,所以这不是一种高可用设置。本任务,将告诉您如何在使用 kubeadm 创建一个 kubernetes 集群时创建一个外部 etcd:有三个成员的高可用 etcd 集群。
准备开始
- 三个可以通过 2379 和 2380 端口相互通信的主机。本文档使用这些作为默认端口。不过,它们可以通过 kubeadm 的配置文件进行自定义。
- 每个主机必须 安装有 docker、kubelet 和 kubeadm。
- 一些可以用来在主机间复制文件的基础设施。例如
ssh
和scp
就可以满足需求。
建立集群
一般来说,是在一个节点上生成所有证书并且只分发这些必要的文件到其它节点上。
说明:kubeadm 包含生成下述证书所需的所有必要的密码学工具;在这个例子中,不需要其他加密工具。
将 kubelet 配置为 etcd 的服务管理器。
由于 etcd 是首先创建的,因此您必须通过创建具有更高优先级的新文件来覆盖 kubeadm 提供的 kubelet 单元文件。
cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf [Service] ExecStart= # Replace "systemd" with the cgroup driver of your container runtime. The default value in the kubelet is "cgroupfs". ExecStart=/usr/bin/kubelet --address=127.0.0.1 --pod-manifest-path=/etc/kubernetes/manifests --cgroup-driver=systemd Restart=always EOF systemctl daemon-reload systemctl restart kubelet
为 kubeadm 创建配置文件。
使用以下脚本为每个将要运行 etcd 成员的主机生成一个 kubeadm 配置文件。
# 使用 IP 或可解析的主机名替换 HOST0、HOST1 和 HOST2 export HOST0=10.0.0.6 export HOST1=10.0.0.7 export HOST2=10.0.0.8 # 创建临时目录来存储将被分发到其它主机上的文件 mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/ ETCDHOSTS=(${HOST0} ${HOST1} ${HOST2}) NAMES=("infra0" "infra1" "infra2") for i in "${!ETCDHOSTS[@]}"; do HOST=${ETCDHOSTS[$i]} NAME=${NAMES[$i]} cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml apiVersion: "kubeadm.k8s.io/v1beta2" kind: ClusterConfiguration etcd: local: serverCertSANs: - "${HOST}" peerCertSANs: - "${HOST}" extraArgs: initial-cluster: infra0=https://${ETCDHOSTS[0]}:2380,infra1=https://${ETCDHOSTS[1]}:2380,infra2=https://${ETCDHOSTS[2]}:2380 initial-cluster-state: new name: ${NAME} listen-peer-urls: https://${HOST}:2380 listen-client-urls: https://${HOST}:2379 advertise-client-urls: https://${HOST}:2379 initial-advertise-peer-urls: https://${HOST}:2380 EOF done
生成证书颁发机构
如果您已经拥有 CA,那么唯一的操作是复制 CA 的
crt
和key
文件到etc/kubernetes/pki/etcd/ca.crt
和/etc/kubernetes/pki/etcd/ca.key
。复制完这些文件后继续下一步,“为每个成员创建证书”。如果您还没有 CA,则在
$HOST0
(您为 kubeadm 生成配置文件的位置)上运行此命令。kubeadm init phase certs etcd-ca
创建了如下两个文件
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/etcd/ca.key
为每个成员创建证书
kubeadm init phase certs etcd-server --config=/tmp/${HOST2}/kubeadmcfg.yaml kubeadm init phase certs etcd-peer --config=/tmp/${HOST2}/kubeadmcfg.yaml kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST2}/kubeadmcfg.yaml kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST2}/kubeadmcfg.yaml cp -R /etc/kubernetes/pki /tmp/${HOST2}/ # 清理不可重复使用的证书 find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete kubeadm init phase certs etcd-server --config=/tmp/${HOST1}/kubeadmcfg.yaml kubeadm init phase certs etcd-peer --config=/tmp/${HOST1}/kubeadmcfg.yaml kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST1}/kubeadmcfg.yaml kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST1}/kubeadmcfg.yaml cp -R /etc/kubernetes/pki /tmp/${HOST1}/ find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete kubeadm init phase certs etcd-server --config=/tmp/${HOST0}/kubeadmcfg.yaml kubeadm init phase certs etcd-peer --config=/tmp/${HOST0}/kubeadmcfg.yaml kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST0}/kubeadmcfg.yaml kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST0}/kubeadmcfg.yaml # 不需要移动 certs 因为它们是给 HOST0 使用的 # 清理不应从此主机复制的证书 find /tmp/${HOST2} -name ca.key -type f -delete find /tmp/${HOST1} -name ca.key -type f -delete
复制证书和 kubeadm 配置
证书已生成,现在必须将它们移动到对应的主机。
USER=ubuntu HOST=${HOST1} scp -r /tmp/${HOST}/* ${USER}@${HOST}: ssh ${USER}@${HOST} USER@HOST $ sudo -Es root@HOST $ chown -R root:root pki root@HOST $ mv pki /etc/kubernetes/
确保已经所有预期的文件都存在
$HOST0
所需文件的完整列表如下:/tmp/${HOST0} └── kubeadmcfg.yaml --- /etc/kubernetes/pki ├── apiserver-etcd-client.crt ├── apiserver-etcd-client.key └── etcd ├── ca.crt ├── ca.key ├── healthcheck-client.crt ├── healthcheck-client.key ├── peer.crt ├── peer.key ├── server.crt └── server.key
在
$HOST1
:$HOME └── kubeadmcfg.yaml --- /etc/kubernetes/pki ├── apiserver-etcd-client.crt ├── apiserver-etcd-client.key └── etcd ├── ca.crt ├── healthcheck-client.crt ├── healthcheck-client.key ├── peer.crt ├── peer.key ├── server.crt └── server.key
在
$HOST2
$HOME └── kubeadmcfg.yaml --- /etc/kubernetes/pki ├── apiserver-etcd-client.crt ├── apiserver-etcd-client.key └── etcd ├── ca.crt ├── healthcheck-client.crt ├── healthcheck-client.key ├── peer.crt ├── peer.key ├── server.crt └── server.key
创建静态 Pod 清单
既然证书和配置已经就绪,是时候去创建清单了。在每台主机上运行
kubeadm
命令来生成 etcd 使用的静态清单。root@HOST0 $ kubeadm init phase etcd local --config=/tmp/${HOST0}/kubeadmcfg.yaml root@HOST1 $ kubeadm init phase etcd local --config=/home/ubuntu/kubeadmcfg.yaml root@HOST2 $ kubeadm init phase etcd local --config=/home/ubuntu/kubeadmcfg.yaml
可选:检查群集运行状况
docker run --rm -it \ --net host \ -v /etc/kubernetes:/etc/kubernetes k8s.gcr.io/etcd:${ETCD_TAG} etcdctl \ --cert /etc/kubernetes/pki/etcd/peer.crt \ --key /etc/kubernetes/pki/etcd/peer.key \ --cacert /etc/kubernetes/pki/etcd/ca.crt \ --endpoints https://${HOST0}:2379 endpoint health --cluster ... https://[HOST0 IP]:2379 is healthy: successfully committed proposal: took = 16.283339ms https://[HOST1 IP]:2379 is healthy: successfully committed proposal: took = 19.44402ms https://[HOST2 IP]:2379 is healthy: successfully committed proposal: took = 35.926451ms
- 将
${ETCD_TAG}
设置为你的 etcd 镜像的版本标签,例如3.4.3-0
。要查看 kubeadm 使用的 etcd 镜像和标签,请执行kubeadm config images list --kubernetes-version ${K8S_VERSION}
,其中${K8S_VERSION}
是v1.17.0
作为例子。
- 将
${HOST0}
设置为要测试的主机的 IP 地址
- 将
接下来
一旦拥有了一个正常工作的 3 成员的 etcd 集群,你就可以基于 使用 kubeadm 的外部 etcd 方法, 继续部署一个高可用的控制平面。
1.8 - 使用 kubeadm 配置集群中的每个 kubelet
Kubernetes 1.11 [stable]
kubeadm CLI 工具的生命周期与 kubelet解耦,它是一个守护程序,在 Kubernetes 集群中的每个节点上运行。 当 Kubernetes 初始化或升级时,kubeadm CLI 工具由用户执行,而 kubelet 始终在后台运行。
由于kubelet是守护程序,因此需要通过某种初始化系统或服务管理器进行维护。 当使用 DEB 或 RPM 安装 kubelet 时,配置系统去管理 kubelet。 你可以改用其他服务管理器,但需要手动地配置。
集群中涉及的所有 kubelet 的一些配置细节都必须相同,
而其他配置方面则需要基于每个 kubelet 进行设置,以适应给定机器的不同特性(例如操作系统、存储和网络)。
你可以手动地管理 kubelet 的配置,但是 kubeadm 现在提供一种 KubeletConfiguration
API 类型
用于集中管理 kubelet 的配置。
Kubelet 配置模式
以下各节讲述了通过使用 kubeadm 简化 kubelet 配置模式,而不是在每个节点上手动地管理 kubelet 配置。
将集群级配置传播到每个 kubelet 中
你可以通过使用 kubeadm init
和 kubeadm join
命令为 kubelet 提供默认值。
有趣的示例包括使用其他 CRI 运行时或通过服务器设置不同的默认子网。
如果你想使用子网 10.96.0.0/12
作为默认的服务,你可以给 kubeadm 传递 --service-cidr
参数:
kubeadm init --service-cidr 10.96.0.0/12
现在,可以从该子网分配服务的虚拟 IP。
你还需要通过 kubelet 使用 --cluster-dns
标志设置 DNS 地址。
在集群中的每个管理器和节点上的 kubelet 的设置需要相同。
kubelet 提供了一个版本化的结构化 API 对象,该对象可以配置 kubelet 中的大多数参数,并将此配置推送到集群中正在运行的每个 kubelet 上。
此对象被称为 kubelet 的配置组件。
该配置组件允许用户指定标志,例如用骆峰值代表集群的 DNS IP 地址,如下所示:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
clusterDNS:
- 10.96.0.10
有关组件配置的更多详细信息,亲参阅 本节。
提供指定实例的详细配置信息
由于硬件、操作系统、网络或者其他主机特定参数的差异。某些主机需要特定的 kubelet 配置。 以下列表提供了一些示例。
由 kubelet 配置标志
--resolv-conf
指定的 DNS 解析文件的路径在操作系统之间可能有所不同, 它取决于你是否使用systemd-resolved
。 如果此路径错误,则在其 kubelet 配置错误的节点上 DNS 解析也将失败。除非你使用云驱动,否则默认情况下 Node API 对象的
.metadata.name
会被设置为计算机的主机名。 如果你需要指定一个与机器的主机名不同的节点名称,你可以使用--hostname-override
标志覆盖默认值。当前,kubelet 无法自动检测 CRI 运行时使用的 cgroup 驱动程序, 但是值
--cgroup-driver
必须与 CRI 运行时使用的 cgroup 驱动程序匹配,以确保 kubelet 的健康运行状况。取决于你的集群所使用的 CRI 运行时,你可能需要为 kubelet 指定不同的标志。 例如,当使用 Docker 时,你需要指定如
--network-plugin=cni
这类标志;但是如果你使用的是外部运行时, 则需要指定--container-runtime=remote
并使用--container-runtime-endpoint=<path>
指定 CRI 端点。
你可以在服务管理器(例如 systemd)中设定某个 kubelet 的配置来指定这些参数。
使用 kubeadm 配置 kubelet
如果自定义的 KubeletConfiguration
API 对象使用像 kubeadm ... --config some-config-file.yaml
这样的配置文件进行传递,则可以配置 kubeadm 启动的 kubelet。
通过调用 kubeadm config print init-defaults --component-configs KubeletConfiguration
,
你可以看到此结构中的所有默认值。
也可以阅读 kubelet 配置组件的 API 参考来获取有关各个字段的更多信息。
当使用 kubeadm init
时的工作流程
当调用 kubeadm init
时,kubelet 配置被编组到磁盘上的 /var/lib/kubelet/config.yaml
中,
并且上传到集群中的 ConfigMap。
ConfigMap 名为 kubelet-config-1.X
,其中 X
是你正在初始化的 kubernetes 版本的次版本。
在集群中所有 kubelet 的基准集群范围内配置,将 kubelet 配置文件写入 /etc/kubernetes/kubelet.conf
中。
此配置文件指向允许 kubelet 与 API 服务器通信的客户端证书。
这解决了 将集群级配置传播到每个 kubelet的需求。
该文档 提供特定实例的配置详细信息 是第二种解决模式,
kubeadm 将环境文件写入 /var/lib/kubelet/kubeadm-flags.env
,其中包含了一个标志列表,
当 kubelet 启动时,该标志列表会传递给 kubelet 标志在文件中的显示方式如下:
KUBELET_KUBEADM_ARGS="--flag1=value1 --flag2=value2 ..."
除了启动 kubelet 时使用该标志外,该文件还包含动态参数,例如 cgroup 驱动程序以及是否使用其他 CRI 运行时 socket(--cri-socket
)。
将这两个文件编组到磁盘后,如果使用 systemd,则 kubeadm 尝试运行以下两个命令:
systemctl daemon-reload && systemctl restart kubelet
如果重新加载和重新启动成功,则正常的 kubeadm init
工作流程将继续。
当使用 kubeadm join
时的工作流程
当运行 kubeadm join
时,kubeadm 使用 Bootstrap Token 证书执行 TLS 引导,该引导会获取一份证书,该证书需要下载 kubelet-config-1.X
ConfigMap 并把它写入 /var/lib/kubelet/config.yaml
中。
动态环境文件的生成方式恰好与 kubeadm init
相同。
接下来,kubeadm 运行以下两个命令将新配置加载到 kubelet 中:
systemctl daemon-reload && systemctl restart kubelet
在 kubelet 加载新配置后,kubeadm 将写入 /etc/kubernetes/bootstrap-kubelet.conf
KubeConfig 文件中,
该文件包含 CA 证书和引导程序令牌。
kubelet 使用这些证书执行 TLS 引导程序并获取唯一的凭据,该凭据被存储在 /etc/kubernetes/kubelet.conf
中。
当此文件被写入后,kubelet 就完成了执行 TLS 引导程序。
kubelet 的 systemd 文件
kubeadm
中附带了有关系统如何运行 kubelet 的 systemd 配置文件。
请注意 kubeadm CLI 命令不会修改此文件。
通过 kubeadm
DEB
或者 RPM 包
安装的配置文件被写入 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
并由系统使用。
它对原来的 RPM 版本 kubelet.service
或者 DEB 版本 kubelet.service
作了增强:
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf
--kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# 这是 "kubeadm init" 和 "kubeadm join" 运行时生成的文件,动态地填充 KUBELET_KUBEADM_ARGS 变量
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# 这是一个文件,用户在不得已下可以将其用作替代 kubelet args。
# 用户最好使用 .NodeRegistration.KubeletExtraArgs 对象在配置文件中替代。
# KUBELET_EXTRA_ARGS 应该从此文件中获取。
EnvironmentFile=-/etc/default/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
该文件为 kubelet 指定由 kubeadm 管理的所有文件的默认位置。
- 用于 TLS 引导程序的 KubeConfig 文件为
/etc/kubernetes/bootstrap-kubelet.conf
, 但仅当/etc/kubernetes/kubelet.conf
不存在时才能使用。 - 具有唯一 kubelet 标识的 KubeConfig 文件为
/etc/kubernetes/kubelet.conf
。 - 包含 kubelet 的组件配置的文件为
/var/lib/kubelet/config.yaml
。 - 包含的动态环境的文件
KUBELET_KUBEADM_ARGS
是来源于/var/lib/kubelet/kubeadm-flags.env
。 - 包含用户指定标志替代的文件
KUBELET_EXTRA_ARGS
是来源于/etc/default/kubelet
(对于 DEB),或者/etc/sysconfig/kubelet
(对于 RPM)。KUBELET_EXTRA_ARGS
在标志链中排在最后,并且在设置冲突时具有最高优先级。
Kubernetes 二进制文件和软件包内容
Kubernetes 版本对应的 DEB 和 RPM 软件包是:
Package name | Description |
---|---|
kubeadm | 给 kubelet 安装 /usr/bin/kubeadm CLI 工具和 kubelet 的 systemd 文件。 |
kubelet | 安装 kublet 可执行文件到 /usr/bin 路径,安装 CNI 可执行文件到 /opt/cni/bin 路径。 |
kubectl | 安装 /usr/bin/kubectl 可执行文件。 |
cri-tools | 从 cri-tools git 仓库中安装 /usr/bin/crictl 可执行文件。 |
1.9 - 配置您的 kubernetes 集群以自托管控制平台
自托管 Kubernetes 控制平台
kubeadm 允许您实验性地创建 self-hosted Kubernetes 控制平面。 这意味着 API 服务器,控制管理器和调度程序之类的关键组件将通过配置 Kubernetes API 以 DaemonSet Pods 的身份运行, 而不是通过静态文件在 kubelet 中配置静态 Pods。
要创建自托管集群,请参见 kubeadm alpha selfhosting pivot 命令。
警告
注意: 此功能将您的集群设置为不受支持的状态,从而使 kubeadm 无法再管理您的集群。 这包括kubeadm 升级
。
- 1.8及更高版本中的自托管功能有一些重要限制。 特别是,自托管集群在没有人工干预的情况下_无法从控制平面节点的重新启动中恢复_ 。
- 默认情况下,自托管的控制平面 Pod 依赖于从
hostPath
卷加载的凭据。 除初始创建外,这些凭据不由 kubeadm 管理。
- 控制平面的自托管部分不包括 etcd,后者仍作为静态 Pod 运行。
过程
自托管引导过程描述于 kubeadm 设计文档 中。
总体而言,kubeadm alpha 自托管
的工作原理如下:
- 等待此引导静态控制平面运行且良好。
这与没有自我托管的
kubeadm init
过程相同。
- 使用静态控制平面 Pod 清单来构造一组 DaemonSet 清单,这些清单将运行自托管的控制平面。 它还会在必要时修改这些清单,例如添加新的 secrets 卷。
- 在
kube-system
名称空间中创建 DaemonSets ,并等待生成的 Pod 运行。
- 自托管 Pod 运行后,将删除其关联的静态 Pod,然后 kubeadm 继续安装下一个组件。 这将触发 kubelet 停止那些静态 Pod 。
- 当原始静态控制平面停止时,新的自托管控制平面能够绑定到侦听端口并变为活动状态。
2 - 使用 Kops 安装 Kubernetes
本篇快速入门介绍了如何在 AWS 上轻松安装 Kubernetes 集群。
本篇使用了一个名为 kops
的工具。
kops 是一个自用的供应系统:
- 全自动安装流程
- 使用 DNS 识别集群
- 自我修复:一切都在自动扩展组中运行
- 支持多种操作系统(如 Debian、Ubuntu 16.04、CentOS、RHEL、Amazon Linux 和 CoreOS) - 参考 images.md
- 支持高可用 - 参考 high_availability.md
- 可以直接提供或者生成 terraform 清单 - 参考 terraform.md
如果你有不同的观点,你可能更喜欢使用 kubeadm 作为构建工具来构建自己的集群。kops 建立在 kubeadm 工作的基础上。
创建集群
(1/5) 安装 kops
前提条件
你必须安装 kubectl 才能使 kops 工作。
安装
从下载页面下载 kops(从源代码构建也很容易):
在 macOS 上:
curl -OL https://github.com/kubernetes/kops/releases/download/1.10.0/kops-darwin-amd64
chmod +x kops-darwin-amd64
mv kops-darwin-amd64 /usr/local/bin/kops
# 你也可以使用 Homebrew 安装 kops
brew update && brew install kops
在 Linux 上:
wget https://github.com/kubernetes/kops/releases/download/1.10.0/kops-linux-amd64
chmod +x kops-linux-amd64
mv kops-linux-amd64 /usr/local/bin/kops
(2/5) 为你的集群创建一个 route53 域名
kops 在集群内部都使用 DNS 进行发现操作,因此你可以从客户端访问 kubernetes API 服务器。
kops 对集群名称有明显的要求:它应该是有效的 DNS 名称。这样一来,你就不会再使集群混乱, 可以与同事明确共享集群,并且无需依赖记住 IP 地址即可访问群集。
你应该使用子域名来划分集群。作为示例,我们将使用域名 useast1.dev.example.com
。
然后,API 服务器端点域名将为 api.useast1.dev.example.com
。
Route53 托管区域可以服务子域名。你的托管区域可能是 useast1.dev.example.com
,还有 dev.example.com
甚至 example.com
。
kops 可以与以上任何一种配合使用,因此通常你出于组织原因选择不同的托管区域。
例如,允许你在 dev.example.com
下创建记录,但不能在 example.com
下创建记录。
假设你使用 dev.example.com
作为托管区域。你可以使用
正常流程
或者使用诸如 aws route53 create-hosted-zone --name dev.example.com --caller-reference 1
之类的命令来创建该托管区域。
然后,你必须在父域名中设置你的 DNS 记录,以便该域名中的记录可以被解析。
在这里,你将在 example.com
中为 dev
创建 DNS 记录。
如果它是根域名,则可以在域名注册机构配置 DNS 记录。
例如,你需要在购买 example.com
的地方配置 example.com
。
这一步很容易搞砸(这是问题的第一大原因!) 如果你安装了 dig 工具,则可以通过运行以下步骤再次检查集群是否配置正确:
dig DNS dev.example.com
你应该看到 Route53 分配了你的托管区域的 4 条 DNS 记录。
(3/5) 创建一个 S3 存储桶来存储集群状态
kops 使你即使在安装后也可以管理集群。为此,它必须跟踪已创建的集群及其配置、所使用的密钥等。 此信息存储在 S3 存储桶中。S3 权限用于控制对存储桶的访问。
多个集群可以使用同一 S3 存储桶,并且你可以在管理同一集群的同事之间共享一个 S3 存储桶 - 这比传递 kubecfg 文件容易得多。 但是有权访问 S3 存储桶的任何人都将拥有对所有集群的管理访问权限,因此你不想在运营团队之外共享它。
因此,通常每个运维团队都有一个 S3 存储桶(而且名称通常对应于上面托管区域的名称!)
在我们的示例中,我们选择 dev.example.com
作为托管区域,因此让我们选择 clusters.dev.example.com
作为 S3 存储桶名称。
- 导出
AWS_PROFILE
文件(如果你需要选择一个配置文件用来使 AWS CLI 正常工作) - 使用
aws s3 mb s3://clusters.dev.example.com
创建 S3 存储桶 - 你可以进行
export KOPS_STATE_STORE=s3://clusters.dev.example.com
操作,然后 kops 将默认使用此位置。 我们建议将其放入你的 bash profile 文件或类似文件中。
(4/5) 建立你的集群配置
运行 "kops create cluster" 以创建你的集群配置:
kops create cluster --zones=us-east-1c useast1.dev.example.com
kops 将为你的集群创建配置。请注意,它_仅_创建配置,实际上并没有创建云资源 - 你将在下一步中使用 kops update cluster
进行配置。
这使你有机会查看配置或进行更改。
它打印出可用于进一步探索的命令:
- 使用以下命令列出集群:
kops get cluster
- 使用以下命令编辑该集群:
kops edit cluster useast1.dev.example.com
- 使用以下命令编辑你的节点实例组:
kops edit ig --name = useast1.dev.example.com nodes
- 使用以下命令编辑你的主实例组:
kops edit ig --name = useast1.dev.example.com master-us-east-1c
如果这是你第一次使用 kops,请花几分钟尝试一下! 实例组是一组实例,将被注册为 kubernetes 节点。 在 AWS 上,这是通过 auto-scaling-groups 实现的。你可以有多个实例组。 例如,如果你想要的是混合实例和按需实例的节点,或者 GPU 和非 GPU 实例。
(5/5) 在 AWS 中创建集群
运行 "kops update cluster" 以在 AWS 中创建集群:
kops update cluster useast1.dev.example.com --yes
这需要几秒钟的时间才能运行,但实际上集群可能需要几分钟才能准备就绪。
每当更改集群配置时,都会使用 kops update cluster
工具。
它将对配置进行的更改应用于你的集群 - 根据需要重新配置 AWS 或者 kubernetes。
例如,在你运行 kops edit ig nodes
之后,然后运行 kops update cluster --yes
应用你的配置,有时你还必须运行 kops rolling-update cluster
立即回滚更新配置。
如果没有 --yes
参数,kops update cluster
操作将向你显示其操作的预览效果。这对于生产集群很方便!
探索其他附加组件
请参阅附加组件列表探索其他附加组件, 包括用于 Kubernetes 集群的日志记录、监视、网络策略、可视化和控制的工具。
清理
- 删除集群:
kops delete cluster useast1.dev.example.com --yes
反馈
- Slack 频道: #kops-users
- GitHub Issues
接下来
3 - 使用 Kubespray 安装 Kubernetes
此快速入门有助于使用 Kubespray 安装在 GCE、Azure、OpenStack、AWS、vSphere、Packet(裸机)、Oracle Cloud Infrastructure(实验性)或 Baremetal 上托管的 Kubernetes 集群。
Kubespray 是一个由 Ansible playbooks、清单(inventory)、供应工具和通用 OS/Kubernetes 集群配置管理任务的领域知识组成的。 Kubespray 提供:
- 高可用性集群
- 可组合属性
- 支持大多数流行的 Linux 发行版
- Ubuntu 16.04、18.04、20.04
- CentOS / RHEL / Oracle Linux 7、8
- Debian Buster,Jessie,Stretch,Wheezy
- Fedora 31、32
- Fedora CoreOS
- openSUSE Leap 15
- Kinvolk 的 Flatcar Container Linux
- 持续集成测试
要选择最适合你的用例的工具,请阅读此比较以 kubeadm 和 kops 。
创建集群
(1/5)满足下层设施要求
按以下要求来配置服务器:
- 在将运行 Ansible 命令的计算机上安装 Ansible v2.9 和 python-netaddr
- 运行 Ansible Playbook 需要 Jinja 2.11(或更高版本)
- 目标服务器必须有权访问 Internet 才能拉取 Docker 镜像。否则,需要其他配置(请参见离线环境)
- 目标服务器配置为允许 IPv4 转发
- 你的 SSH 密钥必须复制到清单中的所有服务器部分
- 防火墙不受管理,你将需要按照以前的方式实施自己的规则。为了避免在部署过程中出现任何问题,你应该禁用防火墙
- 如果从非 root 用户帐户运行 kubespray,则应在目标服务器中配置正确的特权升级方法。然后应指定“ansible_become” 标志或命令参数 “--become” 或 “-b”
Kubespray 提供以下实用程序来帮助你设置环境:
(2/5)编写清单文件
设置服务器后,请创建一个 Ansible 的清单文件。你可以手动执行此操作,也可以通过动态清单脚本执行此操作。有关更多信息,请参阅“建立你自己的清单”。
(3/5)规划集群部署
Kubespray 能够自定义部署的许多方面:
- 选择部署模式: kubeadm 或非 kubeadm
- CNI(网络)插件
- DNS 配置
- 控制平面的选择:本机/可执行文件或容器化
- 组件版本
- Calico 路由反射器
- 组件运行时选项
- 证书生成方式
可以修改变量文件以进行 Kubespray 定制。 如果你刚刚开始使用 Kubespray,请考虑使用 Kubespray 默认设置来部署你的集群并探索 Kubernetes 。
(4/5)部署集群
接下来,部署你的集群:
使用 ansible-playbook 进行j集群部署。
ansible-playbook -i your/inventory/inventory.ini cluster.yml -b -v \
--private-key=~/.ssh/private_key
大型部署(超过 100 个节点)可能需要特定的调整,以获得最佳效果。
(5/5)验证部署
Kubespray 提供了一种使用 Netchecker 验证 Pod 间连接和 DNS 解析的方法。 Netchecker 确保 netchecker-agents pod 可以解析。 DNS 请求并在默认名称空间内对每个请求执行 ping 操作。 这些 Pods 模仿其余工作负载的类似行为,并用作集群运行状况指示器。
集群操作
Kubespray 提供了其他 Playbooks 来管理集群: scale 和 upgrade。
扩展集群
你可以通过运行 scale playbook 向集群中添加工作节点。有关更多信息, 请参见 “添加节点”。 你可以通过运行 remove-node playbook 来从集群中删除工作节点。有关更多信息, 请参见 “删除节点”。
升级集群
你可以通过运行 upgrade-cluster Playbook 来升级集群。有关更多信息,请参见 “升级”。
清理
你可以通过 reset Playbook 重置节点并清除所有与 Kubespray 一起安装的组件。
注意: 运行 reset playbook 时,请确保不要意外地将生产集群作为目标!
反馈
- Slack 频道:#kubespray(你可以在此处获得邀请)
- GitHub 问题
接下来
查看有关 Kubespray 的路线图的计划工作。