JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

Kubernetes基本概念和操作 kubernetes 概念

wys521 2024-10-06 00:02:50 精选教程 21 ℃ 0 评论

从本节开始给大家介绍下Kubernetes当中的基本概念,比如像Container,Pod,Label,Service都是干什么的,都是什么意思。

先来看下Container,Kubernetes中的Container和Docker中的Container是一个意思,那话说出来,什么是Container呢?Container是运行起来的镜像,死的时候是个镜像,躺着的时候是个尸体,但是我活着我就是个人!就类似于我活着的时候是个Container,死的时候是个镜像。

如图-1所示,Pod是一组密切关联的容器集合,一般来说,你这个业务有时跑个Tomcat,但是你想跑多个实例,跑多个实例一则是保证一个挂了之后还有其他的Tomcat可以提供服务。虽然你可以跑成分布的,但有时候也可以一堆Tomcat跑在一起。或者说是不同功能的,比如说Tomcat和Nginx想跑在一起就叫一个Pod。就是相当于把一堆的Container融到一个Pod里面。这对Pod有什么关系?他们同时共享pid、pic、network和NameSpace。相当于他们是能再CPU和内存上隔离,但是能再很多命名空间上去共享,包括网络、进程通信,很适合于类似于像Nginx和Tomcat这种关系的东西去部署。简单来说就是一个Nginx跑起来叫做Container,一个Nginx加一个tomcat就叫做Pod。基本上Pod的文件系统也是共享的,你可以去读东西。Kubernetes里面很多的东西都是通过Pod共享来操作的。比如后面讲到的configmap都是通过这种东西来实现的。

在Kubernetes中它是通过一种叫做Yaml的文件来组织和部署的,它通过Yaml来描述我这个部署是怎么回事,能达成什么结果的,如果你有固定的镜像,然后你有固定的YAML,他就能保证你在镜像和YAML不变的情况下保证你这个部署无论在世界任何角落哪个Kubernetes集群上都是一样的(当然版本不要差太多),都可以部署出同样的效果。

Kubernetes里面一般对象都是通过Yaml来实现的,虽然说支持json,但是没有人会用json,因为用json写括号会把你恶心死。

apiVersion: v1
 kind: Pod
 metadata:
 name: nginx
 labels:
 app: nginx
 spec:
 containers:
 - name: nginx
 image: nginx
 ports:
 - containerPort: 80

Yaml很简单,Yaml文件里面的内容就是什么东西冒号空格什么东西,什么东西冒号空格什么东西。YAML文件里面的内容也是通过层级来进行划分结构的,比如metadata里面有个name,name叫做Nginx。metadata里面有个Label,Label底下有个app,app叫做Nginx。就类似于层级化的kv(key/value|键值对)结构,树一样的东西。-类似于是个list,Container里面有个list,第一个list的名字叫做Nginx,image叫做Nginx,post下面有分层级,第一个list的Containerpost端口是80。相当于这些东西都是属于这一个list里面的东西,后面还可以在跟一个-(第二个list),同一个层级上可以跟很多平行的list。

Node是Pod真正运行的主机,可以是物理机也可以是虚拟机。为了管理Pod,每个Node节点上至少要运行Container runtime(比如Docker或者rkt)、kubelet和kube-proxy服务如图-2所示。

NameSpace是纯Kubernetes里面的概念,NameSpace类似于像是linux里面不同用户的这种感觉。他从名义上各种逻辑上的东西是隔离的,用户A的环境变量和用户B的环境变量,他俩是不一样的东西。但是它从物理上又没那么隔离,它只是单纯的逻辑上的一种隔离。官方解释说是对一组资源和对象的抽象集合,默认它会有个default的NameSpace。但是你也可以弄成一对自己的NameSpace。比如说你搞什么测试环境,开个线上环境,灰度环境都可以通过NameSpace来实现。

NameSpace有什么用呢?其实NameSpace就是用来隔离环境的。有些公司根本不用NameSpace,全部用默认的default。Kubernetes内部也用一些NameSpace的东西,因为Kubernetes里面他会有一些自己的容器,跟Kubernetes系统相关的容器。它会把自己系统相关的容器就会放到自己的NameSpace里面。一般命名为system之类的。这样做是为了防止和其他的东西冲突,做到有效的隔离,防止误操作。

Pod、Service、controller和deployment都是属于NameSpace里面的,但是如果Kubernetes外部的,比如说宿主机和persistentVolumes(类似于前面讲到的分布式文件系统这种卷)等都不属于NameSpace。它属于和Kubernetes平级的东西,所以说他不可能属于NameSpace。

