# 深入刨析Kubernetes > 来源:原 mongodb 集合 `t_blog` · 整理日期:2026-08-25 > 分类 ID:`2022051619278900000000000002` · 排序:5 · 文章数:14 ## 目录 1. [第2章 Docker](#第2章-docker) 2. [第3章 设计与架构](#第3章-设计与架构) 3. [kubernetes etcd安装](#kubernetes-etcd安装) 4. [第4章 kubeadm](#第4章-kubeadm) 5. [第5章 编排原理](#第5章-编排原理) 6. [第7章 网络原理](#第7章-网络原理) 7. [第6章 存储原理](#第6章-存储原理) 8. [第8章 调度与资源管理](#第8章-调度与资源管理) 9. [第10章 资源](#第10章-资源) 10. [第11章 权限控制](#第11章-权限控制) 11. [基于虚拟网卡共有网络k8s集群搭建](#基于虚拟网卡共有网络k8s集群搭建) 12. [kubernetes 二进制安装master](#kubernetes-二进制安装master) 13. [kubernetes Calico 配置](#kubernetes-calico-配置) 14. [kubernetes 二进制安装worker](#kubernetes-二进制安装worker) --- ## 1. 第2章 Docker bid: `2022051619278900000000000003` ## kubernetes 第2章 Docker ### docker network --- [参考1](https://baijiahao.baidu.com/s?id=1730776907492640810&wfr=spider&for=pc) [参照2](https://blog.csdn.net/gui951753/article/details/79210535) # show network command: bridge, host, none docker network ls # bridge # host # none ### docker 项目最核心的原理是,为带创建的用户进程 ### 重新认识linux容器 --- 1.Linux Namespace 的隔离能力 2.Linux Cgroups的限制能力 3.基于rootfs的文件系统 其中用到了chroot 和 pivot_root 两个系统调用切换进程目录的能力 docker 在镜像的设计中引入了layer的概念 docker镜像使用的rootfs往往由多个layer组成。 这些layer 分: - ro+wh layer - rw layer - init layer - init层是docker项目单独生成的内部层,专门存放/etc/hosts,/etc/resolv.conf等信息。用户 commit时 init层并不会提交。提交的时rw层。 ### Dockerfile --- [doc](https://docs.docker.com/engine/reference/builder/) # Comment INSTRUCTION arguments FROM python:2.7-slim WORKDIR /app ADD . /app RUN pip install --trusted-host pypi.python.org -r requirements.txt EXPOSE 80 ENV NAME World CMD ["python", "app.py"] # dockerfile默认提供了一个隐式的ENTRYPOINT INSTRUCTION 即 /bin/sh -c 所以Docker容器的启动进程为ENTRYPOINT, 而不是CMD 而CMD命令为Dockerfile指定python app.py 为该容器进程 CMD的内容就是ENTRYPOINT 的参数 实际上在容器中运行的进程为 /bin/sh -c "python app.py" ### Linux Namespace 隔离机制 --- Linux Namespace虽然看不见摸不到,但是一个进程的Namespace信息在宿主机上是确实存在的,并且以文件的形式存在。 $ docker inspect --format '{{ .State.pid }}' 4ddf4542324 25686 此时,可以查看宿主机文件 $ls -l /proc/25686/ns 可以看出一个进程是有多个Namespace的,存放于该目录下。 这就意味着,一个进程可以选择加入某个Namespace中,这就是docker exec 原理 ### docker Volume 在chroot之前,宿主机的文件目录对容器进程是可见的,我们只需要在rootfs准备好后,在执行chroot之前,把Volume指定的宿主机目录挂载到指定容器目录即可。 Volume里信息不会被docker commit提交。 --- ## 2. 第3章 设计与架构 bid: `2022051809471000000000000005` ## kubernetes 第3章 设计与架构 ### Kubernetes 设计与架构 --- 容器实际上是由,Linux Namespace,Linux Cgroup,rootfs 这三种技术构建出来的。 不难看出一个运行中linux的容器其实可以被一分为二的: 1.挂载到/var/lib/docker/aufs/mnt上的rootfs,这一部分被称为容器镜像,是容器的静态视图。 2.一个由Namespace+Cgroups构成的隔离环境,这一部分被称为容器运行时,是容器的动态视图。 容器编排项目:compose+Swarm和Kubarnetes容器编排工具。 ### Kubernetes的核心能力与项目定位 --- Kubernetes 的本质是平台的平台,即一个用来帮助用户构建上层平台的基础平台。 Pod是Kubernetes 中最基础的单元 声明式API是kubernetes最核心的设计理念,通过 ### apiserver ### etcd ### cri ### kubectl ### kubelet ### proxy ### --- ## 3. kubernetes etcd安装 bid: `2022053111285300000000000018` ### 删除kubeadm 残留信息 --- yum remove -y kubelet kubeadm kubectl rm -rf /etc/kubernetes/ rm -rf /etc/systemd/system/kubelet.service.d rm -rf /etc/systemd/system/kubelet.service rm -rf /usr/bin/kube* rm -rf /etc/cni rm -rf /opt/cni rm -rf /var/lib/etcd rm -rf /var/etcd ### etcd 集群安装 --- **1.1** 服务器规划 etcd-1 etcd-2 etcd-3 **1.2** 资源准备 wget https://github.com/kubernetes/kubernetes/archive/refs/tags/v1.23.8.tar.gz 从gethub源码中的go.mod可以看出,etcd的版本依赖是v3.5.0 然后我去下载etcd-v3.5.0 wget https://github.com/etcd-io/etcd/releases/download/v3.5.0/etcd-v3.5.0-linux-amd64.tar.gz **1.3** cfssl证书生成工具准备 cfssl是一个开源的证书管理工具,使用json文件生成证书,相比openssl更方便使用。 找任意一台服务器操作,这里用Master1节点。 #创建目录存放cfssl工具 mkdir /software-cfssl #下载相关工具 cd /software-cfssl wget -q --timestamping https://storage.googleapis.com/kubernetes-the-hard-way/cfssl/1.4.1/linux/cfssl https://storage.googleapis.com/kubernetes-the-hard-way/cfssl/1.4.1/linux/cfssljson cd /software-cfssl/ chmod +x * mv cfssl cfssljson /usr/local/bin **1.4** 自签证书颁发机构(CA) # 创建工作目录 mkdir -p ~/TLS/{etcd,k8s} cd ~/TLS/etcd/ # 生成自签CA配置 ```bash cat > ca-config.json << EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "www": { "expiry": "87600h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] } } } } EOF ``` ```bash cat > ca-csr.json << EOF { "CN": "etcd CA", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "ShangHai", "ST": "ShangHai" } ] } EOF ``` - 生成自签CA证书 ```bash cfssl gencert -initca ca-csr.json | cfssljson -bare ca - ``` - ca的有效证书查看 ```bash openssl x509 -in ca.pem -noout -text ``` **1.5** 签发etcd https证书 # 使用自签CA cat > server-csr.json << EOF { "CN": "etcd", "hosts": [ "49.233.4.79", "43.138.55.43", "43.138.73.106", "10.0.16.3", "10.0.8.13", "127.0.0.1" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "ShangHai", "ST": "ShangHai" } ] } EOF - 生成证书 ```bash cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server ``` - 查看有效期 ```bash openssl x509 -in server.pem -noout -text `` **1.5** 部署etcd集群 mkdir /usr/local/etcd-v3.5.0/{bin,cfg,ssl} -p tar -xf etcd-v3.4.9-linux-amd64.tar.gz mv etcd-v3.4.9-linux-amd64/{etcd,etcdctl} /usr/local/etcd-v3.5.0/bin/ --- # 创建etcd配置文件 cat > /usr/local/etcd-v3.5.0/conf/etcd.conf << EOF #[Member] ETCD_NAME="etcd-1" # 需要修改 ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_PEER_URLS="https://49.233.4.79:2380" ETCD_LISTEN_CLIENT_URLS="https://49.233.4.79:2379" #[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="https://49.233.4.79:2380" ETCD_ADVERTISE_CLIENT_URLS="https://49.233.4.79:2379" ETCD_INITIAL_CLUSTER="etcd-1=https://49.233.4.79:2380,etcd-2=https://43.138.55.43:2380,etcd-3=https://138.73.106:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="new"  # etc-1 为new,etcd-2/2为existing,网上很多文章都是直接copy不改,是不好使的 EOF --- # systemd管理etcd cat > /usr/lib/systemd/system/etcd.service << EOF [Unit] Description=Etcd Server After=network.target After=network-online.target Wants=network-online.target [Service] Type=notify EnvironmentFile=/usr/local/etcd-v3.5.0/conf/etcd.conf User=root # 此处必须要指定用户,要不启动会报错 ExecStart=/usr/local/etcd-v3.5.0/bin/etcd \ --cert-file=/usr/local/etcd-v3.5.0/ssl/server.pem \ --key-file=/usr/local/etcd-v3.5.0/ssl/server-key.pem \ --peer-cert-file=/usr/local/etcd-v3.5.0/ssl/server.pem \ --peer-key-file=/usr/local/etcd-v3.5.0/ssl/server-key.pem \ --trusted-ca-file=/usr/local/etcd-v3.5.0/ssl/ca.pem \ --peer-trusted-ca-file=/usr/local/etcd-v3.5.0/ssl/ca.pem \ --logger=zap Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF --- 将master1节点所有生成的文件拷贝到节点2和节点3 xsync etcd-v3.5.0 --- 修改节点2,节点3 ,etcd.conf配置文件中的节点名称和当前服务器IP: --- 启动etcd并设置开机自启 --- 检查etcd集群状态 --- etcd问题排查(日志) less /var/log/message journalctl -u etcd journalctl -xe etcd 默认数据目录 /var/lib/etcd/ # 只有第一次启动时候,发生"msg":"request cluster ID mismatch" rm -rf /usr/local/etcd-v3.5.0/data systemctl stop etcd systemctl start etcd etcd 启动 etcd --config-file /usr/local/etcd-v3.5.0/conf/etcd.conf.yml etcd 后台启动 nohup etcd --config-file /usr/local/etcd-v3.5.0/conf/etcd.conf.yml >/usr/local/etcd-v3.5.0/log/etcd.log 2>&1 & 测试 ETCDCTL_API=2 etcdctl ETCDCTL_API=3 etcdctl --- 关于客户端和CA证书的问题,etcdctl 是 客户端,而我们签发的证书都是服务端证书,所以访问服务端时候必须把z --cacert=/usr/local/etcd-v3.5.0/ssl/ca.pem --cert=/usr/local/etcd-v3.5.0/ssl/server.pem --key=/usr/local/etcd-v3.5.0/ssl/server-key.pem --- ## 4. 第4章 kubeadm bid: `2022060613040400000000000019` ## kubernetes 第4章 kubeadm ### k8s 安装相关 doc --- [apiDoc](https://kubernetes.io/docs/reference/config-api/) [docker centos install doc](https://docs.docker.com/engine/install/centos/) ## 4.1 安装背景 --- 腾讯云服务器,3台2G四核的不同网段的轻量云服务器(特价买的)。 因为轻量云服务器采用的是VPC网络,所以通过ip addr 命令可以看到并没有公网网址。 和一个网段私有网络不同,这里是需要公网ip的,所以做了一个临时的虚拟网卡: `4.1.1` 创建临时网卡先应付: # 每台机器都要做(临时网卡做法,永久性的暂时没测试) ifconfig eth0:1 49.233.4.79 netmask 255.255.255.0 up ifconfig eth0:1 43.138.55.43 netmask 255.255.255.0 up ifconfig eth0:1 43.138.73.106 netmask 255.255.255.0 up `4.1.2` 腾讯云有两个网络访问安全的设置: # 添加 安全组 规则 放行所有6443 TCP端口 # 防火前 添加 规则 ,放行 node1 node2 node3 的6443 TCP网络 `4.1.3` hostname修改 # hostname 修改 hostnamectl set-hostname xx `4.1.4` 设置3台机器的网络连接: # 修改 /etc/hosts vi /etc/hosts # 将以下内容添加即可 49.233.4.79 node1 43.138.55.43 node2 43.138.73.106 node3 # ping ping node3 `4.1.5` 将 SELinux 设置为 permissive 模式(相当于将其禁用) sudo setenforce 0 sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config `4.1.6` 关闭swap swapoff -a sed -ri 's/.*swap.*/#&/' /etc/fstab `4.1.7` 允许 iptables 检查桥接流量 cat < docker-ce-cli- containerd.io docker-compose-plugin yum install docker-ce-20.10.17-3.el7 docker-ce-cli-20.10.17-3.el7 containerd.io docker-compose-plugin cat < /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=0 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF `4.2.2` kubelet/kubectl/kubeadm download # 指定版本号最好 yum -y install kubelet-1.23.7-0 kubeadm-1.23.7-0 kubectl-1.23.7-0 # 如果原来存在多个版本,请删除,因为默认是使用高版本的,会导致无法加入node yum -y remove kubeadm* kubelet* kubectl* systemctl enable kubelet.service # 修改 docker 的cgroup # 添加以下内容 vim /etc/docker/daemon.json { "exec-opts": ["native.cgroupdriver=systemd"] } # 重启docker systemctl restart docker docker info | grep Cgroup ### 4.3 kubeadm init # 创建集群,其他默认就可以,需要指定集群公网地址和CIDR局域网网段 kubeadm init --apiserver-advertise-address 49.233.4.79 --pod-network-cidr=10.244.0.0/16 # 使集群生效, mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config # token 24h 过期 kubeadm token create --print-join-command # 查看集群master节点 kubectl describe node node1 # 查看集群pods,我们会发现,coredns 一直处于Pending状态,这是符合预期的,因为我们还没有安装集群插件 kubectl get pods -A # 安装集群插件 flannel # https://github.com/flannel-io/flannel/blob/master/Documentation/kube-flannel.yml kubectl apply -f kube-flannel.yaml # 安装集群网络插件 kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml # 再查看集群pods,一定要先安装网络插件,再去添加集群节点哦。 kubectl get pods -A # 加入worker节点 # 由于不在一个内网,集群间通讯默认走内网ip,因此需要借助公网ip,通过iptables转换 iptables -t nat -A OUTPUT -d -j DNAT --to-destination 青云内网ip # 然后 kubeadm join 在其他node处添加进来。 kubeadm join 49.233.4.79:6443 --token xx.xxx \ --discovery-token-ca-cert-hash sha256:xxxxxxx # 到这一步集群节点就算完事了。 ### 4.4 ETCD --- `4.4.1` etcd ca # etcd 作为数据库 也有自己的ca,kubeadm 安装etcd时ca是存入以下路径 /etc/kubernetes/pki/etcd/ `4.4.2` etcd comman 1. 查看ETCD集群中运行的ETCD pod kubectl get pod -n kube-system | grep etcd 2. 进入ETCD pod容器 kubectl exec -it etcd-node1 -n kube-system -- /bin/sh 3. 设置环境变量为v3 export ETCDCTL_API=3 4. 查看 member list ETCDCTL_API=3 etcdctl \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \ --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \ member list check perf 4. 查看 key 需要加上cert才可以 etcdctl get /registry/pods/kube-system/kube-flannel-ds-vnhrw 5. 未查询简单化,添加别名 # 别名列表 alias -p # 添加别名 alias cls=clear # 删除别名 unalias 别名 alias etc="/usr/local/bin/etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key" 6. 查询所有的key etcdctl get / --prefix --keys-only 7. 查询flnanel配置 etcdctl get /registry/configmaps/kube-system/kube-flannel-cfg ETCD_ENABLE_V2=true ETCDCTL_API=2 etcdctl ls /coreos.com/network/subnets/ ETCDCTL_API=2 etcdctl cluster-health ETCDCTL_API=2 etcdctl member list ETCDCTL_API=3 etcdctl member list ETCDCTL_API=3 etcdctl check perf ### 4.5 各种错误的解决方法。 --- # 最典型的就是版本不统一导致的安装错误 [ERROR CRI]: container runtime is not running: output: time="2022-06-13T10:26:24+08:00" level=fatal msg="unable to determine runtime API version: rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial unix /var/run/containerd/containerd.sock: connect: no such file or directory\"" 详细过程如下: 这个原因吧 是一开始 直接yum -y install docker 发生的错,后来用docker-ce 就直接修复了 [ERROR KubeletVersion]: the kubelet version is higher than the control plane version. This is not a supported version skew and may lead to a malfunctional cluster. Kubelet version: "1.24.1" Control plane version: "1.23.7" yum -y remove kubelet yum -y install kubelet-1.23.7 kubeadm-1.23.7 kubeadm init 时候会发现被墙了。 I0613 12:39:59.679221 18038 checks.go:859] pulling: k8s.gcr.io/coredns/coredns:v1.8.6 [preflight] Some fatal errors occurred: [ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-apiserver:v1.23.7: output: Error response from daemon: Get "https://k8s.gcr.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) 解决方案: https://www.cnblogs.com/lifan1998/p/14326761.html DOCKERHUB_URL=registry.aliyuncs.com/google_containers --- kubeadm init 时候kubelet check 出错 [kubelet-check] It seems like the kubelet isn't running or healthy. [kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp [::1]:10248: connect: connection refused. 使用 journalctl -xeu kubelet查看错误信息,基本上是docker 的cgroup和k8s的cgroup不一致导致的。 修改 docker 的cgroup 解决方法 # 添加以下内容 vim /etc/docker/daemon.json { "exec-opts": ["native.cgroupdriver=systemd"] } # 重启docker systemctl restart docker docker info | grep Cgroup # 重新初始化 kubeadm reset # 先重置 ### 上述master节点完成后进入,worker node安装 --- # 确保和主节点的kubeadm版本相同 yum list --showduplicates kubeadm yum -y install kubeadm-1.23.7-0 kubelet-1.23.7-0 kubectl-1.23.7-0 systemctl enable kubelet.service ### /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1 错误 [ERROR FileContent–proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1 [preflight] If you know what you are doing, you can make a check non-fatal with --ignore-preflight-errors=... 解决方案 echo “1” >/proc/sys/net/bridge/bridge-nf-call-iptables --- ## 5. 第5章 编排原理 bid: `2022060717000500000000000021` ## kubernetes 第5章 编排原理 ### 污点 --- `taints:污点,定义在节点上,是键值数据` `tolerations:容忍度,定义在pod上,可以定义能容忍哪些污点` taints: - effect: NoSchedule 不会被调度 key: node-role.kubernetes.io/master - effect: PreferNoSchedule 尽量不调度 key: node-role.kubernetes.io/master - effect: NoExecute 驱逐节点 key: node-role.kubernetes.io/master tolerations: - key: "key" operator: "Equal" value: "value" effect: "NoSchedule" tolerations: - key: "key" operator: "Exists" effect: "NoSchedule" 一个 toleration和一个 taint 相"匹配"是指它们有一样的key和effect operator 默认是 Equal ,即value 相等才匹配 `master节点默认是有污点的可以通过以下命令查看` kubectl describe nodes node1 | grep Taints Taints: node-role.kubernetes.io/master:NoSchedule 该污点表示,不会被调度。 kubectl describe nodes node2 | grep Taints Taints: `如何在master节点发布pod呢` --- ## 6. 第7章 网络原理 bid: `2022060814410000000000000024` ## ### 7.2 深入解析容器跨主机网络 --- 为了解决容器跨主机通信问题,就一定要从Flannel项目说起。 Flannel项目目前提供了三种实现: (1)VXLAN (2)host-gw了。 (3)UDP UDP是最早的支持的一种方式,但是,性能较差,已经弃用,但这种方式简单直接,也是最容易理解的一种容器跨主机网络实现。 Flannel会在宿主机上创建一些列路由规则,flannel0 flannel0是基于CIDR/16的,而docker0,eth0是基于CIDR/24的。并且flannel0设备类型很有意思,他是一个基于TUN设备(tunnel设备) 在linux中tunnel设备是在一种第三层(网络层)工作的virtual device。他的功能也非常简单,就是在操作系统内核和用户应用程序之间传递ip包。 当操作系统,将一个Ip包发送给一个flannel0设备之后,flannel0会把这个ip包交给创建该设备的应用程序,也就是Flannel进程,这是一个内核态到用户态的流动方向。 反之,如果Flannel进程,向flannel0设备发送了一个ip包,这个ip包会出现在 宿主机network stack 中,根据宿主机的路由表进行下一步处理。这是用户态向内核态的流动方向。 还有一个重要概念subnet子网:事实上,一台主机上的所有容器都会被分配一个CIDR/24的子网,而主机和子网的映射关系保存在k8s的分布式存储etcd当中。 // 查看keys $ etcdctl ls /coreos.com/network/subnets /coreos.com/network/subnets/100.96.1.0-24 /coreos.com/network/subnets/100.96.2.0-24 /coreos.com/network/subnets/100.96.3.0-24 // 获取public ip $ etcdctl get /coreos.com/network/subnets/100.96.2.0-24 {"PublicIP": "10.168.0.3"} 以上过程的总结: 容器确定source ip和 target ip,如果他们在一个CIDR/24下,则走的直连规则,如果不是一个子网段,则会把ip包通过docker0进入到宿主机ip route表中进行匹配,然后进入到flannel0设备中,flannel0 通过tunnel 把ip包转给flannel1d进程,然后通过etcd查询target的共有ip,并将ip包发出。 当然,采用UDP得以实现的原因是,每台宿主机flannelid都监听着一个8285端口。 当然这种方式,性能很差,差在tunnel设备需要三次用户态和内核态的切换,很肥资源。 这也是Flannel 后来支持VXLAN的模式成为主流的网络解决方案。 ### VXLAN(virtual extensible LAN 虚拟可扩展局域网) --- 是linux本来就支持的网络虚拟化技术。 VXLAN可以在完全在内核态上实现封装和解封的工作,从而构建UDP模式相似的网络。 VXLAN是在二层网络上构建出的隧道模式,只不过对他进行封装和解封的对象是二层数据帧(ethernet frame),而且这个工作全部是在内核里完成,(因为VXLAN就是linux内核的一个模块) 但是为了解决发送时IP包并不知道MAC,所以需要维护一个ARP表 可以通过命令去查看 $ ip neigh show dev flannel.1 ### 7.3 kubernetes网络模型与CNI网络插件 --- 7.2的流程,是k8s对容器网络的处理方法。只不过k8s是通过一个叫做CNI的接口维护了一个单独的网桥来代替docker0.默认的设备名称cni0. 具体内容就不细说了, ### 7.4 解读kubernetes 三层网络方案 host-gw -- ### 7.5 解读kubernetes 三层 -- --- ## 7. 第6章 存储原理 bid: `2022060814418900000000000023` kubernetes 第6章 存储原理 --- ## 8. 第8章 调度与资源管理 bid: `2022060814420100000000000025` ## kubernetes 第8章 调度与资源管理 ### 8.1 kubernetes 资源模型 --- - 可压缩资源(compressiable resources) CPU,当他不足时,Pod只会饥饿,不会退出 - 不可压缩资源(imcompressiable resources) 内存,当他不足时,Pod会因为OOM被内核结束。 由于Pod是可以由多个Containner组成,而每个Containner都是一个进程,所以Pod整体的资源配置是由Container所有进程资源配置累加的,同时资源配置是需要配置在Container上的。 此外,k8s是允许,CPU设置成分数的,cpu=0.5或者cpu=500m这样的写法,才是k8s的内部通用表示法。 内存的单位自然就是byte,注意区分MB和Mib **※** 1MiB 1024x1024 1Mb=1000x1000 apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: db image: mysql env: - name: MYSQL_ROOT_PASSWORD value: "password" resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" - name: wp image: wordpress resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" 关于limits和requests 区别: 调度时候,kube-scheduler只会按照requests的值去计算。 而在真正设置Cgroups的时候,kubelet会按照limits去计算。 ### qosclass类型 --- 如果只定义了limits,那么k8s默认会将requests与limits设置一样, qosclass字段会被k8s自动设置成Guaranteed 当Pod不满足Guaranteed,但至少有一个container设置了requests,k8s会将qosclass设置成Burstable 如果一个Pod既没有设置limits也没有设置requests,Qos的类型为BestEffort **作用** 当宿主机资源紧张的时候,kubelet对Pod进行资源回收(Eviction)时候需要用到。具体来说,宿主机上不可压缩资源资源短缺时候,就有可能触发Eviction 目前Eviction的默认值如下: memory.available<100Mi nodefs.available<10% nodefs.inodesFree<5% imagefs.avaialble<15% kubelet中是可以对上述Eviction进行配置的。 配置时,有两种模式Soft和Hard, 而k8s计算Eviction的阈值数据来源,是通过Cgroup读取的值和cAdsivor监控到的数据。 当宿主机的Eviction阈值达到后,会进入MemoryPressure或者DiskPressure状态,从而避免新的Pod被调度到这个宿主机。 **Eviction** 发生Eviction按照,BestEffort->Burstable(超过requests的容器)->Guaranteed **cpuset** 我们可以通过cpuset将容器绑定到某个CPU的核上,而不是像cpushare共享cpu计算能力。这样操作系统在cpu直接的切换会大大减少。 ### 8.2 kubernetes 默认调度器 --- - default scheduler 默认调度器的主要职责是,为创建出来的Pod需找一个最合适的节点。 Node selection in kube-scheduler kube-scheduler selects a node for the pod in a 2-step operation: 1. Filtering 2. Scoring 根据算法选出,可调度的list,在根据算法从中选出最优。 Predicate算法,检查每个节点是否可用 Priority算法,给每个节点打分,得分最高的就是最终的调度结果。 而,scheduler对Pod的调度成功体现在,他的spec.nodeName字段填上调度结果的节点名字。 ### 8.3 kubernetes 默认调度器调度策略 --- - 调度策略 - [doc](https://kubernetes.io/docs/reference/scheduling/policies/) 1. GeneralPredicates 2. 与Volume相关的过滤策略 NoDiskConflict检查多个Pod声明的PV是否有冲突,比如AWS EBS类型的Volume不允许被两个Pod同时使用。 MaxPDVolumeCountPredicate检查一个节点某个类型的PV是否超过一定数量。 3. 宿主机相关的过滤策略 NodeMemoryPressurePredicate 4. Pod相关的过滤策略 PodAffinityPredicate 亲密性affinity和反亲密性anti-affinity。 ## 8.4 kubernetes 默认调度器优先级和抢占机制 --- Priority和Preemption解决的是Pod调度失败后该怎么办的问题。 提交一个priorityclass定义: apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority value: 1000000 globleDefault: false description: "~~~~" 默认的Pod的priority的value是0 globleDefault是false意味着,不是默认的,需要在pod声明指定 因为scheduler中维护了一个调度队列,当Pod中priority高的就有可能提前出队列,从而更早的完成调度过程。 当一个高priority的Pod调度失败后,scheduler的抢占Preemption能力就会触发。 scheduler 在调度队列中实现了两个不同的队列: activeQ和unschedulableQ activeQ中的Pod都是下一次调度周期需要调度的对象 unschedulableQ存放的都是调度失败的Pod。 当一个unschedulableQ发生更新后,k8s --- ## 9. 第10章 资源 bid: `2022061515517700000000000028` ## 1. ingress来龙去脉 --- [doc](https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/) - Ingress-nginx quick start [quick start](https://kubernetes.github.io/ingress-nginx/deploy/#quick-start) K8s集群对外暴露服务的方式目前只有三种: - Loadblancer - Nodeport - ingress - headerless ### ingress介绍 --- ingress由两部分组成 - ingress 指的是k8s中的一个api对象,一般用yaml配置。作用是定义请求如何转发到service的规则,可以理解为配置模板。 - ingress controller 具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。 ingress-controller并不是k8s自带的组件,实际上ingress-controller只是一个统称,用户可以选择不 同的ingress-controller实现 目前,由k8s维护的ingress-controller只有google云的GCE与ingress-nginx两个,其他还有很多第三方维护的ingress-controller ### ingress-controller 安装 [参照](https://blog.csdn.net/weixin_38797137/article/details/124251698) # 先现在 配置文件 wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/cloud/deploy.yaml # 由于国内被墙,有几个镜像是下载不下来的,所以修改deploy.yaml vi deploy.yaml # /image 查找镜像 # 修改controller:v1.2.0 bitnami/nginx-ingress-controller:1.2.0 # 修改kube-webhook-certgen registry.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1 # /externalTrafficPolicy # 修改externalTrafficPolicy = Cluster # 最后 apply kubectl apply -f deploy.yaml ### ingress tls 证书替换 // [可以参考 linux 下的 nginx 证书使用](https://cloud.tencent.com/document/product/400/35244) [root@node1 ~]# kubectl create secret tls https-secret2023 --cert=/usr/local/kubernetes/secret/violin-home.cn_bundle.crt --key=/usr/local/kubernetes/secret/violin-home.cn.key -n devops [root@node1 ~]# kubectl get secret -A [root@node1 ~]# kubectl edit ingress violin-ingress -n devops ## 2. Service --- [doc](https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/) [root@node1 ~]# kubectl get svc -A NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default kubernetes ClusterIP 10.96.0.1 443/TCP 2d21h kube-system kube-dns ClusterIP 10.96.0.10 53/UDP,53/TCP,9153/TCP 2d21h `先了解以下参与k8s网络的角色` - kube-dns - kube-proxy - kube-flannel-ds - coredns - cni0 - controller --- ## 10. 第11章 权限控制 bid: `2022061710512100000000000001` ## RBAC规则 --- ### 概念 RBAC模型(Role-Based Access Control:基于角色的访问控制) 在RBAC模型里面,有3个基础组成部分,分别是:用户、角色和权限。 - User(用户):每个用户都有唯一的UID识别,并被授予不同的角色 - Role(角色):不同角色具有不同的权限 - Permission(权限):访问权限 # user -> role <- Permission 张三 管理员 增删改查 李四 普通用户 查 王五 普通用户 查 设置角色,然后对角色进行权限设置,然后将用户和角色关联即可。 用户和权限没有必然关系,是通过角色去控制的 ### kubernetes 中的RBAC RBAC规则包含ServiceAccount、ClusterRole、ClusterRoleBinding三类YAML文件,即三种对象 - **Service Account** 是面向命名空间的: apiVersion: v1 kind: ServiceAccount metadata: name: beckend-serviceaccount namespace: kube-users - **ClusterRole** 是面向整个集群所有命名空间的 ClusterRole的一条规则由apiGroups、resources、verbs共同组成 ClusterRole 用来描述 一个角色和他所拥有的权限 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: namespace-readonly rules: - apiGroups: - "" resources: - namespaces verbs: - get - list - watch - apiGroups: - metrics.k8s.io resources: - pods verbs: - get - list - watch - ClusterRoleBinding 是面向整个集群所有命名空间的 ClusterRoleBinding中subjects是访问API的主体 subjects包含users、groups、service accounts三种类型 我们使用的是ServiceAccount类型 ClusterRoleBinding 描述的是将 ServiceAccount(用户)和 ClusterRole(角色)jin'xing apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: namespace-readonly-sa roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: namespace-readonly subjects: - apiGroup: rbac.authorization.k8s.io kind: ServiceAccount name: system:serviceaccounts:kube-users --- ## 11. 基于虚拟网卡共有网络k8s集群搭建 bid: `2022062320127000000000000005` ### linux --- - port set 在腾讯云控制面对相应端口进行放行 TCP 6443 UDP 8472 TCP 30000-32767 - SELinux 设置为 permissive 模式(相当于将其禁用) sudo setenforce 0 sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config - 关闭swap # 临时关闭swap分区,当前会话生效,重启失效 swapoff -a # 永久关闭swap分区 sed -ri 's/.*swap.*/#&/' /etc/fstab - 所有机器都要做 echo "1" >/proc/sys/net/bridge/bridge-nf-call-iptables echo 1 > /proc/sys/net/ipv4/ip_forward vi /etc/sysctl.conf net.ipv4.ip_forward = 1 cat < /etc/sysconfig/network-scripts/ifcfg-eth0:1 < PREFIX=32 TYPE=Ethernet USERCTL=no ONBOOT=yes EOF ### 版本信息 --- kubernetes, kubelet, kubectl, kubeadm version v1.23.7 ### 修改kubelet( per machine) --- # 此文件安装kubeadm后就存在了 vim /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf # 注意,这步很重要,如果不做,节点仍然会使用内网IP注册进集群 # 在末尾添加参数 --node-ip=公网IP ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS --node-ip=<公网IP> ### 编写启动配置文件 --- # 添加配置文件,注意替换下面的IP cat > kubeadm-config.yaml <bid: `2022070116141100000000000006` ### 事前准备 --- 如果以前有安装过, 请清理掉 ll /usr/lib/systemd/system/kube* systemctl stop kube-apiserver systemctl stop kube-controller-manager systemctl stop kubelet systemctl stop kube-proxy systemctl stop kube-scheduler 目录准备 mkdir -p /usr/local/kubernetes/{bin,conf,ssl,logs} ### kube-apiserver 安装 --- `生成自签CA配置` cat > ca-config.json << EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "expiry": "87600h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] } } } } EOF cat > ca-csr.json << EOF { "CN": "kubernetes CA", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "ShangHai", "ST": "ShangHai", "O": "k8s", "OU": "system" } ] } EOF 生成CA cfssl gencert -initca ca-csr.json | cfssljson -bare ca - --- `给apiServer签发证书` cat > server-csr.json << EOF { "CN": "kubernetes", "hosts": [ "10.244.0.1", "10.0.0.1", "127.0.0.1", "49.233.4.79", "43.138.55.43", "43.138.73.106", "10.0.16.3", "10.0.8.13", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "ShangHai", "ST": "ShangHai", "O": "k8s", "OU": "system" } ] } EOF cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server 生成token head -c 16 /dev/urandom | od -An -t x | tr -d ' ' cat > /usr/local/kubernetes/conf/token.csv << EOF f41424f202b2c2e71da40ce20d32f1d2,kubelet-bootstrap,10001,"system:node-bootstrapper" EOF --- cat > /usr/lib/systemd/system/kube-apiserver.service << EOF [Unit] Description=Kubernetes API Server Documentation=https://github.com/kubernetes/kubernetes [Service] EnvironmentFile=/usr/local/kubernetes/conf/kube-apiserver.conf ExecStart=/usr/local/kubernetes/bin/kube-apiserver \$KUBE_APISERVER_OPTS Restart=on-failure [Install] WantedBy=multi-user.target EOF --- vi kube-apiserver.conf KUBE_APISERVER_OPTS="--logtostderr=false \ --v=2 \ --log-dir=/usr/local/kubernetes/logs \ --etcd-servers=https://49.233.4.79:2379,https://43.138.55.43:2379,https://43.138.73.106:2379 \ --bind-address=49.233.4.79 \ --secure-port=6443 \ --advertise-address=49.233.4.79 \ --allow-privileged=true \ --service-cluster-ip-range=10.0.0.0/16 \ --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \ --authorization-mode=RBAC,Node \ --enable-bootstrap-token-auth=true \ --token-auth-file=/usr/local/kubernetes/conf/token.csv \ --service-node-port-range=30000-32767 \ --kubelet-client-certificate=/usr/local/kubernetes/ssl/server.pem \ --kubelet-client-key=/usr/local/kubernetes/ssl/server-key.pem \ --tls-cert-file=/usr/local/kubernetes/ssl/server.pem \ --tls-private-key-file=/usr/local/kubernetes/ssl/server-key.pem \ --client-ca-file=/usr/local/kubernetes/ssl/ca.pem \ --service-account-key-file=/usr/local/kubernetes/ssl/ca-key.pem \ --service-account-issuer=api \ --service-account-signing-key-file=/usr/local/kubernetes/ssl/server-key.pem \ --etcd-cafile=/usr/local/etcd-v3.5.0/ssl/ca.pem \ --etcd-certfile=/usr/local/etcd-v3.5.0/ssl/server.pem \ --etcd-keyfile=/usr/local/etcd-v3.5.0/ssl/server-key.pem \ --requestheader-client-ca-file=/usr/local/kubernetes/ssl/ca.pem \ --proxy-client-cert-file=/usr/local/kubernetes/ssl/server.pem \ --proxy-client-key-file=/usr/local/kubernetes/ssl/server-key.pem \ --requestheader-allowed-names=kubernetes \ --requestheader-extra-headers-prefix=X-Remote-Extra- \ --requestheader-group-headers=X-Remote-Group \ --requestheader-username-headers=X-Remote-User \ --enable-aggregator-routing=true \ --audit-log-maxage=30 \ --audit-log-maxbackup=3 \ --audit-log-maxsize=100 \ --audit-log-path=/usr/local/kubernetes/logs/k8s-audit.log" --- # 刷新设置,并设置开机启动,查看status systemctl daemon-reload systemctl start kube-apiserver systemctl enable kube-apiserver systemctl status kube-apiserver -l ### kube-controller-manager 安装 --- `创建配置文件` cat > /usr/local/kubernetes/conf/kube-controller-manager.conf << EOF KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \\ --v=2 \\ --log-dir=/usr/local/kubernetes/logs \\ --leader-elect=true \\ --kubeconfig=/usr/local/kubernetes/conf/kube-controller-manager.kubeconfig \\ --bind-address=127.0.0.1 \\ --allocate-node-cidrs=true \\ --cluster-cidr=10.244.0.0/16 \\ --service-cluster-ip-range=10.0.0.0/16 \\ --cluster-signing-cert-file=/usr/local/kubernetes/ssl/ca.pem \\ --cluster-signing-key-file=/usr/local/kubernetes/ssl/ca-key.pem \\ --root-ca-file=/usr/local/kubernetes/ssl/ca.pem \\ --service-account-private-key-file=/usr/local/kubernetes/ssl/ca-key.pem \\ --cluster-signing-duration=87600h0m0s" EOF --- `生成证书` cd /usr/local/kubernetes/ssl cat > kube-controller-manager-csr.json << EOF { "CN": "system:kube-controller-manager", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "ShangHai", "ST": "ShangHai", "O": "system:masters", "OU": "System" } ] } EOF cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager ll `生成kubeconfig文件` KUBE_CONFIG="/usr/local/kubernetes/conf/kube-controller-manager.kubeconfig" KUBE_APISERVER="https://49.233.4.79:6443" kubectl config set-cluster kubernetes \ --certificate-authority=/usr/local/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=${KUBE_CONFIG} kubectl config set-credentials kube-controller-manager \ --client-certificate=/usr/local/kubernetes/ssl/kube-controller-manager.pem \ --client-key=/usr/local/kubernetes/ssl/kube-controller-manager-key.pem \ --embed-certs=true \ --kubeconfig=${KUBE_CONFIG} kubectl config set-context default \ --cluster=kubernetes \ --user=kube-controller-manager \ --kubeconfig=${KUBE_CONFIG} kubectl config use-context default --kubeconfig=${KUBE_CONFIG} ll /usr/local/kubernetes/conf --- `systemd管理controller-manager` cat > /usr/lib/systemd/system/kube-controller-manager.service << EOF [Unit] Description=Kubernetes Controller Manager Documentation=https://github.com/kubernetes/kubernetes [Service] EnvironmentFile=/usr/local/kubernetes/conf/kube-controller-manager.conf ExecStart=/usr/local/kubernetes/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTS Restart=on-failure [Install] WantedBy=multi-user.target EOF --- `启动并设置开机自启` systemctl daemon-reload systemctl start kube-controller-manager systemctl enable kube-controller-manager systemctl status kube-controller-manager -l ### kube-scheduler 安装 --- `创建配置文件` cat > /usr/local/kubernetes/conf/kube-scheduler.conf << EOF KUBE_SCHEDULER_OPTS="--logtostderr=false \\ --v=2 \\ --log-dir=/usr/local/kubernetes/logs \\ --leader-elect \\ --kubeconfig=/usr/local/kubernetes/conf/kube-scheduler.kubeconfig \\ --bind-address=127.0.0.1" EOF --- `生成kubeconfig文件` cd /usr/local/kubernetes/ssl cat > kube-scheduler-csr.json << EOF { "CN": "system:kube-scheduler", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "ShangHai", "ST": "ShangHai", "O": "system:masters", "OU": "System" } ] } EOF cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler ll --- `生成kubeconfig文件 ` KUBE_CONFIG="/usr/local/kubernetes/conf/kube-scheduler.kubeconfig" KUBE_APISERVER="https://49.233.4.79:6443" kubectl config set-cluster kubernetes \ --certificate-authority=/usr/local/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=${KUBE_CONFIG} kubectl config set-credentials kube-scheduler \ --client-certificate=/usr/local/kubernetes/ssl/kube-scheduler.pem \ --client-key=/usr/local/kubernetes/ssl/kube-scheduler-key.pem \ --embed-certs=true \ --kubeconfig=${KUBE_CONFIG} kubectl config set-context default \ --cluster=kubernetes \ --user=kube-scheduler \ --kubeconfig=${KUBE_CONFIG} kubectl config use-context default --kubeconfig=${KUBE_CONFIG} --- `systemd管理scheduler` cat > /usr/lib/systemd/system/kube-scheduler.service << EOF [Unit] Description=Kubernetes Scheduler Documentation=https://github.com/kubernetes/kubernetes [Service] EnvironmentFile=/usr/local/kubernetes/conf/kube-scheduler.conf ExecStart=/usr/local/kubernetes/bin/kube-scheduler \$KUBE_SCHEDULER_OPTS Restart=on-failure [Install] WantedBy=multi-user.target EOF --- `启动并设置开机启动` systemctl daemon-reload systemctl start kube-scheduler systemctl enable kube-scheduler systemctl status kube-scheduler -l --- ### kubectl 安装 --- `生成kubectl连接集群的证书` cd /usr/local/kubernetes/ssl cat > admin-csr.json < kubelet <-> pod` --- `创建服务` cat > /usr/lib/systemd/system/kubelet.service << EOF [Unit] Description=Kubernetes Kubelet After=docker.service [Service] EnvironmentFile=/usr/local/kubernetes/conf/kubelet.conf ExecStart=/usr/local/kubernetes/bin/kubelet \$KUBELET_OPTS Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF --- `创建服务配置文件` cat > /usr/local/kubernetes/conf/kubelet.conf << EOF KUBELET_OPTS="--logtostderr=false \\ --v=2 \\ --log-dir=/usr/local/kubernetes/logs \\ --network-plugin=cni \\ --hostname-override=k8s-master1 \\ --kubeconfig=/usr/local/kubernetes/conf/kubelet.kubeconfig \\ --bootstrap-kubeconfig=/usr/local/kubernetes/conf/bootstrap.kubeconfig \\ --config=/usr/local/kubernetes/conf/kubelet-config.yml \\ --cert-dir=/usr/local/kubernetes/ssl \\ --pod-infra-container-image=k8s.gcr.io/pause:3.6" EOF --- `创建k8s kubelet资源文件` cat > /usr/local/kubernetes/conf/kubelet-config.yml << EOF kind: KubeletConfiguration apiVersion: kubelet.config.k8s.io/v1beta1 address: 0.0.0.0 port: 10250 readOnlyPort: 10255 cgroupDriver: systemd clusterDNS: - 10.0.0.2 clusterDomain: cluster.local failSwapOn: false authentication: anonymous: enabled: false webhook: cacheTTL: 2m0s enabled: true x509: clientCAFile: /usr/local/kubernetes/ssl/ca.pem authorization: mode: Webhook webhook: cacheAuthorizedTTL: 5m0s cacheUnauthorizedTTL: 30s evictionHard: imagefs.available: 15% memory.available: 100Mi nodefs.available: 10% nodefs.inodesFree: 5% maxOpenFiles: 1000000 maxPods: 110 EOF --- KUBE_CONFIG="/usr/local/kubernetes/conf/bootstrap.kubeconfig" KUBE_APISERVER="https://49.233.4.79:6443" # apiserver IP:PORT TOKEN="f41424f202b2c2e71da40ce20d32f1d2" # 与token.csv里保持一致 /usr/local/kubernetes/conf/token.csv # 生成 kubelet bootstrap kubeconfig 配置文件 kubectl config set-cluster kubernetes \ --certificate-authority=/usr/local/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=${KUBE_CONFIG} kubectl config set-credentials "kubelet-bootstrap" \ --token=${TOKEN} \ --kubeconfig=${KUBE_CONFIG} kubectl config set-context default \ --cluster=kubernetes \ --user="kubelet-bootstrap" \ --kubeconfig=${KUBE_CONFIG} kubectl config use-context default --kubeconfig=${KUBE_CONFIG} ll --- systemctl daemon-reload systemctl stop kubelet systemctl start kubelet systemctl enable kubelet systemctl status kubelet -l --- kubectl get csr kubectl certificate approve node-csr-KbHieprZUMOvTFMHGQ1RNTZEhsSlT5X6wsh2lzfUry4 certificatesigningrequest.certificates.k8s.io/node-csr-KbHieprZUMOvTFMHGQ1RNTZEhsSlT5X6wsh2lzfUry4 approved --- `部署kube-proxy` cat > /usr/local/kubernetes/conf/kube-proxy.conf << EOF KUBE_PROXY_OPTS="--logtostderr=false \\ --v=2 \\ --log-dir=/usr/local/kubernetes/logs \\ --config=/usr/local/kubernetes/conf/kube-proxy-config.yml" EOF --- cat > /usr/local/kubernetes/conf/kube-proxy-config.yml << EOF kind: KubeProxyConfiguration apiVersion: kubeproxy.config.k8s.io/v1alpha1 bindAddress: 0.0.0.0 metricsBindAddress: 0.0.0.0:10249 clientConnection: kubeconfig: /usr/local/kubernetes/conf/kube-proxy.kubeconfig hostnameOverride: k8s-master1 clusterCIDR: 10.244.0.0/16 EOF --- cd /usr/local/kubernetes/ssl cat > kube-proxy-csr.json << EOF { "CN": "system:kube-proxy", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "ShangHai", "ST": "ShangHai", "O": "k8s", "OU": "System" } ] } EOF cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy ll --- `生成kube-proxy.kubeconfig文件` KUBE_CONFIG="/usr/local/kubernetes/conf/kube-proxy.kubeconfig" KUBE_APISERVER="https://49.233.4.79:6443" kubectl config set-cluster kubernetes \ --certificate-authority=/usr/local/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=${KUBE_CONFIG} kubectl config set-credentials kube-proxy \ --client-certificate=/usr/local/kubernetes/ssl/kube-proxy.pem \ --client-key=/usr/local/kubernetes/ssl/kube-proxy-key.pem \ --embed-certs=true \ --kubeconfig=${KUBE_CONFIG} kubectl config set-context default \ --cluster=kubernetes \ --user=kube-proxy \ --kubeconfig=${KUBE_CONFIG} kubectl config use-context default --kubeconfig=${KUBE_CONFIG} --- cat > /usr/lib/systemd/system/kube-proxy.service << EOF [Unit] Description=Kubernetes Proxy After=network.target [Service] EnvironmentFile=/usr/local/kubernetes/conf/kube-proxy.conf ExecStart=/usr/local/kubernetes/bin/kube-proxy \$KUBE_PROXY_OPTS Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF --- systemctl daemon-reload systemctl stop kube-proxy systemctl start kube-proxy systemctl enable kube-proxy systemctl status kube-proxy -l --- ## 13. kubernetes Calico 配置 bid: `2022070223079600000000000007` ### 官方网站 --- 该插件与kubernetes版本对应。 https://projectcalico.docs.tigera.io/archive/v3.20/getting-started/kubernetes/requirements ### 安装 --- 安装文档 https://projectcalico.docs.tigera.io/archive/v3.23/getting-started/kubernetes/self-managed-onprem/onpremises#install-calico-with-kubernetes-api-datastore-50-nodes-or-less ### 填坑 --- `` rm -rf /etc/cni/net.d/* rm -rf /var/lib/cni/calico systemctl restart kubelet systemctl stop kubelet systemctl stop docker rm -rf /var/lib/cni/ rm -rf /var/lib/kubelet/* rm -rf ifconfig cni0 down ifconfig flannel.1 down ifconfig docker0 down iptb ip link delete cni0 ip link delete flannel.1 systemctl start docker systemctl start kubelet `关于污点和容忍` kubectl taint node k8s-master1 node.kubernetes.io/not-ready- `` cat > apiserver-to-kubelet-rbac.yaml << EOF apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: annotations: rbac.authorization.kubernetes.io/autoupdate: "true" labels: kubernetes.io/bootstrapping: rbac-defaults name: system:kube-apiserver-to-kubelet rules: - apiGroups: - "" resources: - nodes/proxy - nodes/stats - nodes/log - nodes/spec - nodes/metrics - pods/log verbs: - "*" --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: system:kube-apiserver namespace: "" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:kube-apiserver-to-kubelet subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: kubernetes EOF kubectl apply -f apiserver-to-kubelet-rbac.yaml ー-- --- ## 14. kubernetes 二进制安装worker bid: `2022070314528700000000000008` ### kubelet --- `kubelet是 kubernetes 工作节点上的一个代理组件,运行在每个节点上。由于我的三台服务都是工作节点,所以也都需要装kubelet和kube-proxy` `apiserver <-> kubelet <-> pod` --- `创建服务` cat > /usr/lib/systemd/system/kubelet.service << EOF [Unit] Description=Kubernetes Kubelet After=docker.service [Service] EnvironmentFile=/usr/local/kubernetes/conf/kubelet.conf ExecStart=/usr/local/kubernetes/bin/kubelet \$KUBELET_OPTS Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF --- `创建服务配置文件` cat > /usr/local/kubernetes/conf/kubelet.conf << EOF KUBELET_OPTS="--logtostderr=false \\ --v=2 \\ --log-dir=/usr/local/kubernetes/logs \\ --network-plugin=cni \\ --hostname-override=k8s-node3 \\ --kubeconfig=/usr/local/kubernetes/conf/kubelet.kubeconfig \\ --bootstrap-kubeconfig=/usr/local/kubernetes/conf/bootstrap.kubeconfig \\ --config=/usr/local/kubernetes/conf/kubelet-config.yml \\ --cert-dir=/usr/local/kubernetes/ssl \\ --pod-infra-container-image=k8s.gcr.io/pause:3.6" EOF --- `创建k8s kubelet资源文件` cat > /usr/local/kubernetes/conf/kubelet-config.yml << EOF kind: KubeletConfiguration apiVersion: kubelet.config.k8s.io/v1beta1 address: 0.0.0.0 port: 10250 readOnlyPort: 10255 cgroupDriver: systemd clusterDNS: - 10.0.0.2 clusterDomain: cluster.local failSwapOn: false authentication: anonymous: enabled: false webhook: cacheTTL: 2m0s enabled: true x509: clientCAFile: /usr/local/kubernetes/ssl/ca.pem authorization: mode: Webhook webhook: cacheAuthorizedTTL: 5m0s cacheUnauthorizedTTL: 30s evictionHard: imagefs.available: 15% memory.available: 100Mi nodefs.available: 10% nodefs.inodesFree: 5% maxOpenFiles: 1000000 maxPods: 110 EOF --- KUBE_CONFIG="/usr/local/kubernetes/conf/bootstrap.kubeconfig" KUBE_APISERVER="https://49.233.4.79:6443" # apiserver IP:PORT TOKEN="47d803a011a25fee21cc2fa434c391aa" # 与token.csv里保持一致 /opt/kubernetes/cfg/token.csv # 生成 kubelet bootstrap kubeconfig 配置文件 kubectl config set-cluster kubernetes \ --certificate-authority=/usr/local/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=${KUBE_CONFIG} kubectl config set-credentials "kubelet-bootstrap" \ --token=${TOKEN} \ --kubeconfig=${KUBE_CONFIG} kubectl config set-context default \ --cluster=kubernetes \ --user="kubelet-bootstrap" \ --kubeconfig=${KUBE_CONFIG} kubectl config use-context default --kubeconfig=${KUBE_CONFIG} --- systemctl daemon-reload systemctl stop kubelet systemctl start kubelet systemctl enable kubelet systemctl status kubelet -l ---