1 Kubernetes基础概念
官网:https://kubernetes.io
Kubernetes是容器集群自动部署、扩容、运维的开源平台。master-nodes架构,master只需要几个来提高可用性,任何时候只有一个master管理集群,nodes多个节点可以真正部署容器。
Kubernetes的特点:
- 自动装箱。基于资源,依靠自动部署服务。
- 自我修复。当一个容器挂断时,它可以自动启动一个新的容器,以更换同样的服务故障。
- 水平扩展自动实现。只要物理资源充足,设置触发阈值,水平伸缩服务就可以自动实现。
- 平衡自动服务发现和负载。service可提供稳定的访问端点和负载平衡。
- 自动发布和回滚。
- 密钥和配置管理。
- 存储安排,动态供应存储卷。
- 批量处理执行。
Kubernetes的架构图:

Kubernetes主模块概念:
名称 | 说明 |
---|---|
Cluster | Cluster是指由Kubernetes使用一系列物理机、虚拟机等基本资源来运行您的应用程序。 |
Node | 一个node只是操作Kubernetes物理机或虚拟机,以及pod上面可以调度。 |
Pod | 一个pod对应由相关容器和卷组成的容器组。 |
Label | 一个label是附加到资源上的键/值对,例如附加到一个Pod上,为它传递用户自定的、可识别的属性,Label子网中的资源也可用于组织和选择。 |
selector | selector通过匹配labels定义资源之间关系的表达式,如负载平衡service指定所目标Pod。 |
Replication Controller | replication controller 是为了确保指定的一定数量Pod复制品可以在任何时候正常工作。它不仅可以使复制系统容易扩展,还可以处理pod当机器重启或发生故障时,再创建一个。 |
Service | 一个service定义了访问pod就像单个固定的方式一样IP与之对应的地址DNS名字之间的关系。 |
Volume | 一个volume容器可以作为未见系统的一部分访问目录。 |
Kubernetes volume | 构建在Docker Volumes支持添加和配置volume目录或其它存储设备。 |
Secret | Secret 存储敏感数据,如允许容器接收请求的权限令牌。 |
Name | 用户为Kubernetes中资源定义的名称。 |
Namespace | Namespace 就像资源名的前缀。它帮助不同的项目、团队或客户共享cluster,例如,防止独立团队之间的命名冲突。 |
Annotation | 相对于label它可以容纳更大的键值,这可能是我们不可读的数据,只是为了存储不可识别的辅助数据,特别是一些由工具或系统扩展的数据。 |
Kubernetes设计图:
1.1 master节点介绍
名称 | 说明 |
---|---|
Kubernetes API Server | API服务提供Kubernetes API服务。通过这项服务,客户端主要提供标准的资源增删改查。REST接口调用,也是kubernetes其他模块集群(etcd、scheduler等)客户端。 |
Scheduler | 未调度的调度器pod通过binding api绑定到节点上。调度器可插拔,我们期待支持多集群调度,甚至希望支持未来用户定制的调度器。 |
Kubernetes控制面板 | Kubernetes控制面板可分为多个部分。目前,它们都在一个部分运行。master然而,为了实现高可用性,节点需要改变。不同部分合作,提供集群的统一视图。 |
etcd | 所有master的持续状态都存在etcd一个例子。这可以很好地存储配置数据。watch在观察者的支持下,可以快速检测到各部件协调中的变化。 |
1.2 node节点介绍
名称 | 说明 |
---|---|
Pod | Pod是k8s管理的最小单位,k8s容器不会直接操作,Pod和容器有什么关系?Pod每个容器可以包括一个或多个容器Pod都有自己的namespace(网络、存储等资源)Pod内部多个容器之间的关系类似于系统之间的过程,直接使用网络localhost可以通信。 |
kubelet | kubelet负责管理pods上面的容器,images镜像、volumes等。 |
kube-proxy | 每个节点还运行一个简单的网络代理和负载平衡,例如创建service资源需要kube-proxy。 |
fluentd | 日志收集工具 |
Pod分类:
- 自主式Pod
- 由控制器管理Pod,不同类型的管理Pod资源
- ReplicaSet(替代ReplicationController)
- Deployment(无状态应用只能管理)
- StatefulSet(管理状态应用)
- DaemonSet(在每一个node运行副本)
- Job(运行结束后自动删除)
- Ctonjob(周期性job)
其中DaemonSet、Job、Ctonjob此外,它还用于特殊应用程序Deployment还支持二级控制器HPA(HorizontalPodAutoscaler),HPA当当当当前服务能力不能满足时,控制器自动监控资源Pod,当Pod资源空闲时,自动回收资源,这些阈值由用户设置。
2 安装kubernetes集群
搭建Kubernetes一些集群工具:
名称 | 说明 |
---|---|
minikube | 搭建单节点集群 |
kubeadm | 搭建多节点集群 |
kops | 多节点集群安装在云上 |
kubernetes-the-hard-way | 建立多节点集群是最困难的k8s在没有任何工具的帮助下,一步一步地使用命令。 |
这里使用kubeadm建设集群总结:
- 在master和node节点上安装kubeadm、kubele、docker
- 在master节点安装kubectl,初始化集群kubeadm init
- 在node节点中加入k8s集群
2.1 准备虚拟机
搭建的kubernetes集群共3个节点,一个master和两个node:
- master:192.168.8.90
- node01:192.168.8.91
- node02:192.168.8.92。
首先在VMware上安装一个centos7系统(master节点),在master虚拟机关闭情况下,复制master虚拟机文件夹作为node01节点,再复制一份master虚拟机文件夹作为node02节点,复制的两个虚拟机的硬件信息是一样的(包括网络),所以需要修改node01和node02节点的网络。打开VMware软件,导入虚拟机文件,在启动node01虚拟机前,点击编辑虚拟街配置–>网络适配器–>高级–>生成,使用新的MAC地址,不能和master虚拟机MAC地址一样。然后启动虚拟,启动时弹出当前是克隆还会复制虚拟机,选择复制,修改node02虚拟机网络的操作也一样。
进入虚拟机修改网络信息:
# 查看网络ens33物理地址
ip addr
# 例如得到物理地址为00:50:56:2c:68:37
# 在网卡配置,文件名可能不一样,目录是一样的
vim /etc/udev/rules.d/90-eno-fix.rules
# 把ATTR{address}的值改为00:50:56:2c:68:37
# 生成UUID
uuidgen ens33
# 例如生成的UUID值f92eec86-8cd5-4ba3-8b3d-ee7a415252c2
# 把UUID填写到ens33网络接口配置中,并修改静态ip地址
vim /etc/sysconfig/network-scripts/ifcfg-eno16777736
# 完整网络配置内容如下:
TYPE=Ethernet
BOOTPROTO=static
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=eno16777736
UUID=f92eec86-8cd5-4ba3-8b3d-ee7a415252c2
DEVICE=eno16777736
ONBOOT=yes
IPADDR=192.168.8.91
NETMASK=255.255.255.0
GATEWAY=192.168.8.1
DNS1=202.96.128.86
DNS2=114.114.114.114
# 重启系统
reboot
然后在master和node节点上修改主机名称和添加主机名记录值:
# master虚拟机
echo 'master' > /etc/hostname
echo "192.168.8.90 master" >> /etc/hosts
# node01虚拟机
echo 'node01' > /etc/hostname
echo "192.168.8.91 node01" >> /etc/hosts
# node02虚拟机
echo 'node02' > /etc/hostname
echo "192.168.8.92 node02" >> /etc/hosts
2.2 在master和node节点都安装docker、kubeadm、kubelet
# 关闭防火墙
systemctl disable firewalld && systemctl stop firewalld
# 自动开启桥接功能
echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables
# 关闭swap
echo "vm.swappiness = 0" >> /etc/sysctl.conf
swapoff -a && swapon -a
# 安装一些工具
yum install -y git vim gcc glibc-static telnet bridge-utils net-tools
# 安装docker-ce
# 删除旧docker
yum remove -y docker docker-common docker-selinux docker-engine
# 安装依赖包
yum install -y yum-utils device-mapper-persistent-data lvm2
# 指向国内源
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新yum包索引
yum makecache fast
# (1) 安装最新版本
yum install -y docker-ce
# (2) 安装指定版本
yum list docker-ce --showduplicates | sort -r
yum install -y libcgroup
# 要先安装docker-ce-selinux-17.03.1.ce,否则安装docker-ce会报错
yum install -y https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-selinux-17.03.1.ce-1.el7.centos.noarch.rpm
# 安装
yum install -y docker-ce-17.03.1.ce
# 把用户添加docker用户组
groupadd docker
gpasswd -a vison docker
# 设置开机启动docker和启动docker
systemctl enable docker
systemctl start docker
由于安装kubernetes需要翻墙,为了省去翻墙,这里使用阿里云镜像地址,打开阿里云镜像网站,找到kubernetes仓库,然后在各节点上yum安装源目录上添加kubernetes仓库地址。
# 新建kubernetes仓库文件
vim /etc/yum.repos.d/kubernetes.repo
# 添加内容:
[kubernetes]
name=Kubernetes Repo
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
enabled=1
# 检查kubernetes.repo配置有没有错误
yum repolist
# 下载依赖包
wget https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
# 导入依赖包
rpm --import rpm-package-key.gpg
# 在master节点安装kubeadm、kubelet、kubectl
yum install -y kubeadm-1.11.1 kubelet-1.11.1 kubectl-1.11.1
systemctl enable kubelet
systemctl start kubelet # 虽然启动失败,但是也得启动,否则集群初始化会卡死
# 在node节点安装kubeadm、kubelet
yum install -y kubeadm-1.11.1 kubelet-1.11.1
systemctl enable kubelet
systemctl start kubelet
2.3 在master节点上初始化集群
在master节点初始化集群时去官方下载(需翻墙)相关镜像,下载官方镜像有两种方式:
(1) 不翻墙情况下导入镜像
已经准备好1.11.1版本所有相关镜像压缩包。
# 下载镜像
链接:https://pan.baidu.com/s/17ObSpbcgjZipIClQ-ynp2w
提取码:sa9a
# 在master和node节点都导入镜像
tar xf k8s-v1.11.1.images.tar.gz
docker load -i k8s-v1.11.1.images
(2) 配置docker翻墙代理
# 打开docker系统配置
vim /usr/lib/systemd/system/docker.service
# 添加环境变量
Environment="HTTPS_PROXY=http://127.0.0.1:1080"
Environment="NO_PROXY=127.0.0.0/8"
# 重新加载docker配置和重启docker
systemctl daemon-reload
systemctl restart docker
# 查看是否有代理配置
docker info
# 安装完成需要回去注释掉添加的环境变量
初始化kubernetes集群:
# 忽略swap错误
echo 'KUBELET_EXTRA_ARGS="--fail-swap-on=false"' > /etc/sysconfig/kubelet
# 初始化
kubeadm init --kubernetes-version=v1.11.1 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --ignore-preflight-errors=Swap
# 当看到提示Your Kubernetes master has initialized successfully!说明集群初始完成,并记录下加入集群join命令(重要)
kubeadm join 192.168.8.90:6443 --token fs5eos.m8p4pab3fxlefap5 --discovery-token-ca-cert-hash sha256:c353514a313f41ae9124e6cf5a45cfbd67e12e7762b28bbfe44538f07efba363
# 给普通用户vison操作集群权限
mkdir -p /home/vison/.kube
cp -i /etc/kubernetes/admin.conf /home/vison/.kube/config
chown -R vison.vison /home/vison/.kube
# 查看版本信息
kubectl info
# 如果k8s服务端提示The connection to the server localhost:8080 was refused - did you specify the right host or port?出现这个问题的原因是kubectl命令需要使用kubernetes-admin来运行。
# 解决办法:
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source ~/.bash_profile
# 查看节点
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# master NotReady master 38m v1.11.3
# 发现主节点在notready状态,因为还没安装网络插件,列如:funnel
# 安装网络插件funnel,等待一会自动拉取镜像并启动
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 查看集群系统pods是否都在Running状态,如果都在Running状态,说明master节点启动完成。
kubectl get pods -n kube-system
# NAME READY STATUS RESTARTS AGE
# coredns-78fcdf6894-24v8q 1/1 Running 0 48m
# coredns-78fcdf6894-kkk9t 1/1 Running 0 48m
# etcd-master 1/1 Running 0 4m
# kube-apiserver-master 1/1 Running 0 4m
# kube-controller-manager-master 1/1 Running 0 4m
# kube-flannel-ds-amd64-g4q5v 1/1 Running 0 4m
# kube-proxy-hqsq5 1/1 Running 0 48m
# kube-scheduler-master 1/1 Running 0 4m
# 查看版本
kubectl version
# 查看集群信息
kubectl cluster-info
2.4 在node节点上加入集群
在node节点上加入集群很简单,直接执行master节点初始化时生成join命令即可。
# 忽略swap错误
echo 'KUBELET_EXTRA_ARGS="--fail-swap-on=false"' > /etc/sysconfig/kubelet
# 加入集群,需要等待一会拉取镜像并启动
kubeadm join 192.168.8.90:6443 --token fs5eos.m8p4pab3fxlefap5 --discovery-token-ca-cert-hash sha256:c353514a313f41ae9124e6cf5a45cfbd67e12e7762b28bbfe44538f07efba363 --ignore-preflight-errors=Swap
# 查看节点
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# master Ready master 13h v1.11.3
# node01 Ready <none> 12h v1.11.3
# node02 Ready <none> 12h v1.11.3
# 查看启动的镜像
docker ps
# CONTAINER ID IMAGE COMMAND NAMES
# d621966213ca f0fad859c909 "/opt/bin/flanneld..." k8s_kube-flannel_kube-flannel-ds-amd64...
# 589dc087efc9 d5c25579d0ff "/usr/local/bin/ku..." k8s_kube-proxy_kube-proxy-6l46n...
# 821e5a9a871f k8s.gcr.io/pause:3.1 "/pause" k8s_POD_kube-flannel-ds-amd64-b27mp...
# e5d792594a3d k8s.gcr.io/pause:3.1 "/pause" k8s_POD_kube-proxy-6l46n...
安装完成集群后清除yum安装aliyun的插件
# 修改插件配置文件
vim /etc/yum/pluginconf.d/fastestmirror.conf
# 把enabled=1改成0,禁用该插件
# 修改yum 配置文件
vim /etc/yum.conf
把plugins=1改为0,不使用插件
yum clean all
yum makecache
2.5 搭建集群遇到的问题
搭建集群时首先保证正常kubelet运行和开机启动,只有kubelet运行才有后面的初始化集群和加入集群操作。
查找启动kubelet失败原因:
# 查看启动状态
systemctl status kubelet
# 提示信息kubelet.service failed.
# 查看报错日志
tail /var/log/messages
# failed to run Kubelet: Running with swap on is not supported, please disable swap!
# 解决办法,忽略swap错误
echo 'KUBELET_EXTRA_ARGS="--fail-swap-on=false"' > /etc/sysconfig/kubelet
2.6 安装单节点k8s集群(minikube)
以下操作在windows下操作。
(1) 下载安装VirtualBox
(2) 下载kubectl (需要翻墙)
下载地址:https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/windows/amd64/kubectl.exe
例如使用1.13.0版本kubectl,把地址的1.10.0改为1.13.0去下载即可。
(3) 下载安装minikube
下载地址:https://github.com/kubernetes/minikube/releases/download/v0.30.0/minikube-installer.exe
下载完后点击安装minikube
(4) 启动minikube,安装指定版本的k8s(需要翻墙下载镜像),默认是v1.10.0,默认使用驱动是virtualbox。
minikube start –registry-mirror=https://registry.docker-cn.com –kubernetes-version v1.13.0
minikube工具会下载虚拟机和k8s的相关文件(minikube-v0.30.0.iso、kubeadm、kubelet),然后启动一个virtualbox虚拟机,虚拟机里自动下载安装k8s镜像,需要等待一段时间。
在等待过程中可以使用命令进入虚拟机,查看是否安装完毕。
# 查看镜像是否下载完毕
$ docker images
# REPOSITORY TAG IMAGE ID CREATED SIZE
# k8s.gcr.io/coredns 1.2.2 367cdc8433a4 3 months ago 39.2MB
# k8s.gcr.io/kubernetes-dashboard-amd64 v1.10.0 0dab2435c100 3 months ago 122MB
# k8s.gcr.io/kube-scheduler-amd64 v1.10.0 704ba848e69a 8 months ago 50.4MB
# k8s.gcr.io/kube-controller-manager-amd64 v1.10.0 ad86dbed1555 8 months ago 148MB
# k8s.gcr.io/kube-apiserver-amd64 v1.10.0 af20925d51a3 8 months ago 225MB
# k8s.gcr.io/etcd-amd64 3.1.12 52920ad46f5b 9 months ago 193MB
# k8s.gcr.io/kube-addon-manager v8.6 9c16409588eb 9 months ago 78.4MB
# k8s.gcr.io/pause-amd64 3.1 da86e6ba6ca1 11 months ago 742kB
# gcr.io/k8s-minikube/storage-provisioner v1.8.1 4689081edb10 13 months ago 80.8MB
# 如果镜像下载完毕,可以查看容器是否有启动失败
docker ps
# 如果出现dashboard或storage相关镜像启动失败,可以忽略,只是这两个插件不能使用,而且在minikube启动的时候会报下面错误,而且等待时间有点长,暂时也找不到原因是什么原因导致dashboard或storage容器总是重启(像是资源不够,k8s控制器强制把pod关闭)。
$ minikube.exe start
# Starting local Kubernetes v1.10.0 cluster...
# Starting VM...
# Getting VM IP address...
# Moving files into cluster...
# Setting up certs...
# Connecting to cluster...
# Setting up kubeconfig...
# Starting cluster components...
# E1207 09:45:14.637633 9276 start.go:302] Error restarting cluster: restarting kube-proxy: waiting for kube-proxy to be up for configmap update: timed out waiting for the condition
# ================================================================================
# An error has occurred. Would you like to opt in to sending anonymized crash
# information to minikube to help prevent future errors?
# To opt out of these messages, run the command:
# minikube config set WantReportErrorPrompt false
# ================================================================================
# Please enter your response [Y/n]:
到此为止,k8s安装基本完成,此时还有个关键步骤是,需要关闭代理软件或工具,否则kubectl连接失败,建议重启系统,然后启动minikube,
minikube start
(5) 基本操作命令
使用命令minikube –help查看有哪些功能。
# 启动minikube
minikube start
# 进入虚拟机
minikube ssh
# 关闭minikube
minikube stop
# 查看当前使用了那些插件
$ minikube addons list
# 查看kubectl是否正常连接
kubectl version
# Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.0", GitCommit:"fc32d2f3698e36b93322a3465f63a14e9f0eaead", GitTreeState:"clean", BuildDate:"2018-03-26T16:55:54Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"windows/amd64"}
# Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.0", GitCommit:"fc32d2f3698e36b93322a3465f63a14e9f0eaead", GitTreeState:"clean", BuildDate:"2018-03-26T16:44:10Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
# 查看集群信息
kubectl cluster-info
# Kubernetes master is running at https://192.168.99.100:8443
# To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
# 查看系统pod
$ kubectl get pod --all-namespaces
# NAMESPACE NAME READY STATUS RESTARTS AGE
# default nginx-deploy-585856bc9-h2xlt 1/1 Running 0 18m
# kube-system coredns-c4cffd6dc-zgfrb 1/1 Running 12 45m
# kube-system etcd-minikube 1/1 Running 0 26m
# kube-system kube-addon-manager-minikube 1/1 Running 1 47m
# kube-system kube-apiserver-minikube 1/1 Running 0 26m
# kube-system kube-controller-manager-minikube 1/1 Running 0 26m
# kube-system kube-scheduler-minikube 1/1 Running 1 46m
# kube-system kubernetes-dashboard-6f4cfc5d87-wtw6t 0/1 CrashLoopBackOff 15 45m
# kube-system storage-provisioner 0/1 CrashLoopBackOff 15 45m
3 kubectl基本操作
kubectl 主要是对pod、service、replicaset、deployment、statefulset、daemonset、job、cronjob、node资源的增删改查。
3.1 安装kubectl命令自动补全
# 安装kubectl自动补全命令包
yum install -y bash-completion
# 添加的当前shell
echo "source <(kubectl completion bash)" >> ~/.bashrc
source ~/.bashrc
3.2 kubectl run命令
kubectl run启动的是deployment、job等类型资源。
# 启动一个测试pod,退出pod自动删除
kubectl run ${RANDOM} --rm -it --image=cirros:0.4 -- /bin/sh
# CirrOS是一个很小的测试镜像,它经常用于测试OpenStack部署
# 在集群启动一个deployment类型的nginx服务
kubectl run nginx-deploy --image=nginx
# 查看deployment。
kubectl get deployments
# NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
# nginx-deploy 1 1 1 1 1m
# 查看pods,并显示在哪个node节点
kubectl get pods -o wide
# NAME READY STATUS RESTARTS AGE IP NODE
# nginx-deploy-59c86578c8-vqdqc 1/1 Running 0 1m 10.244.1.2 node01
# 在集群内部任意一个节点都可访问nginx,暂时外部不可访问
curl 10.244.1.2
# 这个nginx服务ip地址是不确定定的,假如删除了pod,重建了新的pod的Ip地址就变化了,为了使nginx服务ip地址固定,需要创建service资源,分配给deployment类型的nginx一个固定的虚拟ip地址
kubectl expose deployment nginx-deploy --name=nginx-service --port=80 --target-port=80
# 查看service信息,可以查看到固定的ip,删除pod或新建的pod的Ip地址虽然会变化,但service的ip不变,形成固定的访问端点
kubectl get service -o wide
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
# kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14h <none>
# nginx-service ClusterIP 10.102.228.39 <none> 80/TCP 2m run=nginx-deploy
# 在集群内任意一个节点访问nginx服务,此时集群外仍然不可访问
curl 10.102.228.39
# 在客户端上通过service名称直接访问,不需要知道service的ip地址。启动一个测试pod:
kubectl run ${RANDOM} --rm -it --image=cirros:0.4 -- /bin/sh
# 在容器里可以直接使用名称直接访问,即便删除service再重建,service的ip改变了,也不影响域名解析。
curl nginx-service
# 集群是怎样能通过名称直接访问的呢?
# 查看集群系统级别的service,有个域名解析服务,ip地址为10.96.0.10
kubectl get service -n kube-system
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 14h
# 在容器里查看域名解析
cat /etc/resolv.conf
# nameserver 10.96.0.10
# search default.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5
# 有了10.96.0.10和search后缀内容,在访问的域名不完整的时候,会把不完整的域名和后缀(/etc/resolv.conf文件search内容)拼接成为完整域名,通过完整的域名,可以解析service名称对应的ip地址了。
# 解析完整的域名
nslookup nginx-service.default.svc.cluster.local
# 通过service详情可以看出关联哪些pods
kubectl describe service nginx-service
# Name: nginx-service
# Namespace: default
# Labels: run=nginx-deploy
# Annotations: <none>
# Selector: run=nginx-deploy
# Type: ClusterIP
# IP: 10.102.228.39
# Port: <unset> 80/TCP
# TargetPort: 80/TCP
# Endpoints: 10.244.1.3:80
# Session Affinity: None
# Events: <none>
# 其中Labels和Selector标签选择器字段,在pods也有,就是通过selector关联和管理
# 查看pod标签
kubectl get pods --show-labels
# NAME READY STATUS RESTARTS AGE LABELS
# nginx-deploy-59c86578c8-2h8w7 1/1 Running 0 12m pod-template-hash=1574213474,run=nginx-deploy
# 删除原来service
kubectl delete service nginx-service
# 创建集群外可以访问nginx服务的service
kubectl expose deployment nginx-deploy --name=nginx-service --port=80 --target-port=80
# 查看端口映射
kubectl get service
# 在集群外访问nginx服务
curl masster:30193
curl node01:30193
curl node02:30193
3.3 动态缩放pod的数量和动态更新版本
# 启动一个测试pod
kubectl run myapp --image=ikubernetes/myapp:v1 --replicas=3
# 监控查看deployment类型的myapp是否创建完成
kubectl get deployments -w
# 查看pod
kubectl get pods -o wide
# NAME READY STATUS RESTARTS AGE IP NODE
# myapp-848b5b879b-5v5fz 1/1 Running 0 1m 10.244.2.4 node02
# myapp-848b5b879b-8prhr 1/1 Running 0 1m 10.244.1.4 node01
# myapp-848b5b879b-vhkcd 1/1 Running 0 1m 10.244.2.3 node02
# 创建service
kubectl expose deployment myapp --name=myapp --port=80 --target-port=80
# 查看service
kubectl get service | grep myapp
# 启动一个交互式busybody来测试
kubectl run bb01 --image=busybox -it
# 在交互式终端是输入下面命令,获取pod名称
while true; do wget -O - -q http://myapp/hostname.html; sleep 1; done;
# 从结果上看出,获取pod的名称是随机的,说明集群本身带有负载均衡。
# 动态扩展或缩小pod的数量
kubectl scale deployment myapp --replicas=5
# 动态更新版本
# 在busybody容器执行命令打印当前版本信息
while true; do wget -O - -q http://myapp; sleep 1; done;
# 更新镜像
kubectl set image deployment myapp myapp=ikubernetes/myapp:v2
# 查看更新过程
kubectl rollout status deployment myapp
# 查看pod,发现myapp的pod名称已经全部修改了
kubectl get pods
# 在busybody容器可以动态看到版本更新,也可以从deployment中查看当前镜像版本
kubectl get deployments -o wide
# 回滚旧版本
# 如果发现新版本有问题,可以回滚到上一个版本
kubectl rollout undo deployment myapp
# 查看回滚过程
kubectl rollout status deployment myapp
# 在busybody容器打印内容中可以动态看到版本回滚
4 kubernetes集群资源
4.1 资源分类
kubernetes的所有资源都可以抽象为对象,分为几大类:
- 工作负载(workload):Pod、ReplicaSet、Deployment、StatefulSet、DaemonSet、Job、Cronjob
- 服务发现和负载均衡:Service、Ingress
- 配置与存储:Volume、CSI、ConfigMap、Secret、DownwardAPI
- 集群级资源:Namespace、Node、Role、ClusterRole、RoleBinding、ClusterRoleBinding
- 元数据资源:HPA、PodTemplate、LimitRange
# 通过固定格式路径获取所有资源信息
/api/<GROUP>/<VERSION>/namespace/<NAMESPACE>/<TYPE>/<NAME>
# 使用命令查看路径
kubectl get deployment nginx-deploy -o yaml | grep selfLink
4.2 资源配置文件说明
查看资源的配置清单:
# yaml格式
kubectl get pod nginx-deploy-59c86578c8-2h8w7 -o yaml
# json格式
kubectl get pod nginx-deploy-59c86578c8-2h8w7 -o json
其实kubernetes集群的apiServer只能解析json格式定义的资源,master节点的apiserver会对非json格式定义的资源或命令统一转换为json格式,例如yaml格式提供的配置清单,apiserver会自动将其转换为json格式。
大部分资源配置清单由五大部分组成(一级字段):
名称 | 说明 |
---|---|
apiVersion | 指明创建的资源属于哪个api群组版本,使用命令kubectl api-versions查看当前有哪些群组版本。 |
kind | 资源类别,例如Deployment、Service等。 |
metadata | 元数据,字段name,同一类资源中,name字段保证唯一;字段labels,可以有多个标签。 |
spec | 资源规格,是用户期望的状态。 |
status | 当前资源状态,由kubernetes集群维护,对于用户为只读,不可修改 |
资源类型这么多,怎么知道那种资源有哪些字段?这些字段意义什么的?kubernetes提供了完整资源定义文档,例如要定义pod类型资源:
# 查看pod资源使用说明
kubectl explain pod
# 可以得知pod资源的属于哪个版本类型VERSION,并显示的是字段的说明,其中需要注意下字段的类型和是否标记为required字段,如果是required字段,是用户定义资源时必填字段。
# 查看下二级字段说明,例如查看spec使用说明
kubectl explain pod.spec
# 查看三级字段说明,例如查看spec下container使用说明
kubectl explain pod.spec.containers
# 如此类推,凡是字段类型为object,都可以通过逐级方式获取使用说明。
4.3 生成资源配置模版文件
用户提交命令给apiServer去创建资源,apiserver会把命令行转为json格式资源清单,用户可以拿这个资源清单来做模板,可以生成清单模板的资源如下:
名称 | 说明 |
---|---|
deployment | 使用指定的名称创建部署 |
service | 使用指定的子命令创建服务 |
configmap | 从本地文件,目录或文字值创建配置映射 |
secret | 使用指定的子命令创建密钥 |
clusterrole | 创建ClusterRole |
clusterrolebinding | 为特定ClusterRole创建ClusterRoleBinding |
job | 创建具有指定名称的作业 |
namespace | 创建具有指定名称的命名空间 |
poddisruptionbudget | 使用指定的名称创建pod中断预算 |
priorityclass | 使用指定的名称创建priorityclass |
quota | 创建具有指定名称的配额 |
role | 使用单个规则创建角色 |
rolebinding | 为特定Role或ClusterRole创建RoleBinding |
serviceaccount | 创建具有指定名称的服务帐户 |
创建资源模板的一些示例:
# 创建deployment资源模板
kubectl create deployment bb-dm --image=busyboxy --dry-run -o yaml > bb-dm.yml
# 创建sevice资源模板
kubectl create service clusterip bb-svc-cip --tcp=80:80 --dry-run -o yaml > bb-svc-cip.yml
# 创建serviceaccount资源模板
kubectl create serviceaccount vison --dry-run -o yaml > vison-sa.yml
5 pod资源
pod的生命周期:
- pod启动过程:用户提交的pod资源清单配置提交给apiserver,apiserver把资源清单存储在etcd当中,apiserver拿着资源配置清单给scheduler,scheduler根据资源配置清单分配资源,然后把调度结果(可以在哪个节点运行)保存到etcd中pod资源清单下status中。apiserver根据scheduler调度结果把把资源配置清单发送给对应节点的kubelet,kubelet根据资源配置清单启动pod,并把最终启动状态保存到etcd中pod资源清单下status,如果创建pod当前状态和目标状态不一致,kubelet会尽可能使其一致。
- pod状态:Pending、Running、successed、failed、Unknown。
- pod生命周期中的重要行为:初始化容器、liveness容器探测、readiness容器探测。
- pod的容器重启策略:用户可以资源配置清单spec下设置restartPolicy,共有三种策略:总是重启(默认)、不重启、错误下重启(正常结束不重启)。总是重启并不是真正意义马上重启,第一次立刻重启,第二次延时10秒,第三次延时20秒,第四次延时40秒,最大延时300秒。
- pod终止:当用户删除pod时,pod会发送终止信号给容器,让容器平滑关闭,避免数据丢失,如果pod等待30秒后,发现容器还没终止,会发送kill信号给容器,强行杀掉容器。
一般实际使用中很少使用自主创建pod的资源,都是pod控制器创建,例如Deployment、StatefulSet、job等。
5.1 创建一个Pod资源示例
创建pod资源清单配置文件pod-demo.yml,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: nginx-demo
# 标签,给选择器过滤
labels:
app: mynginx
# 注释,仅提供元数据
#annotations:
# key: value
spec:
containers:
- name: nginx
image: nginx
# 拉取镜像策略,存在则不重新拉取
imagePullPolicy: IfNotPresent
# 这里暴露端口只是信息说明,不能真正意义上的暴露端口
ports:
- name: http
containerPort: 80
# 这里命令不是在shell执行,如果要在shell上执行,在前面加/bin/sh -c
#command:["/bin/sh"]
#agrs:["-c", "while true; do echo hello; sleep 10;done"]
# 节点选择器
#nodeSelector:
# key: value
# 选择在哪个节点上运行
#nodeName: node01
当配置中使用command命令时,注意镜像中的Entrypoint、Cmd和资源配置中容器的command、agrs的关系,它们的关系如下图所示:
kubectl创建资源有几种用法:命令式用法、资源配置清单式用法,这里使用资源配置清单式用法。
# 创建资源
kubectl create -f pod-demo.yml
kubectl apply -f pod-demo.yml # 如果资源已创建,忽略,如果不存在,创建。
# 查看详情,详情最后Events是启动过程日志
kubectl describe -f pod-demo.yml
# 删除
kubectl delete -f pod-demo.yml
5.2 容器探测
容器探测分为就绪探测和存活性探测,两者都有三种探测类型ExecAction、HTTPGetAtion、TCPSocketAtion,根据需要使用一种。
创建容器存活探测资源配置文件pod-exec-live.yml,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec
spec:
containers:
- name: busybox
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "touch /tmp/healthy; sleep 100; rm -f /tmp/healthy; sleep 1000"]
livenessProbe:
# 探测方式exec
exec:
command: ["test", "-e", "/tmp/healthy"]
# 等待初始化时间
initialDelaySeconds: 3
# 探测间隔时间
periodSeconds: 10
从资源配置清单可以看出3次探测失败(30s)后重启容器。
为什么需要就绪性探测?有些时候虽然容器启动了,可能服务还没初始化化完成,在服务还没初始化完成情况下容器启动就马上对外提供服务,造成客户端访问出错,这时需要做服务就绪性探测,探测到服务完成准备完成就可以对外提供服务了。
创建容器的存活探测和就绪性探测的资源配置文件pod-httpget-live.yml,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget
spec:
containers:
- name: mynginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- name: indexfile
containerPort: 80
livenessProbe:
# 探测方式httpget
httpGet:
port: indexfile
path: /index.html
# 等待初始化时间
initialDelaySeconds: 3
# 探测间隔时间
periodSeconds: 10
# 就绪探测
readinessProbe:
# 探测方式httpget
httpGet:
port: indexfile
path: /50x.html
# 等待初始化时间
initialDelaySeconds: 3
# 探测间隔时间
periodSeconds: 3
检验存活性探测和就绪性是否有效:
# 进去容器
kubectl exec -it liveness-httpget -- /bin/bash
# 存活性探测测试
# 删除index.html
rm -f /usr/share/nginx/html/index.html
# 因为删除了index.html,探测肯定失败的,如果连续3次失败后能够重启容器,说明正常。
# 查看pod的重启次数
kubectl get pod
# 查看pod详情信息
kubectl describe -f pod-httpget-live.yml
# 就绪性探测测试
# 修改文件名
mv /usr/share/nginx/html/50x.html /usr/share/nginx/html/50x.html.bk
# 等待10s查看就绪情况,应该为0
kubectl get pod
# 恢复文件
mv /usr/share/nginx/html/50x.html.bk /usr/share/nginx/html/50x.html
# 再次查看就绪情况,就绪情况状态值马上恢复为1
kubectl get pod
5.3 标签选择器
给Pod资源定义标签作用是给Pod控制器分类管理,可以在命令行给资源添加标签,也可以在资源清单配置文件添加标签。
标签操作:
# 添加标签
kubectl label pods nginx-demo version=release
kubectl label -f pod-demo.yml version=release
# 显示标签
kubectl get pod --show-labels
# 更新标签
kubectl label -f pod-demo.yml version=release --overwrite
标签选择器:
# 等值标签选择器,只显示满足标签条件的资源
kubectl get pod -l app
kubectl get pod -l app=mynginx
kubectl get pod -l app=mynginx,version=stable
kubectl get pod -l app!=mynginx
# 集合关系选择器
kubectl get pod -l "version in (beta, stable, release)"
kubectl get pod -l "version notin (beta, stable, release)"
6 Pod控制器
Pod的控制器有:ReplicaSet、Deployment、StatefuleSet、DaemonSet、Job、Cronjob。
6.1 ReplicaSet资源
ReplicaSet资源是在Pod之上新创建的一层管理Pod的资源,支持动态伸缩Pod的数量,所以非常适合部署无状态服务;支持更新容器镜像版本,但是需要手动重启Pod中的容器才会使用最新版本镜像,已运行的pod中容器使用镜像版本不会更改。使用Deployment资源可以解决手动重启pod来更新版本问题。所以实际中使用ReplicaSet资源也不多。
创建ReplicaSet资源配置文件replicaSet-demo.yml,内容如下:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-rs
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
name: nginx-pod
# 注意:这里标签一定要包括上面自定义的selector标签
labels:
tier: frontend
app: myapp
# 下面就是pod的spec
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- name: nginx
containerPort: 80
6.2 Deployment资源
Deployment资源是在ReplicaSet之上新创建的一层用来管理ReplicaSet的资源,除了拥有ReplicaSet特性之外,还有自动更新版本、回滚、自定义更新策略功能。
创建Deployment资源配置文件deployment-demo.yml,内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-dm
# 下面是ReplicaSet的spec
spec:
replicas: 3
# 更新策略
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
tier: frontend
template:
metadata:
name: nginx-pod
# 注意:这里标签一定要包括上面自定义的selector标签
labels:
tier: frontend
app: myapp
# 下面就是pod的spec
spec:
containers:
- name: nginx
image: nginx:1.12.2
#imagePullPolicy: IfNotPresent
ports:
- name: nginx
containerPort: 80
测试动态扩容、更新镜像版本、回滚:
# 创建资源,这里使用apply替换create,apply可以执行多次,可以识别文件修改值,create只能执行一次。
kubectl apply -f deployment-demo.yml
# 修改配置方式有三种:
# (1) 修改资源配置文件示例:kubectl apply -f deployment-demo.yml
# (2) 打补丁方式示例:kubectl patch -f deployment-demo.yml -p '{"spec":{"replicas":5}}'
# (3) 在线编辑示例:kubectl edit -f deployment-demo.yml
# 动态扩容,扩容为5个pod运行
kubectl patch -f deployment-demo.yml -p '{"spec":{"replicas":5}}'
# 更新镜像版本
kubectl set image -f deployment-demo.yml nginx=nginx:1.15.2
# 回滚版本(默认是上一个版本)
kubectl rollout undo deployment nginx-dm
# 查看历史版本
kubectl rollout history deployment nginx-dm
# 回滚到指定版本
kubectl rollout undo deployment nginx-dm --to-revision=2
默认更新方式是滚动更新RollingUpdate,滚动更新策略是pod数量最少不能小于25%,最大不能超过25%,不足1个pod当作一个处理,如下图所示:
有时发布的新版本想在线上试运行一段时间,又不想让当前版本的所有pod都更新为最新版本,等新版本试运营一段时间没问题后,再把当前版本更新为最新版本。很明显自动滚动更新不能满足需求,需要用户改变滚动更新策略。
# 更新镜像时马上暂停,根据自定义更新策略,新添加一个pod,pod启动后暂停更新操作,让新版本运行一段时间。
kubectl set image -f deployment-demo.yml nginx=nginx:1.14.0 && kubectl rollout pause deployment nginx-dm
# 监控状态
kubectl rollout status deployment nginx-dm
kubectl get pod -o wide -w
# 确认新版本服务没问题后,继续更新剩余的pod
kubectl rollout resume deployment nginx-dm
6.3 DaemonSet资源
DaemonSet资源是在Pod之上新创建的一层用来管理Pod的资源,每个node节点都会运行一个守护进程,支持滚动更新,更新策略是先终止再启动新的Pod。也支持有限个节点上运行DaemonSet,DaemonSet的一些典型用法是:
- 在每个节点上运行集群存储守护程序,例如glusterd,ceph等。
- 在每个节点上运行日志收集守护程序,例如fluentd、logstash等。
- 在每个节点上运行节点监视守护程序,例如Prometheus Node Exporter,collectd等。
创建DaemonSet资源配置文件daemonSet-demo.yml,内容如下:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-ds
spec:
selector:
matchLabels:
app: mynginx
template:
metadata:
labels:
app: mynginx
spec:
containers:
- name: nginx
image: nginx:1.15.2
ports:
- name: nginx-port
containerPort: 80
6.4 StatefulSet资源
有些分布式集群(例如redis集群)的应用是有状态的,集群各个节点应用程序不能随便删除和创建,每个节点都有各自的状态,如果有pod挂了,必须要在原节点上重新启动pod,而且pod名字要一样,kubernetes集群的Deployment资源不能满足有状态程序的部署,可以用StatefulSet资源来部署有状态的应用程序,在kubernetes集群部署有状态的应用程序是比较麻烦的,需要关联的pv、pvc、headless service等资源,StatefulSet管理的Pod都有各自专用的pv和pvc,用来存储数据,关联headless service才能给每一个Pod固定的标识符,即使重启或删除Pod,Pod名称和在节点启动位置都不会改变,StatefulSet也支持滚动更新和伸缩扩容。
使用StatefulSet部署Pod的特点:
- 稳定且唯一的网络标识符
- 稳定且持久的存储
- 有序、平滑地部署和扩展
- 有序、平滑地删除和终止
- 有序的滚动更新
创建StatefulSet资源前,在集群外的虚拟机先准备3个挂nfs载点目录/data/volumes/v01、/data/volumes/v02、/data/volumes/v03。然后在集群上创建3个存储卷pv,具体配置文件看9.4节的pv资源创建示例。
# 在集群外的虚拟机上的三个挂载点目录下创建index.html文件给应用程序使用
echo '<h1> volume 01 data </h1>' > /data/volumes/v01/index.html
echo '<h1> volume 02 data </h1>' > /data/volumes/v02/index.html
echo '<h1> volume 03 data </h1>' > /data/volumes/v03/index.html
创建statefulSet资源配置文件statefulSet-demo.yml,配置文件中必须包含三个组件:headless service、StatefulSet、volumeClaimTemplate(存储卷申请模板),内容如下:
apiVersion: v1
kind: Service
metadata:
name: httpd-svc
spec:
selector:
app: httpd-pod
clusterIP: None
ports:
- name: httpd-ports
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: httpd-sts
spec:
serviceName: httpd-svc
replicas: 2
selector:
matchLabels:
app: httpd-pod
template:
metadata:
labels:
app: httpd-pod
spec:
containers:
- name: httpd
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c", "/bin/httpd -f -h /usr/share/web/"]
ports:
- name: httpd
containerPort: 80
volumeMounts:
- name: htmlfiles
mountPath: /usr/share/web/
# 为每个pod动态生成一个pvc,创建statefulSet之前必须先准备好pv
volumeClaimTemplates:
- metadata:
name: htmlfiles
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 2Gi
测试是否访问存储卷的index.html文件、重启、动态伸缩:
# 启动
kubectl apply -f statefulSet-demo.yml
# 查看pv
kubectl get pv
# NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIMAGE
# pv001 2Gi RWO,RWX Retain Bound default/htmlfiles-httpd-sts-0
# pv002 2Gi RWO,RWX Retain Bound default/htmlfiles-httpd-sts-1
# pv003 2Gi RWO,RWX Retain Available
# 查看pvc
kubectl get pvc
# NAME STATUS VOLUME CAPACITY ACCESS MODES
# htmlfiles-httpd-sts-0 Bound pv001 2Gi RWO,RWX
# htmlfiles-httpd-sts-1 Bound pv002 2Gi RWO,RWX
# 查看pod的ip地址
kubectl get pod -o wide
# NAME READY STATUS RESTARTS AGE IP NODE
# httpd-sts-0 1/1 Running 0 36s 10.244.1.66 node01
# httpd-sts-1 1/1 Running 0 34s 10.244.2.77 node02
# 测试访问是否正常
curl 10.244.1.66
# <h1> volume 01 data </h1>
curl 10.244.2.77
# <h1> volume 02 data </h1>
# 动态伸缩,把配置中replicas的值改为3,wq保存。
kubectl edit sts httpd-sts
# 查看扩展的pod是否正常运行
kubectl get pod -o wide
# NAME READY STATUS RESTARTS AGE IP NODE
# httpd-sts-0 1/1 Running 0 29m 10.244.1.66 node01
# httpd-sts-1 1/1 Running 0 29m 10.244.2.77 node02
# httpd-sts-2 1/1 Running 0 21s 10.244.1.67 node01
# 退出所有pod,然后重新重启,查看pod的名字、对应的存储卷、运行的node是否一致
kubectl delete -f statefulSet-demo.yml # pvc会保留,保证pod挂载存储卷不变。
kubectl apply -f statefulSet-demo.yml
# 查看pod的ip地址
get pod -o wide
# NAME READY STATUS RESTARTS AGE IP NODE
# httpd-sts-0 1/1 Running 0 17s 10.244.1.68 node01
# httpd-sts-1 1/1 Running 0 16s 10.244.2.78 node02
# 再次访问pod,数据也保持一致,说明pod退出前后的状态不变,启动和关闭pod都是有顺序的。
因为StatefulSet下的pod的名称是固定不变,可以通过pod的名称定位到ip地址,所以客户端通过名称就可以访问pod的服务,不需要知道pod的具体ip地址。
# pod完整域名格式:pod名称.service名称.名称空间.svc.cluster.local
# 示例:httpd-sts-0.httpd-svc.default.svc.cluster.local
# 启动一个测试pod
kubectl run ${RANDOM} --rm -it --image=cirros:0.4 -- /bin/sh
# 检验是否可以ping通pod
ping httpd-sts-0.httpd-svc.default.svc.cluster.local
6.5 job资源
job资源的容器是一次性任务,比如批处理程序,完成后容器就退出。
创建一个job资源配置文件myapp-job.yml,内容如下:
apiVersion: batch/v1
kind: Job
metadata:
name: myapp-job
spec:
# 并行执行job,默认是1,设置运行Pod数量,提高Job的执行效率
parallelism: 1
template:
metadata:
name: myapp-pod
spec:
# 重启策略,Never和OnFailure(程序出错,不会无限重启容器)
restartPolicy: OnFailure
containers:
- name: myapp
image: busybox
#imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "for i in $(seq 1 10); do echo $(date) $i;sleep 1; done"]
6.6 HPA资源
HPA全称Horizontal Pod Autoscaling,即pod的水平自动扩展,根据Pod当前系统的负载来自动水平扩容,如果系统负载超过预定值,就开始增加Pod的个数,如果低于某个值,就自动减少Pod的个数,HPA的v2版本除了根据CPU资源使用情况去度量系统的负载,还可以根据其他资源作为度量(例如内存、访问数)。HPA不属于pod控制,是元数据资源。
创建HPA资源配置文件hpa-demo.yml,内容如下:
# ---------------------- Deployment 资源 -------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-dm
spec:
replicas: 1
selector:
matchLabels:
app: nginx
tier: frontend
template:
metadata:
name: nginx-pod
labels:
app: nginx
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.15.2
ports:
- name: nginx
containerPort: 80
resources:
requests:
cpu: 1m
memory: 10Mi
limits:
cpu: 100m
memory: 100Mi
---
# ---------------------- Service资源 -------------------------
apiVersion: v1
kind: Service
metadata:
name: nginx-svc-np
spec:
selector:
app: nginx
tier: frontend
type: NodePort
ports:
- name: nginx-ports
port: 80
targetPort: 80
nodePort: 30080
---
# ---------------------- HPA 资源 -------------------------
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: nginx-hpa
labels:
project: nginx-pod
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx-dm
minReplicas: 1
maxReplicas: 10
# autoscaling/v1群组,根据CPU资源使用情况去度量
# targetCPUUtilizationPercentage: 66
# autoscaling/v2beta1群组,根据CPU、内存资源使用情况去度量
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 66
- type: Resource
resource:
name: memory
targetAverageValue: 66Mi
测试是否能够自动伸缩Pod:
# 安装压测工具ab
yum install -y httpd-tools
# 在master节点上压测
ab -c 10 -n 500000 http://master:30080/index.html
# 监控pod数量
kubectl get pod -w
# 查看hpa
kubectl describe hpa nginx-hpa
7 Service资源
因为Pod资源是有生命周期的,Pod的删除或新创建,ip地址会改变,为了给访问Pod的客户端一个固定的访问端点(ip:port),需要在客户端和Pod之间添加一层Service资源,Service的ip和端口固定的,Service资源依赖于安装集群时部署的coreDNS附件。
模型:userspace、iptable(默认)、ipvs(新版本支持ipvs,安装集群时要手动配置,系统也要求支持ipvs,如果不支持会降级为iptable)
Service分类:
名称 | 说明 |
---|---|
ClusterIP | 只在集群内部可达的私网地址,集群外部无法访问 |
NodePort | 通过节点端口映射使得集群外部可达,是在ClusterIP基础上添加一层节点端口映射,访问路径:集群外客户端–>节点ip:port–>ClusterIP:port–>PodIP:port |
LoadBalancer | 如果客户端只访问一个节点,会对该节点造成很大压力,一般在NodePort之前加入负载均衡,加入负载均衡器有两种方式:一是使用公有云的LBaaS,二是自己搭建负载均衡器 |
ExternalName | 当Pod客户端想访问集群之外的服务时,使用前几种类型Service是无法绕过集群直接访问外部服务的,使用ExternalName类型的主机名或域名映射方式可以和集群外通信 |
HeadLess | 特殊类型Service(无头服务),直接把服务名称映射到Pod的Ip上 |
kubernetes网络分为三类:node network、pod network、cluster network,前两种是真实存在的,而cluster network是虚拟的,仅用于Service资源。
Service工作模式:
在用户空间的Client Pod需要访问Server Pod时,需要到内核空间的Service IP中查找符合标签选择器的Server Pod的ip地址,拿到Server Pod真实ip地址后,经过overlay网络直接去访问对应Server Pod。当Server Pod的地址发生改变后,kube-apiserver会保存改变信息保存到etcd中,每个节点的kube-proxy监听到kube-apiserver有信息(ip地址)改变,kube-proxy会把改变后的ip地址同步到Service IP中,各个模块信息更新是同步的,使得Client Pod每次都能找到正确的Server Pod地址,相对于Client Pod来说,服务端点地址是固定的。而且Serice IP对同一类型Server Pod内置了负载均衡,如下图所示:
7.1 ClusterIP类型的Service资源
创建ClusterIP类型的Service资源配置文件service-clusterIP-demo.yml,这个Service资源关联使用Deployment创建的3个Pod,内容如下:
# ---------------------- Deployment资源 ----------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-dm
# 下面是ReplicaSet的spec
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
name: nginx-pod
# 注意:这里标签一定要包括上面自定义的selector标签
labels:
app: nginx
tier: frontend
# 下面就是pod的spec
spec:
containers:
- name: nginx
image: nginx:1.15.2
imagePullPolicy: IfNotPresent
ports:
- name: nginx
containerPort: 80
# 资源定义分割符
---
# ---------------------- Service资源 ----------------------
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
# 这里选择器要关联到哪些Pod资源
selector:
app: nginx
tier: frontend
type: ClusterIP
ports:
- name: nginx-ports
port: 80
targetPort: 80
测试Service是否关联Deployment下的3个Pod:
# 查看select是否匹配
kubectl get deployments -o wide
kubectl get pod --show-labels -o wide
kubectl get service -o wide
# 判断是否关联成功,从获取service中得到虚拟ip地址10.106.176.161,
curl 10.106.176.161
# service资源内置负载均衡器,每次访问都会随机访问到3个nginx服务中的一个。
7.2 NodePort类型的Service资源
NodePort类型是ClusterIp类型的增强版,是外部网络打通