「Kubernetes」- etcd,常用维护操作

问题描述
该笔记将记录:在 Kubernetes Cluster 中,如何维护 etcd 组件,以及常见问题解决方案。
解决方案
管理 etcd 集群
How to access kubernetes keys in etcd – Stack Overflow Operating etcd clusters for Kubernetes | Kubernetes etcdctl v3 environment variables · Issue #6645 · etcd-io/etcd · GitHub

export ETCDCTL_API=3
export ETCDCTL_CACERT=’/etc/kubernetes/pki/etcd/ca.crt’ # –cacert
export ETCDCTL_CERT=’/etc/kubernetes/pki/etcd/server.crt’ # –cert
export ETCDCTL_KEY=’/etc/kubernetes/pki/etcd/server.key’ # –key
export ETCDCTL_ENDPOINTS=’172.31.253.61:2379,172.31.253.62:2379,172.31.253.63:2379′ # –endpoints

# etcdctl member list
4d763151a94a71ad, started, k8scp-02, https://172.31.253.62:2380, https://172.31.253.62:2379
704c9040de8224e9, started, k8scp-03, https://172.31.253.63:2380, https://172.31.253.63:2379
f15c34749947bfb8, started, k8scp-01, https://172.31.253.61:2380, https://172.31.253.61:2379

# etcdctl member remove 704c9040de8224e9

# etcdctl endpoint status

# etcdctl endpoint health

# 获取 certificate key 参数
kubeadm init phase upload-certs –upload-certs

# 获取加入集群的命令
kubeadm token create –print-join-command –certificate-key “[……]

READ MORE

「KUBERNETES-TROUBLESHOOT」- etcd

etcd 是 Kubernetes 集群中最关键的一部分。这一点从 etcd 在整个集群中引发的、以不同方式表现出来的大量问题可以看出来。经过非常仔细的研究,我们才找到根本原因,并扩展 etcd 以匹配我们预期的规模。
在扩展过程中,许多 Raft proposal 开始失败。
通过调查分析,我们发现,GCP 将 PD-SSD 磁盘的吞吐量限制在每秒 100MB 左右(如下图所示),我们的磁盘大小为 100G。GCP 没有提供增加吞吐量限制的方法——它只 随着磁盘的大小增加。尽管 etcd 节点只需要不到 10G 的空间,我们首先尝试了 1TB PD-SSD。然而,当所有 4k 个节点同时加入 Kubernetes 控制平面时,磁盘再大也会成为一个 瓶颈。我们决定使用本地 SSD,它的吞吐量非常高,代价是在出现故障时丢失数据的几率略高,因为它 不是持久化的。
在迁移到本地 SSD 后,我们并没有看到最快的 SSD 带来了预期的性能。我们用 FIO 直接在磁盘上做了一些基准测试,数值在意料之中。但是,对于所有成员的写入并发,etcd 基准测试讲述了一个不同的故事:本地 SSD 的表现更差!
经过深入调查,这是由 ext4 文件系统的写屏障缓存提交导致的。由于 etcd 使用写前日志,并在每次提交到 Raft 日志时调用 fsync,所以可以禁用写屏障。此外,我们在文件系统级和应用程序级有 DB 备份作业,用于 DR。在这样修改之后,使用本地 SSD 的数值提高到了与 PD-SSD 相当的程度。
这一改进的效果在 etcd 的 WAL 同步持续时间和后端提交延迟上体现了出来。
etcd 中默认的 MVCC 数据库大小为 2GB。在 DB 空间不足的告警被触发时,这个大小最大会增加到 8GB。由于该数据库的 利用率约为 60%,所以我们能够扩展到 20 万个无状态 Pod。
经过上述这些优化,在预期的规模下,集群更加稳定了,然而,在 API 延迟方面,我们的 SLI 还差很多。
etcd 服务器还会偶尔重启,仅一次重启就会破坏基准测试结果,尤其是 P99 值。仔细观察发现,v1.20 版的 etcd YAML 中有一个存活探针 Bug。为了解决这个问题,我们采用了一个变通办法,即增加失败阈值的计数。
在用尽所有方法对 etcd 进行了垂直扩展之后,主要是在资源方面(CPU、内存、磁盘),我们发现,etcd 的性能受到范围查询的影响。当范围查询很多时,etcd 的表现并不好,对 Raft 日志的写入也受到影响,增加了集群的延迟。
由于这些查询很耗时,etcd 的后端延迟受到了很大的影响。在事件资源上对 etcd 服务器进行分片管理后,我们看到,在 Pod 高度竞争的情况下,集群的稳定性有[……]

READ MORE

「kubelet」- 磁盘 I/O 极高

原因分析
内存压力导致磁盘 IO 极高。
解决方案
Kubelet & heapster extremely high disk i/o (reads) · Issue #47928 · kubernetes/kubernetes · GitHub Reserve Compute Resources for System Daemons | Kubernetes
1)通过处理内存占用高的应用,来环节内存压力; 2)然后,为应用程序增加 CPU、MEM 资源限制;
参考文献
Kubelet & heapster extremely high disk i/o (reads) · Issue #47928 · kubernetes/kubernetes · GitHub Reserve Compute Resources for System Daemons | Kubernetes[……]

READ MORE

「Kubernetes」- 管理与配置

该部分笔记整理:Kubernetes Cluster 管理与日常维护工作。
但是本部分不包含:对象的管理(比如部署、服务、定时任务等等)
Namespaces Walkthrough Why disable swap on kubernetes
如何利用kubernetes实现应用的水平扩展(HPA)ingre
Networking and Network Policy K8S的apiVersion该用哪个 kubernetes-dashboard获取令牌登陆 Custom HTTP Port
# TODO kubelet https://kubernetes.io/docs/reference/kubectl/kubectl[……]

