两台腾讯云服务器 在不同的vpc中 Linux版本centos7
在部署 Kubernetes 集群时关闭防火墙,通常是为了避免出现网络问题导致的部署失败或集群节点之间无法通信的问题。
SELinux(Security-Enhanced Linux)是一个Linux内核模块,用于提供更高级别的访问控制和安全保护。但在某些情况下,为了方便和实用,需要牺牲一些安全性以便更好的完成某些操作,例如部署 Kubernetes 或者一些特殊的应用软件。因此,关闭 SELinux 可以在一定程度上放松对系统资源的限制,从而提高系统的灵活性和可用性。
systemctl stop firewalld && systemctl disable firewalld && iptables -F
sed -i 's/enforcing/disabled/' /etc/selinux/config && setenforce 0
在 Kubernetes 集群中,关闭 swap 分区是很重要的,这是因为 Kubernetes 对于内存资源的管理有着自己的特殊需求。
在 Kubernetes 的内存资源管理策略中,每个 Pod 通常都需要分配一个固定的内存量。如果 pods 的内存使用量已经超过可用内存,那么 Kubernetes 会强制终止该 Pod,并且不会再自动重启。
但是,当系统使用 swap 后,内存将被交换到硬盘上。这样,当 Pod 使用所有可用的 RAM 时,swap 将被用来存储不常用的内存块。但是,当系统交换内存时,I/O 磁盘速度的限制将导致应用程序变得特别缓慢。这会对应用程序性能和可用性造成很大的影响,甚至可能会使 Pod 直接终止或死循环,最终导致整个系统崩溃。
因此,关闭 swap 分区可以防止 Kubernetes 使用 swap,从而避免由于内存交换导致的系统性能问题和 Pod 的异常终止。但是,在关闭 swap 分区之前,需要确保系统的内存容量足够满足所有 Pod 的内存需求,以及不会因为关闭 swap 分区而导致系统崩溃或出现其他问题。
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
k8s需要docker的驱动为native.cgroupdriver=systemd
cat <<EOF | sudo tee /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],#驱动方式 必须修改
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com"#镜像地址 也可以用阿里的 外网的话不需要
]
}
EOF
sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker
配置的含义如下:
net.bridge.bridge-nf-call-ip6tables = 1
表示启用网桥对 IPv6 的 iptables 转发机制进行处理。此配置会影响到容器间的网络通讯,如果不开启,有可能出现网络连接问题。net.bridge.bridge-nf-call-iptables = 1
表示启用网桥对 iptables 转发机制进行处理。此配置启用后,Docker 容器之间的网络转发和宿主机与容器之间的网络转发,都会被 iptables 进行控制。如果没有启用此配置,在使用容器时,常常会遇到 iptables 规则无法生效导致容器无法与外部通信的问题。在 Docker 容器网络模式中,当容器需要访问外部网络或另一个容器时,数据包必须经过 host 上面的 iptables 规则来转发。而开启以上两个选项,可以确保网桥正确地设置了 iptables 转发规则,从而实现容器网络通讯的正确转发。
需要注意的是,以上两个选项的默认值是 0,也就是默认关闭,如果想要在 Docker 中顺畅地使用容器网络,需要手动设置这两个参数。同时,关闭这两个参数也可以提高系统的安全性,因为网络转发需要经过 iptables 的控制,关闭掉就可以防止网络攻击。
当 net.ipv4.ip_forward=1
时,表示 IP 转发已经开启。这个参数是用于实现 Linux 主机的路由功能,即当 Linux 主机不仅仅是一个单纯的终端设备,而是一个网络设备时,可以通过开启 IP 转发功能,让主机能够将数据包在不同网络接口(如:网卡)之间转发。
在 Kubernetes 集群中,开启 net.ipv4.ip_forward=1
非常重要,因为在 Kubernetes 中,Pod 之间需要通过网络相互通信。如果数据包不能在不同的节点之间转发,Pod 就不能通过 Kubernetes 网络正确地访问对方。
另外,需要注意的是,在开启 IP 转发之前,需要确保相应的网络已经配置好、已经连接,并且网络和路由规则已经正确地设置和生效,以确保能够实现正确的网络转发和路由工作。
因此,在 Linux 主机上设置 net.ipv4.ip_forward=1
,可以确保 Kubernetes 集群中的各个 Pod 之间可以相互通信,从而保证了整个集群的正常工作
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward=1 # better than modify /etc/sysctl.conf
EOF
sudo sysctl --system
yum install ntpdate -y
ntpdate time.windows.com
hostnamectl set-hostname k8s-master #master机器
hostnamectl set-hostname k8s-node1 #worker机器
Kubeadm 是由 Kubernetes 官方提供的一个命令行工具,用于在 Linux 系统上快速、简单地部署 Kubernetes 环境。Kubeadm 提供了一种简洁、易于使用的方式来初始化 Kubernetes 控制平面,并将节点加入 Kubernetes 集群中。此外,它还支持自定义插件来满足各种区分的组织要求,如:CNI 网络插件、 Kubeadm Config 配置文件、等等。
kubectl是Kubernetes的客户端命令行工具,是Kubernetes中使用最广泛的客户端工具之一。kubectl通过HTTP协议与Kubernetes API Server进行通信,可以用于管理Kubernetes集群中的各种资源及发布应用程序,如Pod、Service、Deployment、Node等。
kubelet 是 Kubernetes 中的一个核心组件,用于管理和控制运行在 Kubernetes 节点上的容器。Kubelet 是 Kubernetes Node 上的主要组件之一,它运行在节点上并监听 Kubernetes API,以接收新的 Pod 定义并确保在 Node 上正常运行它们。Kubelet 负责处理从 Master 节点传递下来的容器创建请求,例如启动、停止和重启容器,它还负责监视容器的生命周期,对容器的状态变化做出反应,如容器退出或死亡等等。此外,kubelet 还负责节点的资源监控,如 CPU、内存、磁盘等,当节点的资源利用率超过预设阈值时,Kubelet 会采取相应的措施,如通知 Scheduler 调度器,调度容器到其他可用节点上。
yum install -y kubelet-1.23.3 kubeadm-1.23.3 kubectl-1.23.3
systemctl enable kubelet
因为国内网络的原因导致kubeadm启动的时候一些镜像是没办法拉取下来的,有以下两种办法获取 镜像
罗列出kubeadm需要的镜像然后手动从阿里云拉取
kubeadm config images list --kubernetes-version v1.23.3
可以用以下的脚本获取
repo=registry.aliyuncs.com/google_containers
for name in `kubeadm config images list --kubernetes-version v1.23.3`; do #获取需要的镜像
src_name=${name#k8s.gcr.io/}
src_name=${src_name#coredns/}
docker pull $repo/$src_name # 从阿里云拉取镜像
docker tag $repo/$src_name $name # tag命名为kubeadm config images list --kubernetes-version v1.23.3 对应的tag
docker rmi $repo/$src_name
done
因为 minikube 本身也打包了 Kubernetes 的组件镜像,所以完全可以从它的节点里把这些镜像导出之后再拷贝过来。先启动 minikube,然后 minikube ssh 登录进虚拟节点,用 docker save -o 命令把相应版本的镜像都保存下来,再用 minikube cp 拷贝到本地
kubeadm init --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.23.3 --apiserver-advertise-address {$public_ip} --control-plane-endpoint={$public_ip} --apiserver-bind-port 6443 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --v=6
#--v=6 v>5能在启动的时候显示更多的细节
#public_ip 公网ip(如果你是在一个vpc内搭建的话可以使用内网IP)
在启动之后 进程会block在如下位置
因为 etcd 绑定端口的时候使用外网 IP,而云服务器外网 IP 并不是本机的网卡,而是网关分配的一个供外部访问的 IP,从而导致初始化进程一直重试绑定,长时间卡住后失败。
有网络上的文档提出的方法是在卡住的同时 打开另一个终端修改k8s的etcd.yaml
vim /etc/kubernetes/manifests/etcd.yaml
将下面两个配置修改为
--listen-client-urls=https://0.0.0.0:2379
--listen-peer-urls=https://0.0.0.0:2380
进程会自动重试并初始化成功
但是作者试了多次依旧不成功,最后选择下面的方法
vim kubeadm-init.yaml
配置文件如下
apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: {$public_ip} #你的公网ip
bindPort: 6443
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
extraArgs:
listen-client-urls: https://0.0.0.0:2379 #直接在配置文件指定
listen-peer-urls: https://0.0.0.0:2380 #直接在配置文件指定
kind: ClusterConfiguration
kubernetesVersion: 1.23.3
networking:
dnsDomain: cluster.local
podSubnet: "10.244.0.0/16"
serviceSubnet: 10.96.0.0/12
imageRepository: "registry.aliyuncs.com/google_containers"
controlPlaneEndPoint: "{$public_ip}:6443"
scheduler: {}
---
apiVersion: kubeadm.k8s.io/v1beta2
kind: UserConfig
metadata:
name: admin
users:
- name: admin
user:
client-certificate: /etc/kubernetes/pki/admin.crt
client-key: /etc/kubernetes/pki/admin.key
embed-certs: true
certificate-authority: /etc/kubernetes/pki/ca.crt
启动指令
kubeadm init --config=kubeadm-init.yaml
启动之后会有
kubeadm join {$public_ip}:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:2f4652177e7410db7a5eb28e57b63b986be4185bb4c3380b0529c37d4b097d56
记录下来这个sh,worker节点需要这个指令加入集群
如果忘记可以用下面的指令重新生成一个
kubeadm token create --print-join-command
使用如下指令可以看 apiserver的证书是否支持你的公网ip
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text
按照提示复制admin.conf 到 $HOME/.kube/config
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl使用的默认配置文件是$HOME/.kube/config,/etc/kubernetes/admin.conf 是 Kubernetes 集群的管理员配置文件,它包含了与 Kubernetes API 服务器(通常在主节点上运行)交互所需的信息,例如:
该管理员配置文件通常由 kubeadm 工具在初始化 Kubernetes 集群时自动生成,并存储在 /etc/kubernetes 目录下。
kubectl作为kube-apiserver的客户端需要证书和密钥来操作,所以使用admin.conf作为kubectl的配置文件
source <(kubectl completion bash)
此时使用指令
kubectl get nodes
会看到k8s-master的 status为 notReady,使用
kubectl describe node k8s-master #会发现是网络的原因
同样下面的指令也一样能发现原因
systemctl status kubelet
# 报错
"Unable to update cni config" err="no networks found in /etc/cni/net.d"
最开始使用了 flannel的插件,
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
所有的 daemonSet和pod 都是正常的,/etc/cni/net.d/ 下也有flannel的配置文件但是网络依旧失败,
尝试的措施有
1.修改kube-flannel.yml 之后kubectl apply -f kube-flannel.yml
# 修改kube-flannel.yml
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
},
"PublicIP": "192.168.0.100"
}
2.修改/etc/cni/net.d/10-flannel.conflist
添加IP配置重启kubelet
3.重启k8s 重启之前修改flannel.alpha.coreos.com/public-ip-overwrite
kubectl annotate node master flannel.alpha.coreos.com/public-ip-overwrite={$public_ip} #替换为公网ip
kubeadm init --config=kubeadm-init.yaml
启动之后
kubectl describe node k8s-master
会看到
flannel.alpha.coreos.com/public-ip: {$public_ip}
但是以上三种方式均失败,如果有大佬知道原因求教
文档如下
https://docs.tigera.io/calico/latest/getting-started/kubernetes/quickstart
Tigera Operator 是一个 Kubernetes 控制器,用于管理 Calico 和相关网络和安全解决方案的部署和运行。它可以部署 Calico 和其相关组件(如 Calico Policy Controller、Calico Enterprise 等)以及 Tigera Secure Enterprise Edition 中的所有组件。
Calico 是一个开源的容器网络和网络安全解决方案,提供了针对 Kubernetes 和容器平台的高效网络连接和网络策略管理。它是一种基于 BGP 的容器网络解决方案,支持网络分段、跨主机和跨 K8s 集群的互连等功能,以实现高性能、高可用性的容器通信。
在 K8s 集群中使用 Calico,需要先部署 Calico 相应的组件,如:calico/node、calico/cni 等。而 Tigera Operator 可以让您完成这些工作,简化了 Calico 的部署和管理,提高了 Kubernetes 集群的网络和安全性能。
同时,Tigera Operator 还支持 Istio service mesh,Kubernetes Network Policies 和 Common Services 等,并提供了各种高级功能(如 IPAM、高级网络流控制、网络策略、安全审计等),这些功能可以帮助用户快速实现 Kubernetes 网络和安全管理,以及从根本上解决在容器平台上的常见网络和安全问题。
# 安装tigera-operator
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/tigera-operator.yaml
# 安装calico
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/custom-resources.yaml
custom-resources.yaml需要修改pod network CIDR.
或者对于custom-resource.yaml直接替换问下面的yaml
# This section includes base Calico installation configuration.
# For more information, see: https://projectcalico.docs.tigera.io/master/reference/installation/api#operator.tigera.io/v1.Installation
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
# Configures Calico networking.
calicoNetwork:
# Note: The ipPools section cannot be modified post-install.
ipPools:
- blockSize: 26
cidr: 10.244.0.0/16 # 启动指令的--pod-network-cidr 或者是启动配置文件的podSubnet
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()
---
# This section configures the Calico API server.
# For more information, see: https://projectcalico.docs.tigera.io/master/reference/installation/api#operator.tigera.io/v1.APIServer
apiVersion: operator.tigera.io/v1
kind: APIServer
metadata:
name: default
spec: {}
calico就可以启动了
在worker节点和master节点使用一样的流程安装玩kubeadm kubectl kubelet之后 join 集群
kubeadm join {$public_ip}:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:2f4652177e7410db7a5eb28e57b63b986be4185bb4c3380b0529c37d4b097d56
最后的结果如下图所示
让master节点也能允许pod运行
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
kubectl taint nodes --all node-role.kubernetes.io/master-
worker机器的ip转发
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master Ready control-plane,master 11d v1.23.3 publicIp <none> CentOS Linux 7 (Core) 3.10.0-1160.11.1.el7.x86_64 docker://20.10.5
k8s-node1 Ready <none> 10d v1.23.3 10.0.4.14 <none> CentOS Linux 7 (Core) 3.10.0-1160.11.1.el7.x86_64 docker://20.10.5
可以看到 node的internal_ip 10.0.4.14是内网的 使用以下指令转发即可
iptables -t nat -A OUTPUT -d {$k8s-node1 INTERNAL-IP} -j DNAT --to-destination {$node1的公网ip}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。