背景

客户有一个java应用比较耗内存,在kubernetes上对cpu和内存进行了限制,但效果不大好,应用经常被kill掉,由于该应用属于核心应用,后面就解除限制,在jvm上对堆内存进行了限制,因为没有配置kubernetes资源请求限制,kubernetes在调度上就无法灵活调度,经常将多个副本调度到同一节点,多个大内存应用运行在同一个节点,内存很容易就被耗尽导致jvm gc频繁,频繁的gc又导致了服务器cpu负载过大,最终应用挂掉无法访问。如果kubernetes能将应用多个副本调度到不同节点那么至少能保证一个节点挂掉,其他节点应用还可以继续服务。

方案

  • DaemonSet

首先想到的是DaemonSet,DaemonSet能保证应用跑在不同的节点,但DaemonSet应用场景一般是作为守护进程或者日志收集,并且每个节点都会部署一个副本,这并不是我们想要的结果,因此不考虑DaemonSet。

Read the rest of this entry

背景

客户通过Jenkins流水线构建镜像上传harbor部署到kubernetes,经过不断的CI/CD,harbor占用空间不断增大,但旧的镜像其实是可以删除掉,保留最新的几个版本供回滚就可以,因此需要制定删除策略,目前情况如下

  • 保留每个镜像最新3个版本即可
  • 用户通过tag区分环境,比如 definesys/hr:dev.20210601,definesys/hr:uat.20210601,这样就导致如果保留最新3个镜像,有可能都保留了dev.xxx,其他环境的都被删除,因此也要考虑按照环境做分组,只保留每个分组内的最新3个版本即可

harbor本身并没有提供类似的功能,但是harbor有完善的restapi,因此可以自己写工具去实现以上需求。

方案

  • java开发清理程序,打包为jar包,通过Main运行
  • 通过jenkins打包应用并执行清理动作

之所以选择jenkins运行jar包,是因为jenkins可以提供配置参数界面,可以将清理程序的一些配置项通过jenkins传入,省的再去开发界面,而且jenkins有定时调度的功能,可以实现定时清理的功能。

Read the rest of this entry

,

背景

某客户kubernetes集群新加了一个节点,新节点部署应用后,应用会间歇性unavaliable,用户访问报503,没有事件消息,主机状态也正常。

排查

初步怀疑是新节点问题,在系统日志/var/log/messagedmesg中都未发现相关错误信息,在kubelet中发现以下日志

kubernetes集群时通过rke进行安装,可以在节点上直接执行命令docker logs -f --tail=30 kubelet查看kubelet日志
E0602 03:18:27.766726    1301 controller.go:136] failed to ensure node lease exists, will retry in 7s, error: an error on the server ("") has prevented the request from succeeding (get leases.coordination.k8s.io k8s-node-dev-6)
E0602 03:18:34.847254    1301 reflector.go:178] k8s.io/client-go/informers/factory.go:135: Failed to list *v1.CSIDriver: an error on the server ("") has prevented the request from succeeding (get csidrivers.storage.k8s.io)
I0602 03:18:39.176996    1301 streamwatcher.go:114] Unexpected EOF during watch stream event decoding: unexpected EOF
E0602 03:18:43.771023    1301 controller.go:136] failed to ensure node lease exists, will retry in 7s, error: an error on the server ("") has prevented the request from succeeding (get leases.coordination.k8s.io k8s-node-dev-6)

Read the rest of this entry

,

背景

某项目kubernetes环境某个应用每隔20分钟左右就会重启一次,时间不固定,但在容器事件里面没有任何记录。

排查

首先怀疑是健康检查没过导致容器自动重启,以下是健康检查的配置

按照该配置,检查间隔30s,不健康阈值60,也就是1800s=30分钟后会标记为不健康,但很快就排除该猜测,理由是

  • 手动调用健康检查是ok的
  • 后台有健康检查的记录,记录显示也都是通过的
  • 如果是健康检查不过的话,事件里面会有记录,这里找不到记录

正常情况下如果kubernetes重启pod那会在事件里记录重启的原因,但事件里面没有任何记录,所以可能不是kubernetes重启的,那么很容易想到一个可能性就是OOM,也就是进程因为内存使用超过限制触发OOM操作系统将其kill掉,查看操作系统日志/var/log/messages发现以下日志

Read the rest of this entry

weblogic Provider

做过OAM,OID项目的同学应该都知道,要集成OAM和OID需要在weblogic的Security Realms中配置Provider,那什么是Provider?在业务系统中,认证和授权一直是最复杂的一块,体现在

  • 认证协议多样性,比如OAuth2,SAML等
  • 认证方式多样性,比如二次认证,验证码认证等
  • 认证策略多样性,比如有多个认证源,策略可以多样性,可以是一个不通过就不通过,也可以是只要有一个通过就全部通过
  • 自定义认证的需求,这个在企业里面还是挺多的,一些系统上线时还没有相应的标准出来,所以都是自开发
  • 密码认证策略多样性,大部分系统密码存储是不可逆的,如果一开始没有将密码存储在LDAP之类的服务里,后续如果要做升级,就无法拿到原始密码,那么就需要自定义密码认证策略。

总之,认证并不是用户名密码验证这么简单,所以weblogic针对不同的认证场景提供不同的Provider,weblogic作为成熟的商业服务器,自然包含大部分认证场景,以weblogic 11g为例,包含了以下Provider

