sts、ds、pod生命周期、nginx/tomcat 动静分离
控制器
Statefulset
-
简介
1、为了解决有状态服务的集群部署,集群之间的数据同步问题(如mysql主从等)
2、Statefulset所管理的Pod拥有唯一且固定的Pod名称(deployment创建的Pod删除了后,Pod名称会随机重建,如创建3个mysql Pod名称可能为mysql-0、mysql-1、mysql-2)
3、Statefulset按照顺序对pod进行启停,伸缩、回收和创建
4、Headless Service(pod之间通信为无头服务,请求的解析直接将pod名解析到Pod IP,pod名存入etcd)
- 每次访问Headless Service,会被解析为不同的pod地址(不是转发请求,而是直接成为某个podip的域名)
注意:只有第一个Pod启动后,才会启动第二个。第一个没完全起来,后续Pod不会启动,涉及数据同步的服务

DaemonSet
-
简介
DaemonSet再当前集群中每个节点运行同一个Pod,当有新的节点加入进群时也会为新的节点配置相同的Pod,当节点从集群中移除时其Pod与会被kubernetes回收,删除Daemonset控制器将删除其创建的所有Pod

daemonset 使用宿主机网络时,访问pod后,不会再次进行转发,网络损耗较小
但是使用pod网络时,会有损耗,请求先到宿主机,再由iptables规则转发到指定的Pod
iptables -t nat -vnL |grep pod ip

-
Prometheus的ds类型Pod的部分编排

Pod基础概念
pod的常见状态
-
pod启动流程


-
pod常见状态
1、 Unschedulable: #Pod不 能被调度,kube-scheduler没 有匹配到合适的node节点
2、 PodScheduled: #pod正 处于调度中,在kube-scheduler刚 开始调度的时候,还没有将pod分配到指定的node,在筛选出合适的节点后就会更新etcd数据,将pod分配到指定的node
3、 Pending:#正在创建Pod但是Pod中的容器还没有全部被创建完成=[处于此状态的Pod应该检查Pod依赖的存储是否有权限挂载等。
4、 Failed: #Pod中 有容器启动失败而导致pod工作异常。
5、 Unknown:#由于某种原因无法获得pod的当前状态,通常是由于与pod所在的node节点通信错误。
6、 Initialized: #所 有pod中的初始化容器已经完成了
7、 ImagePulBackOff: #Pod所 在的node节点下载镜像失败
8、 Running:#Pod内部的容器已经被创建并且启动。
9、 Ready: #表示pod中的容器已经可以提供访问服务
Error: #pod启动过程中发生错误
NodeLost: #Pod所在节点失联
Waiting: #Pod等待启动
Terminating: #Pod正在被销毁
CrashLoopBackOff: #pod,但是x
PodInitializing: #pod正 在初始化中
DockerDaemonNotReady: #node节点decker服务没有启动
NetworkPluginNotReady: #网络插件没有启动
pause容器
基础容器,在k8s中是pod的底层容器,是由kubelet加上出的
在kubelet的.service文件中
--pod-infra-container-image=xxx/pause:3.6
-
功能
负责初始化容器的network namespace
infra负责初始化网络运行环境,供当前pod中的容器去使用
为什么这样做:当一个pod有两个或多个容器,不会每个容器分配一个地址,而是共用infra容器中的地址
注意:共用网络,但是文件系统、用户空间仍是隔离的
-
共享了哪些Namespace
1、NET Namespace:pod中多个容器共享同一个网络命名空间,即使用相同的IP和端口信息
2、IPC Namespace:pod中多个容器可使用System V IPC或POSIX消息队列进行通信(unix通信协议)
3、UTS Namespace:pod中多个容器共享一个主机名。
4、MNT Namespace 、 PID Namespace、User Namespace未共享

查看容器网卡是宿主机的哪一块
1、进入容器安装两个包
apt update
apt install net-tools ethtool -y
2、查看网卡信息
ethtool -S eth0
peer_ifindes: 24 # 网卡编号

3、在宿主机中
ip link show
24即容器对应的网卡

