Docker容器教程:https://blog.tag.gg/showinfo-3-36227-0.html
Kubernetes的核心概念:
K8s 功能:
(1)自动装箱
基于容器对应用运行环境的资源配置要求自动部署应用容器
(2)自我修复(自愈能力)
当容器失败时,会对容器进行重启
当所部署的 Node 节点有问题时,会对容器进行重新部署和重新调度
当容器未通过监控检查时,会关闭此容器直到容器正常运行时,才会对外提供服务
(3)水平扩展
通过简单的命令、用户 UI 界面或基于 CPU 等资源使用情况,对应用容器进行规模扩大
或规模剪裁
(3)服务发现
用户不需使用额外的服务发现机制,就能够基于 Kubernetes 自身能力实现服务发现和
负载均衡
(4)滚动更新
可以根据应用的变化,对应用容器运行的应用,进行一次性或批量式更新
(5)版本回退
可以根据应用部署情况,对应用容器运行的应用,进行历史版本即时回退
(6)密钥和配置管理
在不需要重新构建镜像的情况下,可以部署和更新密钥和应用配置,类似热部署。
(7)存储编排
自动实现存储系统挂载及应用,特别对有状态应用实现数据持久化非常重要
存储系统可以来自于本地目录、网络存储(NFS、Gluster、Ceph 等)、公共云存储服务
(8)批处理
提供一次性任务,定时任务;满足批量数据处理和分析的场景
1、什么是Pod:
答:
- Pod是最小部署单元,一个容器中可以有多个Pod。
- 是一组容器的集合
- 一个容器中的Pod是共享网络的。
- 生命周期是短暂的,比如重启服务器后重新部署了,之前的pod将丢失,会生成新的pod。
答:
- 可以确保逾期的Pod副本数量。
- 无状态及有状态应用部署
- 确保所有的node运行同一个pod。
- 一次性任务和定时任务。
那什么是无状态应用?
- 认为Pod都是一样的
- 没有顺序要求
- 不考虑应用在哪个node上运行
- 能够进行随意伸缩和扩展
有状态应用:
上述的因素都需要考虑到
- 让每个Pod独立的
- 让每个Pod独立的,保持Pod启动顺序和唯一性
- 唯一的网络标识符,持久存储
- 有序,比如mysql中的主从
适合StatefulSet的业务包括数据库服务MySQL 和 PostgreSQL,集群化管理服务Zookeeper、etcd等有状态服务
StatefulSet的另一种典型应用场景是作为一种比普通容器更稳定可靠的模拟虚拟机的机制。传统的虚拟机正是一种有状态的宠物,运维人员需要不断地维护它,容器刚开始流行时,我们用容器来模拟虚拟机使用,所有状态都保存在容器里,而这已被证明是非常不安全、不可靠的。
使用StatefulSet,Pod仍然可以通过漂移到不同节点提供高可用,而存储也可以通过外挂的存储来提供 高可靠性,StatefulSet做的只是将确定的Pod与确定的存储关联起来保证状态的连续性。
3、什么是Service答:
- 定义一组Pod的访问规则
搭建K8S集群:
准备工作:
1、搭建K8S环境平台规划
单Master集群:多个node节点,只有一个Master节点。
多Master集群:多个node节点,多个Master节点,中间通过负载均衡调度。(高可用)
本次将先搭建单Master集群,后面根据情况搭建多Master集群。
2、服务器配置要求
测试环境:Master节点建议2核+4G节点以上。node节点建议4核+8G+50G以上硬盘。
生成环境:配置越高越好。
3、搭建K8S集群的部署方式
两种搭建方式:
kubeadm:Kubeadm 是一个 K8s 部署工具,提供 kubeadm init 和 kubeadm join,用于快速部署 Kubernetes 集群。
二进制:从 github 下载发行版的二进制包,手动部署每个组件,组成 Kubernetes 集群。
Kubeadm 降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。如果想更容易可控,推荐使用二进制包部署 Kubernetes 集群,虽然手动部署麻烦点,期间可以学习很多工作原理,也利于后期维护。
kubeadm部署方式介绍
安装要求
在开始之前,部署 Kubernetes 集群机器需要满足以下几个条件:
- 一台或多台机器,操作系统 CentOS7.x-86_x64
- 硬件配置:2GB 或更多 RAM,2 个 CPU 或更多 CPU,硬盘 30GB 或更多
- 集群中所有机器之间网络互通
- 可以访问外网,需要拉取镜像
- 禁止 swap 分区
系统初始化
关闭防火墙:
关闭 selinux:systemctl stop firewalld && systemctl disable firewalld
sed -i 's/enforcing/disabled/' /etc/selinux/config
# 永久
关闭 swap:setenforce 0 # 临时
主机名:swapoff -a # 临时
vim /etc/fstab #将swap相关的挂载注释
在 master 添加 hosts:hostnamectl set-hostname <hostname>
在master和node节点中将桥接的 IPv4 流量传递到 iptables 的链:cat >> /etc/hosts << EOF
172.19.81.11 k8s-master
172.19.81.12 k8s-node1
172.19.81.13 k8s-node2
EOF
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
时间同步:sysctl --system # 生效
yum install ntpdate -y && ntpdate time.windows.com
所有节点都安装Docker/kubeadm/kubelet
kubernetes默认CRI(容器运行时)为Docker,因此先安装Docker。
1、所有节点安装Docker
2、所有节点添加阿里云 YUM 软件源wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
sudo yum install -y docker-ce docker-ce-cli containerd.io
systemctl enable docker && systemctl start docker
docker --version
设置仓库地址
所有节点添加 yum 源cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF
所有节点安装 kubeadm,kubelet 和 kubectlcat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
默认安装的是最新版
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet
如果新版出现:
[kubelet-check] Initial timeout of 40s passed.报错,则可卸载最新版安装如下老版本试下。(本人就出现了这个问题,换了版本后解决)
yum install -y kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6 && systemctl enable kubelet
查看版本号:
启动kubeletkubelet --version
kubectl version
kubeadm version
3、部署 Kubernetes Mastersystemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet
在 172.19.81.11(Master)执行
由于默认拉取镜像地址 k8s.gcr.io 国内无法访问,这里指定阿里云镜像仓库地址。kubeadm init \
--apiserver-advertise-address=172.19.81.11 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.23.6 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16
安装完成maser节点会显示如下信息则表示正常安装。
如果安装过程中遇到问题,可以参考后面报错说明Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 172.19.81.11:6443 --token 2wbu5k.a1eie02nqo4zmhh0 \
--discovery-token-ca-cert-hash sha256:e7977da44729f54ed2e8223827a2eda24c4a9c315704a56d4554bc0b5efbf77b
如果使用 kubectl 工具,则执行如下命令(命令在安装好后会显示,可参考上面信息)(只在master上执行)
查看节点:mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
执行结果:kubectl get nodes
4、向集群添加新节点,执行在 kubeadm init 输出的 kubeadm join 命令(在node上执行)[root@blog.tag.gg-k8s-master lib]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master NotReady control-plane,master 21m v1.23.6
输出如下结果表示正常kubeadm join 172.19.81.11:6443 --token 2wbu5k.a1eie02nqo4zmhh0 \
--discovery-token-ca-cert-hash sha256:e7977da44729f54ed2e8223827a2eda24c4a9c315704a56d4554bc0b5efbf77b
此时在master节点执行如下命令会显示加入的节点:[root@blog.tag.gg-k8s-node2 ~]# kubeadm join 172.19.81.11:6443 --token 2wbu5k.a1eie02nqo4zmhh0 \
> --discovery-token-ca-cert-hash sha256:e7977da44729f54ed2e8223827a2eda24c4a9c315704a56d4554bc0b5efbf77b
[preflight] Running pre-flight checks
[WARNING Hostname]: hostname "k8s-node2" could not be reached
[WARNING Hostname]: hostname "k8s-node2": lookup k8s-node2 on 114.114.114.114:53: no such host
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
执行结果:(NotReady未就绪)kubectl get nodes
5、部署CNI网络插件:(master节点)[root@blog.tag.gg-k8s-master lib]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master NotReady control-plane,master 30m v1.23.6
k8s-node1 NotReady <none> 5m40s v1.23.6
k8s-node2 NotReady <none> 5m41s v1.23.6
执行命令:
该地址在海外,可能无法访问,届时可以用ping方法看其他节点然后hosts解析。kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
执行结果:
执行如下命令查看是否正常:[root@blog.tag.gg-k8s-master lib]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
namespace/kube-flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
返回如下则表示正常了(Running状态)kubectl get pods -n kube-system
执行如下命令:[root@blog.tag.gg-k8s-master lib]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-6d8c4cb4d-lddvj 1/1 Running 0 42m
coredns-6d8c4cb4d-tsstd 1/1 Running 0 42m
etcd-k8s-master 1/1 Running 1 (43m ago) 42m
kube-apiserver-k8s-master 1/1 Running 1 (44m ago) 42m
kube-controller-manager-k8s-master 1/1 Running 1 (44m ago) 42m
kube-proxy-fjdc6 1/1 Running 0 17m
kube-proxy-skgdv 1/1 Running 0 17m
kube-proxy-tdwsw 1/1 Running 0 42m
kube-scheduler-k8s-master 1/1 Running 1 (44m ago) 42m
返回结果:显示Ready则表示正常准备好了。可能需要等待几十秒或几分钟。kubectl get nodes
至此,k8s集群搭建完成。[root@blog.-tag.gg-k8s-master lib]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane,master 46m v1.23.6
k8s-node1 Ready <none> 21m v1.23.6
k8s-node2 Ready <none> 21m v1.23.6
6、测试K8s集群是否正常。
在k8s集群中创建一个pod,验证是否运行正常。
1、拉取一个nignx镜像:
返回结果:kubectl create deployment nginx --image=nginx
此时可以使用如下命令查看拉取情况。[root@blog.tag.gg-k8s-master lib]# kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
显示如下:显示Running 则表示拉取完成kubectl get pod
2、对外暴露80端口使其可以访问。[root@blog.tag.gg-k8s-master lib]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-85b98978db-mfks4 1/1 Running 0 59s
执行结果:表示执行成功。kubectl expose deployment nginx --port=80 --type=NodePort
3、执行如下命令查看pod的情况以及端口等信息[root@blog.tag.gg-k8s-master lib]# kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed
执行如下:kubectl get pod,svc
测试方法:[root@blog.tag.gg-k8s-master lib]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/nginx-85b98978db-mfks4 1/1 Running 0 3m35s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 55m
service/nginx NodePort 10.110.177.174 <none> 80:32588/TCP 77s
node节点ip+端口号,例如如上:可以使用http://172.19.81.13:32588/ 或者 http://172.19.81.12:32588/ 访问显示nginx的默认页面则表示部署成功。
安装过程中常见问题:
1、在master上初始化集群失败报错“[kubelet-check] Initial timeout of 40s passed.”
解决方法:查找了一下资料是说k8s版本太高,已经不支持docker导致,重新安装k8s低版本的,可执行如下命令卸载后并重新安装:
注意:卸载前请务必核实是否有数据,建议做好备份或做好快快照操作。
若是生产环境,不建议轻易操作。
卸载K8s:
重新在所有节点安装k8s低版本:yum remove -y kubelet kubeadm kubectl
kubeadm reset -f
modprobe -r ipip
lsmod
rm -rf ~/.kube/
rm -rf /etc/kubernetes/
rm -rf /etc/systemd/system/kubelet.service.d
rm -rf /etc/systemd/system/kubelet.service
rm -rf /usr/bin/kube*
rm -rf /etc/cni
rm -rf /opt/cni
rm -rf /var/lib/etcd
rm -rf /var/etcd
2、master初始化集群报错“The kubelet is not running”。yum install -y kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6
systemctl enable kubelet
原因:kubelet没启动,尝试执行命令service kubelet start启动但失败。
解决方法:
1、执行如下命令看具体启动失败原因:
输出:journalctl -xeu kubelet | grep Failed
编辑:vi /etc/docker/daemon.json文件,在大括号内增加如下:[root@blog.tag.gg-k8s-master ~]# journalctl -xeu kubelet | grep Failed
1月 07 17:07:41 k8s-master kubelet[17877]: E0107 17:07:41.164885 17877 server.go:302] "Failed to run kubelet" err="failed to run Kubelet: misconfiguration: kubelet cgroup driver: \"systemd\" is different from docker cgroup driver: \"cgroupfs\""
添加后如下:(注意是否有中文符号,否则docker将启动失败,本人为了一个符号折腾了1小时),
"exec-opts": ["native.cgroupdriver=systemd"]
重启docker:{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
重启k8s:sudo systemctl daemon-reload && sudo systemctl restart docker
systemctl daemon-reload && systemctl restart kubelet && netstat -lunpt
报错:The connection to the server localhost:8080 was refused - did you specify the right host or port?
原因是在node节点上执行了命令,是需要在master节点执行才可以。
采用二进制搭建K8s集群方法:
1、创建多台虚拟机(已创建略过)
2、系统初始化:
初始化方法可参考上面教程。
3、为etcd和apiserver自签证书
准备 cfssl 证书生成工具
cfssl 是一个开源的证书管理工具,使用 json 文件生成证书,相比 openssl 更方便使用。
找任意一台服务器操作,这里用 Master 节点。
下载很慢,甚至可能下载不了,可以ping其他节点ip然后hosts解析。
生成 Etcd 证书wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
自签证书颁发机构(CA)
创建工作目录:
自签 CA:mkdir -p ~/TLS/{etcd,k8s}
cd TLS/etcd
cat > ca-config.json<< EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"www": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
生成证书:cat > ca-csr.json<< EOF
{
"CN": "etcd CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing"
}
]
}
EOF
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
执行结果如下:ls *pem
ca-key.pem ca.pem
[root@master etcd]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
2023/03/21 20:58:58 [INFO] generating a new CA key and certificate from CSR
2023/03/21 20:58:58 [INFO] generate received request
2023/03/21 20:58:58 [INFO] received CSR
2023/03/21 20:58:58 [INFO] generating key: rsa-2048
2023/03/21 20:58:58 [INFO] encoded CSR
2023/03/21 20:58:58 [INFO] signed certificate with serial number 14951914944477411348481876419999757812811653542
使用自签 CA 签发 Etcd HTTPS 证书[root@master etcd]# ll
总用量 20
-rw-r--r--. 1 root root 175 3月 21 20:58 ca-config.json
-rw-r--r--. 1 root root 956 3月 21 20:58 ca.csr
-rw-r--r--. 1 root root 121 3月 21 20:58 ca-csr.json
-rw-------. 1 root root 1679 3月 21 20:58 ca-key.pem
-rw-r--r--. 1 root root 1265 3月 21 20:58 ca.pem
[root@master etcd]# ls *pem
ca-key.pem ca.pem
创建证书申请文件:
注:上述文件 hosts 字段中 IP 为所有 etcd 节点的集群内部通信 IP,一个都不能少!为了cat > server-csr.json<< EOF
{
"CN": "etcd",
"hosts": [
"172.22.139.11",
"172.22.139.22",
"172.22.139.33"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
EOF
方便后期扩容可以多写几个预留的 IP。
生成证书:
执行后如下:cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server
从 Github 下载二进制文件[root@master etcd]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server
2023/03/21 21:04:23 [INFO] generate received request
2023/03/21 21:04:23 [INFO] received CSR
2023/03/21 21:04:23 [INFO] generating key: rsa-2048
2023/03/21 21:04:23 [INFO] encoded CSR
2023/03/21 21:04:23 [INFO] signed certificate with serial number 551743223946492829929705690629601704728862091398
2023/03/21 21:04:23 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
wget https://github.com/etcd-io/etcd/releases/download/v3.4.9/etcd-v3.4.9-linux-amd64.tar.gz
4、部署etcd集群
5、部署master组件
需安装组件:kube-apiserver、kube-controller-manager、kube-scheduler、etcd
6、部署node组件
需安装组件:kubelet、kube-proxy、docker、etcd
7、部署集群网络插件
kubernetes集群命令行工具kubectl
1、kubectl概述:
kubectl 是 Kubernetes 集群的命令行工具,通过 kubectl 能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。
2、kubectl 命令的语法
(1)comand:指定要对资源执行的操作,例如 create、get、describe 和 deletekubectl [command] [type] [name] [flags]
(2)TYPE:指定资源类型,资源类型是大小写敏感的,开发者能够以单数、复数和缩略的
形式。例如:
执行结果:kubectl get pod pod1
kubectl get pods pod1
kubectl get po pod1
(3)NAME:指定资源的名称,名称也大小写敏感的。如果省略名称,则会显示所有的资源,
例如:
kubectl get pods
flags:指定可选的参数。例如,可用-s 或者–server 参数指定 Kubernetes APIserver 的地址和端口。[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-85b98978db-nh2m4 1/1 Running 0 45h
kubectl help 获取更多信息
命令:
Kubectl 子命令使用分类kubectl --help
详细命令可参考:https://blog.csdn.net/freellf/article/details/128343111
基础命令 |
create |
通过文件名或标准办输入创建资源 |
expose |
将一个资源公开为一个新的Service |
|
run |
在集群中运行一个特定的镜像 |
|
set |
在对象上设置特定的镜像 |
|
get |
显示一个或多个资源 |
|
explain |
文档参考资料 |
|
edit |
使用默认的编辑器编辑一个资源 |
|
delete |
通过文件名、标准输入、资源名称或标签选择器来删除资源 |
|
部署命令 |
rollout |
管理资源的发布 |
rolling-update |
对给定的复制控制器滚动更新 |
|
scale |
扩容或缩容Pod数时,Deployment、ReplicaSet、RC或Job |
|
autoacale |
创建一个自动选择扩容或缩容并设置Pod数量 |
|
集群管理命令 |
certificate |
修改证书资源 |
cluster-info |
显示集群信息 |
|
top |
显示资源(CPU/Memory/Storage)使用。需要Heapster运行 |
|
cordon |
标记节点不可调度 |
|
uncordon |
标记节点可调度 |
|
drain |
驱逐节点上的应用,准备下线维护 |
|
taint |
修改节点taint标记 |
|
故障诊断和调试命令 |
describe |
显示特定资源或资源组的详细信息 |
logs |
在一个Pod中打印一个容器日志,如果Pod只有一个容器,容器名称是可选的 |
|
attach |
附加到一个运行的容器 |
|
exec |
执行命令到容器 |
|
port-forward |
转发一个或多个本地端口到一个pod |
|
proxy |
运行一个proxy到Kubernetes API server |
|
cp |
拷贝文件或目录到容器中 |
|
auth |
检查授权 |
|
高级命令 |
apply |
通过文件名或标准输入对资源应用配置 |
patch |
使用补丁修改、更新资源的字段 |
|
replace |
通过文件名或标准输入替换一个资源 |
|
convert |
不同的API版本之间转换配置文件 |
设置命令 |
label |
更新资源上的标签 |
annotate |
更新资源上的注解 |
|
completion |
用于实现kubectl工具自动补全 |
|
其他命令 |
api-versions |
打印受支持的API版本 |
config |
修改kubeconfig文件(用于访问API, 比如配置认证信息) |
|
help |
所用命令帮助 |
|
plugin |
运行一个命令行插件 |
|
version |
打印客户端和服务版本信息 |
kubernetes 集群 YAML 文件详
1、YAML 文件概述
k8s 集群中对资源管理和资源对象编排部署都可以通过声明样式(YAML)文件来解决,也就是可以把需要对资源对象操作编辑到 YAML 格式文件中,我们把这种文件叫做资源清单文件(或资源编排),通过 kubectl 命令直接使用资源清单文件就可以实现对大量的资源对象进行编排部署
了。
2、YAML 文件书写格式
(1)YAML 介绍
YAML :仍是一种标记语言。为了强调这种语言以数据做为中心,而不是以标记语言为重点。
YAML 是一个可读性高,用来表达数据序列的格式。
(2)YAML 基本语法
* 使用空格做为缩进
* 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
* 低版本缩进时不允许使用 Tab 键,只允许使用空格
* 使用#标识注释,从这个字符一直到行尾,都会被解释器忽略
*一般开头缩进两个空格
*字符后缩进一个空格,比如冒号和逗号后面都需要空格。
*使用“---”表示新的yaml文件开始。
*使用“#”表示注释。
(3)YAML 文件组成部分
一个简单的nginx的yaml文件:
另一个版本的详细说明:apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
name: nginx
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: harbor.xxx.cn/official_hub/nginx:1.13-alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
其中,红色部分表示“控制器定义”(要控制那些事),蓝色部分是“被控制对象”( 控制的具体的事 )。apiVersion: apps/v1 #与k8s集群版本有关,使用 kubectl api-versions 即可查看当前集群支持的版本
kind: Deployment #该配置的类型,我们使用的是 Deployment
metadata: #译名为元数据,即 Deployment 的一些基本属性和信息
name: nginx-deployment #Deployment 的名称
labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组,目前不需要理解
app: nginx #为该Deployment设置key为app,value为nginx的标签
spec: #这是关于该Deployment的描述,可以理解为你期待该Deployment在k8s中如何使用
replicas: 1 #使用该Deployment创建一个应用程序实例
selector: #标签选择器,与上面的标签共同作用,目前不需要理解
matchLabels: #选择包含标签app:nginx的资源
app: nginx
template: #这是选择或创建的Pod的模板
metadata: #Pod的元数据
labels: #Pod的标签,上面的selector即选择包含标签app:nginx的Pod
app: nginx
spec: #期望Pod实现的功能(即在pod中部署)
containers: #生成container,与docker中的container是同一种
- name: nginx #container的名称
image: nginx:1.7.9 #使用镜像nginx:1.7.9创建container,该container默认80端口可访问
常用字段含义
参数名 | 字段类型 | 说明 |
version | string | k8s api的版本号,目前是v1,可以通过kubectl api-version查看 |
kind | string | 指定资源类型,例如Pod,Deployment,Service等 |
metadata | object | 自定义metadata |
metadata.name | string | 对象名字,用户自定义 |
metadata.namespace | string | 对象的命名空间,用户自定义 |
spec | Object | 对象的详细信息 |
spc.restartPolicy | string |
pod重启策略 Always:pod一旦退出就要进行重启 OnFailure:只有非正常退出才进行重启 Nerver:退出后不再拉起 |
spec.hostNetwork | bool |
是否使用主机网络,默认值false 设置为true,表示与主机在同一个网络空间 |
spec.nodeSelector | object | 标签选择器,k-v形式 |
spec.containers[] | list | 容器对象列表 |
spec.containers[].name | string | 容器的名称 |
spec.containers[].image | string | 容器使用的镜像 |
spec.containers[].imagePullPolicy | string |
Always:每次都重新下载 IfNotPresent:如果本地存在则使用本地镜像,不重新拉取 Never:表示仅使用本地镜像 |
spec.containers[].command[] | list | 指定容器启动命令,可以是多个命令,如果不指定则使用镜像中启动命令 |
spec.containers[].args[] | list | 启动命令参数,可以多个 |
spec.containers[].workingDir | string | 容器的工作目录 |
spec.containers[].volumeMounts[] | list | 指定容器的挂在卷,可以多个 |
spec.containers[].volumeMounts[].name | string | 挂在卷名称 |
spec.containers[].volumeMounts[].mountPath | string | 挂在卷路径 |
spec.containers[].volumeMounts[].readOnly | bool | 读写模式,true只读(默认值),false读写 |
spec.containers[].ports[] | list | 容器用到端口 |
spec.containers[].ports[].name | string | 端口名称 |
spec.containers[].ports[].containerPort | number | 端口号 |
spec.containers[].ports[].hostPort | number | 指定host主机使用端口。主要适用于端口映射,默认值是和容器内端口相同 |
spec.containers[].ports[].protocol | string | 监听协议,tcp、udp,默认是tcp |
spec.containers[].env[] | list | 容器的环境变量列表 |
spec.containers[].env[].name | string | 环境变量name |
spec.containers[].env[].value | string | 环境变量value |
spec.containers[].resources | object | 用于设置资源限制和资源请求 |
spec.containers[].resources.limits | object | 设置资源上限 |
spec.containers[].resources.limits.cpu | string | 对cpu的限制,k8s将一个逻辑cpu划分成1000个millicore(毫核)。例如 limits.cpu=500m相当于0.5个cpu。 limits.cpu=2表示占用2个cpu |
spec.containers[].resources.limits.memory | string | 对内存的限制 |
spec.containers[].resources.requests | object | 容器启动和调度是的限制设置 |
spec.containers[].resources.requests.cpu | string | 对cpu的限制,k8s将一个逻辑cpu划分成1000个millicore(毫核)。例如 limits.cpu=500m相当于0.5个cpu。 limits.cpu=2表示占用2个cpu |
spec.containers[].resources.requests.memory | string | 对内存的限制 |
kind种类:
kind种类:
分类 | 说明 | 其他 |
Pod | k8s最基本管理单元 | |
ReplicationController(RC) |
副本控制器,用于控制Pod副本数,目前官方不建议使用 | 保证副本数,始终为用户指定数目 |
ReplicaSet(RS) |
是RC的升级版本,比RC多了一个选择器,其他都一样。 | 保证副本数,始终为用户指定数目,不能动态扩缩容 |
Deployment | 支持动态扩缩容,滚动升级,版本回滚,RS不支持 | |
DeamonSet | 确保全部或部分Node 上运行一个 Pod 的副本 | 例如:要求每个node上都有监控系统,日志系统等 |
Job | 执行脚本,linux命令等 | 适用于批处理任务 |
CronJob | 定时执行脚本,linux命令等 | 定时批处理任务 |
Service | 提供负载均衡和服务自动发现,底层通过EndPoint实现 | |
EndPoints | pod名字和ip映射关系集合,支撑Service | |
ConfigMap | 配置集合,用于给pod/容器传递参数 | 1、 将环境变量直接定义在configMap中,当Pod启动时,通过env来引用configMap中定义的环境变量。 2、 将一个完整配置文件封装到configMap中,然后通过共享卷的方式挂载到Pod中,实现给应用传参。 |
举例
这个例子摘自其他网友
如何快速编写yaml文件:apiVersion: v1 #指定api版本,此值必须在kubectl apiversion中
kind: Pod #指定创建资源的角色/类型
metadata: #资源的元数据/属性
name: web04-pod #资源的名字,在同一个namespace中必须唯一
labels: #设定资源的标签,详情请见http://blog.csdn.net/liyingke112/article/details/77482384
k8s-app: apache
version: v1
kubernetes.io/cluster-service: "true"
annotations: #自定义注解列表
- name: String #自定义注解名字
spec: #specification of the resource content 指定该资源的内容
restartPolicy: Always #表明该容器一直运行,默认k8s的策略,在此容器退出后,会立即创建一个相同的容器
nodeSelector: #节点选择,先给主机打标签kubectl label nodes kube-node1 zone=node1
zone: node1
containers:
- name: web04-pod #容器的名字
image: web:apache #容器使用的镜像地址
imagePullPolicy: Never #三个选择Always、Never、IfNotPresent,每次启动时检查和更新(从registery)images的策略,
# Always,每次都检查
# Never,每次都不检查(不管本地是否有)
# IfNotPresent,如果本地有就不检查,如果没有就拉取
command: ['sh'] #启动容器的运行命令,将覆盖容器中的Entrypoint,对应Dockefile中的ENTRYPOINT
args: ["$(str)"] #启动容器的命令参数,对应Dockerfile中CMD参数
env: #指定容器中的环境变量
- name: str #变量的名字
value: "/etc/run.sh" #变量的值
resources: #资源管理,请求请见http://blog.csdn.net/liyingke112/article/details/77452630
requests: #容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行
cpu: 0.1 #CPU资源(核数),两种方式,浮点数或者是整数+m,0.1=100m,最少值为0.001核(1m)
memory: 32Mi #内存使用量
limits: #资源限制
cpu: 0.5
memory: 32Mi
ports:
- containerPort: 80 #容器开发对外的端口
name: httpd #名称
protocol: TCP
livenessProbe: #pod内容器健康检查的设置,详情请见http://blog.csdn.net/liyingke112/article/details/77531584
httpGet: #通过httpget检查健康,返回200-399之间,则认为容器正常
path: / #URI地址
port: 80
#host: 127.0.0.1 #主机地址
scheme: HTTP
initialDelaySeconds: 180 #表明第一次检测在容器启动后多长时间后开始
timeoutSeconds: 5 #检测的超时时间
periodSeconds: 15 #检查间隔时间
#也可以用这种方法
#exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常
# command:
# - cat
# - /tmp/health
#也可以用这种方法
#tcpSocket: //通过tcpSocket检查健康
# port: number
lifecycle: #生命周期管理
postStart: #容器运行之前运行的任务
exec:
command:
- 'sh'
- 'yum upgrade -y'
preStop:#容器关闭之前运行的任务
exec:
command: ['service httpd stop']
volumeMounts: #详情请见http://blog.csdn.net/liyingke112/article/details/76577520
- name: volume #挂载设备的名字,与volumes[*].name 需要对应
mountPath: /data #挂载到容器的某个路径下
readOnly: True
volumes: #定义一组挂载设备
- name: volume #定义一个挂载设备的名字
#meptyDir: {}
hostPath:
path: /opt #挂载设备类型为hostPath,路径为宿主机下的/opt,这里设备类型支持很多种
1、使用kubectl create 命令生产yaml文件,然后根据生产的文件修改。(一般用于还没部署情况)
不真正运行,只是输出yaml文件。
命令范例:
说明,生产一个nginx的,名称为web,-o yaml 是生成yaml文件,--dry-run是尝试运行(不是真正运行,只输出yaml文件)。kubectl create deployment web --image=nginx -o yaml --dry-run
执行结果如下:
也可以将生成的yaml文件输出到文件。[root@master ~]# kubectl create deployment web --image=nginx -o yaml --dry-run
W0323 15:20:01.966640 584 helpers.go:598] --dry-run is deprecated and can be replaced with --dry-run=client.
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}
[root@master ~]#
输出结果:kubectl create deployment web --image=nginx -o yaml --dry-run > blog.tag.gg.yaml
2、使用kubectl get 命令从部署好的项目中导出yaml文件。[root@master ~]# kubectl create deployment web --image=nginx -o yaml --dry-run > blog.tag.gg.yaml
W0323 15:22:30.634903 1788 helpers.go:598] --dry-run is deprecated and can be replaced with --dry-run=client.
[root@master ~]# ll
总用量 8
-rw-------. 1 root root 1322 3月 20 20:07 anaconda-ks.cfg
-rw-r--r-- 1 root root 376 3月 23 15:22 blog.tag.gg.yaml
查看已部署的项目:
执行结果:kubectl get deploy
有运行一个nginx,我们将nginx的yaml文件导出。[root@master ~]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 1/1 1 1 47h
执行结果:kubectl get deploy nginx -o=yaml
将导出的yaml文件放到指定文件:[root@master ~]# kubectl get deploy nginx -o=yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2023-03-21T07:33:46Z"
generation: 1
labels:
app: nginx
name: nginx
namespace: default
resourceVersion: "1255"
uid: e91408dd-7e3e-4961-aa7a-0b3fa7b4e5b6
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 1
conditions:
- lastTransitionTime: "2023-03-21T07:34:14Z"
lastUpdateTime: "2023-03-21T07:34:14Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2023-03-21T07:33:46Z"
lastUpdateTime: "2023-03-21T07:34:14Z"
message: ReplicaSet "nginx-85b98978db" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 1
replicas: 1
updatedReplicas: 1
[root@master ~]#
执行后出现下面错误。kubectl get deploy nginx -o=yaml --export > blog.tag.ggs.yaml
原因:原因是 --export在所使用的版本中已经被去除了,将--export删除即可。error: unknown flag: --export
See 'kubectl get --help' for usage.
执行后没有任何提示则表示正常,可以打开生成的blog.tag.ggs.yaml看下:kubectl get deploy nginx -o=yaml > blog.tag.ggs.yaml
kubernetes 核心技术-Pod
1、Pod 概述
Pod 是 k8s 系统中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最小资源对象模型,也是在 k8s 上运行容器化应用的资源对象,其他的资源对象都是用来支撑或者扩展 Pod 对象功能的,比如控制器对象是用来管控 Pod 对象的,Service 或者Ingress 资源对象是用来暴露 Pod 引用对象的,PersistentVolume 资源对象是用来为 Pod提供存储等等,k8s 不会直接处理容器,而是 Pod,Pod 是由一个或多个 container 组成Pod 是 Kubernetes 的最重要概念,每一个 Pod 都有一个特殊的被称为”根容器“的 Pause容器。Pause 容器对应的镜 像属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod还包含一个或多个紧密相关的用户业务容器。
2、Pod 特性
(1)资源共享
一个 Pod 里的多个容器可以共享存储和网络,可以看作一个逻辑的主机。共享的如namespace,cgroups 或者其他的隔离资源。多个容器共享同一 network namespace,由此在一个 Pod 里的多个容器共享 Pod 的 IP 和端口 namespace,所以一个 Pod 内的多个容器之间可以通过 localhost 来进行通信,所需要注意的是不同容器要注意不要有端口冲突即可。不同的 Pod 有不同的 IP,不同 Pod 内的多个容器之前通信,不可以使用 IPC(如果没有特殊指定的话)通信,通常情况下使用 Pod的 IP 进行通信。
一个 Pod 里的多个容器可以共享存储卷,这个存储卷会被定义为 Pod 的一部分,并且可以挂载到该 Pod 里的所有容器的文件系统上。
(2)生命周期短暂
Pod 属于生命周期比较短暂的组件,比如,当 Pod 所在节点发生故障,那么该节点上的 Pod会被调度到其他节点,但需要注意的是,被重新调度的 Pod 是一个全新的 Pod,跟之前的Pod 没有半毛钱关系。
(3)平坦的网络
K8s 集群中的所有 Pod 都在同一个共享网络地址空间中,也就是说每个 Pod 都可以通过其他 Pod 的 IP 地址来实现访问。
Pod存在的意义:
1、创建容器使用docker,一个docker对应是一个容器,一个容器有进程,一个容器运行一个应用程序。(单进程管理)
2、pod是多进程设计,一个pod中有多个容器,一个容器运行一个应用程序。
3、pod的存在也是为了亲密性应用。例如,两个应用之间进行交互或者网络之间调用以及两个应用之间要频繁调用。所以叫“亲密性应用”
pod实现机制:
1、共享网络
容器之间本身是相互隔离的比如用namespace 几group方式隔离。
同一个pod中的容器是如何实现网络共享的。
创建容器时系统会先创建一个根容器Pause(info容器),后面创建的业务容器会自动加入到Pause(info容器)根容器是包含ip 、mac port等信息,在同一个名称空间中即可实现网络共享(类似阿里云的vpc,在同一个vpc下网络互通)
2、共享存储
实际上是将数据做持久化存储(数据卷 Volume),将数据保存在一个地方,多个容器可以访问这个持久化存储数据。
Pod镜像拉去策略:
主要有三种:Always 、Never 、IfNotPresent
Always
总是从镜像仓库获取镜像。当标签为latest,默认为Always
Never
禁止从仓库中获取镜像,只能使用本地镜像
IfNotPresent
仅当本地没有镜像时,才从镜像仓库获取镜像。当标签为自定义时(不是latest),默认为IfNotPresent
范例:
Pod资源限制:containers:
- name: redis
image: redis:6.0
imagePullPolicy: Always
pod中,容器的程序要运行肯定是要占用一定资源的,比如CPU和内存等,如果不对某个容器的资源对限制,那么它就可能消耗大量资源,导致其他容器无法运行,针对这样情况,kubernetes提供了对内存和CPU资源进行配额的机制,这种机制主要通过配置pod中容器的resources选项实现,resources提供了2个主要的参数,如下:
可以通过上面两个选项设置资源的上下线;limits:用于限制运行时容器的最大占用资源,当容器占用资源超过limit时就会被终止,进进行重启;
requests:用于设置容器需要的最小资源,如果环境资源不够,容器将无法启动;(最低配额,保证被调度的节点上至少有的资源配额)
资源限制另外的说明:[root@master ~]# cat pod-busybox.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-command
labels:
env: dev
namespace: default
spec:
containers:
- image: busybox
name: busybox-container
command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt;sleep 3;done;"]
resources: #资源配额
limits: #限制最大资源,上限
cpu: 2 #CPU限制,单位是code数
memory: 2G #内存最大限制
requests: #请求资源(最小,下限)
cpu: 1 #CPU请求,单位是code数
memory: 500G #内存最小请求
[root@master ~]#
Pod 资源配置(资源限制):
每个 Pod 都可以对其能使用的服务器上的计算资源设置限额,Kubernetes 中可以设置限额的计算资源有 CPU 与 Memory 两种,其中 CPU 的资源单位为 CPU 数量,是一个绝对值而非相对值。Memory 配额也是一个绝对值,它的单 位是内存字节数。
Kubernetes 里,一个计算资源进行配额限定需要设定以下两个参数: Requests 该资源最小申请数量,系统必须满足要求 Limits 该资源最大允许使用的量,不能突破,当容器试图使用超过这个量的资源时,可能会被 Kubernetes Kill 并重启
(1)举例
上述代码表明 MySQL 容器申请最少 0.25 个 CPU 以及 64MiB 内存,在运行过程中容器所能使用的资源配额为 0.5 个 CPU 以及 128MiB 内存。sepc
containers:
- name: db
image: mysql
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
容器健康检查:
应用层面健康检查。
健康检查相关说明可参考:https://blog.tag.gg/showinfo-3-36270-0.html
关于节点标签的创建、修改、删除及使用方法可访问:https://blog.tag.gg/showinfo-3-36271-0.html地址详细查看:
kubernetes调度策略
创建pod过程: master节点:
1、创建一个pod,首先会进入到apiserver并将pod信息存储到etcd里面。
2、pod创建后会进入scheduler,首先会监听apiserver是否有新的pod创建,有新的pod创建,则通过etcd读取pod,然后调度分配到node节点中。
node节点:
首先kubelet会先访问apiserver,然后读取etcd获取分配给当前节点的pod,然后通过docker创建对应容器,创建好后将容器信息返回给apiserver然后再etcd中存储。
在创建pod过程中有什么因素会影响pod调度过程:
影响调度的属性:
1、pod资源限制对pod调用产生影响,例如内存和cpu限制。具体说明可参考上面“Pod 资源配置(资源限制)”说明。
2、节点选择器会对pod调度产生影响,具体可参考“https://blog.tag.gg/showinfo-3-36271-0.html”说明
3、节点亲和性对pod调度影响。
关于节点亲和性的说明可访问:https://blog.tag.gg/showinfo-3-36273-0.html
4、污点和污点容忍影响调度。
关于污点及污点容忍设置及使用方法可访问:https://blog.tag.gg/showinfo-3-36272-0.html
controller概述和应用场景:
1、什么是controller控制器
在集群中管理和运行容器的对象,controller中还有很多controller。
2、pod和controller是什么关系
pod是通过controller实现应用的运维,比如伸缩、滚动升级等都是controller实现的。
pod和controller之间是通过label标签建立关系。
3、deployment控制器应用场景
部署无状态应用
管理pod和replicaset
部署,滚动升级等功能
web服务、微服务。
4、yaml文件字段说明
5、deployment控制器实际部署应用
通过label标签建立关系
kubectl create deployment web --image=nginx --dry-run -o yaml >web.yaml #导出yaml文件。
通过yaml文件部署。apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}
查看创建情况kubectl apply -f web.yaml
对外发布,暴露端口,生成一个yaml文件kubectl get pods
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-76b56fd968-r8djm 1/1 Running 1 (23m ago) 47h
通过上面生成的yaml文件部署kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web11 -o yaml >web11.yaml
执行如下命令查看pod及端口情况。kubectl apply -f web11.yaml
kubectl get pods,svc
通过新的yaml文件生成新的pod。[root@master ~]# kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/web-76b56fd968-r8djm 1/1 Running 1 (29m ago) 2d
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d23h
service/nginx NodePort 10.96.241.120 <none> 80:31261/TCP 5d23h
service/web11 NodePort 10.100.177.151 <none> 80:31247/TCP 2m56s
[root@master ~]# kubectl apply -f web.yaml
deployment.apps/web configured
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-5c48757fd6-x5wbz 0/1 ContainerCreating 0 13s
web-76b56fd968-r8djm 1/1 Running 1 (44m ago) 2d
6、升级回滚
升级:
编辑之前的 web.yaml 文件,将 image: nginx 改成 image: nginx:1.14 (也就是指定版本)
现在nignx版本是1.14,我们升级到1.15版本,命令如下。apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web
spec:
containers:
- image: nginx:1.14
name: nginx
resources: {}
status: {}
查看升级状态是否成功:[root@master ~]# kubectl set image deployment web nginx=nginx:1.15
deployment.apps/web image updated
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-5c48757fd6-x5wbz 1/1 Running 0 4m5s
web-9b696bd8f-p5p7l 0/1 ContainerCreating 0 5s
在node节点执行docker images 可以看到最新的1.15的nginx镜像。[root@master ~]# kubectl rollout status deployment web
deployment "web" successfully rolled out
回滚:
1、查看历史版本
kubectl rollout history deployment web
还原版本:[root@master ~]# kubectl rollout history deployment web
deployment.apps/web
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>
还原到上一个版本,例如现在升级到了1.15,要还原到1.14
kubectl rollout undo deployment web
查看状态,成功:[root@master ~]# kubectl rollout undo deployment web
deployment.apps/web rolled back
还原到指定版本:[root@master ~]# kubectl rollout status deployment web
deployment "web" successfully rolled out
还原成功:kubectl rollout undo deployment web --to-revision=1
7、弹性伸缩[root@master ~]# kubectl rollout undo deployment web --to-revision=1
deployment.apps/web rolled back
[root@master ~]# kubectl rollout status deployment web
Waiting for deployment "web" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "web" rollout to finish: 1 old replicas are pending termination...
deployment "web" successfully rolled out
一次性创建10个副本。kubectl scale deployment web --replicas=10
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-76b56fd968-rp2n2 1/1 Running 0 3m24s
[root@master ~]# kubectl scale deployment web --replicas=10
deployment.apps/web scaled
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-76b56fd968-4qf6x 0/1 ContainerCreating 0 2s
web-76b56fd968-62xb7 0/1 ContainerCreating 0 2s
web-76b56fd968-7hg5r 0/1 ContainerCreating 0 2s
web-76b56fd968-dts64 0/1 ContainerCreating 0 2s
web-76b56fd968-fm79d 0/1 ContainerCreating 0 2s
web-76b56fd968-kb97w 0/1 ContainerCreating 0 2s
web-76b56fd968-ms22c 0/1 ContainerCreating 0 2s
web-76b56fd968-rp2n2 1/1 Running 0 3m29s
web-76b56fd968-szmtp 0/1 ContainerCreating 0 2s
web-76b56fd968-vmn2p 0/1 ContainerCreating 0 2s
[root@master ~]#
Service
1、sevice存在的意义:防止pod失联(服务发现)
因为Pod每次创建都对应一个IP地址,而这个IP地址是短暂的,每次随着Pod的更新都会变化,假设当我们的前端页面有多个Pod时候,同时后端也多个Pod,这个时候,他们之间的相互访问,就需要通过注册中心,拿到Pod的IP地址,然后去访问对应的Pod。
2、定义一组pod访问策略(负载均衡)
页面前端的Pod访问到后端的Pod,中间会通过Service一层,而Service在这里还能做负载均衡,负载均衡的策略有很多种实现策略,
例如: 随机 轮询 响应比。
Pod 和 Service 的关系
这里Pod 和 Service 之间还是根据 label 和 selector 建立关联的 【和Controller一样】
例如:service中定义:app:nginx联系的。
pod中定义:selector:
app:nginx
service中有vip(虚拟ip)一般用于做高可用,当访问时先访问到虚拟ip。然后service在通过服务发现或负载均衡方式访问到后面的pod。labels:
app:nginx
Service常用类型
Service 常用类型有三种:
- ClusterIp:集群内部访问
- NodePort:对外访问应用使用(对外暴露端口)
- LoadBalancer:可以做到NodePort一样的效果,但功能更强大,对外访问应用使用,公有云
举例
我们可以导出一个文件 包含service的配置信息service.yaml 如下所示:kubectl expose deployment web --port=80 --target-port=80 --dry-run -o yaml > service.yaml
执行如下命令创建pod,apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web11
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
status:
loadBalancer: {}
执行如下命令后显示:如果我们没有做设置的话,默认使用的是第一种方式 ClusterIp,也就是只能在集群内部使用kubectl apply -f service.yaml
我们可以添加一个type字段,用来设置我们的service类型为:NodePort[root@master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/web-76b56fd968-4qf6x 1/1 Running 2 (29m ago) 2d18h
pod/web-76b56fd968-62xb7 1/1 Running 2 (29m ago) 2d18h
pod/web-76b56fd968-7hg5r 1/1 Running 2 (29m ago) 2d18h
pod/web-76b56fd968-dts64 1/1 Running 2 (29m ago) 2d18h
pod/web-76b56fd968-fm79d 1/1 Running 2 (29m ago) 2d18h
pod/web-76b56fd968-kb97w 1/1 Running 2 (29m ago) 2d18h
pod/web-76b56fd968-ms22c 1/1 Running 2 (29m ago) 2d18h
pod/web-76b56fd968-rp2n2 1/1 Running 2 (29m ago) 2d18h
pod/web-76b56fd968-szmtp 1/1 Running 2 (29m ago) 2d18h
pod/web-76b56fd968-vmn2p 1/1 Running 2 (29m ago) 2d18h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
service/nginx NodePort 10.96.241.120 <none> 80:31261/TCP 8d
service/web11 ClusterIP 10.100.177.151 <none> 80/TCP 2d19h
修改完命令后,我们使用创建一个podapiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web11
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
type: NodePort
status:
loadBalancer: {}
执行命令后显示如下,可以看到是:NodePortkubectl apply -f service.yaml
node一般是在内网进行部署,而外网一般是不能访问到的,那么如何访问的呢?[root@master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/web-76b56fd968-4qf6x 1/1 Running 2 (33m ago) 2d18h
pod/web-76b56fd968-62xb7 1/1 Running 2 (33m ago) 2d18h
pod/web-76b56fd968-7hg5r 1/1 Running 2 (33m ago) 2d18h
pod/web-76b56fd968-dts64 1/1 Running 2 (33m ago) 2d18h
pod/web-76b56fd968-fm79d 1/1 Running 2 (33m ago) 2d18h
pod/web-76b56fd968-kb97w 1/1 Running 2 (33m ago) 2d18h
pod/web-76b56fd968-ms22c 1/1 Running 2 (33m ago) 2d18h
pod/web-76b56fd968-rp2n2 1/1 Running 2 (33m ago) 2d18h
pod/web-76b56fd968-szmtp 1/1 Running 2 (33m ago) 2d18h
pod/web-76b56fd968-vmn2p 1/1 Running 2 (33m ago) 2d18h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
service/nginx NodePort 10.96.241.120 <none> 80:31261/TCP 8d
service/web11 ClusterIP 10.100.177.151 <none> 80/TCP 2d19h
service/web21 NodePort 10.111.156.174 <none> 80:31990/TCP 55s
找到一台可以通过外网访问机器,安装nginx,反向代理
手动把可以访问的节点添加到nginx中
如果我们使用LoadBalancer,就会有负载均衡的控制器,类似于nginx的功能,就不需要自己添加到nginx上
删除pod以及删除service方法
删除pod和service可访问:https://blog.tag.gg/showinfo-3-36274-0.html
无状态和有状态
1、无状态:
之前用deployment创建的pod都是无状态。
- 无状态认为pod都是一样的。
- 没有顺序要求
- 不用考虑在哪一个node运行
- 随意进行伸缩和扩展
- 在无状态下不用考虑的问题在有状态下都有考虑。
- 让每个pod独立的,保持pod启动顺序和唯一性。
- 唯一的网络标识符,持久存储。
- 有顺序,比如mysql主从。
无头service
什么是无头service
ClusterIP是none 则表示无头service
如何部署有状态应用:
1、用StatefulSet部署有状态应用
执行如下命令生成podapiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None #这里可以有IP,也可以无IP,推荐无IP,也就是 无头service
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web-statefulset
spec:
serviceName: "nginx"
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.15.2
ports:
- containerPort: 80
name: web
执行后如下:kubectl apply -f stat.yaml
[root@master ~]# kubectl apply -f stat.yaml
service/nginx unchanged
statefulset.apps/web-statefulset created
查看pod,每个都有是唯一的名称。[root@master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/web-statefulset-0 1/1 Running 0 57s
pod/web-statefulset-1 1/1 Running 0 39s
pod/web-statefulset-2 1/1 Running 0 8s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
service/nginx ClusterIP None <none> 80/TCP 4m57s
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-statefulset-0 1/1 Running 0 74s
web-statefulset-1 1/1 Running 0 56s
web-statefulset-2 1/1 Running 0 25s
deployment和statefueset区别:有身份的唯一表示。
是根据主机名+按照一定规则生成域名。例如web-statefulset-0到 web-statefulset-2
每个pod有唯一主机名
唯一域名:
格式:
主机名称.service名称.名称空间.svc.cluster.local
部署守护进程DaemonSet:web-StatefulSet-0.nginx.default.svc.cluster.local
有时需要在集群中的所有node上运行一个pod的副本。当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
范例:
在每个node节点安装数据采集工具,编写ds.yaml文件
部署应用:apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ds-test
labels:
app: filebeat
spec:
# 标签选择器
selector:
matchLabels:
app: filebeat
# 标签类型
template:
metadata:
labels:
app: filebeat
spec:
# 配置容器
containers:
- name: logs
image: nginx
ports:
- containerPort: 80
# 挂载目录
volumeMounts:
- name: varlog
mountPath: /tmp/log
volumes:
- name: varlog
hostPath:
path: /var/log
执行后如下kubectl apply -f ds.yaml
创建后可以进入这个pod看下情况。[root@master ~]# kubectl apply -f ds.yaml
daemonset.apps/ds-test created
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ds-test-crpsf 1/1 Running 0 72s
ds-test-glnql 1/1 Running 0 72s
进入pod命令:
进入后显示如下:kubectl exec -it ds-test-crpsf bash
进入后执行如下命令查看。[root@master ~]# kubectl exec -it ds-test-crpsf bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@ds-test-crpsf:/#
ls /tmp/log
退出pod:root@ds-test-crpsf:/# ls /tmp/log
anaconda containers maillog-20230402 tallylog vmware-network.8.log
audit cron messages tuned vmware-network.9.log
boot.log cron-20230402 messages-20230402 vmware-network.1.log vmware-network.log
boot.log-20230327 dmesg pods vmware-network.2.log vmware-vgauthsvc.log.0
boot.log-20230330 dmesg.old rhsm vmware-network.3.log vmware-vmsvc-root.log
boot.log-20230402 firewalld secure vmware-network.4.log vmware-vmtoolsd-root.log
btmp grubby_prune_debug secure-20230402 vmware-network.5.log wtmp
btmp-20230402 lastlog spooler vmware-network.6.log yum.log
chrony maillog spooler-20230402 vmware-network.7.log
exit
Job和Cronjob任务部署方法
job是一次性任务。cronjob是定时任务
部署方法及范例可访问:https://blog.tag.gg/showinfo-3-36275-0.html
Secret加密数据创建及挂载
Secret详细说明及演示访问:https://blog.tag.gg/showinfo-3-36277-0.html
ConfigMap
configmap创建及挂载可访问:https://blog.tag.gg/showinfo-3-36278-0.html
3、Pod 定义
(1)下面是 yaml 文件定义的 Pod 的完整内容
4、Pod 的基本使用方法apiVersion: v1
kind: Pod
metadata: //元数据
name: string
namespace: string
labels:
-name: string
annotations:
-name: string
spec:
containers: //pod 中的容器列表,可以有多个容器
- name: string //容器的名称
image: string //容器中的镜像
imagesPullPolicy: [Always|Never|IfNotPresent]//获取镜像的策略,默认值为
Always,每次都尝试重新下载镜像
command: [string] //容器的启动命令列表(不配置的话使用镜像内部的命令) args:
[string] //启动参数列表
workingDir: string //容器的工作目录 volumeMounts: //挂载到到容器内部的存储
卷设置
-name: string
mountPath: string //存储卷在容器内部 Mount 的绝对路径 readOnly: boolean //
默认值为读写
ports: //容器需要暴露的端口号列表
-name: string
containerPort: int //容器要暴露的端口
hostPort: int //容器所在主机监听的端口(容器暴露端口映射到宿主机的端口,设置
hostPort 时同一 台宿主机将不能再启动该容器的第 2 份副本)
protocol: string //TCP 和 UDP,默认值为 TCP env: //容器运行前要设置的环境
列表
-name: string value: string
resources:
limits: //资源限制,容器的最大可用资源数量 cpu: Srting
memory: string
requeste: //资源限制,容器启动的初始可用资源数量 cpu: string
memory: string
livenessProbe: //pod 内容器健康检查的设置 exec:
command: [string] //exec 方式需要指定的命令或脚本 httpGet: //通过 httpget 检
查健康
path: string port: number host: string scheme: Srtring httpHeaders:
- name: Stirng value: string
tcpSocket: //通过 tcpSocket 检查健康
port: number initialDelaySeconds: 0//首次检查时间 timeoutSeconds: 0 //检查超时
时间
periodSeconds: 0 //检查间隔时间
successThreshold: 0
failureThreshold: 0 securityContext: //安全配置
privileged: falae
restartPolicy: [Always|Never|OnFailure]//重启策略,默认值为 Always
nodeSelector: object //节点选择,表示将该 Pod 调度到包含这些 label 的 Node 上,以
key:value 格式指定
imagePullSecrets:
-name: string
hostNetwork: false //是否使用主机网络模式,弃用 Docker 网桥,默认否
volumes: //在该 pod 上定义共享存储卷列表
-name: string emptyDir: {} hostPath:
path: string secret:
secretName: string item:
-key: string path: string
configMap: name: string items:
-key: string
path: string
在 kubernetes 中对运行容器的要求为:容器的主程序需要一直在前台运行,而不是后台运行。应用需要改造成前 台运行的方式。如果我们创建的 Docker 镜像的启动命令是后台执行程序,则在 kubelet 创建包含这个容器的 pod 之 后运行完该命令,即认为 Pod 已经结束,将立刻销毁该 Pod。如果为该 Pod 定义了 RC,则创建、销毁会陷入一个无 限循环的过程中。Pod 可以由 1 个或多个容器组合而成。
(1)一个容器组成的 Pod 的 yaml 示例
# 一个容器组成的 Pod
(2)多个容器组成的 Pod 的 yaml 示例apiVersion: v1 kind: Pod metadata:
name: mytomcat labels:
name: mytomcat spec:
containers:
- name: mytomcat image: tomcat ports:
- containerPort: 8000
#两个紧密耦合的容器
(3)创建apiVersion: v1 kind: Pod metadata:
name: myweb labels:
name: tomcat-redis
spec:
containers:
-name: tomcat image: tomcat ports:
-containerPort: 8080
-name: redis image: redis ports:
-containerPort: 6379
(4)查看kubectl create -f xxx.yaml
(5)删除kubectl get pod/po <Pod_name>
kubectl get pod/po <Pod_name> -o wide
kubectl describe pod/po <Pod_name>
5、Pod 的分类kubectl delete -f pod pod_name.yaml
kubectl delete pod --all/[pod_name]
Pod 有两种类型
(1)普通 Pod
普通 Pod 一旦被创建,就会被放入到 etcd 中存储,随后会被 Kubernetes Master 调度到某个具体的 Node 上并进行绑定,随后该 Pod 对应的 Node 上的 kubelet 进程实例化成一组相关的 Docker 容器并启动起来。在默认情 况下,当 Pod 里某个容器停止时,Kubernetes 会自动检测到这个问题并且重新启动这个 Pod 里某所有容器, 如果 Pod 所在的 Node 宕机,则会将这个 Node 上的所有 Pod 重新调度到其它节点上。
(2)静态 Pod
静态 Pod 是由 kubelet 进行管理的仅存在于特定 Node 上的 Pod,它们不能通过 API Server进行管理,无法与 ReplicationController、Deployment 或 DaemonSet 进行关联,并且kubelet 也无法对它们进行健康检查。
6、Pod 生命周期和重启策略
pod在整个生命周期中被系统定义为各种状态,熟悉pod的各种状态对于理解如何设置pod的调度策略、重启策略是很有必要的
pod状态如下:
状态值 | 描述 |
---|---|
Pending | API Server已经创建了pod,但在pod内还有一个或多个容器的镜像没有创建,包括正在下载镜像的过程 |
Running | pod内所有容器均已创建,且至少有一个容器处于运行状态、正在启动状态或正在重启状态 |
Succeeded | pod内所有容器均成功执行后退出,且不会在重启 |
Failed | pod内所有容器均已退出,但至少有一个容器为退出失败状态 |
Unknown | 由于某种原因无法获取该Pod的状态,可能由于网络通信不畅导致的 |
pod的重启策略(RestartPolicy)应用于pod内的所有容器,并且仅在pod所处的 node 上 由kubelet 进行判断和重启操作。
当某个容器异常退出或者健康检查 失败时,kubelet将根据RestartPolicy的设置进行相应的操作,pod的重启策略包括Always、OnFailure和Never(默认值为Always):
重启策略 | 描述 |
---|---|
Always | 当容器失效时,由kubelet自动重启该容器 |
OnFailure | 当容器终止运行且退出码不为0时,由kubelet自动重启该容器 |
Never | 不论容器运行状态如何,kubelet都不会重启该容器 |
[root@master test]# vim never.yaml
apiVersion: v1
kind: Pod
metadata:
name: foo01
namespace: zy
spec:
containers:
- name: busybox
image: busybox
args:
- /bin/sh
- -c
- sleep 30; exit 3
restartPolicy: Never
kubelet重启失效容器的时间间隔以symc-frequency乘以2n来计算,例如1、 2、4、8倍等,最长延时5min,并且在成功重启后的10min后重置该时间。
pod的重启策略与控制方式息息相关,当前可用于管理pod的控制器包括
ReplicationController、Job、DaemonSet,还可以通过kubelet管理(静态
pod)。每种控制器对Pod的重启策略要求如下:
控制器 | 要求 |
---|---|
RC和DaemonSet | 必须设置为Always,需要保证该容器持续运行 |
Job | OnFailure或Never,确保容器执行完成后不再重启 |
kubelet | 在Pod失效时自动重启它,不论将RestartPolicy设置为什么值,也不会对Pod进行健康检查 |
(3)常见状态转换:
Pod的容器数 | Pod当前状态 | 发生的事件 | Pod结果状态 | ||
---|---|---|---|---|---|
RestartPolicy=Always | RestartPolicy=OnFailure | RestartPolicy=Never | |||
包含一个容器 | Running | 容器成功退出 | Running | Succeeded | Succeeded |
包含一个容器 | Running | 容器失败退出 | Running | Running | Failure |
包含两个容器 | Running | 1个容器失败退出 | Running | Running | Running |
包含两个容器 | Running | 容器被OOM杀掉 | Running | Running | Failure |
文章评论 本文章有个评论