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

 

 

 
posted @ 2022-05-06 16:08  wyllearning  阅读(477)  评论(0)    收藏  举报