1 前述
1.1 云原生定义
Pivotal《传统应用和SOA向云原生转型指南》(2015)的云原生的特征:
符合 12 要素应用
基准代码 :一份基准代码,多份部署(类似于Git版本控制系统的main分支);
显示声明所有依赖关系 :通过依赖清单,确切地声明所有依赖项;
把后端服务当作附加资源 :各种后端服务(如数据库、消息队列、邮件服务、缓存系统),不区别对待本地或第三方服务;
构建、发布、运行 :严格区分构建、发布、运行这三个步骤;
无状态进程 :应用的进程必须无状态;
端口绑定 :互联网应用通过端口绑定来提供服务,并监听发送至该端口的请求。应用完全自我加载,不依赖于任何网络服务器;
并发 :通过进程模型进行扩展。进程是一等公民;
易处理 :进程可以瞬间开启或停止,有利于快速、弹性的伸缩应用。进程应追求最小启动时间;进程一旦接受终止信号就会优化的终止;进程在面对突然死亡时保持健壮;
开发环境与线上环境等价 :尽可能的保持开发,预发布,线上环境相同,以尽量做到持续部署;
日志 :应用本身从不存储自己的输出流,不应该试图去写或者管理日志文件,相反,每一个运行的进程都会直接的标准输出(stdout)事件流;
管理进程 :后台管理任务当作一次性进程运行;
面向微服务架构
微服务将单体系统 分解为多个“仅做好一件事”的可独立部署的服务。这件事通常代表某项业务能力,或者最小可提供业务价值的“原子“服务单元。具备以下优点:
变更周期解耦 :只要变更限于单一有界的环境,并且服务继续履行其现有合约;实现了更频繁和快速的部署,从而实现了持续的价值流动;
减少业务领域和现有代码的学习负担 ;
可以加快采用新技术的步伐 ;
提供独立、高效的服务扩展 ;
自服务敏捷架构(可以认为是DevOps):
一个能够持续部署和运行这些微服务的平台;如代码以Git形式“推送”。 然后,自服务敏捷平台构建应用程序工件,构建应用程序环境,部署应用程序,并启动必要的进程。 团队不必考虑他们的代码在哪里运行或如何到达那里,这些对用户都是透明得,因为平台会关注这些。
基于 API 的协作
抗脆弱性
云原生计算基金会(2015)定义的特征
应用容器化
面向微服务架构
应用支持容器的编排制度
云原生计算基金会(2018)定义
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API
这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更
1.2 容器、虚拟机、Docker、Openstack 和 K8S
容器&虚拟机 :均为虚拟化技术,容器更为轻量化、效率更高、启动更快;虚拟机需数分钟启动,容器仅需数十毫秒;
Docker : 容器化虚拟技术事实上的标准;
OpenStack :分布式的虚拟机服务平台,相比于普通的虚拟机软件(如Vmare),多了分布式虚拟机调度管理的功能和节点的负载均衡;
K8S :分布式的容器调度管理平台,相比于Docker,多了分布式的容器调度管理和节点的负载均衡;
注意 :常见的中文资料均言K8S是容器编排软件,这里的编排是指调度、管理的意思,而非工作流编排的意思,容易有误导性;
注意 :无论是Openstack还是K8S,均不支持跨节点的容器或虚拟机的创建;所以将多台电脑合并成一台电脑的想法是不现实的;
1.3 K8S 和 云原生
在单机上运行容器,无法发挥它的最大效能,只有形成集群,才能最大程度发挥容器的良好隔离、资源分配与编排管理的优势,而对于容器的编排管理,Swarm、Mesos 和 Kubernetes 的大战已经基本宣告结束,Kubernetes 成为了无可争议的赢家。
Kubernetes 成为云原生应用的基石
有机会成为跨云的真正的云原生应用的操作系统
1.4 K8S 介绍
官方 :Kubernetes 也称为 K8S ,是用于自动部署、扩缩和管理容器化应用程序的开源系统。
发展历史 :由Google 设计并捐赠给Cloud Native Computing Foundation (今属Linux 基金会)来使用。
能力 :Google 每周运行数十亿个容器,能够在不扩张运维团队的情况下进行规模扩展。
作用 : 相当于一个操作系统,可以快速提供PaaS 服务:1)创建各种容器化测试化环境;2)发布各种容器化服务;3)快速安装各种容器化服务,如MongoDB、Hbase 、Postgresql 、Redis 、Spark 等;快速提供IaaS服务:通过安装Openstack 或KubeVirt 等软件;快速提供FaaS 服务:通过安装Kube Native 等软件;
1.5 基本概念
Pod的设计理念基础是微服务,不同类型的业务组合由不同类型的Pod执行,一个Pod对应一个微服务
K8S中,采用manifest(yaml或json)定义对象,比如nginx服务(包含了一个nginx 容器image)定义为:
1 2 3 4 5 6 7 8 9 10 11 apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx ports:
Node: 是Pod运行的主机,可以为物理机,也可以为虚拟机。每个Node上要运行container runtime (docker或者rkt)、kubelet和kube-proxy服务
Service: 一个Pod只是一个运行服务的实例,可能在一个节点上停止,在另一个节点以一个新的IP启动一个新的Pod。在K8S集群中,客户端需要访问的服务就是Service对象。每个Service会对应一个集群内部有效的虚拟IP,集群内部通过虚拟IP访问一个服务。
Kube-proxy: 负责每个节点的硬件负载均衡
1.6 K8S 常见命令
运行一个Nginix容器:
kubectl run --image=nginx:alpine nginx-app --port=80
Kubectl 命令:
kubectl get - 类似于 docker ps,查询资源列表
kubectl describe - 类似于 docker inspect,获取资源的详细信息
kubectl logs - 类似于 docker logs,获取容器的日志
kubectl exec - 类似于 docker exec,在容器内执行一个命令
kubectl create -f file.yaml – 根据yaml创建Deployment资源
kubectl delete 删除命令,可删除node、pod、svc、depolyment
yaml 定义 Pod:
1 2 3 4 5 6 7 8 9 10 11 12 apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80
Volume:
一个Pod 一旦发生异常,Pod 产生的数据会随着 Pod 消亡而自动消失。Volume 用于持久化容器数据。
如:为 redis 容器指定一个 hostPath 来存储 redis 数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 apiVersion: v1 kind: Pod metadata: name: redis spec: containers: - name: redis image: redis volumeMounts: - name: redis-persistent-storage mountPath: /data/redis volumes: - name: redis-persistent-storage hostPath: path: /data/
Service:
kubectl创建Pod,Pob的IP地址会随着Pod的重启而变化
为了访问Pod提供的服务,采用Service提供为一组Pod一个统一的入口,并提供负载均衡和自动服务发现 。
kubectl expose deployment nginx-app --port=80 --target-port=80 --type=NodePort
Replicas set:
在一个Service中,可为Pod设置数个副本,以确保服务永不掉线
kubectl scale --replicas=3 deployment/nginx-app
滚动升级(Rolling Update):
滚动升级(Rolling Update)通过逐个副本容器替代升级的方式来实现无中断的服务升级:
kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2
滚动升级中若发生错误,可随时回滚:
kubectl rolling-update frontend-v1 frontend-v2 --rollback
资源限制:
K8S通过 cgroups 提供容器资源管理的功能,可限制每个容器的 CPU 和内存使用,比如对于刚才创建的 deployment,可以通过下面的命令限制 nginx 容器最多只用 50% 的 CPU 和 128MB 的内存:
kubectl set resources deployment nginx-app -c=nginx --limits=cpu=500m,memory=128Mi
或者在yaml中指定资源限制
健康检查:
K8S Kubernetes 提供了两种探针(Probe,支持 exec、tcpSocket 和 http 方式)来探测容器的状态:
LivenessProbe:探测应用是否处于健康状态,如果不健康则删除并重新创建容器
ReadinessProbe:探测应用是否启动完成并且处于正常服务状态,如果不正常则不会接收来自 Kubernetes Service 的流量
1.7 K8S 常用运维命令
查看pod,及所在的节点:
若有节点warn,回收垃圾失败:
1 2 kubectl drain --delete-local-data --ignore-daemonsets NODENAME kubectl uncordon NODENAME
2 K8S 集群基础环境部署
若服务器之前搭建过 K8S 集群,需要彻底删除
参考 :https://blog.csdn.net/qq_43159578/article/details/124131709
1 2 sudo systemctl stop kubelet sudo systemctl stop containerd
1 yum remove kubeadm kubectl kubelet kubernetes-cni -y
1 2 3 4 rm -rf /root/.kuberm -rf /etc/cni/net.drm -rf /etc/kubernetes/*
kubeadm reset
命令用于清除当前节点上所有与 kubeadm init
或 kubeadm join
命令创建的 Kubernetes 集群相关的状态。其主要作用如下:
移除 Kubernetes 集群相关的系统服务,如 kubelet 和 kube-proxy。
删除所有在当前节点上创建的 Kubernetes 对象,包括 Pod、Service、Deployment 等。
移除 etcd 中与当前节点相关的信息,如节点标识、配置信息等。
删除 Kubernetes 数据目录,包括证书、密钥、kubeconfig 文件等。
使用 kubeadm reset
命令可以清除当前节点上的所有 Kubernetes 相关状态,以便重新创建新的 Kubernetes 集群或者将当前节点加入到另一个 Kubernetes 集群中。在进行 kubeadm reset
操作之前,应该先备份当前节点上的重要数据和配置信息,以便在需要时进行恢复。
2.1 服务器
网络资源:各节点间通过 千兆交换机 互联(非光纤交换机)
管理节点:
计算节点:
Gisweb3,GISweb2,dellm640-01, Gisweb4, dellslot03, dellslot4
持久化存储资源:
目前采用:
nfs-client: 23服务器的/mnt/storage/k8s/pv
Node1(刀片3):
子网 IP:192.168.0.177
CPU:Intel® Xeon® Silver 4216 CPU @ 2.10GHz;32核心 ,64线程。
内存:64GB(32GB*2),每根DDR4, 3000Mhz
Node2(刀片4):
子网 IP:192.168.0.209
CPU:Intel® Xeon® Silver 4216 CPU @ 2.10GHz;32核心 ,64线程。
内存:64GB(32GB*2),每根DDR4 3200Mhz
2.2 安装过程
2.2.1 前提条件
a. 节点之中不可以有重复的主机名、MAC
地址或 product_uuid
1 cat /sys/class/dmi/id/product_uuid
b. 检查网络适配器:若有多个网卡,确保每个node的子网通过默认路由可达
c. 防火墙开放端口(所有节点) :
1 2 3 4 5 6 7 systemctl restart firewalld firewall-cmd --zone=public --add-port=443/tcp --permanent firewall-cmd --zone=public --add-port=6443/tcp --permanent firewall-cmd --zone=public --add-port=2379-2380/tcp --permanent firewall-cmd --zone=public --add-port=10250/tcp --permanent firewall-cmd --zone=public --add-port=10259/tcp --permanent firewall-cmd --zone=public --add-port=10257/tcp --permanent
d. 关闭防火墙(所有节点) :
1 2 systemctl stop firewalld NetworkManager systemctl disable firewalld NetworkManager
e. 关闭交换分区并禁用 SELinux(所有节点) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 free -m setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config swapoff -a sed -ri 's/.*swap.*/#&/' /etc/fstab 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 EOF sysctl --system
f. 时间同步(所有节点) :
1 2 3 4 yum install chrony -y systemctl start chronyd systemctl enable chronyd chronyc sources
g. 设置主机名并添加 ip 映射(所有节点) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 hostname hostnamectl set-hostname gisweb4 bash echo "125.250.153.23 gisweb4" >> /etc/hostsecho "125.250.153.23 gisweb4" >> /etc/hosts192.168.0.203 gisweb1 192.168.0.202 gisweb2 192.168.0.204 gisweb4 192.168.0.208 gisweb3 192.168.0.176 dellm640-01 192.168.0.177 dellm640-03 192.168.0.209 dellslot04 125.220.153.26 gisweb1 125.220.153.25 gisweb2 125.220.153.22 gisweb3 125.220.153.23 gisweb4 125.220.153.28 dellm640-01
2.2.2 升级 Linux 内核到最新(所有节点) :
清除缓存,重新构建缓存:
1 2 yum makecache & yum -y update
参考链接 :https://zhuanlan.zhihu.com/p/368879345
2.2.3 转发 IPv4 并让 iptables 看到桥接流量(所有节点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # a. 验证br_netfilter是否已经加载 lsmod | grep br_netfilter # b. 加载br_netfilter模块: modprobe br_netfilter # c. iptabels桥接 cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay modprobe br_netfilter # 设置所需的 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 参数而不重新启动 sysctl --system
2.2.4 安装 ipvsadm(所有节点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 yum install ipvsadm ipset sysstat conntrack libseccomp -y cat <<EOF | sudo tee /etc/modules-load.d/ipvs.conf ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack ip_tables ip_set xt_set ipt_set ipt_rpfilter ipt_REJECT ipip EOF systemctl restart systemd-modules-load.service lsmod | grep -e ip_vs -e nf_conntrack
2.2.5 修改内核参数(所有节点,lb除外)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-iptables = 1 fs.may_detach_mounts = 1 vm.overcommit_memory=1 vm.panic_on_oom=0 fs.inotify.max_user_watches=89100 fs.file-max=52706963 fs.nr_open=52706963 net.netfilter.nf_conntrack_max=2310720 net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_keepalive_probes = 3 net.ipv4.tcp_keepalive_intvl =15 net.ipv4.tcp_max_tw_buckets = 36000 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_max_orphans = 327680 net.ipv4.tcp_orphan_retries = 3 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 16384 net.ipv4.ip_conntrack_max = 65536 net.ipv4.tcp_max_syn_backlog = 16384 net.ipv4.tcp_timestamps = 0 net.core.somaxconn = 16384 net.ipv6.conf.all.disable_ipv6 = 0 net.ipv6.conf.default.disable_ipv6 = 0 net.ipv6.conf.lo.disable_ipv6 = 0 net.ipv6.conf.all.forwarding = 1 EOF sysctl --systemS
2.2.6 安装Container Runtime(选用containerd,弃用docker) :
Docker-engine+cir-dockerd方案(舍弃 ) :从kubernetes 1.24开始,dockershim已经从kubelet中移除,但因为历史问题docker却不支持kubernetes主推的CRI(容器运行时接口)标准,需要在kubelet和docker之间加上一个中间层cri-docker。cri-docker是一个支持CRI标准的shim。一头通过CRI跟kubelet交互,另一头跟docker api交互,从而间接的实现了kubernetes以docker作为容器运行时。但是这种架构缺点也很明显,调用链更长,效率更低 。因此选用containerd作为容器runtime
containerd 方案: containerd 是一个docker 的容器runtime ,成为CNCF 的官方项目
官方安装教程:https://github.com/containerd/containerd/blob/main/docs/getting-started.md
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install containerd.io mkdir -p /opt/cni/bincd /opt/cni/bintar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.1.1.tgz systemctl restart containerd systemctl enable containerd containerd config default | sudo tee /etc/containerd/config.toml vim /etc/containerd/config.toml [plugins."io.containerd.grpc.v1.cri" .containerd.runtimes.runc] ... [plugins."io.containerd.grpc.v1.cri" .containerd.runtimes.runc.options] SystemdCgroup = true 并且将 sandbox_image = "registry.k8s.io/pause:3.6" 修改为 sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6" systemctl restart containerd systemctl enable containerd netstat -nlput | grep containerd tcp 0 0 127.0.0.1:36669 0.0.0.0:* LISTEN 8665/containerd off (0.00/0/0)
2.2.7 在所有电脑上安装 kubeadm, kubelet and kubectl(所有节点)
配置阿里云的k8s源,加速安装
1 2 3 4 5 6 7 8 9 cat <<EOF | sudo tee /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=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF
将 SELinux 设置为 permissive 模式(相当于将其禁用)
1 2 setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
安装
1 2 3 4 yum install -y --nogpgcheck kubelet-1.25.2 kubeadm-1.25.2 kubectl-1.25.2 systemctl enable --now kubelet
2.2.8 启动控制面节点
1 2 3 kubeadm init --kubernetes-version=v1.25.2 --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr=10.244.0.0/16
若出现如下错误(上一次集群初始化的残留文件)
1 2 [ERROR FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
执行如下命令后再次初始化
1 2 rm -rf /var/lib/etcdrm -rf /etc/kubernetes/manifests/*
2.2.9 配置环境变量(初始化后)
1 2 3 mkdir -p $HOME /.kubecp -i /etc/kubernetes/admin.conf $HOME /.kube/configchown $(id -u):$(id -g) $HOME /.kube/config
2.2.10 将 master 作为node(管理节点上执行)
检查 node 是否存在污点
污点值有三种:
NoSchedule :一定不被调度
PreferNoSchedule :尽量不被调度【也有被调度的几率】
NoExecute :不会调度,并且还会驱逐Node已有Pod
1 kubectl describe nodes gisweb4 |grep Taints
1 2 kubectl taint nodes --all node-role.kubernetes.io/control-plane-
2.2.11 安装 Pod 网络插件(CNI:Container Network Interface)(master)
你必须部署一个基于 Pod 网络插件的 容器网络接口 (CNI),以便你的 Pod 可以相互通信。
确保kubeadm初始化时,pod_cidr 为10.244.0.0
1 curl https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml -O
1 2 3 vim kube-flannel.yml - --iface-regex=^192.168..
1 kubectl apply -f kube-flannel.yml
2.2.12 node 节点加入集群
1 2 3 kubeadm token create --print-join-command kubeadm join 125.220.153.23:6443 --token x0wdaj.d5wltdzdtos22fl6 --discovery-token-ca-cert-hash sha256:9245d363cdeb1757bacba21b9ccdc06a28e7490bcedfb0eeb404b56f769fa112
如果此步报如下错误
The connection to the server localhost:8080 was refused - did you specify the right host
出现这个问题的原因是kubectl命令需要使用kubernetes-admin
的身份来运行,在kubeadm int
启动集群的步骤中就生成了/etc/kubernetes/admin.conf
。
因此,解决方法如下,将主节点中的/etc/kubernetes/admin.conf
文件拷贝到工作节点相同目录下:
然后分别在工作节点上配置环境变量:
解决方案
1 2 scp -P22 /etc/kubernetes/admin.conf oge@125.220.153.22:/etc/kubernetes/
node
节点执行如下命令后,再次执行加入集群的命令
1 2 echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profilesource ~/.bash_profile
2.2.13 添加新的 master 节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 kubeadm token create --print-join-command kubeadm join 125.220.153.23:6443 --token mc56rw.t9b3d1ql53yhom9y --discovery-token-ca-cert-hash sha256:753ccf865a9c590413043d469a9848300871afaef7221e3fdb97d981939a2b83 kubeadm init phase upload-certs --upload-certs I0413 11:00:30.817038 10009 version.go:256] remote version is much newer: v1.27.0; falling back to: stable-1.25 [upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace [upload-certs] Using certificate key: 70d43cde7f6423b5c3e88c0fa9d08511cefbc53992dc63a13544cd548a912941 kubectl -n kube-system edit cm kubeadm-config
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 kubeadm join 125.220.153.23:6443 --token mc56rw.t9b3d1ql53yhom9y --discovery-token-ca-cert-hash sha256:753ccf865a9c590413043d469a9848300871afaef7221e3fdb97d981939a2b83 --control-plane --certificate-key 70d43cde7f6423b5c3e88c0fa9d08511cefbc53992dc63a13544cd548a912941 This node has joined the cluster and a new control plane instance was created: * Certificate signing request was sent to apiserver and approval was received. * The Kubelet was informed of the new secure connection details. * Control plane label and taint were applied to the new node. * The Kubernetes control plane instances scaled up. * A new etcd member was added to the local /stacked etcd cluster. To start administering your cluster from this node, you need to run the following as a regular user: mkdir -p $HOME /.kube sudo cp -i /etc/kubernetes/admin.conf $HOME /.kube/config sudo chown $(id -u):$(id -g) $HOME /.kube/config Run 'kubectl get nodes' to see this node join the cluster.
3 K8S 管理平台 dashboard 环境部署(管理节点)
1 kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.6.1/aio/deploy/recommended.yaml
修改配置文件(以node)
但是这个只能内部访问,所以要外部访问,要么部署 ingress,要么就是设置 service NodePort 类型。这里选择 service 暴露端口。
1 2 3 4 5 6 7 kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard kubectl get svc -A |grep kubernetes-dashboard
1 2 3 4 5 6 kubectl apply -f https://kuboard.cn/install-script/k8s-dashboard/auth.yaml kubectl -n kubernetes-dashboard create token admin-user eyJhbGciOiJSUzI1NiIsImtpZCI6IkdVQTZzb3JEM1FHdkpxVDNsSEwtVEZWc2hyR08tbmFFWnFGX2Q2OGt5cEkifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjgzNzM1MTQ1LCJpYXQiOjE2ODM3MzE1NDUsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJhZG1pbi11c2VyIiwidWlkIjoiMzBlMWQzNDEtNDc0Yi00M2MyLWIyNzYtZGIxZTU4NzM5ZTgxIn19LCJuYmYiOjE2ODM3MzE1NDUsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDphZG1pbi11c2VyIn0.mg1IU29tBpH23nglJVbRmVa2A26WZjXxMCzckQyb-dnviLBRzBuvNebb8H4YH5CNJUPkB2GGC_r7dlm5zEbPpK8RqkbwXy-wqkOoMephs83gIQkJ3RgskpWqTgqqg87e6WXHRtuzYsQQZ4Rq3Y4uQy9jJS9o1lIoRTujpmpWORb9vu4JN0RqEfK2chQqNsYCe_TCtvtvkP2EyuU3QSeYdvWh5NNZ9CYwA8l8eqA6ijrmTqZjnI6Q9Ymo7trKSuGFmffotBpN9dTYZoyv6Io_VgEz6_1oHsA0pwG-3wc41Ly11sDAzwjZvoGN1yfw0vsVcwnAjH4LkRG2ImwYIcZbig
4 安装K8S的包管理工具Helm (管理节点)
参考 :https://helm.sh/docs/intro/install/
参考 :https://www.cnblogs.com/zhanglianghhh/p/14165995.html
github地址 :https://github.com/helm/helm
1 2 3 4 5 6 cd ~/k8s/helmwget https://get.helm.sh/helm-v3.11.3-linux-amd64.tar.gz tar zxfv helm-v3.11.3-linux-amd64.tar.gz mv ./linux-amd64/helm /usr/bin/helm version
5 安装K8S的包管理工具 krew(管理节点)
参考 :https://krew.sigs.k8s.io/docs/user-guide/setup/install/
1 2 3 git version yum -y install git
1 2 3 4 5 6 7 8 9 ( set -x; cd "$(mktemp -d) " && OS="$(uname | tr '[:upper:]' '[:lower:]') " && ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/') " && KREW="krew-${OS} _${ARCH} " && curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW} .tar.gz" && tar zxvf "${KREW} .tar.gz" && ./"${KREW} " install krew )
添加 $HOME/.krew/bin
目录到您的 PATH 环境变量。 更新你的 .bashrc
或者 .zshrc
文件
1 2 3 export PATH="${KREW_ROOT:-$HOME /.krew} /bin:$PATH " source ~/.bashrc
1 2 3 4 5 6 7 8 9 10 wget https://github.com/kubernetes-sigs/krew/releases/latest/download/krew-linux_amd64.tar.gz tar -zxvf krew-linux_amd64.tar.gz export PATH="${KREW_ROOT:-$HOME /.krew} /bin:$PATH " mv ./krew-linux_amd64 ./kubectl-krewmv ./kubectl-krew /usr/local/bin/kubectl krew version
1 2 kubectl krew kubectl plugin list
6 为 K8S 创建 PV 持久卷
6.1 PV和PVC
持久卷(PersistentVolume,PV) 是集群中由管理员配置的一段网络存储。它是集群中的资源,就像节点是集群资源一样。PV持久卷和普通的Volume一样,也是使用卷插件来实现的,只是它们拥有独立于任何使用PV的Pod的生命周期。此API对象捕获存储实现的详细信息,包括NFS,iSCSI或特定于云提供程序的存储系统。
持久卷申领(PersistentVolumeClaim,PVC) 表达的是用户对存储的请求。概念上与Pod类似。Pod会耗用节点资源,而PVC申领会耗用PV资源。
6.2 用 storageClass 动态创建 PV
对1PB的大量目录创建NFS服务,gisweb1-4,以gisweb4为例子
1 2 安装NFS: yum -y install nfs-utils rpcbind
1 2 3 chown -R nobody:nfsnobody /mnt/storage/k8s/pv
1 2 3 4 vim /etc/exports /mnt/storage/k8s/pv 192.168.0.0/24(rw,sync ,no_root_squash)
1 2 3 4 5 6 7 8 9 10 11 systemctl start rpcbind systemctl enable rpcbind systemctl enable nfs systemctl start nfs systemctl start nfs-server systemctl enable nfs-server systemctl start firewalld firewall-cmd --permanent --add-service=nfs firewall-cmd --reload systemctl stop firewalld && sudo systemctl disable firewalld
1 2 exportfs -rv showmount -e 127.0.0.1
1 2 3 4 5 yum install -y nfs-utils mount -t nfs 192.168.0.204:/mnt/storage/k8s/pv /mnt/storage/k8s/pv df -h
安装nfs-client-provisioner (需要翻墙)
参考:https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
1 2 3 4 5 6 7 8 9 10 11 12 13 helm repo update helm search repo nfs-subdir-external-provisioner helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/ helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \ --set nfs.server=192.168.0.204 \ --set nfs.path=/mnt/storage/k8s/pv \ --set image.repository=registry.cn-hangzhou.aliyuncs.com/xzjs/nfs-subdir-external-provisioner \ --set image.tag=v4.0.0
手动安装 nfs-client-provisioner
参考:http://www.mydlq.club/article/109/#创建-nfs-subdir-external-provisioner-部署文件
成功后,安装时添加持久化参数,其中 nfs-storage 为安装的 storageclass 的 provisioner 字段名字
7 安装 kubeAPPS 可视化软件管理工具
参考:https://kubeapps.dev/docs/latest/tutorials/getting-started/
1 2 3 4 5 6 helm repo add bitnami https://charts.bitnami.com/bitnami kubectl create namespace kubeapps helm install kubeapps --namespace kubeapps bitnami/kubeapps
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 kubectl create --namespace default serviceaccount kubeapps-operator kubectl create clusterrolebinding kubeapps-operator --clusterrole=cluster-admin --serviceaccount=default:kubeapps-operator cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: kubeapps-operator-token namespace: default annotations: kubernetes.io/service-account.name: kubeapps-operator type: kubernetes.io/service-account-token EOF
1 kubectl get --namespace default secret kubeapps-operator-token -o go-template='{{.data.token | base64decode}}'
1 eyJhbGciOiJSUzI1NiIsImtpZCI6IkdVQTZzb3JEM1FHdkpxVDNsSEwtVEZWc2hyR08tbmFFWnFGX2Q2OGt5cEkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Imt1YmVhcHBzLW9wZXJhdG9yLXRva2VuIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6Imt1YmVhcHBzLW9wZXJhdG9yIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiNTNjY2M0N2YtZWFmMS00NDY4LWJkN2ItYTVhMzliMzJjMzExIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6a3ViZWFwcHMtb3BlcmF0b3IifQ.qsTBQODZLD1EUP5WjF_ju0-_ZFoJa2pEGCGf2zoLK71TjZeytD0GUGp4Z5ACNFuJMtedtx8tRgWhioU2oimxGdCIL4f7Szt0dOQgXD15HmoiUjYEcDQNsfTdcmfZw-m3-zwtTqa3kTTG3Wio0wf_f_ayw8qZCDL2i3PK-7h0QeAb1rQhtCz_e8huNrcshjixGlyw8aKUvdi2hPe6yvpxKJqQeOalNhT22b-ax28oIyqmC-NXYUMyRbEsgOjyuJAv6XdjqsQKbOGMKsTtNyf7CvnHl88hfRZpF0W-GuKj1ggKGYClTHuXnsv9QP-AQN1UaEtcAbUp08bHN9isedJL6w
1 2 kubectl edit svc kubeapps -n kubeapps
1 kubectl get svc -A |grep kubeapps
8 在 K8S 上部署虚拟机服务 Kubevirt
1 2 3 vim /etc/kubernetes/manifests/kube-apiserver.yaml --allow-privileged=true
1 2 3 virt-host-validate qemu yum install -y qemu-kvm libvirt virt-install bridge-utils
1 2 3 4 5 6 7 8 vim /etc/default/grub GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet intel_iommu=on" grub2-mkconfig -o /boot/grub2/grub.cfg reboot
1 2 3 4 kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/v0.58.0-rc.0/kubevirt-operator.yaml kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/v0.58.0-rc.0/kubevirt-cr.yaml
1 kubectl -n kubevirt wait kv kubevirt --for condition=Available
参考 :https://kubevirt.io/labs/kubernetes/lab2.html
1 kubectl get pods -n kubevirt
1 2 kubectl krew install virt kubectl virt help
1 2 3 4 5 6 7 8 9 10 11 12 Xxx kubectl apply -f test.yaml kubectl get vmis kubectl delete -f vmi.yaml kubectl delete vmis testvmi virtctl start/stop/pause my-vm
9 在 K8S 上部署 PostgreSQL
安装
注意:数据库安装需要持久卷,需提前创建满足要求的pv ,或者创建nas 的stroageclass ,以自动根据mysql 的pvc 创建pv 。
集群已经配置23服务器的/mnt/storage/k8s/pv
为NAS,并已经配置名字为nas-storage 的sc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 helm repo add bitnami https://charts.bitnami.com/bitnami kubectl create ns oge helm install -n oge bitnami/postgresql \ --set global.storageClass=nfs-client \ --set readReplicas.persistence.storageClass=nfs-client \ --set primary.persistence.storageClass=nfs-client \ --set primary.persistence.size=200Gi \ --set readReplicas.persistence.size=200Gi \ --set image.tag=14.5.0-debian-11-r6 helm install -n geoctap bitnami/postgresql \ --set global.storageClass=nfs-client \ --set readReplicas.persistence.storageClass=nfs-client \ --set primary.persistence.storageClass=nfs-client \ --set primary.persistence.size=200Gi \ --set readReplicas.persistence.size=200Gi \ --set image.tag=14.5.0-debian-11-r6
1 2 3 4 kubectl get secret --namespace oge postgresql -o jsonpath="{.data.postgres-password}" | base64 -d 7jXf2gsmUX
1 2 3 4 kubectl edit svc --namespace oge postgresql echo "SUBSYSTEM==\"net\", ACTION==\"add\", DRIVERS==\"?*\", ATTR{address}==\" b8:85:84:71:64:28\", ATTR{type}==\"1\", KERNEL==\"eno*\", NAME=\"eno1\"" >> /etc/udev/rules.d/70-persistent-net.rules
1 2 3 4 5 6 kubectl get deployment kubectl get all -n oge kubectl scale --replicas=1 statefulset.apps/postgresql -n oge
1 2 3 4 5 6 kubectl exec -it -n oge postgresql-0 bash psql -U postgres 7jXf2gsmUX
1 psql -h 125.220.153.23 -p 30865 -U postgres -W -f ./public.sql
10 在 K8S 上部署 MySQL
安装
注意:数据库安装需要持久卷,需提前创建满足要求的pv
,或者创建nas
的 stroageclass
,以自动根据postgresql的pvc创建pv。
集群已经配置23服务器的/mnt/storage/k8s/pv
为 NAS
,并已经配置名字为 nas-storage
的 sc
1 2 3 4 5 6 7 8 9 helm repo add bitnami https://charts.bitnami.com/bitnami helm install -n oge mysql bitnami/mysql \ --set global.storageClass=nfs-client \ --set readReplicas.persistence.storageClass=nfs-client \ --set primary.persistence.storageClass=nfs-client \ --set primary.persistence.size=200Gi \ --set readReplicas.persistence.size=200Gi
1 2 3 4 kubectl get secret --namespace oge mysql -o jsonpath="{.data.mysql-root-password}" | base64 -d VubCMiHvT1
1 2 3 4 kubectl edit svc --namespace oge mysql echo "SUBSYSTEM==\"net\", ACTION==\"add\", DRIVERS==\"?*\", ATTR{address}==\" b8:85:84:71:64:28\", ATTR{type}==\"1\", KERNEL==\"eno*\", NAME=\"eno1\"" >> /etc/udev/rules.d/70-persistent-net.rules
缩放副本集
1 2 3 4 5 kubectl get deployment kubectl get all -n oge kubectl scale --replicas=1 statefulset.apps/mysql -n oge
在K8S中进入数据库
1 2 3 4 kubectl exec -it -n oge mysql-1 bash mysql -u root -p
11 在K8S上部署 MongoDB
安装
注意:数据库安装需要持久卷,需提前创建满足要求的pv,或者创建nas的stroageclass,以自动根据postgresql的pvc创建pv。
集群已经配置23服务器的/mnt/storage/k8s/pv
为NAS,并已经配置名字为nas-storage的sc
1 2 3 4 5 6 7 8 9 helm repo add bitnami https://charts.bitnami.com/bitnami helm install -n ydy mongodb bitnami/mongodb \ --set global.storageClass=nfs-client \ --set readReplicas.persistence.storageClass=nfs-client \ --set primary.persistence.storageClass=nfs-client \ --set primary.persistence.size=100Gi \ --set readReplicas.persistence.size=100Gi
1 2 3 4 kubectl get secret --namespace ydy mongodb -o jsonpath="{.data.mongodb-root-password}" | base64 -d WUL9FPQ2V9
1 2 3 4 kubectl edit svc --namespace ydy mongodb echo "SUBSYSTEM==\"net\", ACTION==\"add\", DRIVERS==\"?*\", ATTR{address}==\" b8:85:84:71:64:28\", ATTR{type}==\"1\", KERNEL==\"eno*\", NAME=\"eno1\"" >> /etc/udev/rules.d/70-persistent-net.rules
缩放副本集
1 2 3 4 5 kubectl get deployment kubectl get all -n ydy kubectl scale --replicas=1 statefulset.apps/mongodb -n ydy
在K8S中进入数据库
1 kubectl exec -it -n ydy mongodb-644c657c4f-x62cn bash
12 在 K8S 上部署 Apache Spark
两个方式,第一种方式为Spark官方提出的;第二种为Google提出的,更符合K8S原生概念
Spark On K8S
spark-on-k8s-operator
Spark On K8S
spark-on-k8s-operator
12.1 安装 spark-on-k8s-operator
参考 :https://blog.csdn.net/w8998036/article/details/122217230
1 2 3 4 5 6 7 helm repo add spark-operator https://googlecloudplatform.github.io/spark-on-k8s-operator kubectl create ns spark-operator helm install spark-operator spark-operator/spark-operator --namespace spark-operator --set sparkJobNamespace=default --set webhook.enable=true
1 2 vim spark-application-rbac.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 apiVersion: v1 kind: ServiceAccount metadata: name: spark namespace: spark --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: spark name: spark-role rules: - apiGroups: ["" ] resources: ["pods" ] verbs: ["*" ] - apiGroups: ["" ] resources: ["services" ] verbs: ["*" ] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: spark-role-binding namespace: spark subjects: - kind: ServiceAccount name: spark namespace: spark roleRef: kind: Role name: spark-role apiGroup: rbac.authorization.k8s.io
1 kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
创建一个Spark作业的YAML配置文件,并进行部署。
创建spark-pi.yaml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 apiVersion: "sparkoperator.k8s.io/v1beta2" kind: SparkApplication metadata: name: spark-pi namespace: spark spec: type: Scala mode: cluster image: "registry.cn-hangzhou.aliyuncs.com/yudayu/spark:v3.1.1" imagePullPolicy: IfNotPresent mainClass: org.apache.spark.examples.SparkPi mainApplicationFile: "local:///opt/spark/examples/jars/spark-examples_2.12-3.1.1.jar" sparkVersion: "3.1.1" restartPolicy: type: Never volumes: - name: "test-volume" hostPath: path: "/tmp" type: Directory driver: cores: 1 coreLimit: "1200m" memory: "512m" labels: version: 3.1 .1 serviceAccount: spark volumeMounts: - name: "test-volume" mountPath: "/tmp" executor: cores: 1 instances: 2 memory: "512m" labels: version: 3.1 .1 volumeMounts: - name: "test-volume" mountPath: "/tmp"
部署一个Spark计算任务
1 kubectl apply -f spark-pi.yaml
运维
1 2 3 kubectl get sparkapplications kubectl describe sparkapplications kubectl get svc
12.2 安装 Spark On K8S
1 2 3 4 5 helm repo add bitnami https://charts.bitnami.com/bitnami kubectl create ns spark-on-k8s helm install -n spark-on-k8s spark bitnami/spark \ --set worker.coreLimit=28
1 2 3 4 5 6 7 8 9 10 ./bin/spark-submit \ --class org.apache.spark.examples.SparkPi \ --conf spark.kubernetes.container.image=bitnami/spark:3 \ --master k8s://https://125.220.153.23:6443 \ --conf spark.kubernetes.driverEnv.SPARK_MASTER_URL=spark://10.97.43.141:7077 \ --deploy-mode cluster \ --executor-memory 20G \ --num-executors 10 \ --conf spark.executor.instances=5 \ https:///data/spark-examples_2.12-3.3.0.jar 1000
1 2 3 4 5 6 kubectl run --namespace spark-on-k8s spark-oge --rm --tty -i --restart='Never' \ --image bitnami/spark:3 \ -- spark-submit --master spark://10.97.43.141:7077 \ --class org.apache.spark.examples.SparkPi \ --deploy-mode cluster \ /data/spark-examples_2.12-3.3.0.jar 100000
13 在K8S上部署redis集群
14 在K8S上部署nginx
14.1 创建pv
1 2 3 4 5 6 7 8 9 10 11 12 13 14 apiVersion: v1 kind: PersistentVolume metadata: name: nginx-ydy-pv namespace: ydy spec: capacity: storage: 10Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: manual hostPath: path: /mnt/storage/k8s/pv/ydy-nginx-pvc
14.2 创建pvc
1 2 3 4 5 6 7 8 9 10 11 12 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nginx-ydy-pvc namespace: ydy spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: manual
14.3 安装nginx并设置静态资源挂载的pvc
将nginx中的/app
挂载到/mnt/storage/k8s/pv/luluancheng-nginx-pvc
下
1 2 helm install -n ydy nginx bitnami/nginx \ --set staticSitePVC=nginx-ydy-pvc
附录:疑难问题解决:
1 K8S强制删除 namespace(会删除该命名空间中的所有 pod )
1 2 3 kubectl get ns oge -o json > oge.json
1 2 kubectl proxy --port=8081
1 2 curl -k -H "Content-Type: application/json" -X PUT --data-binary @oge.json http://127.0.0.1:8081/api/v1/namespaces/oge/finalize
2 CNI网络错误
从上面的截图中看到问题出现在给Pod分配IP上,意思是 cni0 的IP不同于``10.244.9.1/24,下面我们使用
ifconfig`命令查看IP信息
从上面的图中我们可以看到``flannel.1的 **IP** 为
10.244.9.0,然后我们又使用
cat /run/flannel/subnet.env`,该文件内容如下:
1 2 3 ifconfig cni0 down ip link delete cni0
3 28 服务器增加路由(为了让两台刀片上网)
1 2 iptables -t nat -A POSTROUTING -s 192.168.0.209/24 -o em1_2 -j MASQUERADE iptables -t nat -A POSTROUTING -s 192.168.0.177/24 -o em1_2 -j MASQUERADE
4 异常断电等导致 etcd 心跳检测出现问题
5 OpenStack服务器网络跳转镜像
作用: 保证OpenStack上服务器与实验室服务器可以 ping 通