READ MORE

「K3s」- 搭建实验环境

问题描述
该笔记将记录:如何使用 K3s 快速搭建 Kubernetes 环境,以及相关问题解决方法。
解决方案
版本:v1.22.6+k3s1 https://github.com/k3s-io/k3s/releases/tag/v1.22.6%2Bk3s1
第一步、Run Master

# wget https://github.com/k3s-io/k3s/releases/download/v1.22.7%2Bk3s1/k3s # 下载 k3s 文件

# k3s server # 启动节点
INFO[0000] Acquiring lock file /var/lib/rancher/k3s/data/.lock
INFO[0000] Preparing data dir /var/lib/rancher/k3s/data/31ff0fd447a47323a7c863dbb0a3cd452e12b45f1ec67dc55efa575503c2c3ac INFO[0000] Starting k3s v1.22.7+k3s1 (8432d7f2)
INFO[0006] Configuring sqlite3 database connection pooling: maxIdleConns=2, maxOpenConns=0, connMaxLifetime=0s

# k3s kubectl get nodes # 查看状态
NAME STATUS ROLES[……]

READ MORE

「Kubernetes」- 创建集群

使用kubeadm安装集群,kubeadm也是安装其他程序的基础。
如何获取工作平面;工作节点相关的可执行文件。
使用hyperkube建立容器化的Kubernetes,并演示如果创建systemd文件以监管Kubernetes组件。
在Google Cloud和Azure上建立集群。
2.3. Downloading a Kubernetes Release from GitHub
https://github.com/kubernetes/kubernetes/releases
记得检查下载文件的HASH值。
2.4. Downloading Client and Server Binaries
源码中并不包含可执行文件(考虑到大小),需要单独下载:

kubernetes/cluster/get-kube-binaries.sh

-> kubernetes/cluster/client/bin/

kubectl
kubefed

-> kubernetes/cluster/server/bin/

cloud-controller-manager
kube-api-server

上面下载的是最新的版本。如果要下载指定版本,可以访问“https://storage.googleapis.com/kubernetes-release/”%E4%B8%8B%E8%BD%BD
2.5. Using a hyperkube Image to Run a Kubernetes Master Node with Docker
将Kubernetes运行在容器中:hyperkube + etcd

etcd:键值分布式存储。用于保存集群的状态;
hyperkube:以Docker镜像的方式提供的一站式可执行文件。使用该镜像启动所有的Kubernetes进程。

#!/bin/sh

# 首先启动etcd服务:
docker run -d –name=k8s -p 8080:8080 \
gci.io/google_containers/etcd:3.1.10 etcd \
–data-dir /var/lib/data

# 使用hyperkube启动API服务:
docker run -d –net=container:k8s
gcr.io/google_containers/hyperkube:v1.7.11 apiserver \
–etcd-servers=http:/[……]

READ MORE

「Kubernetes」- 使用 minikube 快速搭建集群(实验集群)

问题描述
学习 Kubernetes 技术,就要先部署 Kubernetes 环境,不然怎么练习呢?(光看文档是学不会的)。然而,部署 Kubernetes 集群需要很多台机器,并且过程也不简单,让人忘而生畏(其实也没有那么复杂,我们之所以这么说,纯粹是为了引出 minikube 工具,不然我们没办法继续往下说呀)。幸好有 minikube 工具,让我们快速在本地创建用于学习和开发的 Kubernetes 集群。
该笔记将记录:使用 minikube 搭建用于学习的 Kubernetes 集群(用于本地测试、功能体验)的方法及注意事项。
实验环境
# 09/18/2020 Debian GNU/Linux 10 (buster)
# 03/15/2021 Ubuntu 20.04 LTS(由于硬件不到位,我们少张阵列卡,磁盘空间不足,所以临时使用 minikube 搭建测试环境)
解决方案
第一步、安装环境依赖
安装 kubectl 命令:参考 Install and Set Up kubectl 笔记(或者,官方文档)。该步骤是可选的,最后我们会通过 minikube 来安装对应版本的 kubectl 命令。
安装集群底层运行环境:使用 minikube 创建的 Kubernetes 集群,运行在不同的环境内。比如 minikube 可以调用 VirtualBox 来创建集群,也可以调用 VMware 来创建集群(还支持使用 Docker、Podman 等等,参考 Drivers 文档)。我们使用 kvm 虚拟化(因为更贴近于使用场景),所以需要安装 KVM 虚拟化环境,参考 Setting Up a KVM VM Host Server 笔记。
第二步、检查虚拟化是否开启

# egrep -q ‘vmx|svm’ /proc/cpuinfo && echo yes || echo no
yes # 输出 yes 表示支持虚拟化

第三步、安装 minikube 命令
有两种安装方法:1)使用包管理器安装、2)使用二进制安装
方法一、使用包管理器安装:

# 我们使用 Debian 发行版(适用于 Ubuntu 发行版),因此执行如下安装命令:
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube_latest_amd64.deb
dpkg -i minikube_latest_amd64.deb

# 其他 Linux 发行版,参考 minikube start 页面
# https://minikube.sigs.k8s.io/doc[……]

READ MORE

「Kubernetes」- 集群与高可用

