惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tenable Blog
MyScale Blog
MyScale Blog
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
博客园 - 司徒正美
D
Darknet – Hacking Tools, Hacker News & Cyber Security
量子位
N
News | PayPal Newsroom
S
Secure Thoughts
酷 壳 – CoolShell
酷 壳 – CoolShell
L
LINUX DO - 热门话题
有赞技术团队
有赞技术团队
V
Visual Studio Blog
T
Tailwind CSS Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Project Zero
Project Zero
B
Blog RSS Feed
J
Java Code Geeks
Google Online Security Blog
Google Online Security Blog
Last Week in AI
Last Week in AI
Cyberwarzone
Cyberwarzone
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
小众软件
小众软件
博客园 - 【当耐特】
Latest news
Latest news
T
Threat Research - Cisco Blogs
aimingoo的专栏
aimingoo的专栏
博客园_首页
博客园 - 三生石上(FineUI控件)
Engineering at Meta
Engineering at Meta
D
Docker
Forbes - Security
Forbes - Security
Help Net Security
Help Net Security
Apple Machine Learning Research
Apple Machine Learning Research
P
Proofpoint News Feed
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V2EX - 技术
V2EX - 技术
N
Netflix TechBlog - Medium
The Last Watchdog
The Last Watchdog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Threatpost
Cloudbric
Cloudbric
T
The Exploit Database - CXSecurity.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
Webroot Blog
Webroot Blog

陈少文的网站

巨变与机遇的未来十年 Kubernetes 平台管理软件压力测试方案 使用镜像部署 Hexo 静态页面 终于等到你 - GitHub 镜像仓库服务(ghcr.io) 一起来学 Go --(6)Interface 一起来学 Go --(5)Goroutine 和 Channel 什么是函数式编程 如何在 Kubernetes 集群集成 Kata 柯里化与偏函数 使用 PyGithub 自动创建 Label 软件产品是团队能力的输出 Helm 2 、Helm 3 比较 IoT 变现 Kubernetes 中的 DNS 服务 国内的 Helm 镜像源 Harbor 使用自签证书支持 Https 访问 DevOps 工具链之 Prow 如何使用 kfctl 安装 Kubeflow VS Code 无法下载 Go 插件的工具包 工程师更应具有服务精神 你不知道的 Docker 使用技巧 使用 Docker 运行 Tensorflow 论中国 什么是左移 如何清空 Git 仓库全部历史记录 一禅小和尚 有风吹过厨房 时间的玫瑰 如何在 CentOS 安装 GPU 驱动 开发 Tips(19) 使用 Velero 备份 Kubernetes 集群 Kubernetes Cheat Sheet 开发 Tips(18) 如何构建一个 Java 工程 开发 Tips(17) KubeSpray 安装 Kubernetes 报错 ip in ansible_all_ipv4_addresses 基于 Kubernetes 和 Jenkins 搭建自动化测试系统 在 Kubernetes 上动态创建 Jenkins Slave 使用 Jenkins 进行服务拨测 开发 Tips(16) Kubernetes 签发 Ingress 证书及日常故障运维 Kubernetes 中 Deployment 的基本操作 Kubernetes 中的证书 如何使用 KubeBuilder 开发一个 Operator Kubernetes 1.6.0 安装问题汇总 镜像管理工具 -- Harbor 开发 Tips(15) Docker 如何拉取镜像 开发 Tips(14) 使用 Helm 安装 harbor 开发 Tips(13) 使用 S2I 构建云原生应用 在 Kubernetes 中使用 emptyDir、hostPath、localVolume 开发 Tips(12) 开发 Tips(11) 代码质量分析工具 SonarQube 使用 Kubeadm 安装 Kubernetes 集群 一起来学 Go --(4)常用函数 Kubernetes 中的 Ceph Kubernetes 之 Volumes Kubernetes 之 Labels、Selectors 开发 Tips(10) 开源正在重构商业模式 Kubernetes 之网络 Kubernetes 之 API 使用 Helm 和 Operator 快速部署 Prometheus Kubernetes 复杂有状态应用管理框架 -- Operator Kubernetes 的包管理器 -- Helm 一起来学 Go --(3)Go Modules 如何一步一步地优化博客方案 kubectl 实用指南 Kubernetes 中的基本概念 搭建远程 Kubernetes 开发环境 大公司和小公司的 ToB 思路 开发 Tips(9) Go 入门指南 一起来学 Go --(2)数据与逻辑结构 如何预防 Web 富文本中的 XSS 攻击 django-xss-cleaner 云工作时代 一起来学 Go --(1)背景与特点 SaaS 开发团队的不同阶段 你不知道的 Git 使用技巧 输出既服务 微服务设计 继续奔跑 开发 Tips(8) 从账户安全到二次验证 Django 性能之数据库查询优化 Django 性能之分库分表 敏捷开发之研发流程 打造一致性的团队 开发 Tips(7) Pytest 进阶学习之 Mock PaaS 部署之 buildpack Go 开发配置 领域输出才是 PaaS 的核心竞争力 Pytest 入门学习 开发 Tips(6) 如何使用 Jenkins、Docker、GitLab 搭建 Django 自动化部署流程
KubeSphere DevOps 3.0 流水线运维指南
微信公众号 · 2020-10-14 · via 陈少文的网站

