当决心要学习一门新的知识时,不要仅仅盯着知识点的价值,而是多想想它能帮我解决什么问题。 我曾经上过一门营销学的课程,课堂上的讲师讲出一个让我很深刻的观点:不要侃侃其谈你产品的卖点,多找别人的买点。 Kubernetes的知识很多,但互联网更广泛。不要一根针把头扎了进去,带着我们想解决的问题去研究获得最适合自己的学习方案。
回归主题,如果在中小型企业或者非互联网型的传统企业,Kubernetes的卖点(分布式微服务架构,高可用高并发,弹性扩容)未必会派上用场,但不代表Kubernetes没有可用武之地。它的服务隔离、可扩展性,再配合上Jenkins的可持续集成 可以让企业内部的IT治理变得有序可管。
简单地说,我的资源有限(有限的机器数),业务的项目无限(每年持 续增长)。Kubernetes的特性可以让有限资源尽可能充分有效地满足无限的业务量,榨干榨尽每一滴。
当从Kubernetes找到以下解决方案后,Kubernetes就可以在企业IT治理中发挥其价值的时候:
- 服务发布
- 健康监控
- 存储持久化
- 快速部署、高可用
- 故障排查
使用Deployment
通常来说,在编写yml 时,Pod与Deployment 成对出现。因为弹性伸缩的需要,Deployment 扮演着Pod 的监管者角色。
#本地终端,进入server节点容器的命令
multipass shell server
#如果看了上一章,并且按照指引创建了Pod:k3s-test,为了避免冲突麻烦,先删除掉旧的Pod吧。
#如果没有请略过。
ubuntu@server:~$ sudo kubectl delete pod k3s-test
#ubuntu@server:~$ sudo vi k3s-test-deployment.yml
#k3s-test-deployment.yml
apiVersion: apps/v1 #这里要注意了,单独创建Pod时是v1,换成Deployment后,这里要改写为apps/v1
kind: Deployment #指定要创建的类型
metadata: #译名为元数据,即 Deployment 的一些基本属性和信息
name: k3s-test-deployment #deployment 的名称
labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组,目前不需要理解
app: k3s-test #app 为key ,k3s-test 为value,还可以定义多个
spec: #这里开始就是Deployment的属性配置了
replicas: 1 #指定Pod的数量
selector: #标签选择器,与上面的标签共同作用,目前不需要理解
matchLabels: #选择包含标签app:k3s-test的资源
app: k3s-test
template: #Pod模板
metadata:
labels: #Pod的标签,上面的selector即选择包含标签app:k3s-test的Pod
app: k3s-test
spec: #期望Pod实现的功能(即在pod中部署)
containers: #容器信息
- name: k3s-test
image: registry.cn-hangzhou.aliyuncs.com/dawson-project/hello-node:latest #还是我们的Node Demo
ports: #这里代表Pod 可输出的端口,7001是我们Node Demo 默认可访问的端口
- containerPort: 7001
我们在server 节点的根目录下已经创建好k3s-test-deployment.yml 文件,继续执行kubectl 的通用引用命令。
ubuntu@server:~$ sudo kubectl apply -f k3s-test-deployment.yml
#输出内容
deployment/k3s-test-deployment created
#通过命令检查是否创建成功
ubuntu@server:~$ sudo kubectl get deployments -o wide
#得到的输出结果
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
k3s-test-deployment 1/1 1 1 82s k3s-test registry.cn-hangzhou.aliyuncs.com/dawson-project/hello-node:latest app=k3s-test
#再通过命令检查Pod
ubuntu@server:~$ sudo kubectl get pods -o wide
#得到的输出结果
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
k3s-test-deployment-6f6b9977d9-2p598 1/1 Running 0 2m56s 10.42.1.50 node1 <none> <none>
执行完上述命令后,我们在输出终端也看到有一个Pod 被创建出来,IP地址为。这个IP地址如Kubernetes(k3s)学习(二) -- 基于最小的pod单元来创建应用所讲,只允许被Kubenetes 内部环境所访问,外网不能正常访问。
#在server 节点访问的结果
ubuntu@server:~$ curl http://10.42.1.50:7001
#输出
Hello K8s!
#在node1节点以及node2访问的结果
ubuntu@node1:~$ curl http://10.42.1.50:7001
#输出
Hello K8s!
#在本机正常环境的访问
#输出
curl http://10.42.1.50:7001
#输出
#没有结果
怎样才能让外界能够访问容器呢?先不急,我们再来看看弹性扩容的。方法很简单,修改k3s-test.deployment.yml的replicas 节点就好,我们把节点数量调节成3,然后再重新运行后,检查输出结果。
#server 环境
#ubuntu@server:~$ sudo vi k3s-test-deployment.yml
#修改replicas 的节点, 把1 改为3,并保存
#执行命令
ubuntu@server:~$ sudo kubectl apply -f k3s-test-deployment.yml
#输出结果
deployment.apps/k3s-test-deployment configured
#再看查看pods
ubuntu@server:~$ sudo kubectl get pods -o wide
#输出结果
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
k3s-test-deployment-5975994799-8rfrv 1/1 Running 0 7m44s 10.42.1.50 node1 <none> <none>
k3s-test-deployment-5975994799-jnd4z 0/1 Running 0 27s 10.42.2.44 server <none> <none>
k3s-test-deployment-5975994799-r7l8t 0/1 Running 0 27s 10.42.0.36 node2 <none> <none>
简单的使用,成功地扩容成三个节点,并且IP为的Pod还保留着。至于缩小节点数,执行步骤是一样的。这里就忽略了。
使用Service
本来是同一套服务,但经过动态扩容后,得到了三个IP地址。这时我们需要有一个统一的负载IP提供统一入口管理,这时候就由Service 发挥作用了。
#server 环境
#ubuntu@server:~$ sudo vi k3s-test-service.yml
apiVersion: v1 #apiVersion 需要回到v1 命名
kind: Service #指定要创建的类型
metadata:
name: k3s-test-service
labels:
app: k3s-test
spec:
selector: #选择器,需要与pod 的命名是一致
app: k3s-test
type: NodePort #先介绍NodePort,后面再介绍ClusterIp
ports:
- name: k3s-test-service-port
protocol: TCP
port: 80
nodePort: 31600
targetPort: 7001
#targetPort: 要映射去Pod 的可访问端口
#port: Kubenetes 内部环境可访问的端口
#nodePort : 外部环境可访问,但Kubenetes内部环境不能访问的端口。
#如果不指定,将由Kubenetes 自动分配端口
执行kubectl 的通用引用命令
ubuntu@server:~$ sudo kubectl apply -f k3s-test-service.yml
#输出内容
service/k3s-test-service created
#通过命令检查是否创建成功
ubuntu@server:~$ sudo kubectl get services -o wide
#得到的输出结果
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 21d <none>
k3s-test-service NodePort 10.43.194.131 <none> 80:31600/TCP 65s app=k3s-test
这里,我们分别在节点server、node1、node2、“终端”环境验证IP:以及端口
和
。
#server 节点,允许直接访问80端口
ubuntu@server:~$ curl http://10.43.194.131
#输出
Hello K8s!
#不允许访问31600端口
ubuntu@server:~$ curl http://10.43.194.131:31600
#没有输出,不允许访问31600端口
#node1 、node2 节点,允许直接访问80端口
ubuntu@node1:~$ curl http://10.43.194.131
#输出
Hello K8s!
ubuntu@node1:~$ curl http://10.43.194.131:31600
#没有输出,不允许访问31600端口
#终端环境
#其中192.168.64.2是server节点的IP地址,
#31600端口对外暴露输出
xxx@xxxx ~ % curl http://192.168.64.2:31600
Hello K8s!
#如何获取192.168.64.2地址请回第一章
#Kubernetes(k3s)学习(一) -- 使用集群部署
#https://www.jianshu.com/p/64c34d69ea39
xxx@xxxx ~ % curl http://192.168.64.2
#输出了404,终端不能直接访问80端口
404 page not found
Service 除了类型外,默认选择是
。其区别在于不能定义对外暴露端口
。
实际项目执行中,我偏向于使用类型,减少Master节点被过多暴露端口。
服务发布
Kubenetes 提供了一种基于 Ingress 的服务发布式,通过配置 Ingress 和外部实现的 Ingress Controller 可以方便的实现服务发布的功能。
k3s 默认集成了基于 Traefix 的 Ingress Controller,所以直接使用即可,不需要手工再安装 Traefix。
新建 k3s-test-ingress.yml 配置规则吧。
#server 环境
#ubuntu@server:~$ sudo vi k3s-test-ingress.yml
apiVersion: networking.k8s.io/v1 #apiVersion 需要回到networking.k8s.io/v1 命名
kind: Ingress #需要创建的类型
metadata:
name: k3s-test-ingress
labels:
name: k3s-test
spec:
rules:
- host: www.k3s-test.com #这里是外界入口可访问的域名配置
http:
paths:
- pathType: Prefix
path: "/" #可配置访问的入口路径
backend:
service:
name: k3s-test-service #选择器,代表访问Service:k3s-test-service
port:
number: 80 #对外暴露的端口
其中 rules[].host 设置了一个域名:www.k3s-test.com,这只是一个测试域名,非本人所有,所以提供给外界访问,但本机环境下,我们可以通过修改 hosts 文件来达到跳过域名解析的目的。下面是具体操作。
#server节点环境执行
ubuntu@server:~$ sudo kubectl apply -f k3s-test-ingress.yml
#输出
#返回到本机的“终端”
# 修改 本机的hosts
xxx@xxx % sudo vi /etc/hosts
# 在该文件中添加一条解析记录
192.168.64.2 www.k3s-test.com
#192.168.64.2 为server节点的IP地址
#如何获取192.168.64.2地址请回第一章
#Kubernetes(k3s)学习(一) -- 使用集群部署
#https://www.jianshu.com/p/64c34d69ea39
我们来进行最后测试吧,本机访问
xxx@xxx % http://www.k3s-test.com
#成功输出结果
Hello K8s!
说明 Ingress 已正常工作。
希望大家通过阅读完此章后以及一些实战例子,能够轻松地掌握Kubernetes的基础。后面我再深入聊Kubenetes 其他的实战特性。