赞
踩
在部署应用程序的方式上,主要经历了三个时代:
传统部署:互联网早期,会直接将应用程序部署在物理机上 优点:简单,不需要其它技术的参与 缺点:不能为应用程序定义资源使用边界,很难合理地分配计算资源,而且程序之间容易产生影响
虚拟化部署:可以在一台物理机上运行多个虚拟机,每个虚拟机都是独立的一个环境 优点:程序环境不会相互产生影响,提供了一定程度的安全性 缺点:增加了操作系统,浪费了部分资源
容器化部署:与虚拟化类似,但是共享了操作系统 优点: 可以保证每个容器拥有自己的文件系统、CPU、内存、进程空间等 运行应用程序所需要的资源都被容器包装,并和底层基础架构解耦 容器化的应用程序可以跨云服务商、跨Linux操作系统发行版进行部署
容器化部署方式给带来很多的便利,但是也会出现一些问题,比如说:
这些容器管理的问题统称为容器编排问题,为了解决这些容器编排问题,就产生了一些容器编排的软件:
kubernetes,是一个全新的基于容器技术的分布式架构领先方案,是谷歌严格保密十几年的秘密武器---Borg系统的一个开源版本,于2014年9月发布第一个版本,2015年7月发布第一个正式版本。
kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。目的是实现资源管理的自动化,主要提供了如下的主要功能:
一个kubernetes集群主要是由控制节点(master)、**工作节点(node)**构成,每个节点上都会安装不同的组件。
master:集群的控制平面,负责集群的决策 ( 管理 )
- ApiServer : 资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制
- Scheduler : 负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上
- ControllerManager : 负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等
- Etcd :负责存储集群中各种资源对象的信息
node:集群的数据平面,负责为容器提供运行环境 ( 干活 )
- Kubelet : 负责维护容器的生命周期,即通过控制docker,来创建、更新、销毁容器
- KubeProxy : 负责提供集群内部的服务发现和负载均衡
- Docker : 负责节点上容器的各种操作
下面,以部署一个nginx服务来说明kubernetes系统各个组件调用关系:
这样,外界用户就可以访问集群中的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的运行环境
目前生产部署Kubernetes 集群主要有两种方式:
kubeadm
Kubeadm 是一个K8s 部署工具,提供kubeadm init 和kubeadm join,用于快速部署Kubernetes 集群。
官方地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/
二进制包
从github 下载发行版的二进制包,手动部署每个组件,组成Kubernetes 集群。
Kubeadm 降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。如果想更容易可控,推荐使用二进制包部署Kubernetes 集群,虽然手动部署麻烦点,期间可以学习很多工作原理,也利于后期维护。
kubeadm 是官方社区推出的一个用于快速部署kubernetes 集群的工具,这个工具能通过两条指令完成一个kubernetes 集群的部署:
角色 | IP地址 | 组件 |
master01 | 192.168.5.3 | docker,kubectl,kubeadm,kubelet |
node01 | 192.168.5.4 | docker,kubectl,kubeadm,kubelet |
node02 | 192.168.5.5 | docker,kubectl,kubeadm,kubelet |
- # 此方式下安装kubernetes集群要求Centos版本要在7.5或之上
- [root@master ~]# cat /etc/redhat-release
- Centos Linux 7.5.1804 (Core)
为了方便集群节点间的直接调用,在这个配置一下主机名解析,企业中推荐使用内部DNS服务器
- # 主机名成解析 编辑三台服务器的/etc/hosts文件,添加下面内容
- 192.168.90.100 master
- 192.168.90.106 node1
- 192.168.90.107 node2
企业中建议配置内部的会见同步服务器
- # 启动chronyd服务
- [root@master ~]# systemctl start chronyd
- [root@master ~]# systemctl enable chronyd
- [root@master ~]# date
kubernetes和docker 在运行的中会产生大量的iptables规则,为了不让系统规则跟它们混淆,直接关闭系统的规则
- # 1 关闭firewalld服务
- [root@master ~]# systemctl stop firewalld
- [root@master ~]# systemctl disable firewalld
- # 2 关闭iptables服务
- [root@master ~]# systemctl stop iptables
- [root@master ~]# systemctl disable iptables
selinux是linux系统下的一个安全服务,如果不关闭它,在安装集群中会产生各种各样的奇葩问题
- # 编辑 /etc/selinux/config 文件,修改SELINUX的值为disable
- # 注意修改完毕之后需要重启linux服务
- SELINUX=disabled
swap分区指的是虚拟内存分区,它的作用是物理内存使用完,之后将磁盘空间虚拟成内存来使用,启用swap设备会对系统的性能产生非常负面的影响,因此kubernetes要求每个节点都要禁用swap设备,但是如果因为某些原因确实不能关闭swap分区,就需要在集群安装过程中通过明确的参数进行配置说明
- # 编辑分区配置文件/etc/fstab,注释掉swap分区一行
- # 注意修改完毕之后需要重启linux服务
- vim /etc/fstab
- 注释掉 /dev/mapper/centos-swap swap
- # /dev/mapper/centos-swap swap
- # 修改linux的内核采纳数,添加网桥过滤和地址转发功能
- # 编辑/etc/sysctl.d/kubernetes.conf文件,添加如下配置:
- net.bridge.bridge-nf-call-ip6tables = 1
- net.bridge.bridge-nf-call-iptables = 1
- net.ipv4.ip_forward = 1
-
- # 重新加载配置
- [root@master ~]# sysctl -p
- # 加载网桥过滤模块
- [root@master ~]# modprobe br_netfilter
- # 查看网桥过滤模块是否加载成功
- [root@master ~]# lsmod | grep br_netfilter
在Kubernetes中Service有两种带来模型,一种是基于iptables的,一种是基于ipvs的两者比较的话,ipvs的性能明显要高一些,但是如果要使用它,需要手动载入ipvs模块
- # 1.安装ipset和ipvsadm
- [root@master ~]# yum install ipset ipvsadm -y
- # 2.添加需要加载的模块写入脚本文件
- [root@master ~]# cat <<EOF> /etc/sysconfig/modules/ipvs.modules
- #!/bin/bash
- modprobe -- ip_vs
- modprobe -- ip_vs_rr
- modprobe -- ip_vs_wrr
- modprobe -- ip_vs_sh
- modprobe -- nf_conntrack_ipv4
- EOF
- # 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 -e ip_vs -e nf_conntrack_ipv4
- # 1、切换镜像源
- [root@master ~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
-
- # 2、查看当前镜像源中支持的docker版本
- [root@master ~]# yum list docker-ce --showduplicates
-
- # 3、安装特定版本的docker-ce
- # 必须制定--setopt=obsoletes=0,否则yum会自动安装更高版本
- [root@master ~]# yum install --setopt=obsoletes=0 docker-ce-18.06.3.ce-3.el7 -y
-
- # 4、添加一个配置文件
- #Docker 在默认情况下使用Vgroup Driver为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、启动dokcer
- [root@master ~]# systemctl restart docker
- [root@master ~]# systemctl enable docker
- # 1、由于kubernetes的镜像在国外,速度比较慢,这里切换成国内的镜像源
- # 2、编辑/etc/yum.repos.d/kubernetes.repo,添加下面的配置
- [kubernetes]
- name=Kubernetes
- baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
- enabled=1
- gpgchech=0
- repo_gpgcheck=0
- gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
- http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
-
- # 3、安装kubeadm、kubelet和kubectl
- [root@master ~]# yum install --setopt=obsoletes=0 kubeadm-1.17.4-0 kubelet-1.17.4-0 kubectl-1.17.4-0 -y
-
- # 4、配置kubelet的cgroup
- #编辑/etc/sysconfig/kubelet, 添加下面的配置
- KUBELET_CGROUP_ARGS="--cgroup-driver=systemd"
- KUBE_PROXY_MODE="ipvs"
-
- # 5、设置kubelet开机自启
- [root@master ~]# systemctl enable kubelet
- # 在安装kubernetes集群之前,必须要提前准备好集群需要的镜像,所需镜像可以通过下面命令查看
- [root@master ~]# kubeadm config images list
-
- # 下载镜像
- # 此镜像kubernetes的仓库中,由于网络原因,无法连接,下面提供了一种替换方案
- images=(
- kube-apiserver:v1.17.4
- kube-controller-manager:v1.17.4
- kube-scheduler:v1.17.4
- kube-proxy:v1.17.4
- pause:3.1
- etcd:3.4.3-0
- coredns:1.6.5
- )
-
- for imageName in ${images[@]};do
- docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
- docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
- docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
- done
下面的操作只需要在master节点上执行即可
- # 创建集群
- [root@master ~]# kubeadm init \
- --apiserver-advertise-address=192.168.90.100 \
- --image-repository registry.aliyuncs.com/google_containers \
- --kubernetes-version=v1.17.4 \
- --service-cidr=10.96.0.0/12 \
- --pod-network-cidr=10.244.0.0/16
- # 创建必要文件
- [root@master ~]# mkdir -p $HOME/.kube
- [root@master ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
- [root@master ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config
下面的操作只需要在node节点上执行即可
- kubeadm join 192.168.0.100:6443 --token awk15p.t6bamck54w69u4s8 \
- --discovery-token-ca-cert-hash sha256:a94fa09562466d32d29523ab6cff122186f1127599fa4dcd5fa0152694f17117
在master上查看节点信息
- [root@master ~]# kubectl get nodes
- NAME STATUS ROLES AGE VERSION
- master NotReady master 6m v1.17.4
- node1 NotReady <none> 22s v1.17.4
- node2 NotReady <none> 19s v1.17.4
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
由于外网不好访问,如果出现无法访问的情况,可以直接用下面的 记得文件名是kube-flannel.yml,位置:/root/kube-flannel.yml内容:
https://github.com/flannel-io/flannel/tree/master/Documentation/kube-flannel.yml
也可手动拉取指定版本
- docker pull quay.io/coreos/flannel:v0.14.0 #拉取flannel网络,三台主机
- docker images #查看仓库是否拉去下来
若是集群状态一直是 notready,用下面语句查看原因,
journalctl -f -u kubelet.service
若原因是:
cni.go:237] Unable to update cni config: no networks found in /etc/cni/net.d
- mkdir -p /etc/cni/net.d #创建目录给flannel做配置文件
- vim /etc/cni/net.d/10-flannel.conf #编写配置文件
-
-
- {
- "name":"cbr0",
- "cniVersion":"0.3.1",
- "type":"flannel",
- "deledate":{
- "hairpinMode":true,
- "isDefaultGateway":true
- }
-
- }
- #在master节点之外的节点进行操作
- kubeadm reset
- systemctl stop kubelet
- systemctl stop docker
- rm -rf /var/lib/cni/
- rm -rf /var/lib/kubelet/*
- rm -rf /etc/cni/
- ifconfig cni0 down
- ifconfig flannel.1 down
- ifconfig docker0 down
- ip link delete cni0
- ip link delete flannel.1
- ##重启kubelet
- systemctl restart kubelet
- ##重启docker
- systemctl restart docker
- # 重启kubelet
- systemctl restart kubelet
- # 重启docker
- systemctl restart docker
使用配置文件启动fannel
kubectl apply -f kube-flannel.yml
等待它安装完毕 发现已经是 集群的状态已经是Ready
- # 生成 新的token
- [root@master ~]# kubeadm token create --print-join-command
kubectl create deployment nginx --image=nginx:1.14-alpine
kubectl expose deploy nginx --port=80 --target-port=80 --type=NodePort
kubectl get pod,svc
浏览器测试结果:
在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理kubernetes。
kubernetes的本质上就是一个集群系统,用户可以在集群中部署各种服务,所谓的部署服务,其实就是在kubernetes集群中运行一个个的容器,并将指定的程序跑在容器中。
kubernetes的最小管理单元是pod而不是容器,所以只能将容器放在Pod中,而kubernetes一般也不会直接管理Pod,而是通过Pod控制器来管理Pod的。
Pod可以提供服务之后,就要考虑如何访问Pod中服务,kubernetes提供了Service资源实现这个功能。
当然,如果Pod中程序的数据需要持久化,kubernetes还提供了各种存储系统。
学习kubernetes的核心,就是学习如何对集群上的Pod、Pod控制器、Service、存储等各种资源进行操作
命令式对象管理:直接使用命令去操作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命令的语法如下:
kubectl [command] [type] [name] [flags]
comand:指定要对资源执行的操作,例如create、get、delete
type:指定资源类型,比如deployment、pod、service
name:指定资源的名称,名称大小写敏感
flags:指定额外的可选参数
- # 查看所有pod
- kubectl get pod
-
- # 查看某个pod
- kubectl get pod pod_name
-
- # 查看某个pod,以yaml格式展示结果
- kubectl get pod pod_name -o yaml
资源类型
kubernetes中所有的内容都抽象为资源,可以通过下面的命令进行查看:
kubectl api-resources
经常使用的资源有下面这些:
操作
kubernetes允许对资源进行多种操作,可以通过–help查看详细的操作命令
kubectl --help
下面以一个namespace / pod的创建和删除简单演示下命令的使用:
- # 创建一个namespace
- [root@master ~]# kubectl create namespace dev
- namespace/dev created
-
- # 获取namespace
- [root@master ~]# kubectl get ns
- NAME STATUS AGE
- default Active 21h
- dev Active 21s
- kube-node-lease Active 21h
- kube-public Active 21h
- kube-system Active 21h
-
- # 在此namespace下创建并运行一个nginx的Pod
- [root@master ~]# kubectl run pod --image=nginx:latest -n dev
- kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
- deployment.apps/pod created
-
- # 查看新创建的pod
- [root@master ~]# kubectl get pod -n dev
- NAME READY STATUS RESTARTS AGE
- pod 1/1 Running 0 21s
-
- # 删除指定的pod
- [root@master ~]# kubectl delete pod pod-864f9875b9-pcw7x
- pod "pod" deleted
-
- # 删除指定的namespace
- [root@master ~]# kubectl delete ns dev
- namespace "dev" deleted
命令式对象配置就是使用命令配合配置文件一起来操作kubernetes资源。
1) 创建一个nginxpod.yaml,内容如下:
apiVersion: v1 kind: Namespace metadata: name: dev --- apiVersion: v1 kind: Pod metadata: name: nginxpod namespace: dev spec: containers: - name: nginx-containers image: nginx:latest
2)执行create命令,创建资源:
-
- [root@master ~]# kubectl create -f nginxpod.yaml
- namespace/dev created
- pod/nginxpod created
此时发现创建了两个资源对象,分别是namespace和pod
3)执行get命令,查看资源:
- [root@master ~]# kubectl get -f nginxpod.yaml
- NAME STATUS AGE
- namespace/dev Active 18s
-
- NAME READY STATUS RESTARTS AGE
- pod/nginxpod 1/1 Running 0 17s
这样就显示了两个资源对象的信息
4)执行delete命令,删除资源:
- [root@master ~]# kubectl delete -f nginxpod.yaml
- namespace "dev" deleted
- pod "nginxpod" deleted
此时发现两个资源对象被删除了
总结:
命令式对象配置的方式操作资源,可以简单的认为:命令 + yaml配置文件(里面是命令需要的各种参数)
声明式对象配置跟命令式对象配置很相似,但是它只有一个命令apply。
- # 首先执行一次kubectl apply -f yaml文件,发现创建了资源
- [root@master ~]# kubectl apply -f nginxpod.yaml
- namespace/dev created
- pod/nginxpod created
- # 再次执行一次kubectl apply -f yaml文件,发现说资源没有变动
- [root@master ~]# kubectl apply -f nginxpod.yaml
- namespace/dev unchanged
- pod/nginxpod unchanged
总结:
其实声明式对象配置就是使用apply描述一个资源最终的状态(在yaml中定义状态)
使用apply操作资源:
如果资源不存在,就创建,相当于 kubectl create
如果资源已存在,就更新,相当于 kubectl patch
扩展:kubectl可以在node节点上运行吗 ?
kubectl的运行是需要进行配置的,它的配置文件是$HOME/.kube,如果想要在node节点运行此命令,需要将master上的.kube文件复制到node节点上,即在master节点上执行下面操作:
scp -r HOME/.kube node1: HOME/
使用推荐: 三种方式应该怎么用 ?
创建/更新资源 使用声明式对象配置 kubectl apply -f XXX.yaml
删除资源 使用命令式对象配置 kubectl delete -f XXX.yaml
查询资源 使用命令式对象管理 kubectl get(describe) 资源名称
本章节将介绍如何在kubernetes集群中部署一个nginx服务,并且能够对其进行访问。
Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。
默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的"组",以方便不同的组的资源进行隔离使用和管理。
可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。
kubernetes在集群启动之后,会默认创建几个namespace
- [root@master ~]# kubectl get namespace
- NAME STATUS AGE
- default Active 45h # 所有未指定Namespace的对象都会被分配在default命名空间
- kube-node-lease Active 45h # 集群节点之间的心跳维护,v1.13开始引入
- kube-public Active 45h # 此命名空间下的资源可以被所有人访问(包括未认证用户)
- kube-system Active 45h # 所有由Kubernetes系统创建的资源都处于这个命名空间
下面来看namespace资源的具体操作:
- # 1 查看所有的ns 命令:kubectl get ns
- [root@master ~]# kubectl get ns
- NAME STATUS AGE
- default Active 45h
- kube-node-lease Active 45h
- kube-public Active 45h
- kube-system Active 45h
-
- # 2 查看指定的ns 命令:kubectl get ns ns名称
- [root@master ~]# kubectl get ns default
- NAME STATUS AGE
- default Active 45h
-
- # 3 指定输出格式 命令:kubectl get ns ns名称 -o 格式参数
- # kubernetes支持的格式有很多,比较常见的是wide、json、yaml
- [root@master ~]# kubectl get ns default -o yaml
- apiVersion: v1
- kind: Namespace
- metadata:
- creationTimestamp: "2021-05-08T04:44:16Z"
- name: default
- resourceVersion: "151"
- selfLink: /api/v1/namespaces/default
- uid: 7405f73a-e486-43d4-9db6-145f1409f090
- spec:
- finalizers:
- - kubernetes
- status:
- phase: Active
-
- # 4 查看ns详情 命令:kubectl describe ns ns名称
- [root@master ~]# kubectl describe ns default
- Name: default
- Labels: <none>
- Annotations: <none>
- Status: Active # Active 命名空间正在使用中 Terminating 正在删除命名空间
-
- # ResourceQuota 针对namespace做的资源限制
- # LimitRange针对namespace中的每个组件做的资源限制
- No resource quota.
- No LimitRange resource.
- # 创建namespace
- [root@master ~]# kubectl create ns dev
- namespace/dev created
- # 删除namespace
- [root@master ~]# kubectl delete ns dev
- namespace "dev" deleted
首先准备一个yaml文件:ns-dev.yaml
- apiVersion: v1
- kind: Namespace
- metadata:
- name: dev
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f ns-dev.yaml
删除:kubectl delete -f ns-dev.yaml
Pod是kubernetes集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于Pod中。
Pod可以认为是容器的封装,一个Pod中可以存在一个或者多个容器。
kubernetes在集群启动之后,集群中的各个组件也都是以Pod方式运行的。可以通过下面命令查看:
- [root@master ~]# kubectl get pod -n kube-system
- NAMESPACE NAME READY STATUS RESTARTS AGE
- kube-system coredns-6955765f44-68g6v 1/1 Running 0 2d1h
- kube-system coredns-6955765f44-cs5r8 1/1 Running 0 2d1h
- kube-system etcd-master 1/1 Running 0 2d1h
- kube-system kube-apiserver-master 1/1 Running 0 2d1h
- kube-system kube-controller-manager-master 1/1 Running 0 2d1h
- kube-system kube-flannel-ds-amd64-47r25 1/1 Running 0 2d1h
- kube-system kube-flannel-ds-amd64-ls5lh 1/1 Running 0 2d1h
- kube-system kube-proxy-685tk 1/1 Running 0 2d1h
- kube-system kube-proxy-87spt 1/1 Running 0 2d1h
- kube-system kube-scheduler-master 1/1 Running 0 2d1h
kubernetes没有提供单独运行Pod的命令,都是通过Pod控制器来实现的
- # 命令格式: kubectl run (pod控制器名称) [参数]
- # --image 指定Pod的镜像
- # --port 指定端口
- # --namespace 指定namespace
- [root@master ~]# kubectl run nginx --image=nginx:latest --port=80 --namespace dev
- deployment.apps/nginx created
- # 查看Pod基本信息
- [root@master ~]# kubectl get pods -n dev
- NAME READY STATUS RESTARTS AGE
- nginx 1/1 Running 0 43s
-
- # 查看Pod的详细信息
- [root@master ~]# kubectl describe pod nginx -n dev
- Name: nginx
- Namespace: dev
- Priority: 0
- Node: node1/192.168.5.4
- Start Time: Wed, 08 May 2021 09:29:24 +0800
- Labels: pod-template-hash=5ff7956ff6
- run=nginx
- Annotations: <none>
- Status: Running
- IP: 10.244.1.23
- IPs:
- IP: 10.244.1.23
- Controlled By: ReplicaSet/nginx
- Containers:
- nginx:
- Container ID: docker://4c62b8c0648d2512380f4ffa5da2c99d16e05634979973449c98e9b829f6253c
- Image: nginx:latest
- Image ID: docker-pullable://nginx@sha256:485b610fefec7ff6c463ced9623314a04ed67e3945b9c08d7e53a47f6d108dc7
- Port: 80/TCP
- Host Port: 0/TCP
- State: Running
- Started: Wed, 08 May 2021 09:30:01 +0800
- Ready: True
- Restart Count: 0
- Environment: <none>
- Mounts:
- /var/run/secrets/kubernetes.io/serviceaccount from default-token-hwvvw (ro)
- Conditions:
- Type Status
- Initialized True
- Ready True
- ContainersReady True
- PodScheduled True
- Volumes:
- default-token-hwvvw:
- Type: Secret (a volume populated by a Secret)
- SecretName: default-token-hwvvw
- Optional: false
- QoS Class: BestEffort
- Node-Selectors: <none>
- Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
- node.kubernetes.io/unreachable:NoExecute for 300s
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal Scheduled <unknown> default-scheduler Successfully assigned dev/nginx-5ff7956ff6-fg2db to node1
- Normal Pulling 4m11s kubelet, node1 Pulling image "nginx:latest"
- Normal Pulled 3m36s kubelet, node1 Successfully pulled image "nginx:latest"
- Normal Created 3m36s kubelet, node1 Created container nginx
- Normal Started 3m36s kubelet, node1 Started container nginx
- # 获取podIP
- [root@master ~]# kubectl get pods -n dev -o wide
-
- apiVersion: v1
- kind: Service
- metadata:
- name: service-nodeport
- namespace: dev
- spec:
- selector:
- app: nginx-pod
- type: NodePort # service类型
- ports:
- - port: 80
- nodePort: 30002 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
- targetPort: 80
- # 创建service
- [root@k8s-master01 ~]# kubectl create -f service-nodeport.yaml
- service/service-nodeport created
-
- # 查看service
- [root@k8s-master01 ~]# kubectl get svc -n dev -o wide
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) SELECTOR
- service-nodeport NodePort 10.105.64.191 <none> 80:30002/TCP app=nginx-pod
-
- # 接下来可以通过电脑主机的浏览器去访问集群中任意一个nodeip的30002端口,即可访问到pod
- # 删除指定Pod
- [root@master ~]# kubectl delete pod nginx -n dev
- pod "nginx" deleted
-
- # 此时,显示删除Pod成功,但是再查询,发现又新产生了一个
- [root@master ~]# kubectl get pods -n dev
- NAME READY STATUS RESTARTS AGE
- nginx 1/1 Running 0 21s
-
- # 这是因为当前Pod是由Pod控制器创建的,控制器会监控Pod状况,一旦发现Pod死亡,会立即重建
- # 此时要想删除Pod,必须删除Pod控制器
-
- # 先来查询一下当前namespace下的Pod控制器
- [root@master ~]# kubectl get deploy -n dev
- NAME READY UP-TO-DATE AVAILABLE AGE
- nginx 1/1 1 1 9m7s
-
- # 接下来,删除此PodPod控制器
- [root@master ~]# kubectl delete deploy nginx -n dev
- deployment.apps "nginx" deleted
-
- # 稍等片刻,再查询Pod,发现Pod被删除了
- [root@master ~]# kubectl get pods -n dev
- No resources found in dev namespace.
创建一个pod-nginx.yaml,内容如下:
- apiVersion: v1
- kind: Pod
- metadata:
- name: nginx
- namespace: dev
- spec:
- containers:
- - image: nginx:latest
- name: pod
- ports:
- - name: nginx-port
- containerPort: 80
- protocol: TCP
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f pod-nginx.yaml
删除:kubectl delete -f pod-nginx.yaml
Label是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对它们进行区分和选择。
Label的特点:
可以通过Label实现资源的多维度分组,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。
一些常用的Label 示例如下:
版本标签:“version”:“release”, “version”:“stable”…
环境标签:“environment”:“dev”,“environment”:“test”,“environment”:“pro”
架构标签:“tier”:“frontend”,“tier”:“backend”
标签定义完毕之后,还要考虑到标签的选择,这就要使用到Label Selector,即:
Label用于给某个资源对象定义标识
Label Selector用于查询和筛选拥有某些标签的资源对象
当前有两种Label Selector:
name = slave: 选择所有包含Label中key="name"且value="slave"的对象
env != production: 选择所有包括Label中的key="env"且value不等于"production"的对象
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 ~]# kubectl label pod nginx-pod version=1.0 -n dev
- pod/nginx-pod labeled
-
- # 为pod资源更新标签
- [root@master ~]# kubectl label pod nginx-pod version=2.0 -n dev --overwrite
- pod/nginx-pod labeled
-
- # 查看标签
- [root@master ~]# kubectl get pod nginx-pod -n dev --show-labels
- NAME READY STATUS RESTARTS AGE LABELS
- nginx-pod 1/1 Running 0 10m version=2.0
-
- # 筛选标签
- [root@master ~]# kubectl get pod -n dev -l version=2.0 --show-labels
- NAME READY STATUS RESTARTS AGE LABELS
- nginx-pod 1/1 Running 0 17m version=2.0
- [root@master ~]# kubectl get pod -n dev -l version!=2.0 --show-labels
- No resources found in dev namespace.
-
- #删除标签
- [root@master ~]# kubectl label pod nginx-pod -n dev tier-
- pod/nginx unlabeled
- apiVersion: v1
- kind: Pod
- metadata:
- name: nginx
- namespace: dev
- labels:
- version: "3.0"
- env: "test"
- spec:
- containers:
- - image: nginx:latest
- name: pod
- ports:
- - name: nginx-port
- containerPort: 80
- protocol: TCP
然后就可以执行对应的更新命令了:kubectl apply -f pod-nginx.yaml
在kubernetes中,Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于pod的管理,确保pod资源符合预期的状态,当pod的资源出现故障时,会尝试进行重启或重建pod。
在kubernetes中Pod控制器的种类有很多,本章节只介绍一种:Deployment。
- # 命令格式: kubectl create deployment 名称 [参数]
- # --image 指定pod的镜像
- # --port 指定端口
- # --replicas 指定创建pod数量
- # --namespace 指定namespace
- [root@master ~]# kubectl run nginx --image=nginx:latest --port=80 --replicas=3 -n dev
- deployment.apps/nginx created
-
- # 查看创建的Pod
- [root@master ~]# kubectl get pods -n dev
- NAME READY STATUS RESTARTS AGE
- nginx-5ff7956ff6-6k8cb 1/1 Running 0 19s
- nginx-5ff7956ff6-jxfjt 1/1 Running 0 19s
- nginx-5ff7956ff6-v6jqw 1/1 Running 0 19s
-
- # 查看deployment的信息
- [root@master ~]# kubectl get deploy -n dev
- NAME READY UP-TO-DATE AVAILABLE AGE
- nginx 3/3 3 3 2m42s
-
- # UP-TO-DATE:成功升级的副本数量
- # AVAILABLE:可用副本的数量
- [root@master ~]# kubectl get deploy -n dev -o wide
- NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
- nginx 3/3 3 3 2m51s nginx nginx:latest run=nginx
-
- # 查看deployment的详细信息
- [root@master ~]# kubectl describe deploy nginx -n dev
- Name: nginx
- Namespace: dev
- CreationTimestamp: Wed, 08 May 2021 11:14:14 +0800
- Labels: run=nginx
- Annotations: deployment.kubernetes.io/revision: 1
- Selector: run=nginx
- Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
- StrategyType: RollingUpdate
- MinReadySeconds: 0
- RollingUpdateStrategy: 25% max unavailable, 25% max 违规词汇
- Pod Template:
- Labels: run=nginx
- Containers:
- nginx:
- Image: nginx:latest
- Port: 80/TCP
- Host Port: 0/TCP
- Environment: <none>
- Mounts: <none>
- Volumes: <none>
- Conditions:
- Type Status Reason
- ---- ------ ------
- Available True MinimumReplicasAvailable
- Progressing True NewReplicaSetAvailable
- OldReplicaSets: <none>
- NewReplicaSet: nginx-5ff7956ff6 (3/3 replicas created)
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal ScalingReplicaSet 5m43s deployment-controller Scaled up replicaset nginx-5ff7956ff6 to 3
-
- # 删除
- [root@master ~]# kubectl delete deploy nginx -n dev
- deployment.apps "nginx" deleted
创建一个deploy-nginx.yaml,内容如下:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx namespace: dev spec: replicas: 3 selector: matchLabels: run: nginx template: metadata: labels: run: nginx spec: containers: - image: nginx:latest name: nginx ports: - containerPort: 80 protocol: TCP
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f deploy-nginx.yaml
删除:kubectl delete -f deploy-nginx.yaml
通过上节课的学习,已经能够利用Deployment来创建一组Pod来提供具有高可用性的服务。
虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题:
这样对于访问这个服务带来了难度。因此,kubernetes设计了Service来解决这个问题。
Service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。
- # 暴露Service
- [root@master ~]# kubectl expose deploy nginx --name=svc-nginx1 --type=ClusterIP --port=80 --target-port=80 -n dev
- service/svc-nginx1 exposed
-
- # 查看service
- [root@master ~]# kubectl get svc svc-nginx1 -n dev -o wide
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
- svc-nginx1 ClusterIP 10.109.179.231 <none> 80/TCP 3m51s run=nginx
-
- # 这里产生了一个CLUSTER-IP,这就是service的IP,在Service的生命周期中,这个地址是不会变动的
- # 可以通过这个IP访问当前service对应的POD
- [root@master ~]# curl 10.109.179.231:80
- <!DOCTYPE html>
- <html>
- <head>
- <title>Welcome to nginx!</title>
- </head>
- <body>
- <h1>Welcome to nginx!</h1>
- .......
- </body>
- </html>
- # 上面创建的Service的type类型为ClusterIP,这个ip地址只用集群内部可访问
- # 如果需要创建外部也可以访问的Service,需要修改type为NodePort
- [root@master ~]# kubectl expose deploy nginx --name=svc-nginx2 --type=NodePort --port=80 --target-port=80 -n dev
- service/svc-nginx2 exposed
-
- # 此时查看,会发现出现了NodePort类型的Service,而且有一对Port(80:31928/TC)
- [root@master ~]# kubectl get svc svc-nginx2 -n dev -o wide
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
- svc-nginx2 NodePort 10.100.94.0 <none> 80:31928/TCP 9s run=nginx
-
- # 接下来就可以通过集群外的主机访问 节点IP:31928访问服务了
- # 例如在的电脑主机上通过浏览器访问下面的地址
- http://192.168.90.100:31928/
- [root@master ~]# kubectl delete svc svc-nginx-1 -n dev
- service "svc-nginx-1" deleted
创建一个svc-nginx.yaml,内容如下:
- apiVersion: v1
- kind: Service
- metadata:
- name: svc-nginx
- namespace: dev
- spec:
- clusterIP: 10.109.179.231 #固定svc的内网ip
- ports:
- - port: 80
- protocol: TCP
- targetPort: 80
- selector:
- run: nginx
- type: ClusterIP
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f svc-nginx.yaml
删除:kubectl delete -f svc-nginx.yaml
小结
至此,已经掌握了Namespace、Pod、Deployment、Service资源的基本操作,有了这些操作,就可以在kubernetes集群中实现一个服务的简单部署和访问了,但是如果想要更好的使用kubernetes,就需要深入学习这几种资源的细节和原理。
每个Pod中都可以包含一个或者多个容器,这些容器可以分为两类:
用户程序所在的容器,数量可多可少
Pause容器,这是每个Pod都会有的一个根容器,它的作用有两个:
下面是Pod的资源清单:
- apiVersion: v1 #必选,版本号,例如v1
- kind: Pod #必选,资源类型,例如 Pod
- metadata: #必选,元数据
- name: string #必选,Pod名称
- namespace: string #Pod所属的命名空间,默认为"default"
- labels: #自定义标签列表
- - name: string
- spec: #必选,Pod中容器的详细定义
- containers: #必选,Pod中容器列表
- - name: string #必选,容器名称
- image: string #必选,容器的镜像名称
- imagePullPolicy: [ Always|Never|IfNotPresent ] #获取镜像的策略
- command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令
- args: [string] #容器的启动命令参数列表
- workingDir: string #容器的工作目录
- volumeMounts: #挂载到容器内部的存储卷配置
- - name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
- mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符
- readOnly: boolean #是否为只读模式
- ports: #需要暴露的端口库号列表
- - name: string #端口的名称
- containerPort: int #容器需要监听的端口号
- hostPort: int #容器所在主机需要监听的端口号,默认与Container相同
- protocol: string #端口协议,支持TCP和UDP,默认TCP
- env: #容器运行前需设置的环境变量列表
- - name: string #环境变量名称
- value: string #环境变量的值
- resources: #资源限制和请求的设置
- limits: #资源限制的设置
- cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
- memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
- requests: #资源请求的设置
- cpu: string #Cpu请求,容器启动的初始可用数量
- memory: string #内存请求,容器启动的初始可用数量
- lifecycle: #生命周期钩子
- postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启
- preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止
- livenessProbe: #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器
- exec: #对Pod容器内检查方式设置为exec方式
- command: [string] #exec方式需要制定的命令或脚本
- httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
- path: string
- port: number
- host: string
- scheme: string
- HttpHeaders:
- - name: string
- value: string
- tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式
- port: number
- initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒
- timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
- periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
- successThreshold: 0
- failureThreshold: 0
- securityContext:
- privileged: false
- restartPolicy: [Always | Never | OnFailure] #Pod的重启策略
- nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上
- nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上
- imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
- - name: string
- hostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
- volumes: #在该pod上定义共享存储卷列表
- - name: string #共享存储卷名称 (volumes类型有很多种)
- emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
- hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
- path: string #Pod所在宿主机的目录,将被用于同期中mount的目录
- secret: #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部
- scretname: string
- items:
- - key: string
- path: string
- configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
- name: string
- items:
- - key: string
- path: string
- #小提示:
- # 在这里,可通过一个命令来查看每种资源的可配置项
- # kubectl explain 资源类型 查看某种资源可以配置的一级属性
- # kubectl explain 资源类型.属性 查看属性的子属性
- [root@k8s-master01 ~]# kubectl explain pod
- KIND: Pod
- VERSION: v1
- FIELDS:
- apiVersion <string>
- kind <string>
- metadata <Object>
- spec <Object>
- status <Object>
-
- [root@k8s-master01 ~]# kubectl explain pod.metadata
- KIND: Pod
- VERSION: v1
- RESOURCE: metadata <Object>
- FIELDS:
- annotations <map[string]string>
- clusterName <string>
- creationTimestamp <string>
- deletionGracePeriodSeconds <integer>
- deletionTimestamp <string>
- finalizers <[]string>
- generateName <string>
- generation <integer>
- labels <map[string]string>
- managedFields <[]Object>
- name <string>
- namespace <string>
- ownerReferences <[]Object>
- resourceVersion <string>
- selfLink <string>
- uid <string>
本小节主要来研究pod.spec.containers属性,这也是pod配置中最为关键的一项配置。
- [root@k8s-master01 ~]# kubectl explain pod.spec.containers
- KIND: Pod
- VERSION: v1
- RESOURCE: containers <[]Object> # 数组,代表可以有多个容器
- FIELDS:
- name <string> # 容器名称
- image <string> # 容器需要的镜像地址
- imagePullPolicy <string> # 镜像拉取策略
- command <[]string> # 容器的启动命令列表,如不指定,使用打包时使用的启动命令
- args <[]string> # 容器的启动命令需要的参数列表
- env <[]Object> # 容器环境变量的配置
- ports <[]Object> # 容器需要暴露的端口号列表
- resources <Object> # 资源限制和资源请求的设置
创建pod-base.yaml文件,内容如下:
- apiVersion: v1
- kind: Pod
- metadata:
- name: pod-base
- namespace: dev
- labels:
- user: heima
- spec:
- containers:
- - name: nginx
- image: nginx:1.17.1
- - name: busybox
- image: busybox:1.30
上面定义了一个比较简单Pod的配置,里面有两个容器:
- # 创建Pod
- [root@k8s-master01 pod]# kubectl apply -f pod-base.yaml
- pod/pod-base created
-
- # 查看Pod状况
- # READY 1/2 : 表示当前Pod中有2个容器,其中1个准备就绪,1个未就绪
- # RESTARTS : 重启次数,因为有1个容器故障了,Pod一直在重启试图恢复它
- [root@k8s-master01 pod]# kubectl get pod -n dev
- NAME READY STATUS RESTARTS AGE
- pod-base 1/2 Running 4 95s
-
- # 可以通过describe查看内部的详情
- # 此时已经运行起来了一个基本的Pod,虽然它暂时有问题
- [root@k8s-master01 pod]# kubectl describe pod pod-base -n dev
创建pod-imagepullpolicy.yaml文件,内容如下:
- apiVersion: v1
- kind: Pod
- metadata:
- name: pod-imagepullpolicy
- namespace: dev
- spec:
- containers:
- - name: nginx
- image: nginx:1.17.1
- imagePullPolicy: Never # 用于设置镜像拉取策略
- - name: busybox
- image: busybox:1.30
imagePullPolicy,用于设置镜像拉取策略,kubernetes支持配置三种拉取策略:
默认值说明:
如果镜像tag为具体版本号, 默认策略是:IfNotPresent
如果镜像tag为:latest(最终版本) ,默认策略是always
- # 创建Pod
- [root@k8s-master01 pod]# kubectl create -f pod-imagepullpolicy.yaml
- pod/pod-imagepullpolicy created
-
- # 查看Pod详情
- # 此时明显可以看到nginx镜像有一步Pulling image "nginx:1.17.1"的过程
- [root@k8s-master01 pod]# kubectl describe pod pod-imagepullpolicy -n dev
- ......
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal Scheduled <unknown> default-scheduler Successfully assigned dev/pod-imagePullPolicy to node1
- Normal Pulling 32s kubelet, node1 Pulling image "nginx:1.17.1"
- Normal Pulled 26s kubelet, node1 Successfully pulled image "nginx:1.17.1"
- Normal Created 26s kubelet, node1 Created container nginx
- Normal Started 25s kubelet, node1 Started container nginx
- Normal Pulled 7s (x3 over 25s) kubelet, node1 Container image "busybox:1.30" already present on machine
- Normal Created 7s (x3 over 25s) kubelet, node1 Created container busybox
- Normal Started 7s (x3 over 25s) kubelet, node1 Started container busybox
在前面的案例中,一直有一个问题没有解决,就是的busybox容器一直没有成功运行,那么到底是什么原因导致这个容器的故障呢?
原来busybox并不是一个程序,而是类似于一个工具类的集合,kubernetes集群启动管理后,它会自动关闭。解决方法就是让其一直在运行,这就用到了command配置。
创建pod-command.yaml文件,内容如下:
- apiVersion: v1
- kind: Pod
- metadata:
- name: pod-command
- namespace: dev
- spec:
- containers:
- - name: nginx
- image: nginx:1.17.1
- - name: busybox
- image: busybox:1.30
- command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done;"]
command,用于在pod中的容器初始化完毕之后运行一个命令。
稍微解释下上面命令的意思:
“/bin/sh”,“-c”, 使用sh执行命令
touch /tmp/hello.txt; 创建一个/tmp/hello.txt 文件
while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done; 每隔3秒向文件中写入当前时间
- # 创建Pod
- [root@k8s-master01 pod]# kubectl create -f pod-command.yaml
- pod/pod-command created
-
- # 查看Pod状态
- # 此时发现两个pod都正常运行了
- [root@k8s-master01 pod]# kubectl get pods pod-command -n dev
- NAME READY STATUS RESTARTS AGE
- pod-command 2/2 Runing 0 2s
-
- # 进入pod中的busybox容器,查看文件内容
- # 补充一个命令: kubectl exec pod名称 -n 命名空间 -it -c 容器名称 /bin/sh 在容器内部执行命令
- # 使用这个命令就可以进入某个容器的内部,然后进行相关操作了
- # 比如,可以查看txt文件的内容
- [root@k8s-master01 pod]# kubectl exec pod-command -n dev -it -c busybox /bin/sh
- / # tail -f /tmp/hello.txt
- 14:44:19
- 14:44:22
- 14:44:25
- 特别说明:
- 通过上面发现command已经可以完成启动命令和传递参数的功能,为什么这里还要提供一个args选项,用于传递参数呢?这其实跟docker有点关系,kubernetes中的command、args两项其实是实现覆盖Dockerfile中ENTRYPOINT的功能。
- 1 如果command和args均没有写,那么用Dockerfile的配置。
- 2 如果command写了,但args没有写,那么Dockerfile默认的配置会被忽略,执行输入的command
- 3 如果command没写,但args写了,那么Dockerfile中配置的ENTRYPOINT的命令会被执行,使用当前args的参数
- 4 如果command和args都写了,那么Dockerfile的配置被忽略,执行command并追加上args参数
5.2.4 环境变量
创建pod-env.yaml文件,内容如下:
- apiVersion: v1
- kind: Pod
- metadata:
- name: pod-env
- namespace: dev
- spec:
- containers:
- - name: busybox
- image: busybox:1.30
- command: ["/bin/sh","-c","while true;do /bin/echo $(date +%T);sleep 60; done;"]
- env: # 设置环境变量列表
- - name: "username"
- value: "admin"
- - name: "password"
- value: "123456"
env,环境变量,用于在pod中的容器设置环境变量。
- # 创建Pod
- [root@k8s-master01 ~]# kubectl create -f pod-env.yaml
- pod/pod-env created
-
- # 进入容器,输出环境变量
- [root@k8s-master01 ~]# kubectl exec pod-env -n dev -c busybox -it /bin/sh
- / # echo $username
- admin
- / # echo $password
- 123456
这种方式不是很推荐,推荐将这些配置单独存储在配置文件中,这种方式将在后面介绍。
5.2.5 端口设置
本小节来介绍容器的端口设置,也就是containers的ports选项。
首先看下ports支持的子选项:
- [root@k8s-master01 ~]# kubectl explain pod.spec.containers.ports
- KIND: Pod
- VERSION: v1
- RESOURCE: ports <[]Object>
- FIELDS:
- name <string> # 端口名称,如果指定,必须保证name在pod中是唯一的
- containerPort<integer> # 容器要监听的端口(0<x<65536)
- hostPort <integer> # 容器要在主机上公开的端口,如果设置,主机上只能运行容器的一个副本(一般省略)
- hostIP <string> # 要将外部端口绑定到的主机IP(一般省略)
- protocol <string> # 端口协议。必须是UDP、TCP或SCTP。默认为“TCP”。
接下来,编写一个测试案例,创建pod-ports.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: pod-ports
- namespace: dev
- spec:
- containers:
- - name: nginx
- image: nginx:1.17.1
- ports: # 设置容器暴露的端口列表
- - name: nginx-port
- containerPort: 80
- protocol: TCP
- # 创建Pod
- [root@k8s-master01 ~]# kubectl create -f pod-ports.yaml
- pod/pod-ports created
-
- # 查看pod
- # 在下面可以明显看到配置信息
- [root@k8s-master01 ~]# kubectl get pod pod-ports -n dev -o yaml
- ......
- spec:
- containers:
- - image: nginx:1.17.1
- imagePullPolicy: IfNotPresent
- name: nginx
- ports:
- - containerPort: 80
- name: nginx-port
- protocol: TCP
- ......
访问容器中的程序需要使用的是Podip:containerPort
容器中的程序要运行,肯定是要占用一定资源的,比如cpu和内存等,如果不对某个容器的资源做限制,那么它就可能吃掉大量资源,导致其它容器无法运行。针对这种情况,kubernetes提供了对内存和cpu的资源进行配额的机制,这种机制主要通过resources选项实现,他有两个子选项:
可以通过上面两个选项设置资源的上下限。
接下来,编写一个测试案例,创建pod-resources.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: pod-resources
- namespace: dev
- spec:
- containers:
- - name: nginx
- image: nginx:1.17.1
- resources: # 资源配额
- limits: # 限制资源(上限)
- cpu: "2" # CPU限制,单位是core数
- memory: "10Gi" # 内存限制
- requests: # 请求资源(下限)
- cpu: "1" # CPU限制,单位是core数
- memory: "10Mi" # 内存限制
在这对cpu和memory的单位做一个说明:
- # 运行Pod
- [root@k8s-master01 ~]# kubectl create -f pod-resources.yaml
- pod/pod-resources created
- # 查看发现pod运行正常
- [root@k8s-master01 ~]# kubectl get pod pod-resources -n dev
- NAME READY STATUS RESTARTS AGE
- pod-resources 1/1 Running 0 39s
- # 接下来,停止Pod
- [root@k8s-master01 ~]# kubectl delete -f pod-resources.yaml
- pod "pod-resources" deleted
- # 编辑pod,修改resources.requests.memory的值为10Gi
- [root@k8s-master01 ~]# vim pod-resources.yaml
- # 再次启动pod
- [root@k8s-master01 ~]# kubectl create -f pod-resources.yaml
- pod/pod-resources created
- # 查看Pod状态,发现Pod启动失败
- [root@k8s-master01 ~]# kubectl get pod pod-resources -n dev -o wide
- NAME READY STATUS RESTARTS AGE
- pod-resources 0/1 Pending 0 20s
- # 查看pod详情会发现,如下提示
- [root@k8s-master01 ~]# kubectl describe pod pod-resources -n dev
- ......
- Warning FailedScheduling 35s default-scheduler 0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 Insufficient memory.(内存不足)
我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期,它主要包含下面的过程:
容器启动后钩子(post start)、容器终止前钩子(pre stop)
容器的存活性探测(liveness probe)、就绪性探测(readiness probe)
在整个生命周期中,Pod会出现5种状态(相位),分别如下:
pod的创建过程
pod的终止过程
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。