问题描述
在 Kubernetes 的官方文档中,已经介绍搭建集群的方法,以及各种拓扑的利弊(为了保证知识是有效的,建议定期阅读官方文档);
在进行研究和对比之后,我们便编写该笔记,用于日后指导我们如何选择高可用集群的拓扑结构,以及注意需要关注的问题;
该部分笔记将记录:在 Kubernetes 中,搭建高可用的 Kubernetes Cluster 的选择,以及相关问题处理,并附有集群搭建笔记;
解决方案
在生产环境中,集群的高可用(比如 容灾、稳定性、故障恢复 等等),是必须考虑的问题;
创建高可用集群: Creating Highly Available clusters with kubeadm Set up High-Availability Kubernetes Masters
集群拓扑类型概览
高可用集群有两种方案: 1)With stacked control plane nodes(内部 etcd 服务) 2)With an external etcd cluster(外部 etcd 服务)
两种方案各有利弊,在文档 Options for Highly Available topology 中有所描述,需要根据各自需求进行选择;
内部 etcd 服务(Stacked etcd topology)

该类型高可用集群集群,提供数据存储的 etcd 服务在集群(由节点组成,由运行主节点组件的 kubeadm 管理)内部;
1)主机节点运行 APIServer、Scheduler、Controller-Manager 组件,而 APIServer 会暴露为工作节点; 2)每个主机节点会创建本地 etcd 成员,它只与本地的 APIServer 通讯;Controller-Manager、Scheduler 只与本地 APIServer 通讯; 3)对于 Load Balancer 服务,可以选择独立主机来运行,或者在每台主节点上运行;
优点: 1)节省主机:该集群 etcd 成员与主节点在相同节点,相对于外部 etcd 服务集群,该方案需要的主机数量少; 2)部署简单:集群部署比较简单,复制易于管理;
缺点: 1)如果主节点故障,则将无法访问 etcd 服务(因此需要多个主节点),此外该节点的 kube-apiserver、kube-scheduler、kube-controller-manager 组件也将不可用; 2)正如官方文档所说,最少需要 3 个 Control Plane 节点。两个节点是无法容错的,因为一个节点失败后,etcd 无法完成选举,导致 etcd 不可用,进而导致集群不可用;
集群部署参考: 1)1.17,[……]

READ MORE

「Kubernetes」- 搭建高可用集群(集群、搭建、高可用、1.18、kube-vip)

问题描述
正如标题,在虚拟化环境中,我们将使用 kubeadm 部署高可用集群。我们选择通过 kubeadm 部署集群是因为:通过 kubeadm 部署的集群能够满足最佳实践的要求;并且我们能够通过 kubeadm 命令进行集群管理,比如 Bootstrap Token 管理、集群升级等等;并且我们还未达到使用 Kubespray 的规模。因此,我们遵循着官方的建议,完成对生产环境的部署(虽然以后我们肯定会踩别人踩过的坑,但是现实情况就是这个样子)。我们也知道还有很多第三方的解决方案,但是我们依旧未达到那样的规模,贸然的引入复杂且巨大的技术栈,对于我们来说并不是明智的选择。迭代更新与推翻重建是必然的,我们无法一部到位。所以,对于我们来说,就目前的情形以及未来的规模,选择 kubeadm 部署集群是最好的选择。
创建这篇笔记是为了记录我们的部署过程,并为大家提供部署经验,也便于我们在日后能够进行快速部署,而不是指导大家如何部署高可用的 Kubernetes 集群。虽然参考笔记我们的能够保证集群部署成功,但是由于部分细节未提及,很可能会部署失败,因此我们仍旧建议参考官方文档完成集群的部署。
该笔记将记录:在 Linux 中,如何搭建 Kubernetes 1.20 集群,以及常见问题处理。
补充说明
集群架构
集群架构:我们采用官方的 Stacked Control Plane 架构,以为该架构所需要的主机数量少,而其缺点也是我们能接受的,且从目前来看对未来的影响不大。
节点数量:共计 6 个节点,Control Plane x 3,Worker Node x 3
高可用性:我们采用 kube-vip 来实现高可用,所有节点访问 VIP 来通讯。而且 kube-vip x 3 都运行在 Control Plane 所在的主机中,以减少集群主机数量。
部署信息
操作系统: Ubuntu 18.04.5 LTS(鉴于 CentOS 现在的情况,我们只能另选其他发行版。而服务软件支持的 Linux 发行版是有限的,比如 Docker 支持 CentOS、Debian、Fedora、Ubuntu 发行版。此外,结合使用习惯,我们能在 Debian 和 Ubuntu 之间选择。最后决定选择 Ubuntu 是因为该发行版的工具链更丰富,而 Debian 的应用及内核会稍微落后些。也许 Ubuntu 的稳定性差些,但是都在容忍范围内,不然我们就要容忍工具链陈旧难以排查问题的情况)
服务版本: 1)Docker 19.03.12 2)kubeadm 1.20.5 3)Calico 3.18.1
网络信息: 1)Control Plane:172.31.253.60(负载均衡的虚拟地址),172.3[……]

READ MORE

「Kubernetes」- 集群部署;集群版本:1.20;部署工具:kubeadm;高可用:kube-vip;