模拟在没有k8s的环境,使用pause容器,共享容器网络(了解)
## 运行pause容器
docker run -d -p 80:80 --name pause-container-test \
registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6
#前提。配置文件已经准备好,
## 运行nginx容器并使用上面步骤创建的pause容器的网络
docker run -d --name nginx-container-test \
-v `pwd`/nginx.conf:/etc/nginx/nginx.conf \
-v `pwd`/html:/usr/share/nginx/html \
--net=container:pause-container-test \
nginx:1.20.2
## 运行php容器并使用上面步骤创建的pause容器的网络
docker run -d --name php-container-test \
--net=container:pause-container-test \
-v `pwd`/html:/usr/share/nginx/html \
php:5.6.40-fpm
--net :指定网络
--net=container:指定容器
-----------------------------------------------------
--net=bridge ##默认
--net=host使用本地网络
--net=container:container_name or container_id
init容器
-
作用、简介
1、可以为业务容器提前准备好业务容器的运行环境,比如讲业务容器需要的配置文件提前生成并放在指定位置,检查数据权限或完整性、软件版本等基础运行环境
2、可以在运行业务容器之前准备好需要的业务数据,如OSS下载,或者从其他地方copy
3、检查依赖服务是否能够访问
-
特点
1、一个pod可以有多个业务容器还能在有多个init容器,但是每个init容器和业务容器的运行环境都是隔离的
2、init容器比业务容器先启动
3、init容器运行成功后会继续运行业务容器
4、如果一个pod有多个init容器则需要从上到下逐个运行并且成功,最后才会运行业务容器
5、init容器不支持探针检查(因为初始化完退出就再也不运行了)
-
例子--同步数据库
1、当添加从库时,首先会先通过init容器去同步主库的数据到自己的pvc里面
2、配置主库,建立主从关系(可能通过两个init容器,也可以一个init容器一次搞定)
3、从mysql容器启动,提供读请求

Health Check
由发起者对容器进行周期性健康状态检测
周期检测相当于人类的周期性体检
每次检测相当于人类每次体检内容
一般为查询接口等
-
在docker中做健康检查,两种方式:
1、docker-compose
1、docker-compose
healthcheck: #添加服务监控状态检查
test: ["CMD","curl","-f","http://localhost"]
interval: 5s ##监控状态检查的时间间隔,默认30s
timeout: 5s ## 单次检查的失败超时时间默认30s
retries: 3 ## 连续失败次数,默认3次,当连续失败retries次数后将容器置为unhealthy状态
start_period: 60s ##可认为延迟检查时间,防止服务启动过慢 在该时间内检查成功就认为是检查成功,将容器置为healthy状态

2、dockerfile
FROM nginx:1.21.1
HEALTHCHECK --initerval=5s --timeout=2s --retries=3 \
CMD curl --silent --fail localhost:80 || exit 1
Pod生命周期和探针
pod lifecycle(pod生命周期)
pod的生命周期,从start后可以配置postStart检测,运行过程中可以配置livenessProe和readinessProbe,最后在stop前可配置preStop操作
readinessProbe:就绪探针。查看容器是否就绪,失败则从svc中剔除该pod
livenessProbe:存活探针,查看容器运行过程中是否出现问题,出问题则删除该容器