Service官方叫做应用服务的抽象,一般来说一个Service就相当于就是一个能完整的对外提供服务的一套东西。Service一般来说就会给它分配一个域名。我们运行的时候,一堆Container可能会继承一个Pod,一个Pod会有一个IP,但是这个IP只是一个内部IP,是Kubernetes内部的一个10.开头的内部IP,我们是无法进行访问的。Service这个东西相当于是可以把一堆Pod或者说是一个Pod给他部署,然后暴露出来一个Service,这样一来,这个Service他就会有一个IP,但是这个IP它不保证是固定的,如果发生服务宕机重启之类的这个ServiceIP会发生变化。但是,它会给这个IP分配一个DNS的名字,这个DNS的名字会跟Service名字相关联,这个DNS名字指向哪个IP它会自动的帮你进行调整。所以说,无论你是服务重启还是宿主机宕机等情况的发生,域名一定是固定的,不会产生任何的变化。这是怎么实现的呢?其实是非常简单的,Service的dns就相当于是Kubernetes内部跑了一个dns master,DNS服务器叫做masq,masq是一个古老的常用的非常轻量级的C写的DNS服务器,Kubernetes内部跑了masq这么一个玩意。所以它内部有一套自己的DNS。当然Service也可以不暴露到外部,可以只拿内网进行访问。也可以暴露到外部,如果你暴露到外部就要涉及到后面一个叫做ingress(网关)的东西,当然除了ingress这种暴露方式以外还有Nodeport这种方式,如图-3所示。

apiVersion: v1
kind: service
metadata:
 name: nginx
spec:
 ports:
 - port: 8078 # the port that this Service should serve on
 name: http
 targetPort: 80
 protocol: TCP
selector:
 app: nginx

Label是Kubernetes里面比较常见的一个概念。我们可以把一组资源打个Label(标签),干什么用呢?比如说在Kubernetes集群里分了好多机柜的机器,或者说是不同机房的机器,比如说是亚马逊的可用区之类的。你想区分下这些可用区,比如有些跑在A可用区,有些跑在B可用区。这时候你可以给宿主机打一个Label(标签)。宿主机Label比如叫做机房A和机房B等等。也可以给Container打Label,Container-A属于哪个部门,Container-B属于哪个部门,都是可以通过Label来表示的。这样一来就非常方便的进行管理了。Label后面会有一个Label Selector的一套东西,我们可能会有这样一个需求,我需要保证某些服务只部署到A机房。我们可以在A机房宿主机上打个Label,然后让Label Selector去指定,比如说我选择的时候写一个函数判断,如果是这个Label就进行部署,如果不是这个Label就不进行部署,Label Selector主要是用来实现这样一个功能。

Annotations主要是用来给人看的,可以写在YAML里面,相当于注释一类的东西。

有两个在线的Kubernetes运行网站,一个是play-with-k8s,可以使用4个小时;还有一个网站叫做katacoda playground,可以使用十分钟。在线的好处是不需要我们在服务器上或者本地搭建一套Kubernetes,而前面说到的这两个网站是给我们提供了现成的测试环境。

play-with-k8s网址:https://labs.play-with-k8s.com/。我们可以在这上面运行管理Kubernetes集群的命令,如图-4所示。

在kubernetes集群上启动一个Nginx容器,命令如下所示。该命令的意思是使用的是nginx alpine镜像,名字叫做nginx-app,端口是80端口。

master $ kubectl run --image=nginx:alpine nginx-app --port=80
 deployment.apps/nginx-app created

kubectl get pods可以看到启起来一个nginx的pod,状态处于Running状态,READY1/1表示启动成功,命令如下所示。

master $ kubectl get pods
 NAME READY STATUS RESTARTS AGE
 nginx-app-c9945559d-cbxnb 1/1 Running 0 3m

如果想获取nginx容器的详细信息可以使用describe命令进行查看,如图-5所示。

如果不在默认的default命名空间下需要使用-n选项指定所在的命名空间进行查看,命令如下所示。

master $ kubectl describe pod/nginx-app-c9945559d-cbxnb -n kube-system

查看下刚才启动的nginx容器的IP地址,得知IP地址后可使用curl命令+nginx容器的ip地址查看该容器是否启动成功,如图-6所示。

使用kubectl logs命令可以查看该容器的日志信息,命令如下所示。

