03-kubeadm快速搭建k8s集群

摘要

本文内容转自网络,个人学习记录使用,请勿传播

部署k8s集群的两种方式

二进制部署

通过官网下载的二进制包,手动部署集群中每一个组件,形成k8s集群。

官方文档

kubeadm方式部署

通过官方提供的kubeadm集群管理工具部署集群,可以通过kubeadm initkubeadm join命令快速部署一个k8s集群。

官方文档

##

方案对比

部署方式 优势 劣势
二进制 部署灵活,可以自定义 部署方式没有完整、明确的官方文档
便于理解组件关系 部署复杂,部署慢
对集群的掌控力强
Kubeadm 部署快 自定义能力相对差
目前版本也可以用户生产环境部署

使用Kubernets快速部署一个k8s集群

准备工作

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
31
32
33
关闭防火墙:
$ systemctl stop firewalld
$ systemctl disable firewalld

关闭selinux:
$ sed -i 's/enforcing/disabled/' /etc/selinux/config # 永久
$ setenforce 0 # 临时

关闭swap:
$ swapoff -a # 临时
$ vim /etc/fstab # 永久

设置主机名:
$ hostnamectl set-hostname <hostname>

在master添加hosts:
$ cat >> /etc/hosts << EOF
192.168.31.61 k8s-master
192.168.31.62 k8s-node1
192.168.31.63 k8s-node2
EOF

将桥接的IPv4流量传递到iptables的链:
$ cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
$ sysctl --system # 生效

时间同步:
$ yum install ntpdate -y
$ ntpdate time.windows.com

所有节点安装Docker/kubeadm/kubelet

Kubernetes默认CRI(容器运行时)为Docker,因此先安装Docker。

安装Docker

1
2
3
4
5
$ wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
$ yum -y install docker-ce-19.03.15-3.el7
$ systemctl enable docker && systemctl start docker
$ docker --version
Docker version 18.06.1-ce, build e68fc7a
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
31
32
33
34
35
36
37
# cat > /etc/docker/daemon.json << EOF
{
"data-root": "/opt/docker/container",
"exec-opts": [],
"exec-root": "/opt/docker/bootstrap",
"experimental": false,
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"labels": [],
"live-restore": true,
"log-driver": "json-file",
"log-opts": {
"labels": "io.docker.log",
"max-size": "1g",
"max-file": "100"
},
"max-concurrent-downloads": 3,
"max-concurrent-uploads": 3,
"debug": false,
"log-level": "info",
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 102400,
"Soft": 102400
},
"nproc": {
"Name": "nproc",
"Hard": 102400,
"Soft": 102400
}
},
"registry-mirrors": ["https://dqzk2i1e.mirror.aliyuncs.com"]
}
EOF

添加阿里云YUM软件源

1
2
3
4
5
6
7
8
9
$ cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

安装kubeadm,kubelet和kubectl

由于版本更新频繁,这里指定版本号部署:

1
2
$ yum install -y kubelet-1.21.0 kubeadm-1.21.0 kubectl-1.21.0
$ systemctl enable kubelet

部署Kubernetes Master

在192.168.31.61(Master)执行。

1
2
3
4
5
6
7
$ kubeadm init \
--apiserver-advertise-address=192.168.31.61 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.21.0 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--ignore-preflight-errors=all

由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里指定阿里云镜像仓库地址。

使用kubectl工具:需要先将默认的认证文件复制到默认位置

1
2
3
4
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
$ kubectl get nodes
  • 安装目录:/etc/kubernetes/

  • 组件配置文件目录:/etc/kubernetes/manifests/

  • 证书文件位置:/etc/kubernetes/pki

安装Pod网络插件(CNI)

目前calico是Kubernets主流的网络方案,calico可以在三层工作,也可以实现udp封装的跨主机虚拟网络