问题描述
我们将通过 kubeadm 命令创建的 Kubernetes 1.20 高可用集群,并使用 kube-vip 作为负载均衡器。
该笔记将记录:部署 Kubernetes Cluster 的方法,以及注意事项、常见问题的解决办法。
解决方案
根据官方 Bootstrapping clusters with kubeadm 文档的指引,我们得以实施该部署过程。
该部署过程及内容并非依照官方文档顺序来记录,而是依照实际部署过程来记录,即我们遵循「先记录,后实施」的原则;
环境概述
每台主机仅有一张网卡; 192.168.10.70 VIP 192.168.10.71 eth0 k8s70-cp01 192.168.10.72 eth0 k8s70-cp02 192.168.10.73 eth0 k8s70-cp03
补充说明: 1)对于某些特殊主机配置(比如 Master * 3 的网卡名各不相同)未包含在该笔记说明中。
第一步、配置节点环境
进行主机检查
在部署集群之前,需要准备工作和环境检查: 1)兼容的 Linux 主机;我们使用 Ubuntu 20.04 TLS 发行版; 2)最少 2vCPU 2gMEM 资源; 3)集群中所有机器间的网络互联(公共或专用网络都可以),以及正确的网络配置; 4)每个节点 [hostname、mac address、product_uuid] 要唯一; 5)机器上的某些端口不能别占用,且要允许访问:6443; 6)禁用 SWAP 分区:

# 3)集群中所有机器间的网络互联(公共或专用网络都可以),以及正确的网络配置;

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
systemctl restart systemd-modules-load.service

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

# 4)每个节点 [hostname、mac address、product_uuid] 要唯一;

ip link
hostname
cat /sys/class/dmi/id/product_uuid

# 5)机器上的某些端口不能别占用,且要允许访问:6443;

nc -v -z 127.0.0.1 6443
systemctl stop ufw.service &a[……]

READ MORE

「Kubernetes」- 搭建高可用集群(集群、搭建、高可用、1.17、keepalived)

问题描述
我们将通过 kubeadm 命令创建的 Kubernetes 1.22 高可用集群,并使用 kube-vip 作为负载均衡器;
该笔记将记录:如何搭建 Kubernetes Cluster(内部 etcd 服务),以及相关问题处理方法;
解决方案
根据官方 Kubernetes/Bootstrapping clusters with kubeadm 文档的指引,我们得以实施该部署过程; 该部署过程及内容并非依照官方文档顺序来记录,而是依照实际部署过程来记录,即我们遵循「先记录,后实施」的原则;
第零步、配置节点环境
操作系统:Ubuntu 20.04 LTS 软件版本:Kubernetes 1.22.13
检查节点环境
在部署集群之前,需要准备工作和环境检查: 1)兼容的 Linux 主机;我们使用 Ubuntu 20.04 TLS 发行版; 2)最少 2gMEM 资源; 3)2vCPU 4)集群中所有机器间的网络互联(公共或专用网络都可以),以及正确的网络配置; 5)每个节点 [hostname、mac address、product_uuid] 要唯一; 6)机器上的某些端口不能别占用,且要允许访问:6443; 7)禁用 SWAP 分区:

# 4)每个节点 [hostname、mac address、product_uuid] 要唯一;

ip link
hostname
cat /sys/class/dmi/id/product_uuid

# 检查主机网卡配置:
# 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

# 网络端口检查,确认开放比较端口
systemctl stop ufw
systemctl disable ufw
nc -v -z 127.0.0.1 6443

# 关闭 Swap 分区
# swapoff -a && sysctl -w vm.swappiness=0
yes | cp /etc/fstab /etc/fstab.backup
sed -i -E ‘s/(.+swap.+swap.+)/# \1/g’ /etc/fstab
swapof[……]

READ MORE

「Kubernetes」- 使用 containerd 环境、切换 Docker 为 containerd 环境

问题描述
# 04/18/2022 在 Kubernetes Cluster 中,我们又尝试使用 containerd 作为容器环境。
该笔记将记录:在 Kubernetes Cluster 中使用 containerd 的方法,以及相关问题的解决办法。
解决方案
阅读 Changing the Container Runtime on a Node from Docker Engine to containerd 文档,以获取容器运行时替换的更多细节。
v1.22.10-aliyun.1 => containerd://1.5.13
第零步、准备工作

kubectl drain –ignore-daemonsets –delete-emptydir-data <node-to-drain>

SSH> systemctl stop kubelet && systemctl disable docker.service –now

第一步、配置 containerd 服务
配置 Kernel 参数

cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

modprobe overlay
modprobe br_netfilter

# Setup required sysctl params, these persist across reboots.
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

# Apply sysctl params without reboot
sysctl –system

部署 containerd 服务
CRI/containerd
Kubernetes 1.22, containerd 1.5.13 Kubernetes 1.24, containerd 1.5.13
调整 containerd 参数

# vim /etc/containerd/config.toml

# 通过 Docker 仓库安装 continerd 服务,需要注释该行
# 否则 kubeadm join 失败:[ERROR CRI][……]

READ MORE

「K3S」- 搭建,高可用,嵌入式数据库