master $ kubectl logs nginx-app-c9945559d-cbxnb
 10.40.0.0 - - [17/Jan/2019:11:47:21 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"

使用kubectl exec命令可以进入某个容器,并可以在里面执行一些命令,命令如下所示。

master $ kubectl exec -it nginx-f95d765f9-qpx4l bash

注意:如果你熟知docker的使用和管理,那么你对kubernetes学习和管理起来就会变得非常容器了。比如kubectl exec就类似于docker exec,kubectl logs类似于docker logs,kubectl describe类似于docker inspect,kubectl get类似于docker ps。

前面我们只是run了一个最简单的nginx容器,其实我们还可以通过YAML文件去定义自定义的Pod。比如我们写好了一个YAML文件后,我们可以使用kubectl create命令去创建该Pod,不妨我们现在来测试下。创建一个nginx.yaml文件,在该文件中配置一个nginx pod,创建完毕后创建该Pod,命令如下所示。

	apiVersion: v1
	kind: Pod
	metadata:
	 name: nginx
	 labels:
	 app: nginx
	spec:
	 containers:
	 - name: nginx
	 image: nginx
	 ports:
	 - containerPort: 80

注意:Run并不是直接去创建一个Pod,它不像docker那个run一样直接创建一个容器。这是为什么呢?因为kubernetes他会把叫replication的东西放到一个非常高的地位上,也就是说你创建时候,它认为它创建的是一个服务。告诉它副本数是多少,然后它就会想尽办法在这堆它所能控制的Node里面保证这个副本数是这么多,死了重启,重启不成功就去别的地方给你找。所以说,它的过程就是先创建一个Deployment资源,把它当做上线,而不是启进程。先上线一个Deployment,然后告诉它副本数(replication)是1,这个东西如果发现是0,就会启动一个。它是通过这样的一个过程实现的,前面的YAML很简短的就实现了一个Nginx Pod,其实它等价于如下所示配置。

	apiVersion: extensions/v1beta1
	kind: Deployment
	metadata:
	 labels:
	 run: nginx-app
	 name: nginx-app
	 namespace: default
	spec:
	 replicas: 1
	 selector:
	 matchLabels:
	 run: nginx-app
	 strategy:
	 rollingUpdate:
	 maxSurge: 1
	 maxUnavailable: 1
	 type: RollingUpdate
	 template:
	 metadata:
	 labels:
	 run: nginx-app
	 spec:
	 containers:
	 - image: nginx
	 name: nginx-app
	 ports:
	 - containerPort: 80
	 protocol: TCP
	 dnsPolicy: ClusterFirst
	 restartPolicy: Always

使用volume可以做映射,因为Pod 的生命周期通常比较短,只要出现了异常,就会创建一个新的 Pod 来代替它。那容器产生的数据呢?容器内的数据会随着 Pod 消亡而自动消失。Volume 就是为了持久化容器数据而生,比如可以为 redis 容器指定一个 hostPath 来存储 redis 数据,配置如下所示。

	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/

Kubernetes volume 支持非常多的插件,支持插件如下所示,我们可以根据实际需要来选择。

  • emptyDir
  • hostPath
  • gcePersistentDisk
  • awsElasticBlockStore
  • nfs
  • iscsi
  • flocker
  • glusterfs
  • rbd
  • cephfs
  • gitRepo
  • secret
  • persistentVolumeClaim
  • downwardAPI
  • azureFileVolume
  • vsphereVolume

在云上面玩kubernetes是非常爽的,因为云上面它有天然的做好的卷,比如阿里云和腾讯云,阿里云就非常支持kubernetes。用虚拟机的时候本身也是用卷去挂载,但是现在可以直接把虚拟机扔掉了。跑什么东西,挂载什么卷迁移过去还挂这个卷,卷的名字一直跟这个跑,你会发现宿主机在中间插着根本就没有什么存在的价值。

我们前面虽然创建了一个Pod,但是并没去创建Service,所以说这个Pod的IP会发生变化。但是并不建议使用Pod的IP做交互,所以建议创建一个Service。我们可以把已经创建好的弄成一个Service。可以使用kubectl expose命令进行实现,命令如下所示。

$ kubectl expose deployment nginx-app --port=80 --target-port=80 --type=NodePort
service "nginx-app" exposed
$ kubectl describe service nginx-app

如果想学习更多的kubernetes知识可以参考和借鉴笔者所写的《Linux系统架构与运维实战》一书,书中详细的进行了介绍kubernetes从无到有的全过程。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表