市面上很多kubeadm的文章都是错误示范或者不够详细,大多数都没写系统设置之类的就直接kubeadm init
导致很多跟着做的人会报错
我期望看到本文的读者最少具备以下知识:
- Linux一些目录规范和systemd
- 学过一点docker
- 懂dns和/etc/hosts、curl互相结合来测试一些web的接口响应状态
- 不要求github有自己项目,至少会浏览github
本教学将以下列节点数与规格来进行部署Kubernetes集群,系统CentOS 7.6+
,有条件7.8
,不要使用centos7.4以及一下,容器技术依赖于内核技术,低版本系统部署和运行后问题会非常多。有读者用debian10测试过了,apt系列的ubuntu应该16.04以上也行。总之本教程使用yum系列的系统和apt的系统
IP | Hostname | role | CPU | Memory |
---|---|---|---|---|
172.19.0.2 | K8S-M1 | master | 4 | 8G |
172.19.0.3 | K8S-M2 | master | 4 | 8G |
172.19.0.4 | K8S-M3 | master | 4 | 8G |
172.19.0.5 | K8S-N1 | node | 2 | 4G |
- kubeadm好像要求最低配置2c2g还是多少来着,云主机的话如果是新手最好在同一个vpc内的机器整
- 所有操作全部用root使用者进行,系统盘尽量大点,不然到时候镜像多了例如到了85%会被gc回收镜像
- 高可用一般建议大于等于3台的奇数台,我使用3台
master
来做高可用,如果是虚机的话最好不要克隆,所以机器都要是静态ip,别配置dhcp- 一台也可以,但是差距不大,差异性我会在文章中注明的,并且单台master的话其他的master ip不用写即可
事前准备(每台机器)
系统层面设置
假设系统是刚用官方 iso 安装完成未作任何配置(网络和dns自行去配置),apt 系列的系统可能需要自行配制下国内的包管理源。对于各系统的差异性我会在命令前加系统区别开,没有声明系统的就是通用的命名
所有防火墙与 SELinux 已关闭。如 CentOS:
否则后续 K8S 挂载目录时可能报错 Permission denied,有些云厂商的 ip 是被 NetworkManager 纳管的(例如青云),停了它会网络不通,可以不停。
yum系列系统:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18systemctl disable --now firewalld NetworkManager
# 不关闭 NetworkManager 的话执行下面的 -------------------
cat> /etc/NetworkManager/conf.d/k8s.conf << 'EOF'
[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:tunl*;interface-name:vxlan.calico;interface-name:flannel*;interface-name:veth*;interface-name:cni0;interface-name:docker0
# nmcli con show 显示 uuid
# 解决nmcli con show <uuid> | grep ipv4.dns 为空
# 机器重启后 /etc/resolv.conf 为空 nameserver 的问题
[main]
dns=none
EOF
systemctl restart NetworkManager
#-------------------
#关闭selinux
setenforce 0
sed -ri '/^[^#]*SELINUX=/s#=.+$#=disabled#' /etc/selinux/configapt系列系统:
1
ufw disable
设置时区
1
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
关闭 dnsmasq (可选)
linux 系统开启了 dnsmasq 后(如 GUI 环境),将系统 DNS Server 设置为 127.0.0.1,这会导致 docker 容器无法解析域名,需要关闭它1
systemctl disable --now dnsmasq
核查下
cat /etc/resolv.conf
coredns会proxy 非集群的 search(也就是pod访问外网,这个就是集群外的解析)到它自己的/etc/resolv.conf
里的nameserver
,这个文件内容会和宿主机一样,有的apt系统会把dns解析到127.0.0.xx
本地跑一个dns server,代理本地的所有 dns 请求到公网,这样会导致 pod 无法解析外网的域名1
2search lan
nameserver 127.0.0.xx文件有上面内容的话自行配置下,dns 上游改成公网的 dns 或者内网的 dns server,去掉 search 行
Kubernetes 建议关闭系统 Swap,在
所有机器
使用以下指令关闭 swap 并注释掉/etc/fstab
中 swap 的行,不想关闭可以不执行,后面会应对的配置选项:
1 | swapoff -a && sysctl -w vm.swappiness=0 |
- 安装一些基础依赖和工具
yum系列系统:
1 | yum install epel-release -y |
apt系列系统:
1 | apt-get update && apt-get install -y wget \ |
- 如果集群 kube-proxy 想使用 ipvs 模式的话需要开机加载下列模块儿,按照规范使用
systemd-modules-load
来加载而不是在/etc/rc.local
里写modprobeapt 系列的系统先使用1
2
3
4
5
6
7
8
9
10
11
12:> /etc/modules-load.d/ipvs.conf
module=(
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
br_netfilter
)
for kernel_module in ${module[@]};do
/sbin/modinfo -F filename $kernel_module |& grep -qv ERROR && echo $kernel_module >> /etc/modules-load.d/ipvs.conf || :
donesystemctl cat systemd-modules-load
看下有没有Install
段,没有则执行下面启动该模块管理服务1
2
3
4cat>>/usr/lib/systemd/system/systemd-modules-load.service<<EOF
[Install]
WantedBy=multi-user.target
EOF1
2systemctl daemon-reload
systemctl enable --now systemd-modules-load.service
上面如果 systemctl enable
命令报错可以 systemctl status -l systemd-modules-load.service
看看哪个内核模块加载不了,在 /etc/modules-load.d/ipvs.conf
里注释掉它再 enable 试试
确认内核模块加载
1 | $ lsmod | grep ip_v |
所有机器
需要设定/etc/sysctl.d/k8s.conf
的系统参数,目前对 ipv6 支持不怎么好,所以里面也关闭 ipv6了。如果选择关闭 swap 也要在内核里关闭,不关闭可以不执行1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29cat <<EOF > /etc/sysctl.d/k8s.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv4.neigh.default.gc_stale_time = 120
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
net.ipv4.ip_forward = 1
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_synack_retries = 2
# 要求iptables不对bridge的数据进行处理
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-arptables = 1
net.netfilter.nf_conntrack_max = 2310720
fs.inotify.max_user_watches=89100
fs.may_detach_mounts = 1
fs.file-max = 52706963
fs.nr_open = 52706963
vm.overcommit_memory=1
vm.panic_on_oom=0
EOF
sysctl --system1
echo 'vm.swappiness = 0' >> /etc/sysctl.d/k8s.conf
如果 kube-proxy 使用 ipvs 的话为了防止 timeout 需要设置下 tcp 参数
1 | cat <<EOF >> /etc/sysctl.d/k8s.conf |
优化设置 journal 日志相关,避免日志重复搜集,浪费系统资源。修改systemctl启动的最小文件打开数量。关闭ssh反向dns解析
1
2
3
4
5
6
7
8# 下面两句apt系列系统没有,执行不影响
sed -ri 's/^\$ModLoad imjournal/#&/' /etc/rsyslog.conf
sed -ri 's/^\$IMJournalStateFile/#&/' /etc/rsyslog.conf
sed -ri 's/^#(DefaultLimitCORE)=/\1=100000/' /etc/systemd/system.conf
sed -ri 's/^#(DefaultLimitNOFILE)=/\1=100000/' /etc/systemd/system.conf
sed -ri 's/^#(UseDNS )yes/\1no/' /etc/ssh/sshd_config文件最大打开数,按照规范,在子配置文件写
1
2
3
4
5
6
7
8
9
10cat>/etc/security/limits.d/kubernetes.conf<<EOF
* soft nproc 131072
* hard nproc 131072
* soft nofile 131072
* hard nofile 131072
root soft nproc 131072
root hard nproc 131072
root soft nofile 131072
root hard nofile 131072
EOF
集群的HA依赖于时间一致性,安装并配置chrony
yum:
1 | yum install -y chrony |
apt:
1 | apt-get install -y chrony |
配置文件
1 | cat>/etc/chrony.conf<<EOF |
修改hostname
kubelet和kube-proxy上报node信息默认是取hostname的,除非通过--hostname-override
指定,这里自行设置hostname1
hostnamectl set-hostname xxx
docker官方的内核检查脚本建议
(RHEL7/CentOS7: User namespaces disabled; add 'user_namespace.enable=1' to boot command line)
,如果是yum系列的系统使用下面命令开启,apt类型的系统不需要
yum:1
grubby --args="user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"
重启系统
1 | reboot |
安装docker
- 检查系统内核和模块是否适合运行 docker (仅适用于 linux 系统),该脚本可能因为墙的原因无法生成,可以先去掉重定向看看能不能访问到脚本现在docker存储驱动都是使用的overlay2(不要使用devicemapper,这个坑非常多),我们重点关注overlay2是否不是绿色
1
2curl -s https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh > check-config.sh
bash ./check-config.sh
这里我们使用年份命名版本的docker-ce,假设我们要安装v1.18.6
的k8s,我们去 https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG 里进对应版本的CHANGELOG-1.18.md
里搜The list of validated docker versions remain
查找官方验证过的docker版本,docker版本不一定得在列表里,实际上测试过19.03也能使用(19.03+修复了runc的一个性能bug),这里我们使用docker官方的安装脚本安装docker(该脚本支持centos和ubuntu)。阿里和azure 的 docker-ce.repo 文件里都是从官方源同步过来的,这个文件里地址还是指向官方,所以我们得加个sed修改下再执行。
1 | export VERSION=19.03 |
所有机器
配置加速源并配置docker的启动参数使用systemd,使用 systemd 是官方的建议,详见 https://kubernetes.io/zh/docs/setup/production-environment/container-runtimes/#cgroup-%E9%A9%B1%E5%8A%A8%E7%A8%8B%E5%BA%8F1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24mkdir -p /etc/docker/
cat>/etc/docker/daemon.json<<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": [
"https://fz5yth0r.mirror.aliyuncs.com",
"https://dockerhub.mirrors.nwafu.edu.cn/",
"https://mirror.ccs.tencentyun.com",
"https://docker.mirrors.ustc.edu.cn/",
"https://reg-mirror.qiniu.com",
"http://hub-mirror.c.163.com/",
"https://registry.docker-cn.com"
],
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
EOFLive Restore Enabled
这个千万别开,某些极端情况下容器Dead状态之类的必须重启docker daemon才能解决,开了就只能重启机器解决了CentOS安装完成后docker需要手动设置docker命令补全:
1 | yum install -y epel-release bash-completion |
apt系列操作为取消文件/etc/bash.bashrc
内下面行的注释
1 | # enable bash completion in interactive shells |
复制补全脚本
1 | cp /usr/share/bash-completion/completions/docker /etc/bash_completion.d/ |
- 防止FORWARD的DROP策略影响转发,给docker daemon添加下列参数修正,当然暴力点也可以
iptables -P FORWARD ACCEPT
1 | mkdir -p /etc/systemd/system/docker.service.d/ |
启动docker并看下信息是否正常
1 | systemctl enable --now docker |
如果enable docker的时候报错开启debug,如何开见 https://github.com/zhangguanzhang/Kubernetes-ansible/wiki/systemctl-running-debug
- 物理机的话切到非省电模式,apt系列系统暂时不知道,省电模式cpu频率低,见 https://zhangguanzhang.github.io/2019/04/28/k8s-java-start-time-not-same/#%E6%AD%A3%E7%A1%AE%E5%A7%BF%E5%8A%BF
1
tuned-adm profile throughput-performance
kubeadm部署
安装kubeadm相关
默认源在国外会无法安装,我们使用国内的镜像源,所有机器都要操作
yum:
1 | cat <<EOF >/etc/yum.repos.d/kubernetes.repo |
apt:
1 | curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add - |
master部分
k8s的node就是kubelet+cri(一般是docker),kubectl 是一个 agent 读取 kubeconfig 去访问 kube-apiserver 来操作集群,kubeadm 是部署,所以 master 节点需要安装三个,node 一般不需要 kubectl
安装相关软件
yum: 如果依赖错误,yum命令后面加个--setopt=obsoletes=0
1 | yum install -y \ |
apt:
1 | apt-get install -y \ |
node
1 | yum install -y \ |
1 | apt-get install -y \ |
配置kubelet的参数方法(有需要的话)
查看kubelet的systemd文件
1 | systemctl cat kubelet |
我们可以看到/etc/sysconfig/kubelet
是EnvironmentFile
,里面注释也写明了我们应该在该文件里写KUBELET_EXTRA_ARGS
来给kubelet配置运行参数,下面是个例子,具体参数啥的可以kubelet --help
看
1 | cat >/etc/sysconfig/kubelet<<EOF |
文件/var/lib/kubelet/kubeadm-flags.env
也一样
如果自己离线的话这块儿实际上就是二进制文件+systemd,可以自己去剥离成离线,同时systemd不要完全抄官方的,可以简单写,例如不要像kubelet的systemd那样拼变量
配置HA,所有机器(单个master跳过此步)
关于HA我博客 https://zhangguanzhang.github.io/2019/03/11/k8s-ha/ 说得很清楚,这里我用nginx实现local proxy来玩(配置文件来源于kubespray),因为 localproxy 是每台机器上的,可以不用SLB和无视在云上vpc里无法使用vip的限制,需要每个机器上运行nginx实现
每台机器(master+node)配置hosts
1 | cat >>/etc/hosts << EOF |
每台机器(master+node)生成配置文件,上面的三个hosts可以不写,不写的话下面配置文件里的域名得使用ip即可,但是这样更改ip需要重新加载,所以推荐还是写域名。
1 | mkdir -p /etc/kubernetes |
因为 localproxy 是每台机器上的,可以不用 SLB 和 vpc 无法使用 vip 的限制,这里我使用容器运行 nginx,当然自己也可以写成 staticPod 的 yaml 在 init 的阶段放入目录里
1 | docker run --restart=always \ |
配置集群信息(第一个master上配置)
- 打印默认init的配置信息
1 | kubeadm config print init-defaults > initconfig.yaml |
我们看下默认init的集群参数
1 | apiVersion: kubeadm.k8s.io/v1beta2 |
我们主要关注和只保留ClusterConfiguration
的段,然后修改下,可以参考下列的v1beta2
文档,如果是低版本可能是v1beta1
,某些字段和新的是不一样的,自行查找godoc看
https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2#hdr-Basics
https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2
https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2#pkg-constants
https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2#ClusterConfiguration
ip 啥的自行更改成和自己的一致,cidr 不懂咋计算就别乱改。controlPlaneEndpoint
写域名(内网没dns所有机器写hosts也行)或者SLB,VIP,原因和注意事项见 https://zhangguanzhang.github.io/2019/03/11/k8s-ha/ 这个文章我把 HA 解释得很清楚了,不要再问我了,下面是最终的yaml
1 | apiVersion: kubeadm.k8s.io/v1beta2 |
- swap的话看最后一行
- 单台master的话把
controlPlaneEndpoint
的值改为第一个master的ip - etcd的支持版本可以去代码里查看
- 如果apiserver 前面接了云厂商的 SLB 的话,SLB 也配置了公网 ip,或者 master 的机器有公网 ip,可以把 公网ip 或者 域名 加到所有的
certSANs
里 - 上面yaml文件里涉及到ip的地方都更改为自己对应的ip
- 镜像这部分别像市面上普遍文章里拉 mirror 然后改名
k8s.gcr.io
的,系统容量到了一定百分比后会gc掉镜像,你镜像名是k8s.gcr.io
会在 gc 掉后无法拉取镜像。所以不建议这样做,而是设置一个能拉取的repo kubectl get cs
依赖的端口已经准备在 1.19 里删掉了,所以你监控就别依赖这个了,要开的话在controllerManager
和scheduler
的extraArgs
加port: 1025x
- 例如
10.95.0.0/12
实际上是在10.80.0.0/12
的子网范围里,不会确定可以在线找个 cidr 计算下。不要写成子网了。
- 检查文件是否错误,忽略
warning
,错误的话会抛出error
,没错则会输出到包含字符串kubeadm join xxx
啥的
1 | kubeadm init --config initconfig.yaml --dry-run |
- 检查镜像是否正确,版本号不正确就把yaml里的
kubernetesVersion
取消注释写上自己对应的版本号
1 | kubeadm config images list --config initconfig.yaml |
- 预先拉取镜像
1 | kubeadm config images pull --config initconfig.yaml # 下面是输出 |
kubeadm init
init(只在第一个master上面操作)
下面init只在第一个master上面操作
1 | # --experimental-upload-certs 参数的意思为将相关的证书直接上传到etcd中保存,这样省去我们手动分发证书的过程 |
如果超时了看看是不是kubelet没起来,调试见 https://github.com/zhangguanzhang/Kubernetes-ansible/wiki/systemctl-running-debug
记住init后打印的token(记不住或者ttl过期了看后面),复制kubectl的kubeconfig,kubectl的kubeconfig路径默认是~/.kube/config
1 | mkdir -p $HOME/.kube |
init的yaml信息实际上会存在集群的configmap里,我们可以随时查看,该yaml在其他node和master join的时候会使用到
1 | kubectl -n kube-system get cm kubeadm-config -o yaml |
如果单个master,也不想整其他的node,需要去掉master节点上的污点,多master一般是+n个node的,所以一般是不需要去掉master上的污点的
1 | kubectl taint nodes --all node-role.kubernetes.io/master- |
设置ep的rbac
kube-apiserver的web健康检查路由有权限,我们需要开放用来监控或者对接SLB的健康检查,yaml文件 https://github.com/zhangguanzhang/Kubernetes-ansible-base/blob/roles/master/files/healthz-rbac.yml 。因为网络因素而无法apply的话就自己下载或者赋值内容后创建文件后apply文件
1 | kubectl apply -f https://raw.githubusercontent.com/zhangguanzhang/Kubernetes-ansible-base/roles/master/files/healthz-rbac.yml |
配置其他master的k8s管理组件
手动拷贝(某些低版本不支持上传证书的时候操作,如果前面kubeadm init的时候加了上传证书选项这步不用执行)
如果前面kubeadm init的时候加了上传证书选项这步不用执行
第一个master上拷贝ca证书到其他master节点上,因为交互输入密码,我们安装sshpass,zhangguanzhang是root密码
1 | yum install sshpass -y |
复制ca证书到其他master节点
1 | for node in 172.19.0.3 172.19.0.4;do |
其他master join进来
注意是前面init最后输出的命令里选择长串的,不是短串,短传的是node,不是master
1 | mkdir /var/lib/etcd |
token忘记或者ttl过期了的话可以kubeadm token list
查看,可以通过kubeadm token create --print-join-command
查看,老版本不确定支持--print-join-command
这个选项,不支持的话就不带这个选项创建token,
sha256的值可以通过下列命令获取
1 | openssl x509 -pubkey -in \ |
所有master配置kubectl
准备kubectl的kubeconfig
1 | mkdir -p $HOME/.kube |
设置kubectl的补全脚本
1 | kubectl completion bash > /etc/bash_completion.d/kubectl |
所有master配置etcd备份
复制出容器里的etcdctl
1 | docker cp `docker ps -a | awk '/k8s_etcd/{print $1}'`:/usr/local/bin/etcdctl /usr/local/bin/etcdctl |
1.13还是具体哪个版本后k8s默认使用v3 api的etcd,这里我们配置下etcdctl的参数
1 | cat >/etc/profile.d/etcd.sh<<'EOF' |
重新ssh下或者手动加载下环境变量. /etc/profile.d/etcd.sh
1 | etcd_v3 endpoint status --write-out=table # 下面是输出 |
配置etcd备份脚本
1 | mkdir -p /opt/etcd |
crontab -e添加下面内容自动保留四个备份副本,下面是每天凌晨2点备份,最大保留4个备份副本
1 | 0 2 * * * bash /opt/etcd/etcd_cron.sh -c 4 -d /opt/etcd/ &>/dev/null |
node
按照前面的做:
- 配置系统设置
- 设置hostname
- 安装docker-ce
- 设置hosts和nginx
- 配置软件源,安装kubeadm kubelet
和master的join一样,提前准备好环境和docker,然后join的时候不需要带--control-plane
,只有一个master的话join的那个ip写controlPlaneEndpoint
的值
1 | $ kubectl get node -o wide |
ROLES
只是一个label,可以打 label 让其显示指定的字符串,想显示啥就node-role.kubernetes.io/xxxx
1 | kubectl label node k8s-n1 node-role.kubernetes.io/node="" |
addon(此章开始到结尾选取任意一个master上执行)
容器的网络还没处理好,coredns无法分配到ip会处于pending
状态,这里我用flannel部署,如果你了解 bgp 可以使用 calico
yaml文件来源与 flannel 官方github https://github.com/coreos/flannel/tree/master/Documentation
如果之前环境部署过 calico,这里想使用 flannel,请确保目录 /etc/cni/net.d/
里无非 flannel 的文件
1 | wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml |
修改
如果是在1.16之前使用psp,
policy/v1beta1
得修改成extensions/v1beta1
1
2apiVersion: policy/v1beta1
kind: PodSecurityPolicyrbac的version改为下面,不要使用
v1beta1
了,使用下面命令修改1
sed -ri '/apiVersion: rbac/s#v1.+#v1#' kube-flannel.yml
官方yaml自带了四种架构的daemonset,我们删掉除了amd64 以外的,大概是226行到结尾,文件行数可能会变,这里我用 shell 取行数来删除
1 | NUM=`awk '{if(/^apiVersion: apps\/v1/){a++};if(a==2){print NR;exit}}' kube-flannel.yml` |
pod的cidr修改了的话这里也要修改,如果是在同一个二层,可以使用把
vxlan
改为性能更强的host-gw
模式,vxlan的话需要安全组放开8472端口的udp1
2
3
4
5
6
7net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}这步可以先不改,如果flannel一直crash(某些版本下 request 和 limit 一样会频繁crash,实际上这种pod的优先级比较高)就修改下limits,需要大于request
1 | ... |
部署flannel
1.15后 node 的 cidr 是数组,而不是单个了,在一些非最新版本部署的话会有下列错误,见文档
https://github.com/kubernetes/kubernetes/blob/v1.15.0/staging/src/k8s.io/api/core/v1/types.go#L3890-L3893
https://github.com/kubernetes/kubernetes/blob/v1.18.6/staging/src/k8s.io/api/core/v1/types.go#L4269-L4279
1 | Error registering network: failed to acquire lease: node "xxx" pod cidr not assigned |
手动打patch,后续扩的 node 也记得打下,新版本会处理老的和新的字段的 cidr 值,所以下面是判断为空则 patch ,兼容1.15后面所有版本。如果此处写自动化部署可以根据版本看是否需要打patch
1 | nodes=`kubectl get node --no-headers | awk '{print $1}'` |
1 | kubectl apply -f kube-flannel.yml |
验证集群可用性
验证
1 | kubectl -n kube-system get pod -o wide |
等待 kube-system 空间下的 pod 都是 Running 后我们来测试下集群可用性
1 | cat<<EOF | kubectl apply -f - |
等待 pod running
1 | kubectl get po,svc -o wide |
验证集群dns解析
1 | kubectl exec -ti busybox -- nslookup kubernetes |
如果不是2秒以内返回,而且是vxlan模式下不正常则看这篇文章k8s vxlan63秒延迟解决 1.18.6,1.16.13,1.17.9已经修复这个问题了,但是如果你版本是1.17.0-1.18.5就会有这个问题,你处于1.17.0-1.18.5
版本的话不想全部升级可以单独去切 kube-proxy 的版本例如下面
1 | kubectl -n kube-system set image daemonset/kube-proxy *=registry.aliyuncs.com/k8sxio/kube-proxy:v1.18.6 |
同样的也可以node上用dig测pod的overlay网络:
1 | dig @10.96.0.10 +short kubernetes.default.svc.cluster.local |
在master上curl nginx的svc的ip出现nginx的index内容即集群正常,例如我的nginx svc ip是10.100.39.101
1 | curl -s 10.100.39.101 |
pod里验证集群域名到pod是否正常
1 | $ kubectl exec -ti busybox -- curl nginx |
清理测试的pod
1 | kubectl delete deploy nginx |
关于使用kubeadm的注意事项和个人建议
- 小白不要着急啥都往上部署,例如dashboard和什么helm,没这个必要,先把命令行的kubectl和一些基础学会了
- 默认证书是只有一年的,可以自己去修改源码更改
- 先去把官方文档的concept和tasks板块看完,市面上的书籍和教程实际上都是讲的这俩板块儿
- 不懂网络的话去找点CCIE的教程看下
- systemd和docker以及Linux基础都是挺重要的,–help找选项很多人居然都不会
- yaml,yaml的结构就是无非那些字符,数字,object,数组的混合,可以尝试大脑中把一段yaml转换成json,不然看不懂yaml的结构学不会k8s。很多层级实际上是遵循着逻辑的,例如一个pod有多个容器,所以pod.spec.containers就是一个object的数组,又因为pod共享network namepsace,所以
hostNetwork
这个属性肯定给所有容器设置的,所以是和containers同个级别的 - kubeconfig实际上就是存了三个信息,一个是host(集群),用户认证信息,这些都是可以写多个的,所以都是以yaml的数组-开头,以及当前的context是哪个host搭配哪个认证信息。和web的jwt思想一样用于认证鉴权,同时一个kubeconfig可以有多个上下文来切换身份(RBAC)或者集群
- 互斥和污点都是基础知识,也在concept和tasks板块里,上生产的话多份pod肯定要互斥自己分散开来,就像没有容器技术的时代是每个节点跑一份服务,这样down了一个node业务不会挂
- 获取和操作集群资源对象不单单是kubectl,你用curl带上证书啥的也能操作集群。
- kubectl的子命令带上-v=数字能够调试,最大是8,不同级别的log输出信息不一样,8是最详细的,同理k8s所有组件也支持
--log-level
,很多时候是排查的一个手段 - 如果不想打开网页,想查看
pod.spec.hostNetwork
字段的意思,kubectl explain pod.spec.hostNetwork
kubeadm的master是利用 staticPod ,kubelet创建 staticPod 不需要连接 kube-apiserver 即可创建,虽然kubelet的log会一直刷连不上kube-apiserver,但是kubelet另一边也会创建管理组件和etcd的staticPod,最终kube-apiserver起来后我们就能操作集群里。staticPod也是基础知识,看到过很多人感觉从没看过官方文档,居然还问staticPod是啥
关于kubeadm过程和更多详细参数选项见下面文章
其他参考: