kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。
这个工具能通过两条指令完成一个kubernetes集群的部署:
1 2 3 4 5 # 创建一个 Master 节点 $ kubeadm init # 将一个 Node 节点加入到当前集群中 $ kubeadm join <Master节点的IP和端口 >
1. 安装要求 在开始之前,部署Kubernetes集群机器需要满足以下几个条件:
一台或多台机器,操作系统 CentOS7.x-86_x64
硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多
可以访问外网,需要拉取镜像,如果服务器不能上网,需要提前下载镜像并导入节点
禁止swap分区
2. 准备环境
角色
IP
master
192.168.1.11
node1
192.168.1.12
node2
192.168.1.13
使用kubeadm方式搭建K8s集群主要分为以下几步
准备三台虚拟机,同时安装操作系统CentOS 7.x
对三个安装之后的操作系统进行初始化操作
在三个节点安装 docker kubelet kubeadm kubectl
在master节点执行kubeadm init命令初始化
在node节点上执行 kubeadm join命令,把node节点添加到当前集群
配置CNI网络插件,用于节点之间的连通【失败了可以多试几次】
通过拉取一个nginx进行测试,能否进行外网测试
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 # 关闭防火墙 systemctl stop firewalld && systemctl disable firewalld # 关闭selinux # 永久 # 临时 sed -i 's/enforcing/disabled/' /etc/selinux/config && setenforce 0 ## 关闭swap 临时 # 永久 swapoff -a && sed -ri 's/.*swap.*/#&/' /etc/fstab # 根据规划设置主机名 hostnamectl set-hostname <hostname> # 在master添加hosts cat >> /etc/hosts << EOF 172.17.156.95 master 172.17.156.96 node1 172.17.156.97 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 EOF sysctl --system # 生效 # 时间同步 yum install ntpdate -y ntpdate time.windows.com
3. 所有节点安装Docker/kubeadm/kubelet Kubernetes默认CRI(容器运行时)为Docker,因此先安装Docker。
3.1 安装Docker 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 # 1.1 切换镜像源 $ wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo # 1.23 更新并安装Docker-CE sudo yum makecache fast # 2 查看当前镜像源中支持的docker版本 $ yum list docker-ce --showduplicates $ yum search docker-ce --showduplicates # 3 安装特定版本的docker-ce # 如果想安装最新版本sudo yum -y install docker-ce $ yum -y install --setopt=obsoletes=0 docker-ce-cli-20.10.18-3.el7.x86_64 # 4 添加一个配置文件 # Docker在默认情况下使用的Cgroup Driver为cgroupfs,而kubernetes推荐使用systemd来代替cgroupfs # 4.1 查看docker 的 cgroup-driver $ docker info |grep Cgroup Cgroup Driver: cgroupfs # 4.2 修改为 cgroupfs 添加一个配置文件 $ cat > /etc/docker/daemon.json << EOF { "exec-opts": ["native.cgroupdriver=systemd"], "registry-mirrors": ["https://kn0t2bca.mirror.aliyuncs.com"] } EOF # 5 启动docker $ systemctl enable docker && systemctl start docker # 6 检查docker状态和版本 $ docker --version Docker version 20.10.18, build b40c2f6
3.2 安装kubernetes组件 添加阿里云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 3 4 5 6 7 8 9 10 11 # 卸载旧版本 yum remove -y kubelet kubeadm kubectl # 查看可以安装的版本 yum list kubelet --showduplicates | sort -r # 安装kubelet、kubeadm、kubectl 指定版本 yum install -y kubelet-1.23.0 kubeadm-1.23.0 kubectl-1.23.0 # 开机启动kubelet systemctl enable kubelet && systemctl start kubelet
4. 部署Kubernetes Master 在192.168.31.61(Master)执行。
-apiserver-advertise-address写master节点IP
1 2 3 4 5 6 $ kubeadm init \ --apiserver-advertise-address=192.168.16.4 \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.23.0 \ --service-cidr=10.96.0.0/12 \ --pod-network-cidr=10.244.0.0/16
由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里指定阿里云镜像仓库地址。
当我们出现下面的情况时,表示kubernetes的镜像已经安装成功
使用kubectl工具:
1 2 3 4 mkdir -p $HOME /.kubesudo cp -i /etc/kubernetes/admin.conf $HOME /.kube/config sudo chown $(id -u):$(id -g) $HOME /.kube/config $ kubectl get nodes
执行完成后,我们使用下面命令,查看我们正在运行的节点
kubectl get nodes
能够看到,目前有一个master节点已经运行了,但是还处于未准备状态
下面我们还需要在Node节点执行其它的命令,将node1和node2加入到我们的master节点上
5. 加入Kubernetes Node 在192.168.1.12/13(Node)执行。
向集群添加新节点,执行在kubeadm init输出的kubeadm join命令:
1 2 $ kubeadm join 192.168.1.11:6443 --token esce21.q6hetwm8si29qxwn \ --discovery-token-ca-cert-hash sha256:00603a05805807501d7181c3d60b478788408cfe6cedefedb1f97569708be9c5
默认token有效期为24小时,当过期之后,该token就不可用了。这时就需要重新创建token,操作如下:
1 kubeadm token create --print-join-command
当我们把两个节点都加入进来后,我们就可以去Master节点 执行下面命令查看情况
kubectl get node
6. 部署CNI网络插件 1 2 # 下载网络插件配置 wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
如果下载不了可以直接在任意目录下创建kube-flannel.yml文件
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 --- 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 image: quay.mirrors.ustc.edu.cn/coreos/flannel/flannel:v0.14.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: quay.mirrors.ustc.edu.cn/coreos/flannel/flannel:v0.14.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/ volumes: - name: run hostPath: path: /run/flannel - name: cni hostPath: path: /etc/cni/net.d - name: flannel-cfg configMap: name: kube-flannel-cfg
默认镜像地址无法访问,sed命令修改为docker hub镜像仓库。
1 2 3 4 5 6 7 8 9 10 # 修改文件中quay.io仓库为quay-mirror.qiniu.com 或者quay.mirrors.ustc.edu.cn 随便一个 sed -i 's#quay.io/coreos/flannel#quay.mirrors.ustc.edu.cn/coreos/flannel#' kube-flannel.yml sed -i 's#quay.io/coreos/flannel#quay-mirror.qiniu.com/coreos/flannel#' kube-flannel.yml kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE kube-flannel-ds-amd64-2pc95 1/1 Running 0 72s
运行后的结果
运行完成后,我们查看状态可以发现,已经变成了Ready状态了
如果上述操作完成后,还存在某个节点处于NotReady状态,可以在Master将该节点删除
1 2 3 4 5 6 7 # master节点将该节点删除 kubectl delete node k8snode1 # 然后到k8snode1节点进行重置 kubeadm reset # 重置完后在加入 kubeadm join 192.168.177.130:6443 --token 8j6ui9.gyr4i156u30y80xf --discovery-token-ca-cert-hash sha256:eda1380256a62d8733f4bddf926f148e57cf9d1a3a58fb45dd6e80768af5a500
1 2 3 4 5 6 7 8 9 10 # 看出pod状态都是running kubectl get pod --all-namespaces # 查看集群状态都是Healthy ok kubectl get cs 如果出现unhealthy,分别修改下面两个文件,注释 - --port=0,然后重启kubelet vim /etc/kubernetes/manifests/kube-controller-manager.yaml vim /etc/kubernetes/manifests/kube-scheduler.yaml systemctl restart kubelet.service
7. 测试kubernetes集群 在Kubernetes集群中创建一个pod,验证是否正常运行:
1 2 3 4 5 6 $ kubectl create deployment nginx --image=nginx # 暴露端口 $ kubectl expose deployment nginx --port=80 --type =NodePort # 查看一下对外的端口 $ kubectl get pod,svc
能够看到,我们已经成功暴露了 80端口 到 30529上
访问地址:http://NodeIP:Port
拓展
journalctl -f -u kubelet.service
systemctl status kubelet -l
1 2 3 4 5 6 sudo mkdir -p /opt/cni/bin cd /opt/cni/bin 然后接下来去下载相应的压缩包 https://github.com/containernetworking/plugins/releases/tag/v0.8.6 下载一个cni-plugins-linux-amd64-v0.8.6.tgz 然后将其解压在/opt/cni/bin下就可以了。
允许Mater上调度 1 2 3 4 5 6 7 8 9 10 # 查看node kubectl get nodes # 查看污点 kubectl describe node k8s-master |grep Taints Taints: node-role.kubernetes.io/master:NoSchedule # 删除污点 kubectl taint nodes --all node-role.kubernetes.io/master- kubectl taint nodes --all node.kubernetes.io/not-ready-
卸载k8s集群 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 一、清空K8S集群设置 # 在卸载K8s组件前,先执行kubeadm reset命令,清空K8s集群设置 kubeadm reset 二、卸载管理组件 # 把之前通过yum安装的管理组件卸载 yum erase -y kubelet kubectl kubeadm kubernetes-cni 三、删除基础组件镜像 # 基础组件通过Docker镜像部署,因此只需要强制删除对应镜像即可卸载 docker rmi -f k8s.gcr.io/kube-apiserver:v1.20.1 docker rmi -f k8s.gcr.io/kube-controller-manager:v1.20.1 docker rmi -f k8s.gcr.io/kube-scheduler:v1.20.1m docker rmi -f k8s.gcr.io/kube-proxy:v1.20.1 docker rmi -f k8s.gcr.io/pause:3.2 docker rmi -f k8s.gcr.io/etcd:3.4.13 docker rmi -f k8s.gcr.io/coredns:1.8.1