问题描述
在低资源的环境中,我们需要部署 Kubernetes 集群,最后我们选择 K3S 服务(轻量级的 Kubernetes 集群)。
该笔记将记录:在 Linux 中,如何部署高可用 K3S 集群,以及常见问题解决办法。
解决方案
选择 K3S 原因(毫无正经原因): 1)安装 Ubuntu Server 时候,推荐应用有 K3S 服务; 2)我们使用 Rancher 服务,而 K3S 为 Rancher Lab 出品;
选择内嵌数据库(etcd)的原因: 1)外置数据库需要做高可用:我们不想做 MySQL 高可用;
关于高可用,之前我们一直存在错误理解: 1)我们一直以为三个 Master 节点需要通过 VIP 才能实现高可用,这是错误的; —- 实际上 VIP 是提供给 Worker 进行连接的,提供唯一且稳定的 Master 地址; 3)另外 TLS SAN 需要包含该 VIP 的原因是: —- 当 VIP 漂移到节点后,通过 VIP 访问时要求 TLS 包含该 VIP 地址; —- 如果使用四层负载均衡,就不存在该问题,因为最终请求的仍旧是特定节点地址;
准备工作
准备工作便是阅读官方文档,形成对于该设施的基本认识,明确工作流程: 1)快速部署单节点集群:Quick-Start Guide 2)通过内嵌数据库的高可用架构: —- High-Availability K3s Server with an External DB —- High Availability with Embedded DB
环境信息
k3s-lb, 172.21.251.10, 四层负载均衡
# 鉴于使用 etcd 数据库,所以需要奇数个节点 # 这与 Kubernetes 类似 k3s-m1, 172.21.251.11, Master 01, 1vCPU/1G/10G k3s-m2, 172.21.251.12, Master 02, 1vCPU/1G/10G k3s-m3, 172.21.251.13, Master 03, 1vCPU/1G/10G
# 根据负载,增加自己需要的节点数量 k3s-w1, 172.21.251.21, Master 04 k3s-w2, 172.21.251.22, Master 05 k3s-w3, 172.21.251.23, Master 06 …
集群部署
第一步、创建主节点
操作节点:k3s-m1,k3s-m2,k3s-m3

# 创建首个主节点,k3s-m1
curl -sfL https://get.k3s.io \
| bash -s – server –cluster-i[……]

READ MORE

「Kubernetes」- Admission Controller

问题描述
该笔记将记录:在 Kubernetes 中,与 Admission Controller 有关的内容,以及常见问题的解决办法。
解决方案
查看已启用的 Admission Controller 插件
通过官方文档,能够获取默认启用的 Admission Controller 插件:Using Admission Controllers/Which plugins are enabled by default?
通过命令行查找,能够获取通过命令行启用的 Admission Controller 插件:ps -ef | grep apiserver | grep — –enable-admission-plugins
# 06/26/2021 目前,我们还没有“正规的”方法。
参考文献
Using Admission Controllers | Kubernetes kubectl – Kubernetes admission controllers check – Stack Overflow[……]

READ MORE

「Kubernetes」- 集群证书续期(重新申请证书,Part of the existing bootstrap client certificate is expired)

问题描述
集群无法访问,使用 journalctl -f -u kubelet.service 查看日志,提示如下错误:

11月 24 14:26:59 k8s-master1 kubelet[1768]: I1124 14:26:59.608288 1768 server.go:408] Version: v1.12.1
11月 24 14:26:59 k8s-master1 kubelet[1768]: I1124 14:26:59.608812 1768 plugins.go:99] No cloud provider specified.
11月 24 14:26:59 k8s-master1 kubelet[1768]: E1124 14:26:59.616261 1768 bootstrap.go:205] Part of the existing bootstrap client certificate is expired: 2019-11-23 12:18:53 +0000 UTC

原因分析
在 Kubernetes Cluster 中,当集群初时化时创建的证书一年到期。当到期后,集群的各个组件之间将无法访问,需要重新续期证书才能解决。

# kubeadm alpha certs check-expiration
[check-expiration] Reading configuration from the cluster…
[check-expiration] FYI: You can look at this config file with ‘kubectl -n kube-system get cm kubeadm-config -oyaml’

CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
admin.conf Feb 21, 2023 03:37 UTC 335d no
apiserver Feb 21, 2023 03:37 UTC 335d ca no
apiserver-etcd-client Feb 21, 2023 03:37 UTC 335d etcd-ca no[……]

READ MORE

「Kubernetes Cluster」- 添加额外的 SAN

问题描述
在 Kubernetes Cluster 中,certSANs 默认仅包含 Control Plane 地址,还可能包含 controlPlaneEndpoint 地址;
通过其他地址来访问集群,kubectl 将提示 Unable to connect to the server: x509: certificate is valid for xxx 错误;
该笔记将记录:向 certSANs 中添加新地址(或主机名)的方法,以及相关问题的解决方案;
解决方案
通过 –insecure-skip-tls-verify 选项,能够解决该问题,但在实际应用场景中,更新 certSAN 才是最终的解决方案。
在我们的场景中,为了方便 Control Plane 的管理,例如我们希望修改 Control Plane 地址;
第一步、更新配置文件

# kubectl -n kube-system get configmap kubeadm-config -o jsonpath='{.data.ClusterConfiguration}’ > kubeadm.yaml

# vim kubeadm.yaml

apiServer:
certSANs:
– “172.31.253.120”
– “172.31.253.121”
– “172.31.253.122”
– “172.31.253.123”
– “d3rm-infrastructure.kubernetes.d3rm.site”

# kubeadm init phase upload-config kubeadm –config kubeadm.yaml

# scp kubeadm.yaml root@controp-plane:/root/

第二步、更新节点证书
在所有控制节点中,执行如下命令:

# 否则 kubeadm 将不会重新创建证书
mv /etc/kubernetes/pki/apiserver.{crt,key} ~

# 更新节点证书
kubeadm init phase certs apiserver –config kubeadm.yaml -v=10

# 验证证书生效
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text | grep “X509v3 Subject Alternative Name:” -A 1

# 重启,或重启 Pod 实例
reboot

参考文献
Adding a Name to the Kubernetes API Server[……]

READ MORE

「Kubernetes」- Feature Gates

