k8s快速入门
介绍
容器化部署
随着Docker技术的流行,对项目的容器化部署方式越来越流行,容器化部署的优点如下:
- 可以保证每个容器拥有自己的文件系统、CPU、内存、进程空间等
- 运行应用程序所需要的资源都被容器包装,并和底层基础架构解耦
- 容器化的应用程序可以跨云服务商、跨Linux操作系统发行版进行部署
虽然容器化部署可以带来很多便利,但是也会出现一些问题,比如说:
- 一个容器故障停机了,怎么样让另外一个容器立刻启动去替补停机的容器
- 当并发访问量变大的时候,怎么样做到横向扩展容器数量
这些容器管理的问题统称为容器编排问题,为了解决这些容器编排问题,就产生了一些容器编排技术:
- Swarm:Docker自己的容器编排工具
- Mesos:Apache的一个资源统一管控的工具,需要和Marathon结合使用
- Kubernetes:Google开源的的容器编排工具
目前为止Kubernetes是最为流行的一种容器编排技术。
k8s
kubernetes,由于k和s之间有8个字符,所以简称k8s,是一个全新的基于容器技术的分布式架构领先方案,是谷歌严格保密十几年的秘密武器----Borg系统的一个开源版本,于2015年7月发布第一个正式版本,它的本质是**一组服务器集群**,可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理,主要提供了如下主要功能:
- 自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器
- 弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
- 服务发现:服务可以通过自动发现的形式找到它所依赖的服务
- 负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡
- 版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
- 存储编排:可以根据容器自身的需求自动创建存储卷
组件
一个k8s集群主要是由控制节点(master)、工作节点(node)构成,每个节点上都会安装不同的组件。
master:集群的控制平面,负责集群的决策 ( 管理 )
> ApiServer: 资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制
>
> Scheduler: 负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上
>
> ControllerManager: 负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等
>
> Etcd:负责存储集群中各种资源对象的信息
node:集群的数据平面,负责为容器提供运行环境 ( 干活 )
> Kubelet: 负责维护容器的生命周期,即通过控制docker,来创建、更新、销毁容器
>
> KubeProxy: 负责提供集群内部的服务发现和负载均衡
>
> Docker: 负责节点上容器的各种操作
<imgsrc="assets/image-20200406184656917.png"alt="image-20200406184656917"style="zoom:200%;"/>
下面,以部署一个nginx服务来说明kubernetes系统各个组件调用关系:
1.首先要明确,一旦kubernetes环境启动之后,master和node都会将自身的信息存储到etcd数据库中。
2. 一个nginx服务的安装请求会首先被发送到master节点的apiServer组件。
3. apiServer组件会调用scheduler组件来决定到底应该把这个服务安装到哪个node节点上,
在此时,它会从etcd中读取各个node节点的信息,然后按照一定的算法进行选择,并将结果告知apiServer。
4. apiServer调用controller-manager去调度Node节点安装nginx服务。
5. kubelet接收到指令后,会通知docker,然后由docker来启动一个nginx的pod,
pod是kubernetes的最小操作单元,容器必须跑在pod中至此,
6. 一个nginx服务就运行了,如果需要访问nginx,就需要通过kube-proxy来对pod产生访问的代理。
这样,外界用户就可以访问集群中的nginx服务了
核心概念
Master:集群控制节点,每个集群需要至少一个master节点负责集群的管控
Node:工作负载节点,由master分配容器到这些node工作节点上,然后node节点上的docker负责容器的运行
Pod:kubernetes的最小控制单元,容器都是运行在pod中的,一个pod中可以有1个或者多个容器
Controller:控制器,通过它来实现对pod的管理,比如启动pod、停止pod、伸缩pod的数量等等
Service:pod对外服务的统一入口,下面可以维护者同一类的多个pod
Label:标签,用于对pod进行分类,同一类pod会拥有相同的标签
NameSpace:命名空间,用来隔离pod的运行环境
环境搭建
主机准备
>本次搭建的是一台Master节点和多台Node节点构成的集群
| 作用 | IP地址 | 操作系统 | 配置 |
| ------ | --------------- | --------------------------- | ------------------------ |
| Master | 192.168.109.101 | Centos7.5 基础设施服务器 | 2颗CPU 2G内存 50G硬盘 |
| Node1 | 192.168.109.102 | Centos7.5 基础设施服务器 | 2颗CPU 2G内存 50G硬盘 |
| Node2 | 192.168.109.103 | Centos7.5 基础设施服务器 | 2颗CPU 2G内存 50G硬盘 |
环境初始化
1) 检查操作系统的版本
#此方式下安装kubernetes集群要求Centos版本要在7.5或之上[root@master~]#cat/etc/redhat-releaseCentOSLinuxrelease7.5.1804(Core)
2) 主机名解析
为了方便后面集群节点间的直接调用,在这配置一下主机名解析,企业中推荐使用内部DNS服务器。
#主机名成解析编辑三台服务器的/etc/hosts文件,添加下面内容192.168.109.100master192.168.109.101node1192.168.109.102node2
3) 时间同步
kubernetes要求集群中的节点时间必须精确一致,这里直接使用chronyd服务从网络同步时间。
企业中建议配置内部的时间同步服务器
#启动chronyd服务[root@master~]#systemctlstartchronyd#设置chronyd服务开机自启[root@master~]#systemctlenablechronyd#chronyd服务启动稍等几秒钟,就可以使用date命令验证时间了[root@master~]#date
4) 禁用iptables和firewalld服务
kubernetes和docker在运行中会产生大量的iptables规则,为了不让系统规则跟它们混淆,直接关闭系统的规则
#1关闭firewalld服务[root@master~]#systemctlstopfirewalld[root@master~]#systemctldisablefirewalld#2关闭iptables服务[root@master~]#systemctlstopiptables[root@master~]#systemctldisableiptables
5) 禁用selinux
selinux是linux系统下的一个安全服务,如果不关闭它,在安装集群中会产生各种各样的奇葩问题
#编辑/etc/selinux/config文件,修改SELINUX的值为disabled#注意修改完毕之后需要重启linux服务SELINUX=disabled
6) 禁用swap分区
swap分区指的是虚拟内存分区,它的作用是在物理内存使用完之后,将磁盘空间虚拟成内存来使用
启用swap设备会对系统的性能产生非常负面的影响,因此kubernetes要求每个节点都要禁用swap设备
但是如果因为某些原因确实不能关闭swap分区,就需要在集群安装过程中通过明确的参数进行配置说明
#编辑分区配置文件/etc/fstab,注释掉swap分区一行#注意修改完毕之后需要重启linux服务UUID=455cc753-7a60-4c17-a424-7741728c44a1/bootxfsdefaults00/dev/mapper/centos-home/homexfsdefaults00#/dev/mapper/centos-swapswapswapdefaults00
7)修改linux的内核参数
#修改linux的内核参数,添加网桥过滤和地址转发功能#编辑/etc/sysctl.d/kubernetes.conf文件,添加如下配置:net.bridge.bridge-nf-call-ip6tables=1net.bridge.bridge-nf-call-iptables=1net.ipv4.ip_forward=1#重新加载配置[root@master~]#sysctl-p#加载网桥过滤模块[root@master~]#modprobebr_netfilter#查看网桥过滤模块是否加载成功[root@master~]#lsmod|grepbr_netfilter
8)配置ipvs功能
在kubernetes中service有两种代理模型,一种是基于iptables的,一种是基于ipvs的
两者比较的话,ipvs的性能明显要高一些,但是如果要使用它,需要手动载入ipvs模块
#1安装ipset和ipvsadm[root@master~]#yuminstallipsetipvsadmin-y#2添加需要加载的模块写入脚本文件[root@master~]#cat<<EOF>/etc/sysconfig/modules/ipvs.modules#!/bin/bashmodprobe--ip_vsmodprobe--ip_vs_rrmodprobe--ip_vs_wrrmodprobe--ip_vs_shmodprobe--nf_conntrack_ipv4EOF#3为脚本文件添加执行权限[root@master~]#chmod+x/etc/sysconfig/modules/ipvs.modules#4执行脚本文件[root@master~]#/bin/bash/etc/sysconfig/modules/ipvs.modules#5查看对应的模块是否加载成功[root@master~]#lsmod|grep-eip_vs-enf_conntrack_ipv4
9) 重启服务器
上面步骤完成之后,需要重新启动linux系统
[root@master~]#reboot
安装docker
#1切换镜像源[root@master~]#wgethttps://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo-O/etc/yum.repos.d/docker-ce.repo#2查看当前镜像源中支持的docker版本[root@master~]#yumlistdocker-ce--showduplicates#3安装特定版本的docker-ce#必须指定--setopt=obsoletes=0,否则yum会自动安装更高版本[root@master~]#yuminstall--setopt=obsoletes=0docker-ce-18.06.3.ce-3.el7-y#4添加一个配置文件#Docker在默认情况下使用的CgroupDriver为cgroupfs,而kubernetes推荐使用systemd来代替cgroupfs[root@master~]#mkdir/etc/docker[root@master~]#cat<<EOF>/etc/docker/daemon.json{"exec-opts":["native.cgroupdriver=systemd"],"registry-mirrors":["https://kn0t2bca.mirror.aliyuncs.com"]}EOF#5启动docker[root@master~]#systemctlrestartdocker[root@master~]#systemctlenabledocker#6检查docker状态和版本[root@master~]#dockerversion
安装k8s
#由于kubernetes的镜像源在国外,速度比较慢,这里切换成国内的镜像源#编辑/etc/yum.repos.d/kubernetes.repo,添加下面的配置[kubernetes]name=Kubernetesbaseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64enabled=1gpgcheck=0repo_gpgcheck=0gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpghttp://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg#安装kubeadm、kubelet和kubectl[root@master~]#yuminstall--setopt=obsoletes=0kubeadm-1.17.4-0kubelet-1.17.4-0kubectl-1.17.4-0-y#配置kubelet的cgroup#编辑/etc/sysconfig/kubelet,添加下面的配置KUBELET_CGROUP_ARGS="--cgroup-driver=systemd"KUBE_PROXY_MODE="ipvs"#4设置kubelet开机自启[root@master~]#systemctlenablekubelet
准备集群镜像
#在安装kubernetes集群之前,必须要提前准备好集群需要的镜像,所需镜像可以通过下面命令查看[root@master~]#kubeadmconfigimageslist#下载镜像#此镜像在kubernetes的仓库中,由于网络原因,无法连接,下面提供了一种替代方案images=(kube-apiserver:v1.17.4kube-controller-manager:v1.17.4kube-scheduler:v1.17.4kube-proxy:v1.17.4pause:3.1etcd:3.4.3-0coredns:1.6.5)forimageNamein${images[@]};dodockerpullregistry.cn-hangzhou.aliyuncs.com/google_containers/$imageNamedockertagregistry.cn-hangzhou.aliyuncs.com/google_containers/$imageNamek8s.gcr.io/$imageNamedockerrmiregistry.cn-hangzhou.aliyuncs.com/google_containers/$imageNamedone
集群初始化
下面开始对集群进行初始化,并将node节点加入到集群中
> 下面的操作只需要在`master`节点上执行即可
#创建集群[root@master~]#kubeadminit\--kubernetes-version=v1.17.4\--pod-network-cidr=10.244.0.0/16\--service-cidr=10.96.0.0/12\--apiserver-advertise-address=192.168.109.100#创建必要文件[root@master~]#mkdir-p$HOME/.kube[root@master~]#sudocp-i/etc/kubernetes/admin.conf$HOME/.kube/config[root@master~]#sudochown$(id-u):$(id-g)$HOME/.kube/config
> 下面的操作只需要在`node`节点上执行即可
#将node节点加入集群[root@master~]#kubeadmjoin192.168.109.100:6443\--token8507uc.o0knircuri8etnw2\--discovery-token-ca-cert-hash\sha256:acc37967fb5b0acf39d7598f8a439cc7dc88f439a3f4d0c9cae88e7901b9d3f#查看集群状态此时的集群状态为NotReady,这是因为还没有配置网络插件[root@master~]#kubectlgetnodesNAMESTATUSROLESAGEVERSIONmasterNotReadymaster6m43sv1.17.4node1NotReady<none>22sv1.17.4node2NotReady<none>19sv1.17.4
安装网络插件
kubernetes支持多种网络插件,比如flannel、calico、canal等等,任选一种使用即可,本次选择flannel
> 下面操作依旧只在`master`节点执行即可,插件使用的是DaemonSet的控制器,它会在每个节点上都运行
#获取fannel的配置文件[root@master~]#wgethttps://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml#修改文件中quay.io仓库为quay-mirror.qiniu.com#使用配置文件启动fannel[root@master~]#kubectlapply-fkube-flannel.yml#稍等片刻,再次查看集群节点的状态[root@master~]#kubectlgetnodesNAMESTATUSROLESAGEVERSIONmasterReadymaster15mv1.17.4node1Ready<none>8m53sv1.17.4node2Ready<none>8m50sv1.17.4
至此,kubernetes的集群环境搭建完成
服务部署
接下来在kubernetes集群中部署一个nginx程序,测试下集群是否在正常工作。
#部署nginx[root@master~]#kubectlcreatedeploymentnginx--image=nginx:1.14-alpine#暴露端口[root@master~]#kubectlexposedeploymentnginx--port=80--type=NodePort#查看服务状态[root@master~]#kubectlgetpods,serviceNAMEREADYSTATUSRESTARTSAGEpod/nginx-86c57db685-fdc2k1/1Running018mNAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGEservice/kubernetesClusterIP10.96.0.1<none>443/TCP82mservice/nginxNodePort10.104.121.45<none>80:30073/TCP17m#4最后在电脑上访问下部署的nginx服务~~~<imgsrc="assets/image-20200405142656921.png"alt="image-20200405142656921"style="zoom:80%;border:1pxsolid"/>
资源管理
在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理kubernetes。
kubernetes的本质上就是一个集群系统,用户可以在集群中部署各种服务,也就是在kubernetes集群中运行一个个的容器,并将指定的程序跑在容器中。
kubernetes的最小管理单元是pod而不是容器,所以只能将容器放在`Pod`中,而kubernetes一般也不会直接管理Pod,而是通过`Pod控制器`来管理Pod的。
Pod可以提供服务之后,就要考虑如何访问Pod中服务,kubernetes提供了`Service`资源实现这个功能。
>k8s提供了三种资源管理方式
- 命令式对象管理:直接使用命令去操作kubernetes资源
`kubectl run nginx-pod --image=nginx:1.17.1 --port=80`
- 命令式对象配置:通过命令配置和配置文件去操作kubernetes资源
`kubectl create/patch -f nginx-pod.yaml`
- 声明式对象配置:通过apply命令和配置文件去操作kubernetes资源
`kubectl apply -f nginx-pod.yaml`
命令式对象管理
kubectl命令
kubectl是kubernetes集群的命令行工具,通过它能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。kubectl命令的语法如下:
~~~md
kubectl [command] [type] [name] [flags]
~~~
comand:指定要对资源执行的操作,例如create、get、delete
type:指定资源类型,比如deployment、pod、service
name:指定资源的名称,名称大小写敏感
flags:指定额外的可选参数
#查看所有podkubectlgetpod#查看某个podkubectlgetpodpod_name#查看某个pod,以yaml格式展示结果kubectlgetpodpod_name-oyaml
下面以一个namespace / pod的创建和删除简单演示下命令的使用:
#创建一个namespace[root@master~]#kubectlcreatenamespacedevnamespace/devcreated#获取namespace[root@master~]#kubectlgetnsNAMESTATUSAGEdefaultActive21hdevActive21skube-node-leaseActive21hkube-publicActive21hkube-systemActive21h#在此namespace下创建并运行一个nginx的Pod[root@master~]#kubectlrunpod--image=nginx-ndevkubectlrun--generator=deployment/apps.v1isDEPRECATEDandwillberemovedinafutureversion.Usekubectlrun--generator=run-pod/v1orkubectlcreateinstead.deployment.apps/podcreated#查看新创建的pod[root@master~]#kubectlgetpod-ndevNAMEREADYSTATUSRESTARTSAGEpod-864f9875b9-pcw7x1/1Running021s#删除指定的pod[root@master~]#kubectldeletepodpod-864f9875b9-pcw7xpod"pod-864f9875b9-pcw7x"deleted#删除指定的namespace[root@master~]#kubectldeletensdevnamespace"dev"deleted
命令式对象配置
命令式对象配置就是使用命令配合配置文件一起来操作kubernetes资源。
1) 创建一个nginxpod.yaml,内容如下:
apiVersion:v1kind:Namespacemetadata:name:dev---apiVersion:v1kind:Podmetadata:name:nginxpodnamespace:devspec:containers:-name:nginx-containersimage:nginx:1.17.1
2)执行create命令,创建资源:
[root@master~]#kubectlcreate-fnginxpod.yamlnamespace/devcreatedpod/nginxpodcreated
此时发现创建了两个资源对象,分别是namespace和pod
3)执行get命令,查看资源:
[root@master~]#kubectlget-fnginxpod.yamlNAMESTATUSAGEnamespace/devActive18sNAMEREADYSTATUSRESTARTSAGEpod/nginxpod1/1Running017s
这样就显示了两个资源对象的信息
4)执行delete命令,删除资源:
[root@master~]#kubectldelete-fnginxpod.yamlnamespace"dev"deletedpod"nginxpod"deleted~~~此时发现两个资源对象被删除了
此时发现两个资源对象被删除了
~~~md
总结:
命令式对象配置的方式操作资源,可以简单的认为:命令 + yaml配置文件(里面是命令需要的各种参数)
~~~
声明式对象配置
声明式对象配置跟命令式对象配置很相似,但是它只有一个命令apply。
#首先执行一次kubectlapply-fyaml文件,发现创建了资源[root@master~]#kubectlapply-fnginxpod.yamlnamespace/devcreatedpod/nginxpodcreated#再次执行一次kubectlapply-fyaml文件,发现说资源没有变动[root@master~]#kubectlapply-fnginxpod.yamlnamespace/devunchangedpod/nginxpodunchanged
实战
> 本章节将介绍如何在kubernetes集群中部署一个nginx服务,并且能够对其进行访问。
Namespace
Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。
默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的"组",以方便不同的组的资源进行隔离使用和管理。
可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。
kubernetes在集群启动之后,会默认创建几个namespace
[root@master~]#kubectlgetnamespaceNAMESTATUSAGEdefaultActive45h#所有未指定Namespace的对象都会被分配在default命名空间kube-node-leaseActive45h#集群节点之间的心跳维护,v1.13开始引入kube-publicActive45h#此命名空间下的资源可以被所有人访问(包括未认证用户)kube-systemActive45h#所有由Kubernetes系统创建的资源都处于这个命名空间
下面来看namespace资源的具体操作:
查看
#1查看所有的ns命令:kubectlgetns[root@master~]#kubectlgetnsNAMESTATUSAGEdefaultActive45hkube-node-leaseActive45hkube-publicActive45hkube-systemActive45h#2查看指定的ns命令:kubectlgetnsns名称[root@master~]#kubectlgetnsdefaultNAMESTATUSAGEdefaultActive45h#3指定输出格式命令:kubectlgetnsns名称-o格式参数#kubernetes支持的格式有很多,比较常见的是wide、json、yaml[root@master~]#kubectlgetnsdefault-oyamlapiVersion:v1kind:Namespacemetadata:creationTimestamp:"2020-04-05T04:44:16Z"name:defaultresourceVersion:"151"selfLink:/api/v1/namespaces/defaultuid:7405f73a-e486-43d4-9db6-145f1409f090spec:finalizers:-kubernetesstatus:phase:Active#4查看ns详情命令:kubectldescribensns名称[root@master~]#kubectldescribensdefaultName:defaultLabels:<none>Annotations:<none>Status:Active#Active命名空间正在使用中Terminating正在删除命名空间#ResourceQuota针对namespace做的资源限制#LimitRange针对namespace中的每个组件做的资源限制Noresourcequota.NoLimitRangeresource.
创建
[root@master~]#kubectlcreatensdevnamespace/devcreated
删除
[root@master~]#kubectldeletensdevnamespace"dev"deleted
配置方式
首先准备一个yaml文件:ns-dev.yaml
apiVersion:v1kind:Namespacemetadata:name:dev
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f ns-dev.yaml
删除:kubectl delete -f ns-dev.yaml
Pod
Pod是kubernetes集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于Pod中。
Pod可以认为是容器的封装,一个Pod中可以存在一个或者多个容器。
<imgsrc="assets/image-20200407121501907.png"alt="image-20200407121501907"style="zoom:80%;"/>
kubernetes在集群启动之后,集群中的各个组件也都是以Pod方式运行的。可以通过下面命令查看:
[root@master~]#kubectlgetpod-nkube-systemNAMESPACENAMEREADYSTATUSRESTARTSAGEkube-systemcoredns-6955765f44-68g6v1/1Running02d1hkube-systemcoredns-6955765f44-cs5r81/1Running02d1hkube-systemetcd-master1/1Running02d1hkube-systemkube-apiserver-master1/1Running02d1hkube-systemkube-controller-manager-master1/1Running02d1hkube-systemkube-flannel-ds-amd64-47r251/1Running02d1hkube-systemkube-flannel-ds-amd64-ls5lh1/1Running02d1hkube-systemkube-proxy-685tk1/1Running02d1hkube-systemkube-proxy-87spt1/1Running02d1hkube-systemkube-scheduler-master1/1Running02d1h
创建并运行
kubernetes没有提供单独运行Pod的命令,都是通过Pod控制器来实现的
#命令格式:kubectlrun(pod控制器名称)[参数]#--image指定Pod的镜像#--port指定端口#--namespace指定namespace[root@master~]#kubectlrunnginx--image=nginx:1.17.1--port=80--namespacedevdeployment.apps/nginxcreated
查看pod信息
#查看Pod基本信息[root@master~]#kubectlgetpods-ndevNAMEREADYSTATUSRESTARTSAGEnginx-5ff7956ff6-fg2db1/1Running043s#查看Pod的详细信息[root@master~]#kubectldescribepodnginx-5ff7956ff6-fg2db-ndevName:nginx-5ff7956ff6-fg2dbNamespace:devPriority:0Node:node1/192.168.109.101StartTime:Wed,08Apr202009:29:24+0800Labels:pod-template-hash=5ff7956ff6run=nginxAnnotations:<none>Status:RunningIP:10.244.1.23IPs:IP:10.244.1.23ControlledBy:ReplicaSet/nginx-5ff7956ff6Containers:nginx:ContainerID:docker://4c62b8c0648d2512380f4ffa5da2c99d16e05634979973449c98e9b829f6253cImage:nginx:1.17.1ImageID:docker-pullable://nginx@sha256:485b610fefec7ff6c463ced9623314a04ed67e3945b9c08d7e53a47f6d108dc7Port:80/TCPHostPort:0/TCPState:RunningStarted:Wed,08Apr202009:30:01+0800Ready:TrueRestartCount:0Environment:<none>Mounts:/var/run/secrets/kubernetes.io/serviceaccountfromdefault-token-hwvvw(ro)Conditions:TypeStatusInitializedTrueReadyTrueContainersReadyTruePodScheduledTrueVolumes:default-token-hwvvw:Type:Secret(avolumepopulatedbyaSecret)SecretName:default-token-hwvvwOptional:falseQoSClass:BestEffortNode-Selectors:<none>Tolerations:node.kubernetes.io/not-ready:NoExecutefor300snode.kubernetes.io/unreachable:NoExecutefor300sEvents:TypeReasonAgeFromMessage-------------------------NormalScheduled<unknown>default-schedulerSuccessfullyassigneddev/nginx-5ff7956ff6-fg2dbtonode1NormalPulling4m11skubelet,node1Pullingimage"nginx:1.17.1"NormalPulled3m36skubelet,node1Successfullypulledimage"nginx:1.17.1"NormalCreated3m36skubelet,node1CreatedcontainernginxNormalStarted3m36skubelet,node1Startedcontainernginx
访问Pod
#获取podIP[root@master~]#kubectlgetpods-ndev-owideNAMEREADYSTATUSRESTARTSAGEIPNODE...nginx-5ff7956ff6-fg2db1/1Running0190s10.244.1.23node1...#访问POD[root@master~]#curlhttp://10.244.1.23:80<!DOCTYPEhtml><html><head><title>Welcometonginx!</title></head><body><p><em>Thankyouforusingnginx.</em></p></body></html>
删除指定Pod
#删除指定Pod[root@master~]#kubectldeletepodnginx-5ff7956ff6-fg2db-ndevpod"nginx-5ff7956ff6-fg2db"deleted#此时,显示删除Pod成功,但是再查询,发现又新产生了一个[root@master~]#kubectlgetpods-ndevNAMEREADYSTATUSRESTARTSAGEnginx-5ff7956ff6-jj4ng1/1Running021s#这是因为当前Pod是由Pod控制器创建的,控制器会监控Pod状况,一旦发现Pod死亡,会立即重建#此时要想删除Pod,必须删除Pod控制器#先来查询一下当前namespace下的Pod控制器[root@master~]#kubectlgetdeploy-ndevNAMEREADYUP-TO-DATEAVAILABLEAGEnginx1/1119m7s#接下来,删除此PodPod控制器[root@master~]#kubectldeletedeploynginx-ndevdeployment.apps"nginx"deleted#稍等片刻,再查询Pod,发现Pod被删除了[root@master~]#kubectlgetpods-ndevNoresourcesfoundindevnamespace.
配置操作
创建一个pod-nginx.yaml,内容如下:
apiVersion:v1kind:Podmetadata:name:nginxnamespace:devspec:containers:-image:nginx:1.17.1name:podports:-name:nginx-portcontainerPort:80protocol:TCP
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f pod-nginx.yaml
删除:kubectl delete -f pod-nginx.yaml
Label
Label是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对它们进行区分和选择。
Label的特点:
- 一个Label会以key/value键值对的形式附加到各种对象上,如Node、Pod、Service等等
- 一个资源对象可以定义任意数量的Label ,同一个Label也可以被添加到任意数量的资源对象上去
- Label通常在资源对象定义时确定,当然也可以在对象创建后动态添加或者删除
可以通过Label实现资源的多维度分组,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。
> 一些常用的Label 示例如下:
>
> - 版本标签:"version":"release", "version":"stable"......
> - 环境标签:"environment":"dev","environment":"test","environment":"pro"
> - 架构标签:"tier":"frontend","tier":"backend"
标签定义完毕之后,还要考虑到标签的选择,这就要使用到Label Selector,即:
Label用于给某个资源对象定义标识
Label Selector用于查询和筛选拥有某些标签的资源对象
当前有两种Label Selector:
- 基于等式的Label Selector
name = slave: 选择所有包含Label中key="name"且value="slave"的对象
env != production: 选择所有包括Label中的key="env"且value不等于"production"的对象
- 基于集合的Label Selector
name in (master, slave): 选择所有包含Label中的key="name"且value="master"或"slave"的对象
name not in (frontend): 选择所有包含Label中的key="name"且value不等于"frontend"的对象
标签的选择条件可以使用多个,此时将多个Label Selector进行组合,使用逗号","进行分隔即可。例如:
name=slave,env!=production
name not in (frontend),env!=production
命令方式
#为pod资源打标签[root@master~]#kubectllabelpodnginx-podversion=1.0-ndevpod/nginx-podlabeled#为pod资源更新标签[root@master~]#kubectllabelpodnginx-podversion=2.0-ndev--overwritepod/nginx-podlabeled#查看标签[root@master~]#kubectlgetpodnginx-pod-ndev--show-labelsNAMEREADYSTATUSRESTARTSAGELABELSnginx-pod1/1Running010mversion=2.0#筛选标签[root@master~]#kubectlgetpod-ndev-lversion=2.0--show-labelsNAMEREADYSTATUSRESTARTSAGELABELSnginx-pod1/1Running017mversion=2.0[root@master~]#kubectlgetpod-ndev-lversion!=2.0--show-labelsNoresourcesfoundindevnamespace.#删除标签[root@master~]#kubectllabelpodnginx-podversion--ndevpod/nginx-podlabeled
配置方式
apiVersion:v1kind:Podmetadata:name:nginxnamespace:devlabels:version:"3.0"env:"test"spec:containers:-image:nginx:1.17.1name:podports:-name:nginx-portcontainerPort:80protocol:TCP
然后就可以执行对应的更新命令了:kubectl apply -f pod-nginx.yaml
Deployment
在kubernetes中,Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于pod的管理,确保pod资源符合预期的状态,当pod的资源出现故障时,会尝试进行重启或重建pod。
在kubernetes中Pod控制器的种类有很多,本章节只介绍一种:Deployment。
<imgsrc="assets/image-20200408193950807.png"alt="image-20200408193950807"style="border:1pxsolid;zoom:80%;"/>
命令操作
#命令格式:kubectlrundeployment名称[参数]#--image指定pod的镜像#--port指定端口#--replicas指定创建pod数量#--namespace指定namespace[root@master~]#kubectlrunnginx--image=nginx:1.17.1--port=80--replicas=3-ndevdeployment.apps/nginxcreated#查看创建的Pod[root@master~]#kubectlgetpods-ndevNAMEREADYSTATUSRESTARTSAGEnginx-5ff7956ff6-6k8cb1/1Running019snginx-5ff7956ff6-jxfjt1/1Running019snginx-5ff7956ff6-v6jqw1/1Running019s#查看deployment的信息[root@master~]#kubectlgetdeploy-ndevNAMEREADYUP-TO-DATEAVAILABLEAGEnginx3/3332m42s#UP-TO-DATE:成功升级的副本数量#AVAILABLE:可用副本的数量[root@master~]#kubectlgetdeploy-ndev-owideNAMEREADYUP-TO-DATEAVAILABLEAGECONTAINERSIMAGESSELECTORnginx3/3332m51snginxnginx:1.17.1run=nginx#查看deployment的详细信息[root@master~]#kubectldescribedeploynginx-ndevName:nginxNamespace:devCreationTimestamp:Wed,08Apr202011:14:14+0800Labels:run=nginxAnnotations:deployment.kubernetes.io/revision:1Selector:run=nginxReplicas:3desired|3updated|3total|3available|0unavailableStrategyType:RollingUpdateMinReadySeconds:0RollingUpdateStrategy:25%maxunavailable,25%maxsurgePodTemplate:Labels:run=nginxContainers:nginx:Image:nginx:1.17.1Port:80/TCPHostPort:0/TCPEnvironment:<none>Mounts:<none>Volumes:<none>Conditions:TypeStatusReason----------------AvailableTrueMinimumReplicasAvailableProgressingTrueNewReplicaSetAvailableOldReplicaSets:<none>NewReplicaSet:nginx-5ff7956ff6(3/3replicascreated)Events:TypeReasonAgeFromMessage-------------------------NormalScalingReplicaSet5m43sdeployment-controllerScaledupreplicasetnginx-5ff7956ff6to3#删除[root@master~]#kubectldeletedeploynginx-ndevdeployment.apps"nginx"deleted
配置操作
创建一个deploy-nginx.yaml,内容如下:
apiVersion:apps/v1kind:Deploymentmetadata:name:nginxnamespace:devspec:replicas:3selector:matchLabels:run:nginxtemplate:metadata:labels:run:nginxspec:containers:-image:nginx:1.17.1name:nginxports:-containerPort:80protocol:TCP
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f deploy-nginx.yaml
删除:kubectl delete -f deploy-nginx.yaml
Service
通过上节课的学习,已经能够利用Deployment来创建一组Pod来提供具有高可用性的服务。
虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题:
- Pod IP 会随着Pod的重建产生变化
- Pod IP 仅仅是集群内可见的虚拟IP,外部无法访问
这样对于访问这个服务带来了难度。因此,kubernetes设计了Service来解决这个问题。
Service可以看作是一组同类Pod**对外的访问接口**。借助Service,应用可以方便地实现服务发现和负载均衡。
操作一:创建集群内部可访问的Service
#暴露Service[root@master~]#kubectlexposedeploynginx--name=svc-nginx1--type=ClusterIP--port=80--target-port=80-ndevservice/svc-nginx1exposed#查看service[root@master~]#kubectlgetsvcsvc-nginx-ndev-owideNAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGESELECTORsvc-nginx1ClusterIP10.109.179.231<none>80/TCP3m51srun=nginx#这里产生了一个CLUSTER-IP,这就是service的IP,在Service的生命周期中,这个地址是不会变动的#可以通过这个IP访问当前service对应的POD[root@master~]#curl10.109.179.231:80<!DOCTYPEhtml><html><head><title>Welcometonginx!</title></head><body><h1>Welcometonginx!</h1>.......</body></html>
操作二:创建集群外部也可访问的Service
#上面创建的Service的type类型为ClusterIP,这个ip地址只用集群内部可访问#如果需要创建外部也可以访问的Service,需要修改type为NodePort[root@master~]#kubectlexposedeploynginx--name=svc-nginx2--type=NodePort--port=80--target-port=80-ndevservice/svc-nginx2exposed#此时查看,会发现出现了NodePort类型的Service,而且有一对Port(80:31928/TC)[root@master~]#kubectlgetsvcsvc-nginx-1-ndev-owideNAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGESELECTORsvc-nginx2NodePort10.100.94.0<none>80:31928/TCP9srun=nginx#接下来就可以通过集群外的主机访问节点IP:31928访问服务了#例如在的电脑主机上通过浏览器访问下面的地址http://192.168.109.100:31928/
删除Service
[root@master~]#kubectldeletesvcsvc-nginx-1-ndev
配置方式
创建一个svc-nginx.yaml,内容如下:
apiVersion:v1kind:Servicemetadata:name:svc-nginxnamespace:devspec:clusterIP:10.109.179.231ports:-port:80protocol:TCPtargetPort:80selector:run:nginxtype:ClusterIP
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f svc-nginx.yaml
删除:kubectl delete -f svc-nginx.yaml
> 小结
>
> 至此,已经掌握了Namespace、Pod、Deployment、Service资源的基本操作,有了这些操作,就可以在kubernetes集群中实现一个服务的简单部署和访问了,但是如果想要更好的使用kubernetes,就需要深入学习这几种资源的细节和原理。
版权声明
本文仅代表作者观点,不代表博信信息网立场。