探针是由kubelet对容器执行的定期诊断,以保证Pod的状态始终处于运行状态,要执行诊断,kubelet调用由容器实现的Handler(处理程序),也成为Hook(钩子),有三种类型的处理程序:
ExecAction:
# 在容器内执行指定命令,如果命令退出时返回码为0则认为诊断成功。
TCPSocketAction:
# 对指定端口上的容器的P地址进行TCP检查,如果端口打开,则诊断被认为是成功的。
HTTPGeLAction:
#对指定的端口和路径上的容器的IP地址执行HTTPGet请求,如果响应的状态码大于等于200且小于400,则诊断被认为是成功的。
每次探测都将获得以下三种结果之一:
成功:容器通过了诊断。
失败:容器未通过诊断。
未知诊断失败,因此不会采取任何行动。
重启策略
pod一旦配置探针,在检测失败的时候,会基于restartPolicy对Pod进行下一步操作:
restartPolicy:
Always:当容器异常时,k8s自动重启该容器
replicationController/RC/deploy默认是为Always
OnFailure:当容器失败时(容器停止运行且退出码不为0)k8s自动重启该容器
Never:无论容器运行状态如何都不会重启该容器,Job或CronJob
镜像拉取策略
imagePullPolicy
ifNotPresent:node节点没有此镜像就去指定的镜像仓库拉取,有就用本地镜像
Always:每次重建Pod都会重新拉取镜像
Never:从不到镜像中心去拉取,只用本地镜像
探针类型解析
startupProbe: ##启动探针,v1.16引入
判断容器内的应用程序是否启动完成,如果配置了启动探测,则会先禁用所有的其他探测,知道startupProbe检测成功为止,如果startupProbe探测失败,则kubelet将杀死容器,容器按照重启策略进行下一步操作。如果容器没有提供启动探测,则默认为成功
livenessProbe:存活探针
检测容器是否正在运行,如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的影响,如果容器不提供存活探针,则默认状态为Success, livenessProbe用于控制是否重启pod.
readinessProbe:就堵探针
如果就绪探测失败,端点控制器将从与Pod匹配的所有Service的端点中删除该Pod的IP地址,初始延迟之前的就绪状态默认为Failure(失败),如果容器不提供就绪探针,则默认状态为Success, readinessProbe用于控制pod是否添加至service.(探测成功一次,即加回svc的端点控制器中,两次都不行,只能是一次)
探针字段解析(各探针通用)
initialDelaySeconds: 120
## 初始化延迟时间,在pod创建后多久,才进行探针检测,默认0s.最小0s
periodSeconds: 30
## 探针检查周期间隔时间。多久探测一次,默认10秒,最小为1
timeoutSeconds: 30
## 单次探测超时时间,探测超时后等待多少秒,默认1秒,最小为1 (小于等于间隔时间)
successThreshold: 1
## 从失败转为成功的重试次数,探测成功后,被视为成功的最小连续成功次数。默认为1,必须为1
failureThreshold: 3
## 从成功转为失败的重试次数,当pod启动并且探测到了失败,kubernetes的重试次数,默认为3,最小为1
-
http检查
host:
##连接使用的主机名,默认是pod的ip
scheme: http
# 用于设置连接主机的方式,(http还是https,默认http)
path: /monitor/index.html
# 访问http服务的路径
httpHeaders:
## 请求中自定义http头,http头字段允许重复
port: 80
访问容器的端口或者端口名,数字必须在1~65535之间
-
示例 httpGet(只展示探针部分,没有详细写内容)
apiVersion: apps/v1
kind: Deployment
metadata:
name:
spec:
selector:
matchLables:
app: xxx
template:
metadata:
labels:
app: xxx
spec:
containers:
- name:
image:
livenessProbe:
httpGet:
path: /index.html
port: 80
scheme: http
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
-
实例tcpSocket(只展示探针部分,没有详细写内容)
apiVersion: apps/v1
kind: Deployment
metadata:
name:
spec:
selector:
matchLables:
app: xxx
template:
metadata:
labels:
app: xxx
spec:
containers:
- name:
image:
livenessProbe:
exec:
command:
- /usr/local/bin/redis-cli
- quit
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
postStart与preStop
-
启动前将自己注册到注册中心,停止前移除注册中心中信息
kind:
apiVersion:
metadata:
name:
spec:
selector:
matchLabels:
app: xxx
template:
metadata:
labels:
app: xx
spec:
containers:
- name:
image:
lifecycle
postStart:
exec:
command: ["/bin/sh","-c","echo 'hello from the postStart handler'>>/xxx" ]
preStop:
exec:
command: ["/usr/local/tomcat/bin/catalina.sh","stop"]
Pod终止流程
1.创建pod
完成调度流程
容器启动并执行postStart
livenessProbe
进入running状态
readinessProbe
service关联pod
接受客户端请求
2.做除pod
Pod被设置为’Terminating’状态、从service的Endpoints列表中删除并不再接受客户端请求。
执行PreStop
Kubernetes向pod中的客器发送SIGTERM信号(正常终止信号)终止pod里面的主进程,这个信号让容器知道自己很快将会被关闭
terminationGracePeriodSeconds:60'日可选终止等待期,如果有设置删除宽限时间,则等待宽限时间到期,否则最多等待30s,
Kubernetes等待指定的时间称为优雅终止宽限期,默认情况下是30秒,值得注意的是等待期与preStop Hook和SIGTERM信号并行执行,即Kubernetes可能不会等待preStop Hook完成(最长30秒之后主进程还没有结束就就强制终止pod).