本篇主要介绍如何运维 DevOps 流水线,怎么解决一些常见的问题。问题主要分为两大类,一类是 Kubernetes 相关的,具有一定通用性;另一类是与业务相关,需要对领域有所了解,解决问题时才能事半功倍。文档内容,会不断滚动更新。

1. Kubernetes 问题排查

1.1 基本的创建流程

如上图所示,是用户创建一个 Deployment 的简单流程。主要分为以下步骤:

  1. kubectl 根据用户输入的命令,填充相关字段,将 deployment/pvc 对象发送给 kube-apiserver
  2. kube-apiserver 会有一系列的权限/准入控制,最终将数据序列化存储在 etcd 中
  3. kube-controller-manager 包含大量的控制器,这些控制器会生成 replicaset/pod 对象存储在 etcd 中。pvc 需要绑定到 pv 上,如果没有满足要求的 pv,则通过 Storage Class 动态创建一个 pv 。
  4. kube-sheduler 负责给 pod 选择运行的 node 节点,然后将 NodeName 字段写入 pod 对象中。
  5. kubelet 发现当前 node 节点有待创建的 pod,然后开始调用 CRI 接口去管理 pod 的生命周期。如果有 pvc,还需要将远程磁盘挂载到宿主机目录。

了解基本的创建流程,有利于排查各种可能的故障。故障可以理解为集群生命周期中的一个状态,而创建是整个生命周期的起点。同时,重置、重启是非常快速地解决问题的方法,都涉及创建。

1.2 解决集群故障的思路

如上图所示,是我的集群故障修复思路。主要分为以下步骤:

  1. kubectl get 检查 node、pod 等资源是否符合预期
  2. kubectl describe 查看 Kubernetes 中的事件信息,包括 kube-sheduler 的调度、拉取镜像、启动是否成功等。通常能解决大部分的问题。
  3. kubectl logs 查看负载的日志。当 pod 处于 running,但是又无法正常提供服务时,logs 信息能够给出有用的提示。有时无法查看 pod 中容器的日志,那么需要去 pod 所在的节点查看 docker 的日志。journal 通过 -u 参数指定服务,通过 -f 查看滚动的最新日志,也十分有用。
  4. 如果上面两种思路还不能解决问题,那么恭喜你,又有机会提高自己了。检查底层服务,也就是检查集群的基础环境,包括磁盘、允许的协议、允许的端口、防火墙、网络等。最终能不能解决,取决于你的积累和检索问题答案的能力。

1.3 必要的检查项

这里列举一些必要的检查项,可以辅助排查问题。

  • node 负载

node 负载过高时,有可能导致节点 NotReady。

  • node 磁盘

磁盘包括两部分,大小和 inode。

  • swap、firewall

安装集群时的配置,在重启机器之后,可能会失效。

  • 跨 node 的 pod 通信

跨节点通信异常时,会导致服务无法访问。

  • node 节点上 kubelet、docker 的状态

systemctl status kubeletsystemctl status docker 查看组件的状态。

  • 检查 kubelet 、docker 的配置

ps aux|grep kubeletdocker info 查看相关配置是否符合预期。

  • 查看存储 CSI 存储插件日志

通常 StorageClass 是通过 CSI 插件提供存储服务的,可以查看相关日志,检查是否有异常输出。

  • 检查 ip 转发功能

执行命令 cat /proc/sys/net/ipv4/ip_forward ,如果输出 0 则表示未开启。ip 转发允许将一个端口的包转发到另外一个端口。未开启时,会导致网络访问失败,tcpdump 中发送了大量 syn 数据包,但是没有 ack 。

  • 检查 Pod CIDR 与主机网段是否冲突

可以先查看 Pod 的 ip,检查其与主机、VPC 的 ip 是否有重叠。如果发生冲突,将会导致服务不可访问,提示 No route to host 类似的错误,需要修改 CIDR 。

2. 安装问题

如上图所示,是 installer 在执行安装 DevOps 时的依赖关系。DevOps 主要有两个核心组件 S2I 和 Jenkins 。S2I 依赖于 minio 存储文件,Jenkins 依赖于 uc 提供插件下载、依赖 openldap 打通账户体系。

