23 视频:中级篇实操总结
你好,我是Chrono。
到今天我们“中级篇”的学习也告一段落了,在这段时间里我们使用kubeadm搭建了更接近生产环境的多节点Kubernetes集群,然后学习了Deployment、DaemonSet、Service、Ingress这4个非常重要的API对象。
这节课作为对“中级篇”的总结和回顾,仍然是视频的形式,把前面几节课里的一些操作都实际演示出来,方便你对照着操作上下文来学习。
首先我会带你看看kubeadm搭建集群的完整过程,然后编写YAML文件,示范Deployment、DaemonSet、Service、Ingress等对象的具体用法,最后是使用这些对象搭建WordPress网站。
让我们开始视频课程的学习吧。
一点说明:视频是我的操作实录,有些包安装比较慢,屏幕会几秒没有动作,在参考视频以及你自己操作的时候可以耐心一些。
一. 安装kubeadm
我们先来安装Master节点,当然在这之前你需要保证已经安装好了Docker(安装参考第1讲)。
首先四步准备工作:改主机名、改Docker配置、改网络设置、改交换分区。
修改主机名,把它改成 master
:
修改Docker的配置文件,把cgroup的驱动程序改成 systemd
,然后是修改iptables的配置,启用 br_netfilter
模块,还有修改“/etc/fstab”,关闭Linux的swap分区。
这些操作步骤都已经列在了第17讲里了,因为一个个文件修改很麻烦,我就写了一个脚本文件,把这些操作都自动化了,大概看一下:
第一部分是修改Docker配置文件然后重启,第二部分是修改iptables配置,第三部分是关闭Linux的swap分区。我们执行这个脚本,安装的准备工作就做好了。
接下来,下载kubeadm可执行文件,同样我也写成了一个方便的脚本文件:
基本流程和Kubernetes官方文档是一样的,只是改成了国内的软件源。
注意在使用 apt install
的时候,应该明确指定要安装的版本号,像这里我就使用的是Kubernetes 1.23.3,如果不指定就会使用当前的最新版本,也就是1.24。
安装完成之后,我们用 kubeadm version
、kubectl version
来看一下版本是否正确:
可以看到确实是安装了我们刚才指定的1.23.3版本。
二. 安装Kubernetes
有了kubeadm,我们就可以开始正式安装Kubernetes了。安装时需要从gcr.io拉取镜像,我这里从国内镜像网站上提前下载好了镜像,给你看一下:
这些镜像中包括Kubernetes的核心组件,比如etcd、apiserver、controller-manager。
现在我们来执行 kubeadm init
初始化Master节点,看一下脚本文件:
初始化的时候我使用了参数 pod-network-cidr
指定Pod的IP地址范围是“10.10.0.0/16”,然后Kubernetes版本也指定使用1.23.3。
为了让kubectl在安装完成后能正常工作,脚本里还会把Kubernetes的配置文件拷贝到当前用户的 .kube
目录下。
好了,现在我们就运行这个脚本。
注意Master节点初始化完成后,kubeadm会给出一些重要的提示信息,一个是拷贝配置文件,这个我们已经在脚本里做过了,另一个是Worker节点加入集群的 kubeadm join
命令,一定要保存好。我们可以新建一个文件,比如k.txt,然后把它存下来。
我们再用 kubectl version
、kubectl get node
来检查Kubernetes的版本和集群的节点状态了:
Master节点的状态是“NotReady”,接下来还要安装网络插件Flannel。
Flannel的安装很简单,记得要修改它的YAML文件,“net-conf.json”里的网络范围必须和 kubeadm init
里的一样:
现在我们用 kubectl apply
来安装Flannel网络:
稍等一小会,我们再执行 kubectl get node
来看节点状态:
就看到Master节点的状态是“Ready”,表明节点网络也工作正常了。
三. Kubernetes集群部署
Worker节点的安装步骤和Master节点是差不多的,先是改主机名,再用prepare.sh做准备工作,修改Docker配置文件、iptables,关闭Linux的swap分区,然后下载kubeadm可执行文件和Kubernetes镜像。
这几步和Master节点完全一样,我就不展示脚本文件了,直接运行。
有了kubeadm之后,因为这个是Worker节点,所以我们不需要执行 kubeadm init
,而是要执行 kubeadm join
,也就是之前安装Master节点时拷贝的那条命令。它会自动连接Master节点,然后拉取镜像,安装网络插件,最后把节点加入集群。
Worker节点安装好之后,让我们在控制台检查节点的状态,执行 kubectl get node
,会看到两个节点都是“Ready”。
现在让我们用 kubectl run
,运行Nginx来测试一下:
会看到Pod运行在Worker节点上,表明我们的Kubernetes多节点集群部署成功。
四. Deployment的使用
接下来我们来看看Deployment的用法。
首先是 kubectl api-resources
来查看Deployment的基本信息:
可以看到Deployment的简称是“deploy”,它的apiVersion是“apps/v1”,kind是“Deployment”。
然后我们执行 kubectl create
,让Kubernetes为我们自动生成Deployment的样板文件。
先要定义一个环境变量out:
然后创建名字叫“ngx-dep”的对象,使用的镜像是“nginx:alpine”:
我们把这个样板存入一个文件ngx.yml:
这里可以删除一些不需要的字段,让YAML看起来更干净,然后把replicas改成2,意思是启动两个Nginx Pod。
把Deployment的YAML写好之后,我们就可以用 kubectl apply
来创建对象了:
用 kubectl get
命令查看Deployment的状态:
最后来试验一下Deployment的应用伸缩功能,使用命令 kubectl scale
,把Pod数量改成5个:
我们再用 kubectl get
命令查看,就会发现Pod已经成功变成了5个副本:
最后删除这个Deployment:
五. DaemonSet的使用
看完Deployment,我再来演示DaemonSet。
因为DaemonSet不能使用 kubectl create
直接生成样板文件,但大体结构和Deployment是一样的,所以我们可以先生成一个Deployment,然后再修改几个字段就行了。
这里我使用了Linux系统里常用的小工具sed,直接替换Deployment里的名字,再删除replicas字段,这样就自动生成了DaemonSet的样板文件:
kubectl create deploy redis-ds --image=redis:5-alpine $out \
| sed 's/Deployment/DaemonSet/g' - \
| sed -e '/replicas/d' -
这个样板文件因为是从Deployment改来的,所以不会有tolerations字段,不能在Master节点上运行,需要手工添加。
下面这个就是已经改好的完整的DaemonSet YAML描述文件:
注意看里面的tolerations字段,它能够容忍节点的 node-role.kubernetes.io/master:NoSchedule
这个污点,也就是说能够运行在Master节点上。
现在让我们部署这个加上了“容忍度”的DaemonSet:
再用 kubectl get
查看对象的状态:
可以看到,这个Redis 的DaemonSet已经跑在了Master和Worker节点上。
最后删除这个DaemonSet:
六. Service的使用
下面我们来看看Kubernetes里的负载均衡对象Service。
因为Service对象服务于Pod、Deployment等对象,所以在创建它之前,我们需要先创建一个Deployment:
这个Deployment管理了两个Nginx Pod:
然后我们我们使用 kubectl expose
创建Service样板文件:
修改之后就是svc.yml,再用 kubectl apply
创建Service对象:
用 kubectl get svc
可以列出Service对象,可以看到它的虚IP地址:
想要看Service代理了哪些后端的Pod,要用 kubectl describe
命令:
用 kubectl get pod
可以对比验证Service是否正确代理了Nginx Pod:
现在让我们用 kubectl exec
进入Pod,验证Service的域名功能:
使用curl,加上域名“ngx-svc”,也就是Service对象的名字:
多执行几次,就会看到通过这个域名,Service对象实现了对后端Pod的负载均衡,把流量分发到不同的Pod。
我们还可以再尝试Service的其他域名形式,比如加上名字空间:
最后看一下Service使用NodePort方式对外暴露服务的用法,看一下Service对象:
在PORT里显示它分配了一个随机的端口号31980,只要访问集群里任意一个节点,加上这个端口号,就可以访问到Service对象和它后面的Pod。
我们来试验一下,注意210是Master节点,220是Worker节点:
最后删除Deployment和Service对象:
七. Ingress的使用
学习了Service之后,我们再来看管理集群入口流量的Ingress对象。
我们使用Nginx公司开发的Ingress Controller,需要按照它的文档,创建名字空间、RBAC等相关的资源,这里我使用一个简单脚本来完成:
使用命令 kubectl get ns
可以看到已经有了一个新的名字空间 nginx-ingress
。
为了测试验证Ingress和Ingress controller的用法,我们还是要先创建Deployment和Service对象:
来看一下Ingress的定义:
这个YAML里包含了两个API对象,第一个是Ingress Class,名字是ngx-ink,注意在spec里,controller要指定成Nginx Ingress Controller。
第二个对象就是路由规则对象Ingress了,我为它添加了一个注解nginx.org/lb-method,指定使用Round-Robin负载均衡算法,然后是关键字段ingressClassName,这样就可以把Ingress和Ingress Class联系起来。
后面的rules就是具体的路由规则,比较复杂,要指定host、path,还有后端要转发的Service,最好用kubectl create来自动生成,不然很容易写错。
接下来我们看看Ingress Controller的定义,它在kic YAML 里:
它其实是从Nginx官方的示例文件修改而来的,所以只需要关注几个地方。
第一个是镜像,我改成了更精简的Alpine版本,第二个是启动参数args,一定要加上-ingress-class,关联上刚才的Ingress Class对象,否则Ingress Controller就无法找到路由规则Ingress。
它后面还有几个参数,比如-health-status、-ready-status等等,你可以参考官方文档了解它们的作用。
现在我们就应用这两个YAML 文件,创建Ingress对象:
用 kubectl get
来逐个查看这些对象的状态:
kubectl get ingressclass
kubectl get ing
kubectl describe ing ngx-ing
kubectl get deploy -n nginx-ingress
kubectl get pod -n nginx-ingress
确认它们都工作正常,我们来做个测试,把本地的8080端口映射到Ingress Controller Pod的80端口:
因为在Ingress里我们设定的路由规则是ngx.test域名,所以要用curl的resolve参数来把它强制解析到127.0.0.1:
多执行几次,你就会发现Nginx Ingress Controller通过域名路由规则,把请求转发到了不同的后端Pod。
最后我们删除刚才创建的这些Deployment、Service、Ingress等对象:
kubectl delete -f deploy.yml
kubectl delete -f svc.yml
kubectl delete -f ingress.yml
kubectl delete -f kic.yml
八. 搭建WordPress网站
这里我们还是来搭建WordPress网站,实际操作Deployment、Service、Ingress这些对象的用法。
第一步是部署MariaDB:
它的ConfigMap没有变化,还是“DATABASE”“USER”“PASSWORD”那几个环境变量。下面的部署方式改成了Deployment,简单起见只使用一个实例。之后又为它定义了一个Service对象,这样我们就可以使用域名而不是IP地址来访问数据库。
第二步是部署WordPress应用:
注意在ConfigMap里我们不再使用固定IP地址了,而是改用了Service提供的域名maria-svc。然后在Deployment里,把WordPress实例设置为2,增加了冗余度,提高了可用性。之后我们还是为它定义了Service对象,并且设置为NodePort模式,指定使用端口30088。
第三步是部署Ingress:
Ingress的定义和之前差不多,但Ingress Class的名字改成了wp-ink,Ingress路由的host改成了wp.test。
Ingress Controller的变化也不大:
关键还是args里的参数-ingress-class,必须和Ingress Class匹配,也就是wp-ink。还有就是字段hostNetwork: true,让Pod直接使用节点的网络
看完了这些YAML ,让我们用kubectl apply来创建对象:
kubectl apply -f wp-maria.yml
kubectl apply -f wp-dep.yml
kubectl apply -f wp-ing.yml
kubectl apply -f wp-kic.yml
创建完成之后,我们再用kubectl get看一下对象的状态:
现在让我们来到集群之外,假设你已经修改了本地的hosts域名解析文件,把域名wp.test解析到Kubernetes的节点,那就可以直接在浏览器里输入http://wp.test来访问Nginx Ingress Controller,再访问WordPress网站了。
课后作业
如果你在操作过程中遇到困难,欢迎在留言区留言,记得把你的问题描述清楚,这样我和其他同学也能更好地就问题详细讨论。
希望你在这段时间的学习过程中有所收获,下节课就是最后的高级篇了,我们下节课再见。
- YueShi 👍(10) 💬(1)
1、推荐之前的课程全都自己完成一遍,然后在看这个实战视频,就有点查漏补缺的味道了,看的很轻松 2、关于楼上同学“按道理应该是进入Service”的困惑,有感,K8S的基本思想就是组合和适配器模式,在k8s里感觉万物皆可组合,如果不能满足,基于现有的api在适配出一个api出来,组合和适配在k8s里是互逆的 3、同志们继续学呀,在坚持学一节,就甩掉了很多人,加油💪💪💪💪
2022-08-14 - 小江爱学术 👍(3) 💬(1)
老师问个问题呀 kubectl get deploy kubectl get svc kubectl get pod -n nginx-ingress 从这里可以看出应用的deploy以及svc是在default命名空间下的,ingress是在自己的nginx-ingress命名空间下,他们在k8s中不属于一个命名空间。但是在ingress rule的配置里,关于backend的配置直接用的service的名字,是因为如果这里不提供具体的命名空间的名字,他会自动认为是default吗。谢谢。
2022-10-08 - 花花大脸猫 👍(3) 💬(2)
遇到个奇怪的问题,在node节点执行kubeadm join的时候,都会卡死,然后通过--v=5,发现连接master一直拒绝:I0816 23:05:48.343080 5359 token.go:217] [discovery] Failed to request cluster-info, will try again: Get "https://10.0.3.15:6443/api/v1/namespaces/kube-public/configmaps/cluster-info?timeout=10s": dial tcp 10.0.3.15:6443: connect: connection refused,看解决方案有说在kubeadm init的时候需要指定(108是我node节点的虚拟机IP)--apiserver-cert-extra-sans 192.168.56.108 --apiserver-advertise-address 192.168.56.108 \,凌乱了
2022-08-16 - 牙小木 👍(2) 💬(1)
如果忘了了master的join 信息也没关系,可以执行 kubeadm token create --print-join-command 如果没有信息,或者过期了,可以执行 kubeadm token create
2023-07-28 - peter 👍(2) 💬(2)
请教老师几个问题: Q1:“kubeadm join”命令里的token的时效性没有起作用。 讲kubeadm的时候,提到:“kubeadm join”命令里的token有时效性,默认是24小时。 但是,我的集群环境创建成功后,master虚拟机启动后k8s自动运行,worker虚拟机启动后自动 连接到master,一个多星期了还是这样,好像token永远不会过期,为什么? Q2:是否需要清理环境,有一键清除的命令吗? 老师的视频,每一个视频的环境都是干净的,和其他视频无关。 而我的操作不是这样。我的操作是:每一讲都在同一个集群环境中操作,操作之前也没有清理 以前的东西,比如以前创建的POD、deploy等都存在。这种操作方法不好吧,应该清理吧。 如果需要清理,有一键清除的命令吗?还是需要逐个删除?比如逐个查看cm、ds、POD等。 Q3:Service代理POD后,用exec进入POD,再用curl访问。 请问:为什么是进入POD,Service代理POD,按道理应该是进入Service呀。 Q4:删除service的时候,也必须删除deploy吗? 视频中的删除方法是: kubectl delete -f deploy.yml -f svc.yml, 有两个子问题: 第一,这里的deploy.yml应该是对应svc.yml吧,就是说svc.yml创建的service, 代理的POD是由deploy.yml创建出来的,对吧。 另外,可以只删除service而不删除service代理的POD吗? Q5:两种删除方法都可以吗? 第一种:kubectl delete delploy xxx 第二种:kubctl delete -f deploy.yml 第一种方法中的xxx是第二种方法中的 deploy.yml创建出来的。 这两种方法都可以吗? 而且,好像所有的对象都有这两种删除方法。
2022-08-12 - Greenery 👍(1) 💬(1)
老师,这个wp-kic中的service是什么作用的?我访问30080端口显示nginx404...
2023-06-25 - 吃鸡吃鸡 👍(1) 💬(1)
如果Ingress Controller的service换成云厂商slb/alb,那么入口服务发现能的重任就在负载均衡了
2023-04-07 - 农民园丁 👍(1) 💬(2)
八. 搭建 WordPress 网站 访问http://wp.test/进入安装页面,但是之后登录浏览器显示跳转到以下连接时: http://wp.test/wp-login.php?redirect_to=http%3A%2F%2Fwp.test%2Fwp-admin%2F&reauth=1 没有登录,还是停在登录界面,用户名和密码都输对了。 请教这是上面问题? 还有就是宿主机的hosts将wp.host与其中1个节点绑定,还是任意1个节点都可以,实验发现好像只能绑定其中1个节点。
2023-01-14 - 无为 👍(1) 💬(2)
老师您好, 您的课程非常的易学. 我有一个问题, 我本地的 kubeadm 并没有使用docker images 的镜像, 是我漏了什么步骤吗?
2022-12-04 - MonsterCale 👍(1) 💬(1)
worker节点kubeadm join之后,worker节点上kubectl get nodes能看到master、worker节点都Ready了,master节点kubectl get nodes只能看到master节点看不到worker节点,这是为什么
2022-10-09 - 大师兄 👍(1) 💬(2)
对比了相关git上的文件,重新弄了一次,访问 wp.test 返回错误信息: Error establishing a database connection,是否还需要其他内容调整,目前是用了git上的yaml,跟着视频部署了一遍
2022-09-02 - 龙之大者 👍(1) 💬(2)
work节点上面,join到集群成功后,运行kubectl get nodes,报错如下 Unable to connect to the server: dial tcp 192.168.49.2:8443: connect: no route to host master节点上面kubectl get nodes,可以看到master和worker,work状态not ready
2022-08-17 - BROOKS 👍(1) 💬(5)
有用 oh my zsh 的吗,在 ~/.zshrc 中定义了 export out="--dry-run=client -o yaml",使用命令导出模板时会提示: error: Invalid dry-run value (client -o yaml). Must be "none", "server", or "client".
2022-08-16 - 墨龙 👍(1) 💬(1)
请问老师,为什么replicas=2的deployment创建第二个pod的时候那么慢,但是scale到replicas=5操作时pod几乎秒扩容到了5个?谢谢
2022-08-13 - 默默且听风 👍(0) 💬(1)
自己用k3s瞎搞了一年多,回来再看老师这篇文章有种茅塞顿开的赶脚
2024-05-28