kubectl explain deploy.spec.template.spec |grep -A 9 'terminationGracePeriodSeconds'
注意,该字段与containers平级
k8s优势
业务容器化优势
1、提高资源利用率,节约部署IT成本
2、提高部署效率,基于kubernetes实现微服务的快速部署与交付、容器的批量调度与秒级启动
3、实现横向扩容、灰度发布、回滚、链路追踪、服务治理
4、可根据业务负载进行自动弹性伸缩
5、容器将环境和代码打包放在镜像内,保证了测试与生产运行环境的一致性
6、紧跟云原生社区技术发展的步伐,不给公司遗留技术债,为后期技术升级夯实了基础
7、为个人储备前沿技术,提高个人level
构建镜像
根据k8s-data中的文件进行基础镜像构建
注意:如需要filebeat,需要自己获取
1、构建centos基础镜像
cd /magedu/k8s-4day/k8s-data/dockerfile/system/centos
bash build-command.sh
## build-command.sh #!/bin/bash docker build -t harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009 . docker push harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009
FROM centos:7.9.2009 MAINTAINER Jack.Zhang 2973707860@qq.com # ADD filebeat-7.12.1-x86_64.rpm /tmp RUN yum install -y /tmp/filebeat-7.12.1-x86_64.rpm vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop && rm -rf /etc/localtime /tmp/filebeat-7.12.1-x86_64.rpm && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
2、构建jdk镜像
cd /magedu/k8s-4day/k8s-data/dockerfile/web/pub-images/jdk-1.8.212
bash build-command.sh
##build-command.sh
#!/bin/bash docker build -t harbor.magedu.local/pub-images/jdk-base:v8.212 . sleep 1 docker push harbor.magedu.local/pub-images/jdk-base:v8.212
FROM harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009 MAINTAINER zhangshijie "zhangshijie@magedu.net" ADD jdk-8u212-linux-x64.tar.gz /usr/local/src/ RUN ln -sv /usr/local/src/jdk1.8.0_212 /usr/local/jdk ADD profile /etc/profile ENV JAVA_HOME /usr/local/jdk ENV JRE_HOME $JAVA_HOME/jre ENV CLASSPATH $JAVA_HOME/lib/:$JRE_HOME/lib/ ENV PATH $PATH:$JAVA_HOME/bi
3、构建nginx镜像
cd /magedu/k8s-4day/k8s-data/dockerfile/web/pub-images/nginx-base
bash build-command.sh
#!/bin/bash docker build -t harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009 . docker push harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009
FROM centos:7.9.2009 MAINTAINER Jack.Zhang 2973707860@qq.com # ADD filebeat-7.12.1-x86_64.rpm /tmp RUN yum install -y /tmp/filebeat-7.12.1-x86_64.rpm vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop && rm -rf /etc/localtime /tmp/filebeat-7.12.1-x86_64.rpm && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
4、构建tomcat基础镜像
需要自己准备tomcat的软件包
cd /magedu/k8s-4day/k8s-data/dockerfile/web/pub-images/tomcat-base-8.5.43
bash build-command.sh
#!/bin/bash docker build -t harbor.magedu.local/pub-images/tomcat-base:v8.5.43 . sleep 3 docker push harbor.magedu.local/pub-images/tomcat-base:v8.5.43
#Tomcat 8.5.43基础镜像 FROM harbor.magedu.local/pub-images/jdk-base:v8.212 MAINTAINER zhangshijie "zhangshijie@magedu.net" RUN mkdir /apps /data/tomcat/webapps /data/tomcat/logs -pv ADD apache-tomcat-8.5.43.tar.gz /apps RUN useradd tomcat -u 2050 && ln -sv /apps/apache-tomcat-8.5.43 /apps/tomcat && chown -R tomcat.tomcat /apps /data
实战案例
镜像分层
-
在公司中,一般都是使用自己构建的镜像
1、选择基础镜像环境(centos、Ubuntu、alpine)
2、自己定义基础进行环境(python、jdk、nginx、go)
3、基础镜像再进行细分(jdk可继续成为toncat镜像、dubbo镜像、spring镜像)
4、业务容器选择上面步骤构建好的基础镜像进行构建(tomcat选择tomcat、python选择python)

