GitLab 部署k8s deployment 502的问题

本文详细描述了一个在Kubernetes环境中遇到的服务更新问题,即在GitLab CI/CD部署过程中出现502错误。通过分析,确定问题是由于新旧服务切换不当导致。解决方案是调整Deployment的发布策略和添加ReadinessProbe,确保新服务准备就绪后再切断旧服务,避免服务中断。最终,通过配置就绪探针实现了不停机更新,保证了服务的高可用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.发现问题

2.分析问题

为啥需要解决这个问题呢?

3.解决问题

1. 调节发布策略,防止旧的deployment在新的deployment启动前销毁:

2.让新服务启动就绪后,再关闭旧的服务,访问新的服务:

4.问题总结


1.发现问题

如下图我们通过Git Lab的CI/CD完成最新的代码部署,但是当我们完成最后阶段的deploy的时候。访问服务,此时服务会无法访问。

这是会出现502的错误:

2.分析问题

为啥需要解决这个问题呢?

  • 服务不可用会导致这时候的用户无法完成相应的业务,而且如果没有重试或者容错处理,可能产生一些脏数据,可能有的记录了错误日志的还需要人工处理。
  • 还可能由于部分服务的不可用拖垮其他服务。
  • 为了提升用户的体验感,真正的做到不停机更新,就必须要解决到此问题。

既然是发布的时候出错就可能是新旧服务切换的时候出了问题。

要么是旧服务关闭早了,或者是新服务还没有就绪

3.解决问题

由于我们使用的是k8s对容器进行管理,所以查询了k8s关于在部署deployment时的一些参数配置。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-deployment
spec:
  selector:
    matchLabels:
      app: order
  replicas: 3
  template:
    metadata:
      labels:
        app: order
    spec:
      containers:
      - name: order-service

1. 调节发布策略,防止旧的deployment在新的deployment启动前销毁

 通过 strategy 可以配置 pod 的替换策略,主要参数如下。

.spec.strategy.type - 用于指定替换 pod 的策略类型。该参数可取值 Recreate 或 RollingUpdate,默认为 RollingUpdate

  • Recreate - K8s 会先删掉全部原有 pod 再创建新的 pod。该方式适用于新老版本互不兼容、无法共存的场景。但由于该方式会造成一段时间内服务完全不可用,在上述场景之外须慎用。
  • RollingUpdate - K8s 会将 pod 分批次逐步替换掉,可用来实现服务热升级。

发现我们就是滚动发布的方式,已经不需要更改。那么就看看新的deployment发布的配置。

2.让新服务启动就绪后,再关闭旧的服务,访问新的服务

查阅了相关资料,发现只有配置ReadinessProbe探针才能做到消除502,让服务一直处于可用的状态。

配置探针

K8s 提供以下两类探针:

  • ReadinessProbe - 默认情况下,一旦某个 pod 中的所有容器全部启动,k8s 就会认为该 pod 处于就绪状态,从而将流量发往该 pod。但某些应用启动后,还需要完成数据或配置文件的加载工作才能对外提供服务,因此通过容器是否启动来判断其是否就绪并不严谨。通过为容器配置就绪探针,能让 k8s 更准确地判断容器是否就绪,从而构建出更健壮的应用。K8s 保证只有 pod 中的所有容器全部通过了就绪探测,才允许 service 将流量发往该 pod。一旦就绪探测失败,k8s 会停止将流量发往该 pod。
  • LivenessProbe - 默认情况下,k8s 会认为处于运行状态下的容器是可用的。但如果应用在出现问题或不健康时无法自动退出(例如发生严重死锁),这种判断就会出现问题。通过为容器配置活性探针,能让 k8s 更准确地判断容器是否正常运行。如果容器没有通过活性探测,kubelet 会将其停止,并根据重启策略决定下一步的动作。

探针的配置非常灵活,用户可以指定探针的探测频率、探测成功阈值、探测失败阈值等。各参数的含义和配置方法可参考文档 Configure Liveness and Readiness Probes

样例为目标容器配置了就绪探针活性探针

  1. 就绪探针的 initialDelaySeconds 设置成 30,这是因为应用平均需要 30 秒时间完成初始化工作。
  2. 在配置活性探针时,需要保证容器有足够时间到达就绪状态。如果参数 initialDelaySeconds、periodSeconds、failureThreshold 设置得过小,可能造成容器还未就绪就被重启,以至于永远无法达到就绪状态。样例中的配置保证如果容器能在启动后的 80 秒内就绪就不会被重启,相对 30 秒的平均初始化时间有足够的缓冲。
  3. 就绪探针的 periodSeconds 设置成 10,failureThreshold 设置成 1。这样当容器异常时,大约 10 秒后就不会有流量发往它。
  4. 活性探针的 periodSeconds 设置成 20,failureThreshold 设置成 3。这样当容器异常时,大约 60 秒后就不会被重启。

4.问题总结

通过加上就绪探针readinessProbe的配置就可以在新的deployment真正启动,deployment能对外提供服务的时候,service再将流量转发过来,实现不停机更新的操作。

        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 60

 最后完整的k8s的service和deployment配置如下:

kind: Service
apiVersion: v1
metadata:
  name: order-service
spec:
  selector:
    app: order
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-deployment
spec:
  selector:
    matchLabels:
      app: order
  replicas: 3
  strategy:
    type: 
  template:
    metadata:
      labels:
        app: order
    spec:
      containers:
      - name: order-service
        image: code.darmi.com:5672/darmi/darmi-mall-service/order-service
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 15
          periodSeconds: 60
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 60
        nodeSelector:
          environment: dev  

<think>好的,用户想了解如何通过GitLabCI/CD流水线部署Kubernetes。首先,我需要回忆一下相关的步骤和配置。记得GitLabKubernetes的集成通常需要配置Cluster,然后在.gitlab-ci.yml文件中定义部署阶段。可能需要用到kubectl或者Helm之类的工具。 首先,用户可能需要先在GitLab中集成Kubernetes集群。这一步通常在项目的Operations > Kubernetes页面里添加集群信息,包括API URL和证书。不过证书部分可能需要使用base64编码,用户可能需要根据文档操作。 接下来是配置GitLab Runner,确保它能够执行部署任务。可能需要使用带有kubectl的Docker镜像,或者自己构建一个包含必要工具的镜像。比如,可以在.gitlab-ci.yml里指定image: alpine/k8s:1.18.2,这样容器里就有kubectl了。 然后,用户需要在CI/CD流水线中定义部署的job。通常分为构建和部署阶段。构建阶段可能包括Docker镜像的构建和推送到容器仓库,比如GitLab自己的Container Registry。部署阶段则需要使用kubectl apply或者helm upgrade来更新Kubernetes的资源。 另外,安全方面需要注意。用户可能需要设置KUBECONFIG环境变量,或者使用Service Account的token来进行认证。GitLab提供了Kubernetes集成,可以自动创建service account和secret,这样可以避免在代码中暴露敏感信息。 可能遇到的问题包括权限问题,比如Service Account是否有足够的权限进行部署,或者网络问题,比如GitLab Runner能否访问Kubernetes集群的API。这时候可能需要检查RBAC配置和网络策略。 用户可能还需要了解如何动态生成配置文件,比如使用envsubst替换变量,或者使用Helm chart进行模板渲染。这部分如果用户的项目比较复杂,可能需要更详细的步骤。 最后,测试流水线是否正常工作,查看日志排查错误。可能建议用户分阶段测试,先验证构建阶段,再测试部署阶段,逐步排查问题。 现在需要整理这些步骤,结构清晰,并且引用提供的参考资料。虽然用户给的引用可能不直接相关,但可以适当关联到GitLab CI/CD的一般流程,比如引用创建流水线的教程,或者集成外部系统的例子。</think>以下是使用GitLab CI/CD流水线部署Kubernetes的详细步骤: ### 1. 配置Kubernetes集群集成 - 进入GitLab项目 > **Operate > Kubernetes** - 点击**Add Kubernetes cluster**,选择**Existing cluster** - 填写集群信息: - API URL:`https://<your-k8s-api-server>:6443` - CA证书:通过`kubectl config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}'`获取[^1] - Service Token:创建具有部署权限的ServiceAccount(示例RBAC配置见下文) ### 2. 编写RBAC配置文件 ```yaml # deploy-role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: gitlab-deploy-role rules: - apiGroups: ["apps", ""] resources: ["deployments", "services", "pods"] verbs: ["get", "list", "watch", "create", "update", "patch"] --- # rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: gitlab-deploy-binding namespace: default subjects: - kind: ServiceAccount name: gitlab-deploy-sa roleRef: kind: Role name: gitlab-deploy-role ``` ### 3. 配置.gitlab-ci.yml ```yaml stages: - build - deploy build_image: stage: build image: docker:20.10 services: - docker:20.10-dind variables: IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker build -t $IMAGE_TAG . - docker push $IMAGE_TAG deploy_production: stage: deploy image: bitnami/kubectl:latest script: - kubectl config set-cluster ${KUBE_CLUSTER} --server=${KUBE_URL} - kubectl config set-credentials deploy-user --token=${KUBE_TOKEN} - kubectl config set-context ${KUBE_CONTEXT} --cluster=${KUBE_CLUSTER} --user=deploy-user - kubectl config use-context ${KUBE_CONTEXT} - kubectl set image deployment/myapp myapp=${IMAGE_TAG} --record only: - main ``` ### 4. 设置环境变量 在GitLab项目设置中配置: - `KUBE_URL`: Kubernetes API地址 - `KUBE_TOKEN`: 通过`kubectl get secret <service-account-secret> -o jsonpath='{.data.token}' | base64 -d`获取 - `KUBE_CLUSTER`: 集群名称(自定义) - `KUBE_CONTEXT`: 上下文名称(自定义) ### 5. 部署验证(可选) ```yaml verify_deployment: stage: deploy image: curlimages/curl:7.68 script: - curl -sS http://${PRODUCTION_ENDPOINT}/healthcheck | grep "OK" ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知始行末

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值