Read the rest of this entry

介绍

harbor支持docker compose和helm两种方式进行安装,一般情况下如果是kubernetes运行环境推荐用helm进行安装,如果是纯docker环境建议用docker compose进行安装,本次安装使用helm进行安装,安装版本为v2.2.1

创建命名空间

harbor包含服务较多,建议单独创建命名空间进行安装,便于后续的管理

apiVersion: v1
kind: Namespace
metadata:
  name: harbor
  labels:
    name: harbor

另存为harbor-namespace.yaml文件,并执行kubectl apply -f harbor-namespace.yaml命令进行创建

创建共享目录

目录必须创建在共享存储的介质上面,比如NFS等

mkdir -p /u02/appdata/harbor/registry
mkdir -p /u02/appdata/harbor/chartmuseum
mkdir -p /u02/appdata/harbor/jobservice
mkdir -p /u02/appdata/harbor/database
mkdir -p /u02/appdata/harbor/redis
mkdir -p /u02/appdata/harbor/trivy
chmod 777 /u02/appdata/harbor/registry
chmod 777 /u02/appdata/harbor/chartmuseum
chmod 777 /u02/appdata/harbor/jobservice
chmod 777 /u02/appdata/harbor/database
chmod 777 /u02/appdata/harbor/redis
chmod 777 /u02/appdata/harbor/trivy

Read the rest of this entry

, ,

背景

某项目应用需迁移到k8s环境,其中有个应用配置了Ingress,但通过域名访问,始终返回503服务不可用,应用服务都是正常的

➜ curl -v http://mdm-sts-test.xxx.com
<center><h1>503 Service Temporarily Unavailable</h1></center>
<hr><center>nginx/1.19.2</center>

从错误日志可以看出503是nginx返回的,并不是后端服务返回(后端tomcat),也就是说请求可能根本没有到达后端服务

排查

将Ingress连接到其他应用的service,还是继续报错,将Ingress的域名换成其他域名,结果正常,所以从测试结果上看应该是域名出问题。因为该域名已经在dns中配置,所以怀疑是不是又解析回到dns造成死循环(虽然k8s不会犯这么低级的错误),把域名配置到了hosts文件也是一样的错误,而且有类似配置的应用也都是正常的,这个猜测被否定。

Read the rest of this entry

背景

某项目需要升级kubernetes集群,考虑到原k8s版本较低,并且在部署结构上不是很合理,因此决定重新搭建一套新的k8s集群,做应用迁移。迁移过程也是非常曲折,这个后面会专门写一篇文章记录,应用迁移后有部分应用在注册中心状态为DOWN

如果服务状态为DOWN调用该服务就报404错误,因为应用配置了健康检查,怀疑是健康检查没有通过,进入后台调用接口查看检查结果

$ curl http://localhost:8080/management/health
{"description":"Remote status from Eureka server","status":"DOWN"}

服务使用jhipster框架生成,在配置文件里面有以下配置

eureka:
    client:
        enabled: true
        healthcheck:
            enabled: true
        fetch-registry: true
        register-with-eureka: true
        instance-info-replication-interval-seconds: 10
        registry-fetch-interval-seconds: 10

eureka.client.healthcheck.enabled设置为false后,注册中心恢复正常,因此可以肯定是健康检查的问题。但是在后台没有任何错误,甚至将日志级别调整到最低也未发现错误信息,这个给排查带来很大的困难。

Read the rest of this entry

,

背景

在docker中,为了尽可能缩减镜像大小,常常不会包含一些常用的工具,类似ping,curl,tcpdump等,虽然精简了镜像,但如果我们需要在容器内部测试网络联通性时,没有这些工具就非常的头疼。其实容器内部和主机之间的网络环境是互相隔离的,处于独立的命名空间下,那如果能在主机上切换命名空间,就可以在主机上以容器的网络环境进行操作,就可以利用主机上的工具,能够实现这种需求的工具就是我们今天要介绍的nsenter

使用

nsenter [options] [program [arguments]]
options:
-t, --target pid:指定被进入命名空间的目标进程的pid
-m, --mount[=file]:进入mount命令空间。如果指定了file,则进入file的命令空间
-u, --uts[=file]:进入uts命令空间。如果指定了file,则进入file的命令空间
-i, --ipc[=file]:进入ipc命令空间。如果指定了file,则进入file的命令空间
-n, --net[=file]:进入net命令空间。如果指定了file,则进入file的命令空间
-p, --pid[=file]:进入pid命令空间。如果指定了file,则进入file的命令空间
-U, --user[=file]:进入user命令空间。如果指定了file,则进入file的命令空间
-G, --setgid gid:设置运行程序的gid
-S, --setuid uid:设置运行程序的uid
-r, --root[=directory]:设置根目录
-w, --wd[=directory]:设置工作目录
如果没有给出program,则默认执行$SHELL。

Read the rest of this entry

Rancher安装

执行以下命令安装最新版本rancher

docker run --privileged -d --restart=unless-stopped -p 8080:80 -p 4443:443 rancher/rancher

导入kubernetes集群

rancher docker运行后访问http://host:4443设置密码即可进入rancher,点击导入集群选择导入现有的kubernetes集群

Read the rest of this entry

,