0%

Kubernetes1.20开始不建议使用docker作为运行时,作为容器运行时,其实还有其他一些:

  • containerd
  • CRI-O

经过对比,我选择了containerd进行验证。这次我并没有升级整体Kubernetes集群,只是打算增加一个使用containerd的容器运行时的节点。

安装containerd

我使用CentOS 7,首先需要设置内核参数,这个和之前Docker一样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 设置必需的 sysctl 参数,这些参数在重新启动后仍然存在。
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

# Apply sysctl params without reboot
sudo sysctl --system

然后开始安装,containerd使用yum源和docker-ce相同:

1
2
3
4
# 安装 containerd
## 设置仓库
### 安装所需包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
1
2
3
4
### 新增 Docker 仓库
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
1
2
## 安装 containerd
sudo yum update -y && sudo yum install -y containerd.io

配置containerd

首先获得缺省配置:

1
2
3
# 配置 containerd
sudo mkdir -p /etc/containerd
sudo containerd config default > /etc/containerd/config.toml

因为国内无法访问部分image源,同事docker hub比较慢,修改使用国内镜像:

1
2
3
4
5
6
7
8
9
10
11
vi /etc/containerd/config.toml

# 修改一下内容:
...
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.2"
...
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://docker.mirrors.ustc.edu.cn"]
...
1
2
# 重启 containerd
sudo systemctl restart containerd

加入k8s集群

首先安装k8s,包括kubeadmkubeletkubectl

1
yum install -y kubeadm kubelet kubectl

然后加入到集群:

1
kubeadm join master.k8s:8443 --token xxx     --discovery-token-ca-cert-hash sha256:xxxxxxx

现在已经使用containerd允许时的节点已经加入到集群,部署容器测试可以正常使用。

containerd管理

使用containerd已经不能使用熟悉的docker命令进行容器的管理了,containerd提供了2个工具可以使用:

  • ctr
  • crictl

ctr

ctr是一个简单的命令工具,使用并不复杂,但需要注意:

  • ctr不会使用配置文件/etc/containerd/config.toml,也就是说配置的mirror并不能使用
  • images也有命名空间,k8s会使用一个名为k8s.io的命名空间
  • ctr的参数有顺序,如ctr -n=k8s.io images list正确,而ctr images list -n=k8s.io则不正确

希望未来ctr会更完善一些。

crictl

crictl使用和docker命令类似,比较方便。使用前需要增加配置文件:/etc/crictl.yaml。内容如下:

1
2
3
4
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false

升级Kubernetes1.18时发现1个严重的问题:

首先是发现部分Services无法访问,经过各种检查最终发现当Pod重启后,就无法访问。

搭建一个测试的DeploymentService,进行问题排查:Deployment如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: apps/v1
kind: Deployment
metadata:
name: hostnames
spec:
selector:
matchLabels:
app: hostnames
replicas: 1
template:
metadata:
labels:
app: hostnames
spec:
containers:
- name: hostnames
image: mirrorgooglecontainers/serve_hostname
ports:
- containerPort: 9376
protocol: TCP

Service如下:

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
name: hostnames
spec:
selector:
app: hostnames
ports:
- name: default
protocol: TCP
port: 80
targetPort: 9376

再启动一个curl进行测试:

1
kubectl run curl --image=radial/busyboxplus:curl -it

正确情况如下:

1
2
[ root@curl-69c656fd45-ztblt:/ ]$ curl hostnames
hostnames-dd4cc9dd9-5k42b

可以通过Service正常访问到Pod

现在删除掉hostnamesPod,等到Pod运行正常时,再次执行:

1
2
[ root@curl-69c656fd45-ztblt:/ ]$ curl hostnames
connect to hostnames failed: No route to host

通过检查确定DNS没有问题,通过PodIP,可以正常访问,通过ServiceIP就无法访问了。也就是说,升级Kubernetes V1.18(我的版本是V1.18.2),就会导致Pod重新启动后,Service无法访问。

那么现在重点是Proxy的检查,我使用的是模式是ipvs,检查ipvs列表。
master或其他节点上执行:

1
2
3
4
5
6
7
[root@node01 ~]# ipvsadm -L |grep -A 5 10.103.122.243
TCP 10.103.122.243:http rr
-> 10.244.10.237:9376 Masq 1 0 0
TCP 10.103.123.173:webcache rr
-> 10.244.9.26:webcache Masq 1 0 0
TCP 10.103.143.242:6379 rr
-> 10.244.9.229:6379 Masq 1 0 0

10.103.122.243ServiceIP, 而转发地址10.244.10.237:9376是老的Pod的地址,不是新Pod的地址,这样肯定无法访问。再次验证一下这个原因,将转发修改正确:

1
2
3
[root@node01 ~]# ipvsadm -D -t 10.103.122.243:http 

[root@node01 ~]# ipvsadm -a -t 10.103.122.243:http -r 10.244.10.238:9376 -m

第一句是删除老的转发,第二句是新增正确的转发。其中10.244.10.238是新的Pod的的地址

进入curl容器执行:

1
2
[ root@curl-69c656fd45-ztblt:/ ]$ curl hostnames
hostnames-dd4cc9dd9-5k42b

看到结果已经正常。这个确定了导致这个问题的原因是ipvs规则没有更新。经过确定,需要升级Liunx的内核到V4以上。