tomcat+nginx+nfs实现动静分离
构建tomcat服务镜像
-
根据上面的tomcat基础镜像,构建tomcat服务镜像(配置文件需要自己准备)
cd /magedu/k8s-4day/k8s-data/dockerfile/web/magedu/tomcat-app1/
bash build-command.sh 202205061515 #时间戳为镜像标签
#!/bin/bash TAG=$1 docker build -t harbor.magedu.local/magedu/tomcat-app1:${TAG} . sleep 3 docker push harbor.magedu.local/magedu/tomcat-app1:${TAG}
#tomcat web1 FROM harbor.magedu.local/pub-images/tomcat-base:v8.5.43 ADD catalina.sh /apps/tomcat/bin/catalina.sh ADD server.xml /apps/tomcat/conf/server.xml #ADD myapp/* /data/tomcat/webapps/myapp/ ADD app1.tar.gz /data/tomcat/webapps/myapp/ ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh #ADD filebeat.yml /etc/filebeat/filebeat.yml RUN chown -R tomcat.tomcat /data/ /apps/ #ADD filebeat-7.5.1-x86_64.rpm /tmp/ #RUN cd /tmp && yum localinstall -y filebeat-7.5.1-amd64.deb EXPOSE 8080 8443 CMD ["/apps/tomcat/bin/run_tomcat.sh"]
构建好镜像后,运行,查看镜像是否构建成功
docker run -it --rm -p 8080:8080 harbor.magedu.local/magedu/tomcat-app1:202205061515


-
成功访问,镜像构建成功
运行tomcat服务
cd /magedu/k8s-4day/k8s-data/dockerfile/web/magedu/tomcat-app1# cd /magedu/k8s-4day/k8s-data/yaml/magedu/tomcat-app1/
kubectl apply -f
测试通过端口访问

-
服务启动成功!
构建nginx服务镜像
cd /magedu/k8s-4day/k8s-data/dockerfile/web/magedu/nginx
./build-command.sh 202205061534
#!/bin/bash TAG=$1 docker build -t harbor.magedu.local/magedu/nginx-web1:${TAG} . echo "镜像构建完成,即将上传到harbor" sleep 1 docker push harbor.magedu.local/magedu/nginx-web1:${TAG} echo "镜像上传到harbor完成"
FROM harbor.magedu.local/pub-images/nginx-base:v1.20.2 RUN useradd tomcat -u 2050 ADD nginx.conf /usr/local/nginx/conf/nginx.conf ADD app1.tar.gz /usr/local/nginx/html/webapp/ ADD index.html /usr/local/nginx/html/index.html #静态资源挂载路径 RUN mkdir -p /usr/local/nginx/html/webapp/static /usr/local/nginx/html/webapp/images && chown tomcat.tomcat -R /usr/local/nginx/html/webapp/static /usr/local/nginx/html/webapp/images EXPOSE 80 443 CMD ["nginx"]
-
nginx配置文件 主要为访问/myapp时将请求转发到tomcat容器,实现动静分离
user tomcat tomcat;
worker_processes auto;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
daemon off;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
upstream tomcat_webserver {
server magedu-tomcat-app1-service.magedu.svc.magedu.local:80;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /webapp {
root html;
index index.html index.htm;
}
location /myapp {
proxy_pass http://tomcat_webserver;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
运行并访问nginx镜像
cd /magedu/k8s-4day/k8s-data/yaml/magedu/nginx
kubectl apply -f nginx.yaml

访问tomcat

-
注意:访问tomcat时,会需要重新输入端口,这里建议通过负载均衡器访问
配置负载均衡
vim haproxy.cfg ##bind为最开始用的vip
listen magedu-linux66-nginx-80
bind 192.168.1.23:80
mode tcp
server node1 192.168.1.15:30090 check inter 3s fall 3 rise 1
server node2 192.168.1.16:30090 check inter 3s fall 3 rise 1
listen magedu-linux66-nginx-443
bind 192.168.1.23:443
mode tcp
server node1 192.168.1.15:30091 check inter 3s fall 3 rise 1
server node2 192.168.1.16:30091 check inter 3s fall 3 rise 1
systemctl restart haproxy
通过vip访问服务
-
访问nginx

-
访问tomcat


浙公网安备 33010602011771号