参考资料:[https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#pod-network]

1
wget https://docs.projectcalico.org/manifests/calico.yaml

下载完后还需要修改里面定义Pod网络(CALICO_IPV4POOL_CIDR),与前面kubeadm init的 –pod-network-cidr指定的一样。

1
2
kubectl apply -f calico.yaml
kubectl get pods -n kube-system

使用etcd存储

参考文档:https://docs.projectcalico.org/getting-started/kubernetes/installation/config-options

CoreDNS问题处理

1
2
3
4
5
6
7
8
9
10
11
12
13
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-8db96c76-z7h5p 1/1 Running 0 16m
calico-node-pshdd 1/1 Running 0 16m
calico-node-vjwlg 1/1 Running 0 16m
coredns-545d6fc579-5hd9x 0/1 ImagePullBackOff 0 16m
coredns-545d6fc579-wdbsz 0/1 ImagePullBackOff 0 16m



# 手动pull镜像并重新打tag
docker pull registry.aliyuncs.com/google_containers/coredns:1.8.0
docker tag registry.aliyuncs.com/google_containers/coredns:1.8.0 registry.aliyuncs.com/google_containers/coredns/coredns:v1.8.0

flannel

1
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

确保能够访问到quay.io这个registery。

如果Pod镜像下载失败,可以改成这个镜像地址:lizhenliang/flannel:v0.11.0-amd64

加入Kubernetes Node

在192.168.31.62/63(Node)执行。

向集群添加新节点,执行在kubeadm init输出的kubeadm join命令:

1
2
$ kubeadm join 192.168.31.61:6443 --token esce21.q6hetwm8si29qxwn \
--discovery-token-ca-cert-hash sha256:00603a05805807501d7181c3d60b478788408cfe6cedefedb1f97569708be9c5

默认token有效期为24小时,当过期之后,该token就不可用了。这时就需要重新创建token,可以直接使用命令快捷生成:

1
kubeadm token create --print-join-command

删除node

1
2
3
kubectl drain NodeName
kubectl delete node NodeName
# 之后删除节点的 /etc/kubernetes/ /var/lib/kubelet 并重装kubelet就可以加入到其他集群了

测试kubernetes集群

在Kubernetes集群中创建一个pod,验证是否正常运行:

1
2
3
$ kubectl create deployment nginx --image=nginx
$ kubectl expose deployment nginx --port=80 --type=NodePort
$ kubectl get pod,svc

访问地址:http://NodeIP:Port

部署 Dashboard

1
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml

默认Dashboard只能集群内部访问,修改Service为NodePort类型,暴露到外部:

1
2
3
4
5
6
7
8
9
10
11
12
13
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard

访问地址:http://NodeIP:30001

创建service account并绑定默认cluster-admin管理员集群角色:

1
2
3
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

使用输出的token登录Dashboard。

chrome提示不安全,无法访问

dashboard默认带的证书认证是信息不全的,证书时间也早就过期了,因此chrome、safari无法访问,需要使用火狐浏览器才能访问,可以通过重新创建证书的方式让chrome、safari可以访问。

重新创建secret

1
2
3
4
5
# kubeadm安装的直接用apiserver的证书
kubectl delete secret kubernetes-dashboard-certs -n kubernetes-dashboard

kubectl create secret generic kubernetes-dashboard-certs \
--from-file=/etc/kubernetes/pki/apiserver.key --from-file=/etc/kubernetes/pki/apiserver.crt -n kubernetes-dashboard

修改dashboard.yaml配置

1
2
3
4
5
6
7
args:
# PLATFORM-SPECIFIC ARGS HERE
- --auto-generate-certificates
- --tls-key-file=apiserver.key
- --tls-cert-file=apiserver.crt

kubectl apply -f kubernetes-dashboard.yaml --force

删除原pod自动拉起新pod

1
2
3
kubectl get pods -n kubernetes-dashboard
# 根据自己的pod删除
# kubectl delete pod xxx xxx -n kubernetes-dashboard

另一种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mkdir key && cd key
#生成证书
openssl genrsa -out dashboard.key 2048
openssl req -new -out dashboard.csr -key dashboard.key -subj '/CN=192.168.1.202'
openssl x509 -req -in dashboard.csr -signkey dashboard.key -out dashboard.crt
#删除原有的证书secret
kubectl get secret kubernetes-dashboard-certs -n kubernetes-dashboard
kubectl delete secret kubernetes-dashboard-certs -n kubernetes-dashboard
#创建新的证书secret
kubectl create secret generic kubernetes-dashboard-certs --from-file=dashboard.key --from-file=dashboard.crt -n kubernetes-dashboard
#查看pod
kubectl get pod -n kubernetes-dashboard
#重启pod
kubectl delete pod <pod name> -n kubernetes-dashboard

kubeconfig配置文件

kubectl使用kubeconfig认证文件连接K8s集群,使用kubectl config指令生成kubeconfig文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
clusters: # 进群信息
- cluster:
certificate-authority-data:
server: https://192.168.31.61:6443
name: kubernetes
contexts: # 上下文信息
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes # 当前使用的上下文
kind: Config
preferences: {}
users: # 客户端认证
- name: kubernetes-admin
user:
client-certificate-data:
client-key-data:

kubectl命令行管理工具

分类 命令 描述
基础命令 create 通过文件名或标准输入创建资源
expose 为Deployment,Pod创建Service
run 在集群中运行一个特定的镜像
set 在对象上设置特定的功能
explain 文档参考资料
get 显示一个或多个资源
edit 使用系统编辑器编辑一个资源。
delete 通过文件名、标准输入、资源名称或标签选择器来删除资源。
部署命令 rollout 管理Deployment,Daemonset资源的发布(例如状态、发布记录、回滚等)
rolling-update 滚动升级,仅限ReplicationController
scale 对Deployment、ReplicaSet、RC或Job资源扩容或缩容Pod数量
autoscale 为Deploy, RS, RC配置自动伸缩规则(依赖metrics-server和hpa)
集群管理命令 certificate 修改证书资源
cluster-info 显示集群信息
top 查看资源利用率(依赖metrics-server)
cordon 标记节点不可调度
uncordon 标记节点可调度
drain 驱逐节点上的应用,准备下线维护
taint 修改节点taint标记
故障诊断和调试命令 describe 显示资源详细信息
logs 查看Pod内容器日志,如果Pod有多个容器,-c参数指定容器名称
attach 附加到Pod内的一个容器
exec 在容器内执行命令
port-forward 为Pod创建本地端口映射
proxy 为Kubernetes API server创建代理
cp 拷贝文件或目录到容器中,或者从容器内向外拷贝
高级命令 apply 从文件名或标准输入对资源创建/更新
patch 使用补丁方式修改、更新资源的某些字段
replace 从文件名或标准输入替换一个资源
convert 在不同API版本之间转换对象定义
设置命令 label 给资源设置、更新标签
annotate 给资源设置、更新注解
completion kubectl工具自动补全,source <(kubectl completion
其他命令 api-resources 查看所有资源
api-versions 打印受支持的API版本
config 修改kubeconfig文件(用于访问API,比如配置认证信息)
help 所有命令帮助
version 查看kubectl和k8s版本部署命令

快速部署一个应用

使用deployment控制器部署一个服务

1
2
# 使用nginx镜像部署一个nginx服务
kubectl create deploy nginx-web --image=nginx:1.17.10

通过service将pod端口暴露出去

1
2
3
4
5
6
7
kubectl expose deployment nginx-web --port=80 --type=NodePort --target-port=80 --name=nginx-web
--port=80 # service端口,k8s集群内部访问端口,目前用不到,后面再用
--target-port=80 # 镜像里服务运行的端口,
--type=NodePort # 指定service类型为nodePort,在node上随机生成一个端口,k8s集群外部访问端口,

kubectl get service
nginx-web NodePort 10.98.95.255 <none> 80:8602/TCP 1s

修改nodePort默认端口范围

1
2
cat /etc/kubernetes/manifests
kube-apiserver.yaml: - --service-node-port-range=8000-9000

访问测试

1
2
3
4
5
6
7
8
9
10
curl 192.168.31.61:8602 -I
HTTP/1.1 200 OK
Server: nginx/1.17.10
Date: Mon, 30 Aug 2021 07:02:46 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 14 Apr 2020 14:19:26 GMT
Connection: keep-alive
ETag: "5e95c66e-264"
Accept-Ranges: bytes

将容器引擎更换为Containerd

参考资料)

准备工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF

sudo sysctl --system

安装containerd

1
2
3
4
5
6
7
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
yum install -y containerd.io
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml

修改配置文件

  • pause镜像设置过阿里云镜像仓库地址
  • cgroups驱动设置为systemd
  • 拉取Docker Hub镜像配置加速地址设置为阿里云镜像仓库地址
1
2
3
4
5
6
7
8
9
10
11
vi /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.2"
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
...
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://b9pmyelo.mirror.aliyuncs.com"]

systemctl restart containerd

配置kubelet使用containerd

1
2
3
4
vi /etc/sysconfig/kubelet 
KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --cgroup-driver=systemd

systemctl restart kubelet

验证

1
kubectl get node -o wide

容器管理工具

containerd提供了ctr命令行工具管理容器,但功能比较简单,所以一般会用crictl工具检查和调试容器。

项目地址:https://github.com/kubernetes-sigs/cri-tools/

设置crictl连接containerd

1
2
3
4
5
vi /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false

docker与crictl命令对照表

镜像相关功能

镜像相关功能 Docker Containerd
显示本地镜像列表 docker images crictl images
下载镜像 docker pull crictl pull
上传镜像 docker push 无,例如buildk
删除本地镜像 docker rmi crictl rmi
查看镜像详情 docker inspect IMAGE-ID crictl inspecti IMAGE-ID

容器相关功能

容器相关功能 Docker Containerd
显示容器列表 docker ps crictl ps
创建容器 docker create crictl create
启动容器 docker start crictl start
停止容器 docker stop crictl stop
删除容器 docker rm crictl rm
查看容器详情 docker inspect crictl inspect
attach docker attach crictl attach
exec docker exec crictl exec
logs docker logs crictl logs
stats docker stats crictl stats

pod相关功能

POD 相关功能 Docker Containerd
显示 POD 列表 crictl pods
查看 POD 详情 crictl inspectp
运行 POD crictl runp
停止 POD crictl stopp