CentOS7下安装K8S
启用 bridge-nf-call-iptables 这个内核参数 (置为 1),表示 bridge 设备在二层转发时也去调用 iptables 配置的三层规则 (包含 conntrack),所以开启这个参数就能够解决上述 Service 同节点通信问题,这也是为什么在 Kubernetes 环境中,大多都要求开启 bridge-nf-call-iptables 的原因。Kubernetes CN
目录
二进制方式安装docker不能使用systemd(systemctl)工具管理docker服务的问题:
为什么 kubernetes 环境要求开启 bridge-nf-call-iptables ?
配置linux net.ipv4.ip_forward 数据包转发:
CentOS7下安装docker
由于配置文件粘贴会让文档显示很乱,所以文档中缺少部分红色字体标记的service配置文件,具体内部可参数官方文档.如果需要整个文档内容可点击下载:https://download.csdn.net/download/lyclngs/89634260
在Linux上安装守护程序和客户端二进制文件:
先决条件
在尝试从二进制文件安装Docker之前,请确保您的主机满足以下先决条件:
64位安装/Linux内核的3.10或更高版本。建议使用适用于您的平台的最新版本的内核。
iptables 1.4版或更高版本/git 1.7或更高版本/ps可执行,通常由提供procps或类似的包。
XZ Utils 4.9或更高
下载静态二进制存档:
转到 https://download.docker.com/linux/static/stable/ (或更改stable为nightly或test),选择您的硬件平台,然后下载.tgz与要安装的Docker Engine版本有关的文件。
使用该tar实用程序提取存档。在dockerd和docker 二进制文件被提取。
$>wget https://download.docker.com/linux/static/stable/x86_64/docker-23.0.0.tgz
$>tar xzvf docker-23.0.0.tgz
$>cd docker
可选:将二进制文件移到可执行路径上的目录,例如/usr/bin/。如果跳过此步骤,则在调用docker或dockerd命令时必须提供可执行文件的路径。
$> sudo cp docker/doc* /usr/bin/
配置docker.server,docker.socket,containerd.service 此目录/etc/systemd/system/ 或者如下目录
$>vim /usr/lib/systemd/system/docker.service
$>vim /usr/lib/systemd/system/docker.socket
$>vim /usr/lib/systemd/system/containerd.service
启动Docker守护程序:启动doker时会启动docker.service,docker.socket,containerd.service
$>systemctl daemon-reload && systemctl start docker && systemctl enable docker
$>systemctl status docker && systemctl status docker.socket && systemctl status containerd
如果需要使用其他选项启动守护程序,请相应地修改以上命令,或者创建并编辑文件/etc/docker/daemon.json 以添加定制配置选项。
通过运行hello-world 映像来验证是否正确安装了Docker 。
$> sudo docker run hello-world
此命令下载测试图像并在容器中运行它。容器运行时,它会打印参考消息并退出
$> docker --version 查看安装版本
默认情况下,docker 命令会使用 Unix socket 与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组。
命令如下:
$ sudo groupadd docker
$ sudo usermod -G docker $USER
二进制方式安装docker不能使用systemd(systemctl)工具管理docker服务的问题:
配置 docker 的开启自启动:
$> sudo systemctl enable docker
Failed to execute operation: No such file or directory
看官网配置 systemd 的文章:Control and configure Docker with systemd
下载docker.servcie和docker.socket放到我们的/etc/systemd/system目录下
$> systemctl start docker
A dependency job for docker.service faled. See ‘journalctl -xe’ for details.
参数文档:https://github.com/moby/moby/issues/25559
修改docker.socker文档:
修改docker.service文档:
再次运行:$> service start docker
启动docker:$> systemctl start docker / service docker start
重启docker:$> systemctl restart docker / service docker restart
关闭docker :$>systemctl stop docker / service docker stop
重启守护进程:$>systemctl daemon-reload
安装Kubernetes(k8s)
官网:https://kubernetes.io/
Github:https://github.com/kubernetes/kubernetes
版本:kubernetes-1.28.0
server地址:https://github.com/kelseyhightower/kubestack/blob/master/packer/units/kube-scheduler.service
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
$>cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 应用 sysctl 参数而不重新启动
$>sudo sysctl --system
生成ca.crt ca.key证书文件放到/etc/kubernetes/pki目录下
$> mkdir -p /etc/kubernetes/pki && cd /etc/kubernetes/pki
$> openssl genrsa -out ca.key 2048
$> openssl req -x509 -new -nodes -key ca.key -subj "/CN=l92.168.106.101" -days 36500 -out ca.crt
下载:https://github.com/etcd-io/etcd/releases
wget https://github.com/etcd-io/etcd/archive/refs/tags/v3.4.22.tar.gz
$>tar -zxvf etcd-v3.4.22-linux-amd64.tar.gz
$>cd etcd-v3.4.22-linux-amd64/
$>cp etcd* /usr/bin/
$>mkdir /usr/local/etcd && cd /usr/local/etcd
创建配置文件:etcd.conf
$>vim /usr/locl/etcd/etcd.conf
创建etcd.service:https://github.com/search?q=repo%3Aetcd-io%2Fetcd%20etcd.service&type=code
$>vim /usr/lib/systemd/system/etcd.service
创建etcd的CA证书
$>vim /usr/local/etcd/etcd_ssl.conf
创建etcd的服务端面CA证书/etc/etcd/pki/
$>mkdir -p /etc/etcd/pki/ && cd /etc/etcd/pki/
$>openssl genrsa -out etcd_server.key 2048
$>openssl req -new -key etcd_server.key -config /usr/local/etcd/etcd_ssl.conf -subj "/CN=etcd-server" -out etcd_server.csr
$>openssl x509 -req -in etcd_server.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile /usr/local/etcd/etcd_ssl.conf -out etcd_server.crt
创建客户端使用的CA证书:/etc/etcd/pki/
$>openssl genrsa -out etcd_client.key 2048
$>openssl req -new -key etcd_client.key -config /usr/local/etcd/etcd_ssl.conf -subj "/CN=etcd-client" -out etcd_client.csr
$>openssl x509 -req -in etcd_client.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile /usr/local/etcd/etcd_ssl.conf -out etcd_client.crt
$>systemctl daemon-reload
$>systemctl enable etcd
$>systemctl start etcd
验证etcd集群状态:
$>etcdctl --cacert=/etc/kubernetes/pki/ca.crt --cert=/etc/etcd/pki/etcd_client.crt --key=/etc/etcd/pki/etcd_client.key --endpoints=https://192.168.106.101:2379,https://192.168.106.102:2379,https://192.168.106.103:2379 endpoint health
$>etcdctl --cacert=/etc/kubernetes/pki/ca.crt --cert=/etc/etcd/pki/etcd_client.crt --key=/etc/etcd/pki/etcd_client.key --endpoints=https://192.168.106.101:2379,https://192.168.106.102:2379,https://192.168.106.103:2379 member list -w table
证书在其中一台服务器生成.复制到其它服务器.文档目录保持一致
报错信息:
Master 节点上需要部署的服务包括 etcd kube-apiserver kube-controller-manager kube-scheduler
在工作节点 (Worker Node)上需要部署的服务包括 docker kubelet kube-proxy
下载:https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG
$>wget https://dl.k8s.io/v1.28.0/kubernetes-server-linux-amd64.tar.gz
$>tar -zxvf kubernetes-server-linux-amd64.tar.gz
$>cd kubernetes
将Kubernetes二进制可执行文件复制到/usr/bin目录下,然后在usr/lib/systemd/system目录下为各服务创建systemd服务配置文件
$>cp apiextensions-apiserver kubeadm kube-aggregator kube-apiserver kube-controller-manager kubectl kubectl-convert kubelet kube-log-runner kube-proxy kube-scheduler mounter /usr/bin/
创建master_ssl.cnf
$>vim /usr/local/kubernetes/master_ssl.cnf
$>cd /etc/kubernetes/pki/
$>openssl genrsa -out apiserver.key 2048
$>openssl req -new -key apiserver.key -config /usr/local/kubernetes/master_ssl.cnf -subj "/CN=l92.168.106.101" -out apiserver.csr
$>openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile /usr/local/kubernetes/master_ssl.cnf -out apiserver.crt
创建kube-apiserver.service
$>vim /usr/lib/systemd/system/kube-apiserver.service
配置apiserver
$>vim /etc/kubernetes/apiserver
$>systemctl daemon-reload && systemctl start kube-apiserver && systemctl enable kube-apiserver
报错:W0831 19:34:13.143157 17709 lease.go:263] Resetting endpoints for master service
修改配置文件--endpoint-reconciler-type=master-count改为lease
kube-controller-manager kube-scheduler kubelet kube-proxy作为客户端连接kube-apiserver需要为他们创建客户端证书
$>cd /etc/kubernetes/pki
$>openssl genrsa -out client.key 2048
$>openssl req -new -key client.key -subj "/CN=admin" -out client.csr
$>openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 36500 -out client.crt
subj 参数中/CN的名称可以被设置为admin用标识连接kube-apiserver的客户端用户的名称
客户端连接kube-apiserver服务所需要的kubeconfig配置文件
为kube-controller-manager,kube-scheduler,kubelet,kube-proxy服务统一创建一个kubeconfig文件作为连接kube-apiserver服务的配置文件,后续也作为kubectl命令行工具连接kube-apiserver服务的配置文件在kubeconfig文件中主要设置访问kube-apiserver的URL地址及所需CA证书的相关参数,示例如下:
$>cd /etc/kubernetes/
$>vim kubeconfig
$>vim /usr/lib/systemd/system/kube-controller-manager.service
配置controller-manager
$>vim /etc/kubernetes/controller-manager
$>systemctl daemon-reload && systemctl start kube-controller-manager && systemctl enable kube-controller-manager
$>vim /usr/lib/systemd/system/kube-scheduler.service
报错信息
配置kube-scheduler
$>vim /etc/kubernetes/kube-scheduler
$>systemctl daemon-reload && systemctl start kube-scheduler && systemctl enable kube-scheduler
配置kubelet.service 和kubelet,kubelet.config
$>vim /usr/lib/systemd/system/kubelet.service
$>vim /etc/kubernetes/kubelet
$>vim /usr/local/kubernetes/kubelet.config
$>systemctl daemon-reload && systemctl start kubelet && systemctl enable kubelet
Kubelet.config参数文档:
https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/
https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/
$>systemctl daemon-reload && systemctl start kubelet && systemctl enable kubelet
$>systemctl status kubelet
$>systemctl status containerd
$>kubectl version --client
Kubernetes CNI 提供了一个标准的接口,用于容器运行时(如 Docker、rkt 等)与网络插件之间的通信。这种插件化的设计使得 Kubernetes 可以与各种不同的网络解决方案集成,例如 Calico、Flannel、Weave 等。
Kubernetes CNI 主要负责以下几个方面的工作:
分配和管理 Pod 的 IP 地址
配置容器的网络接口
安装和配置网络插件(CNI 插件)
$>cd /usr/local/lib
$>wget https://github.com/containernetworking/plugins/releases/download/v1.1.0/cni-plugins-linux-amd64-v1.1.0.tgz
$>mkdir /opt/cni/bin -p
$>tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin
$>cd /usr/local/cni/
执行如下命令,初始化admin.conf 报错可根据提示忽略(--ignore-preflight-errors=all),执行kubeadm init会生成配置文件包含admin.conf
$>kubeadm init
$>echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
$>source ~/.bash_profile
#获取yaml文件
$>wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
$>kubectl create -f kube-flannel.yml
执行成功输出:
安装到后面发现问题不断.
使用以下命令检查 Kubernetes CNI 的状态:
kubectl describe pod <pod-name> -n kube-system
kubectl get pod -n kube-system
遇到问题:
关闭swap分区
swapoff -a #临时
sed -ri 's/.*swap.*/#&/' /etc/fstab #永久
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab #永久
查询是否开启:free -m 最后一行显示0 0 0表示没有开启
问题:dial tcp 127.0.0.1:8080: socket: too many open files
$>vim /etc/security/limits.conf
添加:
* soft nofile 65535
* hard nofile 65535
$>ulimit -n 65535 --临时生效
此问题没有找到解决方案:直接删除了kube-fannel
$>kubectl delete -f kube-flannel.yml
下面命令只为查看配置使用:
kubectl get pod -n kube-flannel
kubectl describe pod kube-flannel-ds-2wz5z -n kube-flannel
设置全局有效
vim /etc/bashrc
source <(kubectl completion bash)
若设置当前shell环境有效
source <(kubectl completion bash)
配置kube-proxy.service 和 kube-proxy
$>vim /usr/lib/systemd/system/kube-proxy.service
$>vim /etc/kubernetes/kube-proxy
$>systemctl daemon-reload && systemctl start kube-proxy && systemctl enable kube-proxy
Master上通过 kubectl 验证 Node 信息
在各个 Node 的 kubelet 和 kube-proxy 服务正常启动之后,会将本 Node 自动注册到Master上,然后就可以到 Master 主机上通过 kubectl 查询自动注册到 Kubernetes 集群的Node 的信息了由于 Master 开启了 HTTPS 认证 ,所以 kubectl 需要使用客户端 CA 证书连接 Master,可以直接使用 kube-controller-manager 的 kubeconfig 文件,命令如下:
$> kubectl --kubeconfig=/etc/kubernetes/kubeconfig get nodes
如果输出
Node 的状态为 NotReady 这是因为还没有部署 CNI 网络插件无法设置容器网络。
类似于通 kubeadm 创建 Kubernetes 集群,例如选择 Calico CNI 插件运行下面的命令一键完成 CNI 网络插件的部署:
$> kubectl apply -f "https://docs.projectcalico.org/manifests/calico.yaml"
在CNI 网络插件成功运行之后,Node 的状态会更新为 Ready,再运行命令:
$> kubectl --kubeconfig=/etc/kubernetes/kubeconfig get nodes
为了使 kubernetes 集群正常工作我们还需要部署 DNS务,建议使用 CoreDNS进行部署.
至此,一个有三个 Master 节点的高可用 Kubernetes 集群就部署完成了.接下来就可以创建 Pod、Deployment、Service 等资源对象来部署、管理容器应用和微服务了
安装coredns服务
添加coredns.yaml配置,获取配置信息地址 https://github.com/coredns/deployment/blob/master/kubernetes/coredns.yaml.sed
$>cd /usr/local/dns
$>vim coredns.yaml
通过 kubectl create 命令完成 CoreDNS 服务的创建:
$>kubectl create -f coredns.yaml
查看 deployment Pod Service, 确保容器成功启动:
$>kubectl get deployment --namespace=kube-system
NAME READY UP-TO-DATE AVAILABLE AGE
coredns 1/1 1 1 33h
$>kubectl get pods --namespace=kube-system
NAME READY STATUS RESTARTS AGE
coredns-85b4878f78-vcdnh 1/1 Running 2 33h
$>kubectl get services --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 169.169.0.100 <none> 53/UDP, 53/TCP, 9153/TCP 33h
查看信息:crictl ps -a
$>crictl logs -f 4d820678d2cde[CONTAINER]
$>crictl logs -f 4d820678d2cde[CONTAINER]
错误:
解决方案:
cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
timeout: 0
debug: false
pull-image-on-create: false
EOF
安装mysql服务
官网地址:
Run a Single-Instance Stateful Application | Kubernetes
版本地址:https://hub.docker.com/_/mysql
创建服务: Service:mysql-service.yaml
$>vim /usr/local/mysql/mysqlk8s/mysql-service.yaml
创建持久卷: PV:mysql-pv.yaml
$>vim /usr/local/mysql/mysqlk8s/mysql-pv.yaml
创建持久卷声明: PVC:mysql-pvc.yaml
$>vim /usr/local/mysql/mysqlk8s/mysql-pvc.yaml
部署 MySQL:mysql-deployment.yaml
$>vim /usr/local/mysql/mysqlk8s/mysql-deployment.yaml
创建服务:kubectl create/apply -f ***
$>kubectl create -f mysql-service.yaml
$>kubectl create -f mysql-pv.yaml
$>kubectl create -f mysql-pvc.yaml
$>kubectl create -f mysql-deployment.yaml
删除服务:kubectl create -f ***
查看已创建服务:
$>kubectl get pods
如果指定了命令空间则需要加上 -n 空间名称
$>kubectl get pods -n mysql
$>kubectl describe pod mysql -n k8s-mysql
$>kubectl get deployment
$>kubectl get svc
$>kubectl get pv
$>kubectl get pvc
$>kubectl get ns
$>kubectl get rs
可以写一个文件中以“---”分隔每一个kind.创建所有的服务:
$>vim /usr/local/mysql/mysqlk8s/mysql-deployment-all.yaml
$>kubectl create -f mysql-deployment-all.yaml
连接mysql,IP+30366端口
为什么 kubernetes 环境要求开启 bridge-nf-call-iptables ?
Kubernetes环境中,很多时候都要求节点内核参数开启 bridge-nf-call-iptables:
sysctl -w net.bridge.bridge-nf-call-iptables=1
参考官方文档 Network Plugin Requirements
如果不开启或中途因某些操作导致参数被关闭了,就可能造成一些奇奇怪怪的网络问题,排查起来非常麻烦。
为什么要开启呢?本文就来跟你详细掰扯下。
基于网桥的容器网络
Kubernetes 集群网络有很多种实现,有很大一部分都用到了 Linux 网桥:
每个 Pod 的网卡都是 veth 设备,veth pair 的另一端连上宿主机上的网桥。
由于网桥是虚拟的二层设备,同节点的 Pod 之间通信直接走二层转发,跨节点通信才会经过宿主机 eth0。
Service 同节点通信问题
不管是 iptables 还是 ipvs 转发模式,Kubernetes 中访问 Service 都会进行 DNAT,将原本访问 ClusterIP:Port 的数据包 DNAT 成 Service 的某个 Endpoint (PodIP:Port),然后内核将连接信息插入 conntrack 表以记录连接,目的端回包的时候内核从 conntrack 表匹配连接并反向 NAT,这样原路返回形成一个完整的连接链路:
但是 Linux 网桥是一个虚拟的二层转发设备,而 iptables conntrack 是在三层上,所以如果直接访问同一网桥内的地址,就会直接走二层转发,不经过 conntrack:
Pod 访问 Service,目的 IP 是 Cluster IP,不是网桥内的地址,走三层转发,会被 DNAT 成 PodIP:Port。
如果 DNAT 后是转发到了同节点上的 Pod,目的 Pod 回包时发现目的 IP 在同一网桥上,就直接走二层转发了,没有调用 conntrack,导致回包时没有原路返回 (见下图)。
由于没有原路返回,客户端与服务端的通信就不在一个 “频道” 上,不认为处在同一个连接,也就无法正常通信。
常见的问题现象就是偶现 DNS 解析失败,当 coredns 所在节点上的 pod 解析 dns 时,dns 请求落到当前节点的 coredns pod 上时,就可能发生这个问题。
开启 bridge-nf-call-iptables
如果 Kubernetes 环境的网络链路中走了 bridge 就可能遇到上述 Service 同节点通信问题,而 Kubernetes 很多网络实现都用到了 bridge。
启用 bridge-nf-call-iptables 这个内核参数 (置为 1),表示 bridge 设备在二层转发时也去调用 iptables 配置的三层规则 (包含 conntrack),所以开启这个参数就能够解决上述 Service 同节点通信问题,这也是为什么在 Kubernetes 环境中,大多都要求开启 bridge-nf-call-iptables 的原因。
配置linux net.ipv4.ip_forward 数据包转发:
出于安全考虑,Linux系统默认是禁止数据包转发的。所谓转发即当主机拥有多于一块的网卡时,其中一块收到数据包,根据数据包的目的ip地址将数据包发往本机另一块网卡,该网卡根据路由表继续发送数据包。这通常是路由器所要实现的功能。
要让Linux系统具有路由转发功能,需要配置一个Linux的内核参数net.ipv4.ip_forward。这个参数指定了Linux系统当前对路由转发功能的支持情况;其值为0时表示禁止进行IP转发;如果是1,则说明IP转发功能已经打开
文档
更多推荐
所有评论(0)