市面上很多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 18 systemctl 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/config
apt系列系统:
设置时区
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 2 search lan nameserver 127.0.0.xx
文件有上面内容的话自行配置下,dns 上游改成公网的 dns 或者内网的 dns server,去掉 search 行
Kubernetes 建议关闭系统 Swap,在所有机器使用以下指令关闭 swap 并注释掉/etc/fstab中 swap 的行,不想关闭可以不执行,后面会应对的配置选项:
1 2 swapoff -a && sysctl -w vm.swappiness=0 sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab
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 29 30 31 32 yum install epel-release -y yum install -y \ curl \ wget \ git \ parted \ conntrack-tools \ psmisc \ nfs-utils \ jq \ socat \ ebtables \ ethtool \ util-linux \ bash-completion \ ipset \ ipvsadm \ conntrack \ libseccomp \ net-tools \ crontabs \ sysstat \ unzip \ netcat \ iftop \ nload \ strace \ bind-utils \ tcpdump \ telnet \ lsof \ htop
apt系列系统:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 apt-get update && apt-get install -y wget \ git \ psmisc \ nfs-kernel-server \ nfs-common \ jq \ socat \ bash-completion \ ipset \ ipvsadm \ conntrack \ libseccomp2 \ net-tools \ cron \ sysstat \ unzip \ dnsutils \ tcpdump \ telnet \ lsof \ htop \ curl \ apt-transport-https \ ca-certificates
如果集群 kube-proxy 想使用 ipvs 模式的话需要开机加载下列模块儿,按照规范使用systemd-modules-load来加载而不是在/etc/rc.local里写modprobe
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 || : done
apt 系列的系统先使用systemctl cat systemd-modules-load看下有没有Install段,没有则执行下面
1 2 3 4 cat>>/usr/lib/systemd/system/systemd-modules-load.service<<EOF [Install] WantedBy=multi-user.target EOF
启动该模块管理服务
1 2 systemctl 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 2 3 4 5 6 7 $ lsmod | grep ip_v ip_vs_sh 12688 0 ip_vs_wrr 12697 0 ip_vs_rr 12600 11 ip_vs 145497 17 ip_vs_rr,ip_vs_sh,ip_vs_wrr nf_conntrack 133095 7 ip_vs,nf_nat,nf_nat_ipv4,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_netlink,nf_conntrack_ipv4 libcrc32c 12644 3 ip_vs,nf_nat,nf_conntrack
所有机器 需要设定 /etc/sysctl.d/k8s.conf 的系统参数,目前对 ipv6 支持不怎么好,所以里面也关闭 ipv6了。
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 29 cat <<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 --system
如果选择关闭 swap 也要在内核里关闭,不关闭可以不执行
1 echo 'vm.swappiness = 0' >> /etc/sysctl.d/k8s.conf
如果 kube-proxy 使用 ipvs 的话为了防止 timeout 需要设置下 tcp 参数
1 2 3 4 5 6 7 8 9 cat <<EOF >> /etc/sysctl.d/k8s.conf # https://github.com/moby/moby/issues/31208 # ipvsadm -l --timout # 修复ipvs模式下长连接timeout问题 小于900即可 net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_keepalive_intvl = 30 net.ipv4.tcp_keepalive_probes = 10 EOF sysctl --system
优化设置 journal 日志相关,避免日志重复搜集,浪费系统资源。修改systemctl启动的最小文件打开数量。关闭ssh反向dns解析
1 2 3 4 5 6 7 8 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 10 cat >/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:
apt:
1 apt-get install -y chrony
配置文件
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 29 30 31 32 33 34 35 36 37 cat>/etc/chrony.conf<<EOF server cn.pool.ntp.org iburst minpoll 4 maxpoll 10 server s1b.time.edu.cn iburst minpoll 4 maxpoll 10 # Ignor source level stratumweight 0 # Record the rate at which the system clock gains/losses time. driftfile /var/lib/chrony/chrony.drift # This directive enables kernel synchronisation (every 11 minutes) of the # real-time clock. Note that it can’t be used along with the 'rtcfile' directive. rtcsync # Allow the system clock to be stepped in the first three updates # if its offset is larger than 1 second. makestep 1.0 3 # Enable hardware timestamping on all interfaces that support it. #hwtimestamp * # Increase the minimum number of selectable sources required to adjust # the system clock. #minsources 2 bindcmdaddress 127.0.0.1 #bindcmdaddress ::1 # Specify file containing keys for NTP authentication. keyfile /etc/chrony/chrony.keys logdir /var/log/chrony # adjust time big than 1 sec will log to file logchange 1 EOF
修改hostname kubelet和kube-proxy上报node信息默认是取hostname的,除非通过--hostname-override指定,这里自行设置hostname
1 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) "
重启系统
安装docker
检查系统内核和模块是否适合运行 docker (仅适用于 linux 系统),该脚本可能因为墙的原因无法生成,可以先去掉重定向看看能不能访问到脚本
1 2 curl -s https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh > check-config.sh bash ./check-config.sh
现在docker存储驱动都是使用的overlay2(不要使用devicemapper,这个坑非常多),我们重点关注overlay2是否不是绿色
这里我们使用年份命名版本的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 2 3 4 export VERSION=19.03curl -fsSL "https://get.docker.com/" | \ sed -r '/add-repo \$yum_repo/a sed -i "s#https://download.docker.com#http://mirrors.aliyun.com/docker-ce#" /etc/yum.repos.d/docker-*.repo ' | \ bash -s -- --mirror Aliyun
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 mkdir -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" } } EOF
Live Restore Enabled这个千万别开,某些极端情况下容器Dead状态之类的必须重启docker daemon才能解决,开了就只能重启机器解决了
CentOS安装完成后docker需要手动设置docker命令补全:
1 2 yum install -y epel-release bash-completion
apt系列操作为取消文件/etc/bash.bashrc内下面行的注释
1 2 3 4 5 6 7 8 # enable bash completion in interactive shells #if ! shopt -oq posix; then # if [ -f /usr/share/bash-completion/bash_completion ]; then # . /usr/share/bash-completion/bash_completion # elif [ -f /etc/bash_completion ]; then # . /etc/bash_completion # fi #fi
复制补全脚本
1 cp /usr/share/bash-completion/completions/docker /etc/bash_completion.d/
防止FORWARD的DROP策略影响转发,给docker daemon添加下列参数修正,当然暴力点也可以iptables -P FORWARD ACCEPT
1 2 3 4 5 6 7 8 mkdir -p /etc/systemd/system/docker.service.d/cat >/etc/systemd/system/docker.service.d/10-docker.conf<<EOF [Service] ExecStartPost=/sbin/iptables --wait -I FORWARD -s 0.0.0.0/0 -j ACCEPT ExecStopPost=/bin/bash -c '/sbin/iptables --wait -D FORWARD -s 0.0.0.0/0 -j ACCEPT &> /dev/null || :' ExecStartPost=/sbin/iptables --wait -I INPUT -i cni0 -j ACCEPT ExecStopPost=/bin/bash -c '/sbin/iptables --wait -D INPUT -i cni0 -j ACCEPT &> /dev/null || :' EOF
启动docker并看下信息是否正常
1 2 systemctl enable --now docker docker info
如果enable docker的时候报错开启debug,如何开见 https://github.com/zhangguanzhang/Kubernetes-ansible/wiki/systemctl-running-debug
1 tuned-adm profile throughput-performance
kubeadm部署 安装kubeadm相关 默认源在国外会无法安装,我们使用国内的镜像源,所有机器都要操作 yum:
1 2 3 4 5 6 7 cat <<EOF >/etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=0 EOF
apt:
1 2 3 4 5 curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add - cat> /etc/apt/sources.list.d/kubernetes.list<<EOF deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" EOF apt-get update
master部分 k8s的node就是kubelet+cri(一般是docker),kubectl 是一个 agent 读取 kubeconfig 去访问 kube-apiserver 来操作集群,kubeadm 是部署,所以 master 节点需要安装三个,node 一般不需要 kubectl 安装相关软件 yum: 如果依赖错误,yum命令后面加个--setopt=obsoletes=0
1 2 3 4 5 6 yum install -y \ kubeadm-1.18.13 \ kubectl-1.18.13 \ kubelet-1.18.13 \ --disableexcludes=kubernetes && \ systemctl enable kubelet
apt:
1 2 3 4 apt-get install -y \ kubeadm=1.18.13-00 \ kubectl-1.18.13-00 \ kubelet-1.18.13-00
node 1 2 3 4 5 yum install -y \ kubeadm-1.18.13 \ kubelet-1.18.13 \ --disableexcludes=kubernetes && \ systemctl enable kubelet
1 2 3 apt-get install -y \ kubeadm=1.18.13-00 \ kubelet-1.18.13-00
配置kubelet的参数方法(有需要的话) 查看kubelet的systemd文件
我们可以看到/etc/sysconfig/kubelet是EnvironmentFile,里面注释也写明了我们应该在该文件里写KUBELET_EXTRA_ARGS来给kubelet配置运行参数,下面是个例子,具体参数啥的可以kubelet --help看
1 2 3 cat >/etc/sysconfig/kubelet<<EOF KUBELET_EXTRA_ARGS="--xxx=yyy --aaa=bbb" 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 2 3 4 5 6 cat >>/etc/hosts << EOF 127.0.0.1 apiserver.k8s.local 172.19.0.2 apiserver01.k8s.local 172.19.0.3 apiserver02.k8s.local 172.19.0.4 apiserver03.k8s.local EOF
每台机器(master+node)生成配置文件,上面的三个hosts可以不写,不写的话下面配置文件里的域名得使用ip即可,但是这样更改ip需要重新加载,所以推荐还是写域名。
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 mkdir -p /etc/kubernetescat > /etc/kubernetes/nginx.conf << EOF error_log stderr notice; worker_processes 2; worker_rlimit_nofile 130048; worker_shutdown_timeout 10s; events { multi_accept on; use epoll; worker_connections 16384; } stream { upstream kube_apiserver { least_conn; server apiserver01.k8s.local:6443 max_fails=3 fail_timeout=10s; server apiserver02.k8s.local:6443 max_fails=3 fail_timeout=10s; server apiserver03.k8s.local:6443 max_fails=3 fail_timeout=10s; } server { listen 8443; proxy_pass kube_apiserver; proxy_timeout 10m; proxy_connect_timeout 1s; } } http { aio threads; aio_write on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 75s; keepalive_requests 100; reset_timedout_connection on; server_tokens off; autoindex off; server { listen 8081; location /healthz { access_log off; return 200; } location /stub_status { stub_status on; access_log off; } } } EOF
因为 localproxy 是每台机器上的,可以不用 SLB 和 vpc 无法使用 vip 的限制,这里我使用容器运行 nginx,当然自己也可以写成 staticPod 的 yaml 在 init 的阶段放入目录里
1 2 3 4 5 6 7 docker run --restart=always \ -v /etc/kubernetes/nginx.conf:/etc/nginx/nginx.conf \ -v /etc/localtime:/etc/localtime:ro \ --name k8s \ --net host \ -d \ nginx:alpine
配置集群信息(第一个master上配置)
1 kubeadm config print init-defaults > initconfig.yaml
我们看下默认init的集群参数
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 29 30 31 32 33 34 35 36 37 38 apiVersion: kubeadm.k8s.io/v1beta2 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 1.2 .3 .4 bindPort: 6443 nodeRegistration: criSocket: /var/run/dockershim.sock name: k8s-m1 taints: - effect: NoSchedule key: node-role.kubernetes.io/master --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta2 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {}dns: type: CoreDNS etcd: local: dataDir: /var/lib/etcd imageRepository: k8s.gcr.io kind: ClusterConfiguration kubernetesVersion: v1.16.0 networking: dnsDomain: cluster.local serviceSubnet: 10.96 .0 .0 /12 scheduler: {}
我们主要关注和只保留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 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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 apiVersion: kubeadm.k8s.io/v1beta2 kind: ClusterConfiguration imageRepository: registry.aliyuncs.com/k8sxio certificatesDir: /etc/kubernetes/pki clusterName: kubernetes networking: dnsDomain: cluster.local serviceSubnet: 10.96 .0 .0 /12 podSubnet: 10.244 .0 .0 /16 controlPlaneEndpoint: apiserver.k8s.local:8443 apiServer: timeoutForControlPlane: 4m0s extraArgs: authorization-mode: "Node,RBAC" enable-admission-plugins: "NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeClaimResize,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,Priority" runtime-config: api/all=true storage-backend: etcd3 etcd-servers: https://172.19.0.2:2379,https://172.19.0.3:2379,https://172.19.0.4:2379 certSANs: - 10.96 .0 .1 - 127.0 .0 .1 - localhost - apiserver.k8s.local - 172.19 .0 .2 - 172.19 .0 .3 - 172.19 .0 .4 - apiserver01.k8s.local - apiserver02.k8s.local - apiserver03.k8s.local - master - kubernetes - kubernetes.default - kubernetes.default.svc - kubernetes.default.svc.cluster.local extraVolumes: - hostPath: /etc/localtime mountPath: /etc/localtime name: localtime readOnly: true controllerManager: extraArgs: bind-address: "0.0.0.0" experimental-cluster-signing-duration: 876000h extraVolumes: - hostPath: /etc/localtime mountPath: /etc/localtime name: localtime readOnly: true scheduler: extraArgs: bind-address: "0.0.0.0" extraVolumes: - hostPath: /etc/localtime mountPath: /etc/localtime name: localtime readOnly: true dns: type: CoreDNS imageRepository: docker.io imageTag: 1.8 .4 etcd: local: imageTag: v3.4.15 dataDir: /var/lib/etcd serverCertSANs: - master - 172.19 .0 .2 - 172.19 .0 .3 - 172.19 .0 .4 - etcd01.k8s.local - etcd02.k8s.local - etcd03.k8s.local peerCertSANs: - master - 172.19 .0 .2 - 172.19 .0 .3 - 172.19 .0 .4 - etcd01.k8s.local - etcd02.k8s.local - etcd03.k8s.local extraArgs: auto-compaction-retention: "1h" max-request-bytes: "33554432" quota-backend-bytes: "8589934592" enable-v2: "false" --- apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: ipvs ipvs: excludeCIDRs: null minSyncPeriod: 0s scheduler: "rr" syncPeriod: 15s iptables: masqueradeAll: true masqueradeBit: 14 minSyncPeriod: 0s syncPeriod: 30s --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd failSwapOn: true
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 2 3 4 5 6 7 8 kubeadm config images pull --config initconfig.yaml [config/images] Pulled registry.aliyuncs.com/k8sxio/kube-apiserver:v1.18.13 [config/images] Pulled registry.aliyuncs.com/k8sxio/kube-controller-manager:v1.18.13 [config/images] Pulled registry.aliyuncs.com/k8sxio/kube-scheduler:v1.18.13 [config/images] Pulled registry.aliyuncs.com/k8sxio/kube-proxy:v1.18.13 [config/images] Pulled registry.aliyuncs.com/k8sxio/pause:3.2 [config/images] Pulled registry.aliyuncs.com/k8sxio/etcd:v3.4.10 [config/images] Pulled coredns/coredns:1.6.9
kubeadm init init(只在第一个master上面操作) 下面init只在第一个master上面操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # --experimental-upload-certs 参数的意思为将相关的证书直接上传到etcd中保存,这样省去我们手动分发证书的过程 # 注意在v1.15+版本中,已经变成正式参数,不再是实验性质,之前的版本请使用 --experimental-upload-certs # https://github.com/etcd-io/etcd/blob/master/CHANGELOG-3.4.md#breaking-changes mkdir /var/lib/etcd chmod 0700 /var/lib/etcd # etcd 3.4.10开始目录权限必须是0700,见上面文档 kubeadm init --config initconfig.yaml --upload-certs ...下面是输出 You can now join any number of the control-plane node running the following command on each as root: --------------master加入的话使用下面命令,此时先别加入 kubeadm join apiserver.k8s.local:8443 --token d3v79c.i8be79zo2iip15hf \ --discovery-token-ca-cert-hash sha256:455c158a77f60df39a9a0af821950b0468d46571154b638e0a27f0ceee8e1ff5 \ --control-plane --certificate-key 7a59a81ec3d95bb51bd1757766c5f63263cde5aa499c8dd37c4ef847afcd468b Please note that the certificate-key gives access to cluster sensitive data, keep it secret! As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use "kubeadm init phase upload-certs --upload-certs" to reload certs afterward. Then you can join any number of worker nodes by running the following on each as root: -----------node加入的话使用下面命令 kubeadm join apiserver.k8s.local:8443 --token d3v79c.i8be79zo2iip15hf \ --discovery-token-ca-cert-hash sha256:455c158a77f60df39a9a0af821950b0468d46571154b638e0a27f0ceee8e1ff5
如果超时了看看是不是kubelet没起来,调试见 https://github.com/zhangguanzhang/Kubernetes-ansible/wiki/systemctl-running-debug
记住init后打印的token(记不住或者ttl过期了看后面),复制kubectl的kubeconfig,kubectl的kubeconfig路径默认是~/.kube/config
1 2 3 mkdir -p $HOME /.kubesudo \cp /etc/kubernetes/admin.conf $HOME /.kube/configsudo chown $(id -u):$(id -g) $HOME /.kube/config
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 2 3 yum install sshpass -y alias ssh='sshpass -p zhangguanzhang ssh -o StrictHostKeyChecking=no' alias scp='sshpass -p zhangguanzhang scp -o StrictHostKeyChecking=no'
复制ca证书到其他master节点
1 2 3 4 5 6 7 for node in 172.19.0.3 172.19.0.4;do ssh $node 'mkdir -p /etc/kubernetes/pki/etcd' scp -r /etc/kubernetes/pki/ca.* $node :/etc/kubernetes/pki/ scp -r /etc/kubernetes/pki/sa.* $node :/etc/kubernetes/pki/ scp -r /etc/kubernetes/pki/front-proxy-ca.* $node :/etc/kubernetes/pki/ scp -r /etc/kubernetes/pki/etcd/ca.* $node :/etc/kubernetes/pki/etcd/ done
其他master join进来 注意是前面init最后输出的命令里选择长串的,不是短串,短传的是node,不是master
1 2 3 4 5 mkdir /var/lib/etcdchmod 0700 /var/lib/etcdkubeadm join apiserver.k8s.local:8443 --token xxxxxxx \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ --control-plane --certificate-key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
token忘记或者ttl过期了的话可以kubeadm token list查看,可以通过kubeadm token create --print-join-command查看,老版本不确定支持--print-join-command这个选项,不支持的话就不带这个选项创建token, sha256的值可以通过下列命令获取
1 2 3 4 openssl x509 -pubkey -in \ /etc/kubernetes/pki/ca.crt | \ openssl rsa -pubin -outform der 2>/dev/null | \ openssl dgst -sha256 -hex | sed 's/^.* //'
所有master配置kubectl 准备kubectl的kubeconfig
1 2 3 mkdir -p $HOME /.kubesudo \cp /etc/kubernetes/admin.conf $HOME /.kube/configsudo chown $(id -u):$(id -g) $HOME /.kube/config
设置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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 cat >/etc/profile.d/etcd.sh<<'EOF' ETCD_CERET_DIR=/etc/kubernetes/pki/etcd/ ETCD_CA_FILE=ca.crt ETCD_KEY_FILE=healthcheck-client.key ETCD_CERT_FILE=healthcheck-client.crt ETCD_EP=https://172.19.0.2:2379,https://172.19.0.3:2379,https://172.19.0.4:2379 alias etcd_v2="etcdctl --cert-file ${ETCD_CERET_DIR} /${ETCD_CERT_FILE} \ --key-file ${ETCD_CERET_DIR} /${ETCD_KEY_FILE} \ --ca-file ${ETCD_CERET_DIR} /${ETCD_CA_FILE} \ --endpoints $ETCD_EP " alias etcd_v3="ETCDCTL_API=3 \ etcdctl \ --cert ${ETCD_CERET_DIR} /${ETCD_CERT_FILE} \ --key ${ETCD_CERET_DIR} /${ETCD_KEY_FILE} \ --cacert ${ETCD_CERET_DIR} /${ETCD_CA_FILE} \ --endpoints $ETCD_EP " function etcd-ha (){ etcd_v3 endpoint status --write-out=table } EOF
重新ssh下或者手动加载下环境变量. /etc/profile.d/etcd.sh
1 2 3 4 5 6 7 8 etcd_v3 endpoint status --write-out=table +-------------------------+------------------+---------+---------+-----------+-----------+------------+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX | +-------------------------+------------------+---------+---------+-----------+-----------+------------+ | https://172.19.0.2:2379 | d7380397c3ec4b90 | 3.4.10 | 2.1 MB | true | 9 | 85397 | | https://172.19.0.3:2379 | f776f8545c82d916 | 3.4.10 | 2.1 MB | false | 9 | 85405 | | https://172.19.0.4:2379 | ead42f3e6c9bb295 | 3.4.10 | 2.1 MB | false | 9 | 85406 | +-------------------------+------------------+---------+---------+-----------+-----------+------------+
配置etcd备份脚本
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 mkdir -p /opt/etcdcat >/opt/etcd/etcd_cron.sh<<'EOF' set -eexport PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin: ${bak_dir:=/root/} : ${cert_dir:=/etc/kubernetes/pki/etcd/} : ${endpoints:=https://172.19.0.2:2379,https://172.19.0.3:2379,https://172.19.0.4:2379} bak_prefix='etcd-' cmd_suffix='date +%Y-%m-%d-%H:%M' bak_suffix='.db' temp=`getopt -n $0 -o c:d: -u -- "$@ " ` [ $? != 0 ] && { echo ' Examples: # just save once bash $0 /tmp/etcd.db # save in contab and keep 5 bash $0 -c 5 ' exit 1 } set -- $temp while true ;do case "$1 " in -c) [ -z "$bak_count " ] && bak_count=$2 printf -v null %d "$bak_count " &>/dev/null || \ { echo 'the value of the -c must be number' ;exit 1; } shift 2 ;; -d) [ ! -d "$2 " ] && mkdir -p $2 bak_dir=$2 shift 2 ;; *) [[ -z "$1 " || "$1 " == '--' ]] && { shift ;break ; } echo "Internal error!" exit 1 ;; esac done function etcd_v2 (){ etcdctl --cert-file $cert_dir /healthcheck-client.crt \ --key-file $cert_dir /healthcheck-client.key \ --ca-file $cert_dir /ca.crt \ --endpoints $endpoints $@ } function etcd_v3 (){ ETCDCTL_API=3 etcdctl \ --cert $cert_dir /healthcheck-client.crt \ --key $cert_dir /healthcheck-client.key \ --cacert $cert_dir /ca.crt \ --endpoints $endpoints $@ } etcd::cron::save (){ cd $bak_dir / etcd_v3 snapshot save $bak_prefix$($cmd_suffix )$bak_suffix rm_files=`ls -t $bak_prefix *$bak_suffix | tail -n +$[bak_count+1]` if [ -n "$rm_files " ];then rm -f $rm_files fi } main (){ [ -n "$bak_count " ] && etcd::cron::save || etcd_v3 snapshot save $@ } main $@ EOF
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 2 3 4 5 6 $ kubectl get node -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME k8s-m1 NotReady master 24m v1.18.13 172.19.0.2 <none> CentOS Linux 7 (Core) 3.10.0-957.el7.x86_64 docker://19.3.5 k8s-m2 NotReady master 19m v1.18.13 172.19.0.3 <none> CentOS Linux 7 (Core) 3.10.0-957.el7.x86_64 docker://19.3.5 k8s-m3 NotReady master 22m v1.18.13 172.19.0.4 <none> CentOS Linux 7 (Core) 3.10.0-957.el7.x86_64 docker://19.3.5 k8s-n1 NotReady <none> 12s v1.18.13 172.19.0.5 <none> CentOS Linux 7 (Core) 3.10.0-957.el7.x86_64 docker://19.3.5
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 2 apiVersion: policy/v1beta1 kind: PodSecurityPolicy
rbac的version改为下面,不要使用v1beta1了,使用下面命令修改
1 sed -ri '/apiVersion: rbac/s#v1.+#v1#' kube-flannel.yml
官方yaml自带了四种架构的daemonset,我们删掉除了amd64 以外的,大概是226行到结尾,文件行数可能会变,这里我用 shell 取行数来删除
1 2 NUM=`awk '{if(/^apiVersion: apps\/v1/){a++};if(a==2){print NR;exit}}' kube-flannel.yml` sed -ri $NUM ',$d' kube-flannel.yml
pod的cidr修改了的话这里也要修改,如果是在同一个二层,可以使用把vxlan改为性能更强的host-gw模式,vxlan的话需要安全组放开8472端口的udp
1 2 3 4 5 6 7 net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } }
这步可以先不改,如果flannel一直crash(某些版本下 request 和 limit 一样会频繁crash,实际上这种pod的优先级比较高)就修改下limits,需要大于request
1 2 3 4 ... limits: cpu: "200m" memory: "100Mi"
部署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 2 3 4 5 6 7 8 nodes=`kubectl get node --no-headers | awk '{print $1}' ` for node in $nodes ;do cidr=`kubectl get node "$node " -o jsonpath='{.spec.podCIDRs[0]}' ` [ -z "$(kubectl get node $node -o jsonpath='{.spec.podCIDR}') " ] && { kubectl patch node "$node " -p '{"spec":{"podCIDR":"' "$cidr " '"}}' } || echo "$node dont't need to patch" done
1 kubectl apply -f kube-flannel.yml
验证集群可用性 验证 1 kubectl -n kube-system get pod -o wide
等待 kube-system 空间下的 pod 都是 Running 后我们来测试下集群可用性
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 cat <<EOF | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx:alpine name: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 --- apiVersion: v1 kind: Pod metadata: name: busybox namespace: default spec: containers: - name: busybox image: zhangguanzhang/centos command: - sleep - "3600" imagePullPolicy: IfNotPresent restartPolicy: Always EOF
等待 pod running
1 2 3 4 5 6 7 8 $ kubectl get po,svc -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod/busybox 1/1 Running 0 4m4s 10.244.2.18 k8s-n1 <none> <none> pod/nginx-5c559d5697-2ctxh 1/1 Running 0 4m4s 10.244.2.16 k8s-n1 <none> <none> NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 12m <none> service/nginx ClusterIP 10.100.39.101 <none> 80/TCP 4m4s app=nginx
验证集群dns解析
1 2 3 4 5 6 $ kubectl exec -ti busybox -- nslookup kubernetes Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: kubernetes Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local
如果不是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 2 $ dig @10.96.0.10 +short kubernetes.default.svc.cluster.local 10.96.0.1
在master上curl nginx的svc的ip出现nginx的index内容即集群正常,例如我的nginx svc ip是10.100.39.101
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 $ curl -s 10.100.39.101 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
pod里验证集群域名到pod是否正常
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 $ kubectl exec -ti busybox -- curl nginx <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
清理测试的pod 1 2 3 kubectl delete deploy nginx kubectl delete svc nginx kubectl delete po busybox
关于使用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过程和更多详细参数选项见下面文章
其他参考: