首页 > 其他分享 >Kubernets部署实践

Kubernets部署实践

时间:2023-10-22 17:06:55浏览次数:34  
标签:kubectl nginx 部署 Kubernets 实践 apt -- swap cri

1. 背景

https://blog.51cto.com/u_15327484/7969816文章中,介绍了kubernets启动容器的基本流程。在对k8s有一定了解后,可以尝试部署一个集群,后续可以可以基于这个集群进行一些实践,从而有一定产出。一般公司都有kubernets容器管理平台,无需手动创建k8s集群,本次实践仅为了后续对大数据上云方案进行探索性实践。

2. K8S集群规划

系统:debian 9 k8s版本:v1.24.2

机器 角色
gdc-k8smaster01-taylor master
gdc-k8snode01-taylor node
gdc-k8snode02-taylor node
gdc-k8snode03-taylor node
gdc-k8snode04-taylor node

3. 准备阶段

备注:后续所有操作都基于root用户。

3.1 关闭swap分区

Swap分区介绍:SWAP是操作系统虚拟出来的一部分内存地址,它的物理存储元件是磁盘。在备份数据或恢复数据时,文件系统会向Linux系统请求大量的内存作为cache。在物理内存使用殆尽时候,为了确保程序运行,往往会将另外的一些占用物理内存地址空间的程序映射到swap分区上。

swap分区优点:当内存不足时候,可以将一部分交换出去,不会触发oom-killer。跑得慢总比不能跑好。

swap分区缺点:当进行内存交换时,往磁盘写内存数据,会触发高IO,同时会降低系统的性能。对于我们隔离做的不好的时候,会影响到其他应用的性能。

对重要服务的影响:当由于JVM内存爆满导致Linux使用swap交换内存时,这时候JVM触发GC,GC扫描所有内存,这时候需要访问磁盘,所以相比物理内存,它的速度肯定慢的令人发指,GC停顿的时间一定会非常非常恐怖,造成Java服务基本不可用。因此对于重要的服务,不建议开启swap分区。

关闭swap分区方法:

  1. 设置/proc/sys/vm/swappiness=0。表示最大限度使用物理内存,然后才是 swap空间。swappiness值越大,对swap分区使用越积极。
  2. swapoff -a临时关闭,swapon -a临时开启,swapon --show查看。
  3. vim /etc/fstab,注释LABEL=swap none swap sw 0 0行,重启机器后永久关闭swap。注意:首先要保证内存剩余要大于等于swap使用量,否则会报Cannot allocate memory!swap分区一旦释放,所有存放在swap分区的文件都会转存到物理内存上,可能会引发系统IO或者其他问题。

对于线上的机器,一般设置/proc/sys/vm/swappiness=0,保留4GB swap分区即可。

也可以关闭swap,如图,有2GB swap分区:

root@gdc-k8snode04-taylor:~# free
              total        used        free      shared  buff/cache   available
Mem:        8179236      373536     4175780       84516     3629920     7415220
Swap:       2097148           0     2097148

关闭分区后重启,swap分区大小归0:

ngadm@gdc-k8snode04-taylor:~$ free
              total        used        free      shared  buff/cache   available
Mem:        8179244      263400     7682808       10560      233036     7671028
Swap:             0           0           0

3.2 linux启动netfilter模块

linux收发包流程是一个贼复杂的过程,为了让用户可以在收发包的过程中对数据包进行修改或过滤,linux从2.4版本开始引入了netfilter子系统,在收发包的数据路径中的关键节点上提供扩展(hook)点,这些扩展点上可以编写扩展函数对数据包进行过滤和修改,扩展点一共有五个点,主要有:

  • PREROUTING,数据包刚到达时会经过这个点,通常用来完成DNAT的功能。
  • INPUT,数据包要进入本机的传输层时会经过这个点,通常用来完成防火墙入站检测。
  • FORWARD,数据包要通过本机转发时会经过这个点,通常用来完成防火墙转发过滤。
  • OUTPUT,从本机的数据包要出去的时候会经过这个点,通常用来做DNAT和防火墙出站检测。
  • POSTROUTING,数据包离开本机前会经过这个点,通常用来做SNAT。

对于同节点的两个pod,它们通过二层网络设备网桥相连。pod1通过iptables conntrack(三层转发)请求pod2,当pod2返回时,发现请求的pod在同一网桥上,直接通过网桥(二层转发)返回。由于返回数据没有原路返回(三层转发),客户端认为和服务端不在一个频道,造成DNS 解析失败。

Untitled.png

解决方法:由于数据的转发都基于linux的netfilter模块,因此可以加载netfilter,设置bridge-nf-call-iptables 这个内核参数 (置为 1),表示 bridge 设备在二层转发时也去调用 iptables 配置的三层规则 (包含 conntrack)。操作如下:

#linux添加netfilter模块:
modprobe br_netfilter
#查看linux是否加载了netfilter模块:
lsmod | grep br_netfilter
#修改内核参数,启动netfilter的ip转发功能:
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_nonlocal_bind = 1
net.ipv4.ip_forward = 1
vm.swappiness=0
vm.max_map_count=655360
fs.file-max=1000000
net.ipv4.neigh.default.gc_thresh1=1024
net.ipv4.neigh.default.gc_thresh2=4096
net.ipv4.neigh.default.gc_thresh3=8192
net.core.netdev_max_backlog=10000
fs.inotify.max_user_instances=524288
fs.inotify.max_user_watches=524288
EOF
#使上述配置生效
sudo sysctl --system /etc/sysctl.d/k8s.conf

3.3 linux启动ipvs模块

在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种 VIP(虚拟 IP)的形式。Kubernetes v1.8 添加了 ipvs 代理模式。

ipvs是工作在内核态的4层负载均衡,基于内核底层netfilter实现,netfilter主要通过各个链的钩子实现包处理和转发。ipvs由ipvsadm提供简单的CLI接口进行ipvs配置。由于ipvs工作在内核态,只处理四层协议,因此只能基于路由或者NAT进行数据转发,可以把ipvs当作一个特殊的路由器网关,这个网关可以根据一定的算法自动选择下一跳。

#启动ipvs模块:
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
#查看ipvs是否启动:
lsmod | grep -e ip_vs -e nf_conntrack_ipv4
#安装ipvsadm工具:
apt install -y ipvsadm ipset

3.4 安装docker

#首先,更新现有的包列表:
sudo apt update
#接下来,安装一些允许apt使用包通过HTTPS的必备软件包:
sudo apt install apt-transport-https ca-certificates curl gnupg2 software-properties-common
#然后将官方Docker存储库的GPG密钥添加到系统:
curl -fsSL <https://download.docker.com/linux/debian/gpg> | sudo apt-key add -
#将Docker存储库添加到APT源:
sudo add-apt-repository "deb [arch=amd64] <https://download.docker.com/linux/debian> $(lsb_release -cs) stable"
#接下来,使用新添加的repo中的Docker包更新包数据库:
sudo apt update
#最后安装docker:
apt install -y docker-ce
#注意,apt源的目录为`/etc/apt/sources.list`。
#修改docker容器参数cgroupdriver为systemd,和k8s保持一致:
#创建 /etc/docker 目录
mkdir /etc/docker

cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
}
}
EOF
#配置systemctl启动方式,配置开机自启动:
****mkdir -p /etc/systemd/system/docker.service.d
# 重启docker服务
systemctl daemon-reload && systemctl restart docker && systemctl enable docker

3.5 安装kubeadm工具

kubeadm是一个工具,用于安装k8s集群。

#第一步:更新 apt 包索引并安装使用 Kubernetes apt 仓库所需要的包:
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
#第二步:下载 Google Cloud 公开签名秘钥:
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg <https://packages.cloud.google.com/apt/doc/apt-key.gpg>
#第三步:添加 Kubernetes apt 仓库:
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] <https://apt.kubernetes.io/> kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
#第四步:更新 apt 包索引,安装 kubelet、kubeadm 和 kubectl,并锁定其版本:
sudo apt-get update
sudo apt-get install -y kubectl kubelet kubeadm
sudo apt-mark hold kubelet kubeadm kubectl
#查看kubeadm版本,当前为1.24.2:
kubeadm config images list

3.6 安装cri-docker

当前k8s版本是1.24,已经取消dockershim,直接安装cri-docker替代dockershim即可。

#下载代码:
git clone <https://github.com/Mirantis/cri-dockerd.git>
#编译安装:
# Run these commands as root
###Install GO###
wget <https://storage.googleapis.com/golang/getgo/installer_linux>
chmod +x ./installer_linux
./installer_linux
source ~/.bash_profile

cd cri-dockerd
mkdir bin
go get && go build -o bin/cri-dockerd
mkdir -p /usr/local/bin
install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
cp -a packaging/systemd/* /etc/systemd/system
sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
systemctl daemon-reload
systemctl enable cri-docker.service
systemctl enable --now cri-docker.socket

查看cri-docker是否启动:systemctl status cri-docker

Untitled 1.png

3.7 配置iptables

由于k8s集群开的端口比较随机,关闭drop以免无法访问:

vim /etc/iptables.netease
# 注释掉DROP这一行
#-A INPUT -j DROP

重启iptables:

iptables-restore < /etc/iptables.netease

4. 部署k8s集群

4.1 部署master

在gdc-k8smaster01-taylor机器上,执行:

kubeadm init --apiserver-advertise-address=主机ip  --kubernetes-version v1.24.2 --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16 --cri-socket unix:///var/run/cri-dockerd.sock

如果成功,会显示:

Untitled 2.png

按照指示,先创建kubelet的配置:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

备注:如果要重置k8s集群,就在k8s所有节点中使用reset命令:

kubeadm reset  --cri-socket unix:///var/run/cri-dockerd.sock
ipvsadm --clear
rm $HOME/.kube/config
rm -r  /etc/cni/net.d

重置后,重新执行kubeadm init xxx操作

4.2 部署node

在每台node上,执行master生成的join命令,例如:

kubeadm join 主机ip:6443 --token rromzk.x0bg9jekdr6r2a2i --discovery-token-ca-cert-hash sha256:a2a6eda7ffcd149bb6866fc9ece0b5cbb0e7738c4797db54af312891ea50b785  --cri-socket unix:///var/run/cri-dockerd.sock

注意:一定要在iptables中开放6443端口,不然无法部署Node节点。

配置node节点的kubectl环境: 将master上的/root/.kube/config文件拷贝到node节点上,然后执行sudo chown $(id -u):$(id -g) $HOME/.kube/config

k8s 重新生成token加入集群:

当master创建了1天后,k8s有新node要加入,则需要在master上重新生成token和hash值:

# 创建token,并生成完整的join node的命令
kubeadm token create --print-join-command

# 重新加入集群
kubeadm join <master ip>:6443 --token <token> --discovery-token-ca-cert-hash <hash>  --cri-socket unix:///var/run/cri-dockerd.sock

4.3 master节点配置网络

执行:

wget <https://projectcalico.docs.tigera.io/manifests/calico.yaml> > application/calico.yaml

配置网络:

kubectl apply -f application/calico.yaml

Untitled 3.png

查看状态calico状态:

kubectl  -n kube-system get pod |grep calico

Untitled 4.png

如果要重装网络插件:

# 基于原先的flannel配置,删除对应资源
kubectl delete -f kube-flannel.yml
# 删除相关配置
ifconfig cni0 down
rm -rf /var/lib/cni/
ifconfig flannel.1 down
ip link delete flannel.1
rm -f /etc/cni/net.d/*
systemctl restart kubelet

4.4 验收K8S集群

如下创建了1个master,4个node的集群:

Untitled 5.png

4.5 测试K8S集群

创建目录及文件:

mkdir application/nginx
vim application/nginx/deployment.yaml

deployment.yaml控制器配置如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

创建service资源:

vim application/nginx/service.yml

service.yml文件内容如下:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30080
  type: NodePort

请求master,创建deplyment控制器和service:

kubectl apply -f application/nginx/deployment.yaml
kubectl apply -f application/nginx/service.yml

查看pod所在机器:kubectl get pods -l app=nginx -o wide

Untitled 6.png

此时pod创建在gdc-k8snode03-taylor.i.nease.net节点上,访问nginx服务:

Untitled 7.png

删除一个pod:delete pod nginx-deployment-6595874d85-plv7q,会立刻在当前节点重建一个pod:

Untitled 8.png

删除/下线一个节点:pod会自动在另一个节点上创建。如下所示:先通过cordon下线节点gdc-k8snode03-taylor.i.nease.net,并通过drain驱逐gdc-k8snode03-taylor.i.nease.net节点上的pod,k8s会自动在新节点gdc-k8snode04-taylor.i.nease.net上创建pod:

Untitled 9.png

4.6 K8S集群常用操作

常用命令:

  • 根据YAML配置创建资源:kubectl apply -f xxx.yaml
  • 查询deployment相关信息:kubectl describe deployment nginx-deployment
  • 列出指定标签的pod列表:kubectl get pods -l app=nginx -o wide
  • 查看某一个pod信息:kubectl describe pod <pod-name>
  • 查看所有deployment:kubectl get deployment
  • 删除deployment:kubectl delete deployment nginx-deployment
  • <span style="color:#FF0000">进入容器</span>:kubectl exec -it <pod-name> -- /bin/bash
  • <span style="color:#FF0000">查看pod日志</span>:kubectl logs <pod-name> --tail 100
  • 查看所有service:kubectl get service
  • 删除指定service:kubectl delete service nginx-service
  • 查看节点详细信息:kubectl describe node gdc-k8snode04-taylor.i.nease.net
  • 查看cri-docker服务日志:journalctl -u cri-docker.service
  • 删除节点:kubectl delete node gdc-k8snode04-taylor.i.nease.net。注意,删除后,需要reset节点,再join。
  • cordon下线节点(<span style="color:#FF0000">推荐</span>):
    • 下线节点:kubectl cordon node1
    • 驱逐pod:kubectl drain node1
    • 上线节点:kubectl uncordon node1

标签:kubectl,nginx,部署,Kubernets,实践,apt,--,swap,cri
From: https://blog.51cto.com/u_15327484/7977460

相关文章

  • docker部署matomo网站访问统计工具
    软件安装cat/etc/redhat-release&&uname-aCentOSLinuxrelease7.8.2003(Core)Linuxcentos7-13.10.0-1127.el7.x86_64systemctlstopfirewalld&&systemctldisablefirewalldechoSELINUX=disabled>/etc/sysconfig/selinuxcp-pv/etc/sysc......
  • 商超外卖搜索基于Elasticsearch的优化实践
    业务背景我们是外卖搜索系统,在传统的外卖的基础上,推出了便利超市的功能。但是与外卖商家不同的是,我们有很多大型的商超,每个商超的商品数量会非常多,导致线上调用ES大量超时且ES负载较重。由于我们是多国家业务当前是根据国家拆分所以,以情况最为严重的泰国为例,有数万家商家,和几千......
  • 巧用枚举解决业务场景的 Switch 语句—Java 实践
    巧用枚举解决业务场景的Switch语句——Java实践Switch语句是一种常见的流程控制语句,用于根据不同的条件执行不同的代码块。然而,当业务场景变得复杂时,使用大量的Switch语句可能导致代码冗长、难以维护和扩展。本文将介绍如何巧妙地使用枚举类型来优化和简化Switch语句的使......
  • 华为云云耀云服务器L实例评测|企业项目最佳实践之计划任务与Queue队列实践 (十)
    十一、计划任务与Queue队列实践:1.计划任务:Linux环境下定时或者周期性的执行一些任务通常由cron这个守护进程来完成,这是一个系统自带的相对也比较方便的系统工具。sudoapt-getinstallcron//默认自带目录结构:目录说明/var/spool/cron/crontabs用户调度任务目录,是每个用户包括r......
  • 路由部署基础
    Nginx路由部署Nginx文件目录build编译Vue项目编译结果放到nginx的html目录下启动nginx,config可以更改占用的端口Tomcat......
  • Github Actions实现Spring Boot自动化部署(第二弹)
    GithubActions实现SpringBoot自动化部署(第二弹)前言​ 今天就来讲述一下如何使用GitHub结合Actions实现SpringBoot程序从提交代码到打包、容器化、部署全过程自动化。首先咱们得现有一个能够在本地运行的SpringBoot程序,并且在Github上拥有一个仓库。一、自动化部署1.1提交......
  • MDT2013自动化部署Windows系统-启动映像添加
    添加启动映像:1:打开windows部署服务控制台,右键“启动映像”,选择“添加启动映像”:2:选择启动映像文件存放位置:MDT控制台更新的启动映像存放位置:Deploymentshare\Boot\目录下:3、输入映像名称和相应说明:4、确认选定映像摘要:5、完成启动映像添加:6、完成后视图如下:接下来为大家介绍的是WDS......
  • Yarn federation原理与实践
    1.背景随着业务的增长,Yarn集群也不断扩展。节点数增多、请求增多、队列增多,造成调度性能线性下降。如下是三个集群的性能数据:集群队列数量平均调度耗时最大每秒调度数量CPS集群A27063.8ms483集群B620940微秒1150集群C399676微秒1013对于集群A,......
  • kubernets启动容器过程分析
    1.背景对于大数据组件,经常需要进行扩缩容的服务,例如Yarnnodemanager、AlluxioWorker。往往需要频繁的人工操作上线下线,非常繁琐,耗费较高的人力成本。为了降低这种人工操作的成本,可以考虑将这些服务部署到kubernets中进行管理。本文通过介绍kubernets启动容器的过程,介绍期间经......
  • RocketMQ5.0 搭建 Name Server And Broker+Proxy 同进程部署、搭建RocketMQ控制台图形
    前言RocketMQ5.0中的几个角色NameServer、Broker和Proxy,它们的作用如下:NameServer:NameServer是RocketMQ的名称服务器,负责管理消息队列和消费者组。Broker:Broker是RocketMQ的消息代理服务器,负责接收、处理和存储消息。Proxy:Proxy是RocketMQ的代理服务器,用于扩展消息......