目录

1. 故障处理过程

今天接到同事反馈发现有一套k8s apiserver集群出现如下报错:

Failed to create new replica set "recommend-alg-service-74c6bc97cd": Get https://10.13.96.12:6443/api/v1/namespaces/saas-ec-tomcat-pl/resourcequotas: x509: certificate has expired or is not yet valid

随后去api server节点上查询api server日志,发现也有大量报错:

I0510 17:43:56.889617  790992 reflector.go:211] Listing and watching *v1.MutatingWebhookConfiguration from k8s.io/client-go/informers/factory.go:135
I0510 17:43:56.892900  790992 log.go:172] http: TLS handshake error from 10.13.96.11:36528: remote error: tls: bad certificate
E0510 17:43:56.892945  790992 reflector.go:178] k8s.io/client-go/informers/factory.go:135: Failed to list *v1.MutatingWebhookConfiguration: Get https://10.13.96.11:6443/apis/admissionregistration.k8s.io/v1/mutatingwebhookconfigurations?resourceVersion=331916875: x509: certificate has expired or is not yet valid
I0510 17:43:57.087301  790992 reflector.go:211] Listing and watching *v1.ClusterRole from k8s.io/client-go/informers/factory.go:135
I0510 17:43:57.090560  790992 log.go:172] http: TLS handshake error from 10.13.96.11:36530: remote error: tls: bad certificate
E0510 17:43:57.090625  790992 reflector.go:178] k8s.io/client-go/informers/factory.go:135: Failed to list *v1.ClusterRole: Get https://10.13.96.11:6443/apis/rbac.authorization.k8s.io/v1/clusterroles?resourceVersion=397554978: x509: certificate has expired or is not yet valid

让人奇怪的是,并不是所有请求都报证书错误,通过日志发现,大量的请求到api server都是200的,出现500的为少数。

同时我们通过上面的报错发现,报错的访问来源是10.13.96.11:36528,这个IP是api server自己。

最后我们将错误定位到以下范围:

  • api server自己访问自己报证书过期的错误,而其它组件访问都是正常的。

同时我们检查了服务器上的所有k8s 集群组件使用的证书,并没有过期。

在无计可施时,怀着试试看的想法,我们将api server服务重启了,发现重启后恢复正常。果然是重启能解决99%的问题。

阅读全文

最近在弄AlertManager,发现其集群模式需要知道各个AlertManager节点的IP地址,而我们现在需要在2个K8s集群同时部署AlertManager上来创建一套AlertManager,以确保在某一个K8s集群挂了后报警还能发出来,同时确保当2个K8s集群都正常的时候,一个告警只发一次出来。

但怎么在A集群上找到B集群上的POD的IP,这是个问题。通过研究,我们发现CoreDns可以很好的解决这个问题。

假设我们现在有2套集群,2套集群使用的DNS后缀都是cluster.local,容器网段及service网段都不一样。

我们现在在A集群上,先看旧的CoreDNS的配置:

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        log . {combined} {
          class error
        }
        errors
        health
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . /etc/resolv.conf
        cache 30
        reload
        loadbalance
        #rewrite name saas-fe-zhan.internal.com public-fe-zhan-node-dev.public-fe-node-dev.svc.cluster.local
    }
        

阅读全文

以前写的golang项目一直使用的都是公开的module,最近使用私有gitlab仓库的module时,发现go get mod时需要输入用户名密码,开发环境还好解决,手动输一次让他记住就好了。但是项目正式上线,通过公司统一的jenkins Pipeline执行构建时,没有办法去手动输用户名密码。

Dockerfile配置

要解决这个问题,可以通过.netrc文件来处理。Dockerfile如下:

FROM mirror.ccs.tencentyun.com/library/golang:1.17 as builder

ARG GIT_USR
ARG GIT_PWD

ENV GOPROXY=https://goproxy.cn,direct
ENV GOPRIVATE=stash.xxxx.com
ENV GOOS=linux
ENV GIT_TERMINAL_PROMPT=1

WORKDIR /build
COPY . ./

RUN go env -w GOPRIVATE=stash.xxxx.com \
    && echo "machine stash.xxxx.com login ${GIT_USR} password ${GIT_PWD}" > ~/.netrc \
    && GO111MODULE=on CGO_ENABLED=0 GOOS=${GOOS} GOPROXY=${GOPROXY} go build -o=knative-audit-log

################################################################################
##                               MAIN STAGE                                   ##
################################################################################
# Copy the manager into the distroless image.
FROM mirror.ccs.tencentyun.com/library/alpine:3.13

RUN echo 'https://mirrors.cloud.tencent.com/alpine/v3.13/main' > /etc/apk/repositories \
    && echo 'https://mirrors.cloud.tencent.com/alpine/v3.13/community' >>/etc/apk/repositories \
    && apk update && apk add tzdata && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo "Asia/Shanghai" > /etc/timezone

WORKDIR /usr/local/app
COPY --from=builder /build/knative-audit-log /usr/local/app/knative-audit-log
RUN chmod 755 /usr/local/app/knative-audit-log

ENTRYPOINT ["/usr/local/app/knative-audit-log"]

重点在3,4行和15行,3,4行通过传入GIT_USR和GIT_PWD两个参数到docker构建内,第15行生成.netrc配置。

现在我们就可以通过传参的方式来构建了:

docker build -t hub.docker.com/xxx/knative-audit-log:v0.1 --build-arg GIT_USR=**** --build-arg 'GIT_PWD=****' -f ./Dockerfile .

阅读全文