内容简介
此页面包含「管理员可以”在不同Kubernetes组件上“指定的各种功能」的简单概述,本文整理里工作中遇到的组件。
关于这些特性
在Kubernetes中,有多个组件,每个组件支持的特性也不相同。
管理员可以使用选项-h查看所有组件的所有特性,可以使用–feature-gates选项(–feature-gates=”…,DynamicKubeletConfig=true”)启动或关闭某个特性。
# AttachVolumeLimit
-「Node-specific Volume Limits」 该特性用于报告可以附加到节点的卷数限制。因为Google,Amazon,Microsoft等云商通常对可以连接到节点的卷数量进行限制。对于Kubernetes来说,反映这些限制很重要。否则,调度到节点上的Pod可能会因为等待卷挂载而卡住。
但是,我们是自己部署的集群,没有云商的限制,所有完全可以禁用它。
参考文献
Reference/Feature Gates[……]

READ MORE

「Kubernetes」- 部署 Web 应用(快速开始)

问题描述
1)管理 Kubernetes 基础的工作负载(Workloads):「部署」和「POD」; 2)通过命令行和 YAML 文件,创建「部署」和「POD」; 3)以及如何「伸缩」和「更新」部署;
该笔记将记录:在 Kubernetes Cluster 中,部署演示使用的 Web 应用,以快速入门;
解决方案
清单文件格式
kubectl 可以非常简单的部署一个对象,但是更多的细节需要通过清单文件控制;

kind: Pod
apiVersion: v1
metadata:
name: mypod
# 还可以包含 spec 字段
# spec:
# …

快速创建用于测试的网站(Nginx)
Run a Stateless Application Using a Deployment | Kubernetes

kubectl apply -f – <<EOF

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

apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
# type: NodePort
type: LoadBalancer
ports:
– port: 8080
targetPort: 80
selector:
app: nginx
EOF

Simple Website
MySQL

cat > mysql.yaml <<EOF

apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql[……]

READ MORE

「Docker Compose」- 迁移到 Kubernetes 集群

问题描述
我们需要将 Docker Compose 部署的应用迁移到 Kubernetes 集群。
该笔记将记录:如何将 Docker Compose 管理的应用迁移到 Kubernetes 集群。
解决方案
Kompose
Kubernetes + Compose = Kompose
用于将 docker-compose.yaml 转化 Kubernetes 资源文件(YAML)。
但是,它会生成很多 YAML 文件,对于我们来说过于零散,因此很少采用该工具。
14.4. Converting Your Docker Compose Files to Kubernetes Manifests
假设你通过Docker访问容器,并编写了Docker compose文件来定义多个容器的应用程序。现在如何使用 Kubernetes ,以及重用Docker compose文件?
可以使用 kompose 工具将Docker compose文件转换成 Kubernetest清单文件。
首先,从 GitHub 上下载kompose,为了方便起见加入到$PATH中。例如,在 Macos上可以运行如下命令:

# wget https: //github. com/kubernetes-incubator/k/releases/download/v1.6.0/kompose-darwin-amd64
# mv kompose-darwin-amd64/usr/local/bin/kompose
# chmod +x /usr/local/bin/kompose
# kompose version

如果有下列用于启动 redis 容器 Docker compose文件:(略过)
那么可以通过如下命令,将它自动转换成 Kubernetes清单文件:

# kompose convert –stdout

清单文件将显示在 stdout,其中是 Kubernetes服务和一个部署。想要自动创建这些对象,可以使用up命令,如下所示:

# kompose up

一些 Docker compose 指令不会被转化为 Kubernetes。这种情况下, compose将输出警告信息,通知你转换未成功。
一般来说不会有大问题,但是转换生成的清单文件可能无法在Kubernetes正常工作。这类的转换一般都不会太完美。然而,这些转换可以帮助你创建基本的 Kubernetes清单文件。最值得注意的是卷和网络隔离的处理一般都需要手动定制。
kompose conv[……]

READ MORE

「Kubernetes」- 注解(Annotation)

Annotating a Resource with One Command
Annotation(注解)的内容通常是通用的,非识别性的键值,而且可以是人类不可读的数据。
kubectl annotate pods foobar description=’something’
一般注解用于增加k8s的自动化。
例如,当使用kubectl run创建部署时,没有使用–record参数,那么历史记录里的change-cause一列为空。从1.6.0开始,可以使用kubectl annotate deployment foobar kubernetes.io/change-cause=’Reason foo'[……]

READ MORE

「Kubernetes Objects」- Labels and Selectors

Labeling an Object
为对象创建标签:

kubectl label pods foobar demo=mark

可以快速的更新和处理对象。
标签和“随意”命名,但是不能和系统中的冲突。命名要符合规范:「Labels and Selectors」
Using Labels for Queries
使用命令:kubectl get pods –show-labels
获取POD的标签:kubectl get pods –show-labels
根据指定标签获取:kubectl get pods –selector app=cockroachdb
标签是元数据的一部分,任何对象可以被标记,在Deployment和Service中可以使用标签选择Pod。
除了使用kubectl label命令,还可以在清单文件中指定:

kind: Pod
apiVersion: v1
metadaa:
name; foobar
labels:
tier: frontend

选项-l和–selector是等价的:kubectl get pods -l run=foobar
选项–show-labels显示所有的标签:kubectl get pods –show-labels
选项-L将额外添加一个列,用以返回指定标签的值:kubectl get pods -L run
很多对象都支持以集合方式查询。例如:kubectl get pods -l ‘env in (production, development)’
相关文档
Kubernetes v1.16/CONCEPTS/Labels and Selectors Kubernetes v1.16/API OVERVIEW/LabelSelector v1 meta[……]

READ MORE

「Kubernetes Objects」- Managing Compute Resources(学习笔记)

相关文档及博客
Kubernetes v1.16/Managing Compute Resources for Containers Kubernetes v1.16/Assign Memory Resources to Containers and Pods Kubernetes v1.16/Assign CPU Resources to Containers and Pods
资源限制示例
Resource Management for Pods and Containers | Kubernetes


apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
– name: app
image: images.my-company.example/app:v4
resources:
requests:
memory: “64Mi”
cpu: “250m”
limits:
memory: “128Mi”
cpu: “500m”
– name: log-aggregator
image: images.my-company.example/log-aggregator:v6
resources:
requests:
memory: “64Mi”
cpu: “250m”
limits:
memory: “128Mi”
cpu: “500m”

管理的资源类型
CPU and memory
CPU and memory are each a resource type. CPU and memory are collectively referred to as compute resources, or just resources.
CPU is specified in units of cores
memory is specified in units of bytes
If you’re using Kubernetes v1.14 or newer, you can specify huge page resources.
local ephemeral storage
Kubernetes version 1.8 introduces a new resource, ephemeral-storage for managing local ephemera[……]

READ MORE

「Kubernetes」- 容器资源管理

TODO ! 限制容器使用的资源
Setting Quotas Within a Namespace
操作,在命名空间下创建配额:

# foo.yaml
kind: ResourceQuota
apiVersion: v1
metadata:
name: podquota
namespace: my-app
spec
hard:
pods: “10”

kubectl create namespace my-app kubectl create -f foo.yaml –namespace=my-app kubectl describe resourcequota podquota –namespace=my-app
可以对一系列的对象进行配额限制,包括但不限于Pod、Secret、ConfigMap。
参考文献:「Configure Quotas for API Objects」
相关链接
Managing Compute Resources for Containers Assign CPU Resources to Containers and Pods Kubernetes 给容器和Pod分配内存资源[……]

READ MORE

「Kubernetes Objects」- CronJob(学习笔记)

CronJob 类似于 Linux 中的 crontab,用于定义定时任务。每个 CronJob 对象相当于 crontab 中的一行配置。
可以使用k8s的CronJob对象,来运行定时任务。CronJob集成了更加通用的Job对象。
定义 CronJob 对象

apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: “*/1 * * * *”
jobTemplate:
spec:
template:
spec:
containers:
– name: hello
image: busybox
args:
– /bin/sh
– -c
– date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure

7.2. Running a Task on a Schedule Within a Pod
定时CronJob时额外增加一个schedule一节,其采用的是crontab格式:

kind: CronJob
apiVersion: batch/v2alpha1
metadata:
name: hourly-date
spec:
schedule: “0 * * * *”
jobTemplate:
spec:
template:
spec:
container:
– name: date
image: busybox
command:
– “sh”
– “-c”
– “date”
restartPolicy: OnFailure

参考CronJob手册:「CronJob」
注意事项
关于 Kubernetes CronJob 调度(重要)
所有 CronJob 调度时间都是基于 kube-controller-manager 的时区。也就是说如果 kube-controller-manager 的时区设置不正确,将无法正确进行调度,尤其是对于在特定时间运行的任务(对于周期性任务没有影响,比如每分钟运行)。
在默认情况下,kube-controll[……]

READ MORE

「Kubernetes Objects」- DaemonSet

问题描述
启动日志收集器,或者监控代理等基础设施服务,都需要每个节点上运行一个 POD 实例
解决方案
使用 DaemonSet 服务;
例如,每个节点上运行一个 Fluentd 的容器服务,
按照以下的例子,编写一个 fluentd-daemonset.yaml 文件:

kind: DaemonSet
apiVersion: extensions/v1beat1
metadata:
name: fluentd
spec:
template:
metadata:
name: fluentd
labels:
app: fluented
spec:
containers:
– name: fluentd
image: ‘gci.io/google_conntainers/fluentd-elasticsearch:1.3’
env:
– name: FLUENTD_ARGS
value: ‘-qq’
columeMounts:
– name: varlog
mountPath: /var/log
– name: containers
mountPath: /var/lib/docker/containers
volumes:
– hostPath:
path: /var/log
name: varlog
– hostPath:
path: /var/lib/docker/containers
name: containers

部署资源文件:

kubectl craete -f fluented-daemonset.yaml

kubectl get ds

kubectl describe ds/fluentd

数据存储(PVE)
storageclass & pvc for daemonset
针对 DaemonSet 类型,所有的 Pod 将共享相同的 PVC 资源。
如果每个 Pod 需要独立的数据存储: 1)需要通过应用程序控制,限制当前 Pod 写入目录(诸如 目录锁 等等); 2)通过 hostPath 将数据写入节点; 3)
原理及调度
Q:PodTolerationRestriction[……]

READ MORE

「Kubernetes Objects」- Deployment

问题描述
Deployment(部署),提供管理 Pod 的方法
该笔记将记录:在 Kubernetes 中,与 Deployment 相关的内容,以及常见问题的解决方案;
解决方案
创建(增)
通过 kubectl create deployment 创建:

kubectl create deployment –dry-run -o yaml \
–namespace storage-util fio \
–image=xridge/fio –replicas=1 — sleep infinity | kubectl neat > fio.yaml

导出 Deployment 定义:

kubectl get -n “namespace” deployment “deployment-name” -o yaml –export

修改(改)
修改 Deployment 镜像(How can I edit a Deployment without modify the file manually?):

kubectl set -n “namespace” image “deployment/deploy-foo” “deploy-foo”=”image-name”

打开编辑器修改 Deployment 信息:

kubectl edit deployment/myapp-deployment –image=172.20.34.206:5000/myapp:img:3.0
kubectl edit deployment kubernet-dashboard -n kube-system
kubectl patch deployment “deployment-name” -p “{……}”