升级Kubernetes1.16时发现2个问题:

  1. 执行kubeadm upgrade plan 提示CoreDNS插件失败,解决办法:
    修改CoreDNS配置文件:

    script
    1
    kubectl edit -n kube-system configmaps coredns

    删除:proxy . /etc/resolv.conf
    然后执行就可以成功。

  2. 升级后Node节点状态为Not Ready
    检查日志:

    script
    1
    journalctl -f -u kubelet.service

    结果:

    script
    1
    2
    3
    10月 16 11:46:21 k8s-master kubelet[11043]: E1016 11:46:21.515027   11043 kubelet.go:2187] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
    10月 16 11:46:26 k8s-master kubelet[11043]: W1016 11:46:26.201162 11043 cni.go:202] Error validating CNI config &{cbr0 false [0xc0004a08a0 0xc0004a0940] [123 10 32 32 34 110 97 109 101 34 58 32 34 99 98 114 48 34 44 10 32 32 34 112 108 117 103 105 110 115 34 58 32 91 10 32 32 32 32 123 10 32 32 32 32 32 32 34 116 121 112 101 34 58 32 34 102 108 97 110 110 101 108 34 44 10 32 32 32 32 32 32 34 100 101 108 101 103 97 116 101 34 58 32 123 10 32 32 32 32 32 32 32 32 34 104 97 105 114 112 105 110 77 111 100 101 34 58 32 116 114 117 101 44 10 32 32 32 32 32 32 32 32 34 105 115 68 101 102 97 117 108 116 71 97 116 101 119 97 121 34 58 32 116 114 117 101 10 32 32 32 32 32 32 125 10 32 32 32 32 125 44 10 32 32 32 32 123 10 32 32 32 32 32 32 34 116 121 112 101 34 58 32 34 112 111 114 116 109 97 112 34 44 10 32 32 32 32 32 32 34 99 97 112 97 98 105 108 105 116 105 101 115 34 58 32 123 10 32 32 32 32 32 32 32 32 34 112 111 114 116 77 97 112 112 105 110 103 115 34 58 32 116 114 117 101 10 32 32 32 32 32 32 125 10 32 32 32 32 125 10 32 32 93 10 125 10]}: [plugin flannel does not support config version ""]
    10月 16 11:46:26 k8s-master kubelet[11043]: W1016 11:46:26.201211 11043 cni.go:237] Unable to update cni config: no valid networks found in /etc/cni/net.d

    修改flannel配置:

    script
    1
    vi /etc/cni/net.d/10-flannel.conflist

    "name": "cbr0"前增加:

    script
    1
    "cniVersion": "0.3.1",

    稍等片刻node自动恢复。

最近在Kubernetes中部署了GitLabGitLab使用HTTP,在Kubernetes通过Ingress进行HTTPS代理,对外使用HTTPS访问。

当在部署GitLab Pages时,系统通过Access Contrel进行访问控制时,结果发现出现503错误。经过多次尝试,发现有两个解决方法:

  1. 全部不使用HTTPS,使用HTTP。这个方法简单粗暴,但不安全。
  2. 修改修改配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# external_url设置为https,如果设置http,在通过Ingress代理成https,大部分功能没有问题,但发现Web IDE打开是因为在HTTPS请求中使用了HTTP大致失败,未来有可能GitLab会修改这个问题。但目前只能如此。
external_url 'https://gitlab.example.cn'

# Pages的对外页面,这里使用HTTP,通过Ingress进行HTTPS代理
pages_external_url "http://example.cn/"

# 如果使用容器部署,inplace_chroot需要打开
gitlab_pages['inplace_chroot'] = true

# 接入控制开关
gitlab_pages['access_control'] = true

# auth_server是关键,缺省和external_url相同,因为external_url设置为https,导致pages无法通过证书验证,所有修改认证为http方式。
gitlab_pages['auth_server'] = 'http://gitlab.rd.example.cn'

终于,GitLabWeb IDEPages都可以完美工作了。

备注: GitLab使用版本 V11~`V12.2`

最近发现Kubernetes集群中,出现不稳定情况,怀疑是Calico导致,为了排除文件,打算将Calico更换为Flannel,本来以为很简单,结果还是遇到Calico无法删除干净的问题。所有将删除正确删除过程做一个记录。 顺便说一下,最终确定和Calico无关。

环境:
Kubernetes: V1.15
Calico: V3.5

删除步骤:

  1. 删除K8s对象
    1
    kubectl delete -f calico.yaml
  2. 检查所有节点上的网络,看看是否存在Tunl0
    1
    ip addr show
  3. 如果有Tunl0,将其删除
    1
    modprobe -r ipip
  4. 移除Calico配置文件
    1
    ls /etc/cni/net.d/
    看看是否存在Calico相关的文件和目录,如:10-calico.conflistcalico-kubeconfigcalico-tls,如果有将其移除。

这时候整个Calico移除成功。

在朋友的推荐下尝试了一些Hexo + Next,使用后感觉真的很简单,并且Next效果很棒,最终切换为Hexo + Next

切换过程遇到了一些问题,做一个记录,分享出来。

Read more »

下滑这里查看更多内容

时间处理在开发中最常见的问题,应同事要求我做一个简单的汇总,方便学习。

之所以使用《时间简史》这个名字,一方面是和时间有关,更多的是希望像霍金一样能用最简单的方式来介绍概念,为开发人员进行科普。

Read more »

在开发和实施中,经常需要调整各种源,以到达最快的速度,今天对我常用的源做一个汇总。

Read more »

最早在写React组件时,使用的以下方法:

1
2
3
4
5
6
7
8
9
var App = React.createClass({
handleClick: function () {
...
}

render: function() {
return <div onClick={handleClick}>Click me!</div>;
}
});
Read more »