如何删除一个tcp长连接

有时端口被占用导致服务起不来,发现本机端口被另一个程序使用了。这个时候我们可以使用tcpkill命令来删除这个长连接,让其自动重连换一个端口。然后再启动想启动的服务。

安装tcpkill:

yum -y install dsniff --enablerepo=epel

查询这个连接:

[root@sh5-saas-k8scs1-node-online-167 ~]# netstat -anp | grep 4080
tcp        0      0 10.10.182.167:4080      10.10.182.3:8443        ESTABLISHED 71932/kubelet       
unix  2      [ ACC ]     STREAM     LISTENING     2363408000 61767/containerd     /run/containerd/s/e3515d3603c24c9fdf4f6e16c493fe8953ab73538685ca8a52331356a3951649
unix  3      [ ]         STREAM     CONNECTED     2363408007 61767/containerd 

删除连接:

[root@sh5-saas-k8scs1-node-online-167 ~]# tcpkill -9 port 4080
tcpkill: listening on eth0 [port 4080]

10.10.182.167:4080 > 10.10.182.3:8443: R 1598753917:1598753917(0) win 0
10.10.182.167:4080 > 10.10.182.3:8443: R 1598754418:1598754418(0) win 0
10.10.182.167:4080 > 10.10.182.3:8443: R 1598755420:1598755420(0) win 0
10.10.182.167:4080 > 10.10.182.3:8443: R 1598756923:1598756923(0) win 0
10.10.182.167:4080 > 10.10.182.3:8443: R 1598758927:1598758927(0) win 0
10.10.182.167:4080 > 10.10.182.3:8443: R 1598761432:1598761432(0) win 0
10.10.182.167:4080 > 10.10.182.3:8443: R 1598764438:1598764438(0) win 0
10.10.182.167:4080 > 10.10.182.3:8443: R 1598767945:1598767945(0) win 0
10.10.182.167:4080 > 10.10.182.3:8443: R 1598771953:1598771953(0) win 0
10.10.182.3:8443 > 10.10.182.167:4080: R 1279911727:1279911727(0) win 0
10.10.182.3:8443 > 10.10.182.167:4080: R 1279913189:1279913189(0) win 0
10.10.182.3:8443 > 10.10.182.167:4080: R 1279916113:1279916113(0) win 0
10.10.182.3:8443 > 10.10.182.167:4080: R 1279920499:1279920499(0) win 0
10.10.182.3:8443 > 10.10.182.167:4080: R 1279926347:1279926347(0) win 0
10.10.182.3:8443 > 10.10.182.167:4080: R 1279933657:1279933657(0) win 0
10.10.182.3:8443 > 10.10.182.167:4080: R 1279942429:1279942429(0) win 0
10.10.182.3:8443 > 10.10.182.167:4080: R 1279952663:1279952663(0) win 0
10.10.182.3:8443 > 10.10.182.167:4080: R 1279964359:1279964359(0) win 0

阅读全文

目录

1. 前言

Traefik版本为2.5.2,从今天开始,计划陆续看完Traefik的核心部分的源码。 本文是第一部分,Traefik的程序启动分析。

2. 主流程

main.go在cmd/traefik/traefik.go内,其主要流程为:

image

先构造3个Command启动器,分别是traefik,healthcheck,version,Command结构如下:

源码文件:github.com/traefik/paerser@v0.1.4/cli/commands.go

package cli

type Command struct {
	Name           string
	Description    string
	Configuration  interface{}
	Resources      []ResourceLoader
	Run            func([]string) error
	CustomHelpFunc func(io.Writer, *Command) error
	Hidden         bool
	// AllowArg if not set, disallows any argument that is not a known command or a sub-command.
	AllowArg    bool
	subCommands []*Command
}

可以看到,每个Command都可以配置名字,资源,Run函数等。

然后通过cli.Execute(cmdTraefik)来启动上面3个服务,也就是调用Command内的Run函数。

阅读全文

目录

1.概述

kubernetes-csi-tencentcloud官方地址:https://github.com/TencentCloud/kubernetes-csi-tencentcloud

官方存储类参考:https://kubernetes.io/zh/docs/concepts/storage/storage-classes/

目前支持CBS,CFS,COS这三种存储类型,其中CBS不支持共享模式,CFS支持共享模式。

阅读全文

1. NR_KERNEL_STACK是干什么用的?

通过下面的命令,我们可以查看内核栈的数量:

cat /proc/vmstat  | grep stack
nr_kernel_stack 567

这个值在内核中的宏为:NR_KERNEL_STACK,表示当前内核中有多少个内核栈。

我们使用这个数字来监控K8S节点上使用PID的数量,以避免PID被耗尽。

2. 那么PID与内核栈有什么关系呢?

在linux系统中,每个进程、子进程和线程在运行时都会有一个PID。这些进程或线程在运行时,因为CPU需要进行任务切换,在任务切换时就需要上下文交换,在上下文交换时就需要把当前进程的上下文压到内核栈内去,以便下次再运行时取出继续执行。

所以可以确定:每个进程、子进程和线程都会有一个内核栈。内核栈的数量与PID的数量大致相当。

注:基于linux内核的线程,比如java的线程与linux的线程是一一对应的,nodejs只使用了linux的进程,线程模型是其自己实现的,golang最特别,使用了多进程,每个进程上有多线程(基于内核),线程上还是自己实现的协程或者说goroute(可以理解为自己实现的线程)

阅读全文

作者的图片

阿辉

容器技术及容器集群等分布式系统研究

容器平台负责人

上海