k8s(五)k8s的HelloWorld
作者:lomtom
个人网站:lomtom.cn
个人公众号:博思奥园
你的支持就是我最大的动力。
k8s系列:
使用k8s运行
在K8s部署应用常用方式有以下两种:
- 使用K8s的Yaml文件部署
- 使用helm charts的方式部署
本文将以第一种方式带领大家去完成K8s部署应用的第一个实例。
使用Deployment部署一个Pod
在K8s中,通常是以声明式API来对资源进行控制。这种方式区别于命令式操作,他主要以文件的形式代替了命令的方式。例如Docker、Swarm及大多数软件都是使用的命令式操作。
例如,如果我是用Docker去创建一个nginx,那么我需要拉取镜像,运行容器。
1 | 拉取镜像 |
使用Swarm
去部署一个nginx
。
1 | docker service create --name mynginx --replicas 1 nginx |
而K8s使用声明式API操作,我们只需要将我们需要部署的配置写在一个yaml文件中,然后应用该文件即可,在之后每次的改动、更新等操作,只需要修改该文件即可。
例如,我们需要创建一个nginx服务,那么需要为nginx服务创建一个Deployment
定义文件deploy.yaml
1 | apiVersion: apps/v1 |
然后使用kubectl create
或者 kubectl apply
命令去创建这个Deployment对象。
1 | kubectl create |
稍等片刻,K8s就会创建两个资源:一个Deployment,一个Pod。
1 | [root@master nginx]# kubectl get deploy |
应用被创建出来了,那么这中间到底发生了什么事情呢?
首先,可以看到这个API对象中指定了Kind
为Deployment
,在k8s(三)走进k8s中提及,Deployment
是一个多副本控制器,他会控制副本控制器来完成Pod的创建。
然后,可以查看spec.replicas
参数,其数值为一,那么Deployment
会相应的创建一个副本控制器。我们可以使用kubectl get rs
来进行查看,如果不懂Deployment
与ReplicatSet
的关系也不要紧,后续会着重介绍到。
1 | [root@master nginx]# kubectl get rs |
如果说我们需要两个完全相同的两个副本,并且以负载均衡的方式共同对外提供服务。那么只需要修改yaml文件中副本的数量即可。即:
1 | spec: |
接下来,可以着重关注spc.template
参数,这里定义了一个Pod的模板信息,其中的spc.containers
描述了这个Pod中容器信息,包括容器的镜像、名称、监听的端口号等信息。这里制定了一个名称为nginx
的氢气,镜像指定为nginx:1.7.9
,并且监听80端口。
在这里我们可以很清晰的看到,spc.template
参数描述的就是一个Pod的信息,所以K8s中的一个Pod其实就是K8s中管理与部署的最小单元,并且一个Pod中通常可以有多个容器,你再回过头去看之前(k8s(三)走进k8s)的概念是不是又懂了很多呢。
如果是私有仓库的镜像,或者想要优先从私有仓库拉取的话需要加imagePullPolicy
参数,只从私有仓库拉取就设为Never
,优先从私有仓库拉取设为IfNotPresent
。因为默认是拉去远程的,需要修改配置,在RC定义文件中设置为优先拉取本地或只拉取本地,或者检查该pod所部署的节点有没有进行仓库的授权操作。
1 | imagePullPolicy: IfNotPresent |
使用Service对外暴露服务
单单部署一个应用往往是不够的,一些特殊的应用,往往是需要对外暴露并且能够访问的,那么在K8s中,这又是怎么做到的呢?
如果想要让Pod对外暴露服务,需要定义一个Service,名为svc.yaml
,其内容为:
1 | apiVersion: v1 |
随后,在集群中同样适用kubectl create
或者 kubectl apply
命令去创建这个Service对象。
1 | [root@master service]# kubectl apply -f svc.yaml |
然后,k8s就会创建一个Service并将其与Pod关联起来,接下来,用kubectl命令查看刚刚创建的svc:
1 | [root@master service]# kubectl get svc |
为了验证这个Service服务是否能正常运行,我们可以使用Curl命令访问一下,即CLUSTER-IP + PORT:
1 | [root@master service]# curl http://10.103.11.225 |
可以看出,服务已经正确对外暴露了,但是目前还是只能在集群内部访问,如果需要在集群外也能够访问的话,那么就需要重新修改svc.yaml的内容了,将其类型改为NodePort
,并且设置对外暴露的端口nodePort
,如果不指定nodePort
也没关系,k8s会随机分配一个可用的端口。
1 | apiVersion: v1 |
并且重新更新配置即可:
1 | [root@master service]# kubectl apply -f nginx-svc.yaml |
那么,我们就可以在集群外使用Master IP + NodePort访问了。
那么,Service是怎么与我们建立的Pod的联系起来的呢?
在上述的配置文件中,我们定义了一个类型为Service的API对象,并且通过标签选择器spc.selector
来选择标签为nginx
的Pod实例,而之前使用Deployment创建的Pod中的标签就是nginx
,参数spc.ports.port
指定的端口就是Pod要进行访问的端口。
随后,kube-proxy
会将对这个Service发送的每一个请求都转发到其对应的Pod上。
那么,问题又来了,我们怎么去访问这个Service呢?
其实每一个Service都会生成一个集群内唯一的虚拟IP,即Cluster IP,这个IP只能在集群内能够访问,并且这个IP在Service整个生命周期内都不会发生改变。然后K8s在集群内部做一个Cluster IP与Service (准确来说是ServiceName)的DNS域名映射,即可将该Cluster IP与这个Service一一对应起来。
然后,当Service类型为ClusterIP时,我们仅能够通过Cluster IP + PORT进行服务的访问,因为Cluster IP 仅仅在集群内访问,所以Cluster IP 类型的svc也只能够在集群内进行访问;当Service类型为NodePort时,我们就能Master IP + NodePort进行服务的访问,他会将NodePort的端口的请求转发到Pod的Port端口。这样,我们就能访问我们部署的服务了。
最后,如果我们不需要这些API资源了,同样可以使用kubectl delete
命令进行删除。
1 | [root@master service]# kubectl delete -f svc.yaml |
当然,如果我们想一起创建以上两种资源,可以将其配置文件卸载同一个文件内并且以---
进行分隔即可。
以上体验了一下K8s如何部署应用的,相对于传统的部署方式,是不是方便了很多呢。但是,K8s的强大远远不止这些。
k8s(五)k8s的HelloWorld