前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >公网k8s部署(无坑小白版)

公网k8s部署(无坑小白版)

原创
作者头像
用户7706959
修改2023-05-05 17:05:59
1.5K0
修改2023-05-05 17:05:59
举报
文章被收录于专栏:go程序员的日常go程序员的日常

k8s

部署k8s集群(公网部署)

两台腾讯云服务器 在不同的vpc中 Linux版本centos7

关闭防火墙和selinux( 如果是云服务器需要去对应的控制台打开k8s部署需要的端口)

在部署 Kubernetes 集群时关闭防火墙,通常是为了避免出现网络问题导致的部署失败或集群节点之间无法通信的问题。

SELinux(Security-Enhanced Linux)是一个Linux内核模块,用于提供更高级别的访问控制和安全保护。但在某些情况下,为了方便和实用,需要牺牲一些安全性以便更好的完成某些操作,例如部署 Kubernetes 或者一些特殊的应用软件。因此,关闭 SELinux 可以在一定程度上放松对系统资源的限制,从而提高系统的灵活性和可用性。

代码语言:javascript
复制
systemctl stop firewalld && systemctl disable firewalld && iptables -F
sed -i 's/enforcing/disabled/' /etc/selinux/config && setenforce 0

swap关闭

在 Kubernetes 集群中,关闭 swap 分区是很重要的,这是因为 Kubernetes 对于内存资源的管理有着自己的特殊需求。

在 Kubernetes 的内存资源管理策略中,每个 Pod 通常都需要分配一个固定的内存量。如果 pods 的内存使用量已经超过可用内存,那么 Kubernetes 会强制终止该 Pod,并且不会再自动重启。

但是,当系统使用 swap 后,内存将被交换到硬盘上。这样,当 Pod 使用所有可用的 RAM 时,swap 将被用来存储不常用的内存块。但是,当系统交换内存时,I/O 磁盘速度的限制将导致应用程序变得特别缓慢。这会对应用程序性能和可用性造成很大的影响,甚至可能会使 Pod 直接终止或死循环,最终导致整个系统崩溃。

因此,关闭 swap 分区可以防止 Kubernetes 使用 swap,从而避免由于内存交换导致的系统性能问题和 Pod 的异常终止。但是,在关闭 swap 分区之前,需要确保系统的内存容量足够满足所有 Pod 的内存需求,以及不会因为关闭 swap 分区而导致系统崩溃或出现其他问题。

代码语言:javascript
复制
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab

修改docker的 驱动方式

k8s需要docker的驱动为native.cgroupdriver=systemd

代码语言:javascript
复制
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

修改iptables

配置的含义如下:

  1. net.bridge.bridge-nf-call-ip6tables = 1 表示启用网桥对 IPv6 的 iptables 转发机制进行处理。此配置会影响到容器间的网络通讯,如果不开启,有可能出现网络连接问题。
  2. net.bridge.bridge-nf-call-iptables = 1 表示启用网桥对 iptables 转发机制进行处理。此配置启用后,Docker 容器之间的网络转发和宿主机与容器之间的网络转发,都会被 iptables 进行控制。如果没有启用此配置,在使用容器时,常常会遇到 iptables 规则无法生效导致容器无法与外部通信的问题。

在 Docker 容器网络模式中,当容器需要访问外部网络或另一个容器时,数据包必须经过 host 上面的 iptables 规则来转发。而开启以上两个选项,可以确保网桥正确地设置了 iptables 转发规则,从而实现容器网络通讯的正确转发。

需要注意的是,以上两个选项的默认值是 0,也就是默认关闭,如果想要在 Docker 中顺畅地使用容器网络,需要手动设置这两个参数。同时,关闭这两个参数也可以提高系统的安全性,因为网络转发需要经过 iptables 的控制,关闭掉就可以防止网络攻击。

  1. net.ipv4.ip_forward 是 Linux 操作系统上一个非常重要的内核参数之一,该参数用来配置 Linux 内核是否允许数据包在主机的不同网络接口之间进行转发。

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 之间可以相互通信,从而保证了整个集群的正常工作

代码语言:javascript
复制
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

统一多个服务器的时间

代码语言:javascript
复制
yum install ntpdate -y
ntpdate time.windows.com

修改hostname

代码语言:javascript
复制
hostnamectl set-hostname k8s-master #master机器
hostnamectl set-hostname k8s-node1 #worker机器
​

安装kubeadm kubectl kubelet(注意版本 高版本的k8s不支持Docker-CE 本文选择版本1.23.3)

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 调度器,调度容器到其他可用节点上。

代码语言:javascript
复制
yum install -y kubelet-1.23.3 kubeadm-1.23.3  kubectl-1.23.3
​
systemctl enable kubelet

下载指定镜像

因为国内网络的原因导致kubeadm启动的时候一些镜像是没办法拉取下来的,有以下两种办法获取 镜像

手动拉取

罗列出kubeadm需要的镜像然后手动从阿里云拉取

代码语言:javascript
复制
kubeadm config images list --kubernetes-version v1.23.3

可以用以下的脚本获取

代码语言:javascript
复制
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

因为 minikube 本身也打包了 Kubernetes 的组件镜像,所以完全可以从它的节点里把这些镜像导出之后再拷贝过来。先启动 minikube,然后 minikube ssh 登录进虚拟节点,用 docker save -o 命令把相应版本的镜像都保存下来,再用 minikube cp 拷贝到本地

kubeadm启动master节点

命令行启动(本文尝试失败)
代码语言:javascript
复制
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

代码语言:javascript
复制
vim /etc/kubernetes/manifests/etcd.yaml
​
将下面两个配置修改为
--listen-client-urls=https://0.0.0.0:2379
--listen-peer-urls=https://0.0.0.0:2380

进程会自动重试并初始化成功

但是作者试了多次依旧不成功,最后选择下面的方法

配置文件启动(成功)
代码语言:javascript
复制
vim kubeadm-init.yaml

配置文件如下

代码语言:javascript
复制
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

启动指令

代码语言:javascript
复制
kubeadm init --config=kubeadm-init.yaml

启动之后会有

代码语言:javascript
复制
kubeadm join {$public_ip}:6443 --token abcdef.0123456789abcdef \
  --discovery-token-ca-cert-hash sha256:2f4652177e7410db7a5eb28e57b63b986be4185bb4c3380b0529c37d4b097d56

记录下来这个sh,worker节点需要这个指令加入集群

如果忘记可以用下面的指令重新生成一个

代码语言:javascript
复制
kubeadm token create --print-join-command

使用如下指令可以看 apiserver的证书是否支持你的公网ip

代码语言:javascript
复制
openssl x509 -in /etc/kubernetes/pki/apiserver.crt  -text

创建kubectl默认配置文件

按照提示复制admin.conf 到 $HOME/.kube/config

代码语言:javascript
复制
  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 服务器(通常在主节点上运行)交互所需的信息,例如:

  1. Kubernetes API 服务器的地址和端口。
  2. Administrator 证书和密钥。
  3. CA (Certificate Authority) 证书。

该管理员配置文件通常由 kubeadm 工具在初始化 Kubernetes 集群时自动生成,并存储在 /etc/kubernetes 目录下。

kubectl作为kube-apiserver的客户端需要证书和密钥来操作,所以使用admin.conf作为kubectl的配置文件

kubectl自动补全

代码语言:javascript
复制
source <(kubectl completion bash)

安装网络插件

此时使用指令

代码语言:javascript
复制
kubectl get nodes

会看到k8s-master的 status为 notReady,使用

代码语言:javascript
复制
kubectl describe node k8s-master #会发现是网络的原因

同样下面的指令也一样能发现原因

代码语言:javascript
复制
systemctl status kubelet
# 报错
"Unable to update cni config" err="no networks found in /etc/cni/net.d"
flannel(本文尝试失败)

最开始使用了 flannel的插件,

代码语言:javascript
复制
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

代码语言:javascript
复制
# 修改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

代码语言:javascript
复制
kubectl annotate node master flannel.alpha.coreos.com/public-ip-overwrite={$public_ip} #替换为公网ip
kubeadm init --config=kubeadm-init.yaml

启动之后

代码语言:javascript
复制
kubectl describe node k8s-master

会看到

代码语言:javascript
复制
flannel.alpha.coreos.com/public-ip: {$public_ip}

但是以上三种方式均失败,如果有大佬知道原因求教

calico(成功)

文档如下

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 网络和安全管理,以及从根本上解决在容器平台上的常见网络和安全问题。

代码语言:javascript
复制
# 安装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

代码语言:javascript
复制
# 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就可以启动了

kubeadm启动worker节点

在worker节点和master节点使用一样的流程安装玩kubeadm kubectl kubelet之后 join 集群

代码语言:javascript
复制
kubeadm join {$public_ip}:6443 --token abcdef.0123456789abcdef \
  --discovery-token-ca-cert-hash sha256:2f4652177e7410db7a5eb28e57b63b986be4185bb4c3380b0529c37d4b097d56

最后的结果如下图所示

让master节点也能允许pod运行

代码语言:javascript
复制
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
kubectl taint nodes --all node-role.kubernetes.io/master-

worker机器的ip转发

代码语言:javascript
复制
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是内网的 使用以下指令转发即可

代码语言:javascript
复制
 iptables -t nat -A OUTPUT -d  {$k8s-node1 INTERNAL-IP}  -j DNAT --to-destination {$node1的公网ip}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • k8s
    • 部署k8s集群(公网部署)
      • 关闭防火墙和selinux( 如果是云服务器需要去对应的控制台打开k8s部署需要的端口)
      • swap关闭
      • 修改docker的 驱动方式
      • 修改iptables
      • 统一多个服务器的时间
      • 修改hostname
      • 安装kubeadm kubectl kubelet(注意版本 高版本的k8s不支持Docker-CE 本文选择版本1.23.3)
      • 下载指定镜像
      • kubeadm启动master节点
      • 创建kubectl默认配置文件
      • kubectl自动补全
      • 安装网络插件
      • kubeadm启动worker节点
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档