learn-tech/专栏/Kubernetes入门实战课/22实战演练:玩转Kubernetes(2).md
2024-10-16 06:37:41 +08:00

14 KiB
Raw Blame History

                        因收到Google相关通知网站将会择期关闭。相关通知内容
                        
                        
                        22 实战演练玩转Kubernetes2
                        你好我是Chrono。

我们的“中级篇”到今天马上就要结束了,感谢你这段时间坚持不懈的学习。

作为“中级篇”的收尾课程,我照例还是会对前面学过的内容做一个全面的回顾和总结,把知识点都串联起来,加深你对它们的印象。

下面我先梳理一下“中级篇”里讲过的Kubernetes知识要点然后是实战演示搭建WordPress网站。当然这次比前两次又有进步不用Docker也不用裸Pod而是用我们新学习的Deployment、Service、Ingress等对象。

Kubernetes技术要点回顾

Kubernetes是云原生时代的操作系统它能够管理大量节点构成的集群让计算资源“池化”从而能够自动地调度运维各种形式的应用。

搭建多节点的Kubernetes集群是一件颇具挑战性的工作好在社区里及时出现了kubeadm这样的工具可以“一键操作”使用 kubeadm init、kubeadm join 等命令从无到有地搭建出生产级别的集群([17讲])。

kubeadm使用容器技术封装了Kubernetes组件所以只要节点上安装了容器运行时Docker、containerd等它就可以自动从网上拉取镜像然后以容器的方式运行组件非常简单方便。

在这个更接近实际生产环境的Kubernetes集群里我们学习了Deployment、DaemonSet、Service、Ingress、Ingress Controller等API对象。

[18讲]Deployment是用来管理Pod的一种对象它代表了运维工作中最常见的一类在线业务在集群中部署应用的多个实例而且可以很容易地增加或者减少实例数量从容应对流量压力。

Deployment的定义里有两个关键字段一个是 replicas它指定了实例的数量另一个是 selector它的作用是使用标签“筛选”出被Deployment管理的Pod这是一种非常灵活的关联机制实现了API对象之间的松耦合。

[19讲]DaemonSet是另一种部署在线业务的方式它很类似Deployment但会在集群里的每一个节点上运行一个Pod实例类似Linux系统里的“守护进程”适合日志、监控等类型的应用。

DaemonSet能够任意部署Pod的关键概念是“污点”taint和“容忍度”toleration。Node会有各种“污点”而Pod可以使用“容忍度”来忽略“污点”合理使用这两个概念就可以调整Pod在集群里的部署策略。

[20讲]由Deployment和DaemonSet部署的Pod在集群中处于“动态平衡”的状态总数量保持恒定但也有临时销毁重建的可能所以IP地址是变化的这就为微服务等应用架构带来了麻烦。

Service是对Pod IP地址的抽象它拥有一个固定的IP地址再使用iptables规则把流量负载均衡到后面的Pod节点上的kube-proxy组件会实时维护被代理的Pod状态保证Service只会转发给健康的Pod。

Service还基于DNS插件支持域名所以客户端就不再需要关心Pod的具体情况只要通过Service这个稳定的中间层就能够访问到Pod提供的服务。

[21讲]Service是四层的负载均衡但现在的绝大多数应用都是HTTP/HTTPS协议要实现七层的负载均衡就要使用Ingress对象。

Ingress定义了基于HTTP协议的路由规则但要让规则生效还需要Ingress Controller和Ingress Class来配合工作。

Ingress Controller是真正的集群入口应用Ingress规则调度、分发流量此外还能够扮演反向代理的角色提供安全防护、TLS卸载等更多功能。 Ingress Class是用来管理Ingress和Ingress Controller的概念方便我们分组路由规则降低维护成本。

不过Ingress Controller本身也是一个Pod想要把服务暴露到集群外部还是要依靠Service。Service支持NodePort、LoadBalancer等方式但NodePort的端口范围有限LoadBalancer又依赖于云服务厂商都不是很灵活。

折中的办法是用少量NodePort暴露Ingress Controller用Ingress路由到内部服务外部再用反向代理或者LoadBalancer把流量引进来。

WordPress网站基本架构

简略回顾了Kubernetes里这些API对象下面我们就来使用它们再搭建出WordPress网站实践加深理解。

既然我们已经掌握了Deployment、Service、Ingress这些Pod之上的概念网站自然会有新变化架构图我放在了这里