安装时,比较常见的是 minio 安装失败,导致 DevOps 无法继续安装。而 minio 安装失败通常又是存储和网络导致。

3. Jenkins 运维问题

3.1 修改默认配置导致异常

DevOps 允许用户自定义配置,但 Jenkins /configureSecurity/ 页面中鉴权和 CSRF Protection 不要修改。

修改上图,红色框中的内容,会导致流水线无法使用。

3.2 大量多分支流水线占满磁盘空间

多分支流水线扫描时,会将仓库拉取到 /var/jenkins_home/cache 中,查找 jenkinsfile 文件。

如果大量实践多分支流水线扫描,请将 Jenkins 的 pv 设置大一些,50 GB 以上。

3.3 Lightweight 问题导致并发流水线冲突

具体可以参考文档: Jenkins 中 Lightweight 拉取代码问题分析

3.4 多节点集群,无法创建流水线

节点之间通信问题,可以将 ks-controller-manager 和 ks-jenkins 调度到一个节点进行验证。

如果能够创建成功,那么 Pod 的跨节点通信有问题。

3.5 流水线并发数量少

调整 ks-jenkins 的 cpu 和 memory 限制,还有 Xms、Xmx 值。

具体调整可以参考文档: Kubernetes 动态创建 Jenkins Agent 压力测试

3.6 流水线部署报错

Jenkins 的 Kubernetes Deploy 插件提示可读性不是十分友好,可能的原因有:

  • apiVersion 版本不支持
  • namespace 没有提前创建
  • yaml 本身有问题
  • 凭证有问题
  • 创建的凭证和使用的凭证 ID 不一致

可以在节点上直接执行 kubectl apply 进行验证。怀疑凭证有问题时,可以直接使用 admin 的凭证,进行确认。

如果是 EKS 集群,请参考 https://github.com/kubesphere/community/issues/165 单独生成凭证。EKS 上使用 DevOps 进行部署,需要的是 token 类型的凭证,证书类型的凭证没有足够的权限。简单点,可以直接使用 kubectl -n kubesphere-system get secret kubesphere-token-xxx -o jsonpath={.data.token} | base64 -d 拿到 token,替换至 kubeconfig 。

3.7 流水线一直 Pending,Kubernetes 无法创建 Pod

如果流水线无法执行,并且 kubectl -n kubesphere-devops-system get pod 下没有发现为运行流水线新创建的 Pod,那么很有可能是受限于准入控制。

kube-apiserver 提供了在创建负载时,修改负载相关信息的能力。比如,Istio 通过 webhook 在创建 Pod 时,向其中注入 Sidecar 进行微服务治理。但如果 Istio 组件发生了异常,那么也会导致 Pod 一直等待注入,从而无法创建 Pod 的现象。

解决办法是,给运行的命名空间加上豁免注入的标签,比如,kubectl label namespace kubesphere-devops-system istio-injection=disabled

3.8 变量引用不生效或者流水线引用变量报错

${env.<ParameterName>}${params.<ParameterName>}${<ParameterName>} 都可以引用变量,也可以用于 Stage 之间传值。在引用变量时,常见的错误是没区分单双引号。单引号并不替换变量,双引号才会替换变量,这与 Shell 一致。

另外需要注意,作用域。如果提示 groovy.lang.MissingPropertyException: No such property: ,而你又十分确认定义了这个变量,那么很有可能是作用域的问题。只需要带上 envparams 再试一次就行。

3.9 图形化编辑时,报错 至少需要一个嵌套步骤

API 提示报错 instance failed to match at least one schema 。流水线部分,前端页面图形化与后端数据模型是通过 pipeline-model-api 插件相互转换的。具体接口是 /tojson/tojenkinsfile ,前端编辑的是 json ,后端需要的是 jenkinsfile 。

例如,下面这个示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
pipeline {
  agent any
  stages {
      stage ('Hello') {
          steps {
              echo "Hello"
          }
      }
  }
}

将被转换为如下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
"pipeline":{
  "stages": [
    {
    "branches": [
      {
      "name": "default",
      "steps": [
        {
        "arguments": [
          {
          "key": "message",
          "value": {
            "isLiteral": true,
            "value": "Hello"
          }
          }
        ],
        "name": "echo"
        }
      ]
      }
    ],
    "name": "Hello"
    }
  ],
  "agent": {
    "type": "any"
  },
  "parameters": {}
}

json 格式的流水线对前端十分友好,scheme 非常简单,极大降低实现图形化编辑的难度。转换失败时,页面会展示错误提示。如果返回错误提示为空,那么页面会展示 当前 Jenkinsfile 不是标准的声明式 Jenkinsfile,无法进行图形化显示

