k8s集群的搭建
在 Kubernetes 中,当 Pod 被创建后,它会先进入一个叫做 Pending 的状态,表示 Kubernetes 正在运行必要的调度过程以将 Pod 分配到具体的节点上。直接使用apt-get安装的docker为20.10版本,我们要使用的k8s并不支持这个版本,因此我安装19.03版本的docker,以规避因版本出现的一些问题。根据很多次的失败操作,发现init时将使用hostname
目录
一、实验条件
实验条件为三台Ubuntu20.04虚拟机
其中一台作为k8s-master,两台为k8s集群节点,分别为k8s-node1和k8s-node2
由于虚拟机可以完整克隆,因此我将所有虚拟机共通的步骤在一台机器上做完,再克隆出另外两台虚拟机。
安装虚拟机参考的文档:
https://blog.csdn.net/Baiye959/article/details/122886252?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168517574616800225595156%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168517574616800225595156&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-122886252-null-null.142^v88^insert_down1,239^v2^insert_chatgpt&utm_term=vmware%E5%88%9B%E5%BB%BAubuntu%E8%99%9A%E6%8B%9F%E6%9C%BA&spm=1018.2226.3001.4187
二、克隆前操作
>sudo swapoff -a
一个 Linux 系统命令,它的作用是关闭系统上所有的 Swap 分区或 Swap 文件。Swap 是一种虚拟内存技术,将系统中的一部分磁盘空间用来作为内存使用,以增加系统的内存容量。在一些情况下,这些 Swap 分区可能会对系统的性能产生一定的负面影响,因此需要关闭这些 Swap 分区。
>sudo sed -i 's/.*swap.*/#&/' /etc/fstab
将 /etc/fstab 文件中所有包含 swap 的行注释掉。使用这个命令后,系统下次启动时就不会自动挂载 Swap 分区了。
>sudo systemctl stop ufw
>sudo systemctl disable ufw
>sudo systemctl stop firewalld
>sudo systemctl disable firewalld
以上的命令将虚拟机的防火墙关闭,使外界能够访问虚拟机的所有端口
编辑/etc/apt/source.list
修改镜像源(阿里云/华为/清华园)
可以参考此博客更新系统源:
ubuntu20.04更换国内源方法_武行 |【虾头】的博客-CSDN博客
>sudo apt-get update
更新 Ubuntu 系统中可用软件包的索引列表。
>sudo apt-get upgrade
接下来安装docker。直接使用apt-get安装的docker为20.10版本,我们要使用的k8s并不支持这个版本,因此我安装19.03版本的docker,以规避因版本出现的一些问题。
# 安装必要的工具
>sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
# 添加 Docker 官方 GPG 密钥
>curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# 添加 Docker CE 的稳定版软件源
>sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# 更新 APT 软件包缓存
>sudo apt-get update
# 安装 Docker CE 19.03 版本
>sudo apt-get install -y docker-ce=5:19.03.*~3-0~ubuntu-$(lsb_release -cs) docker-ce-cli=5:19.03.*~3-0~ubuntu-$(lsb_release -cs) containerd.io
>sudo systemctl enable docker
>sudo systemctl daemon-reload
>sudo systemctl restart docker
到此步可以克隆虚拟机。
三、Master操作
要将Master的hostname改为k8s-master
修改/etc文件夹下的hosts和hostname文件
>cd /etc
>sudo vim hostname
里面的内容一开始为ubuntu
将里面的内容改为k8s-master
>vim hosts
文件内有一条映射为127.0.0.1 ubuntu
修改这一行,将127.0.0.1映射到k8s-master
执行完以后重启虚拟机
>reboot
重启以后
>sudo hostname
这样就把hostname修改过来了
(原来的方法sudo hostname k8s-master并不能持久化地修改hostname,可能导致k8s init时出现问题)
>sudo wget https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg
在 Kubernetes 集群中,我们需要通过安装 Kubernetes 的 apt-key 来添加 Kubernetes 的 APT 仓库密钥。这个命令下载的正是阿里云 Kubernetes 镜像源提供的 apt-key.gpg 密钥文件。
>sudo apt-key add apt-key.gpg
把之前下载的 apt-key.gpg 密钥文件添加到 Ubuntu 系统的 APT 仓库密钥中。通过在 Ubuntu 系统中注册 Kubernetes 的公共密钥,可以确保我们能够从 Kubernetes 官网或阿里云源安装更新软件包。
>sudo vim /etc/apt/sources.list
打开/etc/apt/sources.list文件
添加一行
deb https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial main
>sudo apt update
添加以后更新一下apt源
值得注意的是,如果不进行上述步骤,可能出现的问题:
执行报错,无法定位软件包
>sudo apt-get install -y kubelet=1.17.2-00 kubeadm=1.17.2-00 kubectl=1.17.2-00 --allow-unauthenticated
在 Ubuntu 系统上安装 Kubernetes 工具和组件:kubelet、kubeadm 和 kubectl。这些工具是 Kubernetes 集群的核心组件,用于管理和操作 Kubernetes 集群。
>sudo kubeadm config images list
列出当前 Kubernetes 版本中需要使用的所有镜像的名称及版本号。这些镜像是在使用 kubeadm 工具初始化一个 Kubernetes 集群时所需的。
返回如下结果:
接下来,在docker上拉去我们需要的镜像并修改tag
>sudo docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.17.17
>sudo docker tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.17.17 k8s.gcr.io/kube-apiserver:v1.17.17
>sudo docker rmi registry.aliyuncs.com/google_containers/kube-apiserver:v1.17.17
>sudo docker pull registry.aliyuncs.com/google_containers/kube-controller-manager:v1.17.17
>sudo docker tag registry.aliyuncs.com/google_containers/kube-controller-manager:v1.17.17 k8s.gcr.io/kube-controller-manager:v1.17.17
>sudo docker rmi registry.aliyuncs.com/google_containers/kube-controller-manager:v1.17.17
>sudo docker pull registry.aliyuncs.com/google_containers/kube-scheduler:v1.17.17
>sudo docker tag registry.aliyuncs.com/google_containers/kube-scheduler:v1.17.17 k8s.gcr.io/kube-scheduler:v1.17.17
>sudo docker rmi registry.aliyuncs.com/google_containers/kube-scheduler:v1.17.17
>sudo docker pull registry.aliyuncs.com/google_containers/kube-proxy:v1.17.17
>sudo docker tag registry.aliyuncs.com/google_containers/kube-proxy:v1.17.17 k8s.gcr.io/kube-proxy:v1.17.17
>sudo docker rmi registry.aliyuncs.com/google_containers/kube-proxy:v1.17.17
>sudo docker pull registry.aliyuncs.com/google_containers/pause:3.1
>sudo docker tag registry.aliyuncs.com/google_containers/pause:3.1 k8s.gcr.io/pause:3.1
>sudo docker rmi registry.aliyuncs.com/google_containers/pause:3.1
>sudo docker pull registry.aliyuncs.com/google_containers/etcd:3.4.3-0
>sudo docker tag registry.aliyuncs.com/google_containers/etcd:3.4.3-0 k8s.gcr.io/etcd:3.4.3-0
>sudo docker rmi registry.aliyuncs.com/google_containers/etcd:3.4.3-0
>sudo docker pull registry.aliyuncs.com/google_containers/coredns:1.6.5
>sudo docker tag registry.aliyuncs.com/google_containers/coredns:1.6.5 k8s.gcr.io/coredns:1.6.5
>sudo docker rmi registry.aliyuncs.com/google_containers/coredns:1.6.5
下载好了可以使用如下命令查看已经拉取的镜像
>sudo docker images
>sudo kubeadm init --pod-network-cidr=10.244.0.0/16
使用kubeadm工具初始化一个Kubernetes集群,并指定Pod网络的CIDR地址范围
这个命令做的工作有:
- 在当前节点上启动 Kubernetes 控制平面组件(kube-apiserver、kube-controller-manager 和 kube-scheduler);
- 生成一个加入集群的 token,在后续加入工作节点时需要使用该 token,以及一个 CA 证书和私钥用于安全连接集群;
- 部署一个网络插件(flannel、Calico 等),以便将 Pod 之间和 Pod 与外部网络之间的流量路由到正确的地方;
- 最后,输出一些必要信息,包括如何加入工作节点的命令、控制平面节点的地址和端口等。
初始化成功将会输出:
>mkdir -p $HOME/.kube
该命令用于创建一个名为 .kube 的隐藏文件夹
>sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
>sudo chown $(id -u):$(id -g) $HOME/.kube/config
该命令用于更改 $HOME/.kube/config 文件的所有者为当前用户,以便用户可以使用 kubectl 命令进行 Kubernetes 集群的管理。
>kubectl get pods --all-namespaces
用于列出 Kubernetes 中所有命名空间(Namespace)中的 Pod(容器)
输出结果如下:
发现coredns 此时处于pending状态
在 Kubernetes 中,当 Pod 被创建后,它会先进入一个叫做 Pending 的状态,表示 Kubernetes 正在运行必要的调度过程以将 Pod 分配到具体的节点上。在这个过程中,Kubernetes 会根据用户设置的策略和资源限制等条件,选择合适的节点来部署容器。
>kubectl get nodes
该命令用于获取当前 Kubernetes 集群中所有的节点信息,输出的结果如下
可以看到,目前的集群中仅有一个节点k8s-master,且处于NotReady状态
需要部署pod network插件文件
将以下内容写入/usr/local/src/kube-flannel.yml
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp.flannel.unprivileged
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default
seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default
apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
spec:
privileged: false
volumes:
- configMap
- secret
- emptyDir
- hostPath
allowedHostPaths:
- pathPrefix: "/etc/cni/net.d"
- pathPrefix: "/etc/kube-flannel"
- pathPrefix: "/run/flannel"
readOnlyRootFilesystem: false
# Users and groups
runAsUser:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
fsGroup:
rule: RunAsAny
# Privilege Escalation
allowPrivilegeEscalation: false
defaultAllowPrivilegeEscalation: false
# Capabilities
allowedCapabilities: ['NET_ADMIN', 'NET_RAW']
defaultAddCapabilities: []
requiredDropCapabilities: []
# Host namespaces
hostPID: false
hostIPC: false
hostNetwork: true
hostPorts:
- min: 0
max: 65535
# SELinux
seLinux:
# SELinux is unused in CaaSP
rule: 'RunAsAny'
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: flannel
rules:
- apiGroups: ['extensions']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames: ['psp.flannel.unprivileged']
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- ""
resources:
- nodes
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: flannel
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: flannel
subjects:
- kind: ServiceAccount
name: flannel
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: flannel
namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
name: kube-flannel-cfg
namespace: kube-system
labels:
tier: node
app: flannel
data:
cni-conf.json: |
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-flannel-ds
namespace: kube-system
labels:
tier: node
app: flannel
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
tier: node
app: flannel
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
hostNetwork: true
priorityClassName: system-node-critical
tolerations:
- operator: Exists
effect: NoSchedule
serviceAccountName: flannel
initContainers:
- name: install-cni-plugin
#image: flannelcni/flannel-cni-plugin:v1.0.1 for ppc64le and mips64le (dockerhub limitations may apply)
image: rancher/mirrored-flannelcni-flannel-cni-plugin:v1.0.1
command:
- cp
args:
- -f
- /flannel
- /opt/cni/bin/flannel
volumeMounts:
- name: cni-plugin
mountPath: /opt/cni/bin
- name: install-cni
#image: flannelcni/flannel:v0.17.0 for ppc64le and mips64le (dockerhub limitations may apply)
image: rancher/mirrored-flannelcni-flannel:v0.17.0
command:
- cp
args:
- -f
- /etc/kube-flannel/cni-conf.json
- /etc/cni/net.d/10-flannel.conflist
volumeMounts:
- name: cni
mountPath: /etc/cni/net.d
- name: flannel-cfg
mountPath: /etc/kube-flannel/
containers:
- name: kube-flannel
#image: flannelcni/flannel:v0.17.0 for ppc64le and mips64le (dockerhub limitations may apply)
image: rancher/mirrored-flannelcni-flannel:v0.17.0
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
resources:
requests:
cpu: "100m"
memory: "50Mi"
limits:
cpu: "100m"
memory: "50Mi"
securityContext:
privileged: false
capabilities:
add: ["NET_ADMIN", "NET_RAW"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- name: run
mountPath: /run/flannel
- name: flannel-cfg
mountPath: /etc/kube-flannel/
- name: xtables-lock
mountPath: /run/xtables.lock
volumes:
- name: run
hostPath:
path: /run/flannel
- name: cni-plugin
hostPath:
path: /opt/cni/bin
- name: cni
hostPath:
path: /etc/cni/net.d
- name: flannel-cfg
configMap:
name: kube-flannel-cfg
- name: xtables-lock
hostPath:
path: /run/xtables.lock
type: FileOrCreate
再执行命令
>kubectl apply -f /usr/local/src/kube-flannel.yml
在 Kubernetes 集群中部署网络插件 flannel,以便将 Pod 之间和 Pod 与外部网络之间的流量路由到正确的地方。
使用 kubectl apply 命令将 /usr/local/src/kube-flannel.yml 文件中定义的 flannel 配置应用到 Kubernetes 集群中;该文件中指定了 flannel 的 Pod 网络地址范围、网络配置等信息,并会在 Kubernetes 中创建对应的 ConfigMap 和 DaemonSet
再次查看所有pod的状态
>kubectl get pods --all-namespaces
此时发现coredns-6955765f44-8llgc处于Running状态
再次查看集群中所有节点的信息:
>kubectl get node
现在是Ready状态了
集群初始化好了,接下来就是要让node们能够加入此集群
>sudo kubeadm token create --print-join-command
这个命令会返回一个包含了上述 hash 值的完整 kubeadm join 命令
在我的虚拟机上,生成出来的join命令为:
kubeadm join 192.168.61.137:6443 --token q3o6sj.sa97hu0u2oe18yug --discovery-token-ca-cert-hash sha256:ec64d33bfc1e8d73bc9dfffcee1e90f9fa6b495c3963d43b7530daab5f5877c3
四、Node操作
以k8s-node1环境的搭建为例子:
(k8s-node1和k8s-node2要做的内容一致,仅在hostname设置时有名字的不同)
修改/etc文件夹下的hosts和hostname文件
>cd /etc
>sudo vim hostname
里面的内容一开始为ubuntu
将里面的内容改为k8s-node1
>sudo vim hosts
文件内有一条映射为127.0.0.1 ubuntu
修改这一行,将127.0.0.1映射到k8s-node1
执行完以后重启虚拟机
>reboot
重启以后
>sudo hostname
>sudo wget https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg
在 Kubernetes 集群中,我们需要通过安装 Kubernetes 的 apt-key 来添加 Kubernetes 的 APT 仓库密钥。这个命令下载的正是阿里云 Kubernetes 镜像源提供的 apt-key.gpg 密钥文件。
>sudo apt-key add apt-key.gpg
把之前下载的 apt-key.gpg 密钥文件添加到 Ubuntu 系统的 APT 仓库密钥中。通过在 Ubuntu 系统中注册 Kubernetes 的公共密钥,可以确保我们能够从 Kubernetes 官网或阿里云源安装更新软件包。
>sudo vim /etc/apt/sources.list
打开/etc/apt/sources.list文件
添加一行
deb https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial main
>sudo apt update
添加以后更新一下apt源
值得注意的是,如果不进行上述步骤,可能出现的问题:
执行报错,无法定位软件包
>sudo apt-get install -y kubelet=1.17.2-00 kubeadm=1.17.2-00 kubectl=1.17.2-00 --allow-unauthenticated
在 Ubuntu 系统上安装 Kubernetes 工具和组件:kubelet、kubeadm 和 kubectl。这些工具是 Kubernetes 集群的核心组件,用于管理和操作 Kubernetes 集群。
>sudo kubeadm config images list
列出当前 Kubernetes 版本中需要使用的所有镜像的名称及版本号。这些镜像是在使用 kubeadm 工具初始化一个 Kubernetes 集群时所需的。
返回如下结果:
接下来,在docker上拉去我们需要的镜像并修改tag
>sudo docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.17.17
>sudo docker tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.17.17 k8s.gcr.io/kube-apiserver:v1.17.17
>sudo docker rmi registry.aliyuncs.com/google_containers/kube-apiserver:v1.17.17
>sudo docker pull registry.aliyuncs.com/google_containers/kube-controller-manager:v1.17.17
>sudo docker tag registry.aliyuncs.com/google_containers/kube-controller-manager:v1.17.17 k8s.gcr.io/kube-controller-manager:v1.17.17
>sudo docker rmi registry.aliyuncs.com/google_containers/kube-controller-manager:v1.17.17
>sudo docker pull registry.aliyuncs.com/google_containers/kube-scheduler:v1.17.17
>sudo docker tag registry.aliyuncs.com/google_containers/kube-scheduler:v1.17.17 k8s.gcr.io/kube-scheduler:v1.17.17
>sudo docker rmi registry.aliyuncs.com/google_containers/kube-scheduler:v1.17.17
>sudo docker pull registry.aliyuncs.com/google_containers/kube-proxy:v1.17.17
>sudo docker tag registry.aliyuncs.com/google_containers/kube-proxy:v1.17.17 k8s.gcr.io/kube-proxy:v1.17.17
>sudo docker rmi registry.aliyuncs.com/google_containers/kube-proxy:v1.17.17
>sudo docker pull registry.aliyuncs.com/google_containers/pause:3.1
>sudo docker tag registry.aliyuncs.com/google_containers/pause:3.1 k8s.gcr.io/pause:3.1
>sudo docker rmi registry.aliyuncs.com/google_containers/pause:3.1
>sudo docker pull registry.aliyuncs.com/google_containers/etcd:3.4.3-0
>sudo docker tag registry.aliyuncs.com/google_containers/etcd:3.4.3-0 k8s.gcr.io/etcd:3.4.3-0
>sudo docker rmi registry.aliyuncs.com/google_containers/etcd:3.4.3-0
>sudo docker pull registry.aliyuncs.com/google_containers/coredns:1.6.5
>sudo docker tag registry.aliyuncs.com/google_containers/coredns:1.6.5 k8s.gcr.io/coredns:1.6.5
>sudo docker rmi registry.aliyuncs.com/google_containers/coredns:1.6.5
下载好了可以使用如下命令查看已经拉取的镜像
>sudo docker images
接下来将节点加入我们搭建好的集群中
在我的虚拟机上,生成出来的join命令为:
>kubeadm join 192.168.61.137:6443 --token q3o6sj.sa97hu0u2oe18yug --discovery-token-ca-cert-hash sha256:ec64d33bfc1e8d73bc9dfffcee1e90f9fa6b495c3963d43b7530daab5f5877c3
加入成功的输出为:
返回k8s-master虚拟机查看集群节点信息,输出如下:
K8s-node1的状态为NotReady是因为我将虚拟机关机了,导致节点下线。
五、可能出现的问题
1.节点加入集群时可能出现的问题
<1>如果出现coredns网络异常,则可能需要部署网络插件
kubectl apply -f /usr/local/src/kube-flannel.yml
<2>如果出现
Error in configuration:
* unable to read client-cert /var/lib/kubelet/pki/kubelet-client-current.pem for default-auth due to open /var/lib/kubelet/pki/kubelet-client-current.pem: no such file or directory
* unable to read client-key /var/lib/kubelet/pki/kubelet-client-current.pem for default-auth due to open /var/lib/kubelet/pki/kubelet-client-current.pem: no such file or directory
则表示token过期,需要重新create及join
<3>如果出现
error execution phase preflight: couldn't validate the identity of the API Server: Get "https://192.168.xxx.xx:6443/api/v1/namespaces/kube-public/configmaps/cluster-info?timeout=10s": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
To see the stack trace of this error execute with --v=5 or higher
则可能是防火墙问题
<4>如果
W0706 10:27:55.181115 22817 loader.go:221] Config not found: /etc/kubernetes/admin.conf
The connection to the server localhost:8080 was refused - did you specify the right host or port?
发现 Node 节点只有 kubelet.conf 配置项,而没有admin.conf
切换为普通用户
a) mkdir -p $HOME/.kube
b) sudo cp -i /etc/kubernetes/kubelet.conf $HOME/.kube/config
c) sudo chown $(id -u):$(id -g) $HOME/.kube/config
hostname可能出现的问题
根据很多次的失败操作,发现init时将使用hostname的信息,因此若初始化集群的时候,没有将主机名正确地改为k8s-master,将导致k8s集群初始化失败。
版本问题
结合自己的经验和同学失败的经验
发现:
Ubuntu 22版会导致k8s集群初始化时失败
Docker 20.10版不被k8s支持,需要降级为19.03
重启master以后,如何访问集群
重新启动master以后,不管是查看集群节点信息,还是所有集群信息,都会报错
报错的信息时localhost:8080连接失败
解决方法是开启apiserver的代理端口
开启端口代理
>kubectl proxy --port=8080 &
关于node节点的状态问题
实践中发现,当Node虚拟机关机时,从Master主机上查看节点状态,将会时NotReady
启动Node虚拟机,Master主机上的节点状态将会变成Ready
更多推荐
所有评论(0)