这次的部署形式比起Docker、minikube又有了一些细微的差别重点是我们已经完全舍弃了Docker把所有的应用都放在Kubernetes集群里运行部署方式也不再是裸Pod而是使用Deployment稳定性大幅度提升。

原来的Nginx的作用是反向代理那么在Kubernetes里它就升级成了具有相同功能的Ingress Controller。WordPress原来只有一个实例现在变成了两个实例你也可以任意横向扩容可用性也就因此提高了不少。而MariaDB数据库因为要保证数据的一致性暂时还是一个实例。

还有因为Kubernetes内置了服务发现机制Service我们再也不需要去手动查看Pod的IP地址了只要为它们定义Service对象然后使用域名就可以访问MariaDB、WordPress这些服务。

网站对外提供服务我选择了两种方式。

一种是让WordPress的Service对象以NodePort的方式直接对外暴露端口30088方便测试另一种是给Nginx Ingress Controller添加“hostNetwork”属性直接使用节点上的端口号类似Docker的host网络模式好处是可以避开NodePort的端口范围限制。

下面我们就按照这个基本架构来逐步搭建出新版本的WordPress网站编写YAML声明。

这里有个小技巧,在实际操作的时候你一定要记得善用 kubectl create、kubectl expose 创建样板文件,节约时间的同时,也能避免低级的格式错误。

WordPress网站部署MariaDB ————————

首先我们还是要部署MariaDB这个步骤和在[第15讲]里做的也差不多。

先要用ConfigMap定义数据库的环境变量有 DATABASE、USER、PASSWORD、ROOT_PASSWORD

apiVersion: v1 kind: ConfigMap metadata: name: maria-cm

data: DATABASE: 'db' USER: 'wp' PASSWORD: '123' ROOT_PASSWORD: '123'

然后我们需要把MariaDB由Pod改成Deployment的方式replicas设置成1个template里面的Pod部分没有任何变化还是要用 envFrom把配置信息以环境变量的形式注入Pod相当于把Pod套了一个Deployment的“外壳”

apiVersion: apps/v1 kind: Deployment metadata: labels: app: maria-dep name: maria-dep

spec: replicas: 1 selector: matchLabels: app: maria-dep

template: metadata: labels: app: maria-dep spec: containers: - image: mariadb:10 name: mariadb ports: - containerPort: 3306

    envFrom:
    - prefix: 'MARIADB_'
      configMapRef:
        name: maria-cm

我们还需要再为MariaDB定义一个Service对象映射端口3306让其他应用不再关心IP地址直接用Service对象的名字来访问数据库服务

apiVersion: v1 kind: Service metadata: labels: app: maria-dep name: maria-svc

spec: ports:

  • port: 3306 protocol: TCP targetPort: 3306 selector: app: maria-dep

因为这三个对象都是数据库相关的所以可以在一个YAML文件里书写对象之间用 --- 分开,这样用 kubectl apply 就可以一次性创建好:

kubectl apply -f wp-maria.yml

执行命令后,你应该用 kubectl get 查看对象是否创建成功,是否正常运行:

WordPress网站部署WordPress ————————–

第二步是部署WordPress应用。

因为刚才创建了MariaDB的Service所以在写ConfigMap配置的时候“HOST”就不应该是IP地址了而应该是DNS域名也就是Service的名字maria-svc这点需要特别注意

apiVersion: v1 kind: ConfigMap metadata: name: wp-cm

data: HOST: 'maria-svc' USER: 'wp' PASSWORD: '123' NAME: 'db'

WordPress的Deployment写法和MariaDB也是一样的给Pod套一个Deployment的“外壳”replicas设置成2个用字段“envFrom”配置环境变量

apiVersion: apps/v1 kind: Deployment metadata: labels: app: wp-dep name: wp-dep

spec: replicas: 2 selector: matchLabels: app: wp-dep

template: metadata: labels: app: wp-dep spec: containers: - image: wordpress:5 name: wordpress ports: - containerPort: 80

    envFrom:
    - prefix: 'WORDPRESS_DB_'
      configMapRef:
        name: wp-cm

然后我们仍然要为WordPress创建Service对象这里我使用了“NodePort”类型并且手工指定了端口号“30088”必须在30000~32767之间

apiVersion: v1 kind: Service metadata: labels: app: wp-dep name: wp-svc

spec: ports:

  • name: http80 port: 80 protocol: TCP targetPort: 80 nodePort: 30088

