精华内容
下载资源
问答
  • 电磁流量计在停机即不使用的时候,我们要对电磁流量计采取科学合理的维护和保养方法。...尤其对沉淀、易污染电极,含有固相的清洁液,在运行初期应多作检查,以获得经验确定正常检查周期。交流激磁方式的电磁流

    电磁流量计在停机即不使用的时候,我们要对电磁流量计采取科学合理的维护和保养方法。很多人发现在购买电磁流量计使用一段时间以后,再次使用发现测量数据的不准确。其实这不是电磁流量计本身存在的质量问题。是因为使用者没有按照说明书中的方法保养和维护。

    一、电磁流量计维护之零点检查和调整

    电磁流量计投入运行前,通电后要在电磁流量传感器充满液体静止状态下调整零点。投入运行后亦要针对使用条件定期停流作零点检查;尤其对沉淀、易污染电极,含有固相的非清洁液,在运行初期应多作检查,以获得经验确定正常检查周期。交流激磁方式的电磁流量计与矩形波激比,更易产生零点漂移,因此更要注意检查和调整。

    举两个沉积层产生故障的应用失误的例子。一个是石油钻探固井工程中,灌注水泥浆的流总量是重要工艺参数,经常用高压电磁流量计。仪表间歇使用,用毕后以清水冲洗传感器测量管,其余时间是空管。由于清洗不彻底,测量管内壁残留水泥浆固化成薄层,近二个月积聚形成绝缘层,包覆了整个电极表面,导致运行不正常而不能工作。

    另一个是电解切削工艺验装置上,用电磁流量计控制饱和食盐水流量,间隙使用一段时期后发现流量信号渐渐减弱,2个月后信号为零。原因是电解切削过程中氧化铁沉积管壁,形成短路所致。去掉层积即立即恢复正常。

    二、电磁流量计维护之定期检查传感器电性能

    首先,粗略地测量电极间电阻。断开传感器与转换器间信号连线,传感器内充满液体,用万用表测量两电极与接地端的电阻值,是否在制造厂规定值范围内,且所测得两值大体相同。记录下测量的电阻值,此值对以后判断传感器故障原因(如沉积层是导电的还是绝缘的)是有用的。

    其次,将传感器放空液体,擦净内壁,待完全干燥后用兆欧计测量两电极和接地端子间的电阻。

    展开全文
  • PreMiD状态官方) 欢迎使用PreMiD的(正式)Upptime状态存储库。 有时不会记录停机时间。 由于 ,该网站仅使用GitHub服务免费记录停机时间。 实时状态: :yellow_square: 部分中断 网址 状态 历史 响应...
  • 最大好处是零停机,整个更新过程始终有副本在运行,从而保证了业余的连续性。 根据 yaml 创建资源, apply 可以重复执行,create 不行 kubectl create -f deploy.yml kubectl apply -f deploy.yml --re...

    滚动更新的定义和目标

    滚动更新的含义

    一次只更新一小部分副本,成功后,再更新更多的副本,最终完成所有副本的更新。

    滚动更新的好处

    最大好处是零停机,整个更新过程始终有副本在运行,从而保证了业务的连续性。

    根据 yaml 创建资源, apply 可以重复执行,create 不行

    kubectl create -f deploy.yml
    kubectl apply -f deploy.yml --record
    

    注意 当deploy.yml 是上次发布的内容没有更改时,使用kubectl apply无法进行更新发布。比如镜像使用的是latest标签时。

    我们在发布deployment时,如果使用了如下的发布方式 或者 参数配置不正确时,会发现 服务会挂掉一会儿,用户会访问不了。

    kubectl  delete  --ignore-not-found=true -f deploy.yml
    kubectl  create -f deploy.yml
    

    原因是
    pod被删除或者 容器启动后,到服务真正工作起来,中间会有一段时间无法正常访问,但 k8s 却认为服务是正常就绪状态。

    本篇文章主要解决这个问题,实现 平滑的发布,发布更新服务过程中保证服务一直可用,用户零感知。

    设置滚动更新

    服务准备

    我们有一个api服务deploy.yaml如下:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: familytree-api
      namespace: default
    spec:
      selector:
        matchLabels:
          app: familytree-api
      replicas: 3
      template:
        metadata:
          labels:
            app: familytree-api
        spec:
          containers:
          - name: familytree-api
            image: 123.dkr.ecr.cn-sourthwest-1.amazonaws.com.cn/module/familytree-api-module:1.0.0
            imagePullPolicy: Always
            resources:
              requests:
                cpu: 1
                memory: 1Gi
              limits:
                cpu: 4
                memory: 4Gi
            env:
              - name: VERSION
                value: 1.0.0
            ports:
              - containerPort: 8080
    
    
    ---
    
    apiVersion: v1
    kind: Service
    metadata:
      name: familytree-api-service
      namespace: default
    spec:
      selector:
        app: familytree-api
      ports:
        - protocol: TCP
          port: 8080
          targetPort: 8080
    ---
    
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: familytree-api-ingress
      namespace: default
      annotations:
        kubernetes.io/ingress.class: traefik
        traefik.frontend.rule.type: PathPrefix
    spec:
      rules:
      -
        host: api.test.com
        http:
          paths:
          - path: /api/nowater
            backend:
              serviceName: familytree-api-service
              servicePort: 8080
    ---
    
    

    服务中包含url路由接口可返回版本号和当前hostname

    访问路由

       app.router.add_get('/api/nowater/version', service.version_print)
    

    实现代码如下:

    async def version_print(request):
        version = config["version"]
        hostname = socket.gethostname()
        try:
            print("打印版本 "+version+" hostname " + hostname)
            return web.json_response({'version': version, "hostname": hostname})
        except Exception as e:
            return web.json_response({'msg': e.value}, status=500)
    
    

    使用命令发布服务

    kubectl create -f deploy.yml
    

    查看部署列表

    kubectl get deployments | grep familytree-api
    

    查看正在运行的pod

    kubectl get pods  | grep familytree-api
    

    查看正在运行的pod使用的镜像

    kubectl get deployment -o wide  | grep familytree-api
    

    输出如下:

    [zzq@host3 ~]$ kubectl get deployment -o wide  | grep familytree-api
    familytree-api              3         3         3            0           4m        familytree-api             123.dkr.ecr.cn-sourthwest-1.amazonaws.com.cn/module/familytree-api-module:1.0.0   app=familytree-api
    

    通过pod描述,查看服务的当前映像版本

    kubectl describe pods  familytree-api-7c6fd4bb75-5qtr5 
    

    访问服务url

    [zzq@host3 ~]$ curl http://api.test.com/api/nowater/version
    {"version": "1.0.0", "hostname": "familytree-api-66f79b747c-rv69s"}
    

    进行滚动升级

    方式一 将yaml中的镜像版本修改为升级版本–推荐

     image: 123.dkr.ecr.cn-sourthwest-1.amazonaws.com.cn/module/familytree-api-module:2.0.0
    

    环境变量也修改为2.0.0

            env:
              - name: VERSION
                value: 2.0.0
    

    然后使用apply命令重新发布服务

    kubectl apply -f deploy.yml --record
    

    记得一定需要带有 --record,否则没有版本的信息记录,不利于回滚定位。

    方式二 使用命令

    kubectl  set image deployments/familytree-api familytree-api=123.dkr.ecr.cn-sourthwest-1.amazonaws.com.cn/module/familytree-api-module:2.0.0
    

    查看是否升级成功

    查看状态:

    kubectl rollout status deployment/familytree-api
    Waiting for rollout to finish: 1 out of 3 new replicas have been updated..
    deployment "familytree-api" successfully rolled out
    

    暂停升级

    kubectl rollout pause deployment <deployment>
    

    继续升级

    kubectl rollout resume deployment <deployment>
    

    升级结束后,继续查看rs的状态:

    kubectl get rs
    

    根据AGE我们可以看到离我们最近的当前状态是:3,和我们的yaml文件是一致的,证明升级成功了。用describe命令可以查看升级的全部信息:

    kubectl describe deployment familytree-api
    

    输出为

    [zzq@host3 ~]$ kubectl describe deployment familytree-api
    Name:                   familytree-api
    Namespace:              default
    CreationTimestamp:      Mon, 23 Sep 2019 18:12:43 +0800
    Labels:                 <none>
    Annotations:            deployment.kubernetes.io/revision=2
                            kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"kubernetes.io/change-cause":"kubectl apply --filename=./deploy/deploy-prod.yml ...
                            kubernetes.io/change-cause=kubectl apply --filename=./deploy/deploy-prod.yml --record=true
    Selector:               app=familytree-api
    Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
    StrategyType:           RollingUpdate
    MinReadySeconds:        0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
      Labels:  app=familytree-api
      Containers:
       familytree-api:
        Image:     123.dkr.ecr.cn-sourthwest-1.amazonaws.com.cn/module/familytree-api-module:2.0.0
        Port:       8080/TCP
        Host Port:  0/TCP
        Limits:
          cpu:     4
          memory:  4Gi
        Requests:
          cpu:     1
          memory:  1Gi
        Environment:
          VERSION:  2.0.0
        Mounts:     <none>
      Volumes:      <none>
    Conditions:
      Type           Status  Reason
      ----           ------  ------
      Available      True    MinimumReplicasAvailable
      Progressing    True    NewReplicaSetAvailable
    OldReplicaSets:  <none>
    NewReplicaSet:   familytree-api-c6fbb4499 (3/3 replicas created)
    Events:
      Type    Reason             Age   From                   Message
      ----    ------             ----  ----                   -------
      Normal  ScalingReplicaSet  20m   deployment-controller  Scaled up replica set familytree-api-66f79b747c to 3
      Normal  ScalingReplicaSet  3m    deployment-controller  Scaled up replica set familytree-api-c6fbb4499 to 1
      Normal  ScalingReplicaSet  3m    deployment-controller  Scaled down replica set familytree-api-66f79b747c to 2
      Normal  ScalingReplicaSet  3m    deployment-controller  Scaled up replica set familytree-api-c6fbb4499 to 2
      Normal  ScalingReplicaSet  3m    deployment-controller  Scaled down replica set familytree-api-66f79b747c to 1
      Normal  ScalingReplicaSet  3m    deployment-controller  Scaled up replica set familytree-api-c6fbb4499 to 3
      Normal  ScalingReplicaSet  3m    deployment-controller  Scaled down replica set familytree-api-66f79b747c to 0
    
    

    在这里插入图片描述

    访问服务url

    [zzq@host3 ~]$ curl http://api.test.com/api/nowater/version
    {"version": "2.0.0", "hostname": "familytree-api-c6fbb4499-vcbt7"}
    

    设置服务存活探针和服务健康检查探针以及相应参数

    探针官网介绍

    使用上面的发布步骤并不能保证 服务完全平滑。

    因为k8s不能判断 一个的服务是否已经可用,只要pod正常启动就会判断成 可用。

    但是pod启动后并不代表服务可用,比如java的程序 可能还需要启动spring boot框架,去连接数据库等待。

    这样就会导致 短暂的 服务不可用。

    服务不可用的示例

    比如我们一直访问准备好的version版本查询接口如下:

    while :; do curl  http://api.test.com/api/nowater/version; sleep 1; done
    

    然后进行版本更新发布

    kubectl apply -f deploy.yml --record
    

    输出如下:

    [zzq@host3 ~]$  while :; do curl http://api.test.com/api/nowater/version; sleep 1; done 
    ----------
    {"version": "1.0.0", "hostname": "familytree-api-66f79b747c-rv69s"}
    ----------
    {"version": "1.0.0", "hostname": "familytree-api-66f79b747c-rv69s"}
    ----------
    {"version": "1.0.0", "hostname": "familytree-api-66f79b747c-rv69s"}
    ----------
    {"version": "1.0.0", "hostname": "familytree-api-66f79b747c-rv69s"}
    ----------
    curl: (7) Failed to connect to  http://api.test.com/api/nowater/version: Connection refused
    curl: (7) Failed to connect to  http://api.test.com/api/nowater/version: Connection refused
    curl: (7) Failed to connect to  http://api.test.com/api/nowater/version: Connection refused
    curl: (7) Failed to connect to  http://api.test.com/api/nowater/version: Connection refused
    curl: (7) Failed to connect to  http://api.test.com/api/nowater/version: Connection refused
    ----------
    {"version": "2.0.0", "hostname": "familytree-api-c6fbb4499-vcbt7"}
    ----------
    {"version": "2.0.0", "hostname": "familytree-api-c6fbb4499-vcbt7"}
    ----------
    {"version": "2.0.0", "hostname": "familytree-api-c6fbb4499-vcbt7"}
    ----------
    {"version": "2.0.0", "hostname": "familytree-api-c6fbb4499-vcbt7"}
    ----------
    {"version": "2.0.0", "hostname": "familytree-api-c6fbb4499-vcbt7"}
    ----------
    
    

    我们可以发现镜像版本已经更新到2.0.0
    我们可以在2.0.0镜像中加入延迟启动服务,也就是说,会先sleep 20s,然后才去启动app服务。
    这就模拟了在服务启动过程中,虽然pod已经是存在的状态,但是并没有真正提供服务。
    可以看到,由于延迟启动,api并没有真正做好准备提供服务,此时流量已经发到后端,导致服务不可用的状态

    解决方案–探针检测

    在实际生产环境中会遇到这样那样的问题,比如:容器里面应用挂了或者说新启动的容器里面应用还没有就绪等等,所以说就需要进行探测来检验容器是否满足需求。

    那么一般的检测分为几种,比如:进程检测、业务检测。

    进程检测呢很好理解,也就是说通过检测容器进程来验证容器内应用是否存活。
    Kubelet会定期通过Docker Daemon获取所有Docker进程的运行情况,如果发现某个Docker容器未正常运行,则重新启动该容器进程。目前,进程级的健康检查都是默认启用的。

    业务检测呢也好理解,有些人会问,有了进程检测不就挺好的么,为什么要进行业务检测? 
    因为在很多实际场景下,仅仅使用进程级健康检查还远远不够。有时,从Docker的角度来看,容器进程依旧在运行;但是如果从应用程序的角度来看,假设应用代码处于死锁状态的话,那每次调度到这个容器的时候永远都无法正常响应用户的业务。比如对于使用java web服务的应用来说,并不是简单地说tomcat启动成功就可以对外提供服务的,还需要等待spring容器初始化,数据库连接连接上等等。

    为了解决以上问题,Kubernetes引人了一个在容器内执行的活性探针(liveness probe)的概念,以支持用户自己实现应用业务级的健康检查。这些检查项由Kubelet代为执行,以确保用户的应用程序正确运转,至于什么样的状态才算“正确”,则由用户自己定义。

    Kubernetes支持3种类型的应用健康检查动作,分别为HTTP Get、Container Exec和TCP Socket。exec的方式比较通用的,因为不是每个服务都有http服务,但每个服务都可以在自己内部定义健康检查的job,定期执行,然后将检查结果保存到一个特定的文件中,外部探针就不断的查看这个健康文件就OK了。

    介绍完存活性探针(liveness probe)之后我们来看看就绪探针(readiness probe),就绪探针是来确定容器是否已经就绪可以接受访问,只有当Pod中的容器都处于就绪状态时kubelet才会认定该Pod处于就绪状态,至于什么样的状态才算 ”就绪”,还是由用户自己定义。该状态的作用就是控制哪些Pod可以作为service的后端,如果Pod处于非就绪状态,那么它们将会被从service的load balancer中移除,防止 流量分发到 异常的pod中。

    存活性探针(liveness probe)和就绪探针(readiness probe)的区别

    readinessProbe检查成功与否,决定这个pod是否会被加入到Service的load balancer列表中,即是否给它分配访问的流量,并不影响Pod本身的生命周期

    如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活探针; kubelet 将根据Pod的restartPolicy自动执行正确的操作。

    如果您希望容器在探测失败时被杀死并重新启动,那么请指定一个存活探针,并指定restartPolicy为Always或OnFailure。

    如果要仅在探测成功时才开始向 Pod 发送流量,请指定就绪探针。在这种情况下,就绪探针可能与存活探针相同,但是spec中的就绪探针的存在意味着Pod将在没有接收到任何流量的情况下启动,并且只有在探针探测成功后才开始接收流量。

    两种探测的配置方法完全一样,支持的配置参数也一样,既可单独探测又可结合者一起执行。

    LivenessProbe:用于判断容器是否存活(running状态),如果LivenessProbe探针探测到容器不健康,则kubelet杀掉该容器,并根据容器的重启策略做相应的处理。如果一个容器不包含LivenessProbe探针,则kubelet认为该容器的LivenessProbe探针返回的值永远是“Success”。

    ReadinessProbe:用于判断容器是否启动完成(ready状态),可以接收请求。如果ReadinessProbe探针检测到失败,则Pod的状态被修改。Endpoint Controller将从Service的Endpoint中删除包含该容器所在Pod的Endpoint。

    存活性探测

    livenessProbe:存活性探测,最主要是用来探测pod是否需要重启–决定把pod删除重新创建

    在spec的containers中增加
    与image同级
    exec探针

            livenessProbe:
              exec:
                command:
    			- cat
    			- /tmp/healthy
              initialDelaySeconds: 5
              periodSeconds: 10
    		  timeoutSeconds: 2       
              failureThreshold: 3       
    

    http探针

        livenessProbe:
          httpGet:
            path: /health
            port: 8080
            scheme: HTTP
    

    tcp探针

      livenessProbe:
          tcpSocket:
            port: 8080
    

    periodSeconds 规定kubelet要每隔10秒执行一次liveness probe 检查。
    initialDelaySeconds 告诉kubelet在第一次执行probe之前要的等待5秒钟。
    timeoutSeconds 超长时长,默认为1s,最小值也为1s
    failureThreshold 处于成功状态时,探测操作至少连续多少次的失败才被视为检测不通过,默认为3,最小为1
    探针检测命令是在容器中执行 cat /tmp/healthy 命令。
    如果命令执行成功,将返回0,kubelet就会认为该容器是活着的并且很健康。如果返回非0值,kubelet就会杀掉这个容器并重启它。

    就绪性探测

    readinessProbe:就绪性探测,用来探测pod是否已经能够提供服务–决定是否参与分配流量

    在spec的containers中增加
    与image同级

            readinessProbe:
              tcpSocket:
                port: 80
              initialDelaySeconds: 5
              periodSeconds: 10
    

    或者

            readinessProbe:
              httpGet:
    		    path: /api/nowater/version
                port: 8080
    			httpHeaders:
    			- name : X-Custom-Header
    			  value: Awesome
              initialDelaySeconds: 5
              periodSeconds: 10
    

    periodSeconds 规定kubelet要每隔10秒执行一次readinessProbe 检查。
    initialDelaySeconds 告诉kubelet在第一次执行probe之前要的等待5秒钟。
    探针检测命令是检查tcp连接 端口80 是否畅通。
    也可以检查某个http 请求是否返回成功码。
    如果返回一个成功的返回码,kubelet就会认定该容器服务是可用的。
    如果返回失败的返回码,kubelet将该pod改为not ready,将会被从service的load balancer中移除。

    注意:任何大于200小于400的返回码都会认定是成功的返回码。其他返回码都会被认为是失败的返回码。

    由于设置了readinessProbe,虽然pod已经启动起来了,但是并不会立即投入使用,会出现了 READY: 0/1 的情况
    并且有pod出现了一直持续Terminating状态,因为滚动更新的限制,至少要保证有pod可用

    再查看curl的状态,image的版本平滑更新到2.0.0,没有出现报错的状况

    [zzq@host3 ~]$  while :; do curl http://api.test.com/api/nowater/version; sleep 1; done 
    ----------
    {"version": "1.0.0", "hostname": "familytree-api-66f79b747c-rv69s"}
    ----------
    {"version": "1.0.0", "hostname": "familytree-api-66f79b747c-rv69s"}
    ----------
    {"version": "1.0.0", "hostname": "familytree-api-66f79b747c-rv69s"}
    ----------
    {"version": "1.0.0", "hostname": "familytree-api-66f79b747c-rv69s"}
    ----------
    {"version": "2.0.0", "hostname": "familytree-api-c6fbb4499-vcbt7"}
    ----------
    {"version": "2.0.0", "hostname": "familytree-api-c6fbb4499-vcbt7"}
    ----------
    {"version": "2.0.0", "hostname": "familytree-api-c6fbb4499-vcbt7"}
    ----------
    {"version": "2.0.0", "hostname": "familytree-api-c6fbb4499-vcbt7"}
    ----------
    {"version": "2.0.0", "hostname": "familytree-api-c6fbb4499-vcbt7"}
    ----------
    
    

    调整参数设置

    在spec下面添加滚动升级策略:
    与template同级

    minReadySeconds: 5
    strategy:
      # indicate which strategy we want for rolling update
      type: RollingUpdate
      rollingUpdate:
        maxSurge: 1
        maxUnavailable: 1
    

    minReadySeconds:
    这个值默认是0,Kubernetes会假设该容器启动起来后就可以提供服务了,会导致用户访问异常
    这里需要估一个比较合理的值,从容器启动到应用正常提供服务
    如果没有设置该值,Kubernetes会假设该容器启动起来后就提供服务了
    如果没有设置该值,在某些极端情况下可能会造成服务不正常运行

    maxSurge:
    升级过程中最多可以比原先设置多出的POD数量
    例如:maxSurage=1,replicas=5,则表示Kubernetes会先启动1一个新的Pod后才删掉一个旧的POD,整个升级过程中最多会有5+1个POD。

    maxUnavaible:
    升级过程中最多有多少个POD处于无法提供服务的状态
    当maxSurge不为0时,该值也不能为0
    例如:maxUnavaible=1,则表示Kubernetes整个升级过程中最多会有1个POD处于无法服务的状态。

    格式如下

    在这里插入图片描述

    回滚

    查看Deployment的升级历史:

    kubectl rollout history deployment nginx-deploy
    

    查看指定版本的升级历史

    kubectl rollout history deployment nginx-deploy --revision=3
    

    假如现在要直接回退到当前版本的前一个版本:

    kubectl rollout undo deployment nginx-deploy
    deployment "nginx-deploy" rolled back
    

    当然也可以用revision回退到指定的版本:

    kubectl rollout undo deployment nginx-deploy --to-revision=2
    deployment "nginx-deploy" rolled back
    

    现在可以用命令查看Deployment现在的状态了。

    k8s滚动更新的原理

    部署(Deployment)自动创建副本集(ReplicaSet),副本集根据参数策略可以精确地控制每次替换的Pod数量,从而可以很好的实现滚动更新。具体来说,k8s每次使用一个新的副本控制器(replication controller)来替换已存在的副本控制器,从而始终使用一个新的Pod模板来替换旧的pod模板。

    大致步骤如下:

    1、创建一个新的replication controller。
    2、增加或减少pod副本数量,直到满足当前批次期望的数量。
    3、删除旧的replication controller。

    部署概况

    使用命令查看部署概况

    kubectl get deployment
    

    在这里插入图片描述

    上图包含的几个滚动发布过程标量,说明如下:

    DESIRED 最终期望处于READY状态的副本数
    CURRENT 当前的副本总数
    UP-TO-DATE 当前完成更新的副本数
    AVAILABLE 当前可用的副本数

    部署详情

    使用命令查看部署详情

    kubectl describe deployment familytree-api
    

    在这里插入图片描述

    从上图可以看到,k8s精确地控制着整个发布过程,滚动进行,直到所有副本全部更新。其实,k8s提供了两个参数maxSurge和maxUnavailable来精确地控制每次滚动的pod数量,如下:

    maxSurge 滚动更新过程中运行操作期望副本数的最大pod数,可以为绝对数值(eg:5),但不能为0;也可以为百分数(eg:10%)。默认为25%。
    maxUnavailable 滚动更新过程中不可用的最大pod数,可以为绝对数值(eg:5),但不能为0;也可以为百分数(eg:10%)。默认为25%。
    如果未指定这两个可选参数,则k8s使用默认配置,如下:

    kubectl  get deployment familytree-api -o yaml
    

    在这里插入图片描述

    剖析部署helloworldapi的标准输出:

    当前的副本总数 = 3 + 3 * 25% = 4,所以CURRENT为4。

    当前可用的副本数 = 3 - 3 * 25% = 2,所以AVAILABLE为2。

    整个滚动过程是通过控制两个副本集来完成的,新的副本集:familytree-api-c6fbb4499;旧的副本集: familytree-api-66f79b747c 。

    理想状态下的滚动过程:

    创建了一个新的副本集,并为其分配1个新版本的pod,使副本总数达到4,一切正常。
    通知旧副本集,销毁1个旧版本的pod,使可用副本总数保持到2,一起正常。
    当1个副本销毁成功后,通知新副本集,再新增1个新版本的pod,使副本总数达到4,一切正常。

    只要销毁成功,新副本集,就会创造新的pod,一直循环,直到旧的副本集pod数量为0。
    有时整个滚动过程也是不理想的,不符合上述的规律,会有一些混乱。

    k8s最终都会使服务全部更新到期望状态,始终保持最大的副本总数和可用副本总数的不变性

    deployment的常用命令和参数说明

    查看部署状态

    kubectl rollout status deployment/review-demo  --namespace=scm 
    
    kubectl describe deployment/review-demo --namespace=scm
    

    或者这种写法

    kubectl rollout status deployments review-demo --namespace=scm
    
    kubectl describe deployments review-demo --namespace=scm
    

    升级

    kubectl set image deployment/review-demo review-demo=library/review-demo:0.0.1 --namespace=scm
    

    或者

    kubectl edit deployment/review-demo --namespace=scm
    

    编辑.spec.template.spec.containers[0].image的值

    终止升级

    kubectl rollout pause deployment/review-demo --namespace=scm
    

    继续升级

    kubectl rollout resume deployment/review-demo --namespace=scm
    

    回滚

    kubectl rollout undo deployment/review-demo --namespace=scm
    

    查看deployments版本

    kubectl rollout history deployments --namespace=scm
    

    回滚到指定版本

    kubectl rollout undo deployment/review-demo --to-revision=2 --namespace=scm
    

    升级历史

    kubectl describe deployment/review-demo --namespace=scm
    
    Name: review-demo 
    Namespace: scm 
    CreationTimestamp: Tue, 31 Jan 2017 16:42:01 +0800
    Labels: app=review-demo 
    Selector: app=review-demo 
    Replicas: 3 updated | 3 total | 3 available | 0 unavailable 
    StrategyType: RollingUpdate 
    MinReadySeconds: 0 
    RollingUpdateStrategy: 1 max unavailable, 1 max surge 
    OldReplicaSets: <none> 
    NewReplicaSet: review-demo-2741031620 (3/3 replicas created) 
    Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 
    1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set review-demo-2741031620 to 1 
    1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set review-demo-1914295649 to 2 
    1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set review-demo-2741031620 to 2 
    1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set review-demo-1914295649 to 1 
    1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set review-demo-2741031620 to 3
    1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set review-demo-1914295649 to 0
    

    deployment文件

    apiVersion: extensions/v1beta1 
    kind: Deployment 
    metadata:  
    name: review-demo  
    namespace: scm  
    labels:  
    app: review-demo 
    spec:  
    replicas: 3 # 
    minReadySeconds: 60 #滚动升级时60s后认为该pod就绪  
    strategy:  
    rollingUpdate: ##由于replicas为3,则整个升级,pod个数在2-4个之间  
    maxSurge: 1 #滚动升级时会先启动1个pod  
    maxUnavailable: 1 #滚动升级时允许的最大Unavailable的pod个数  
    template:  
    metadata:  
    labels:  
    app: review-demo  
    spec:  terminationGracePeriodSeconds: 60 ##k8s将会给应用发送SIGTERM信号,可以用来正确、优雅地关闭应用,默认为30秒  
    containers:  
    - name: review-demo  
    image: library/review-demo:0.0.1-SNAPSHOT  
    imagePullPolicy: IfNotPresent  
    livenessProbe: #kubernetes认为该pod是存活的,不存活则需要重启  
    httpGet:  path: /health  
    port: 8080  
    scheme: HTTP  
    initialDelaySeconds: 60 ## equals to the maximum startup time of the application + couple of seconds  
    timeoutSeconds: 5 
    successThreshold: 1  
    failureThreshold: 5  
    readinessProbe: #kubernetes认为该pod是启动成功的  
    httpGet:  path: /health  
    port: 8080  
    scheme: HTTP  
    initialDelaySeconds: 30 ## equals to minimum startup time of the application  timeoutSeconds: 5  
    successThreshold: 1  
    failureThreshold: 5  
    resources: # keep request = limit to keep this container in guaranteed class  requests:  
    cpu: 50m  
    memory: 200Mi 
    limits:  
    cpu: 500m  
    memory: 500Mi  
    env:  
    - name: PROFILE  
    value: "test"  
    ports:  
    - name: http  
    containerPort: 8080
    

    几个重要参数说明
    maxSurge与maxUnavailable
    maxSurge: 1 表示滚动升级时会先启动1个pod
    maxUnavailable: 1 表示滚动升级时允许的最大Unavailable的pod个数
    由于replicas为3,则整个升级,pod个数在2-4个之间

    terminationGracePeriodSeconds
    k8s将会给应用发送SIGTERM信号,可以用来正确、优雅地关闭应用,默认为30秒。

    如果需要更优雅地关闭,则可以使用k8s提供的pre-stop lifecycle hook 的配置声明,将会在发送SIGTERM之前执行。

    livenessProbe与readinessProbe
    livenessProbe是kubernetes认为该pod是存活的,不存在则需要kill掉,然后再新启动一个,以达到replicas指定的个数。

    readinessProbe是kubernetes认为该pod是启动成功的,这里根据每个应用的特性,自己去判断,可以执行command,也可以进行httpGet。比如对于使用java web服务的应用来说,并不是简单地说tomcat启动成功就可以对外提供服务的,还需要等待spring容器初始化,数据库连接连接上等等。对于spring boot应用,默认的actuator带有/health接口,可以用来进行启动成功的判断。

    其中readinessProbe.initialDelaySeconds可以设置为系统完全启动起来所需的最少时间,livenessProbe.initialDelaySeconds可以设置为系统完全启动起来所需的最大时间+若干秒。

    这几个参数配置好了之后,基本就可以实现近乎无缝地平滑升级了。对于使用服务发现的应用来说,readinessProbe可以去执行命令,去查看是否在服务发现里头应该注册成功了,才算成功。

    展开全文
  • 该楼层疑似违规已被系统折叠隐藏此楼查看此楼12月12日10点,我们观察到游戏个别玩家的物品出现快速异常增长,为了保证游戏数据的安全,我们对全区进行了紧急停机维护。调查后,我们证实了导致这种物品异常增长的BUG...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

    12月12日10点,我们观察到游戏个别玩家的物品出现快速异常增长,为了保证游戏数据的安全,我们对全区进行了紧急停机维护。调查后,我们证实了导致这种物品异常增长的BUG存在。目前BUG已经得以修复,正常游戏的玩家数据在此次维护中不会受到任何影响,目前服务器已于23:30全部正常开放。

    对于因BUG产生的物品我们进行了清理以保证游戏环境的公平,部分玩家获得的非法装备和物品一律删除,而恶意利用BUG牟利的用户将视情节轻重被暂时封停,甚至永久封停。《QQ华夏》一直努力营造公平、纯净的游戏环境,给所有玩家一个良好的游戏体验,也感谢所有《QQ华夏》用户与我们一起一直致力于此。我们对BUG产生给广大用户带来的不便深感抱歉,但对蓄意利用BUG牟利的行为我们将进行最严厉的打击!

    本次停机维护时间较长,给广大用户游戏带来了不便,我们将对所有用户进行补偿:

    一、所有12月11日00:00 - 12月12日11:30前登陆过的用户都将获得5个对应等级的“速效令牌(绑)”的补偿;该补偿会在服务器开放前发放完毕,届时登陆游戏请玩家打开仓库领取“速效令牌(绑)”;

    二、12月13日 20:00 - 22:00全区举行“雪人大狂欢”活动,希望冬日的雪人能给大家带去游戏的快乐!

    三、12月12日正在使用女娲祝福、伏羲祝福、黄金葫芦、神农之锄、女娲试炼符这几种道具的玩家,道具有效时间将延长一天,此补偿将于下次维护后[12月18日]送出,请玩家查收

    另外:请在12月12日12:00已设置仓库密码的用户,请登陆游戏,重新设置一次仓库密码,已有的仓库密码已在停机维护时全部清除,请广大玩家放心,仓库中的正常物品,不会出现任何异常。

    最后,再次感谢在此次问题处理过程中给予我们支持与帮助的广大玩家!我们相信,有您的支持,QQ华夏的明天将会更灿烂更辉煌!

    《QQ华夏》运营团队

    2007年12月12日

    展开全文
  • 停机数据库迁移 我已经进行了一段时间的持续交付讨论 ,在我的讨论中,我描述了一种如何在不停机的情况下安全地将一个数据库迁移到另一个数据库的模式。 由于许多人联系我并要求提供更多详细信息,因此,我将在...

    不停机数据库迁移

    我已经进行了一段时间的持续交付讨论 ,在我的讨论中,我描述了一种如何在不停机的情况下安全地将一个数据库迁移到另一个数据库的模式。 由于许多人联系我并要求提供更多详细信息,因此,我将在此处按承诺提供更多详细信息。

    您可以使用此模式在两个不同的数据库之间迁移,例如在MySql和MongoDB之间或同一数据库中的两个模式之间迁移。

    这种模式的想法是使用功能切换来进行懒惰的数据库迁移,以控制应用程序的行为并逐步完成迁移的各个阶段。

    假设您要从“旧”数据库迁移到“新”数据库的两个数据库。

    第1步

    构建“新”数据库架构并将其部署到生产环境中。 在此阶段,您的系统保持不变,除了部署了一个新数据库(准备就绪后可以开始使用)之外,没有任何改变。

    第2步

    在您的应用程序中添加一个新的DAO,该DAO将写入“新”数据库。 您可能需要重构应用程序,以使其具有访问数据库的单个(或很少)点。 在您访问数据库或DAO的点上,您添加了一个多状态功能开关,该开关将控制写入数据库的流程。 此功能切换的第一个状态是“使用旧数据库”。 在这种状态下,您的代码将忽略“新”数据库,仅照常使用“旧”数据库。

    第三步

    开始写入“新”数据库,但将“旧”数据库用作主要数据库。 我们现在进入分布式事务世界,因为您永远无法百分百确定写入2个数据库可以同时成功执行失败操作。 当您的代码执行写操作时,它将首先写入“旧”数据库,如果成功,则还将写入“新”数据库。 请注意,在此步骤中,“旧”数据库处于一致状态,而“新”数据库则可能不一致,因为在“旧”数据库写成功的情况下,对它的写入可能会失败。

    在进行下一步之前,让此步骤运行一段时间(数天甚至数周)非常重要。 这将使您确信新代码的写入路径可以按预期工作,并且“新”数据库已正确配置且所有复制都已到位。

    任何时候,只要您确定某件事不起作用,您就可以简单地将功能切换回先前的状态,并停止写入“新”数据库。 您可以对新模式进行修改,如果需要,甚至可以删除它,因为所有数据仍在“旧”数据库中并且处于一致状态。

    安全数据库迁移模式

    第4步

    启用读取路径。 更改功能切换以启用从两个数据库中的读取。 在这一步中,重要的是要记住“旧”数据库是一致的数据库,仍应视为权威数据。

    由于有许多读取模式,因此在这里我只介绍几个,但您可以根据自己的用例进行调整。

    如果您的数据不可变,并且您知道首先从“新”数据库中读取的记录ID,并且如果您找不到该记录,则需要退回到“旧”数据库并在此处查找记录。 仅当两个数据库都没有记录时,您才向客户端返回“未找到”。 否则,如果找到记录,则返回结果,而不是“ new”数据库。

    如果数据是可变的,则仅当时间戳等于“旧”数据库中的记录时,才需要从两个数据库中执行读取操作,并且更喜欢“新”数据库。 请记住,在此阶段中,只有“旧”数据库被认为是一致的。

    如果您不知道记录ID,并且需要获取未知数量的记录,则基本上需要查询两个数据库并合并来自两个DB的结果。

    无论您采用哪种读取模式,请记住,在这种情况下,一致的数据库是“旧”数据库,但是在此阶段,您需要尽可能多地读取和使用“新”数据库读取路径,以便测试您的应用程序和您在实际生产环境中的新DAO。 在此阶段,您可能会发现缺少某些索引或需要更多的只读副本。

    在进入下一个阶段之前,让该阶段运行一段时间。 像在上一个阶段中一样,您始终可以将功能切换回原来的状态,而不必担心数据丢失。

    需要注意的另一件事是,由于您正在从两个模式中读取数据,因此可能需要维护这两个数据集的向后和向前兼容性。

    第5步

    使“新”数据库成为主要数据库。 将功能开关更改为首先写入新数据库(您仍然可以从两者中读取,但现在更喜欢新数据库)。 这是非常重要的一步。 在这一步中,您已经运行了一段时间的代码读写路径,当您感到舒适时,现在就可以切换角色并将“新”数据库设为一致的数据库,而将“旧”数据库设为不一致的数据库。 现在,您无需首先写入“新”数据库,而是先写入“新”数据库,然后尽最大努力写入旧数据库。 此阶段还要求您更改读取优先级。 到目前为止,我们认为“旧”数据库具有权威数据,但是现在您希望使用“新”数据库中的数据(当然,您需要考虑记录时间戳)。

    这也是您应尽力避免将功能切换切换回先前状态的要点,因为您将需要运行手动迁移脚本来比较两个数据库,因为它们可能会写入“旧”数据库未成功(记住分布式事务)。 我称此为“ 不归路 ”。

    第6步

    停止写入“旧”数据库(从两者读取)。 再次更改功能切换,现在停止写入只有“新”数据库的写入路径的“旧”数据库。 由于“新”数据库仍然没有所有记录,因此您仍然需要从“旧”数据库以及新数据库中读取并合并来自两者的数据。

    这是重要的一步,因为它基本上将“旧”数据库转换为“只读”数据库。

    如果您感觉足够舒适,则可以一次性执行步骤5和6。

    步骤7

    将数据从“旧”数据库迁移到“新”数据库。 现在,“旧”数据库处于“只读”模式,非常容易编写迁移脚本,以迁移“旧”数据库中不存在于“新”数据库中的所有记录。

    步骤8

    删除“旧” DAO。 这是将所有数据迁移到“新”数据库的最后一步,您现在可以安全地从代码中删除旧的DAO,而仅保留使用新数据库的新DAO。 您现在当然应该停止从“旧”数据库中读取数据,并删除处理来自两个DAO的合并数据的数据合并代码。

    完成此操作后,就可以安全地在两个数据库之间迁移数据,而无需停机。

    旁注:在Wix中,我们通常分别执行第3步和第4步至少2周,有时甚至一个月,然后再进行下一步。 在这些步骤中遇到的问题的示例是:

    在写路径上,我们将大型对象保存在内存中,这在高峰流量期间引起了GC风暴。 复制配置不正确/无法正常工作。 缺少适当的监视。

    在读取路径上,我们遇到诸如缺少索引的问题。 效率低下的数据模型导致性能不佳,这让我们重新考虑了数据模型以获得更好的读取性能。

    翻译自: https://www.javacodegeeks.com/2015/12/safe-database-migration-pattern-without-downtime.html

    不停机数据库迁移

    展开全文
  • 容易出现很多小小的失误,就像mysql当初优化不到位,影响整体网站的浏览效果一样,其实,网站的常规http状态码的表现也是一样,Google无法验证网站几种解决办法,提及到由于404状态页面设置不正常,导致了google管理...
  • 真正零停机 HAProxy 重载

    千次阅读 2016-12-05 21:01:57
    Yelp 础设施团队的主要目标之一就是尽可能的让网站响应接近零停机时间。那也就是说当用户访问www.yelp.com 作出动作的时候,网站的响应速度必须尽可能的快。一种方法是使用 HAProxy 负载均衡能够保持 www.yelp.com ...
  • 常见HTTP状态(304,200

    千次阅读 2014-08-26 14:28:55
    容易出现很多小小的失误,就像mysql当初优化不到位,影响整体网站的浏览效果一样,其实,网站的常规http状态码的表现也是一样,Google无法验证网站几种解决办法,提及到由于404状态页面设置不正常,导致了google管理...
  • 容易出现很多小小的失误,就像mysql当初优化不到位,影响整体网站的浏览效果一样,其实,网站的常规http状态码的表现也是一样,Google无法验证网站几种解决办法,提及到由于404状态页面设置不正常,导致了google管理...
  • 设置这个参数之后,在DCOS上再次测试,就能正常实现优雅停机了。  03 微服务部署  这时,回头看看我们的目标:整个部署过程中保证业务的连续性,让服务的客户端无感知。  1. 要做到应用容器停止不影响正在执行的...
  • 本文将介绍机器学习和统计分析的几种不同技术和应用,然后展示如何应用这些方法来对特定用例进行异常检测和状态监控。 数字化转型,数字化,工业4.0...... 这些都是你之前可能听过的术语。然而,这些流行语背后...
  • HTTP状态码分类(常用HTTP状态码和HTTP状态码大全)

    千次阅读 多人点赞 2018-03-07 18:07:30
    http状态码有什么用?http状态码的核心作用是Web Server服务器用来告诉客户端,当前的网页请求发生了什么事,或者说当前Web服务器的响应状态。所以HTTP状态码常用来判断和分析当前Web服务器的运行状况。作为一个...
  • CMPP3.0状态报告状态

    千次阅读 2018-07-12 11:30:17
    CMpp3.0状态报告表2007-10-31 17:47CB:0001 神州行预付费用户 CB:0005 PPS用户状态异常(包括未头次使用、储值卡被封锁、储值卡进入保留期、储值卡挂失) CB:0007 用户余额不足 CA 0054 发送消息失败 CB 0001 ...
  • 201-206都表示服务器成功处理了请求的状态代码,说明网页可以正常访问。  200(成功) 服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。  201(已创建) 请求成功且服务器已创建了新的资源...
  • 常见HTTP状态(200,304,404,503

    万次阅读 2013-01-24 07:55:22
    容易出现很多小小的失误,就像mysql当初优化不到位,影响整体网站的浏览效果一样,其实,网站的常规http状态码的表现也是一样,Google无法验证网站几种解决办法,提及到由于404状态页面设置不正常,导致了google管理...
  • 301、404、200、304HTTP状态 在网站建设的实际应用中,容易出现很多小小的失误,就像mysql当初优化不到位,影响整体网站的浏览效果一样,其实,网站的常规http状态码的表现也是一样,Google无法验证网站几种解决...
  • Tomcat停机过程分析及线程处理方法

    千次阅读 2018-04-21 20:31:19
    工作中经常遇到因为Tomcat shutdown时自己创建的线程因没有及时停止而引起的各种莫名其妙的报错,这篇文章将通过对Tomcat停机过程的梳理讨论产生这些错误的原因,同时提出了两个可行的解决办法。Tomcat停机过程分析一...
  • Tomcat停机过程分析与线程处理方法

    千次阅读 2018-02-26 17:07:19
    工作中经常遇到因为Tomcat shutdown时自身创建的线程没有及时停止而引起的各种莫名其妙的报错,这篇文章将通过对Tomcat停机过程的梳理,讨论产生这些错误的原因,同时提出了两个可行的解决办法。Tomcat停机过程分析...
  • 容易出现很多小小的失误,就像mysql当初优化不到位,影响整体网站的浏览效果一样,其实,网站的常规http状态码的表现也是一样,Google无法验证网站几种解决办法,提及到由于404状态页面设置不正常,导致了google管理...
  • 容易出现很多小小的失误,就像mysql当初优化不到位,影响整体网站的浏览效果一样,其实,网站的常规http状态码的表现也是一样,Google无法验证网站几种解决办法,提及到由于404状态页面设置不正常,导致了google管理...
  • 作为一个互联网开发人员对于一些服务器返回的HTTP状态的意思都必须是了如指掌的,只有将这些状态码一一弄清楚,工作中遇到的各种问题才能够处理的得心应手。好了,下面就让我们来...请求正常处理完毕 3xx Redire...
  • 如果向您的服务器发出了某项请求要求显示您网站上的某个网页(例如,当用户通过浏览器访问您的网页或在 Googlebot 抓取该网页时),那么,您的服务器会返回 HTTP 状态代码以响应该请求。 此状态代码提供了有关...
  • 当用户点击或搜索引擎向网站服务器发出浏览请求时,服务器将返回Http Header Http头信息状态码,常见几种如下: 1、Http/1.1 200 OK 访问正常  表示成功访问,为网站可正常访问时的状态。 2、Http/1.1
  • HTTP返回状态值详解

    千次阅读 2015-05-03 11:46:48
    当用户点击或搜索引擎向网站服务器... 表示成功访问,为网站可正常访问时的状态。   2、Http/1.1 301 Moved Permanently 301重定向永久重定向  对搜索引擎相对友好的跳转方式,当网站更换域名时可将原域名作
  • 容易出现很多小小的失误,就像MySQL当初优化不到位,影响整体网站的浏览效果一样,其实,网站的常规http状态码的表现也是一样,Google无法验证网站几种解决办法,提及到由于404状态页面设置不正常,导致了google管理...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,198
精华内容 5,279
关键字:

停机等非正常状态