前端只覆盖了常见的几种情况,提示不是十分准确,例如,当 defaultValue 为空字符串时,提示 至少需要一个嵌套步骤 ,不知所云。最好能够直接参考 /tojson 接口的返回进行处理。

3.10 构建镜像时,无法访问外部服务,报错 timeout

在 Jenkinsfile 中执行 docker build 命令时,由于是 Docker in Docker 网络,使用的是 Node 节点上的 Docker Daemon 进行构建。看着是动态创建的 Pod 无法访问外网,其实是 Node 节点无法访问指定外部服务。

这很有可能是,对网络要求严格的运行环境,禁止了主机访问外网所致。使用 iptables 命令,添加白名单即可。

3.11 升级时,PVC 报错

常见的两种报错提示是 The PersistentVolumeClaim "pvc1" is invalid: spec: Forbidden: is immutable after creation except resources.requests for bound claimsError: UPGRADE FAILED: cannot patch "mysql" with kind PersistentVolumeClaim: persistentvolumeclaims "mysql" is forbidden: only dynamically provisioned pvc can be resized and the storageclass that provisions the pvc must support resize

报错原因是 StorageClass 不支持动态扩容,需要保持升级前后 PVC 容量一致。

在升级之前,可以通过 describe 命令检查 StorageClass 是否支持动态扩容。如果 AllowVolumeExpansion 被设置,则代表支持;否则不支持。

3.12 安装不兼容的插件之后,Jenkins 无法启动

处理办法是进入 Jenkins 运行的 Pod,删掉不兼容的插件。

首先 exec 进入 Pod

1
kubectl -n kubesphere-devops-system exec -it ks-jenkins-xxx bash

然后进入 /var/jenkins_home/plugins 目录,删掉 Jenkins Pod 日志中提到的引发错误的插件。如果你安装了大量的插件,这里有一个技巧是按照日期删除。

有时候,插件之间具有复杂依赖,还有一个救急的方式是直接清空 /var/jenkins_home/plugins ,Jenkins 会根据 /var/jenkins_home/plugins.txt 从 UC 中下载插件,恢复至初始状态。

3.13 修改鉴权策略之后,无法登陆

处理办法是进入 Jenkins 运行的 Pod,将 useSecurity 改为 false,登陆之后改回原来的值。

useSecurity 在 /var/jenkins_home/config.xml 中进行配置。

3.14 Jenkins 找不到用户,LDAP 报错(重置密码)

提示信息类似:

1
2
org.acegisecurity.userdetails.UsernameNotFoundException: User admin not found in directory.
at hudson.security.LDAPSecurityRealm$LDAPUserDetailsService.loadUserByUsername(LDAPSecurityRealm.java:1314)

Jenkins 用户来源于 OpenLdap 组件,报错信息的含义是在 OpenLdap 组件中找不到 admin 用户。解决这个问题,需要检查两个地方:OpenLdap 组件是否异常、admin 用户是否在 OpenLdap 中。然后,修复组件,重新创建 admin 用户。

重建方法从代码 https://github.com/kubesphere/kubesphere/blob/release-3.0/pkg/controller/user/user_controller.go#L537 中可以发现,需要编辑 admin 用户的加密注解。执行命令 kubectl patch users admin --type merge --patch '{"spec":{"password":"P@88w0rd"}, "metadata":{"annotations":{"iam.kubesphere.io/password-encrypted":"false"}}}' 将 admin 用户登陆密码重置为默认值,触发同步逻辑。此条命令也可以用于重置密码。

3.15 流水线创建之后,在页面查看不到

在 3.0.0 中,采用 CRD 对 DevOps 工程和 Pipeline 进行管理,最终同步到 Jenkins 中。流水线创建之后,在页面无法查看到,是没有完成同步。没有完成同步的可能性很多,ks-controller-manager 中的日志将会帮到你。可能是节点之间的网络通信问题,也有可能是 Jenkins 服务发生了异常,需要根据错误日志排查。

3.16 找不到 Docker 命令

首先得了解 Jenkins 创建 Agent 运行流水线的过程:

  1. agent 模板中, 需要挂载 docker.socket 文件
  2. 运行流水线时, Jenkins 通 label 选中一个 agent
  3. Kubernetes 会以 agent 的配置作为模板,创建一个 Pod
  4. 执行 docker 时,需要在 container 包裹下执行(否则使用默认容器 jnlp)

如果执行流水线时,提示找不到 Docker 命令,那么可能是使用了 jnlp 容器。请检查步骤 4, 选中一个包含 docker 命令,并挂载了 docker.socket 的容器。