selector: app: wp-dep type: NodePort

现在让我们用 kubectl apply 部署WordPress

kubectl apply -f wp-dep.yml

这些对象的状态可以从下面的截图看出来:

因为WordPress的Service对象是NodePort类型的我们可以在集群的每个节点上访问WordPress服务。

比如一个节点的IP地址是“192.168.10.210”,那么你就在浏览器的地址栏里输入“http://192.168.10.210:30088”其中的“30088”就是在Service里指定的节点端口号然后就能够看到WordPress的安装界面了

WordPress网站部署Nginx Ingress Controller —————————————–

现在MariaDBWordPress都已经部署成功了第三步就是部署Nginx Ingress Controller。

首先我们需要定义Ingress Class名字就叫“wp-ink”非常简单

apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: wp-ink

spec: controller: nginx.org/ingress-controller

然后用 kubectl create 命令生成Ingress的样板文件指定域名是“wp.test”后端Service是“wp-svc:80”Ingress Class就是刚定义的“wp-ink”

kubectl create ing wp-ing --rule="wp.test/=wp-svc:80" --class=wp-ink $out

得到的Ingress YAML就是这样注意路径类型我还是用的前缀匹配“Prefix”

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: wp-ing

spec: ingressClassName: wp-ink

rules:

  • host: wp.test http: paths:
    • path: / pathType: Prefix backend: service: name: wp-svc port: number: 80

接下来就是最关键的Ingress Controller对象了它仍然需要从Nginx项目的示例YAML修改而来要改动名字、标签还有参数里的Ingress Class。

在之前讲基本架构的时候我说过了这个Ingress Controller不使用Service而是给它的Pod加上一个特殊字段 hostNetwork让Pod能够使用宿主机的网络相当于另一种形式的NodePort

apiVersion: apps/v1 kind: Deployment metadata: name: wp-kic-dep namespace: nginx-ingress

spec: replicas: 1 selector: matchLabels: app: wp-kic-dep

template: metadata: labels: app: wp-kic-dep

spec:
  serviceAccountName: nginx-ingress

  # use host network
  hostNetwork: true

  containers:
  ...

准备好Ingress资源后我们创建这些对象

kubectl apply -f wp-ing.yml -f wp-kic.yml

现在所有的应用都已经部署完毕,可以在集群外面访问网站来验证结果了。

不过你要注意Ingress使用的是HTTP路由规则用IP地址访问是无效的所以在集群外的主机上必须能够识别我们的“wp.test”域名也就是说要把域名“wp.test”解析到Ingress Controller所在的节点上。

如果你用的是Mac那就修改 /etc/hosts如果你用的是Windows就修改 C:\Windows\System32\Drivers\etc\hosts添加一条解析规则就行

cat /etc/hosts 192.168.10.210 wp.test

有了域名解析在浏览器里你就不必使用IP地址直接用域名“wp.test”走Ingress Controller就能访问我们的WordPress网站了

到这里我们在Kubernetes上部署WordPress网站的工作就全部完成了。

小结

这节课我们回顾了“中级篇”里的一些知识要点,我把它们总结成了思维导图,你课后可以对照着它查缺补漏,巩固学习成果。

今天我们还在Kubernetes集群里再次搭建了WordPress网站应用了新对象Deployment、Service、Ingress为网站增加了横向扩容、服务发现和七层负载均衡这三个非常重要的功能提升了网站的稳定性和可用性基本上解决了在“初级篇”所遇到的问题。

虽然这个网站离真正实用还差得比较远但框架已经很完善了你可以在这个基础上添加其他功能比如创建证书Secret、让Ingress支持HTTPS等等。

另外我们保证了网站各项服务的高可用但对于数据库MariaDB来说虽然Deployment在发生故障时能够及时重启Pod新Pod却不会从旧Pod继承数据之前网站的数据会彻底消失这个后果是完全不可接受的。

所以在后续的“高级篇”里我们会继续学习持久化存储对象PersistentVolume以及有状态的StatefulSet等对象进一步完善我们的网站。

课下作业

最后是课下作业时间,还是两个动手操作题:

你能否把WordPress和Ingress Controller改成DaemonSet的部署方式 你能否为Ingress Controller创建Service对象让它以NodePort的方式对外提供服务

欢迎留言分享你的实操体验,如果觉得这篇文章对你有帮助,也欢迎你分享给身边的朋友一起学习。下节课是视频课,我们下节课再见。