查看(查)
查看 Deployment 信息:

kubectl get deployment kubernet-dashboard -n kube-system

更新策略
Rolling update strategy(默认更新策略)
牺牲更新速度,以减少停机时间;

apiVersion: apps/v1 #Older versions of k8s use apps/v1beta1
kind: Deployment
metadata:
name: hello-deploy
spec:
minReadySeconds: 10
strategy:[……]

READ MORE

「Kubernetes Objects」- Job

问题描述
本部分介绍在Kubernetes中与Job有关的内容。
解决方案
运行批处理,比如要进行某个非常耗时的任务。
此时可以创建JOb对象:

kind: Job
apiVersion: batch/v1
metadata:
name: counter
spec:
template:
metadata:
name: counter
spec:
containers:
– name: counter
image: busybox
command:
– “sh”
– “-c”
– “for i in 1 2 3; do echo $i ; done”
restartPolicy: Never

查看Job日志:kubectl logs jobs/counter
删除Job对象:kubectl delete jobs/counter
参考文献
Kubernetes/Concepts/Jobs – Run to Completion[……]

READ MORE

「Kubernetes Objects」- StatefulSets(学习笔记)

问题描述
该笔记将整理:StatefulSet 对象相关的内容,是官方文档的学习笔记;
解决方案
StatefulSets,用于管理「有状态应用」的工作负载 API 对象。它管理一组 Pod 的部署和扩展,并保证这些 Pod 的顺序和唯一性。 像「Deployment」一样,「StatefulSet」基于相同容器规范对 Pod 进行管理。与「Deployment」不同,「StatefulSet」为其每个 Pod 绑定一个标识。这些 Pod 是根据相同的规范创建的,但不能互换:每个 Pod 都有一个永久性标识,在所有重新调度中都会保持该标识;
7.4. Managing Stateful and Leader/Follower Apps
StatefulSet 是一个控制器,为监控的 POD 提供唯一的身份;
出于安全考虑,删除 POD 不会删除对应的卷;
参考 cockroachdb-statefulset.yaml 文档,以获取关于 StatefulSet 相关的示例;
数据存储(PVC)
Why StatefulSets? Can’t a stateless Pod use persistent volumes?
通过 volumeClaimTemplates 属性,能够为 StatefulSet 的 Pod 提供稳定的存储,其确保 Pod 重新调度时将关联到固定的 PVC 实例。
参考文献
StatefulSets | Kubernetes Kubernetes/Concepts/StatefulSets Kubernetes/Tutorials/StatefulSet Basics[……]

READ MORE

「Kubernetes Objects」- Ingress 常见问题处理

关于 apiVersion 字段
Deprecated API Migration Guide | Kubernetes
我们讲过很多不同版本的 apiVersion 字段: 1)apiVersion: extensions/v1beta1 2)apiVersion: networking.k8s.io/v1beta1 3)apiVersion: networking.k8s.io/v1
正常的 APIVersion 升级,我们根据集群版本进行调整资源声明: 1)extensions/v1beta1 与 networking.k8s.io/v1beta1 从 v1.22 不再可用; 2)networking.k8s.io/v1 从 v1.19 开始可用,并引入很多新的属性字段;
Basic Auth
Nginx-ingress Kubernetes routing with basic auth – Stack Overflow
注意事项,我们使用 Nginx Ingress Controller 组件,所以很多示例配置都与之相关。
第一步、创建 Secret 凭证
创建用于 Basic Auth 认证的 Secret 凭证:

$ htpasswd -c auth foo
New password: <bar>
New password:
Re-type new password:
Adding password for user foo

$ kubectl create secret generic basic-auth –from-file=auth
secret “basic-auth” created

$ kubectl get secret basic-auth -o yaml
apiVersion: v1
data:
auth: Zm9vOiRhcHIxJE9GRzNYeWJwJGNrTDBGSERBa29YWUlsSDkuY3lzVDAK
kind: Secret
metadata:
name: basic-auth
namespace: default
type: Opaque

注意事项:该凭证必须包含 名为 auth 的 Key,否则将产生 503 错误;
第二步、添加 Ingress 注解


metadata:
annotations:

nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth[……]

READ MORE

「NGINX Ingress Controller」- 修改默认重定向状态码(IE8 无法跳转)

问题描述
在 NGINX Ingress Controller 中,开启强制 SSL 跳转之后,当访问 HTTP 时将被重定向到 HTTPS 地址。
但是在 IE8 浏览器中,无法正常跳转(虽然现在基本以及忽略 IE8 浏览器),我们需要解决这个问题。
原因分析
默认 NGINX Ingress Controller 返回 308 重定向,但是 IE8 浏览器不支持 308 状态码。同时 Permanent redirect 308 not supported in IE11 #1825 指出 IE11 浏览器也不支持 308 状态码。所以导致浏览器无法正常跳转。
当使用 308 状态码时,在重定向 POST 请求时可以保留“有效载荷”(简单理解成 POST 请求的数据即可)。
解决方案
我们只能修改返回状态码,而不再使用 308 状态码。
这需要修改 Nginx 的 ConfigMap 对象,添加 http-redirect-code: “301” 配置。配置文件结构大致如下:

apiVersion: v1
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
name: nginx-configuration
namespace: ingress-nginx
data:
http-redirect-code: “301”

参考文献
Permanent redirect 308 not supported in IE11 #1825 Change default redirect to 301 to support old internet explorer versions #2002 Kubernetes Nginx Ingress HTTP to HTTPS redirect via 301 instead of 308? NGINX Ingress Controller/ConfigMaps/http-redirect-code[……]

READ MORE